Skip to content

refactor: Migrate auth0 to separate plugin#549

Merged
kingston merged 12 commits into
mainfrom
kingston/eng-379-migrate-auth-plugin-to-plugin-architecture
May 18, 2025
Merged

refactor: Migrate auth0 to separate plugin#549
kingston merged 12 commits into
mainfrom
kingston/eng-379-migrate-auth-plugin-to-plugin-architecture

Conversation

@kingston

@kingston kingston commented May 16, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Introduced a modular Auth0 authentication plugin with configuration UI and integration for backend, web, and admin apps.
    • Added new UI components for model selection and alerts summarizing pending model changes.
    • Developed advanced utilities for structured diffing and merging of project models.
  • Improvements

    • Refactored authentication logic into a plugin-based system for better modularity.
    • Updated forms and components to retrieve roles and models via plugin interfaces.
    • Simplified plugin management and corrected filtering/display logic.
  • Bug Fixes

    • Fixed plugin filtering and display issues in plugin configuration pages.
  • Removals

    • Removed legacy "Features" section and related authentication pages from the web UI.
  • Chores

    • Added build, style, config, license, and metadata files for the new authentication plugin.
  • Tests

    • Added unit tests for model merging and definition diff utilities.

@vercel

vercel Bot commented May 16, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
baseplate-project-builder-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 18, 2025 6:14pm

@linear

linear Bot commented May 16, 2025

Copy link
Copy Markdown

@changeset-bot

changeset-bot Bot commented May 16, 2025

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ae29b1d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@halfdomelabs/baseplate-plugin-storage Patch
@halfdomelabs/project-builder-common Patch
@halfdomelabs/project-builder-server Patch
@halfdomelabs/baseplate-plugin-auth Patch
@halfdomelabs/project-builder-lib Patch
@halfdomelabs/project-builder-web Patch
@halfdomelabs/react-generators Patch
@halfdomelabs/project-builder-cli Patch
@halfdomelabs/project-builder-test Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented May 16, 2025

Copy link
Copy Markdown

Walkthrough

This change set introduces a major refactor to modularize Auth0 authentication functionality into a dedicated plugin, @halfdomelabs/baseplate-plugin-auth, extracting and removing legacy inlined authentication logic from core packages. It updates project builder libraries, generators, and web UI to use a new plugin-based authentication configuration and role management system. Additional utilities for diffing and merging model definitions are introduced, and several test helpers and UI components are added or updated. Redundant or obsolete feature-related pages and routes are removed from the web app, and storage plugin logic is updated to align with the new authentication plugin system.

Changes

File(s) / Path(s) Change Summary
.changeset/lazy-icons-design.md
plugins/baseplate-plugin-auth/* (new directory and files)
Adds new Auth0 authentication plugin: code, schema, React components, generators, configuration, and metadata. Includes build, lint, and test configs, manifest, license, and utility files.
packages/fastify-generators/src/constants/fastify-packages.ts
packages/fastify-generators/src/generators/index.ts
packages/react-generators/src/constants/react-packages.ts
packages/react-generators/src/generators/index.ts
Removes Auth0-related package entries and generator exports from Fastify and React generator packages.
packages/project-builder-common/package.json
packages/project-builder-lib/package.json
Adds new dependency on @halfdomelabs/baseplate-plugin-auth and updates dev dependencies.
packages/project-builder-lib/src/definition/feature/feature-utils.ts
packages/project-builder-lib/src/definition/index.ts
packages/project-builder-lib/src/definition/model/model-utils.ts
packages/project-builder-lib/src/definition/project-definition-container.test-helper.ts
packages/project-builder-lib/src/schema/definition.test-helper.ts
Adds utility functions for feature/model lookup and test helpers for project definitions and models. Updates model utility to include transformer check and PascalCase validation.
packages/project-builder-lib/src/migrations/* Adds migration to move auth config into plugin system (migration-012-migrate-auth-config). Updates migrations index to include new migration.
packages/project-builder-lib/src/plugins/schema/store.ts
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts
packages/project-builder-lib/src/plugins/spec/index.ts
Adds optional plugin spec retrieval and new auth config plugin spec. Updates plugin spec exports.
packages/project-builder-lib/src/schema/auth/index.ts
packages/project-builder-lib/src/schema/auth/types.ts (deleted)
packages/project-builder-lib/src/schema/apps/admin/app.ts
packages/project-builder-lib/src/schema/apps/web/index.ts
packages/project-builder-lib/src/schema/models/graphql.ts
Refactors auth schema: removes zod-based validation, switches to static interfaces, and updates imports/exports accordingly.
packages/project-builder-lib/src/schema/models/index.ts Adds type for model unique constraint input.
packages/project-builder-lib/src/schema/project-definition.ts Removes auth property from project definition schema.
packages/project-builder-lib/src/tools/model-merger/model-merger.ts
packages/project-builder-lib/src/tools/model-merger/model-merger.unit.test.ts
packages/project-builder-lib/src/utils/definition-diff/definition-diff.ts
packages/project-builder-lib/src/utils/definition-diff/definition-diff.unit.test.ts
packages/project-builder-lib/src/utils/definition-diff/index.ts
packages/project-builder-lib/src/utils/index.ts
Adds generic diff/patch utilities and tests. Refactors model merger logic to use new diffing utilities, adds tests for model merging.
packages/project-builder-lib/src/web/components/ModelComboboxField.tsx
packages/project-builder-lib/src/web/components/ModelMergerResultAlert.tsx
packages/project-builder-lib/src/web/components/index.ts
Adds new React components for model selection and displaying model merge results. Updates component exports.
packages/project-builder-server/src/compiler/admin/index.ts
packages/project-builder-server/src/compiler/admin/sections.ts
packages/project-builder-server/src/compiler/backend/fastify.ts
packages/project-builder-server/src/compiler/backend/feature.ts
packages/project-builder-server/src/compiler/backend/graphql.ts
Refactors admin and backend compilers to remove inlined auth logic, switch to plugin-based auth config, and update feature/child generator handling.
packages/project-builder-server/src/compiler/lib/web-auth.ts (deleted)
packages/project-builder-server/src/compiler/web/features.ts (new)
packages/project-builder-server/src/compiler/web/index.ts
Removes legacy web auth compilation logic, adds new web feature compiler, and updates web compiler to use new feature compilation system.
packages/project-builder-web/src/app/AppLayout/AppDesktopSidebar.tsx
packages/project-builder-web/src/app/AppLayout/AppMobileSidebar.tsx
packages/project-builder-web/src/pages/_routes.tsx
packages/project-builder-web/src/pages/features/FeaturesHome.page.tsx (deleted)
packages/project-builder-web/src/pages/features/FeaturesLayout.tsx (deleted)
packages/project-builder-web/src/pages/features/auth/auth-models.ts (deleted)
packages/project-builder-web/src/pages/features/auth/index.tsx (deleted)
packages/project-builder-web/src/pages/features/index.tsx (deleted)
Removes "Features" section: navigation, routes, layout, and feature-specific pages/components.
packages/project-builder-web/src/pages/apps/edit/WebAppForm.tsx
packages/project-builder-web/src/pages/apps/edit/admin/AdminGeneralForm.tsx
packages/project-builder-web/src/pages/data/models/edit/[id]/_components/graphql/GraphQLMutationsSection.tsx
packages/project-builder-web/src/pages/data/models/edit/[id]/_components/graphql/GraphQLQueriesSection.tsx
Refactors role options and auth checks to use plugin-based auth config instead of direct property access.
packages/project-builder-web/src/pages/home/home.page.tsx Swaps "Features" and "Models" cards; updates descriptions and navigation links.
packages/project-builder-web/src/pages/plugins/PluginCard.tsx
packages/project-builder-web/src/pages/plugins/home.page.tsx
packages/project-builder-web/src/pages/plugins/plugin-config.page.tsx
Updates plugin enable/disable logic to use consistent plugin ID matching. Fixes plugin rendering to use correct filtered arrays.
plugins/baseplate-plugin-storage/package.json
plugins/baseplate-plugin-storage/src/storage/core/components/CategoryEditorForm.tsx
plugins/baseplate-plugin-storage/src/storage/core/components/storage-config.tsx
plugins/baseplate-plugin-storage/src/storage/core/schema/models.ts
plugins/baseplate-plugin-storage/src/storage/core/schema/plugin-definition.ts
plugins/baseplate-plugin-storage/src/storage/core/web.ts
Updates storage plugin to use plugin-based auth config, model merger utilities, and corrects schema delete behavior and import paths.
packages/project-builder-lib/src/web/components/ModelComboboxField.tsx
packages/project-builder-lib/src/web/components/ModelMergerResultAlert.tsx
Adds new UI components for model selection and displaying model merge results.
package.json Updates "watch" script to set turbo concurrency to 20.
(Other new/updated config, manifest, and style files in plugins/baseplate-plugin-auth) Adds required build, lint, test, and style configuration for the new plugin.

Sequence Diagram(s)

Plugin-based Authentication Flow (New)

sequenceDiagram
    participant User
    participant WebApp (UI)
    participant ProjectBuilderLib
    participant PluginAuth (Auth0 Plugin)
    participant StoragePlugin

    User->>WebApp: Open authentication/role config UI
    WebApp->>ProjectBuilderLib: Request available plugins
    ProjectBuilderLib->>PluginAuth: Initialize plugin, register schema/components
    WebApp->>PluginAuth: Render AuthDefinitionEditor
    User->>WebApp: Edit/save auth config (roles, user model, etc.)
    WebApp->>PluginAuth: Validate and save plugin config
    PluginAuth->>ProjectBuilderLib: Update plugin config in project definition
    ProjectBuilderLib->>StoragePlugin: Query for user account model via auth plugin
    StoragePlugin->>PluginAuth: getUserAccountModel(definition)
    PluginAuth-->>StoragePlugin: Return user model reference
    StoragePlugin->>ProjectBuilderLib: Complete storage config/model creation
Loading

Model Merger Utility Usage

sequenceDiagram
    participant User
    participant WebApp (UI)
    participant ModelMerger
    participant ProjectDefinition

    User->>WebApp: Edit/create model in UI
    WebApp->>ModelMerger: createModelMergerResult(current, desired, ...)
    ModelMerger->>WebApp: Return PendingModelChange
    WebApp->>ModelMerger: applyModelMergerResultInPlace(definition, result, ...)
    ModelMerger->>ProjectDefinition: Update model(s) in-place
    ProjectDefinition-->>WebApp: Updated definition
Loading

Migration of Legacy Auth Config

sequenceDiagram
    participant MigrationScript
    participant OldConfig
    participant NewConfig
    participant PluginAuth

    MigrationScript->>OldConfig: Read legacy auth config
    alt useAuth0 is true
        MigrationScript->>PluginAuth: Create plugin config from old auth fields
        MigrationScript->>NewConfig: Add plugin config, remove old auth
    else
        MigrationScript->>NewConfig: Remove old auth config
    end
Loading

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@socket-security

socket-security Bot commented May 16, 2025

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedtype-fest@​4.32.0 ⏵ 4.41.0100 +1100100 +193 -1100

View full report

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

🔭 Outside diff range comments (3)
packages/project-builder-lib/src/definition/model/model-utils.ts (1)

63-69: ⚠️ Potential issue

Guard against undefined transformers to avoid runtime crashes

model.service.transformers may be undefined for legacy models or partially-populated test fixtures. Accessing .length on an undefined value will throw at runtime, breaking anything that calls hasService.
Add optional chaining (or a fallback to an empty array) before reading length.

-    !!model.service.delete.enabled ||
-    model.service.transformers.length > 0
+    !!model.service.delete.enabled ||
+    (model.service.transformers?.length ?? 0) > 0
plugins/baseplate-plugin-storage/src/storage/core/schema/models.ts (1)

31-33: ⚠️ Potential issue

Potential integer overflow for large files

The size field is declared as int. For storage use-cases, file sizes can
easily exceed 2 147 483 647 bytes (the typical 32-bit signed limit).
Switching to bigInt (or a 64-bit numeric type supported by the ORM) avoids
silent truncation.

-  {
-    name: 'size',
-    type: 'int',
+  {
+    name: 'size',
+    type: 'bigInt',
   },
packages/project-builder-lib/src/schema/auth/index.ts (1)

12-28: ⚠️ Potential issue

AUTH_DEFAULT_ROLES objects lack an id property

AuthRole requires id, but the constants omit it.
Either relax the AuthRole type for defaults (e.g., Partial<AuthRole>) or generate IDs with authRoleEntityType.generateNewId() to ensure type-safety.

-  {
+  {
+    id: authRoleEntityType.generateNewId(),
     name: 'public',

Repeat for the remaining roles.

🧹 Nitpick comments (29)
plugins/baseplate-plugin-auth/eslint.config.js (1)

1-3: Use the correct ESLint ignore key. The official ESLint config schema uses ignorePatterns to exclude files, not ignores. Please verify that your tooling supports ignores; otherwise, update to:

-export default [...eslintReactConfig, { ignores: ['**/templates/**'] }];
+export default [...eslintReactConfig, { ignorePatterns: ['**/templates/**'] }];
plugins/baseplate-plugin-auth/src/index.ts (1)

1-1: Placeholder Export Consideration
The placeholder export signals a stub. Consider adding a JSDoc comment explaining its purpose or removing this until the plugin API is finalized.

plugins/baseplate-plugin-auth/src/web-export.ts (1)

1-1: Clarify the purpose of main export.

web-export.ts currently exports an empty string. Consider adding a JSDoc comment or populating this export (or renaming the file) to reflect its intended use as the web plugin entry point.

plugins/baseplate-plugin-auth/src/auth0/constants/packages.ts (1)

4-4: Remove unnecessary blank line

There's an extra blank line that creates inconsistent spacing between the package entries.

  auth0: '4.0.2',
  'fastify-auth0-verify': '3.0.0',
-
  '@auth0/auth0-react': '2.3.0',
plugins/baseplate-plugin-auth/src/auth0/core/schema/models.ts (1)

1-34: Consider enhancing the Auth0 user model

The implementation provides a basic user model with UUID, email, and Auth0 ID fields. However, I'd suggest the following improvements:

  1. The email field should have a unique constraint since emails are typically unique identifiers for users
  2. Consider adding common Auth0 profile fields like name and picture
  3. Add documentation explaining how this model integrates with Auth0

Here's a suggested enhancement:

export function createAuth0Models(): {
  user: ModelMergerModelInput;
} {
  return {
    user: {
      model: {
        fields: [
          {
            name: 'id',
            type: 'uuid',
            options: { genUuid: true },
          },
          {
            name: 'email',
            type: 'string',
          },
+         {
+           name: 'name',
+           type: 'string',
+           isOptional: true,
+         },
+         {
+           name: 'picture',
+           type: 'string',
+           isOptional: true,
+         },
          {
            name: 'auth0Id',
            type: 'string',
            isOptional: true,
          },
        ],
        primaryKeyFieldRefs: ['id'],
        uniqueConstraints: [
          {
            fields: [{ fieldRef: 'auth0Id' }],
          },
+         {
+           fields: [{ fieldRef: 'email' }],
+         },
        ],
      },
    },
  };
}
packages/project-builder-lib/src/definition/feature/feature-utils.ts (2)

95-100: Consider handling potential duplicate feature names.

The new getFeatureByName function returns the first feature with a matching name, but doesn't account for potential duplicate feature names in the project definition. Unlike IDs which are unique, names might not be unique across different feature hierarchies.

For consistency with the existing API pattern, consider:

function getFeatureByName(
  projectDefinition: ProjectDefinition,
  name: string,
): FeatureConfig | undefined {
  return projectDefinition.features.find((f) => f.name === name);
}

+function getFeatureByNameOrThrow(
+  projectDefinition: ProjectDefinition,
+  name: string,
+): FeatureConfig {
+  const feature = getFeatureByName(projectDefinition, name);
+  if (!feature) {
+    throw new Error(`Could not find feature with name ${name}`);
+  }
+  return feature;
+}

112-112: Remember to export any additional utility functions.

If you add the suggested getFeatureByNameOrThrow function, don't forget to include it in the exported FeatureUtils object.

plugins/baseplate-plugin-auth/index.html (1)

1-24: Basic HTML template follows best practices

The HTML setup properly configures ES module shims, includes necessary meta tags, and sets up the root element for the React application following standard practices.

Consider using a more specific title than "React Remote", such as "Auth Plugin" or "Authentication Module", to better identify this application in browser tabs.

packages/project-builder-lib/src/definition/model/model-utils.ts (1)

72-75: Minor: broaden model-name validation or document constraints

validateModelName only checks PascalCase. If additional rules (length limits, reserved words, uniqueness) apply elsewhere, consider enforcing them here (or documenting that this util is intentionally minimal).
No code change required if PascalCase is the sole contract.

packages/project-builder-lib/src/definition/project-definition-container.test-helper.ts (1)

34-41: Expose injection points for custom plugin setups

pluginStore and pluginImplementationStore are always created with empty data.
This makes it impossible to write tests that need a pre-loaded plugin catalogue or custom implementations without re-writing the helper.

Consider allowing the caller to pass partial overrides:

-export function createTestProjectDefinitionContainer(
-  input: Partial<ProjectDefinition> = {},
-): ProjectDefinitionContainer {
-  const pluginStore = {
-    availablePlugins: [],
-  };
-  const pluginImplementationStore = new PluginImplementationStore({});
+export function createTestProjectDefinitionContainer(
+  input: Partial<ProjectDefinition> = {},
+  {
+    pluginStore = { availablePlugins: [] },
+    pluginImplementationMap = {},
+  }: {
+    pluginStore?: Parameters<typeof ProjectDefinitionContainer>[1]['pluginStore'];
+    pluginImplementationMap?: ConstructorParameters<typeof PluginImplementationStore>[0];
+  } = {},
+): ProjectDefinitionContainer {
+  const pluginImplementationStore = new PluginImplementationStore(
+    pluginImplementationMap,
+  );

This keeps the current default behaviour but makes the helper far more flexible for future tests.

plugins/baseplate-plugin-storage/src/storage/core/schema/models.ts (1)

66-75: Error message could guide the user

The thrown error only tells what is wrong but not how to fix it. Suggest
adding actionable guidance:

-  throw new Error(
-    'User account model is required for storage plugin. Please enable an auth plugin.',
-  );
+  throw new Error(
+    'Storage plugin requires an auth plugin exposing a user account model. ' +
+      'Add @halfdomelabs/baseplate-plugin-auth (or compatible) before enabling storage.',
+  );
plugins/baseplate-plugin-auth/src/auth0/core/components/auth-definition-editor.tsx (1)

74-83: Variable name misrepresents its meaning

willCreateUserModel is true when the model already exists (isId),
which is the opposite of what the name implies. This can confuse future
maintainers.

-    const willCreateUserModel = modelEntityType.isId(userModelRef);
-    const userModel = willCreateUserModel
+    const isExistingModel = modelEntityType.isId(userModelRef);
+    const userModel = isExistingModel
       ? ModelUtils.byIdOrThrow(definition, userModelRef)
       : createNewModelConfigInput(userModelRef, featureRef);
packages/project-builder-server/src/compiler/web/features.ts (2)

25-33: Detect cyclic feature graphs

compileWebFeatureRecursive assumes an acyclic hierarchy. If a feature mistakenly references an ancestor as a child, this will lead to infinite recursion.

Add a visited set or rely on a depth counter with an upper bound to safeguard against this scenario.


35-42: Handle undefined from getChildrenForFeature

builder.appCompiler.getChildrenForFeature(featureId) may return undefined.
While safeMerge may tolerate this, an explicit fallback makes the intent clearer and protects against future refactors.

-const generatorsForFeature =
-  builder.appCompiler.getChildrenForFeature(featureId);
+const generatorsForFeature =
+  builder.appCompiler.getChildrenForFeature(featureId) ?? {};
packages/project-builder-lib/src/utils/definition-diff/definition-diff.unit.test.ts (1)

124-136: Mismatched field label in DefinitionDiffReplacementField tests

You use 'value' as the field name yet pass whole settings objects.
For clarity—and to mirror the config below—use 'settings'.

-const field = new DefinitionDiffReplacementField<TestSettings>('value');
+const field = new DefinitionDiffReplacementField<TestSettings>('settings');
packages/project-builder-lib/src/schema/definition.test-helper.ts (2)

1-18: Consider deterministic data for test fixtures

faker produces random output which can make snapshot or golden-file tests flaky.
Providing an optional seed or fixed defaults (e.g., "TestFeature") keeps tests deterministic while still allowing overrides.


52-66: Merge order may overwrite provided options defaults

options: { default: '123', ...field.options } places the caller-supplied options after the hard-coded defaults, meaning a user cannot override default. Swap the spread order.

-    options: {
-      default: '123',
-      ...field.options,
-    },
+    options: {
+      ...field.options,
+      default: field.options?.default ?? '123',
+    },
plugins/baseplate-plugin-auth/package.json (2)

37-41: Ambiguous catalog: version specifiers may leak breaking changes

Using the private tag catalog: pins the package to whatever version is in the central catalog at install time.
For public OSS consumers and reproducible CI this can introduce silent breaking upgrades.
Consider publishing an explicit semver range (e.g. "react": "^18.3.0") or flowing the version via workspace protocol ("workspace:^").


70-72: Engines field is overly restrictive

"node": "^22.0.0" prevents installation on Node 20, which is still in LTS and widely used in CI/CD images.
Unless the plugin actually relies on 22-only features (e.g. built-in ^async context), relax to the current active LTSes:

-    "node": "^22.0.0"
+    "node": ">=18.18 <23"
packages/project-builder-server/src/compiler/web/index.ts (1)

66-68: Left-over TODO hints at missing configurability

The hard-coded devBackendHost (http://localhost:${portOffset + 1}) leaks environment assumptions into the compiler.
Given this refactor focuses on modular plugins, exposing this via a CLI flag / env var will make the server compiler more reusable across teams running non-standard port maps.

packages/project-builder-lib/src/web/components/ModelComboboxField.tsx (2)

98-104: Minor: redundant restProps assignment

const restProps = rest; followed by {...restProps} incurs an extra variable without benefit.

-  const restProps = rest;
...
-      {...restProps}
+      {...rest}

63-72: Uncontrolled → controlled transition for searchQuery

searchQuery and onSearchQueryChange are only provided when canCreate is true; otherwise the prop is omitted, making the internal state switch between uncontrolled and controlled modes when canCreate toggles at runtime.

If the parent toggles canCreate dynamically, React will warn about changing a controlled component to uncontrolled.
Safer pattern:

-      searchQuery={canCreate ? searchQuery : undefined}
-      onSearchQueryChange={setSearchQuery}
+      searchQuery={searchQuery}
+      onSearchQueryChange={canCreate ? setSearchQuery : undefined}
packages/project-builder-lib/src/tools/model-merger/model-merger.unit.test.ts (2)

195-213: Diff equality check may become brittle

toEqual against a hard-coded object ignores implementation details such as auto-generated ids, default flags, or additional metadata that might legitimately appear later.

Prefer a partial / property-based assertion:

expect(result?.changes['model.relations']).toEqual(
  expect.arrayContaining([
    expect.objectContaining({ type: 'add', key: 'posts' }),
  ]),
);

This keeps the test focused on observable behaviour rather than internal representation.


318-324: Avoid relying on array index when verifying added elements

Appending to the end is an implementation detail.
Retrieve the element by .find() or use expect.arrayContaining.

plugins/baseplate-plugin-auth/src/auth0/core/schema/plugin-definition.ts (1)

47-65: Minor performance / readability improvement in built-in role merge

Building a Set once avoids re-creating the array for each filter call:

-...roles.filter(
-  (r) => !AUTH_DEFAULT_ROLES.map((v) => v.name).includes(r.name),
-),
+(() => {
+  const builtIn = new Set(AUTH_DEFAULT_ROLES.map((r) => r.name));
+  return roles.filter((r) => !builtIn.has(r.name));
+})(),

Very small gain, but it makes the intent explicit.

packages/project-builder-lib/src/utils/definition-diff/definition-diff.ts (3)

46-53: Redundant assignment of getKey

public readonly getKey is already initialised from the constructor parameter;
the extra this.getKey = getKey; is unnecessary and misleading (the property is
also declared readonly, yet reassigned here).

-    super(name);
-    this.getKey = getKey;
+    super(name);

Removing the line eliminates an avoidable eslint/TypeScript warning.


108-133: update mutates array element in place — cloning recommended

toMerged mutates the existing object reference. If callers retain external
references to elements of currentValue, they will observe silent mutations,
breaking immutability expectations.

Consider cloning before merging:

-items[index] = toMerged(items[index], item);
+items[index] = toMerged(cloneDeep(items[index]), item);

(or return a brand-new array with updated element).


219-236: Deep-clone could be expensive for large objects

cloneDeep on every applyDefinitionDiff may become a hot-spot when diffing
large definitions in tight loops (e.g. interactive editors).
If immutability isn’t a hard requirement, consider a shallow clone or exposing a
flag to skip cloning for performance-critical paths.

packages/project-builder-lib/src/tools/model-merger/model-merger.ts (1)

159-199: Potential quadratic lookup in resolveLocalFieldName.

resolveLocalFieldName does Array.find for every reference/constraint field, resulting in O(N·M) behaviour when a model has many references or constraints.
For most real-world schemas this is negligible, but in code-gen scenarios with hundreds of fields it can become a noticeable hotspot.

A small optimisation keeps correctness while bringing the lookup to O(1):

-  const resolveLocalFieldName = (name: string): string => {
-    const field = inputWithIds.model.fields.find((f) => f.name === name);
-    if (!field) {
-      throw new Error(`Field ${name} not found`);
-    }
-    return field.id;
-  };
+  const fieldNameToId = new Map(
+    inputWithIds.model.fields.map((f) => [f.name, f.id]),
+  );
+  const resolveLocalFieldName = (name: string): string => {
+    const id = fieldNameToId.get(name);
+    if (!id) {
+      throw new Error(`Field ${name} not found`);
+    }
+    return id;
+  };

Not urgent, but worth considering if large models are expected.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Lite
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 066d670 and 393a4dd.

⛔ Files ignored due to path filters (10)
  • plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/generated/ts-import-maps.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/generated/ts-templates.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/generated/ts-templates.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-components/generated/ts-import-maps.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-components/generated/ts-templates.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-hooks/generated/text-templates.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-hooks/generated/ts-import-maps.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-hooks/generated/ts-templates.ts is excluded by !**/generated/**
  • plugins/baseplate-plugin-auth/src/auth0/static/icon.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (103)
  • .changeset/lazy-icons-design.md (1 hunks)
  • package.json (1 hunks)
  • packages/fastify-generators/src/constants/fastify-packages.ts (0 hunks)
  • packages/fastify-generators/src/generators/index.ts (0 hunks)
  • packages/project-builder-common/package.json (1 hunks)
  • packages/project-builder-lib/package.json (2 hunks)
  • packages/project-builder-lib/src/definition/feature/feature-utils.ts (2 hunks)
  • packages/project-builder-lib/src/definition/index.ts (1 hunks)
  • packages/project-builder-lib/src/definition/model/model-utils.ts (3 hunks)
  • packages/project-builder-lib/src/definition/project-definition-container.test-helper.ts (1 hunks)
  • packages/project-builder-lib/src/migrations/index.ts (2 hunks)
  • packages/project-builder-lib/src/migrations/migration-012-migrate-auth-config.ts (1 hunks)
  • packages/project-builder-lib/src/plugins/schema/store.ts (1 hunks)
  • packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1 hunks)
  • packages/project-builder-lib/src/plugins/spec/index.ts (1 hunks)
  • packages/project-builder-lib/src/schema/apps/admin/app.ts (1 hunks)
  • packages/project-builder-lib/src/schema/apps/web/index.ts (1 hunks)
  • packages/project-builder-lib/src/schema/auth/index.ts (1 hunks)
  • packages/project-builder-lib/src/schema/auth/types.ts (0 hunks)
  • packages/project-builder-lib/src/schema/definition.test-helper.ts (1 hunks)
  • packages/project-builder-lib/src/schema/models/graphql.ts (1 hunks)
  • packages/project-builder-lib/src/schema/models/index.ts (1 hunks)
  • packages/project-builder-lib/src/schema/project-definition.ts (0 hunks)
  • packages/project-builder-lib/src/tools/model-merger/model-merger.ts (1 hunks)
  • packages/project-builder-lib/src/tools/model-merger/model-merger.unit.test.ts (1 hunks)
  • packages/project-builder-lib/src/utils/definition-diff/definition-diff.ts (1 hunks)
  • packages/project-builder-lib/src/utils/definition-diff/definition-diff.unit.test.ts (1 hunks)
  • packages/project-builder-lib/src/utils/definition-diff/index.ts (1 hunks)
  • packages/project-builder-lib/src/utils/index.ts (1 hunks)
  • packages/project-builder-lib/src/web/components/ModelComboboxField.tsx (1 hunks)
  • packages/project-builder-lib/src/web/components/ModelMergerResultAlert.tsx (1 hunks)
  • packages/project-builder-lib/src/web/components/index.ts (1 hunks)
  • packages/project-builder-server/src/compiler/admin/index.ts (2 hunks)
  • packages/project-builder-server/src/compiler/admin/sections.ts (2 hunks)
  • packages/project-builder-server/src/compiler/backend/fastify.ts (0 hunks)
  • packages/project-builder-server/src/compiler/backend/feature.ts (1 hunks)
  • packages/project-builder-server/src/compiler/backend/graphql.ts (3 hunks)
  • packages/project-builder-server/src/compiler/lib/web-auth.ts (0 hunks)
  • packages/project-builder-server/src/compiler/web/features.ts (1 hunks)
  • packages/project-builder-server/src/compiler/web/index.ts (2 hunks)
  • packages/project-builder-web/src/app/AppLayout/AppDesktopSidebar.tsx (1 hunks)
  • packages/project-builder-web/src/app/AppLayout/AppMobileSidebar.tsx (1 hunks)
  • packages/project-builder-web/src/pages/_routes.tsx (0 hunks)
  • packages/project-builder-web/src/pages/apps/edit/WebAppForm.tsx (3 hunks)
  • packages/project-builder-web/src/pages/apps/edit/admin/AdminGeneralForm.tsx (2 hunks)
  • packages/project-builder-web/src/pages/data/models/edit/[id]/_components/graphql/GraphQLMutationsSection.tsx (5 hunks)
  • packages/project-builder-web/src/pages/data/models/edit/[id]/_components/graphql/GraphQLQueriesSection.tsx (4 hunks)
  • packages/project-builder-web/src/pages/features/FeaturesHome.page.tsx (0 hunks)
  • packages/project-builder-web/src/pages/features/FeaturesLayout.tsx (0 hunks)
  • packages/project-builder-web/src/pages/features/auth/auth-models.ts (0 hunks)
  • packages/project-builder-web/src/pages/features/auth/index.tsx (0 hunks)
  • packages/project-builder-web/src/pages/features/index.tsx (0 hunks)
  • packages/project-builder-web/src/pages/home/home.page.tsx (1 hunks)
  • packages/project-builder-web/src/pages/plugins/PluginCard.tsx (1 hunks)
  • packages/project-builder-web/src/pages/plugins/home.page.tsx (1 hunks)
  • packages/project-builder-web/src/pages/plugins/plugin-config.page.tsx (2 hunks)
  • packages/react-generators/src/constants/react-packages.ts (0 hunks)
  • packages/react-generators/src/generators/core/react-routes/react-routes.generator.ts (1 hunks)
  • packages/react-generators/src/generators/index.ts (0 hunks)
  • packages/react-generators/src/index.ts (1 hunks)
  • packages/react-generators/src/utils/index.ts (1 hunks)
  • plugins/baseplate-plugin-auth/.gitignore (1 hunks)
  • plugins/baseplate-plugin-auth/LICENSE (1 hunks)
  • plugins/baseplate-plugin-auth/eslint.config.js (1 hunks)
  • plugins/baseplate-plugin-auth/index.html (1 hunks)
  • plugins/baseplate-plugin-auth/manifest.json (1 hunks)
  • plugins/baseplate-plugin-auth/package.json (1 hunks)
  • plugins/baseplate-plugin-auth/postcss.config.js (1 hunks)
  • plugins/baseplate-plugin-auth/prettier.config.js (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/constants/packages.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/common.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/components/auth-definition-editor.tsx (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/components/role-editor-form.tsx (2 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/node.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/schema/models.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/schema/plugin-definition.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/core/web.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/auth0-module.generator.ts (3 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/ts-extractor.json (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/index.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-apollo/auth0-apollo.generator.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/auth0-callback.generator.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/templates/auth0-callback.page.tsx (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/templates/signup.page.tsx (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-components/auth0-components.generator.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-hooks/auth0-hooks.generator.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/generators/react/react-auth0/react-auth0.generator.ts (2 hunks)
  • plugins/baseplate-plugin-auth/src/auth0/metadata.json (1 hunks)
  • plugins/baseplate-plugin-auth/src/index.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/styles.css (1 hunks)
  • plugins/baseplate-plugin-auth/src/utils/cn.ts (1 hunks)
  • plugins/baseplate-plugin-auth/src/web-export.ts (1 hunks)
  • plugins/baseplate-plugin-auth/tsconfig.build.json (1 hunks)
  • plugins/baseplate-plugin-auth/tsconfig.json (1 hunks)
  • plugins/baseplate-plugin-auth/tsconfig.node.json (1 hunks)
  • plugins/baseplate-plugin-auth/vite.config.ts (1 hunks)
  • plugins/baseplate-plugin-auth/vitest.config.ts (1 hunks)
  • plugins/baseplate-plugin-storage/package.json (1 hunks)
  • plugins/baseplate-plugin-storage/src/storage/core/components/CategoryEditorForm.tsx (3 hunks)
  • plugins/baseplate-plugin-storage/src/storage/core/components/storage-config.tsx (3 hunks)
  • plugins/baseplate-plugin-storage/src/storage/core/schema/models.ts (2 hunks)
  • plugins/baseplate-plugin-storage/src/storage/core/schema/plugin-definition.ts (1 hunks)
  • plugins/baseplate-plugin-storage/src/storage/core/web.ts (1 hunks)
💤 Files with no reviewable changes (14)
  • packages/react-generators/src/generators/index.ts
  • packages/fastify-generators/src/generators/index.ts
  • packages/react-generators/src/constants/react-packages.ts
  • packages/project-builder-lib/src/schema/auth/types.ts
  • packages/project-builder-web/src/pages/_routes.tsx
  • packages/project-builder-lib/src/schema/project-definition.ts
  • packages/fastify-generators/src/constants/fastify-packages.ts
  • packages/project-builder-server/src/compiler/backend/fastify.ts
  • packages/project-builder-web/src/pages/features/index.tsx
  • packages/project-builder-web/src/pages/features/FeaturesHome.page.tsx
  • packages/project-builder-web/src/pages/features/FeaturesLayout.tsx
  • packages/project-builder-web/src/pages/features/auth/index.tsx
  • packages/project-builder-web/src/pages/features/auth/auth-models.ts
  • packages/project-builder-server/src/compiler/lib/web-auth.ts
🧰 Additional context used
🧬 Code Graph Analysis (25)
packages/project-builder-lib/src/migrations/index.ts (1)
packages/project-builder-lib/src/migrations/migration-012-migrate-auth-config.ts (1)
  • migration012MigrateAuthConfig (38-90)
packages/project-builder-web/src/pages/plugins/home.page.tsx (1)
packages/project-builder-web/src/pages/plugins/PluginCard.tsx (1)
  • PluginCard (31-163)
packages/project-builder-web/src/pages/plugins/PluginCard.tsx (1)
packages/project-builder-lib/src/schema/plugins/index.ts (1)
  • pluginEntityType (7-7)
packages/project-builder-web/src/pages/home/home.page.tsx (2)
packages/ui-components/src/components/Card/Card.tsx (5)
  • CardTitle (117-117)
  • CardDescription (114-114)
  • CardHeader (116-116)
  • CardFooter (115-115)
  • Card (111-111)
packages/ui-components/src/components/Button/Button.tsx (1)
  • Button (51-51)
plugins/baseplate-plugin-auth/src/auth0/generators/react/react-auth0/react-auth0.generator.ts (2)
packages/core-generators/src/utils/extract-packages.ts (1)
  • extractPackageVersions (7-14)
plugins/baseplate-plugin-auth/src/auth0/constants/packages.ts (1)
  • AUTH0_PACKAGES (1-6)
packages/project-builder-web/src/pages/plugins/plugin-config.page.tsx (1)
packages/project-builder-lib/src/schema/plugins/index.ts (1)
  • pluginEntityType (7-7)
packages/project-builder-lib/src/definition/feature/feature-utils.ts (1)
packages/project-builder-lib/src/schema/project-definition.ts (1)
  • ProjectDefinition (61-61)
packages/project-builder-web/src/pages/apps/edit/WebAppForm.tsx (2)
packages/project-builder-lib/src/web/hooks/useProjectDefinition.ts (1)
  • useProjectDefinition (75-83)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
packages/project-builder-web/src/pages/apps/edit/admin/AdminGeneralForm.tsx (1)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
plugins/baseplate-plugin-storage/src/storage/core/components/CategoryEditorForm.tsx (2)
packages/project-builder-lib/src/web/hooks/useProjectDefinition.ts (1)
  • useProjectDefinition (75-83)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
packages/project-builder-server/src/compiler/backend/graphql.ts (1)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/auth0-module.generator.ts (2)
packages/core-generators/src/utils/extract-packages.ts (1)
  • extractPackageVersions (7-14)
plugins/baseplate-plugin-auth/src/auth0/constants/packages.ts (1)
  • AUTH0_PACKAGES (1-6)
packages/project-builder-lib/src/migrations/migration-012-migrate-auth-config.ts (1)
packages/project-builder-lib/src/migrations/types.ts (1)
  • createSchemaMigration (30-34)
packages/project-builder-lib/src/definition/model/model-utils.ts (1)
packages/utils/src/validators/case-validators.ts (1)
  • PASCAL_CASE_REGEX (11-11)
packages/project-builder-web/src/pages/data/models/edit/[id]/_components/graphql/GraphQLQueriesSection.tsx (2)
packages/project-builder-lib/src/web/hooks/useProjectDefinition.ts (1)
  • useProjectDefinition (75-83)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
plugins/baseplate-plugin-auth/src/auth0/core/common.ts (3)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
plugins/baseplate-plugin-auth/src/auth0/core/schema/plugin-definition.ts (2)
  • auth0PluginDefinitionSchema (37-66)
  • Auth0PluginDefinition (68-68)
packages/project-builder-lib/src/definition/plugins/plugin-utils.ts (1)
  • PluginUtils (63-68)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (2)
packages/project-builder-lib/src/schema/project-definition.ts (1)
  • ProjectDefinition (61-61)
packages/project-builder-lib/src/schema/auth/index.ts (1)
  • AuthRole (5-10)
plugins/baseplate-plugin-auth/vite.config.ts (1)
packages/project-builder-lib/src/plugin-tools/plugin-loader.ts (2)
  • getModuleFederationTargets (270-312)
  • rewriteDistToSrc (258-260)
plugins/baseplate-plugin-storage/src/storage/core/components/storage-config.tsx (3)
plugins/baseplate-plugin-storage/src/storage/core/schema/models.ts (1)
  • createStorageModels (63-94)
packages/project-builder-lib/src/tools/model-merger/model-merger.ts (3)
  • createNewModelConfigInput (202-215)
  • createModelMergerResult (239-270)
  • applyModelMergerResultInPlace (321-347)
packages/project-builder-lib/src/web/components/ModelMergerResultAlert.tsx (1)
  • ModelMergerResultAlert (14-93)
packages/project-builder-lib/src/web/components/ModelMergerResultAlert.tsx (2)
packages/project-builder-lib/src/tools/model-merger/model-merger.ts (1)
  • PendingModelChange (217-222)
packages/ui-components/src/components/Alert/Alert.tsx (3)
  • Alert (77-77)
  • AlertTitle (77-77)
  • AlertDescription (77-77)
plugins/baseplate-plugin-auth/src/auth0/core/components/role-editor-form.tsx (2)
plugins/baseplate-plugin-auth/src/auth0/core/schema/plugin-definition.ts (1)
  • Auth0PluginDefinitionInput (70-72)
plugins/baseplate-plugin-auth/src/utils/cn.ts (1)
  • cn (4-13)
plugins/baseplate-plugin-storage/src/storage/core/schema/models.ts (2)
packages/project-builder-lib/src/tools/model-merger/model-merger.ts (2)
  • ModelMergerScalarFieldInput (30-33)
  • ModelMergerModelInput (58-67)
packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)
  • authConfigSpec (22-25)
packages/project-builder-lib/src/schema/auth/index.ts (1)
packages/project-builder-lib/src/references/types.ts (1)
  • createEntityType (139-151)
packages/project-builder-lib/src/utils/definition-diff/definition-diff.unit.test.ts (1)
packages/project-builder-lib/src/utils/definition-diff/definition-diff.ts (8)
  • DefinitionDiffKeyedArrayField (43-136)
  • diff (55-98)
  • diff (144-149)
  • DefinitionDiffOperation (10-14)
  • DefinitionDiffReplacementField (141-155)
  • createDefinitionDiffConfig (169-173)
  • createDefinitionDiff (182-206)
  • applyDefinitionDiff (211-237)
plugins/baseplate-plugin-auth/src/auth0/core/schema/models.ts (1)
packages/project-builder-lib/src/tools/model-merger/model-merger.ts (1)
  • ModelMergerModelInput (58-67)
🔇 Additional comments (103)
plugins/baseplate-plugin-auth/tsconfig.node.json (1)

1-4: Correct extension of base Node scripts config
The new tsconfig.node.json appropriately extends the shared Node script config and explicitly includes only the build scripts (vite.config.ts, tailwind.config.ts). This keeps the plugin aligned with the monorepo’s TypeScript standards.

plugins/baseplate-plugin-storage/package.json (1)

4-4: Fix grammatical typo in package description
The description has been corrected to “Contains the storage plugin for Baseplate,” which improves clarity. No functional changes detected.

plugins/baseplate-plugin-auth/vitest.config.ts (1)

1-1: Proxy Vitest configuration correctly
Re-exporting the default config from @halfdomelabs/tools/vitest-node ensures consistency with other packages. No issues found.

plugins/baseplate-plugin-auth/prettier.config.js (1)

1-1: Reuse shared Prettier configuration
Exporting the React prettier config from @halfdomelabs/tools/prettier-react maintains formatting consistency across the codebase.

package.json (1)

39-39: Increase concurrency for watch tasks
Adding --concurrency 20 to the turbo watch command will speed up parallel execution of watch tasks. Ensure that your local and CI environments have sufficient resources to handle the increased parallelism.

plugins/baseplate-plugin-auth/.gitignore (1)

1-99: Comprehensive .gitignore for the new plugin. This .gitignore appropriately covers common Node, framework, and tooling artifacts, ensuring transient and build files are excluded from version control.

packages/project-builder-lib/src/schema/models/graphql.ts (1)

5-5: Import path updated to new auth index. This aligns with the refactored auth module exporting authRoleEntityType from index.js. Please confirm that the path resolves correctly in the built artifacts.

packages/project-builder-lib/src/schema/apps/web/index.ts (1)

4-4: Update import path for authRoleEntityType. Changed to import from @src/schema/auth/index.js following module refactor. Implementation looks correct and consistent.

packages/project-builder-lib/src/schema/apps/admin/app.ts (1)

4-4: Sync import path for authRoleEntityType. Updated to reflect the consolidated auth schema in index.js. This keeps consistency across schema files.

plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/templates/signup.page.tsx (1)

35-35: Styling Adjustment Approved
The removal of bg-gray-100 aligns the signup page's background with the callback page, unifying styles across Auth0 flows.

plugins/baseplate-plugin-storage/src/storage/core/web.ts (1)

6-6:

Details

✅ Verification successful

Verify Path-Cased Import
Double-check that the file storage-config matches the new import path exactly (including kebab-case) on case-sensitive file systems.

Run:


🏁 Script executed:

#!/bin/bash
# Locate the component file to confirm correct path and casing
fd -e ts --exec echo {} | grep -i 'storage-config'

Length of output: 52


🏁 Script executed:

#!/bin/bash
# List all files in the components directory to inspect exact names and casing
find plugins/baseplate-plugin-storage/src/storage/core/components -maxdepth 1 -type f -print

# Look for any TypeScript files with “storage-config” in their name
fd --case-sensitive -e ts -e tsx 'storage-config'

# Also check for camelCase variant just in case
fd --case-sensitive -e ts -e tsx 'storageConfig'

Length of output: 520


Import Path Verified
The file plugins/baseplate-plugin-storage/src/storage/core/components/storage-config.tsx exists and matches the kebab-case import in plugins/baseplate-plugin-storage/src/storage/core/web.ts (line 6). No changes required.

packages/project-builder-web/src/app/AppLayout/AppMobileSidebar.tsx (2)

5-5: Removed Unused Icon Import
Deleting HiCollection aligns with the removal of the "Features" section and cleans up unused dependencies.


42-48:

Details

✅ Verification successful

Removed "Features" Navigation Item
The "Features" link was removed to reflect deleted routes. Ensure that no remaining references (routes, tests, documentation) to /features exist.

Run:


🏁 Script executed:

#!/bin/bash
# Search for residual '/features' references
rg "/features" -n

Length of output: 1169


🏁 Script executed:

#!/bin/bash
# Verify there are no remaining navigation links to "/features" in the web app
rg 'to="/features"' -n packages/project-builder-web

Length of output: 53


🏁 Script executed:

#!/bin/bash
# Check for any remaining navigation or route references to "/features" in the web app
rg -nE '(to|path)=["'\'']/features' packages/project-builder-web

Length of output: 127


🏁 Script executed:

#!/bin/bash
# Search for any "/features" references in the web app source (TSX/JSX)
rg "/features" -n packages/project-builder-web -g '*.tsx' -g '*.jsx'

Length of output: 68


Removed "Features" Navigation Item – Verified

File: packages/project-builder-web/src/app/AppLayout/AppMobileSidebar.tsx
Lines: 42–48

        <SidebarNavigationIcon to="/" icon={MdHome} label="Home" end />
        <SidebarNavigationIcon to="/apps" icon={MdApps} label="Apps" />
        <SidebarNavigationIcon
          to="/data/models"
          icon={HiDatabase}
          label="Models"
        />

No remaining /features references found in the web app’s TSX/JSX files. Other /features hits in server and lib are internal module imports, not UI routes.

packages/project-builder-lib/src/utils/definition-diff/index.ts (1)

1-1:

Details

❌ Incorrect review comment

Ensure TypeScript Resolution of .js Modules
Importing from definition-diff.js requires that tsconfig.json has allowJs enabled and proper module resolution for .js extensions. Verify the TS config or consider renaming the source file to .ts.

Run:


---

🏁 Script executed:

```shell
#!/bin/bash
# Check TS config for allowJs and module resolution
grep '"allowJs"' -n tsconfig.json
grep '"moduleResolution"' -n tsconfig.json

Length of output: 80


🏁 Script executed:

#!/bin/bash
# Locate all tsconfig files in the repo
find . -type f -name "tsconfig*.json"
# Search for allowJs and moduleResolution settings within them
rg '"allowJs"' --glob 'tsconfig*.json'
rg '"moduleResolution"' --glob 'tsconfig*.json'

Length of output: 2041


🏁 Script executed:

#!/bin/bash
# Check if project-builder-lib tsconfig extends a base config with allowJs
echo "Extends in tsconfig.json:"
grep -n '"extends"' packages/project-builder-lib/tsconfig.json || true
echo

echo "Extends in tsconfig.build.json:"
grep -n '"extends"' packages/project-builder-lib/tsconfig.build.json || true
echo

echo "Contents of packages/project-builder-lib/tsconfig.json:"
sed -n '1,200p' packages/project-builder-lib/tsconfig.json
echo

echo "Contents of packages/project-builder-lib/tsconfig.build.json:"
sed -n '1,200p' packages/project-builder-lib/tsconfig.build.json

Length of output: 1214


🏁 Script executed:

#!/bin/bash
# Show root tsconfig.json content
sed -n '1,200p' tsconfig.json

Length of output: 169


🏁 Script executed:

#!/bin/bash
# Check allowJs and moduleResolution in Vite lib base config
echo "Searching for allowJs in packages/tools/tsconfig.vite.lib.json:"
grep -n '"allowJs"' packages/tools/tsconfig.vite.lib.json || echo "allowJs not found"

echo -e "\nSearching for moduleResolution in packages/tools/tsconfig.vite.lib.json:"
grep -n '"moduleResolution"' packages/tools/tsconfig.vite.lib.json || echo "moduleResolution not found"

echo -e "\nPreview of packages/tools/tsconfig.vite.lib.json:"
sed -n '1,200p' packages/tools/tsconfig.vite.lib.json

Length of output: 1020


🏁 Script executed:

#!/bin/bash
# List files in the definition-diff directory
echo "Files in packages/project-builder-lib/src/utils/definition-diff:"
find packages/project-builder-lib/src/utils/definition-diff -maxdepth 1 -type f -print

Length of output: 449


No TS config change needed for .js import
The index.ts export uses a .js specifier so that at runtime the compiled .js file is imported, and because this package’s tsconfig.json explicitly sets

"moduleResolution": "node16"

(and TS 4.7+ is required for that option), TypeScript’s Node-style ESM resolution will automatically map the .js import to your definition-diff.ts source without needing allowJs.

• Location: packages/project-builder-lib/tsconfig.json
– Extends @halfdomelabs/tools/tsconfig.vite.lib.json
– Defines "moduleResolution": "node16"
• No allowJs flag is necessary here, and you should keep the .js extension for correct ESM output.

Likely an incorrect or invalid review comment.

packages/project-builder-lib/package.json (2)

54-54: Add Faker as a devDependency
Adds @faker-js/faker to support new randomized test data in unit tests. Ensure that new test helpers import and configure Faker correctly.


63-63: Upgrade type-fest to v4.41.0
Bumps type-fest for updated type utilities. Verify compatibility with existing TypeScript code and regenerate any affected type artifacts.

packages/project-builder-common/package.json (1)

28-28: Introduce the Auth plugin as a workspace dependency
Adds @halfdomelabs/baseplate-plugin-auth to enable plugin-based authentication in common utilities.

plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-apollo/auth0-apollo.generator.ts (1)

6-6: Switch to absolute import for React Apollo config provider
Updates the import of reactApolloConfigProvider to use the consolidated @halfdomelabs/react-generators package. Confirm that this export exists and is version-compatible.

plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/templates/auth0-callback.page.tsx (1)

48-48: Remove gray background utility class
Eliminates bg-gray-100 to align with updated UI styling guidelines. Verify the callback page layout and contrast remains acceptable in all themes.

packages/react-generators/src/index.ts (1)

4-4: Expose utilities via package exports
Adds export * from './utils/index.js' to make shared utilities available in the public API. Ensure downstream consumers import these utilities as expected and update type definitions if needed.

packages/project-builder-lib/src/utils/index.ts (1)

3-3: Clean addition of definition-diff utilities to the public API

This export makes the new definition diffing and patching utilities available through the utils package, providing access to JSON object diffing and patching capabilities based on configurable field definitions. Good modular approach.

packages/project-builder-lib/src/plugins/spec/index.ts (1)

1-1: Well-structured auth config spec exposure

Adding this export is a key enabler for the authentication modularization effort, exposing the interface and contract needed for authentication configuration plugins. This change directly supports the PR's goal of migrating Auth0 to a separate plugin architecture.

packages/react-generators/src/generators/core/react-routes/react-routes.generator.ts (1)

75-78: Good defensive programming with guard clause

Adding this early return guard clause prevents unnecessary processing when there are no routes registered, which could happen now that Auth0 routes are being moved to a separate plugin. This is a clean optimization that avoids potential issues when working with empty route collections.

plugins/baseplate-plugin-auth/manifest.json (1)

1-4: Well-structured plugin manifest

This manifest correctly configures the new Auth0 plugin with appropriate plugin entry points and web build output locations. The structure is clean and follows expected plugin architecture patterns. This is a key component enabling the modularization of Auth0 functionality.

plugins/baseplate-plugin-auth/src/auth0/generators/index.ts (1)

1-2: Consolidated Auth0 generator exports
The two exports correctly expose both the Fastify and React generator modules as the unified entry point for the Auth plugin.

plugins/baseplate-plugin-auth/tsconfig.build.json (1)

1-12: Enable emission and exclude tests/templates
This build configuration properly extends the base tsconfig, turns on output emission, and excludes test files, mocks, and generator templates from the published output.

packages/project-builder-lib/src/web/components/index.ts (1)

1-3: Export new web components
The addition of ModelComboboxField and ModelMergerResultAlert alongside FeatureComboboxField aligns with the new model merging UI features.

packages/project-builder-lib/src/definition/index.ts (1)

9-9: Re-export project-definition-container test helper
Exposing project-definition-container.test-helper.js in the public API simplifies test setup for project definitions.

packages/project-builder-lib/src/schema/models/index.ts (1)

196-198: Add input type for unique constraints
Introducing ModelUniqueConstraintConfigInput brings parity with other z.input<…> types and enhances type safety for unique-constraint inputs.

plugins/baseplate-plugin-auth/src/styles.css (1)

1-6: CSS layering structure looks good

The CSS layer declaration and imports are well-organized, establishing a proper cascade with theme, base, components, and utilities layers. The file correctly imports Tailwind CSS assets and the UI components theme.

packages/project-builder-lib/src/migrations/index.ts (2)

11-11: Appropriate import for the new migration

The import statement for the new migration is correctly added.


20-20: Schema migration sequence properly extended

The migration012MigrateAuthConfig is correctly added to the SCHEMA_MIGRATIONS array, ensuring that existing projects will have their Auth0 configuration migrated to the new plugin-based system.

plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-components/auth0-components.generator.ts (1)

5-12: Imports organization improved

The reorganization of imports is cleaner and more maintainable. Moving authComponentsImportsProvider to be grouped with other imports from @halfdomelabs/react-generators makes the code structure more consistent.

plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-hooks/auth0-hooks.generator.ts (1)

5-10: Imports correctly consolidated from external package

The imports have been properly reorganized to source all React generator providers from the @halfdomelabs/react-generators package instead of local paths, which aligns with the plugin modularization approach.

plugins/baseplate-plugin-storage/src/storage/core/schema/plugin-definition.ts (1)

57-57: Important behavior change for role references

Changing the onDelete behavior from 'RESTRICT' to 'DELETE' is a significant change. This allows roles to be deleted even when referenced by storage categories, with the reference being automatically removed.

This change is necessary for the new plugin-based architecture where roles are managed by the Auth0 plugin, but make sure this cascading deletion behavior is documented for users.

plugins/baseplate-plugin-auth/src/auth0/constants/packages.ts (1)

1-6: Good centralization of Auth0 package versions

This new constant serves as a central place for Auth0 package versions, which is a good practice for version management in this new auth plugin. The mapping of package names to versions is clear and well-typed with as const.

packages/project-builder-web/src/pages/plugins/home.page.tsx (2)

82-84: Bug fix: Now correctly mapping over installed plugins

Good change. The code now correctly maps over installedPlugins instead of the unfiltered plugins array, ensuring only active plugins appear in the "Active Plugins" section.


90-92: Bug fix: Now correctly mapping over uninstalled plugins

Good change. The code now correctly maps over uninstalledPlugins instead of the unfiltered plugins array, ensuring only available but not yet active plugins appear in the "Available Plugins" section.

packages/project-builder-lib/src/plugins/schema/store.ts (1)

20-24: Good addition of a non-throwing plugin spec getter

Adding getPluginSpecOptional method is a good practice for safely retrieving plugin implementations without throwing errors. This supports the plugin architecture by allowing components to gracefully handle optional plugins.

packages/project-builder-web/src/pages/apps/edit/admin/AdminGeneralForm.tsx (2)

6-6: Add import for new auth config spec

Good addition of the new import to support the auth plugin architecture.


56-62: Refactor to use the plugin system for auth roles

Good change. The code now retrieves auth roles through the plugin system instead of directly accessing definition.auth?.roles. This is consistent with the architectural shift to modularize authentication as a plugin.

packages/project-builder-web/src/pages/plugins/PluginCard.tsx (1)

82-93: LGTM: Plugin disabling logic updated for consistency

The updated filter condition correctly uses the plugin's ID with pluginEntityType.fromUid() for identification, which aligns with how plugins are enabled in the enablePlugin function (line 68).

plugins/baseplate-plugin-auth/src/auth0/generators/react/react-auth0/react-auth0.generator.ts (2)

7-11: LGTM: Updated imports for modular Auth0 plugin

The changes correctly update the imports to use the external @halfdomelabs/react-generators package and the Auth0-specific package constants. This aligns with the modularization of Auth0 functionality into a separate plugin.

Also applies to: 19-19


30-32: LGTM: Updated package extraction for Auth0

The change from using REACT_PACKAGES to AUTH0_PACKAGES is appropriate for this Auth0-specific generator, ensuring it uses the correct versions defined in the Auth0 constants.

.changeset/lazy-icons-design.md (1)

1-11: Clear, concise changeset documentation for version updates.

The changeset correctly documents patch version updates for all seven packages involved in the auth0 refactoring, with a clear and descriptive commit message.

packages/project-builder-server/src/compiler/backend/graphql.ts (3)

18-18: Good import addition for the auth plugin integration.

The import for authConfigSpec is necessary for the plugin-based authentication system.


79-84: Clean migration to plugin-based auth system.

This code properly replaces the direct check for auth property with the new plugin-based approach, aligning with the refactoring goal of extracting Auth0 authentication into a separate plugin.


143-148: Consistent implementation of auth plugin integration.

The changes here mirror those made in the buildQueriesFileForModel function, ensuring consistent plugin-based authentication handling throughout the file.

packages/project-builder-web/src/pages/plugins/plugin-config.page.tsx (2)

3-7: Good addition of pluginEntityType import.

The updated imports properly include pluginEntityType which is necessary for the plugin identity comparison.


84-84: Enhanced plugin disabling logic.

The modification to use pluginEntityType.fromUid(metadata.id) for plugin identity comparison aligns with the standardized plugin entity type system, providing more robust plugin ID handling.

plugins/baseplate-plugin-auth/src/auth0/core/web.ts (2)

1-9: Good module structure with appropriate imports.

The imports correctly bring in the necessary dependencies for creating a web platform plugin, including the AuthDefinitionEditor component and global styles.


10-19: Well-structured plugin export with proper component registration.

The plugin export correctly:

  1. Declares dependency on the web configuration specification
  2. Registers the AuthDefinitionEditor component during initialization
  3. Uses the pluginId parameter to ensure proper component registration

This implementation integrates smoothly with the web configuration system.

plugins/baseplate-plugin-auth/tsconfig.json (1)

1-15: TypeScript configuration looks correct for the new auth plugin.

The configuration correctly extends the base Vite library config, sets up path aliases for @src/*, and includes appropriate include/exclude patterns for the plugin's source files.

packages/project-builder-web/src/pages/home/home.page.tsx (2)

28-37: Navigation card update aligns with architecture changes.

The renaming from "Features" to "Models" and updating the navigation path reflects the architectural changes in this PR, focusing on models as a core concept.


42-51: Card redesign enhances plugin-based architecture visibility.

The renaming from "Models" to "Plugins" and updating the description appropriately highlights the new plugin-based architecture, which aligns with the Auth0 plugin extraction in this PR.

plugins/baseplate-plugin-auth/src/auth0/generators/react/auth0-callback/auth0-callback.generator.ts (1)

2-8: Import consolidation improves code organization.

Consolidating the individual imports from local paths into a grouped import from the shared @halfdomelabs/react-generators package improves maintainability and reflects the modularization of Auth0 functionality into its own plugin.

plugins/baseplate-plugin-storage/src/storage/core/components/CategoryEditorForm.tsx (1)

3-3: Good modularization of auth role access

The change properly implements plugin-based authentication role retrieval instead of directly accessing definition.auth?.roles. This improves the modularity of the system by decoupling the storage plugin from direct knowledge of the auth schema structure.

Also applies to: 28-28, 49-55

packages/project-builder-server/src/compiler/admin/sections.ts (1)

71-73: Excellent enhancement for plugin extensibility

This change significantly improves the extensibility of admin features by allowing plugins to dynamically register their UI components. The architecture now supports the addition of new features through plugins without requiring modifications to the core compiler code.

Also applies to: 82-82

plugins/baseplate-plugin-auth/src/utils/cn.ts (1)

1-14: Good practice for CSS isolation in module federation

The cn utility function properly implements CSS class name prefixing with "auth-", which is essential for style isolation in a module federation architecture. The implementation correctly handles multiple class names, filters falsy values, and maintains proper spacing.

packages/project-builder-web/src/pages/apps/edit/WebAppForm.tsx (3)

4-7: LGTM: Updated imports to support plugin-based auth configuration

The addition of authConfigSpec import aligns with the migration to a separate auth plugin.


37-37: LGTM: Enhanced hook usage to access plugin container

Correctly destructuring pluginContainer alongside definition to access plugin-specific functionality.


49-55: LGTM: Migrated role retrieval to plugin-based approach

The code now properly retrieves auth roles through the plugin system instead of directly accessing definition.auth?.roles, which aligns with the modular architecture being implemented.

plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/auth0-module.generator.ts (4)

9-20: LGTM: Improved import organization

Consolidating multiple imports from @halfdomelabs/fastify-generators improves code readability and maintainability.


28-28: LGTM: Updated package constant imports

Using the Auth0-specific package constants aligns with the plugin architecture and ensures proper versioning.


45-45: LGTM: Updated package version extraction

Using AUTH0_PACKAGES instead of FASTIFY_PACKAGES correctly aligns with the migration of Auth0 functionality to a dedicated plugin.


153-153: LGTM: Consistent usage of Auth0 package constants

The use of AUTH0_PACKAGES for the Fastify Auth0 verify package is consistent with the earlier usage.

plugins/baseplate-plugin-auth/src/auth0/core/components/role-editor-form.tsx (3)

11-14: LGTM: Updated imports for plugin-specific utilities and types

The import of the plugin-specific cn utility and Auth0PluginDefinitionInput type aligns with the migration to a plugin-based architecture.


17-17: LGTM: Updated control type for plugin-specific form

The control prop type has been correctly updated from Control<AuthConfigInput> to Control<Auth0PluginDefinitionInput> to match the new plugin-specific schema.


31-31: LGTM: Updated class name utility usage

Replacing clsx with the plugin-specific cn utility ensures consistent styling within the Auth0 plugin context with proper prefixing.

Also applies to: 34-34

packages/project-builder-web/src/pages/data/models/edit/[id]/_components/graphql/GraphQLMutationsSection.tsx (4)

4-7: LGTM: Updated imports to support plugin-based auth configuration

Grouping authConfigSpec with ModelConfigInput improves code organization.


34-34: LGTM: Enhanced hook usage to access plugin container

Correctly destructuring pluginContainer alongside definition to support the plugin-based architecture.


36-42: LGTM: Migrated role retrieval to plugin-based approach

The code now properly retrieves auth roles through the plugin system, using getPluginSpecOptional(authConfigSpec)?.getAuthRoles(definition) instead of directly accessing definition.auth?.roles.


110-110: LGTM: Updated conditional rendering for role-based permissions

The code now checks if roleOptions is truthy before rendering role-based mutation permissions, which is more robust than relying on a derived boolean.

Also applies to: 128-128, 146-146

packages/project-builder-server/src/compiler/backend/feature.ts (1)

3-5: Auth-specific imports removed – looks correct

Auth concerns have been delegated to the new plugin system, so dropping the old imports aligns with the PR objective. No issues spotted here.

packages/project-builder-server/src/compiler/admin/index.ts (1)

31-31: Smooth integration of auth0 plugin with React router

The implementation of safeMerge to integrate root children (from auth0 plugin) with the base admin routes is a clean approach. This pattern properly supports the plugin-based architecture by allowing the auth plugin to inject its routes without directly modifying the admin compiler.

Also applies to: 70-91

packages/project-builder-lib/src/plugins/spec/auth-config-spec.ts (1)

1-26: Well-structured plugin specification for authentication

This spec defines a clean interface for accessing authentication configuration that abstracts the underlying implementation details. The plugin architecture separates concerns appropriately, with clear function types for accessing user account models and auth roles.

The design allows for future authentication providers beyond Auth0 by establishing a standard interface that implementations must conform to.

plugins/baseplate-plugin-auth/LICENSE (1)

1-30: Standard proprietary license for the plugin

The license appropriately establishes the legal framework for the newly extracted authentication plugin, defining terms of use, ownership, and liability limitations.

plugins/baseplate-plugin-auth/src/auth0/core/common.ts (1)

1-40: Clean implementation of Auth0 plugin with proper integration

The implementation correctly fulfills the authConfigSpec interface by providing methods to access user account models and authentication roles from the plugin configuration.

A few observations:

  1. Good dependency declaration with pluginConfigSpec
  2. Proper type casting when retrieving the plugin configuration
  3. Clear separation of concerns with the plugin initialization and exports
plugins/baseplate-plugin-storage/src/storage/core/components/storage-config.tsx (8)

5-7: Enhanced imports for structured model merging

These imports reflect the shift from a raw diff approach to a more structured model merger mechanism. The new imports provide better type safety and encapsulation for handling model changes.


13-14: New ModelMergerResultAlert component adoption

Good replacement of custom alert logic with a dedicated reusable component for displaying model changes, which improves consistency across the UI.


18-18: UI components import consolidation

The import was consolidated to include ComboboxFieldController alongside Button, improving import organization.


46-46: Added feature reference tracking

The addition of featureRef watching is necessary to properly handle model creation with the correct feature reference.


48-63: Refactored model change detection logic

The implementation now uses a more structured approach with createModelMergerResult to generate model changes, improving type safety and readability compared to the previous approach. The dependency array has been properly updated to include featureRef.


68-77: Updated model application logic

The implementation now uses applyModelMergerResultInPlace to handle model changes in a more structured way, including proper handling of new models by updating the fileModelRef reference when necessary.


84-84: Fixed typo in success message

Fixed the typo in the success message: 'Successfully enabled storage plugin!' with proper capitalization of 'plugin'.


107-107: Simplified alert rendering with new component

The raw diff alert rendering has been replaced with the more declarative ModelMergerResultAlert component, which improves code readability and maintenance.

packages/project-builder-lib/src/web/components/ModelMergerResultAlert.tsx (5)

1-9: Well-structured imports and type definitions

The component has appropriate imports from the UI component library and proper typing for React elements. The import for PendingModelChange from tools index follows good practices.


10-12: Clear interface definition with nullable changes

The Props interface is well-defined and allows for undefined changes in the array, which provides flexibility when using this component.


14-22: Robust null-checking and filtering

The component properly filters out undefined entries and returns null if no valid changes remain, preventing unnecessary rendering and potential errors.


24-43: Effective conditional rendering for different change types

The component intelligently adjusts the alert variant and descriptive text based on whether a change represents a new model or an update to an existing model, which improves the user experience.


45-86: Comprehensive change type handling

The component effectively handles all types of model changes (fields, relations, constraints, primary keys) with consistent formatting and conditional rendering. The use of undefined rather than a falsy check is appropriate for conditional rendering.

One minor improvement suggestion:

-                ) : undefined}
+                ) : null}

Using null instead of undefined for conditional rendering is generally preferred in React, though both work.

plugins/baseplate-plugin-auth/vite.config.ts (3)

1-11: Well-structured imports and dependencies

The imports are well-organized, including Vite-specific types and plugins, as well as the necessary module federation utilities from the project builder library.


12-16: Proper use of async configuration with directory rewrites

Using defineConfig with an async function is appropriate for handling the asynchronous getModuleFederationTargets call. The rewriteDistToSrc function is correctly used to transform plugin directory paths.


17-27: Optimal build configuration for plugin development

The build configuration is well-suited for plugin development with source maps enabled and minification disabled. The external declaration for project-builder-lib correctly prevents duplication.

plugins/baseplate-plugin-auth/src/auth0/core/node.ts (6)

1-20: Well-organized imports from generator packages

The imports are cleanly organized by package, separating fastify generators, project builder lib, and react generators. This makes the dependencies clear and maintainable.


21-30: Clear type imports and local generator references

The type import for Auth0PluginDefinition and the import of local generators are well-structured, making the code more maintainable.


32-37: Well-structured platform plugin export with clear dependencies

The plugin correctly declares its dependency on the app compiler specification and defines empty exports. This follows the platform plugin architecture pattern.


38-72: Comprehensive backend compiler registration

The backend compiler registration properly retrieves the Auth0 plugin configuration and adds all necessary authentication-related features. The role mapping is correctly implemented.


73-96: Complete web app compiler registration

The web app compiler registration adds all necessary React-based Auth0 authentication components, hooks, and utilities. The callback path and routes are properly configured.


119-120: Minimal return value

The function returns an empty object after registration, which is appropriate since the plugin operates by registering compilers rather than exporting values.

packages/project-builder-server/src/compiler/web/index.ts (2)

41-50: features nesting depth changed – confirm downstream generators

Previously compileAuthPages/compileAuthFeatures injected pages at the root of the router.
With the new structure those pages are now grouped under features:.
Verify that:

  1. reactRouterGenerator understands the nested features prop.
  2. Any code that looks-up routes by absolute path still resolves correctly.

This is an easy place for regressions in navigation or SSR exports.


35-36:

Details

❌ Incorrect review comment

rootFeatures ordering may override router children unintentionally

safeMerge({ ...staticChildren }, rootFeatures) gives precedence to rootFeatures.
If a root feature happens to declare keys like reactNotFoundHandler or features they will clobber the statically defined ones, silently disabling core routes.

Two possible mitigations:

-          children: safeMerge(
-            {
-              reactNotFoundHandler: reactNotFoundHandlerGenerator({}),
-              features: compileWebFeatures(builder),
-            },
-            rootFeatures,
-          ),
+          children: safeMerge(
+            rootFeatures,
+            {
+              reactNotFoundHandler: reactNotFoundHandlerGenerator({}),
+              features: compileWebFeatures(builder),
+            },
+          ),

or validate for duplicate keys prior to merge.


🏁 Script executed:

#!/bin/bash
# Locate the safeMerge implementation
rg -n "export function safeMerge" -n .

# Confirm the call site in compiler/web/index.ts
rg -n "safeMerge" -n packages/project-builder-server/src/compiler/web/index.ts

Length of output: 811


🏁 Script executed:

#!/bin/bash
# Show the implementation of safeMerge to confirm merge order semantics
rg -n "export function safeMerge<" -n packages/utils/src/objects/safe-merge.ts -A 20 -B 0

Length of output: 1183


Incorrect concern: safeMerge doesn’t silently override—duplicate keys throw

The safeMerge(itemOne, itemTwo) implementation in packages/utils/src/objects/safe-merge.ts uses a customizer that throws on any overlapping key (unless allowEqualValues is enabled and values are identical). It never quietly clobbers your static routes with rootFeatures. Swapping the argument order wouldn’t change that behavior—duplicates still error instead of override.

No changes to the merge call are required.

Likely an incorrect or invalid review comment.

packages/project-builder-lib/src/tools/model-merger/model-merger.ts (1)

321-345: Concurrent mutation risk when pushing a freshly created model.

applyModelMergerResultInPlace mutates the passed definition object directly (definition.models.push(...)). If callers reuse the same PendingModelChange instance across multiple operations (e.g. batched merges in async workflows) this can lead to double-insertion or stale references.

Consider returning a new ProjectDefinition instance or documenting the in-place contract clearly. An immutable approach fits better with the functional style of the diff utilities introduced in this refactor.

"": {
"existingImportsProvider": {
"moduleSpecifier": "@/src/generators/auth/_providers/user-session.js",
"moduleSpecifier": "@halfdomelabs/fastify-generators",

@coderabbitai coderabbitai Bot May 16, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify external module specifier resolution.

The existingImportsProvider.moduleSpecifier now points to the top-level @halfdomelabs/fastify-generators package. Ensure that userSessionServiceImportsProvider is actually re-exported at the package root (and not nested) so the TS extractor can resolve it.


🏁 Script executed:

#!/bin/bash
# Verify that the fastify-generators package re-exports the provider
rg "export .*userSessionServiceImportsProvider" -R packages/fastify-generators/src

Length of output: 489


🏁 Script executed:

#!/bin/bash
# Corrected command: verify that the fastify-generators package re-exports the provider
rg "export .*userSessionServiceImportsProvider" -n packages/fastify-generators/src

Length of output: 211


Re-export userSessionServiceImportsProvider at package root

We only found the provider defined here:

  • packages/fastify-generators/src/generators/auth/_providers/user-session.ts:14

There’s no root‐level re-export, so the TS extractor won’t resolve the top-level module specifier. Please add a re-export in the package entrypoint (e.g. packages/fastify-generators/src/index.ts):

--- a/packages/fastify-generators/src/index.ts
+++ b/packages/fastify-generators/src/index.ts
+ export { userSessionServiceImportsProvider } from './generators/auth/_providers/user-session';

This ensures @halfdomelabs/fastify-generators exposes the provider at its root.

📝 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.

Suggested change
"moduleSpecifier": "@halfdomelabs/fastify-generators",
// packages/fastify-generators/src/index.ts
export { userSessionServiceImportsProvider } from './generators/auth/_providers/user-session';
🤖 Prompt for AI Agents
In
plugins/baseplate-plugin-auth/src/auth0/generators/fastify/auth0-module/ts-extractor.json
at line 5, the moduleSpecifier points to the top-level package
@halfdomelabs/fastify-generators, but userSessionServiceImportsProvider is not
re-exported at the package root. To fix this, add a re-export statement for
userSessionServiceImportsProvider in the package entrypoint file
packages/fastify-generators/src/index.ts so that it is exposed at the root level
and can be resolved by the TS extractor.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@kingston Thank you for confirming. I checked the exports again and can see that userSessionServiceImportsProvider is indeed exported at the root level of the @halfdomelabs/fastify-generators package. The change in the module specifier from the local path to the package import is appropriate for this refactoring. This helps maintain clean module boundaries between the core package and the newly separated Auth0 plugin.


🏁 Script executed:

#!/bin/bash
# Check if userSessionServiceImportsProvider is exported at the root level of the fastify-generators package
cd packages/fastify-generators/src
grep -r "export.*userSessionServiceImportsProvider" --include="*.ts" .
grep -r "export.*from.*user-session" --include="*.ts" .
cat index.ts

Length of output: 593


🏁 Script executed:

#!/bin/bash
# Check the export chain to see if userSessionServiceImportsProvider is properly exported
cd packages/fastify-generators/src

# Check if auth/_providers/index.ts is exported from auth/index.ts
echo "Checking if auth/_providers/index.ts is exported from auth/index.ts:"
grep -r "export.*from.*_providers" --include="*.ts" generators/auth/

# Check if auth/index.ts is exported from generators/index.ts
echo "Checking if auth/index.ts is exported from generators/index.ts:"
grep -r "export.*from.*auth" --include="*.ts" generators/

# Let's also look directly for any path that might lead to userSessionServiceImportsProvider
echo "Checking all export paths that could lead to userSessionServiceImportsProvider:"
find . -type f -name "*.ts" -exec grep -l "export.*from.*user-session" {} \; | xargs cat

Length of output: 1742


@kingston Thank you for the confirmation. I can now see the complete export chain that makes userSessionServiceImportsProvider available at the root level of the @halfdomelabs/fastify-generators package:

  1. Defined in generators/auth/_providers/user-session.ts
  2. Re-exported through _providers/index.jsauth/index.jsgenerators/index.js → root index.js

This chained re-export approach is working correctly with the TS extractor, so changing the module specifier to the package import is the right approach for the Auth0 plugin refactoring.

Comment on lines +1 to +8
{
"name": "auth0",
"displayName": "Auth0",
"icon": "icon.svg",
"description": "This plugin allows users to authenticate and authorize access to the application using Auth0.",
"version": "0.1.0",
"moduleDirectories": ["core"]
}

@coderabbitai coderabbitai Bot May 16, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Validate Auth0 plugin metadata consistency.

Please confirm that:

  • The version in metadata.json matches package.json.
  • The icon.svg file exists under src/auth0.
  • moduleDirectories covers all intended code directories.

🏁 Script executed:

#!/bin/bash
# Check version alignment
meta=$(jq -r '.version' plugins/baseplate-plugin-auth/src/auth0/metadata.json)
pkg=$(jq -r '.version' plugins/baseplate-plugin-auth/package.json)
[[ "$meta" == "$pkg" ]] || { echo "Version mismatch: metadata.json=$meta vs package.json=$pkg"; exit 1; }
# Verify icon file
[[ -f plugins/baseplate-plugin-auth/src/auth0/icon.svg ]] || { echo "Missing icon.svg"; exit 1; }

Length of output: 323


#!/bin/bash
# Verify icon.svg existence
if [[ -f plugins/baseplate-plugin-auth/src/auth0/icon.svg ]]; then
  echo "icon.svg: exists"
else
  echo "icon.svg: missing"
fi

# List subdirectories under src/auth0 for moduleDirectories validation
echo "Subdirectories under plugins/baseplate-plugin-auth/src/auth0:"
find plugins/baseplate-plugin-auth/src/auth0 -mindepth 1 -maxdepth 1 -type d | sed 's|.*/||'

#!/bin/bash
# Verify icon.svg existence
if [[ -f plugins/baseplate-plugin-auth/src/auth0/icon.svg ]]; then
  echo "icon.svg: exists"
else
  echo "icon.svg: missing"
fi

# Show moduleDirectories from metadata.json
echo "moduleDirectories in metadata.json:"
jq -r '.moduleDirectories[]' plugins/baseplate-plugin-auth/src/auth0/metadata.json

# List actual directories under src/auth0
echo "Actual subdirectories under plugins/baseplate-plugin-auth/src/auth0/:"
find plugins/baseplate-plugin-auth/src/auth0 -maxdepth 1 -mindepth 1 -type d -printf "%f\n"

Align Auth0 plugin metadata and package versions
The version in plugins/baseplate-plugin-auth/src/auth0/metadata.json (0.1.0) does not match the version in plugins/baseplate-plugin-auth/package.json (5.1.0). Please update so they are identical.

Additionally:

  • Confirm that plugins/baseplate-plugin-auth/src/auth0/icon.svg exists and is packaged correctly.
  • Ensure the moduleDirectories array in metadata.json lists every subdirectory under plugins/baseplate-plugin-auth/src/auth0 (not just core).
🤖 Prompt for AI Agents
In plugins/baseplate-plugin-auth/src/auth0/metadata.json lines 1 to 8, update
the "version" field to match the version in
plugins/baseplate-plugin-auth/package.json, which is 5.1.0. Verify that the file
plugins/baseplate-plugin-auth/src/auth0/icon.svg exists and is included in the
package. Also, update the "moduleDirectories" array to include all
subdirectories present under plugins/baseplate-plugin-auth/src/auth0, not just
"core", to ensure complete coverage of code directories.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is internal metadata so it's all good here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kingston Understood. If the metadata is for internal use only and the current values are intentional, then there's no need for adjustments. Thanks for the clarification!

import type React from 'react';

import { HiCollection, HiDatabase } from 'react-icons/hi';
import { HiDatabase } from 'react-icons/hi';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm /data route exists.

A new HiDatabase import and sidebar item for /data was added. Verify that the corresponding route and page for /data are defined in the routing configuration (_routes.tsx).


🏁 Script executed:

#!/bin/bash
rg "to=['\"]/data['\"]" -R packages/project-builder-web/src/pages

Length of output: 476


🏁 Script executed:

#!/bin/bash
# Locate and inspect the routing configuration for the `/data` path
ROUTES_FILE=$(fd -t f _routes.tsx | head -n1)
if [ -z "$ROUTES_FILE" ]; then
  echo "Routing config file _routes.tsx not found"
else
  echo "Found routing config at: $ROUTES_FILE"
  echo "Searching for '/data' route definitions:"
  grep -R "\"/data\"" -n "$ROUTES_FILE" || echo "No occurrences of '/data' in $ROUTES_FILE"
fi

Length of output: 670


Define missing /data route in routing configuration

The new sidebar item links to /data, but no corresponding route is defined in packages/project-builder-web/src/pages/_routes.tsx. Please add an entry for the /data page:

• File: packages/project-builder-web/src/pages/_routes.tsx
• Missing path: /data

Example diff:

--- a/packages/project-builder-web/src/pages/_routes.tsx
+++ b/packages/project-builder-web/src/pages/_routes.tsx
@@ -10,6 +10,7 @@ const routes: RouteObject[] = [
   { path: '/', element: <HomePage /> },
   { path: '/projects', element: <ProjectsPage /> },
+  { path: '/data', element: <DataPage /> },
 ];

Ensure the DataPage component exists (e.g. packages/project-builder-web/src/pages/data.tsx).

🤖 Prompt for AI Agents
In packages/project-builder-web/src/app/AppLayout/AppDesktopSidebar.tsx at line
4, you imported HiDatabase and added a sidebar item linking to the /data route,
but the corresponding route is missing in
packages/project-builder-web/src/pages/_routes.tsx. To fix this, add a route
entry for the path "/data" in _routes.tsx, importing and referencing the
DataPage component. Also, verify that the DataPage component exists at
packages/project-builder-web/src/pages/data.tsx or create it if missing.

@@ -0,0 +1 @@
export * from './routes.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure routes.js is present and correctly resolved.

The index now re-exports from ./routes.js. Confirm that routes.js exists at this path and that the build pipeline supports .js extensions in TypeScript imports.


🏁 Script executed:

#!/bin/bash
[[ -f packages/react-generators/src/utils/routes.js ]] || { echo "Missing routes.js"; exit 1; }

Length of output: 110


🏁 Script executed:

#!/bin/bash
# List files in the utils directory and verify if routes.ts exists
echo "Contents of packages/react-generators/src/utils:"
ls -1 packages/react-generators/src/utils

echo
if [[ -f packages/react-generators/src/utils/routes.ts ]]; then
  echo "Found routes.ts"
else
  echo "routes.ts is missing"
fi

Length of output: 283


Fix the export path to match the existing file

The index file is exporting from ./routes.js but only routes.ts exists. Update the export to either omit the extension (preferred) or use .ts so TypeScript can resolve it.

• File: packages/react-generators/src/utils/index.ts
Line 1:

-export * from './routes.js';
+export * from './routes';

This lets TS resolve to routes.ts at compile time (and emit the correct .js import if configured).

📝 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.

Suggested change
export * from './routes.js';
// packages/react-generators/src/utils/index.ts
-export * from './routes.js';
+export * from './routes';
🤖 Prompt for AI Agents
In packages/react-generators/src/utils/index.ts at line 1, the export statement
references './routes.js' but only 'routes.ts' exists in the directory. To fix
this, update the export to './routes' without any extension so TypeScript can
correctly resolve the module during compilation and emit the appropriate
JavaScript import.

Comment thread plugins/baseplate-plugin-auth/postcss.config.js
Comment on lines +34 to +43
const testFeature = createTestFeature();
const existingModel = createTestModel(testFeature.name, {
name: 'ExistingModel',
});
const mockDefinitionContainer: ProjectDefinitionContainer =
createTestProjectDefinitionContainer({
features: [testFeature],
models: [existingModel],
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Create a fresh definition container per test to avoid state-leakage

mockDefinitionContainer is instantiated once and re-used across all tests.
applyModelMergerDiff mutates the container internally (e.g. it allocates new IDs).
If any test mutates shared state, later tests may yield false positives/negatives that are very hard to trace.

-const mockDefinitionContainer: ProjectDefinitionContainer =
-  createTestProjectDefinitionContainer({ ... });
+const createContainer = () =>
+  createTestProjectDefinitionContainer({ ... });

Then call const mockDefinitionContainer = createContainer(); inside each it.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/project-builder-lib/src/tools/model-merger/model-merger.unit.test.ts
around lines 34 to 43, the mockDefinitionContainer is created once and shared
across tests, causing state leakage due to mutations inside
applyModelMergerDiff. To fix this, move the creation of mockDefinitionContainer
inside each individual test (inside each 'it' block) so that each test gets a
fresh container instance, preventing shared mutable state and ensuring test
isolation.

Comment on lines +88 to +91
expect(result?.changes['model.fields']).toHaveLength(1);
expect(result?.changes['model.fields']?.[0].type).toBe('add');
expect(result?.changes['model.fields']?.[0].key).toBe('email');
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Assertion is order-sensitive → use a predicate instead

The test assumes the first element of changes['model.fields'] is the newly added field.
If the diff implementation changes its ordering strategy, the test will break even though the behaviour is still correct.

-expect(result?.changes['model.fields']?.[0].key).toBe('email');
+expect(
+  result?.changes['model.fields']?.some((c) => c.key === 'email' && c.type === 'add'),
+).toBe(true);

Same concern appears in several other assertions throughout the file (e.g. 318-324, 367-369).
Switch to order-agnostic checks or helpers like expect.arrayContaining.

📝 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.

Suggested change
expect(result?.changes['model.fields']).toHaveLength(1);
expect(result?.changes['model.fields']?.[0].type).toBe('add');
expect(result?.changes['model.fields']?.[0].key).toBe('email');
});
expect(result?.changes['model.fields']).toHaveLength(1);
expect(result?.changes['model.fields']?.[0].type).toBe('add');
expect(
result?.changes['model.fields']?.some(
(c) => c.key === 'email' && c.type === 'add'
),
).toBe(true);
});
🤖 Prompt for AI Agents
In packages/project-builder-lib/src/tools/model-merger/model-merger.unit.test.ts
around lines 88 to 91, the test asserts that the first element in
changes['model.fields'] is the added field, which is order-sensitive and may
break if the order changes. Refactor these assertions to be order-agnostic by
using predicates or helpers like expect.arrayContaining to check for the
presence of the added field regardless of its position in the array. Apply
similar changes to other order-sensitive assertions in the file, such as those
around lines 318-324 and 367-369.

Comment on lines +137 to +157
return {
...input,
model: {
...input.model,
fields: input.model.fields.map((f) => ({
...f,
id: f.id ?? modelScalarFieldEntityType.generateNewId(),
})),
relations: input.model.relations?.map((r) => ({
...r,
id: r.id ?? modelLocalRelationEntityType.generateNewId(),
foreignId:
r.foreignId ?? modelForeignRelationEntityType.generateNewId(),
})),
uniqueConstraints: input.model.uniqueConstraints?.map((c) => ({
...c,
id: c.id ?? modelUniqueConstraintEntityType.generateNewId(),
})),
},
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Return type understates the actual shape – consider widening to ModelConfigInput.

attachIdsToModelMergerModelInput is declared to return Pick<ModelConfigInput, 'model'>, yet it spreads input (which includes id, name, featureRef, etc.).
TypeScript will accept the extra properties, but the narrow return signature:

  1. Misleads readers (and IDE tooling) about what is really produced.
  2. Forces callers to up-cast through as unknown as, reducing type safety in the long run.
-function attachIdsToModelMergerModelInput(
-  input: ModelMergerModelInput,
-): Pick<ModelConfigInput, 'model'> {
+function attachIdsToModelMergerModelInput(
+  input: ModelMergerModelInput,
+): ModelConfigInput {

deserializeModelMergerModelInput has the same mismatch – update it as well for consistency.

📝 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.

Suggested change
return {
...input,
model: {
...input.model,
fields: input.model.fields.map((f) => ({
...f,
id: f.id ?? modelScalarFieldEntityType.generateNewId(),
})),
relations: input.model.relations?.map((r) => ({
...r,
id: r.id ?? modelLocalRelationEntityType.generateNewId(),
foreignId:
r.foreignId ?? modelForeignRelationEntityType.generateNewId(),
})),
uniqueConstraints: input.model.uniqueConstraints?.map((c) => ({
...c,
id: c.id ?? modelUniqueConstraintEntityType.generateNewId(),
})),
},
};
}
function attachIdsToModelMergerModelInput(
input: ModelMergerModelInput,
): ModelConfigInput {
return {
...input,
model: {
...input.model,
fields: input.model.fields.map((f) => ({
...f,
id: f.id ?? modelScalarFieldEntityType.generateNewId(),
})),
relations: input.model.relations?.map((r) => ({
...r,
id: r.id ?? modelLocalRelationEntityType.generateNewId(),
foreignId:
r.foreignId ?? modelForeignRelationEntityType.generateNewId(),
})),
uniqueConstraints: input.model.uniqueConstraints?.map((c) => ({
...c,
id: c.id ?? modelUniqueConstraintEntityType.generateNewId(),
})),
},
};
}
🤖 Prompt for AI Agents
In packages/project-builder-lib/src/tools/model-merger/model-merger.ts around
lines 137 to 157, the function attachIdsToModelMergerModelInput is declared to
return Pick<ModelConfigInput, 'model'> but actually returns the full input
object with additional properties like id, name, and featureRef. To fix this,
update the return type of attachIdsToModelMergerModelInput to ModelConfigInput
to accurately reflect the full shape returned. Also, apply the same return type
update to deserializeModelMergerModelInput for consistency and improved type
safety.

Comment on lines +102 to +110
const siblingModelFieldIdMap = new Map([
...input.model.fields.map((f) => [f.id, f.name] as const),
...siblingModels.flatMap((m) =>
m.model.fields.map((f) => [f.id, f.name] as const),
),
]);
const nameFromId = (id: string): string =>
siblingModelFieldIdMap.get(id) ?? definitionContainer.nameFromId(id);
return {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Filter out undefined IDs before populating the siblingModelFieldIdMap.

input.model.fields may legitimately contain new fields whose id is still undefined.
Adding [undefined, name] into the map means Map.get(undefined) will succeed (and may even be overwritten several times), which can accidentally translate an unset ID into an arbitrary field name.
Down-stream, nameFromId(reference.localRef) and nameFromId(reference.foreignRef) may therefore return an unrelated field name instead of delegating to definitionContainer.nameFromId, silently corrupting the diff.

A minimal and safe fix is to skip items with a falsy id:

-    ...input.model.fields.map((f) => [f.id, f.name] as const),
+    ...input.model.fields
+      .filter((f) => f.id !== undefined)
+      .map((f) => [f.id, f.name] as const),

Apply the same guard to the siblingModels branch.
This prevents accidental key collisions on undefined and preserves the fallback to the container look-up.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/project-builder-lib/src/tools/model-merger/model-merger.ts around
lines 102 to 110, the map siblingModelFieldIdMap is populated with entries that
may have undefined IDs, causing incorrect lookups. To fix this, filter out any
fields where the id is falsy (undefined) before adding them to the map, both in
input.model.fields and in siblingModels fields. This ensures that
Map.get(undefined) does not return unintended values and preserves the fallback
to definitionContainer.nameFromId for unset IDs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant