feat: Add TypeScript infrastructure to client app#2218
feat: Add TypeScript infrastructure to client app#2218
Conversation
Set up TypeScript so the project compiles, new files can be written in TS, and existing JS files continue to work via allowJs. - Add typescript as a devDependency - Rename jsconfig.json to tsconfig.json - Rename quasar.config.js to quasar.config.ts with build.typescript config - Update ESLint to lint .ts files instead of ignoring them - Add .ts to prettier format and vite-plugin-checker patterns Commit includes content generated with LLM assistance
Rename 86 .js files to .ts across source, composables, graphql, tiptap extensions, router, apollo, and vitest test/utility files. Add typescript-eslint parser to ESLint config for .ts file support. Apply minimal type fixes: non-null assertion on getCurrentInstance() in vQWrap, networkError type cast in apollo-links, and remove stale .js import extensions. Commit includes content generated with LLM assistance
Fix type errors in converted TS files: apollo-links, tiptap extensions, router routes, userValidation, timeAgo, submission composable, and test utilities. Update eslint and tsconfig for TS support. Commit includes content generated with LLM assistance
Add lang="ts" to 27 Vue component script blocks and convert to type-based props/emits syntax. Convert VQWrap and TagList from Options API to script-setup. Fix bitwise OR operators to logical OR in acceptMore computed properties. Fix Date subtraction to use .getTime(). Update ESLint config to parse TypeScript in Vue SFCs. Commit includes content generated with LLM assistance
The spec files were prematurely renamed to .ts in the non-component conversion commit. Rename them back to .js since test migration is a separate step that requires proper typing of the components first. Commit includes content generated with LLM assistance
Declare $t on ComponentCustomProperties so vue-tsc recognizes it in template expressions of TypeScript Vue components. Commit includes content generated with LLM assistance
Commit includes content generated with LLM assistance
Remove pwa, cordova, capacitor, electron, and bex config blocks that are not used by this project. Fixes the vue-tsc error caused by the pwa.workboxMode casing mismatch. Commit includes content generated with LLM assistance
…afety Add reusable useI18nPrefix composable that provides pt (prefixed translate) and pte (prefixed translate-exists) helpers with full ComposerTranslation type passthrough. Refactor both AssignedPublicationUsers and AssignedSubmissionUsers to use it, replacing inline tp$/tPrefix patterns. Also add proper mutation variable interfaces and DocumentNode typing to both components, replacing untyped useMutation calls. Commit includes content generated with LLM assistance
…elect - Add useI18nPrefix composable with pt/pte helpers for prefixed i18n - Convert FindUserSelect to TypeScript with exported FoundUser interface and FindUserSelectValue type - Refactor AssignedPublicationUsers and AssignedSubmissionUsers to use shared types and composable, replacing inline tp$/tPrefix patterns - Add proper mutation variable interfaces with DocumentNode typing - Pass narrowed types through function parameters instead of re-reading the union ref Commit includes content generated with LLM assistance
Add @graphql-codegen/cli with typescript and typescript-operations plugins to generate TypeScript types from the backend GraphQL schema and the client's centrally-defined operations. - Add codegen.ts config with introspection as primary schema source - Add vite-plugin-graphql-codegen for automatic regeneration during dev - Add custom watch-backend-schema Vite plugin to detect backend schema changes and re-run codegen automatically - Add schema-ast plugin to keep committed schema.graphql in sync - Builds use committed schema file (configOverrideOnBuild), no backend needed - Add graphql:codegen, graphql:fetch-schema, graphql:codegen-offline scripts - Fix 3 duplicate GraphQL operation names in mutations.ts - Remove dead CREATE_SUBMISSION mutation (references non-existent field) - Add developer documentation for backend and client GraphQL workflows - Add generated/ directory to eslint ignores Commit includes content generated with LLM assistance
✅ Deploy Preview for pilcrow-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Migrate all implicit $q template references to use the explicit useQuasar() composable, improving type safety and Composition API consistency. Also converts EmailVerificationBanner from Options API to script setup. Commit includes content generated with LLM assistance
…text composable Replace string-keyed provide/inject for submission review state with typed InjectionKey symbols and composable helpers. This ensures types are defined once, provide sites always use Refs, and TypeScript catches mismatches. - Create src/use/submissionContext.ts with typed keys and composables - Update 5 provide sites to use provideSubmissionReviewContext() / submissionKey - Update 13 inject sites to use useSubmission(), useActiveComment(), etc. - Fix forExport .value access in OverallComment and InlineComment - Update 4 test specs to use Symbol-based injection keys - Clean up let → const for ref declarations Commit includes content generated with LLM assistance
- PublicationStyleCriteria: pass both publication_id and id to delete mutation - SubmissionContent: use querySelectorAll<HTMLElement> for dataset access - StyleCriteriaForm: use $errors.some() instead of possibly-undefined maxLength - EditableList: fix number|false usage in slice() and string/boolean comparison - annotation.ts: convert addOptions from object literal to function Commit includes content generated with LLM assistance
| import FormActions from "../molecules/FormActions.vue" | ||
| import { useI18n } from "vue-i18n" | ||
| const { dirty, setError } = inject("formState") | ||
| const { dirty, setError } = inject("formState") as any |
There was a problem hiding this comment.
Need to address this and type the formState injection.
| default: () => ({}) | ||
| const props = withDefaults( | ||
| defineProps<{ | ||
| criteria?: Record<string, any> |
There was a problem hiding this comment.
Is Record<string, any> the best we can do? We should import the GraphQL types that it should expect
| import { computed, inject } from "vue" | ||
|
|
||
| const { state, errorMessage } = inject("formState") | ||
| const { state, errorMessage } = inject("formState") as any |
There was a problem hiding this comment.
Needs typing on formstae.
|
|
||
| <component | ||
| :is="comment.new ? NewInlineComment : InlineComment" | ||
| :is="'new' in comment ? NewInlineComment : InlineComment" |
There was a problem hiding this comment.
can't this use the isActiveCommentNew computed?
| return comments | ||
| .filter((c) => { | ||
| return c.deleted_at === null || c.replies?.length > 0 | ||
| return c.deleted_at === null || ("replies" in c && c.replies?.length > 0) |
There was a problem hiding this comment.
Why isn't optional chaining ok here?
| } | ||
| }) | ||
| const props = defineProps<{ | ||
| publication: Record<string, any> |
There was a problem hiding this comment.
We should be using the graphql types here.
| } | ||
| }) | ||
| const props = defineProps<{ | ||
| publication: Record<string, any> |
There was a problem hiding this comment.
Needs graphql types;
client/src/pages/FeedPage.vue
Outdated
| import NotificationListItem from "src/components/atoms/NotificationListItem.vue" | ||
|
|
||
| const filterMode = ref(null) | ||
| const filterMode = ref<string | null>(null) |
There was a problem hiding this comment.
Shouldn't this be refactored to ref<"Unread" | "Read" | null>?
| }) | ||
|
|
||
| let viewType = ref("review") | ||
| const viewType = ref("review") |
There was a problem hiding this comment.
Types would clarify what this ref is up to.
client/src/pages/SubmissionsPage.vue
Outdated
| .flat() | ||
| .sort((a, b) => { | ||
| return new Date(b.updated_at) - new Date(a.updated_at) | ||
| return new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime() |
There was a problem hiding this comment.
We re-use this pattern multiple times. Should this get extracted into a utility?
Replace string-based formState provide/inject with typed InjectionKey, use GraphQL generated types instead of Record<string, any>, add proper types to tiptap annotation extension, extract date sort utility, and convert NewPasswordInputMeter to script setup. Commit includes content generated with LLM assistance
Extract inline type parameters from defineProps into named Props interfaces for consistency and readability across all components. Commit includes content generated with LLM assistance
Enforce type-based defineProps declarations over runtime options-object style in Vue components. Commit includes content generated with LLM assistance
Enable tseslint.configs.recommended via extends in ESLint config for .ts, .vue, and test file blocks. Fix violations caught by new rules: remove dead code (no-unused-expressions), replace Function type (no-unsafe-function-type), fix var scoping (no-var/prefer-const), and restructure appAuth.ts error handling. Downgrade no-explicit-any to warn for incremental cleanup. Commit includes content generated with LLM assistance
- Container props: use generated Publication/Submission GraphQL types - VQInput/VQWrap: add VuelidateValidator interface (src/types/vuelidate.ts) for component props (BaseValidation is too complex for Vue's type resolution) - Vuelidate rules props: use ValidationRuleCollection from @vuelidate/core - NewPasswordInputAnalysis: define ZxcvbnComplexity interface for password complexity prop - InlineComments: type commentRefs as InlineComment component instances - FeedPage: Record<string, unknown> for query variables - formState: Ref<Error | null> for mutationError - userValidation: properly typed mutation/rules/variables options - Dialog test mock: use unknown instead of any - Remove no-explicit-any warn overrides from eslint config (now errors) Commit includes content generated with LLM assistance
4892e01 to
1dc0764
Compare
This pull request introduces TypeScript support and integrates GraphQL code generation into the client project. It also improves ESLint configuration for TypeScript, adds automation for GraphQL schema/codegen updates, and performs several file cleanups and conversions. The most significant changes are grouped below.
TypeScript Integration and Improvements:
quasar.config.ts,src/boot/vue-apollo.ts, andsrc/boot/i18n.ts. This includes updating imports, type annotations, and bootstrapping code for better type safety. [1] [2] [3] [4]typescript,typescript-eslint,vue-tsc) and updated the Quasar build configuration to support TypeScript. [1] [2]GraphQL Code Generation Automation:
codegen.ts), scripts to fetch schema and generate types, and related dev dependencies. The.gitignoreand ESLint ignore patterns were updated to exclude generated code. [1] [2] [3] [4] [5]vite-plugin-graphql-codegenand a custom Vite plugin to automatically regenerate types on backend schema changes. [1] [2]ESLint and Formatting Enhancements:
.tsfiles. [1] [2] [3] [4]Cleanup and Refactoring:
src/boot/axios.js,src/boot/i18n.js,jsconfig.json) and updated imports to match new file extensions. [1] [2] [3] [4]Apollo and Error Handling Improvements:
These changes lay the groundwork for a more robust, type-safe, and maintainable frontend codebase with automated GraphQL type generation and improved developer tooling.