-
Notifications
You must be signed in to change notification settings - Fork 0
refactor: Convert React Apollo Generators to new TS scheme #515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Convert React Apollo Generators to new TS scheme #515
Conversation
…accept lexographical ordering
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
WalkthroughThis update implements a major refactor and simplification of the authentication code generation system in the React generators. The legacy, custom authentication generators and their associated templates, hooks, service files, and routes are removed in favor of a new, consolidated provider-based approach. New provider modules are introduced for authentication components and hooks, with a unified export structure. The authentication flow is now exclusively supported via Auth0, with all non-Auth0 logic removed from the server compiler. The Apollo React generator is refactored for stronger typing, modular provider tasks, and improved link management. Several utility enhancements are made, including new topological sort algorithms and error classes, as well as new field container types. Numerous import paths and dependencies are updated across generators to reflect the new modular structure. Additional improvements include centralizing import sorting options, adding new utility methods, and updating project scripts and dependencies. Changes
Sequence Diagram(s)sequenceDiagram
participant Generator as Generator Task
participant Providers as Providers (_providers modules)
participant Templates as Templates/Fragments
participant Apollo as Apollo Config/Links
participant Auth0 as Auth0 Flow
Generator->>Providers: Import and use consolidated auth providers (components, hooks)
Generator->>Templates: Render files using fragments and import maps
Generator->>Apollo: Register Apollo client args and links using provider tasks
Generator-x Auth0: (Legacy non-Auth0 auth removed)
Generator->>Auth0: Use Auth0-only authentication flow
Providers-->>Generator: Export unified interfaces for components/hooks
Templates-->>Generator: Provide code fragments/templates for rendering
Apollo-->>Generator: Provide config and link management via provider
sequenceDiagram
participant MainTask as Main Generator Task
participant RouteTask as Route Collection Task
participant RouteProvider as Route Values Provider
MainTask->>RouteTask: Depends on route/layout collection
RouteTask->>RouteProvider: Export collected routes/layouts
MainTask->>RouteProvider: Use collected data to render routes file
sequenceDiagram
participant ToposortCaller as Any Toposort User
participant Toposort as toposort/toposort.ts
participant TinyQueue as tinyqueue (optional)
participant Errors as errors.ts
ToposortCaller->>Toposort: Call toposort(nodes, edges, options)
Toposort->>TinyQueue: (If compareFunc provided) Use TinyQueue for queue
Toposort->>Errors: Throw ToposortCyclicalDependencyError or ToposortUnknownNodeError on error
Toposort-->>ToposortCaller: Return sorted nodes
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🔭 Outside diff range comments (2)
packages/react-generators/src/generators/core/react-router/react-router.generator.ts (2)
84-122: 🛠️ Refactor suggestionFreeze route collections before exporting to avoid accidental mutation.
routesandlayoutsare pushed to until the build phase, then the same array instances are exported. If any async or future task retains a reference, these arrays could be mutated after construction, leading to hard-to-trace ordering bugs.- build: () => ({ - reactRouteValuesProvider: { - routes, - layouts, - }, + build: () => ({ + reactRouteValuesProvider: { + routes: [...routes], + layouts: [...layouts], + }, }),
123-160:⚠️ Potential issueValidate layout-key uniqueness before rendering.
TODOon line 141 warns about multiple layout keys. A simple runtime check will surface configuration errors early:-// TODO: Make sure we don't have more than one layout key +const duplicateLayouts = layouts + .map((l) => l.key) + .filter((k, i, arr) => arr.indexOf(k) !== i); +if (duplicateLayouts.length) { + throw new Error( + `react-router generator: Duplicate layout keys detected: ${duplicateLayouts.join( + ', ', + )}`, + ); +}This prevents silent overwrites when
renderRoutesreduces layouts.
🧹 Nitpick comments (14)
package.json (1)
17-17: Consider documenting the rationale for the new “lint:only” script.
lint:onlyinvokespnpm run -r lint, which runs the workspace-levellintscript in every package. This is subtly different from the existinglint/lint:affectedscripts that rely on Turborepo (which adds caching, the--continueflag, etc.).
If the intent is simply “run lint in all workspaces without Turborepo”, please add a short comment in the rootREADME(or the commit message) so future maintainers know when to use each variant and avoid accidental duplication.packages/project-builder-web/src/app/ProjectSyncModal/ProjectSyncModal.tsx (1)
50-52: Consider applying consistent error handling.The
startSynccall now useslogAndFormatErrorfor enhanced error handling (with logging), butcancelSyncon line 61 still usesformatError. For consistency, consider updating both error handlers to use the same approach.cancelSync(currentProjectId).catch((error: unknown) => - toast.error(formatError(error)), + toast.error(logAndFormatError(error)), );packages/core-generators/src/renderers/typescript/ts-code-utils.ts (2)
265-284: Guard againstundefinedvalues when joining fragments
mergeFragmentsAsArrayPresortedassumes every element is astring | TsCodeFragment.
When called frommergeFragmentsAsArraythe map entry values already satisfy that, but other external callers may accidentally passundefined, producing the literal stringundefinedinside the generated code.Diff suggestion to hard-filter falsy entries:
- contents: `[${fragments - .map((fragment) => - typeof fragment === 'string' ? fragment : fragment.contents, - ) - .join(',\n')}]`, + contents: `[${fragments + .filter(Boolean) + .map((fragment) => + typeof fragment === 'string' ? fragment : fragment.contents, + ) + .join(',\n')}]`,
300-303:thisuses dynamic binding – keep method syntax to stay safe
mergeFragmentsAsArraydelegates tothis.mergeFragmentsAsArrayPresorted.
Because the enclosing object uses method shorthand earlier,thiswill be theTsCodeUtilsobject only if the code is kept in method form. A future refactor turning this into a property with an arrow function would silently break the call chain.Consider freezing the object (
Object.freeze(TsCodeUtils)) or exporting each util as a named function to remove thethisdependency altogether.packages/react-generators/src/generators/apollo/apollo-error/apollo-error.generator.ts (1)
59-63: Templates are awaited individually – parallelise for speed
awaitinside a loop / single call is okay here, but if more template files are added later the sequentialawaits will slow down generation.
Consider collecting promises andawait Promise.all().packages/utils/src/toposort/toposort-dfs.ts (2)
12-18:makeOutgoingEdgesthrows on unknown nodes – error message clarityGreat that you detect unknown nodes early!
The thrownToposortUnknownNodeErrorcurrently exposes the node only; consider also including the offending edge[source, target]for quicker debugging, especially when nodes are complex objects.
88-90: Potential stack overflow on very large DAGsDFS recursion depth equals the longest path length. If consumers ever feed thousands of nodes you may hit the Node/V8 call-stack limit.
A non-recursive algorithm (explicit stack) would be safer long-term.packages/react-generators/src/generators/apollo/apollo-sentry/apollo-sentry.generator.ts (1)
22-23: Verify path alias@/src/...is mapped in tsconfig
apolloSentryLinkPathuses the alias@/, which requires a matching"paths"entry (or webpack alias) or the file won’t resolve for consumers of the generated code.packages/react-generators/src/generators/auth0/auth0-apollo/auth0-apollo.generator.ts (1)
20-23: Remove or utilise unused dependency to avoid accidental dead-code & tree-shake issues
apolloErroris declared as a dependency but never referenced insiderun().
Keeping unused dependencies can (1) mislead future maintainers, (2) cause unnecessary execution of its upstream generator, and (3) prevent bundlers from tree-shaking the code.If
apolloErroris not required here, remove it from thedependenciesmap; otherwise, add the appropriate usage.- dependencies: { - reactApolloConfig: reactApolloConfigProvider, - apolloError: apolloErrorProvider, - }, + dependencies: { + reactApolloConfig: reactApolloConfigProvider, + // apolloError: apolloErrorProvider, // ← add usage or delete + },packages/react-generators/src/generators/core/react-utils/react-utils.generator.ts (1)
54-60: Minor: drop unnecessary intermediatefilesarray
Object.entries(REACT_UTILS_TS_TEMPLATES)is already iterable twice below; retainingfilesonly increases memory pressure.
Inline the iteration or document why it is cached (e.g., becauseREACT_UTILS_TS_TEMPLATESis huge or expensive to enumerate).packages/utils/src/toposort/toposort.ts (1)
93-101: Typo & potential bug in variable name (unvistedNodeIdx)Misspelling doesn’t break functionality but hurts readability and may confuse IDE symbol searches.
While touching this code, consider early-returning whendfsdetects no cycle to avoid needless path allocation.- const unvistedNodeIdx = nodes.findIndex((node, idx) => !visited.has(idx)); + const unvisitedNodeIdx = nodes.findIndex((_, idx) => !visited.has(idx));.cursor/rules/ts-code-migration.mdc (1)
1-5: Fill-in the front-matter to avoid tooling from treating the rule as “disabled”.
descriptionandglobsare empty, so most linters / rule-runners will simply skip the rule. Provide at least a one-line description and one glob pattern.--- -description: -globs: +description: "Guide for migrating generators to the fragment-based TS scheme" +globs: + - "packages/**/*.ts" alwaysApply: false ---packages/react-generators/src/generators/apollo/react-apollo/react-apollo.generator.ts (2)
14-21:TypescriptCodeUtilsimport looks stale – migrate toTsCodeUtilsor isolate the legacy helper.Everything in this PR promotes the new
TsCodeUtilsAPI, yet we still import the legacyTypescriptCodeUtils.
OnlyextractTemplateSnippetis used later. Either:
- Move that helper to
TsCodeUtils, or- Import it directly:
import { extractTemplateSnippet } from ….This avoids mixed naming that confuses future maintainers.
310-316:findLinkperforms O(n²) lookups; pre-index once for clarity & speed.For ~10 links it’s fine, but the code executes on every build. A simple map avoids the repeated linear search and clarifies intent:
- const findLink = (name: string): ApolloLink => { - const link = apolloLinks.find((link) => link.name === name); - if (!link) throw new Error(`Link ${name} not found`); - return link; - }; + const linkByName = new Map(apolloLinks.map((l) => [l.name, l])); + const findLink = (name: string): ApolloLink => { + const link = linkByName.get(name); + if (!link) throw new Error(`Link ${name} not found`); + return link; + };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Lite
⛔ Files ignored due to path filters (10)
packages/react-generators/src/generators/apollo/apollo-error/generated/ts-import-maps.tsis excluded by!**/generated/**packages/react-generators/src/generators/apollo/apollo-error/generated/ts-templates.tsis excluded by!**/generated/**packages/react-generators/src/generators/apollo/apollo-sentry/generated/ts-templates.tsis excluded by!**/generated/**packages/react-generators/src/generators/apollo/react-apollo/generated/ts-import-maps.tsis excluded by!**/generated/**packages/react-generators/src/generators/apollo/react-apollo/generated/ts-templates.tsis excluded by!**/generated/**packages/react-generators/src/generators/core/react-sentry/generated/ts-import-maps.tsis excluded by!**/generated/**packages/react-generators/src/generators/core/react-sentry/generated/ts-templates.tsis excluded by!**/generated/**packages/react-generators/src/generators/core/react-utils/generated/ts-import-maps.tsis excluded by!**/generated/**packages/react-generators/src/generators/core/react-utils/generated/ts-templates.tsis excluded by!**/generated/**pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (66)
.cursor/rules/ts-code-migration.mdc(1 hunks)package.json(1 hunks)packages/core-generators/src/generators/node/eslint/generate-config.ts(1 hunks)packages/core-generators/src/generators/node/typescript/typescript.generator.ts(3 hunks)packages/core-generators/src/renderers/typescript/imports/sort-imports/sort-import-declarations.ts(1 hunks)packages/core-generators/src/renderers/typescript/ts-code-utils.ts(2 hunks)packages/project-builder-lib/src/plugins/imports/loader.ts(2 hunks)packages/project-builder-server/src/compiler/admin/index.ts(1 hunks)packages/project-builder-server/src/compiler/lib/web-auth.ts(1 hunks)packages/project-builder-server/src/compiler/web/index.ts(1 hunks)packages/project-builder-web/src/app/ProjectSyncModal/ProjectSyncModal.tsx(2 hunks)packages/react-generators/src/generators/admin/admin-bull-board/admin-bull-board.generator.ts(5 hunks)packages/react-generators/src/generators/admin/admin-home/admin-home.generator.ts(1 hunks)packages/react-generators/src/generators/admin/admin-layout/admin-layout.generator.ts(1 hunks)packages/react-generators/src/generators/apollo/apollo-error-link/apollo-error-link.generator.ts(3 hunks)packages/react-generators/src/generators/apollo/apollo-error/apollo-error.generator.ts(4 hunks)packages/react-generators/src/generators/apollo/apollo-sentry/apollo-sentry.generator.ts(2 hunks)packages/react-generators/src/generators/apollo/apollo-sentry/templates/apollo-sentry-link.ts(1 hunks)packages/react-generators/src/generators/apollo/react-apollo/react-apollo.generator.ts(6 hunks)packages/react-generators/src/generators/apollo/react-apollo/templates/app/AppApolloProvider.tsx(1 hunks)packages/react-generators/src/generators/apollo/react-apollo/templates/services/apollo/index.ts(1 hunks)packages/react-generators/src/generators/auth/_providers/auth-components.ts(1 hunks)packages/react-generators/src/generators/auth/_providers/auth-hooks.ts(1 hunks)packages/react-generators/src/generators/auth/_providers/index.ts(1 hunks)packages/react-generators/src/generators/auth/auth-apollo/auth-apollo.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-apollo/templates/auth-link.ts(0 hunks)packages/react-generators/src/generators/auth/auth-components/auth-components.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-components/templates/RequireAuth.tsx(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/auth-hooks.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useCurrentUser.gql(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useCurrentUser.ts(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useLogOut.gql(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useLogOut.ts(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useRequiredUserId.ts(0 hunks)packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useSession.ts(0 hunks)packages/react-generators/src/generators/auth/auth-identify/auth-identify.generator.ts(1 hunks)packages/react-generators/src/generators/auth/auth-layout/auth-layout.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-login-page/auth-login-page.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-login-page/templates/index.tsx(0 hunks)packages/react-generators/src/generators/auth/auth-login-page/templates/login.gql(0 hunks)packages/react-generators/src/generators/auth/auth-pages/auth-pages.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-service/auth-service.generator.ts(0 hunks)packages/react-generators/src/generators/auth/auth-service/templates/index.ts(0 hunks)packages/react-generators/src/generators/auth/auth-service/templates/tokens.gql(0 hunks)packages/react-generators/src/generators/auth/auth-service/templates/tokens.ts(0 hunks)packages/react-generators/src/generators/auth/auth-service/templates/types.ts(0 hunks)packages/react-generators/src/generators/auth/index.ts(1 hunks)packages/react-generators/src/generators/auth0/auth0-apollo/auth0-apollo.generator.ts(2 hunks)packages/react-generators/src/generators/auth0/auth0-callback/auth0-callback.generator.ts(1 hunks)packages/react-generators/src/generators/auth0/auth0-components/auth0-components.generator.ts(1 hunks)packages/react-generators/src/generators/auth0/auth0-hooks/auth0-hooks.generator.ts(1 hunks)packages/react-generators/src/generators/core/react-router/react-router.generator.ts(4 hunks)packages/react-generators/src/generators/core/react-sentry/react-sentry.generator.ts(3 hunks)packages/react-generators/src/generators/core/react-utils/react-utils.generator.ts(1 hunks)packages/react-generators/src/writers/component/index.ts(0 hunks)packages/sync/src/phases/sort-task-phases.ts(2 hunks)packages/sync/src/runner/dependency-sort.ts(2 hunks)packages/sync/src/utils/ordered-list.ts(2 hunks)packages/utils/package.json(1 hunks)packages/utils/src/field-map/field-map.ts(3 hunks)packages/utils/src/toposort/errors.ts(1 hunks)packages/utils/src/toposort/index.ts(1 hunks)packages/utils/src/toposort/toposort-dfs.ts(1 hunks)packages/utils/src/toposort/toposort-dfs.unit.test.ts(1 hunks)packages/utils/src/toposort/toposort.ts(2 hunks)packages/utils/src/toposort/toposort.unit.test.ts(3 hunks)
💤 Files with no reviewable changes (22)
- packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useLogOut.gql
- packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useRequiredUserId.ts
- packages/react-generators/src/generators/auth/auth-service/templates/types.ts
- packages/react-generators/src/generators/auth/auth-components/templates/RequireAuth.tsx
- packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useCurrentUser.gql
- packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useLogOut.ts
- packages/react-generators/src/generators/auth/auth-service/templates/tokens.gql
- packages/react-generators/src/writers/component/index.ts
- packages/react-generators/src/generators/auth/auth-login-page/templates/login.gql
- packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useCurrentUser.ts
- packages/react-generators/src/generators/auth/auth-service/templates/tokens.ts
- packages/react-generators/src/generators/auth/auth-hooks/templates/hooks/useSession.ts
- packages/react-generators/src/generators/auth/auth-layout/auth-layout.generator.ts
- packages/react-generators/src/generators/auth/auth-pages/auth-pages.generator.ts
- packages/react-generators/src/generators/auth/auth-service/templates/index.ts
- packages/react-generators/src/generators/auth/auth-apollo/templates/auth-link.ts
- packages/react-generators/src/generators/auth/auth-apollo/auth-apollo.generator.ts
- packages/react-generators/src/generators/auth/auth-hooks/auth-hooks.generator.ts
- packages/react-generators/src/generators/auth/auth-login-page/templates/index.tsx
- packages/react-generators/src/generators/auth/auth-login-page/auth-login-page.generator.ts
- packages/react-generators/src/generators/auth/auth-service/auth-service.generator.ts
- packages/react-generators/src/generators/auth/auth-components/auth-components.generator.ts
🧰 Additional context used
🧬 Code Graph Analysis (19)
packages/project-builder-server/src/compiler/web/index.ts (1)
packages/project-builder-server/src/compiler/lib/web-auth.ts (1)
compileAuthPages(39-52)
packages/project-builder-server/src/compiler/admin/index.ts (1)
packages/project-builder-server/src/compiler/lib/web-auth.ts (1)
compileAuthPages(39-52)
packages/sync/src/utils/ordered-list.ts (1)
packages/utils/src/toposort/toposort.ts (1)
toposortOrdered(204-210)
packages/sync/src/phases/sort-task-phases.ts (1)
packages/utils/src/toposort/toposort.ts (1)
toposortOrdered(204-210)
packages/sync/src/runner/dependency-sort.ts (1)
packages/utils/src/toposort/toposort-dfs.ts (1)
toposortDfs(40-93)
packages/project-builder-lib/src/plugins/imports/loader.ts (1)
packages/utils/src/toposort/toposort.ts (1)
toposortOrdered(204-210)
packages/react-generators/src/generators/apollo/react-apollo/templates/app/AppApolloProvider.tsx (1)
packages/react-generators/src/generators/apollo/react-apollo/templates/services/apollo/index.ts (1)
createApolloClient(7-17)
packages/react-generators/src/generators/auth/_providers/auth-components.ts (1)
packages/sync/src/providers/providers.ts (1)
createProviderType(151-210)
packages/core-generators/src/renderers/typescript/imports/sort-imports/sort-import-declarations.ts (1)
packages/core-generators/src/renderers/typescript/imports/sort-imports/get-import-sort-group.ts (1)
ImportSortGroup(30-30)
packages/react-generators/src/generators/core/react-sentry/react-sentry.generator.ts (3)
packages/sync/src/generators/generators.ts (1)
createGeneratorTask(196-204)packages/react-generators/src/generators/core/react-sentry/generated/ts-import-maps.ts (2)
reactSentryImportsProvider(19-22)createReactSentryImports(24-35)packages/core-generators/src/providers/scopes.ts (1)
projectScope(3-6)
packages/react-generators/src/generators/auth/_providers/auth-hooks.ts (1)
packages/sync/src/providers/providers.ts (1)
createProviderType(151-210)
packages/react-generators/src/generators/apollo/apollo-error/apollo-error.generator.ts (4)
packages/core-generators/src/generators/node/typescript/typescript.generator.ts (1)
typescriptFileProvider(146-147)packages/core-generators/src/providers/scopes.ts (1)
projectScope(3-6)packages/react-generators/src/generators/apollo/apollo-error/generated/ts-import-maps.ts (2)
apolloErrorImportsProvider(18-21)createApolloErrorImports(23-33)packages/react-generators/src/generators/apollo/apollo-error/generated/ts-templates.ts (1)
APOLLO_APOLLO_ERROR_TS_TEMPLATES(10-10)
packages/utils/src/toposort/toposort-dfs.ts (1)
packages/utils/src/toposort/errors.ts (2)
ToposortUnknownNodeError(12-19)ToposortCyclicalDependencyError(1-10)
packages/react-generators/src/generators/core/react-router/react-router.generator.ts (7)
packages/sync/src/providers/providers.ts (1)
createReadOnlyProviderType(219-224)packages/react-generators/src/providers/routes.ts (4)
ReactRoute(11-17)ReactRouteLayout(5-9)reactRoutesProvider(26-27)reactRoutesReadOnlyProvider(34-37)packages/sync/src/generators/generators.ts (1)
createGeneratorTask(196-204)packages/core-generators/src/providers/scopes.ts (1)
projectScope(3-6)packages/core-generators/src/generators/node/typescript/typescript.generator.ts (1)
typescriptFileProvider(146-147)packages/core-generators/src/renderers/typescript/fragments/creators.ts (1)
tsCodeFragment(39-49)packages/core-generators/src/renderers/typescript/imports/builder.ts (1)
tsImportBuilder(69-77)
packages/core-generators/src/renderers/typescript/ts-code-utils.ts (1)
packages/core-generators/src/renderers/typescript/fragments/types.ts (1)
TsCodeFragment(45-62)
packages/react-generators/src/generators/admin/admin-bull-board/admin-bull-board.generator.ts (5)
packages/sync/src/utils/create-provider-task.ts (1)
createProviderTask(18-32)packages/react-generators/src/generators/core/react-config/react-config.generator.ts (2)
reactConfigProvider(72-72)reactConfigImportsProvider(161-161)packages/sync/src/generators/generators.ts (1)
createGeneratorTask(196-204)packages/core-generators/src/generators/node/typescript/typescript.generator.ts (1)
typescriptProvider(94-95)packages/react-generators/src/generators/core/react-components/react-components.generator.ts (1)
reactComponentsProvider(74-75)
packages/react-generators/src/generators/auth0/auth0-apollo/auth0-apollo.generator.ts (6)
packages/sync/src/utils/create-generator.ts (1)
createGenerator(96-123)packages/sync/src/generators/generators.ts (1)
createGeneratorTask(196-204)packages/react-generators/src/generators/apollo/react-apollo/react-apollo.generator.ts (1)
reactApolloConfigProvider(162-162)packages/react-generators/src/generators/apollo/apollo-error/apollo-error.generator.ts (1)
apolloErrorProvider(26-27)packages/core-generators/src/renderers/typescript/fragments/creators.ts (1)
tsCodeFragment(39-49)packages/core-generators/src/renderers/typescript/imports/builder.ts (1)
tsImportBuilder(69-77)
packages/react-generators/src/generators/apollo/apollo-sentry/apollo-sentry.generator.ts (8)
packages/react-generators/src/generators/apollo/react-apollo/react-apollo.generator.ts (1)
reactApolloConfigProvider(162-162)packages/react-generators/src/generators/apollo/apollo-error-link/apollo-error-link.generator.ts (1)
apolloErrorLinkProvider(21-23)packages/core-generators/src/renderers/typescript/imports/builder.ts (1)
tsImportBuilder(69-77)packages/sync/src/generators/generators.ts (1)
createGeneratorTask(196-204)packages/core-generators/src/generators/node/typescript/typescript.generator.ts (1)
typescriptFileProvider(146-147)packages/react-generators/src/generators/core/react-sentry/react-sentry.generator.ts (1)
reactSentryImportsProvider(168-168)packages/react-generators/src/generators/core/react-error/react-error.generator.ts (1)
reactErrorImportsProvider(126-126)packages/react-generators/src/generators/apollo/apollo-sentry/generated/ts-templates.ts (1)
APOLLO_APOLLO_SENTRY_TS_TEMPLATES(17-17)
packages/utils/src/toposort/toposort.ts (1)
packages/utils/src/toposort/errors.ts (1)
ToposortCyclicalDependencyError(1-10)
🔇 Additional comments (71)
packages/react-generators/src/generators/core/react-router/react-router.generator.ts (2)
49-55: Alias inpagesPathmay not resolve in generated code.
pagesPathis set to'@/src/pages/index.tsx', but the destination file is generated at'src/pages/index.tsx'(line 148). Unless the tooling configures@/as an alias, this import will be unresolved at build-time.-const pagesPath = '@/src/pages/index.tsx'; +// Use relative path; generators relying on ts-config path aliases can still remap this. +const pagesPath = './src/pages/index.tsx';Alternatively, keep the alias but add a follow-up to ensure a
pathsmapping for'@/*'is emitted by the TS/webpack generators.
51-55: Good use of a read-only provider for route values.The newly-introduced
reactRouteValuesProvidercleanly separates data collection from code generation, aligning with the provider pattern used elsewhere.packages/react-generators/src/generators/auth/auth-identify/auth-identify.generator.ts (1)
20-20: Import path updated — confirm provider re-export visibility.The new path
../_providers/auth-hooks.jsassumes that_providersis public to other generators. Ensure that:
auth-hooks.jsis actually moved and exported from the project’s entry points.- TS path aliases / package exports are updated so downstream packages don’t break.
If both are satisfied, this change improves cohesion by colocating common providers.
packages/react-generators/src/generators/admin/admin-home/admin-home.generator.ts (1)
13-13: Updated import path for authHooksProvider
Aligns with the new consolidated provider modules under@src/generators/auth/_providers.packages/utils/package.json (1)
41-41: Added tinyqueue dependency for ordered toposort
This new runtime dependency supports the priority‐queue‐based topological sorting enhancements in@halfdomelabs/utils.packages/react-generators/src/generators/auth0/auth0-hooks/auth0-hooks.generator.ts (1)
14-14: Switched authHooksProvider import to new_providersmodule
Ensures the generator uses the updated, consolidated auth hooks provider.packages/react-generators/src/generators/auth0/auth0-components/auth0-components.generator.ts (1)
9-9: Updated import path for authComponentsProvider
Reflects the move to the centralized_providersdirectory for auth components.packages/sync/src/phases/sort-task-phases.ts (1)
1-1: UsetoposortOrderedfor stable task phase ordering
Replaces the previoustoposortcall to guarantee deterministic ordering of independent nodes.Also applies to: 53-53
packages/project-builder-server/src/compiler/web/index.ts (1)
45-45: Updated function call matches new APIThe removal of the
allowedRolesparameter from thecompileAuthPagesfunction call aligns with the refactored authentication system that now exclusively supports Auth0-based authentication.packages/project-builder-server/src/compiler/admin/index.ts (1)
86-86: Updated function call matches new APIThe removal of the
allowedRolesparameter from thecompileAuthPagesfunction call is consistent with the simplified Auth0-only authentication approach. This change matches the updated function signature in the web-auth.ts file.packages/sync/src/utils/ordered-list.ts (2)
1-1: Updated import to use the new topological sort functionThe import has been changed from
toposorttotoposortOrdered, which is part of the broader refactoring of the topological sorting utilities.
41-41: Switched to improved topological sorting algorithmChanged from
toposorttotoposortOrderedwhich provides more stable ordering with the same functionality. The new function is a BFS-based implementation that supports stable ordering with optional lexical comparison.packages/react-generators/src/generators/auth0/auth0-callback/auth0-callback.generator.ts (1)
10-10: Updated import path to use consolidated providers moduleThe import path for
authHooksProviderhas been changed to use the new consolidated import from theauth/index.jsmodule. This change is part of the broader refactoring of authentication generators, where multiple auth-related providers are now organized in a centralized structure.packages/project-builder-web/src/app/ProjectSyncModal/ProjectSyncModal.tsx (1)
16-16: Good addition of thelogAndFormatErrorfunction.This import modification adds the new error handling utility alongside the existing
formatErrorfunction.packages/sync/src/runner/dependency-sort.ts (2)
1-1: Improved topological sorting implementation.Switching to
toposortDfsbrings enhanced cycle detection and better error reporting capabilities.
84-84: Enhanced topological sorting algorithm.The implementation now uses a depth-first search based algorithm with better cycle detection and more informative error messages when cycles are found in the dependency graph.
packages/react-generators/src/generators/admin/admin-layout/admin-layout.generator.ts (1)
17-18: Good refactoring of auth provider imports.The imports now reference the new consolidated provider modules under the
_providerssubdirectory, which aligns with the broader refactoring of authentication generators into a more unified structure.packages/project-builder-lib/src/plugins/imports/loader.ts (2)
1-1: Improved topological sorting with ordered output.Switching to
toposortOrderedprovides deterministic ordering of nodes with the same dependency level, which is beneficial for reproducible builds and testing.
88-88: Enhanced deterministic sorting.The
toposortOrderedfunction ensures consistent ordering of nodes at the same topological level, improving the predictability of the plugin initialization sequence.packages/utils/src/toposort/index.ts (1)
1-2: Excellent extension of thetoposortmodule public APIThe additions nicely expand the module's functionality by exporting new error classes and the DFS-based topological sort implementation. This supports the broader refactoring goals by providing more specialized sorting algorithms to various consumers in the codebase.
packages/react-generators/src/generators/apollo/apollo-sentry/templates/apollo-sentry-link.ts (2)
3-4: Good shift to aliased importsConverting to aliased imports ('%reactErrorImports' and '%reactSentryImports') aligns with the modular provider approach in the PR objectives. This makes the template more flexible and maintainable.
6-6: Reordered imports for better organizationThe reordering of imports from '@apollo/client/utilities' improves consistency, likely to align with the new import sorting standards being implemented throughout the codebase.
packages/react-generators/src/generators/auth/_providers/index.ts (1)
1-2: Clean consolidation of auth exportsThis barrel file effectively simplifies the auth module's public API by re-exporting components and hooks from a single entry point. This aligns perfectly with the PR's goal of refactoring the React generators to a more organized TypeScript scheme, while focusing on Auth0-based authentication.
packages/core-generators/src/generators/node/eslint/generate-config.ts (1)
78-87: Well-structured import ordering ruleEnabling the import/order rule with this configuration establishes a consistent standard across the codebase. The pattern of external imports first, followed by internal modules ('src/' and '@src/'), with alphabetical ordering is a clean approach that will improve code readability and maintainability.
packages/core-generators/src/generators/node/typescript/typescript.generator.ts (3)
343-354: Good improvement to centralize import sorting configuration.You've created a new
sharedRenderOptionsobject to centralize and standardize import sorting configuration, which is now used by bothrenderTsTemplateFileActionandrenderTsTemplateGroupAction. This improves code maintainability by removing duplication and ensuring consistent import sorting behavior across template renderers.The use of
as constwith the groups array also ensures type safety by making the array readonly.
368-368: Clean implementation of shared options.Spreading the shared configuration here ensures consistent import sorting behavior while keeping the code DRY.
393-393: Consistent application of shared options.The shared import sorting configuration is properly applied to the template group rendering as well, ensuring consistency across all template rendering functions.
packages/react-generators/src/generators/apollo/react-apollo/templates/services/apollo/index.ts (4)
5-5: Updated import to use explicit file extension.Adding the
.jsextension in the import path follows modern ESM best practices for explicit file resolution.
8-8: Template placeholder renamed to follow new convention.Changing from
CREATE_ARGStoTPL_CREATE_ARGSfollows the new template variable naming convention with theTPL_prefix, which makes template placeholders more identifiable and consistent across the codebase.
10-10: Template placeholder renamed to follow new convention.Changing from
LINK_BODIEStoTPL_LINK_BODIESfollows the new naming convention with theTPL_prefix for template variables.
12-12: Template placeholder renamed to follow new convention.Changing from
LINKStoTPL_LINKSfollows the new naming convention with theTPL_prefix for template variables.packages/core-generators/src/renderers/typescript/imports/sort-imports/sort-import-declarations.ts (1)
17-17: Improved type safety with readonly arrays.Changing the
groupsproperty type from a mutable array to a readonly array (readonly (ImportSortGroup | readonly ImportSortGroup[])[]) ensures that the groupings used for sorting import declarations cannot be modified after initialization. This enforces immutability and prevents potential bugs from unintended modifications to the group configurations.This is a good improvement for type safety that aligns with best practices for immutability in TypeScript.
packages/react-generators/src/generators/apollo/react-apollo/templates/app/AppApolloProvider.tsx (3)
6-6: Updated import to use explicit relative path.Replacing the placeholder import
'%react-apollo/client'with a specific relative path'../services/apollo/index.js'improves clarity and follows modern ESM best practices with explicit file extensions.
13-13: Template placeholder renamed to follow new convention.Changing from
RENDER_BODYtoTPL_RENDER_BODYfollows the new naming convention with theTPL_prefix for template variables, making them more identifiable in the code.
16-17: Template placeholders renamed to follow new convention.Changing from:
() => createApolloClient(CREATE_ARG_VALUE)to() => createApolloClient(TPL_CREATE_ARGS)[CREATE_ARGS]to[TPL_MEMO_DEPENDENCIES]These updates follow the new template variable naming convention and improve consistency with the related Apollo client template in
../services/apollo/index.js. This ensures that the template variables are clearly identifiable and consistently named across the codebase.packages/utils/src/toposort/toposort.unit.test.ts (3)
6-7: Import paths updated to reflect modular architectureThe import paths have been updated to import error classes from a separate
errors.jsfile and the maintoposortfunction fromtoposort.js. This follows good modular design principles by separating concerns.
151-155: Updated cycle path order to match new implementationThe test case for detecting longer cycles has been correctly updated to reflect the new cycle path format from the refactored implementation. This ensures the test correctly validates the behavior of the new Kahn's algorithm-based approach.
239-254: Good test coverage for new sorting functionalityThe new test thoroughly verifies that the
toposortfunction correctly respects the provided lexical comparison function by testing both ascending and descending ordering scenarios. This ensures the new stable ordering feature works as expected.packages/react-generators/src/generators/auth/_providers/auth-components.ts (2)
1-8: Clean provider type definition with appropriate importsThe implementation correctly defines the
AuthComponentsProvidertype alias based on theImportMapperinterface, with proper imports from core packages. This follows the modular provider pattern being adopted across the codebase.
7-8: Provider creation with kebab-case identifierThe
authComponentsProvideris properly created using thecreateProviderTypefactory function with the appropriate type parameter and kebab-case identifier. This follows the established conventions for provider types in the codebase.packages/react-generators/src/generators/core/react-sentry/react-sentry.generator.ts (3)
30-33: Imports added for new import provider functionalityThe imports for
createReactSentryImportsandreactSentryImportsProviderfrom the local generated module are correctly added to support the new imports task.
99-110: New imports generator task properly implementedThe new generator task for imports is well-structured and follows the established pattern for provider-based tasks:
- Exports the provider scoped to the project
- Creates runtime imports targeting the correct service path
- Uses the appropriate provider type
This addition enhances modularity and reusability of the React Sentry imports.
168-168: Appropriate re-export of the providerThe provider is correctly re-exported to make it available for other modules to consume, which follows the modular design pattern being implemented across the codebase.
packages/react-generators/src/generators/auth/_providers/auth-hooks.ts (3)
1-4: Proper imports for provider implementationThe implementation correctly imports the required dependencies from core packages to support the provider definition.
5-7: Well-defined interface with clear method signatureThe
AuthHooksProviderinterface properly extends theImportMapperinterface and adds a clearly defined methodaddCurrentUserFieldwith appropriate parameter and return types. This provides a clean API for consumers of this provider.
9-10: Provider creation follows established patternThe
authHooksProvideris correctly instantiated usingcreateProviderTypewith the appropriate type parameter and kebab-case identifier, consistent with other providers in the codebase.packages/react-generators/src/generators/auth/index.ts (1)
1-2:Details
✅ Verification successful
Confirm
.jsextension & downstream import breakagesBoth export paths end with
.jswhile the file itself is.ts.
This is totally fine innodenext/node16resolution modes, but it means every call-site must also use.jsand the compiled output must live next to the sources. Please grep for old paths (e.g../auth-components,./auth-hooks, …) that have now vanished, otherwise consumers will crash at runtime.
🏁 Script executed:
#!/bin/bash # Verify no code still imports the removed symbols. rg -n "from ['\"]\\.\\/auth-(apollo|components|hooks|layout|login-page|pages|service)['\"]"Length of output: 252
🏁 Script executed:
#!/bin/bash # Re‐verify that no files import the removed auth-* modules without the .js extension rg -n "from ['\"]\./auth-(apollo|components|hooks|layout|login-page|pages|service)['\"]" -g "*.ts" -g "*.tsx" -g "*.js" -g "*.jsx"Length of output: 136
No remaining broken imports from auth- modules*
I ran a global search across *.ts, *.tsx, *.js, and .jsx for anyimport … from './auth-apollo'(and other auth- paths) without the.jsextension and found no matches. All downstream references have been updated (or never existed), so consumers won’t crash at runtime.packages/react-generators/src/generators/apollo/apollo-error/apollo-error.generator.ts (1)
14-19: Mismatch between generated file (.ts) and import map (.js)
utilPathis set to@/src/utils/apollo-error.ts, butcreateApolloErrorImports()(see generated map) appendsapollo-error.js.
That means:
- The import map will point to
@/src/utils/apollo-error.js.- The generator writes
apollo-error.ts.Relying on
.jsin import specifiers is fine, yet we will end up with two sibling files after compilation (.ts+ emitted.js). Make sure the build pipeline keeps them in sync and does not emit duplicate declarations.If you intended the import map to reference source, change one side for consistency.
packages/utils/src/toposort/errors.ts (2)
1-10: Well-structured custom error for cyclical dependenciesThe
ToposortCyclicalDependencyErrorclass is well-implemented with:
- Proper extension of the base Error class
- Descriptive error message that includes the cycle path
- Storage of the cycle path for debugging and inspection
- Proper name assignment for error identification
The serialization of nodes in the error message using
JSON.stringifyensures clear error reporting regardless of node type.
12-20: Well-structured custom error for unknown nodesThe
ToposortUnknownNodeErrorclass follows best practices for custom errors:
- Extends the standard Error class
- Creates a descriptive error message with the serialized node
- Stores the unknown node for inspection
- Sets the proper error name for type identification
The implementation is clean and consistent with the previous error class.
packages/utils/src/field-map/field-map.ts (2)
183-234: Well-designed named array container implementationThe
NamedArrayFieldContainerclass is a robust implementation for storing arrays of named objects with several key features:
- Proper implementation of the
FieldContainer<V[]>interface- Internal tracking of value sources to prevent overwrites
- Appropriate error handling for duplicate names
- Sorted output by name property when retrieving values
- Consistent pattern with other containers in the codebase
This container will be valuable for managing collections of named objects while preventing duplicates and maintaining a consistent order.
405-410: Good extension of the schema builderThe
namedArraymethod added toFieldMapSchemaBuilderproperly exposes the new container type, maintaining a consistent API with the other container factory methods. The method correctly passes both the initial values and options to the container constructor.packages/utils/src/toposort/toposort-dfs.unit.test.ts (6)
1-8: Proper imports and test setupThe test file correctly imports the necessary testing tools from Vitest and the custom error classes from the errors module. The import structure is clean and well-organized.
9-39: Excellent helper function for verifying topological orderingThe
expectOrderhelper function provides a robust mechanism for verifying that all dependencies are met in the sorted output. It:
- Creates a position map for efficient lookups
- Checks each edge to ensure source nodes appear before target nodes
- Provides clear error messages when constraints are violated
- Handles edge cases like missing nodes
This is a critical component that improves the readability and robustness of the tests.
40-111: Comprehensive test cases for basic scenariosThese tests thoroughly verify the basic functionality of
toposortDfs:
- Empty graph handling
- Single node scenarios
- Linear chains with different node types (strings and numbers)
- Multiple paths and branching dependencies
- Disconnected components
- Nodes without edges
Each test uses appropriate assertions and the
expectOrderhelper to validate the topological ordering constraints.
113-181: Thorough testing of cycle detectionThe tests for cyclical dependency detection are excellent:
- Simple two-node cycles
- More complex, longer cycles
- Self-loops (nodes depending on themselves)
The error checks verify both the error type and the specific cycle path captured in the error object, ensuring that the error reporting is accurate and helpful for debugging.
182-214: Comprehensive unknown node error testingThese tests thoroughly verify that the algorithm correctly detects and reports unknown nodes:
- Tests for unknown sources in edges
- Tests for unknown targets in edges
- Verification of the error message and the stored unknown node
The multiple assertion approaches (direct throw check, message pattern matching, and error property inspection) provide redundant verification.
216-242: Edge case handling for objects and duplicatesThese final tests ensure that the algorithm correctly handles:
- Nodes as objects (reference equality)
- Duplicate edges without issues
These edge cases are important to verify the robustness of the implementation with different data types and input patterns.
packages/react-generators/src/generators/admin/admin-bull-board/admin-bull-board.generator.ts (6)
12-13: Added import for provider task supportThe
createProviderTaskimport is correctly added to support the new provider task implementation.
19-22: Updated imports for React config providersThe imports are now properly organized to include both
reactConfigImportsProviderandreactConfigProviderfrom the React config generator module. This supports the new modular approach to configuration management.
40-46: Good modularization of configuration setupThe new
reactConfigprovider task properly encapsulates the configuration setup logic:
- Sets the
VITE_BULL_BOARD_BASEconfig entry with appropriate validation- Provides a helpful comment describing the config entry's purpose
- Sets a sensible default value derived from the descriptor
This approach is more modular and maintainable compared to setting config entries directly within the build function.
51-52: Updated dependency to use imports providerThe generator now correctly depends on
reactConfigImportsProviderinstead ofreactConfigProvider, aligning with the architectural changes to separate config definition from usage.
62-63: Updated parameter name in run functionThe run function parameter is correctly updated to match the new dependency name, ensuring proper access to the imports provider.
74-84: Improved import mapping implementationThe import mappers array now includes a custom mapper for
%react-configthat:
- Points to the source path from the
reactConfigImports.config.sourceproperty- Restricts allowed imports to just the
configexport, enhancing type safety- Uses a proper object structure with
getImportMapfunctionThis approach is more robust and flexible than the previous implementation.
packages/project-builder-server/src/compiler/lib/web-auth.ts (1)
29-36: Route / bundle keys risk clashing withcompileAuthPagesThe
authkey is used here for the generator bundle and again as the child route id insidecompileAuthPages.
If the route builder enforces unique ids within a tree, using the same key twice (auth→ children.auth) may either override the parent or cause a collision. Please verify this withreactRoutesGenerator; if collisions are disallowed, rename one of the keys (e.g.authProvider).packages/react-generators/src/generators/apollo/apollo-error-link/apollo-error-link.generator.ts (1)
83-89: Possible mismatch withreactErrorImportsProvider/reactLoggerImportsProviderAPIThe generator accesses
reactErrorImports.logErrorandreactLoggerImports.logger, but the provider types shown in related snippets expose an array (reactErrorImports: TsImportDeclarationBuilder[]).
If the provider now returns named builders, update its type declaration; otherwise this will beundefinedat runtime and the imports won’t be emitted.packages/react-generators/src/generators/apollo/apollo-sentry/apollo-sentry.generator.ts (2)
90-103: Dependency ordering looks good—just ensure the error link is registered firstThe Sentry link declares a dependency on
apolloErrorLink.errorLinkName, which should guarantee correct ordering.
If the link dispatcher does not topologically sortapolloLinksby thedependenciesarray, consider running a quick verification to ensureapolloSentryLinkis inserted aftererrorLink.
114-120: Template rendering: confirm import maps cover all symbols
renderTemplateFilereceives onlyreactSentryImportsandreactErrorImports.
If the template usesGraphQLError,ApolloError, etc., ensure those imports are either hard-coded in the template or included via the provided import maps, otherwise the emitted file may have missing imports.packages/utils/src/toposort/toposort.ts (1)
109-115:defaultCompareFuncmay yield undefined behaviour for non-primitive nodesThe generic
<comparison coerces objects to strings like'[object Object]', giving unstable and implementation-dependent ordering.Either:
- Restrict
toposortOrderedtoT extends string | number; or- Throw if
typeof a !== typeof b || typeof a not in {string, number}; or- Require callers to supply an explicit comparator.
packages/react-generators/src/generators/apollo/react-apollo/react-apollo.generator.ts (2)
348-359: Hard-coded template path may break once the generator is moved; consider usingimport.meta.url+ relative resolve.
builder.readTemplate('websocket-links.ts');relies on the current working directory. Resolve it explicitly to make the generator relocatable:builder.readTemplate( new URL('./templates/websocket-links.ts', import.meta.url).pathname, );
149-160:Details
✅ Verification successful
Verify
t.namedArray()really exists – the public task DSL never advertised it.
createConfigProviderTaskreceives:createApolloClientArguments: t.namedArray<ApolloCreateArgument>(),Search the repo / package for
namedArray. If it is missing or experimental, generation will explode at runtime.
🏁 Script executed:
#!/bin/bash # Does our DSL expose `namedArray`? rg -n "namedArray<" -g "*.ts" | head -n 20Length of output: 434
No issue found:
t.namedArray()is defined in the DSLI verified that
namedArrayis implemented inpackages/utils/src/field-map/field-map.ts(around line 405), so usingt.namedArray<…>()is valid and will not cause runtime errors.
| typescriptFile: typescriptFileProvider, | ||
| }, | ||
| exports: { | ||
| apolloError: apolloErrorProvider.export(projectScope), | ||
| apolloErrorImports: apolloErrorImportsProvider.export(projectScope), | ||
| }, | ||
| run({ typescript }) { | ||
| const [utilImport, utilPath] = makeImportAndFilePath( | ||
| 'src/utils/apollo-error.ts', | ||
| ); | ||
| run({ typescriptFile }) { | ||
| const utilPath = '@/src/utils/apollo-error.ts'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Hard-coded util path reduces reusability
'@/src/utils/apollo-error.ts' is embedded twice, locking projects into that folder structure.
Expose this as a generator descriptor option (defaulting to the current value) so consumers can relocate utilities without forking the generator.
| // TODO: Reversing the array is necessary to keep the behavior consistent | ||
| // with toposort.array from the toposort package. Once we make the | ||
| // generation order independent, we can remove this logic and the reverse | ||
| // iteration below. | ||
| const outgoingEdgesArray = [...outgoingEdges]; | ||
| for (const neighbor of outgoingEdgesArray.reverse()) { | ||
| visit(neighbor, path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Repeated .reverse() hurts big graphs
Inside every DFS call you create const outgoingEdgesArray = [...outgoingEdges].reverse().
For a dense graph this incurs O(E²) extra work. Instead, build the reversed array once when you populate outgoingEdgesMap:
-const outgoingEdgesArray = [...outgoingEdges];
-for (const neighbor of outgoingEdgesArray.reverse()) {
+const neighbors = Array.isArray(outgoingEdges)
+ ? [...outgoingEdges].reverse()
+ : []; // should never be empty
+for (const neighbor of neighbors) {(or better: store them in reversed order up-front).
Committable suggestion skipped: line range outside the PR's diff.
| if (!builder.projectDefinition.auth?.useAuth0) { | ||
| throw new Error('Auth0 is not enabled'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Throwing on missing Auth0 may be too rigid—consider a graceful fallback
Both compileAuthFeatures and compileAuthPages now throw when useAuth0 is falsy.
In projects where includeAuth is true but the provider is intentionally left undecided, this hard-failure prevents the rest of the compilation pipeline from running (e.g. for mobile targets or future providers). Returning undefined (like the early-exit above) or a more descriptive, typed GeneratorDisabledError would allow callers to ignore unsupported auth providers without crashing the build.
Also applies to: 42-44
🏁 Script executed:
#!/bin/bash
# Inspect compileAuthFeatures implementation
rg -n "compileAuthFeatures" -A5 packages/project-builder-server/src/compiler/lib/web-auth.ts
# Inspect compileAuthPages implementation
rg -n "compileAuthPages" -A5 packages/project-builder-server/src/compiler/lib/web-auth.ts
# Check if a GeneratorDisabledError type already exists
rg -n "GeneratorDisabledError"Length of output: 662
🏁 Script executed:
#!/bin/bash
# Search for all occurrences of useAuth0 in the file to see where compileAuthFeatures references it
rg -n "useAuth0" packages/project-builder-server/src/compiler/lib/web-auth.tsLength of output: 185
Gracefully disable Auth0 instead of hard‐failing
Both compileAuthFeatures (at lines 25–26) and compileAuthPages (at lines 42–44) currently do:
if (!builder.projectDefinition.auth?.useAuth0) {
throw new Error('Auth0 is not enabled');
}Throwing a generic Error here will abort your entire build whenever useAuth0 is false. To allow projects that includeAuth but haven’t picked a provider (or target platforms that don’t support Auth0) to continue:
• Change each function to return undefined when Auth0 is disabled (and update its signature to allow undefined)
• —or—
• Define and throw a custom GeneratorDisabledError so callers can catch and skip disabled generators
For example, in packages/project-builder-server/src/compiler/lib/web-auth.ts:
-export function compileAuthPages(...): GeneratorBundle {
- if (!builder.projectDefinition.auth?.useAuth0) {
- throw new Error('Auth0 is not enabled');
- }
+export function compileAuthPages(...): GeneratorBundle | undefined {
+ if (!builder.projectDefinition.auth?.useAuth0) {
+ // Auth0 is disabled—skip this generator
+ return undefined;
+ }And similarly update compileAuthFeatures. Ensure downstream callers check for undefined (or catch your new GeneratorDisabledError) so the rest of the compilation pipeline can proceed.
| reactApolloConfig.apolloLinks.add({ | ||
| name: 'errorLink', | ||
| bodyExpression: TypescriptCodeUtils.createBlock( | ||
| priority: 'error', | ||
| bodyFragment: tsCodeFragment( | ||
| `const errorLink = onError(({ graphQLErrors, networkError, operation }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nameImport missing—type may be incompatible with reactApolloConfig.apolloLinks
reactApolloConfig.apolloLinks.add({ … }) omits the nameImport property that the provider’s type previously required.
Unless the interface was recently updated to accept a bodyFragment instead, this will be a compile-time error.
+ nameImport: tsImportBuilder(['errorLink']).from('@/src/...'),
priority: 'error',
- bodyFragment: tsCodeFragment( … )
+ bodyFragment, // keep the fragment if the new interface allows bothPlease confirm the current shape of apolloLinks before merging.
Committable suggestion skipped: line range outside the PR's diff.
| function getUtilsPath(source: TemplateFileSource): string { | ||
| if (!('path' in source)) { | ||
| throw new Error('Template path is required'); | ||
| } | ||
| return path.join('@/src/utils', source.path); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use path.posix.join to generate portable, repo-style import paths
path.join() produces back-slashes on Windows, which then leak into generated TypeScript import specifiers (e.g. import './utils\\foo') and break builds on *nix CI runners.
Switch to the POSIX helper to guarantee forward-slash separators regardless of host OS.
-import path from 'node:path';
+import path from 'node:path';
...
- return path.join('@/src/utils', source.path);
+ return path.posix.join('@/src/utils', source.path);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function getUtilsPath(source: TemplateFileSource): string { | |
| if (!('path' in source)) { | |
| throw new Error('Template path is required'); | |
| } | |
| return path.join('@/src/utils', source.path); | |
| } | |
| import path from 'node:path'; | |
| function getUtilsPath(source: TemplateFileSource): string { | |
| if (!('path' in source)) { | |
| throw new Error('Template path is required'); | |
| } | |
| return path.posix.join('@/src/utils', source.path); | |
| } |
| const zeroInDegreeQueue = compareFunc | ||
| ? new TinyQueue<number>([], (a, b) => compareFunc(nodes[a], nodes[b])) | ||
| : ([] as number[]); | ||
|
|
||
| function visit(idx: number, path: number[]): void { | ||
| if (visited.has(idx)) { | ||
| return; // Already fully processed, do nothing | ||
| } | ||
| if (visiting.has(idx)) { | ||
| // Cycle detected! Reconstruct the cycle path from the current path | ||
| const cycleStartIndex = path.indexOf(idx); | ||
| const cyclePath = [...path.slice(cycleStartIndex), idx].map( | ||
| (i) => nodes[i], | ||
| ); | ||
| throw new ToposortCyclicalDependencyError(cyclePath); | ||
| for (const [i, nodeInDegree] of nodeInDegrees.entries()) { | ||
| if (nodeInDegree === 0) { | ||
| zeroInDegreeQueue.push(i); | ||
| } | ||
| } | ||
|
|
||
| visiting.add(idx); | ||
| path.push(idx); // Add node to current path (for error reporting) | ||
| const result: T[] = []; | ||
| const visited = new Set<number>(); | ||
|
|
||
| const outgoingEdges = outgoingEdgesMap.get(idx); | ||
| // Process nodes in BFS order | ||
| while (zeroInDegreeQueue.length > 0) { | ||
| const current = zeroInDegreeQueue.pop(); | ||
| if (current === undefined) break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array fallback behaves as a stack, breaking BFS & deterministic order
When compareFunc is not supplied we fall back to a raw array and still call .pop().
Array#pop() is LIFO, so the traversal degrades to DFS order, producing non-deterministic results that differ from the priority-queue path.
Switch to FIFO (shift) or, more simply, always use TinyQueue with a trivial comparator.
- while (zeroInDegreeQueue.length > 0) {
- const current = zeroInDegreeQueue.pop();
+ while (zeroInDegreeQueue.length > 0) {
+ const current = compareFunc
+ ? zeroInDegreeQueue.pop() // TinyQueue → min-heap
+ : zeroInDegreeQueue.shift(); // Array → FIFO queue📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const zeroInDegreeQueue = compareFunc | |
| ? new TinyQueue<number>([], (a, b) => compareFunc(nodes[a], nodes[b])) | |
| : ([] as number[]); | |
| function visit(idx: number, path: number[]): void { | |
| if (visited.has(idx)) { | |
| return; // Already fully processed, do nothing | |
| } | |
| if (visiting.has(idx)) { | |
| // Cycle detected! Reconstruct the cycle path from the current path | |
| const cycleStartIndex = path.indexOf(idx); | |
| const cyclePath = [...path.slice(cycleStartIndex), idx].map( | |
| (i) => nodes[i], | |
| ); | |
| throw new ToposortCyclicalDependencyError(cyclePath); | |
| for (const [i, nodeInDegree] of nodeInDegrees.entries()) { | |
| if (nodeInDegree === 0) { | |
| zeroInDegreeQueue.push(i); | |
| } | |
| } | |
| visiting.add(idx); | |
| path.push(idx); // Add node to current path (for error reporting) | |
| const result: T[] = []; | |
| const visited = new Set<number>(); | |
| const outgoingEdges = outgoingEdgesMap.get(idx); | |
| // Process nodes in BFS order | |
| while (zeroInDegreeQueue.length > 0) { | |
| const current = zeroInDegreeQueue.pop(); | |
| if (current === undefined) break; | |
| // Process nodes in BFS order | |
| while (zeroInDegreeQueue.length > 0) { | |
| const current = compareFunc | |
| ? zeroInDegreeQueue.pop() // TinyQueue → min-heap | |
| : zeroInDegreeQueue.shift(); // Array → FIFO queue | |
| if (current === undefined) break; |
| // TODO: This should live in the defaults not set afterwards to prevent them from being overridden | ||
| websocketOptions.set( | ||
| 'connectionParams', | ||
| tsCodeFragment(`async () => { | ||
| const accessToken = await getAccessToken(); | ||
| if (!accessToken) { | ||
| return {}; | ||
| } | ||
| return { authorization: \`Bearer \${accessToken}\` }; | ||
| }`), | ||
| url: TypescriptCodeUtils.createExpression( | ||
| `getWsUrl()`, | ||
| undefined, | ||
| { | ||
| headerBlocks: [ | ||
| TypescriptCodeUtils.createBlock(getWsUrlTemplate), | ||
| ], | ||
| }, | ||
| ), | ||
| retryAttempts: | ||
| "86400 /* effectively retry forever (1 month of retries) - there's no way of disabling retry attempts */", | ||
| retryWait: retryWaitTemplate, | ||
| shouldRetry: '() => true', | ||
| }); | ||
| ); | ||
|
|
||
| const wsOptions = TypescriptCodeUtils.mergeExpressionsAsObject( | ||
| websocketOptions.value(), | ||
| websocketOptions.set( | ||
| 'url', | ||
| tsCodeFragment(`getWsUrl()`, [], { | ||
| hoistedFragments: [ | ||
| tsHoistedFragment( | ||
| tsCodeFragment(getWsUrlTemplate), | ||
| 'get-ws-url', | ||
| ), | ||
| ], | ||
| }), | ||
| ); | ||
| websocketOptions.set( | ||
| 'retryAttempts', | ||
| "86400 /* effectively retry forever (1 month of retries) - there's no way of disabling retry attempts */", | ||
| ); | ||
| websocketOptions.set('retryWait', retryWaitTemplate); | ||
| websocketOptions.set('shouldRetry', '() => true'); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
websocketOptions currently serialises functions & numbers as strings, producing invalid runtime types.
Example output after mergeFragmentsAsObject:
{
retryAttempts: "86400 /* … */",
shouldRetry: "() => true"
}Both values become string literals instead of number and () => boolean.
Store them as raw fragments instead:
- websocketOptions.set('retryAttempts',
- "86400 /* effectively retry forever (1 month of retries) - there's no way of disabling retry attempts */",
- );
- websocketOptions.set('shouldRetry', '() => true');
+ websocketOptions.set(
+ 'retryAttempts',
+ tsCodeFragment(`86400 /* effectively retry forever (1 month) */`),
+ );
+ websocketOptions.set(
+ 'shouldRetry',
+ tsCodeFragment('() => true'),
+ );This preserves proper types in the generated code.
| const sortedLinks = toposortOrdered( | ||
| apolloLinks, | ||
| apolloLinks.flatMap( | ||
| (link) => | ||
| link.dependencies?.map((dep): [ApolloLink, ApolloLink] => [ | ||
| findLink(dep), | ||
| link, | ||
| ]) ?? [], | ||
| ), | ||
| ).toSorted( | ||
| (a, b) => | ||
| APOLLO_LINK_PRIORITY[a.priority] - | ||
| APOLLO_LINK_PRIORITY[b.priority], | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array.prototype.toSorted requires Node 20+. Use a backwards-compatible sort to avoid runtime crashes.
Most CI runners and user machines are still on Node 18. toSorted will be undefined, producing a silent failure.
- ).toSorted(
+ )
+ .slice() // create a shallow copy
+ .sort(Alternatively, pin the engine to >=20 in package.json.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const sortedLinks = toposortOrdered( | |
| apolloLinks, | |
| apolloLinks.flatMap( | |
| (link) => | |
| link.dependencies?.map((dep): [ApolloLink, ApolloLink] => [ | |
| findLink(dep), | |
| link, | |
| ]) ?? [], | |
| ), | |
| ).toSorted( | |
| (a, b) => | |
| APOLLO_LINK_PRIORITY[a.priority] - | |
| APOLLO_LINK_PRIORITY[b.priority], | |
| ); | |
| const sortedLinks = toposortOrdered( | |
| apolloLinks, | |
| apolloLinks.flatMap( | |
| (link) => | |
| link.dependencies?.map((dep): [ApolloLink, ApolloLink] => [ | |
| findLink(dep), | |
| link, | |
| ]) ?? [], | |
| ), | |
| ) | |
| .slice() // create a shallow copy | |
| .sort( | |
| (a, b) => | |
| APOLLO_LINK_PRIORITY[a.priority] - | |
| APOLLO_LINK_PRIORITY[b.priority], | |
| ); |
Summary by CodeRabbit
New Features
Enhancements
Removals
Bug Fixes
Tests
Chores