fix: Filtering of transformers on web UI#656
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 219fa03 The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
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 |
WalkthroughPatch-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
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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Pre-merge checks (3 passed)✅ Passed checks (3 passed)
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.
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 unit tests
Comment |
There was a problem hiding this comment.
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
isAvailableForModelpredicate 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 localfileRelationId.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.
📒 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 forsrc/)
If a particular interface or type is not exported, change the file so it is exportedIf 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.tsxplugins/plugin-storage/src/storage/transformers/web.tspackages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.tsplugins/plugin-auth/src/local-auth/admin/web.tspackages/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.tsxplugins/plugin-storage/src/storage/transformers/web.tspackages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.tsplugins/plugin-auth/src/local-auth/admin/web.tspackages/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.tsxplugins/plugin-storage/src/storage/transformers/web.tspackages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.tsplugins/plugin-auth/src/local-auth/admin/web.tspackages/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.tsxplugins/plugin-storage/src/storage/transformers/web.tspackages/react-generators/src/generators/admin/admin-crud-foreign-column/admin-crud-foreign-column.generator.tsplugins/plugin-auth/src/local-auth/admin/web.tspackages/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-componentsand 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 fromreact-icons/md(Material Design icons) and import them likeimport { MdAdd, MdDelete } from 'react-icons/md'; avoid using other icon libraries
Files:
packages/project-builder-web/src/routes/admin-sections.$appKey/-components/column-dialog.tsxpackages/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.mdpackages/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 ofallowNewTransformernow include theprojectContainerargument; no further action required.
| .filter( | ||
| (config) => modelRef && config.isAvailableForModel(definition, modelRef), | ||
| ) |
There was a problem hiding this comment.
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.
| .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).
| .filter( | ||
| (config) => modelRef && config.isAvailableForModel(definition, modelRef), | ||
| ) |
There was a problem hiding this comment.
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.
| .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.
Summary by CodeRabbit