feat: Add create-generator action and CLI command to scaffold new generators with boilerplate code#724
Conversation
…erators with boilerplate code
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 5f14a41 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 |
📝 WalkthroughWalkthroughThis PR introduces a "create-generator" feature for scaffolding new code generators with boilerplate. It adds CLI and server-side implementations, core generator creation logic with file generation and directory management, a monorepo root utility, comprehensive documentation files, and unit tests covering multiple scenarios. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant CLI as CLI Command
participant Handler as Handler<br/>(templates.ts)
participant Action as createGenerator<br/>Action
participant Core as createGenerator<br/>Core Logic
participant FileSystem as FileSystem<br/>& Prettier
participant CategoryIdx as Category<br/>Index Manager
User->>CLI: templates create my-gen<br/>./generators --include-templates
CLI->>Handler: invoke create handler<br/>(name, directory, options)
Handler->>Action: call createGeneratorAction
Action->>Core: invoke createGenerator<br/>(name, directory, true)
Core->>Core: parseGeneratorName<br/>(my-gen)
Note over Core: Extract: category, kebabName,<br/>camelCaseName, SCREAMING_NAME
Core->>Core: resolveAbsoluteDir<br/>(./generators)
Core->>Core: validate directory exists<br/>& generator not already present
Core->>FileSystem: mkdir generator directory
Core->>FileSystem: write generator.ts<br/>(scaffold template)
Core->>FileSystem: write index.ts<br/>(barrel export)
Core->>FileSystem: write generated/index.ts<br/>(typed placeholder)
Core->>FileSystem: write extractor.json<br/>(name + empty templates)
Core->>CategoryIdx: update category/index.ts<br/>(append export)
Core->>FileSystem: format files via Prettier
Core->>Action: return CreateGeneratorResult
Action->>Handler: return result
Handler->>CLI: print success message<br/>+ generator path<br/>+ created files list
CLI->>User: Display output
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
packages/project-builder-cli/src/commands/templates.ts (1)
286-318: Consider adding explicit return type annotation.The function implementation is correct and follows established patterns. However, per the coding guidelines, top-level functions should include explicit return types.
🔎 Suggested addition
async function handleCreateGenerator( name: string, directory: string, options: CreateGeneratorOptions, -): Promise<void> { +): Promise<void> {Note: If ESLint is configured to enforce this, it will catch this automatically, so this is optional.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (15)
.changeset/add-create-generator-action.md.claude/skills/modify-generated-code/SKILL.md.cursor/rules/mcp-actions.mdc.cursor/rules/ui-components.mdc.mcp.jsonAGENTS.mdpackages/project-builder-cli/src/commands/templates.tspackages/project-builder-server/src/actions/generators/create-generator.action.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/index.tspackages/project-builder-server/src/actions/registry.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/templates/create/create-generator.unit.test.tspackages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/utils/find-monorepo-root.ts
🧰 Additional context used
📓 Path-based instructions (6)
.changeset/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Add a new Changeset in the
.changeset/directory for new features or changes, with format'package-name': patchand description of the feature or change
Files:
.changeset/add-create-generator-action.md
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
**/*.{ts,tsx}: Use TypeScript with strict type checking enabled
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 exported
If caught on a typing loop where forcing theanytype is necessary, do not iterate too much - leave the typing as broken and let the user fix itIf target code is not easily testable, refactor it to be more testable (e.g., export types or functions)
**/*.{ts,tsx}: Import components from '@baseplate-dev/ui-components' package for UI development (e.g., Button, Input, Card, Dialog, etc.)
Use form components with React Hook Form controller variants (InputField, TextareaField, SelectField, CheckboxField, SwitchField, ComboboxField, MultiComboboxField, ColorPickerField, DatePickerField, DateTimePickerField)
Use SidebarLayout, Card, Breadcrumb, NavigationMenu, and NavigationTabs components for consistent layout structure from @baseplate-dev/ui-components
Use Dialog, ConfirmDialog, and useConfirmDialog from @baseplate-dev/ui-components for modal dialogs and confirmation interactions
Always usecompareStringsfrom@baseplate-dev/utilsinstead ofString.prototype.localeCompare()for code generation, file sorting, and internal data structures
If a particular interface or type is not exported, modify the file to export it
Use TsCodeFragment for composable code pieces and TsCodeUtils for manipulating fragments when generating TypeScript code
Create generators usingcreateGeneratorwith configuration via descriptor schema (Zod), organizing into one or more tasks created withcreateGeneratorTask
Tasks should haverun(initialization) andbuild(code generation) phases, export and consume providers, and may be organized into phases for ordered execution
Use provider scopes to control visibility and prevent collisions be...
Files:
packages/project-builder-server/src/utils/find-monorepo-root.tspackages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/generators/create-generator.action.tspackages/project-builder-server/src/templates/create/create-generator.unit.test.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/registry.tspackages/project-builder-server/src/actions/index.tspackages/project-builder-cli/src/commands/templates.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
**/*.{ts,tsx,js}: Node 16 module resolution - include file extensions in imports (.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
Prefer using nullish coalescing operator (??) instead of logical or (||), enforced via ESLint rule
Prefer barrel exports e.g.export * from './foo.js'instead of individual named exports
Use console.info/warn/error instead of console.log
Files:
packages/project-builder-server/src/utils/find-monorepo-root.tspackages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/generators/create-generator.action.tspackages/project-builder-server/src/templates/create/create-generator.unit.test.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/registry.tspackages/project-builder-server/src/actions/index.tspackages/project-builder-cli/src/commands/templates.ts
**/*.{unit.test.ts,int.test.ts}
📄 CodeRabbit inference engine (.cursor/rules/code-style.mdc)
**/*.{unit.test.ts,int.test.ts}: Unit tests must use.unit.test.tssuffix, integration tests must use.int.test.tssuffix
Always import vitest globals explicitly (describe, it, expect)
Files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
**/*.{unit,int}.test.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)
**/*.{unit,int}.test.{ts,tsx}: Use descriptive test names that explain what is being tested
Structure tests with Arrange-Act-Assert: clear setup, execution, and verification phases
Always mock external API calls and file system operations
Each test should be independent and not rely on other tests
Leverage TypeScript for type-safe mocking in tests
Focus on testing public methods and behaviors, not implementation details
Each test should verify one specific behavior
Extract repeated logic into helper functions to reduce duplication
Test broad behavior and common edge cases intelligently to avoid slowing down CI with excessive tests
For file system operations in tests, use memfs and mocknode:fsandnode:fs/promises
When using globby with mocked fs, pass the mocked fs adapter to the globby call
Files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
**/*.unit.test.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)
Unit tests are colocated with source files using
.unit.test.tssuffix
Files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
🧠 Learnings (52)
📓 Common learnings
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Baseplate development follows a code-first approach: make changes directly in working codebases, extract those changes into reusable templates, update generators to use the new templates, then validate and sync the generated code
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Follow task-based architecture for generators, use provider scopes for explicit wiring, leverage TypeScript rendering system for code generation, organize complex generation with Task Phases, and use Dynamic Tasks for data-driven generation
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Create generators using `createGenerator` with configuration via descriptor schema (Zod), organizing into one or more tasks created with `createGeneratorTask`
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to .changeset/*.md : Add a new Changeset in the `.changeset/` directory for new features or changes, with format `'package-name': patch` and description of the feature or change
Applied to files:
.changeset/add-create-generator-action.md
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Create generators using `createGenerator` with configuration via descriptor schema (Zod), organizing into one or more tasks created with `createGeneratorTask`
Applied to files:
.changeset/add-create-generator-action.mdpackages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/generators/create-generator.action.tspackages/project-builder-server/src/templates/create/create-generator.unit.test.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/registry.tspackages/project-builder-cli/src/commands/templates.ts
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Baseplate development follows a code-first approach: make changes directly in working codebases, extract those changes into reusable templates, update generators to use the new templates, then validate and sync the generated code
Applied to files:
.changeset/add-create-generator-action.mdAGENTS.md.cursor/rules/mcp-actions.mdc.claude/skills/modify-generated-code/SKILL.md
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to packages/ui-components/** : The baseplate-dev/ui-components package provides 52+ production-ready components including Basic, Form, Layout, Interactive, and Display components with Storybook documentation
Applied to files:
.cursor/rules/ui-components.mdcAGENTS.md
📚 Learning: 2025-11-24T19:45:27.654Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-11-24T19:45:27.654Z
Learning: Applies to +(*.tsx|packages/project-builder-web/**/*.tsx|packages/ui-components/**/*.tsx) : Use ShadCN-based components from `baseplate-dev/ui-components` instead of creating custom components
Applied to files:
.cursor/rules/ui-components.mdcAGENTS.md
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Import components from 'baseplate-dev/ui-components' package for UI development (e.g., Button, Input, Card, Dialog, etc.)
Applied to files:
.cursor/rules/ui-components.mdcAGENTS.mdpackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Use SidebarLayout, Card, Breadcrumb, NavigationMenu, and NavigationTabs components for consistent layout structure from baseplate-dev/ui-components
Applied to files:
.cursor/rules/ui-components.mdcAGENTS.md
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Use Dialog, ConfirmDialog, and useConfirmDialog from baseplate-dev/ui-components for modal dialogs and confirmation interactions
Applied to files:
.cursor/rules/ui-components.mdcAGENTS.md
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Use form components with React Hook Form controller variants (InputField, TextareaField, SelectField, CheckboxField, SwitchField, ComboboxField, MultiComboboxField, ColorPickerField, DatePickerField, DateTimePickerField)
Applied to files:
.cursor/rules/ui-components.mdc
📚 Learning: 2025-11-24T19:45:08.523Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/dev-commands.mdc:0-0
Timestamp: 2025-11-24T19:45:08.523Z
Learning: Check types using `pnpm typecheck` from repository root or package
Applied to files:
packages/project-builder-server/src/utils/find-monorepo-root.ts
📚 Learning: 2025-11-24T19:45:08.523Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/dev-commands.mdc:0-0
Timestamp: 2025-11-24T19:45:08.523Z
Learning: Build the project using `pnpm build` from repository root or package
Applied to files:
packages/project-builder-server/src/utils/find-monorepo-root.ts
📚 Learning: 2025-06-03T09:11:29.651Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 562
File: plugins/plugin-auth/package.json:32-36
Timestamp: 2025-06-03T09:11:29.651Z
Learning: With TypeScript project references, TypeScript compilation is watched from the root level using "watch:tsc:root" script, so individual packages no longer need to include their "tsc:watch" scripts in their local "watch" commands. The local "tsc:watch" scripts are renamed from "watch:tsc" but are not meant to be run as part of the package's watch command since TypeScript watching is handled centrally at the workspace root.
Applied to files:
packages/project-builder-server/src/utils/find-monorepo-root.ts
📚 Learning: 2025-06-11T18:31:22.247Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 571
File: packages/core-generators/src/renderers/extractor/plugins/typed-templates-file.ts:102-106
Timestamp: 2025-06-11T18:31:22.247Z
Learning: For `templateExtractorBarrelExportPlugin.addGeneratedBarrelExport`, the generated barrel exports are written into `generated/index.ts`, therefore the `moduleSpecifier` must be specified relative to that file (e.g., `./typed-templates.js`), not the project root.
Applied to files:
packages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-24T19:45:01.582Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-11-24T19:45:01.582Z
Learning: Applies to **/*.{ts,tsx,js} : Prefer barrel exports e.g. `export * from './foo.js'` instead of individual named exports
Applied to files:
packages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-24T19:45:01.582Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-11-24T19:45:01.582Z
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/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : If a particular interface or type is not exported, modify the file to export it
Applied to files:
packages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-01-23T09:12:46.178Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 428
File: packages/project-builder-server/src/sync/index.ts:5-5
Timestamp: 2025-01-23T09:12:46.178Z
Learning: Avoid importing directly from 'dist' directories. Instead, expose functionality through the package's public API and import from the main package entry point.
Applied to files:
packages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-24T19:45:01.582Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-11-24T19:45:01.582Z
Learning: Applies to **/*.{ts,tsx,js} : Node 16 module resolution - include file extensions in imports (`.js`)
Applied to files:
packages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-24T19:45:01.582Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-11-24T19:45:01.582Z
Learning: Applies to **/*.{ts,tsx} : Include absolute paths in import statements via tsconfig paths (`src/` is the alias for `src/`)
Applied to files:
packages/project-builder-server/src/templates/create/index.ts
📚 Learning: 2025-07-12T19:56:08.559Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 606
File: plugins/plugin-auth/src/auth/core/generators/auth-apollo/auth-apollo.generator.ts:24-32
Timestamp: 2025-07-12T19:56:08.559Z
Learning: For generator functions and configuration object methods like those in createGeneratorTask, inferred return types are acceptable when the structure is clear from the implementation. ESLint rules handle enforcement of explicit return types where truly needed, so manual review for this is not necessary.
Applied to files:
packages/project-builder-server/src/templates/create/index.tspackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/registry.tspackages/project-builder-cli/src/commands/templates.ts
📚 Learning: 2025-11-24T19:44:18.133Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:44:18.133Z
Learning: Refer to AGENTS.md for detailed code guidelines
Applied to files:
AGENTS.md
📚 Learning: 2025-11-24T19:45:27.654Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-11-24T19:45:27.654Z
Learning: Applies to +(*.tsx|packages/project-builder-web/**/*.tsx|packages/ui-components/**/*.tsx) : Avoid using alternative icon libraries (lucide-react, heroicons, etc.); consult before using alternatives if icons are not available in `react-icons/md`
Applied to files:
AGENTS.md
📚 Learning: 2025-11-24T19:45:27.654Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-11-24T19:45:27.654Z
Learning: Applies to +(*.tsx|packages/project-builder-web/**/*.tsx|packages/ui-components/**/*.tsx) : Use icons from `react-icons/md` (Material Design icons) exclusively; import like `import { MdAdd, MdDelete } from 'react-icons/md'`
Applied to files:
AGENTS.md
📚 Learning: 2025-11-24T19:44:46.506Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:44:46.506Z
Learning: Write clean, consistent, well-defined code with reusable components
Applied to files:
AGENTS.md
📚 Learning: 2025-11-24T19:45:27.654Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/ui-rules.mdc:0-0
Timestamp: 2025-11-24T19:45:27.654Z
Learning: Applies to +(*.tsx|packages/project-builder-web/**/*.tsx|packages/ui-components/**/*.tsx) : Use Tailwind CSS utility classes exclusively for styling; avoid writing custom CSS classes
Applied to files:
AGENTS.md
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Follow task-based architecture for generators, use provider scopes for explicit wiring, leverage TypeScript rendering system for code generation, organize complex generation with Task Phases, and use Dynamic Tasks for data-driven generation
Applied to files:
AGENTS.mdpackages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/generators/create-generator.action.ts.claude/skills/modify-generated-code/SKILL.mdpackages/project-builder-server/src/templates/create/create-generator.tspackages/project-builder-server/src/actions/registry.tspackages/project-builder-cli/src/commands/templates.ts
📚 Learning: 2025-08-17T01:32:58.983Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 633
File: packages/project-builder-web/src/routes/admin-sections.$appKey/-components/columns/column-configs.ts:1-2
Timestamp: 2025-08-17T01:32:58.983Z
Learning: The project-builder-web package doesn't use ESM (ECMAScript modules), so .js extensions are not required in import statements, unlike other packages in the codebase that do use Node 16 ESM resolution.
Applied to files:
packages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Tasks should have `run` (initialization) and `build` (code generation) phases, export and consume providers, and may be organized into phases for ordered execution
Applied to files:
packages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/templates/create/create-generator.ts
📚 Learning: 2025-07-30T13:27:20.000Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 623
File: plugins/plugin-auth/src/local-auth/core/generators/react-session/templates/src/app/user-session-provider.tsx:6-12
Timestamp: 2025-07-30T13:27:20.000Z
Learning: Ignore ESLint import ordering rules for files in templates/** directories as these are code generation templates, not direct source code.
Applied to files:
packages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-07-16T17:15:56.714Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 613
File: packages/react-generators/src/generators/core/react-components/templates/components/ui/circular-progress/circular-progress.tsx:0-0
Timestamp: 2025-07-16T17:15:56.714Z
Learning: For imports starting with `$` (template aliases), do not require `.js` extensions as these are resolved differently during the generation process, unlike regular file imports which require explicit `.js` extensions under Node 16 module resolution.
Applied to files:
packages/project-builder-server/src/actions/generators/index.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Use descriptive test names that explain what is being tested
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Test broad behavior and common edge cases intelligently to avoid slowing down CI with excessive tests
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Leverage TypeScript for type-safe mocking in tests
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Focus on testing public methods and behaviors, not implementation details
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Extract repeated logic into helper functions to reduce duplication
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Each test should verify one specific behavior
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.unit.test.{ts,tsx} : Unit tests are colocated with source files using `.unit.test.ts` suffix
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Each test should be independent and not rely on other tests
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : Structure tests with Arrange-Act-Assert: clear setup, execution, and verification phases
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-04-23T06:44:30.952Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 510
File: packages/project-builder-server/src/sync/conflict-file-monitor.test.ts:19-24
Timestamp: 2025-04-23T06:44:30.952Z
Learning: When testing file operations in this codebase, the pattern is to use Vitest automocks for 'node:fs' and 'node:fs/promises' (without explicit implementation replacement) while populating a virtual filesystem with vol.fromJSON() from memfs. File operations in tests are performed directly via vol.promises methods.
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-04-23T06:44:30.952Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 510
File: packages/project-builder-server/src/sync/conflict-file-monitor.test.ts:19-24
Timestamp: 2025-04-23T06:44:30.952Z
Learning: In this codebase, when testing file operations, Vitest's automocks for 'node:fs' and 'node:fs/promises' are used in conjunction with memfs, but without replacing the mock implementation explicitly in each test file. The virtual filesystem is populated using vol.fromJSON or similar methods, which works seamlessly with the automocks.
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:44:46.506Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/todo-with-auth0/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:44:46.506Z
Learning: Applies to examples/todo-with-auth0/**/*.{unit,int}.test.ts : Import test functions explicitly from 'vitest' instead of using globals. Example: `import { describe, expect, it } from 'vitest';`
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-04-23T06:44:30.952Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 510
File: packages/project-builder-server/src/sync/conflict-file-monitor.test.ts:19-24
Timestamp: 2025-04-23T06:44:30.952Z
Learning: In the project-builder-server test suite, Vitest automocks for 'node:fs' and 'node:fs/promises' are already configured to use memfs without needing explicit implementation replacement in each test file.
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:01.582Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/code-style.mdc:0-0
Timestamp: 2025-11-24T19:45:01.582Z
Learning: Applies to **/*.{unit.test.ts,int.test.ts} : Always import vitest globals explicitly (describe, it, expect)
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:44:33.994Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: examples/blog-with-auth/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:44:33.994Z
Learning: Applies to examples/blog-with-auth/**/*.test.ts : Import test functions explicitly from 'vitest' instead of relying on globals (e.g., `import { describe, expect, it } from 'vitest';`)
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.tspackages/project-builder-server/src/actions/index.ts
📚 Learning: 2025-06-30T11:52:28.745Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-06-30T11:52:28.745Z
Learning: Applies to **/*.test.{ts,tsx} : For file system operations in tests, use memfs and mock 'node:fs' and 'node:fs/promises' with vi.mock
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-24T19:45:19.136Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:45:19.136Z
Learning: Applies to **/*.{unit,int}.test.{ts,tsx} : For file system operations in tests, use memfs and mock `node:fs` and `node:fs/promises`
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts
📚 Learning: 2025-11-25T22:46:20.505Z
Learnt from: CR
Repo: halfdomelabs/baseplate PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T22:46:20.505Z
Learning: Applies to **/*.{ts,tsx} : Use Dynamic Tasks for data-driven generation where code generation is driven by data
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.ts
📚 Learning: 2025-07-07T18:24:17.522Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 592
File: plugins/plugin-auth/src/auth0/generators/react/auth0-hooks/templates/src/hooks/use-required-user-id.ts:1-2
Timestamp: 2025-07-07T18:24:17.522Z
Learning: Files under templates/** directories can use `// ts-nocheck` because they are templates meant for code generation, not direct type checking.
Applied to files:
packages/project-builder-server/src/templates/create/create-generator.ts
📚 Learning: 2025-08-17T01:38:07.205Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 633
File: plugins/plugin-auth/src/local-auth/admin/generators/admin-crud-manage-roles-action/templates/routes/-components/role-manager-dialog.tsx:116-121
Timestamp: 2025-08-17T01:38:07.205Z
Learning: Generator templates in plugin directories (e.g., plugins/plugin-*/src/*/generators/*/templates/**) do not require CSS class prefixes, unlike direct plugin components that need prefixing to avoid style conflicts.
Applied to files:
packages/project-builder-server/src/actions/registry.ts
📚 Learning: 2025-05-08T12:56:59.222Z
Learnt from: kingston
Repo: halfdomelabs/baseplate PR: 539
File: scripts/check-changesets.ts:10-13
Timestamp: 2025-05-08T12:56:59.222Z
Learning: Node.js 22.0.0 and later versions include both `glob` and `globSync` functionality in the core `node:fs` module, making `import { promises as fs, globSync } from 'node:fs';` valid syntax.
Applied to files:
packages/project-builder-server/src/actions/index.ts
🧬 Code graph analysis (5)
packages/project-builder-server/src/actions/generators/create-generator.action.ts (3)
packages/project-builder-server/src/actions/types.ts (1)
createServiceAction(68-75)packages/project-builder-server/src/templates/create/create-generator.ts (1)
createGenerator(143-243)packages/project-builder-server/src/actions/generators/index.ts (1)
createGenerator(2-2)
packages/project-builder-server/src/templates/create/create-generator.unit.test.ts (1)
packages/project-builder-server/src/templates/create/create-generator.ts (1)
createGenerator(143-243)
packages/project-builder-server/src/templates/create/create-generator.ts (2)
packages/sync/src/utils/parse-generator-name.ts (1)
parseGeneratorName(28-41)packages/project-builder-server/src/utils/find-monorepo-root.ts (1)
findMonorepoRoot(8-23)
packages/project-builder-server/src/actions/registry.ts (1)
packages/project-builder-server/src/actions/generators/create-generator.action.ts (1)
createGeneratorAction(38-71)
packages/project-builder-cli/src/commands/templates.ts (1)
packages/project-builder-server/src/templates/create/create-generator.ts (1)
createGenerator(143-243)
🪛 LanguageTool
.claude/skills/modify-generated-code/SKILL.md
[style] ~455-~455: Consider a different adjective to strengthen your wording.
Context: ... around it. These issues often indicate deeper problems that need proper resolution. ...
(DEEP_PROFOUND)
⏰ 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
- GitHub Check: Lint
- GitHub Check: Test E2E
🔇 Additional comments (15)
packages/project-builder-server/src/actions/index.ts (1)
2-2: LGTM!The barrel export follows coding guidelines correctly: uses barrel export pattern, includes .js extension for Node 16 module resolution, and is alphabetically ordered.
packages/project-builder-server/src/actions/generators/create-generator.action.ts (2)
61-70: Add explicit return type annotation to writeCliOutput function.The writeCliOutput function is missing a return type annotation. Add
: voidto align with coding guidelines.🔎 Proposed fix
- writeCliOutput: (output) => { + writeCliOutput: (output): void => { console.info(`✅ ${output.message}`);As per coding guidelines, **/*.{ts,tsx}: Always include return types on top-level functions.
⛔ Skipped due to learnings
Learnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: examples/todo-with-auth0/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:44:46.506Z Learning: Applies to examples/todo-with-auth0/**/*.{ts,tsx} : Always specify explicit return types for functionsLearnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: examples/blog-with-auth/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:44:33.994Z Learning: Applies to examples/blog-with-auth/**/*.{ts,tsx} : Always specify explicit return types for functions in TypeScriptLearnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: .cursor/rules/code-style.mdc:0-0 Timestamp: 2025-11-24T19:45:01.582Z Learning: Applies to **/*.{ts,tsx} : Always include return types on top-level functions including React components (`React.ReactElement`)Learnt from: kingston Repo: halfdomelabs/baseplate PR: 608 File: plugins/plugin-storage/src/storage/core/schema/migrations.ts:81-81 Timestamp: 2025-07-14T12:21:10.898Z Learning: Do not flag missing explicit return types in manual reviews since ESLint rules are configured to handle return type enforcement automatically.Learnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: examples/todo-with-auth0/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:44:46.506Z Learning: Applies to examples/todo-with-auth0/**/*.{ts,tsx} : Add JSDocs to all exported functions, interfaces, and classes with documentation of the function, its parameters, return value, and all fields
45-60: Add explicit return type annotation to handler function.The handler function is missing a return type annotation. According to coding guidelines, top-level functions should always include return types.
🔎 Proposed fix
- handler: async (input, context) => { + handler: async (input, context): Promise<z.infer<typeof createGeneratorOutputSchema>> => { const { name, directory, includeTemplates } = input;As per coding guidelines, **/*.{ts,tsx}: Always include return types on top-level functions.
⛔ Skipped due to learnings
Learnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-25T22:46:20.505Z Learning: Applies to **/*.{ts,tsx} : Create generators using `createGenerator` with configuration via descriptor schema (Zod), organizing into one or more tasks created with `createGeneratorTask`Learnt from: kingston Repo: halfdomelabs/baseplate PR: 606 File: plugins/plugin-auth/src/auth/core/generators/auth-apollo/auth-apollo.generator.ts:24-32 Timestamp: 2025-07-12T19:56:08.559Z Learning: For generator functions and configuration object methods like those in createGeneratorTask, inferred return types are acceptable when the structure is clear from the implementation. ESLint rules handle enforcement of explicit return types where truly needed, so manual review for this is not necessary.Learnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-25T22:46:20.505Z Learning: Follow task-based architecture for generators, use provider scopes for explicit wiring, leverage TypeScript rendering system for code generation, organize complex generation with Task Phases, and use Dynamic Tasks for data-driven generationLearnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-25T22:46:20.505Z Learning: Applies to **/*.{ts,tsx} : Tasks should have `run` (initialization) and `build` (code generation) phases, export and consume providers, and may be organized into phases for ordered executionLearnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: examples/todo-with-auth0/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:44:46.506Z Learning: Applies to examples/todo-with-auth0/**/*.{ts,tsx} : Always specify explicit return types for functionsLearnt from: CR Repo: halfdomelabs/baseplate PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-25T22:46:20.505Z Learning: Applies to **/*.{ts,tsx} : Use Dynamic Tasks for data-driven generation where code generation is driven by datapackages/project-builder-server/src/actions/registry.ts (1)
2-2: LGTM!The integration of
createGeneratorActioninto the registry follows the established pattern and uses the correct import conventions with the.jsextension.Also applies to: 31-31
packages/project-builder-server/src/templates/create/index.ts (1)
1-1: LGTM!The barrel export follows the established pattern and coding guidelines correctly.
.changeset/add-create-generator-action.md (1)
1-6: LGTM!The changeset properly documents both affected packages with appropriate patch versions and provides a clear description of the feature addition.
packages/project-builder-server/src/actions/generators/index.ts (1)
1-2: LGTM!The exports correctly follow the barrel pattern and use appropriate conventions (
.jsextensions and tsconfig path aliases).packages/project-builder-cli/src/commands/templates.ts (2)
28-30: LGTM!The
CreateGeneratorOptionsinterface follows the established pattern for other option interfaces in this file.
114-132: LGTM!The create subcommand registration follows the established pattern with appropriate command structure, description, and option handling.
packages/project-builder-server/src/templates/create/create-generator.ts (6)
1-26: LGTM!The imports and type definitions follow the coding guidelines correctly, including the
.jsextension for local imports and appropriate use of exported interfaces.
44-80: LGTM!The generated boilerplate follows the established generator pattern with task-based architecture. The references to generated content will intentionally cause type errors until templates are properly set up, which is a good fail-fast mechanism.
85-88: LGTM!The barrel export generation is correct and follows the coding guidelines.
93-114: LGTM!Both the placeholder generated content and extractor JSON generation are correct. The
nevertype in the placeholder is intentional to ensure developers run template generation before using the generator.
119-138: LGTM!The category index update logic correctly handles both new and existing index files, avoids duplicate exports, and maintains proper formatting.
143-243: LGTM!The
createGeneratorfunction is well-structured with proper:
- Directory resolution and validation
- Duplicate detection to prevent overwriting
- Conditional template setup based on
includeTemplatesflag- Category index management with duplicate prevention
- Best-effort Prettier formatting
- Comprehensive result tracking
The logic correctly handles both absolute and relative paths, creates necessary directory structures, and tracks created files for reporting.
| function parseGeneratorName(name: string): ParsedGeneratorName { | ||
| const [category, kebabName] = name.split('/'); | ||
| return { | ||
| category, | ||
| kebabName, | ||
| camelCaseName: camelCase(kebabName), | ||
| screamingSnakeName: constantCase(kebabName), | ||
| }; | ||
| } |
There was a problem hiding this comment.
Add input validation for generator name format.
The function doesn't validate that name contains a / separator. If a name like "my-generator" is passed (without a category), kebabName will be undefined, causing camelCase and constantCase to produce unexpected results and breaking file generation.
🔎 Proposed fix
function parseGeneratorName(name: string): ParsedGeneratorName {
const [category, kebabName] = name.split('/');
+
+ if (!category || !kebabName) {
+ throw new Error(
+ `Invalid generator name format: "${name}". Expected format: "category/kebab-name"`,
+ );
+ }
+
return {
category,
kebabName,
camelCaseName: camelCase(kebabName),
screamingSnakeName: constantCase(kebabName),
};
}🤖 Prompt for AI Agents
In packages/project-builder-server/src/templates/create/create-generator.ts
around lines 31 to 39, the parseGeneratorName function assumes the input
includes a '/' and doesn't validate parts; update it to verify the name contains
a single '/' and both category and kebabName are non-empty before using
camelCase/constantCase, and throw a clear, descriptive Error (e.g. "Invalid
generator name, expected '<category>/<kebab-name>'") when validation fails so
callers don't proceed with undefined values.
| while (currentDir !== root) { | ||
| const workspacePath = path.join(currentDir, 'pnpm-workspace.yaml'); | ||
| if (fs.existsSync(workspacePath)) { | ||
| return currentDir; | ||
| } | ||
| currentDir = path.dirname(currentDir); | ||
| } | ||
|
|
||
| return undefined; |
There was a problem hiding this comment.
Fix loop logic to check filesystem root.
The current loop condition while (currentDir !== root) prevents checking for pnpm-workspace.yaml at the filesystem root. If a workspace file exists at root (e.g., /pnpm-workspace.yaml), it will never be detected.
🔎 Proposed fix
- while (currentDir !== root) {
+ while (true) {
const workspacePath = path.join(currentDir, 'pnpm-workspace.yaml');
if (fs.existsSync(workspacePath)) {
return currentDir;
}
+ if (currentDir === root) {
+ break;
+ }
currentDir = path.dirname(currentDir);
}This ensures we check the current directory before deciding to stop, including the filesystem root.
🤖 Prompt for AI Agents
In packages/project-builder-server/src/utils/find-monorepo-root.ts around lines
14 to 22, the loop `while (currentDir !== root)` never checks the filesystem
root directory for pnpm-workspace.yaml; change the loop to check the current
directory first (e.g., use a do/while or while(true) that tests workspacePath in
currentDir), then after the check set currentDir = path.dirname(currentDir) and
break/return undefined when currentDir no longer changes (i.e., when parent ===
currentDir) to ensure the root directory is inspected before exiting.
Summary by CodeRabbit
New Features
Documentation
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.