Skip to content

Conversation

@kingston
Copy link
Collaborator

@kingston kingston commented Aug 17, 2025

Summary by CodeRabbit

  • New Features

    • Pluggable admin CRUD: custom column & action types with built-in Edit/Delete, per-row actions, and admin UI dialogs for manage-roles and password reset.
    • Local auth: role management UI and password change/reset flows with GraphQL endpoints.
  • Improvements

    • Lens-based nested form editing, configurable table actions, and dynamic per-type column/action configuration in the admin UI.
  • Migration

    • Automatic migration of admin columns to a type-based schema (v19).
  • Chores

    • Upgraded GraphQL dependencies and bumped form-lenses package.

@vercel
Copy link

vercel bot commented Aug 17, 2025

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

Project Deployment Preview Comments Updated (UTC)
baseplate-project-builder-web Ready Ready Preview Comment Aug 17, 2025 4:02am

@changeset-bot
Copy link

changeset-bot bot commented Aug 17, 2025

🦋 Changeset detected

Latest commit: d259c78

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/project-builder-lib Patch
@baseplate-dev/plugin-auth Patch
@baseplate-dev/fastify-generators Patch
@baseplate-dev/project-builder-cli Patch
@baseplate-dev/project-builder-common Patch
@baseplate-dev/project-builder-server Patch
@baseplate-dev/project-builder-test Patch
@baseplate-dev/project-builder-web Patch
@baseplate-dev/plugin-queue Patch
@baseplate-dev/plugin-storage Patch
@baseplate-dev/code-morph Patch
@baseplate-dev/core-generators Patch
@baseplate-dev/create-project Patch
@baseplate-dev/react-generators Patch
@baseplate-dev/sync Patch
@baseplate-dev/tools Patch
@baseplate-dev/ui-components Patch
@baseplate-dev/utils 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
Copy link

coderabbitai bot commented Aug 17, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds a pluggable Admin CRUD actions and columns system across schema, compiler, web UI, generators, and plugins; replaces legacy display-based columns with type-based columns and actions; adds built-in edit/delete and text/foreign implementations, migrations, auth admin roles, password management, and supporting UI/generator changes.

Changes

Cohort / File(s) Summary
Changesets
./.changeset/*
Adds changeset entries for admin CRUD action/column spec, userAdminRoles, password-management features, and GraphQL package upgrades.
Core generators — TypeScript replacement & validation
packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts, .../parse-simple-replacements.ts, .../*.unit.test.ts, .../renderers/template.ts, .../utils/ts-code-utils.ts
Switches replacement emission to in-place AST edits (ts-morph), broadens allowed replacement pattern (adds '?'), removes suggestReplacementType, enforces validation/errors for complex replacements, updates tests, and allows undefined fragments in merge helpers (signature updates).
GraphQL / Pothos upgrades
packages/fastify-generators/src/constants/fastify-packages.ts, .changeset/upgrade-graphql-packages.md
Bumps @envelop, graphql-yoga, @pothos packages versions; updates constant map and adds changeset.
Pothos template type adjustments
packages/fastify-generators/.../FieldWithInputPayloadPlugin/*
Adjusts generic bounds to InputFieldMap and simplifies InputFieldBuilder construction.
Pothos Sentry generator
packages/fastify-generators/.../pothos-sentry.generator.ts
Removes Sentry-related task and GraphQLError-specific logging fragment.
Project-builder-lib: compiler specs & re-exports
packages/project-builder-lib/src/compiler/*.ts, .../index.ts
Adds AdminCrudActionCompiler and AdminCrudColumnCompiler specs, factory implementations, and re-exports.
Schema: admin CRUD actions & columns
packages/project-builder-lib/src/schema/apps/web/admin/sections/crud-actions/*, .../crud-columns/*, .../sections/crud.ts, .../sections/index.ts
Introduces base schemas, entity types, built-in actions (edit/delete) and columns (text/foreign/roles), new createAdminCrudActionSchema/createAdminCrudColumnSchema, replaces legacy display/table-column schemas and adds table.actions default.
Parser & spec registration
packages/project-builder-lib/src/parser/parser.ts, .../web/specs/*, .../plugins/spec/auth-config-spec.ts
Registers adminCrudActionSpec/adminCrudColumnSpec in common specs; adds web-layer admin-crud-action-web-spec and admin-crud-column-web-spec; extends AuthRole with comment and builtIn properties.
Schema creator defaults/typing
packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts
Changes withDefault typing to accept z.input for defaultValue and adjusts isEmpty semantics (treats '' as empty, false not empty).
Model schema defaulting
packages/project-builder-lib/src/schema/models/index.ts
Defaults model.graphql to {} via ctx.withDefault, making graphql present in output type.
Migration: column type-based
packages/project-builder-lib/src/migrations/migration-019-column-type-based.*
Adds migration v19 converting display-based columns to type-based columns with unit tests.
Server: admin CRUD compilers & wiring
packages/project-builder-server/src/compiler/web/admin/crud/{actions,columns}.ts, .../index.ts, .../displays.ts
Adds compileAdminCrudAction/compileAdminCrudColumn, built-in compilers (edit/delete/text/foreign), integrates action/column compilation into section generation; removes legacy displays compiler.
Node plugin store
packages/project-builder-server/src/plugins/node-plugin-store.ts
Registers adminCrudActionCompilerSpec and adminCrudColumnCompilerSpec in NODE_SPEC_IMPLEMENTATIONS.
Web app: admin UI & lenses
packages/project-builder-web/src/routes/admin-sections.$appKey/-components/*, .../services/schema-parser-context.ts, packages/project-builder-web/package.json
Adds ActionDialog, CrudTableActionsForm, lens-based CrudTableColumnsForm, ColumnDialog changes, built-in web configs, integrates web specs into parser context, and adds @hookform/lenses dependency.
React generators: admin providers & actions
packages/react-generators/src/generators/admin/_providers/*, .../admin-crud-edit-action/*, .../admin-crud-delete-action/*
Adds AdminCrudActionContainer provider, introduces edit and delete action generators and exports, and wires action container into list generator.
React generators: column refactor
packages/react-generators/src/generators/admin/*
Migrates display generators to column generators (text/foreign/roles), adds new column generators and re-exports, removes old display generator exports and admin-crud-column generator.
React generators: list/edit templates & extractor
packages/react-generators/src/generators/admin/admin-crud-list/*, .../admin-crud-edit/*
Reworks list template to action-aware table (new table.tsx and variables TPL_ACTION_HOOKS/TPL_ACTION_SIBLING_COMPONENTS), removes built-in delete mutation flow; adds TPL_LIST_ROUTE variable and uses it in edit-form template.
React components (templates)
packages/react-generators/src/generators/core/react-components/...
Adds Badge, Command palette, MultiCombobox and MultiComboboxField templates and exports; updates Sidebar to support toggleSidebar/dismiss-on-click.
UI runtime tweaks
packages/ui-components/src/components/ui/sidebar/sidebar.tsx
Mirrors Sidebar dismiss-on-click changes and updates useSidebar return type.
Plugin-auth: admin UI, generators, schema, core features
plugins/plugin-auth/src/local-auth/{admin,core,web,node}/*
Adds userAdminRoles to plugin definition and editor; registers admin actions (manage-roles, reset-password) and roles column; adds generators/templates for manage-roles/reset-password actions and roles column; adds password management services, GraphQL mutations, updateUserRoles/updateUserRoles service, and wiring to pass admin role lists to generators.
Misc UI markup
packages/project-builder-web/src/routes/data/models/edit.$key/.../graph-ql-mutations-section.tsx
Wraps AlertDescription text in a div; no behavior change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Builder as AppEntryBuilder
  participant PluginStore as PluginStore
  participant ActionSpec as AdminCrudActionCompilerSpec
  participant ColumnSpec as AdminCrudColumnCompilerSpec
  participant BuiltIns as Built-in Compilers
  participant Generators as React Generators

  Builder->>PluginStore: getPluginSpec(ActionSpec/ColumnSpec)
  PluginStore-->>Builder: Spec instance
  Builder->>ActionSpec: getCompiler(action.type, BuiltIns)
  ActionSpec-->>Builder: ActionCompiler
  Builder->>ColumnSpec: getCompiler(column.type, BuiltIns)
  ColumnSpec-->>Builder: ColumnCompiler
  Builder->>ActionCompiler: compileAction(definition, ctx)
  ActionCompiler-->>Generators: adminCrud*ActionGenerator(...)
  Generators-->>Builder: GeneratorBundle
  Builder->>ColumnCompiler: compileColumn(definition, ctx)
  ColumnCompiler-->>Generators: adminCrud*ColumnGenerator(...)
  Generators-->>Builder: GeneratorBundle
Loading
sequenceDiagram
  autonumber
  participant UI as Admin Section UI
  participant Dialog as ActionDialog
  participant WebSpec as adminCrudActionWebSpec
  participant BuiltIn as BUILT_IN_*_WEB_CONFIGS
  participant Form as RHF + Zod

  UI->>Dialog: Open (Add/Edit Action)
  Dialog->>WebSpec: getActionWebConfigs(BuiltIn)
  WebSpec-->>Dialog: Available configs
  Dialog->>Form: build schema via createAdminCrudActionSchema
  Note over Dialog,Form: Renders type-specific WebForm if present
  Form-->>UI: onSave(action)
  UI->>UI: add/update action in table.actions
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ 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/eng-847-extend-auth-plugin-to-add-actions-to-crud-admin

🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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
Copy link

socket-security bot commented Aug 17, 2025

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

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​hookform/​lenses@​0.7.1 ⏵ 0.8.184 +6100100 +295 +5100

View full report

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 28

🔭 Outside diff range comments (4)
packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts (2)

15-22: Unify ZodEffects input type: WithDefaultType should use z.input<T> (mismatch with implementation).

The WithDefaultType type alias still uses z.input<z.ZodOptional<T>> for the ZodEffects input type, but the implementation below uses z.input<T>. This inconsistency will leak into the public API and can cause subtle type incompatibilities.

Align the alias with the implementation:

 export type WithDefaultType = <T extends z.ZodTypeAny>(
   schema: T,
   defaultValue: z.input<T>,
 ) => z.ZodEffects<
   z.ZodOptional<T>,
   z.output<z.ZodOptional<T>>,
-  z.input<z.ZodOptional<T>>
+  z.input<T>
 >;

5-13: Don’t treat false as “empty” in strip mode (data loss for boolean fields).

isEmpty(false) === true means valid boolean false values will be stripped to undefined in strip mode. That’s a correctness bug for boolean fields and can corrupt user intent.

Fix to only treat nullish/empty containers/empty strings as empty, not false:

 function isEmpty(value: unknown): boolean {
-  if (Array.isArray(value)) {
-    return value.length === 0;
-  }
-  if (typeof value === 'object' && value !== null) {
-    return Object.values(value).every((val) => val === undefined);
-  }
-  return value === false || value === '';
+  if (value === undefined || value === null) {
+    return true;
+  }
+  if (Array.isArray(value)) {
+    return value.length === 0;
+  }
+  if (typeof value === 'object') {
+    return Object.values(value).every((val) => val === undefined);
+  }
+  if (typeof value === 'string') {
+    return value === '';
+  }
+  return false;
 }
packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts (1)

86-90: Fix replaceAll usage: provide a string replacement, not a function

Using a function as the second argument to String.prototype.replaceAll is not supported by TypeScript typings and can cause compile/runtime issues. You can precompute the replacement string since the quote is known from the pattern.

Apply this diff:

-      result = result.replaceAll(pattern, (match) => {
-        const quote = match[0];
-        return `${quote}${variable}${quote}`;
-      });
+      const quote = pattern[0];
+      const replacement = `${quote}${variable}${quote}`;
+      result = result.replaceAll(pattern, replacement);
packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts (1)

170-177: Remove unused import: ErrorableLoader is not referenced in the Create button block

reactComponentsImports.ErrorableLoader.declaration() is added to the fragment imports but not used in the markup. This will likely generate an unused import in the output file.

Apply this diff to remove it:

                   [
                     tsImportBuilder(['Link']).from(
                       '@tanstack/react-router',
                     ),
                     tsImportBuilder(['MdAdd']).from('react-icons/md'),
                     reactComponentsImports.Button.declaration(),
-                    reactComponentsImports.ErrorableLoader.declaration(),
                   ],

Comment on lines +185 to 191
/* TPL_COMPLEX_EXPR=data?.user .email */
function Component() {}
`;

expect(() => extractTsTemplateVariables(invalidContent)).toThrow(
'Invalid replacement value "data?.user?.email"',
'Invalid replacement value "data?.user .email"',
);
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Validation case update looks correct; please ensure we also cover the now-valid optional chaining case

Switching the invalid value to include a space aligns with the relaxed rules (optional chaining should be valid). Please verify we have a positive test asserting that data?.user?.email is accepted somewhere in the suite (e.g., parse-simple-replacements.unit.test.ts). If missing, I can provide a patch.

Run this to confirm a positive test exists:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for a test that includes the now-valid optional chaining replacement value
rg -nP -C2 'data\?\.user\?\.email' --type=ts --glob '**/*.unit.test.ts'

Length of output: 93


Add a positive test for the valid optional‐chaining case

I ran a search across all *.unit.test.ts files and didn’t find any existing test that asserts data?.user?.email is accepted. Please add a test case—e.g. in parse-simple-replacements.unit.test.ts (or alongside the other “simple” template‐variable tests)—to verify that data?.user?.email now passes validation.

  • No matches for data?.user?.email in the current test suite

  • Add something like:

    const validContent = `
      /* TPL_SIMPLE_EXPR=data?.user?.email */
      function Component() {}
    `;
    
    expect(extractTsTemplateVariables(validContent)).toEqual([
      'data?.user?.email',
    ]);
🤖 Prompt for AI Agents
In
packages/core-generators/src/renderers/typescript/extractor/extract-ts-template-variables-simple.unit.test.ts
around lines 185 to 191, add a positive unit test that asserts the extractor
accepts optional-chaining with multiple safe-navigation operators (e.g.
"data?.user?.email"); create a test block with content containing the comment /*
TPL_SIMPLE_EXPR=data?.user?.email */ and call
expect(extractTsTemplateVariables(validContent)).toEqual(['data?.user?.email'])
to ensure the value passes validation.

Comment on lines 88 to 99
// Check if the value already exists in the template (would prevent extraction)
// We check the original template, not the processed one
const valuePattern = new RegExp(
`\\b${contents.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)}\\b`,
);
if (valuePattern.test(template)) {
throw new Error(
`The template contents contain the value "${contents}" which would prevent ` +
'template extraction from working correctly. Please ensure that replacement variable values ' +
'are not present in the original template file.',
);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Boundary check can miss values starting/ending with non-word chars; avoid dynamic regex entirely

Using word boundaries (\b) only guards transitions between [A-Za-z0-9_] and non-word chars. Since allowed values include non-word characters like $, /, ., and -, \b will not form a boundary at the start/end for such characters. Example: contents="$FOO" present in the template will not be detected because there’s no word boundary at the start of "$FOO". This can silently allow values that already exist in the template and break extraction later.

Additionally, static analysis flagged dynamic regex construction. While you escape special chars and restrict allowed sets, we can remove the dynamic regex altogether and precisely model “standalone occurrence” using simple indexOf + neighbor checks against the same allowed char class used by the validator.

Apply this diff to replace the dynamic regex check:

-      // Check if the value already exists in the template (would prevent extraction)
-      // We check the original template, not the processed one
-      const valuePattern = new RegExp(
-        `\\b${contents.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)}\\b`,
-      );
-      if (valuePattern.test(template)) {
+      // Check if the value already exists in the template (would prevent extraction)
+      // We check the original template, not the processed one
+      if (containsStandaloneValue(template, contents)) {
         throw new Error(
           `The template contents contain the value "${contents}" which would prevent ` +
             'template extraction from working correctly. Please ensure that replacement variable values ' +
             'are not present in the original template file.',
         );
       }

And add this helper (place it near escapeReplacement):

// Determines if `needle` occurs in `haystack` as a standalone token with respect to
// the allowed character class used for simple replacements: [A-Za-z0-9_$/.-]
function containsStandaloneValue(haystack: string, needle: string): boolean {
  if (needle.length === 0) return false;
  const isAllowed = (ch: string | undefined) =>
    !!ch && /[A-Za-z0-9_$/.-]/.test(ch);

  let idx = haystack.indexOf(needle);
  while (idx !== -1) {
    const prev = idx > 0 ? haystack[idx - 1] : undefined;
    const next =
      idx + needle.length < haystack.length
        ? haystack[idx + needle.length]
        : undefined;

    // Consider it “standalone” if both neighbors are either absent or not allowed
    if (!isAllowed(prev) && !isAllowed(next)) {
      return true;
    }
    idx = haystack.indexOf(needle, idx + 1);
  }
  return false;
}

This:

  • Correctly detects values starting/ending with non-word chars.
  • Eliminates dynamic regex construction (addressing the static analysis warning).
  • Aligns the boundary definition with the validator’s allowed character set.
🧰 Tools
🪛 ast-grep (0.38.6)

[warning] 89-91: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(
\\b${contents.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw$&)}\\b,
)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

Comment on lines +34 to +37
await prisma.$transaction([
prisma.userRole.deleteMany({
where: { userId, role: { notIn: validRoles } },
}),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid deleting built-in roles from the DB.

You filter built-ins out of validRoles, but deleteMany removes any role not in validRoles, which may unintentionally delete built-in roles if they are persisted. Limit deletions to assignable (non-built-in) roles only.

Apply this diff to restrict the deletion set:

   await prisma.$transaction([
     prisma.userRole.deleteMany({
-      where: { userId, role: { notIn: validRoles } },
+      where: {
+        userId,
+        role: { in: assignableRoles, notIn: validRoles },
+      },
     }),

Add the assignableRoles helper near the validRoles computation:

// Place below the validRoles computation (after Line 33)
const assignableRoles = Object.entries(AUTH_ROLE_CONFIG)
  .filter(([, cfg]) => !cfg.builtIn)
  .map(([name]) => name);
🤖 Prompt for AI Agents
In
plugins/plugin-auth/src/local-auth/core/generators/auth-module/templates/module/services/user-roles.service.ts
around lines 34 to 37, the prisma.deleteMany currently removes any role not in
validRoles which can accidentally delete built-in roles; define an
assignableRoles helper immediately below the validRoles computation that
collects role names from AUTH_ROLE_CONFIG where cfg.builtIn is false, then
restrict the deleteMany where clause so it only deletes roles that are
assignable and not in validRoles (i.e., require role ∈ assignableRoles AND role
∉ validRoles) to ensure built-in roles are never removed.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts (1)

21-28: Fix ZodEffects input generic mismatch between type alias and implementation.

WithDefaultType returns ZodEffects whose Input is z.input<z.ZodOptional>, but the implementation annotates the return as z.input. All branches return effects built on optionalSchema, so their Input is actually z.input<z.ZodOptional>. This mismatch will fail type-checking.

Apply this diff to align the implementation with the alias and with the actual return type of all branches:

-    ): z.ZodEffects<z.ZodOptional<T>, z.output<z.ZodOptional<T>>, z.input<T>> {
+    ): z.ZodEffects<z.ZodOptional<T>, z.output<z.ZodOptional<T>>, z.input<z.ZodOptional<T>>> {

If the intended new API is to expose ZodEffects with Input = z.input, we’ll need a different construction pattern (and likely a cast) to avoid widening the accepted input to include undefined; happy to draft that if that’s the goal.

Also applies to: 44-48

♻️ Duplicate comments (3)
packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx (1)

563-569: Same spread-order bug: generated code will drop the mobile-dismiss logic if consumers pass onClick.

{...props} after your inline onClick overrides it. Fix the order (or destructure onClick and spread the rest) to ensure dismissal runs.

Apply this diff:

       className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
-      onClick={(event) => {
-        onClick?.(event);
-        if (isMobile && !event.defaultPrevented) {
-          toggleSidebar();
-        }
-      }}
-      {...props}
+      {...props}
+      onClick={(event) => {
+        onClick?.(event);
+        if (isMobile && !event.defaultPrevented) {
+          toggleSidebar();
+        }
+      }}

Alternative (template-friendly): destructure onClick as userOnClick and spread the rest last, mirroring the suggestion in ui-components.

packages/core-generators/src/renderers/typescript/renderers/template.ts (1)

90-99: Template boundary check uses safe regex construction but still creates dynamic regex.

The use of escapeRegExp(contents) provides safe regex construction, but this still creates a dynamic regex from user input, which static analysis flagged as a potential ReDoS risk.

The boundary check can miss values starting/ending with non-word chars and uses dynamic regex construction. Apply the solution from the previous review to use containsStandaloneValue helper instead.

packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts (1)

47-47: Import declarations skipped intentionally.

Based on previous clarification, skipping import declarations allows unused imports to be removed properly after template variable replacements are applied.

🧹 Nitpick comments (1)
packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts (1)

62-70: Clarify “strip” semantics or compare against defaultValue.

The comment says “remove values matching defaults,” but the code strips only “empty” values and does not use defaultValue. Either update the comment to reflect the behavior, or implement comparison to defaultValue (deep-equal for objects).

Minimal doc fix:

-          // Use transform to remove values matching defaults after validation
+          // Use transform to strip empty values after validation

If you do want to strip values equal to defaultValue, we can add a deep-equality check (without adding deps) — say a small utility for primitives + shallow objects, or a guarded deep-equal where T is known to be JSON-like. Want me to draft that?

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 a77bac6 and 8466dbb.

📒 Files selected for processing (9)
  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts (3 hunks)
  • packages/core-generators/src/renderers/typescript/renderers/template.ts (2 hunks)
  • packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts (2 hunks)
  • packages/react-generators/src/generators/admin/admin-crud-delete-action/admin-crud-delete-action.generator.ts (1 hunks)
  • packages/react-generators/src/generators/admin/admin-crud-edit-action/admin-crud-edit-action.generator.ts (1 hunks)
  • packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts (7 hunks)
  • packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx (3 hunks)
  • packages/ui-components/src/components/ui/sidebar/sidebar.tsx (3 hunks)
  • plugins/plugin-auth/src/local-auth/admin/schema/roles-column.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • plugins/plugin-auth/src/local-auth/admin/schema/roles-column.ts
  • packages/react-generators/src/generators/admin/admin-crud-edit-action/admin-crud-edit-action.generator.ts
  • packages/ui-components/src/components/ui/sidebar/sidebar.tsx
  • packages/react-generators/src/generators/admin/admin-crud-delete-action/admin-crud-delete-action.generator.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.{ts,tsx}: Import UI components from the @baseplate-dev/ui-components package as shown in the provided examples.
Use both standalone and React Hook Form controller variants for form components from @baseplate-dev/ui-components as appropriate.
If a particular interface or type is not exported, change the file so it is exported.

**/*.{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

Files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
  • packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts
  • packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx
  • packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts
  • packages/core-generators/src/renderers/typescript/renderers/template.ts
**/*.{js,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/code-style.mdc)

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

Files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
  • packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts
  • packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx
  • packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts
  • packages/core-generators/src/renderers/typescript/renderers/template.ts
**/*.{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/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
  • packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts
  • packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx
  • packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts
  • packages/core-generators/src/renderers/typescript/renderers/template.ts
**/*

📄 CodeRabbit Inference Engine (.cursor/rules/code-style.mdc)

Use kebab-case for file names

Files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
  • packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts
  • packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx
  • packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts
  • packages/core-generators/src/renderers/typescript/renderers/template.ts
**/*.tsx

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.tsx: When using form components, integrate them with React Hook Form by passing the control prop from useForm().
Use layout components such as SidebarLayout, Card, and Breadcrumb from @baseplate-dev/ui-components to structure pages as shown in the example.
Use interactive dialog components like Dialog, ConfirmDialog, and useConfirmDialog from @baseplate-dev/ui-components for modal interactions.

Files:

  • packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx
🧠 Learnings (6)
📚 Learning: 2025-08-17T01:30:00.333Z
Learnt from: kingston
PR: halfdomelabs/baseplate#633
File: packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts:47-48
Timestamp: 2025-08-17T01:30:00.333Z
Learning: In template extraction systems like apply-simple-replacements.ts, it's intentional to skip processing import declarations to allow unused imports to be removed properly after template variable replacements are applied.

Applied to files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
  • packages/core-generators/src/renderers/typescript/renderers/template.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} : Include absolute paths in import statements via tsconfig paths (`src/` is the alias for `src/`)

Applied to files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
📚 Learning: 2025-07-22T09:09:23.016Z
Learnt from: CR
PR: halfdomelabs/baseplate#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-22T09:09:23.016Z
Learning: Applies to **/*.{ts,tsx} : If a particular interface or type is not exported, change the file so it is exported.

Applied to files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.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} : TypeScript with strict type checking

Applied to files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.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} : If a particular interface or type is not exported, change the file so it is exported

Applied to files:

  • packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts
📚 Learning: 2025-05-05T06:35:57.528Z
Learnt from: kingston
PR: halfdomelabs/baseplate#521
File: packages/sync/src/templates/text-template/render-text-template-file-action.ts:97-106
Timestamp: 2025-05-05T06:35:57.528Z
Learning: In the text template renderer, validation of template variable values against template content is only necessary when preparing for future template extraction (when shouldWriteMetadata is true). This validation prevents extraction errors by ensuring variable values don't already exist in the template content.

Applied to files:

  • packages/core-generators/src/renderers/typescript/renderers/template.ts
🧬 Code Graph Analysis (3)
packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx (2)
packages/react-generators/src/generators/core/react-components/templates/components/ui/tooltip.tsx (1)
  • TooltipContent (63-63)
packages/ui-components/src/components/ui/sidebar/sidebar.tsx (1)
  • useSidebar (776-776)
packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts (6)
packages/react-generators/src/providers/routes.ts (1)
  • reactRoutesProvider (37-38)
packages/react-generators/src/generators/admin/admin-crud-queries/admin-crud-queries.generator.ts (1)
  • adminCrudQueriesProvider (64-65)
packages/react-generators/src/generators/admin/_providers/admin-crud-action-container.ts (2)
  • adminCrudActionContainerProvider (23-24)
  • AdminCrudAction (7-16)
packages/react-generators/src/generators/admin/_providers/admin-crud-column-container.ts (2)
  • adminCrudColumnContainerProvider (16-17)
  • AdminCrudColumn (5-9)
packages/core-generators/src/renderers/typescript/utils/ts-code-utils.ts (1)
  • TsCodeUtils (85-582)
packages/core-generators/src/renderers/typescript/imports/builder.ts (1)
  • tsImportBuilder (74-82)
packages/core-generators/src/renderers/typescript/renderers/template.ts (2)
packages/core-generators/src/renderers/typescript/extractor/parse-simple-replacements.ts (1)
  • isValidSimpleReplacementValue (102-104)
packages/core-generators/src/renderers/typescript/utils/ts-code-utils.ts (1)
  • template (446-467)
🪛 ast-grep (0.38.6)
packages/core-generators/src/renderers/typescript/renderers/template.ts

[warning] 91-91: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(\\b${escapeRegExp(contents)}\\b)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ 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: Lint
  • GitHub Check: test
  • GitHub Check: Test E2E
🔇 Additional comments (39)
packages/project-builder-lib/src/schema/creator/extend-parser-context-with-defaults.ts (1)

23-23: Good change: defaultValue as z.input.

This aligns default inputs with Zod’s input typing and avoids unnecessary conversions at the API boundary.

packages/react-generators/src/generators/core/react-components/templates/components/ui/sidebar.tsx (6)

31-37: LGTM! Good documentation addition.

The documentation block clearly describes the component source and the new dismiss functionality, with a helpful reference to the GitHub issue.


46-54: LGTM! Context interface correctly updated.

The SidebarContextProps interface has been properly updated to include the toggleSidebar function, maintaining type safety for the new functionality.


102-109: LGTM! Toggle function implementation is correct.

The toggleSidebar function correctly handles both mobile and desktop states, using appropriate setters for each mode.


133-144: LGTM! Context value properly includes new function.

The toggleSidebar function is correctly included in both the context value object and the dependency array for the useMemo hook.


546-546: LGTM! Props interface correctly updated.

The onClick prop has been properly added to the component's props interface.


554-554: LGTM! Hook usage updated correctly.

The useSidebar hook call has been updated to destructure the new toggleSidebar function along with the existing values.

packages/core-generators/src/renderers/typescript/renderers/template.ts (7)

1-1: Import added for regex escaping.

The addition of escapeRegExp from es-toolkit provides safe regex construction for template validation.


9-12: Import structure updated for enhanced validation.

The import now includes isValidSimpleReplacementValue function which aligns with the broader validation improvements across the typescript renderers.


67-69: Simplified metadata check avoids optional chaining.

The direct property check !(key in variableMetadata) is more efficient than optional chaining for this validation path.


71-71: Direct property access after validation.

Since Line 67-69 already ensures the key exists in variableMetadata, this direct access is safe and consistent.


74-81: Enhanced validation with better error messaging.

The replacement of regex-based validation with isValidSimpleReplacementValue provides consistent validation logic. The error message clearly specifies allowed characters and suggests alternatives for complex values.


82-88: Duplicate value detection moved after validation.

The logical flow now validates the value format first, then checks for duplicates. This ordering provides better error messaging to users.


101-101: Consistent variable assignment after all validations.

The assignment to replacementVariables occurs after all validation checks pass, ensuring data integrity.

packages/core-generators/src/renderers/typescript/extractor/apply-simple-replacements.ts (7)

2-2: Import statement includes ts for JSX configuration.

The addition of ts import enables proper JSX configuration in the compiler options.


36-36: JSX configuration uses proper enum value.

The change from jsx: 1 to jsx: ts.JsxEmit.ReactJSX uses the proper TypeScript enum value, making the code more maintainable and explicit.


41-41: File extension changed to .tsx for JSX support.

The change from 'temp.ts' to 'temp.tsx' ensures TypeScript properly parses JSX content, which is necessary given the ReactJSX configuration.


44-44: Statement collection includes comments.

Using getStatementsWithComments() instead of getStatements() ensures comment preservation during AST processing.


49-64: In-place AST modification approach.

The new approach processes each statement individually, applying replacements to the statement text and updating the AST in-place. This is more efficient than the previous collection-and-reassembly approach.


66-66: Full text emission after AST transformations.

Using sourceFile.getFullText() leverages ts-morph's built-in text generation rather than manual assembly, which is more reliable for preserving formatting and trivia.


82-89: String literal replacement simplified.

The new approach generates literal pattern strings for different quote types and uses replaceAll instead of regex construction. This eliminates dynamic regex creation and improves performance.

packages/react-generators/src/generators/admin/admin-crud-list/admin-crud-list.generator.ts (18)

22-22: Type import added for action system.

The import of AdminCrudAction type supports the new dynamic action system being introduced.


26-26: Provider import for action container.

Adding adminCrudActionContainerProvider enables the runtime action registration system.


45-45: Renderers integrated into task dependencies.

The addition of renderers: ADMIN_ADMIN_CRUD_LIST_GENERATED.renderers.task enables the new renderer-based approach for generating templates.


53-53: Renderer provider wired into dependencies.

The renderer provider dependency enables access to the table renderer used in the build process.


56-56: Action container exported.

The export of adminCrudActionContainer makes it available for other generators to register actions dynamically.


64-64: Renderer dependency added to run function.

The renderers dependency provides access to the table renderer used later in the build process.


68-68: Action array initialized.

The initialization of an empty actions array prepares for dynamic action registration.


78-81: Action container provider implementation.

The provider implementation provides addAction for registering actions and getModelName for context. The interface is clean and focused.


88-88: Actions sorted by order.

Sorting actions by their order property ensures consistent action positioning in the UI.


129-129: Action GraphQL fields merged.

The inclusion of action GraphQL fields in the row query ensures all necessary data is available for action execution.


152-152: Table component props include loader data.

The table component receives both the data items and extra props from data loaders, maintaining the existing loader integration pattern.


187-201: Dynamic header generation with actions column.

The header generation now includes an "Actions" column when actions exist, with proper styling (w-12 class for width). The conditional rendering ensures the column only appears when needed.


208-213: Actions filtered by position.

The separation of inline and dropdown actions based on their position property enables different rendering strategies for each action type.


215-242: Action fragments properly constructed.

The inline actions are merged directly, while dropdown actions are wrapped in a proper dropdown menu structure with appropriate UI components. The use of MdMoreVert icon and accessibility considerations (sr-only span) show attention to UX details.


244-254: Action cell fragment with proper layout.

The action cell uses flexbox layout (flex items-center gap-2) to properly align inline and dropdown actions. The conditional rendering ensures the cell is only added when actions exist.


257-257: Table rendering uses new renderer system.

The switch from direct template rendering to renderers.table.render enables the extensible renderer-based approach introduced in this PR.


267-270: Cells include action cell conditionally.

The spread of cells followed by the conditional actionCellFragment ensures the actions column is positioned correctly at the end of the table.


284-290: Action-related template variables.

The new template variables TPL_ACTION_HOOKS and TPL_ACTION_SIBLING_COMPONENTS enable per-action hooks and components to be injected into the generated table template.

@kingston kingston merged commit cca138a into main Aug 17, 2025
8 of 9 checks passed
@kingston kingston deleted the kingston/eng-847-extend-auth-plugin-to-add-actions-to-crud-admin branch August 17, 2025 04:04
@github-actions github-actions bot mentioned this pull request Aug 14, 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.

2 participants