Skip to content

fix: Filtering of transformers on web UI#656

Merged
kingston merged 1 commit into
mainfrom
kingston/fix-auth-storage-bugs
Sep 10, 2025
Merged

fix: Filtering of transformers on web UI#656
kingston merged 1 commit into
mainfrom
kingston/fix-auth-storage-bugs

Conversation

@kingston

@kingston kingston commented Sep 10, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Bug Fixes
    • Admin UI no longer shows action or column Type options until a model is selected, preventing invalid choices.
    • Foreign column labels display correctly; “Unknown Item” appears only when data is truly missing, not for empty strings.
    • Storage transformers in the web UI are correctly filtered to only valid file relations.
    • Auth-related admin actions and columns now appear only for the appropriate model, ensuring accurate availability across the UI.

@vercel

vercel Bot commented Sep 10, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
baseplate-project-builder-web Error Error Sep 10, 2025 4:28pm

@changeset-bot

changeset-bot Bot commented Sep 10, 2025

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 219fa03

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

This PR includes changesets to release 18 packages
Name Type
@baseplate-dev/react-generators Patch
@baseplate-dev/plugin-storage Patch
@baseplate-dev/plugin-auth Patch
@baseplate-dev/project-builder-server Patch
@baseplate-dev/project-builder-common Patch
@baseplate-dev/project-builder-cli Patch
@baseplate-dev/project-builder-test Patch
@baseplate-dev/project-builder-web Patch
@baseplate-dev/create-project Patch
@baseplate-dev/code-morph Patch
@baseplate-dev/core-generators Patch
@baseplate-dev/fastify-generators Patch
@baseplate-dev/project-builder-lib Patch
@baseplate-dev/sync Patch
@baseplate-dev/tools Patch
@baseplate-dev/ui-components Patch
@baseplate-dev/utils Patch
@baseplate-dev/plugin-queue 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 Sep 10, 2025

Copy link
Copy Markdown

Walkthrough

Patch-only changesets added. Admin UI dialogs now guard availability filters with a truthy modelRef. React generator uses nullish coalescing for foreign column display fallback. Auth and Storage plugins switch to ModelUtils-based model resolution; Storage also updates function signatures to accept projectContainer and adjusts control flow.

Changes

Cohort / File(s) Summary
Release metadata (changesets)
.changeset/itchy-pigs-find.md, .changeset/salty-lines-ring.md
Added patch changesets for react-generators, plugin-storage, and plugin-auth; metadata-only notes about UI fallback and transformer filtering fix.
Admin UI dialogs: guarded availability filtering
packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx, .../column-dialog.tsx
Filters now require a truthy modelRef before calling config.isAvailableForModel; when absent, option lists become empty.
React generator fallback semantics
packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts
Replaced logical OR (
Plugins: ModelUtils-based model resolution
plugins/plugin-auth/src/local-auth/admin/web.ts, plugins/plugin-storage/src/storage/transformers/web.ts
Switched from direct modelRef equality to ModelUtils.byIdOrThrow(...).name checks. Storage: updated function signatures (allowNewTransformer, findNonTransformedFileRelations) to accept projectContainer and refactored calls accordingly; added related imports/types.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Dialog as Admin Dialog (Action/Column)
  participant Configs as Config Registry

  User->>Dialog: Open dialog
  Dialog->>Dialog: Read modelRef
  alt modelRef is truthy
    Dialog->>Configs: Filter configs with isAvailableForModel(definition, modelRef)
    Configs-->>Dialog: Matching configs
    Dialog-->>User: Render non-empty Type options
  else modelRef is falsy
    Dialog-->>User: Render empty Type options
  end
  note over Dialog: Guard prevents calling isAvailableForModel with undefined
Loading
sequenceDiagram
  autonumber
  participant UI as Admin UI (Storage)
  participant Transformers as transformers/web.ts
  participant Utils as ModelUtils
  participant Def as ProjectDefinitionContainer

  UI->>Transformers: allowNewTransformer(Def, modelConfig)
  Transformers->>Transformers: findNonTransformedFileRelations(Def, modelConfig)
  loop For each relation in modelConfig
    Transformers->>Utils: byIdOrThrow(Def.definition, relation.modelRef)
    Utils-->>Transformers: model (name)
    Transformers->>Transformers: Check name === STORAGE_MODELS.file
  end
  Transformers-->>UI: boolean (allowed) + derived fileRelationIds (via getNewTransformer)
  note over Transformers: Control flow now depends on provided projectContainer
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately references the transformer filtering fix in the storage plugin but does not encompass other important updates such as the auth availability logic, UI filtering guards, and generator fallback changes, making it only a partial summary of the PR.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kingston/fix-auth-storage-bugs

Comment @coderabbitai help to get the list of available commands and usage tips.

@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: 2

🧹 Nitpick comments (5)
plugins/plugin-auth/src/local-auth/admin/web.ts (3)

23-26: Use a tiny helper to DRY repeated model checks (optional).

You repeat the same isAvailableForModel predicate 3x. Consider extracting:

+const isUserModel = (definition: Parameters<typeof ModelUtils.byIdOrThrow>[0], modelId: string) =>
+  ModelUtils.byIdOrThrow(definition, modelId).name === LOCAL_AUTH_MODELS.user;

and then:

- isAvailableForModel: (definition, modelId) =>
-   ModelUtils.byIdOrThrow(definition, modelId).name === LOCAL_AUTH_MODELS.user,
+ isAvailableForModel: isUserModel,

33-36: Same as above — apply helper for consistency.


43-46: Same as above — apply helper for consistency.

plugins/plugin-storage/src/storage/transformers/web.ts (2)

37-39: Potential hard-throw on bad relation refs (optional).

byIdOrThrow(definition, relation.modelRef) will crash the UI if a relation points to a deleted model. If that’s possible in draft states, consider skipping invalid refs instead of throwing.

Apply:

-      ?.filter(
-        (relation) =>
-          ModelUtils.byIdOrThrow(projectContainer.definition, relation.modelRef)
-            .name === STORAGE_MODELS.file &&
+      ?.filter((relation) => {
+        const target = ModelUtils.byId(
+          projectContainer.definition,
+          relation.modelRef,
+        );
+        return (
+          target?.name === STORAGE_MODELS.file &&
           !fileTransformers?.some(
             (transformer) => transformer.fileRelationRef === relation.id,
-          ),
-      )
+          )
+        );
+      })

68-71: Tiny cleanup: reuse local fileRelationId.

Avoid repeating [0] and keep names consistent.

-        const fileRelationIds = findNonTransformedFileRelations(
+        const fileRelationIds = findNonTransformedFileRelations(
           projectContainer,
           modelConfig,
         );
-        const fileRelationId = fileRelationIds[0];
+        const fileRelationId = fileRelationIds[0];
...
-          fileRelationRef: fileRelationIds[0],
+          fileRelationRef: fileRelationId,
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0e648f0 and 219fa03.

📒 Files selected for processing (7)
  • .changeset/itchy-pigs-find.md (1 hunks)
  • .changeset/salty-lines-ring.md (1 hunks)
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx (1 hunks)
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx (1 hunks)
  • packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts (1 hunks)
  • plugins/plugin-auth/src/local-auth/admin/web.ts (2 hunks)
  • plugins/plugin-storage/src/storage/transformers/web.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
.changeset/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

When adding or changing a feature, add a new Changeset markdown file in .changeset/ using the specified frontmatter format with a patch bump

Files:

  • .changeset/salty-lines-ring.md
  • .changeset/itchy-pigs-find.md
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)

**/*.{ts,tsx}: TypeScript with strict type checking
Always include return types on top-level functions including React components (React.ReactElement)
Include absolute paths in import statements via tsconfig paths (@src/ is the alias for src/)
If a particular interface or type is not exported, change the file so it is exported

If an interface or type is needed publicly but is not exported, modify the TypeScript file so it is exported

Files:

  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx
  • plugins/plugin-storage/src/storage/transformers/web.ts
  • packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts
  • plugins/plugin-auth/src/local-auth/admin/web.ts
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)

Node 16 module resolution - include file extensions in imports (.js)

Files:

  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx
  • plugins/plugin-storage/src/storage/transformers/web.ts
  • packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts
  • plugins/plugin-auth/src/local-auth/admin/web.ts
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)

**/*.{ts,tsx,js}: Sort imports by group: external libs first, then local imports
Use camelCase for variables/functions, PascalCase for types/classes
Order functions such that functions are placed below the variables/functions they use
We use the prefer using nullish coalescing operator (??) ESLint rule instead of a logical or (||), as it is a safer operator
Use console.info/warn/error instead of console.log

Files:

  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx
  • plugins/plugin-storage/src/storage/transformers/web.ts
  • packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts
  • plugins/plugin-auth/src/local-auth/admin/web.ts
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx
**/*

📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)

Use kebab-case for file names

Files:

  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx
  • plugins/plugin-storage/src/storage/transformers/web.ts
  • packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts
  • plugins/plugin-auth/src/local-auth/admin/web.ts
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx
{packages/project-builder-web/**,packages/ui-components/**}/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/ui-rules.mdc)

{packages/project-builder-web/**,packages/ui-components/**}/*.tsx: Use ShadCN-based components from @baseplate-dev/ui-components and always prefer these components over creating custom ones
Use Tailwind CSS utilities exclusively for styling; avoid writing custom CSS classes and use Tailwind's utility classes for all styling needs
In plugins, prefix all Tailwind classes with the plugin name (e.g., auth-, storage-)
Use icons from react-icons/md (Material Design icons) and import them like import { MdAdd, MdDelete } from 'react-icons/md'; avoid using other icon libraries

Files:

  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx
  • packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx
🧠 Learnings (3)
📚 Learning: 2025-07-22T09:11:29.223Z
Learnt from: CR
PR: halfdomelabs/baseplate#0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-07-22T09:11:29.223Z
Learning: Applies to {packages/project-builder-web/**,packages/ui-components/**}/*.tsx : In plugins, prefix all Tailwind classes with the plugin name (e.g., `auth-`, `storage-`)

Applied to files:

  • plugins/plugin-storage/src/storage/transformers/web.ts
📚 Learning: 2025-07-22T09:11:29.223Z
Learnt from: CR
PR: halfdomelabs/baseplate#0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-07-22T09:11:29.223Z
Learning: Applies to {packages/project-builder-web/**,packages/ui-components/**}/*.tsx : Use ShadCN-based components from `baseplate-dev/ui-components` and always prefer these components over creating custom ones

Applied to files:

  • plugins/plugin-storage/src/storage/transformers/web.ts
📚 Learning: 2025-07-22T09:10:31.413Z
Learnt from: CR
PR: halfdomelabs/baseplate#0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-07-22T09:10:31.413Z
Learning: Applies to **/*.{ts,tsx,js} : We use the prefer using nullish coalescing operator (`??`) ESLint rule instead of a logical or (`||`), as it is a safer operator

Applied to files:

  • .changeset/itchy-pigs-find.md
  • packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts
🧬 Code graph analysis (2)
plugins/plugin-storage/src/storage/transformers/web.ts (3)
packages/project-builder-lib/src/definition/project-definition-container.ts (1)
  • ProjectDefinitionContainer (31-161)
packages/project-builder-lib/src/definition/model/model-utils.ts (1)
  • ModelUtils (107-119)
plugins/plugin-storage/src/storage/constants/model-names.ts (1)
  • STORAGE_MODELS (1-6)
plugins/plugin-auth/src/local-auth/admin/web.ts (2)
packages/project-builder-lib/src/definition/model/model-utils.ts (1)
  • ModelUtils (107-119)
plugins/plugin-auth/src/local-auth/constants/model-names.ts (1)
  • LOCAL_AUTH_MODELS (1-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test E2E
  • GitHub Check: test
  • GitHub Check: Lint
🔇 Additional comments (5)
.changeset/itchy-pigs-find.md (1)

1-6: Changeset looks correct (patch bump + concise rationale).

Accurately documents the switch to ?? in react-generators. Nothing else to change.

.changeset/salty-lines-ring.md (1)

1-7: Good: patch releases declared for auth + storage with clear message.

This matches the code changes gating transformer availability.

packages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.ts (1)

69-77: Correct switch to nullish coalescing for fallback label.

?? "Unknown Item" matches our guideline and avoids masking empty strings.

plugins/plugin-storage/src/storage/transformers/web.ts (2)

60-64: Nice availability gate via computed relations.

Reads clean and aligns with UI filtering.


25-27: All usages of allowNewTransformer now include the projectContainer argument; no further action required.

Comment on lines +60 to +62
.filter(
(config) => modelRef && config.isAvailableForModel(definition, modelRef),
)

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

Fix: filter callback may return string | boolean under strict TS.

modelRef && expr yields string | boolean because modelRef is string. Make it boolean-safe or branch earlier.

Apply one of these:

-    .filter(
-      (config) => modelRef && config.isAvailableForModel(definition, modelRef),
-    )
+    .filter(
+      (config) => !!modelRef && config.isAvailableForModel(definition, modelRef),
+    )

or (clearer):

-  const actionTypeOptions = actionWeb
-    .getActionWebConfigs(BUILT_IN_ADMIN_CRUD_ACTION_WEB_CONFIGS)
-    .filter(
-      (config) => modelRef && config.isAvailableForModel(definition, modelRef),
-    )
-    .map((config) => ({ label: config.label, value: config.name }));
+  const actionTypeOptions = modelRef
+    ? actionWeb
+        .getActionWebConfigs(BUILT_IN_ADMIN_CRUD_ACTION_WEB_CONFIGS)
+        .filter((config) =>
+          config.isAvailableForModel(definition, modelRef),
+        )
+        .map((config) => ({ label: config.label, value: config.name }))
+    : [];
📝 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
.filter(
(config) => modelRef && config.isAvailableForModel(definition, modelRef),
)
.filter(
(config) => !!modelRef && config.isAvailableForModel(definition, modelRef),
)
🤖 Prompt for AI Agents
In
packages/project-builder-web/src/routes/admin-sections.$appKey/-components/action-dialog.tsx
around lines 60 to 62, the filter callback uses "modelRef &&
config.isAvailableForModel(definition, modelRef)" which under strict TypeScript
yields a union string | boolean because modelRef is a string; change the
expression to return a boolean only — for example, guard earlier with "if
(!modelRef) return false" or replace the expression with a boolean coercion such
as "Boolean(modelRef) && config.isAvailableForModel(definition, modelRef)" or
"modelRef ? config.isAvailableForModel(definition, modelRef) : false" (any of
these will ensure the filter callback is strictly boolean).

Comment on lines +61 to +63
.filter(
(config) => modelRef && config.isAvailableForModel(definition, modelRef),
)

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

Same strict-typing issue as ActionDialog filter.

Use boolean coercion or branch:

-    .filter(
-      (config) => modelRef && config.isAvailableForModel(definition, modelRef),
-    )
+    .filter(
+      (config) => !!modelRef && config.isAvailableForModel(definition, modelRef),
+    )

or:

-  const columnTypeOptions = columnWeb
-    .getColumnWebConfigs(BUILT_IN_ADMIN_CRUD_COLUMN_WEB_CONFIGS)
-    .filter(
-      (config) => modelRef && config.isAvailableForModel(definition, modelRef),
-    )
-    .map((config) => ({ label: config.label, value: config.name }));
+  const columnTypeOptions = modelRef
+    ? columnWeb
+        .getColumnWebConfigs(BUILT_IN_ADMIN_CRUD_COLUMN_WEB_CONFIGS)
+        .filter((config) =>
+          config.isAvailableForModel(definition, modelRef),
+        )
+        .map((config) => ({ label: config.label, value: config.name }))
+    : [];
📝 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
.filter(
(config) => modelRef && config.isAvailableForModel(definition, modelRef),
)
.filter(
(config) => !!modelRef && config.isAvailableForModel(definition, modelRef),
)
🤖 Prompt for AI Agents
In
packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsx
around lines 61 to 63, the Array.filter predicate can return undefined when
modelRef is falsy because config.isAvailableForModel is only evaluated
conditionally; update the predicate to always return a boolean by either
short-circuiting with an explicit boolean coercion (e.g., ensure the left side
is !!modelRef) or by branching earlier (returning an empty array or skipping
filtering when modelRef is not set), so the filter callback consistently returns
true/false rather than undefined.

@kingston kingston merged commit 6d0be95 into main Sep 10, 2025
13 of 14 checks passed
@kingston kingston deleted the kingston/fix-auth-storage-bugs branch September 10, 2025 16:51
@github-actions github-actions Bot mentioned this pull request Sep 10, 2025
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