@swovohq/fuel 0.2.2-alpha.92 → 0.2.2-alpha.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +107 -11
  2. package/dist/bin/fuel.js +61 -0
  3. package/dist/bin/fuel.js.map +1 -1
  4. package/dist/commands/generate-module.d.ts +7 -0
  5. package/dist/commands/generate-module.d.ts.map +1 -0
  6. package/dist/commands/generate-module.js +180 -0
  7. package/dist/commands/generate-module.js.map +1 -0
  8. package/dist/generators/module/index.d.ts +7 -0
  9. package/dist/generators/module/index.d.ts.map +1 -0
  10. package/dist/generators/module/index.js +86 -0
  11. package/dist/generators/module/index.js.map +1 -0
  12. package/dist/generators/module/register.d.ts +4 -0
  13. package/dist/generators/module/register.d.ts.map +1 -0
  14. package/dist/generators/module/register.js +124 -0
  15. package/dist/generators/module/register.js.map +1 -0
  16. package/dist/generators/module/render.d.ts +10 -0
  17. package/dist/generators/module/render.d.ts.map +1 -0
  18. package/dist/generators/module/render.js +19 -0
  19. package/dist/generators/module/render.js.map +1 -0
  20. package/dist/generators/module/skill.d.ts +3 -0
  21. package/dist/generators/module/skill.d.ts.map +1 -0
  22. package/dist/generators/module/skill.js +223 -0
  23. package/dist/generators/module/skill.js.map +1 -0
  24. package/dist/generators/module/templates/api.d.ts +14 -0
  25. package/dist/generators/module/templates/api.d.ts.map +1 -0
  26. package/dist/generators/module/templates/api.js +363 -0
  27. package/dist/generators/module/templates/api.js.map +1 -0
  28. package/dist/generators/module/templates/types-pkg.d.ts +7 -0
  29. package/dist/generators/module/templates/types-pkg.d.ts.map +1 -0
  30. package/dist/generators/module/templates/types-pkg.js +56 -0
  31. package/dist/generators/module/templates/types-pkg.js.map +1 -0
  32. package/dist/generators/module/templates/web.d.ts +16 -0
  33. package/dist/generators/module/templates/web.d.ts.map +1 -0
  34. package/dist/generators/module/templates/web.js +573 -0
  35. package/dist/generators/module/templates/web.js.map +1 -0
  36. package/package.json +1 -1
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerInAppModule = registerInAppModule;
37
+ exports.registerWebTypesDependency = registerWebTypesDependency;
38
+ const fs = __importStar(require("fs-extra"));
39
+ const path = __importStar(require("path"));
40
+ async function registerInAppModule(projectRoot, vars, withAdmin) {
41
+ const appModulePath = path.join(projectRoot, 'apps', 'api', 'src', 'app.module.ts');
42
+ if (!(await fs.pathExists(appModulePath))) {
43
+ throw new Error(`app.module.ts not found at ${appModulePath}`);
44
+ }
45
+ let content = await fs.readFile(appModulePath, 'utf-8');
46
+ const moduleName = `${vars.pascal}Module`;
47
+ const adminModuleName = `Admin${vars.pascal}Module`;
48
+ const importPath = `./${vars.kebab}/${vars.kebab}.module`;
49
+ const adminImportPath = `./${vars.kebab}/admin-${vars.kebab}.module`;
50
+ const insertImport = (src, importLine) => {
51
+ const lastImportMatch = [...src.matchAll(/^import\s[\s\S]*?;$/gm)].pop();
52
+ if (!lastImportMatch || lastImportMatch.index === undefined)
53
+ return src + '\n' + importLine;
54
+ const insertAt = lastImportMatch.index + lastImportMatch[0].length;
55
+ return src.slice(0, insertAt) + '\n' + importLine + src.slice(insertAt);
56
+ };
57
+ const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
58
+ // Matches the name inside any brace-delimited import list from the given
59
+ // path, not just a standalone `{ Name }` import, so a pre-existing
60
+ // multi-name import (e.g. `{ FooModule, DashboardModule }`) isn't missed.
61
+ // Commented-out import lines are ignored, and aliased specifiers (`Foo as
62
+ // Bar`) don't count as importing `Foo` since the local binding differs.
63
+ const hasNamedImport = (src, name, fromPath) => {
64
+ const importRe = new RegExp(`import\\s*\\{([^}]*)\\}\\s*from\\s*['"]${escapeRegExp(fromPath)}['"]`, 'g');
65
+ let match;
66
+ while ((match = importRe.exec(src)) !== null) {
67
+ const lineStart = src.lastIndexOf('\n', match.index) + 1;
68
+ const linePrefix = src.slice(lineStart, match.index);
69
+ if (linePrefix.trimStart().startsWith('//'))
70
+ continue;
71
+ const specifiers = match[1].split(',').map((s) => s.trim()).filter(Boolean);
72
+ if (specifiers.includes(name))
73
+ return true;
74
+ }
75
+ return false;
76
+ };
77
+ if (!hasNamedImport(content, moduleName, importPath)) {
78
+ content = insertImport(content, `import { ${moduleName} } from '${importPath}';`);
79
+ }
80
+ if (withAdmin && !hasNamedImport(content, adminModuleName, adminImportPath)) {
81
+ content = insertImport(content, `import { ${adminModuleName} } from '${adminImportPath}';`);
82
+ }
83
+ // Insert into imports array before OptionalApiModulesModule.forRoot()
84
+ const anchor = 'OptionalApiModulesModule.forRoot()';
85
+ if (!content.includes(anchor)) {
86
+ throw new Error(`Could not find "${anchor}" in app.module.ts. Register ${moduleName}${withAdmin ? ` and ${adminModuleName}` : ''} in the imports array manually.`);
87
+ }
88
+ if (!content.includes(`${moduleName},`)) {
89
+ content = content.replace(anchor, `${moduleName},\n ${anchor}`);
90
+ }
91
+ if (withAdmin && !content.includes(`${adminModuleName},`)) {
92
+ content = content.replace(anchor, `${adminModuleName},\n ${anchor}`);
93
+ }
94
+ await fs.writeFile(appModulePath, content, 'utf-8');
95
+ }
96
+ function isPackageManifest(value) {
97
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
98
+ return false;
99
+ const deps = value.dependencies;
100
+ if (deps === undefined)
101
+ return true;
102
+ if (typeof deps !== 'object' || deps === null || Array.isArray(deps))
103
+ return false;
104
+ return Object.values(deps).every((v) => typeof v === 'string');
105
+ }
106
+ async function registerWebTypesDependency(projectRoot, vars) {
107
+ const webPackageJsonPath = path.join(projectRoot, 'apps', 'web', 'package.json');
108
+ if (!(await fs.pathExists(webPackageJsonPath))) {
109
+ throw new Error(`package.json not found at ${webPackageJsonPath}`);
110
+ }
111
+ const content = await fs.readFile(webPackageJsonPath, 'utf-8');
112
+ const depName = `@fuel/${vars.kebab}-types`;
113
+ const parsed = JSON.parse(content);
114
+ if (!isPackageManifest(parsed)) {
115
+ throw new Error(`Invalid package.json at ${webPackageJsonPath}: expected an object with a "dependencies" object of string values.`);
116
+ }
117
+ const pkg = parsed;
118
+ if (pkg.dependencies?.[depName]) {
119
+ return;
120
+ }
121
+ pkg.dependencies = { ...pkg.dependencies, [depName]: '*' };
122
+ await fs.writeFile(webPackageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf-8');
123
+ }
124
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../../src/generators/module/register.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ModuleVars {
2
+ pascal: string;
3
+ camel: string;
4
+ kebab: string;
5
+ upper: string;
6
+ }
7
+ export declare function render(template: string, vars: ModuleVars): string;
8
+ /** Expects an already-normalized kebab-case name (see `validateName` in generate-module.ts). */
9
+ export declare function toModuleVars(kebab: string): ModuleVars;
10
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/generators/module/render.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAMjE;AAED,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAKtD"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.render = render;
4
+ exports.toModuleVars = toModuleVars;
5
+ function render(template, vars) {
6
+ return template
7
+ .replaceAll('__MODULE_PASCAL__', vars.pascal)
8
+ .replaceAll('__MODULE_CAMEL__', vars.camel)
9
+ .replaceAll('__MODULE_KEBAB__', vars.kebab)
10
+ .replaceAll('__MODULE_UPPER__', vars.upper);
11
+ }
12
+ /** Expects an already-normalized kebab-case name (see `validateName` in generate-module.ts). */
13
+ function toModuleVars(kebab) {
14
+ const camel = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
15
+ const pascal = camel.charAt(0).toUpperCase() + camel.slice(1);
16
+ const upper = kebab.replace(/-/g, '_').toUpperCase();
17
+ return { pascal, camel, kebab, upper };
18
+ }
19
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/generators/module/render.ts"],"names":[],"mappings":";;AAOA,wBAMC;AAGD,oCAKC;AAdD,SAAgB,MAAM,CAAC,QAAgB,EAAE,IAAgB;IACvD,OAAO,QAAQ;SACZ,UAAU,CAAC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC;SAC5C,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC;SAC1C,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC;SAC1C,UAAU,CAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;AAC/C,CAAC;AAED,gGAAgG;AAChG,SAAgB,YAAY,CAAC,KAAa;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;IAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IACpD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AACxC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ModuleVars } from './render';
2
+ export declare function updateSkill(projectRoot: string, vars: ModuleVars, _withAdmin: boolean): Promise<void>;
3
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../../src/generators/module/skill.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAuKlD,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.updateSkill = updateSkill;
37
+ const fs = __importStar(require("fs-extra"));
38
+ const path = __importStar(require("path"));
39
+ const render_1 = require("./render");
40
+ const MODULES_END_MARKER = '<!-- FUEL_MODULES_END -->';
41
+ const moduleEntryTemplate = `### __MODULE_PASCAL__ (\`__MODULE_KEBAB__\`)
42
+
43
+ Generated by \`fuel generate:module __MODULE_KEBAB__\`.
44
+
45
+ **API Layer** (\`apps/api/src/__MODULE_KEBAB__/\`):
46
+
47
+ | File | Purpose |
48
+ |---|---|
49
+ | \`__MODULE_KEBAB__.module.ts\` | NestJS \`@Module\` — registers TypeORM entity, service, repository, controller |
50
+ | \`__MODULE_KEBAB__.controller.ts\` | REST endpoints: GET list, GET :id, POST, PUT :id, DELETE :id |
51
+ | \`__MODULE_KEBAB__.service.ts\` | Business logic — delegates to repository, throws typed exceptions |
52
+ | \`__MODULE_KEBAB__.repository.ts\` | TypeORM data access — wraps \`Repository<__MODULE_PASCAL__Item>\` |
53
+ | \`entities/__MODULE_KEBAB__-item.entity.ts\` | TypeORM entity: \`id\`, \`name\`, \`organizationId\`, timestamps |
54
+ | \`dto/create-__MODULE_KEBAB__.dto.ts\` | Create DTO with class-validator decorators |
55
+ | \`dto/update-__MODULE_KEBAB__.dto.ts\` | \`PartialType(Create__MODULE_PASCAL__Dto)\` |
56
+ | \`dto/__MODULE_KEBAB__-list-query.dto.ts\` | Pagination + search + sort query params |
57
+ | \`exceptions/__MODULE_KEBAB__-exceptions.ts\` | \`__MODULE_PASCAL__ItemNotFoundException extends NotFoundException\` |
58
+
59
+ **Web Layer** (\`apps/web/src/\`):
60
+
61
+ | File | Purpose |
62
+ |---|---|
63
+ | \`api/__MODULE_KEBAB__.ts\` | Typed fetch functions: Get/Create/Update/Delete endpoints |
64
+ | \`hooks/__MODULE_KEBAB__/use-__MODULE_KEBAB__-items.ts\` | \`useQuery\` list hook with pagination/search/sort |
65
+ | \`hooks/__MODULE_KEBAB__/use-create-__MODULE_KEBAB__-item.ts\` | \`useMutation\` create hook with cache invalidation |
66
+ | \`hooks/__MODULE_KEBAB__/use-delete-__MODULE_KEBAB__-item.ts\` | \`useMutation\` delete hook with cache invalidation |
67
+ | \`components/__MODULE_KEBAB__/__MODULE_KEBAB__-context.tsx\` | React context — TanStack Table + URL-synced state via nuqs |
68
+ | \`components/__MODULE_KEBAB__/__MODULE_KEBAB__-table.tsx\` | Client component consuming context |
69
+ | \`components/__MODULE_KEBAB__/create-__MODULE_KEBAB__-item-drawer.tsx\` | react-hook-form + zod create form |
70
+ | \`components/__MODULE_KEBAB__/index.ts\` | Barrel exports |
71
+ | \`app/(dashboard)/__MODULE_KEBAB__/page.tsx\` | Next.js server component page |
72
+ | \`app/(dashboard)/__MODULE_KEBAB__/layout.tsx\` | Layout wrapper |
73
+ | \`app/(dashboard)/__MODULE_KEBAB__/__MODULE_KEBAB__-client-layout.tsx\` | Client layout with \`ContextProvider\` |
74
+
75
+ **Types Package** (\`packages/types/__MODULE_KEBAB__/\`):
76
+
77
+ | File | Purpose |
78
+ |---|---|
79
+ | \`src/types.ts\` | \`__MODULE_PASCAL__Item\` interface, Create/Update input types |
80
+ | \`src/index.ts\` | Barrel export |
81
+
82
+ **NestJS Registration**: \`__MODULE_PASCAL__Module\` auto-registered in \`apps/api/src/app.module.ts\`.`;
83
+ const fullSkillTemplate = `# Fuel Module Skill
84
+
85
+ You are an expert in the Fuel full-stack monorepo module pattern. When a developer asks
86
+ you to work on, explain, or extend a generated Fuel module, use the architectural reference
87
+ below to guide your answers.
88
+
89
+ Always follow the exact file naming, import paths, and code patterns described here. Never
90
+ introduce patterns that don't match what is documented.
91
+
92
+ ---
93
+
94
+ ## Generated Modules in This Project
95
+
96
+ ${moduleEntryTemplate}
97
+
98
+ ${MODULES_END_MARKER}
99
+
100
+ ---
101
+
102
+ ## Architectural Patterns
103
+
104
+ ### API (NestJS) Patterns
105
+
106
+ **Endpoint decoration stack** (read operations):
107
+ \`\`\`typescript
108
+ @UseGuards(BetterAuthOrganizationRolesGuard)
109
+ @SecuredEndpoint(HttpStatus.OK)
110
+ @Get()
111
+ \`\`\`
112
+
113
+ **Endpoint decoration stack** (write operations — require org admin):
114
+ \`\`\`typescript
115
+ @UseGuards(BetterAuthOrganizationRolesGuard)
116
+ @RequireOrganizationAdmin()
117
+ @SecuredEndpoint(HttpStatus.OK)
118
+ @Put(':id')
119
+ \`\`\`
120
+
121
+ **Service pattern:** thin orchestration — delegates to repository, throws typed exceptions.
122
+
123
+ **Repository pattern:** wraps TypeORM \`Repository<T>\`, uses \`createQueryBuilder\` for
124
+ filtered queries, \`addPaginationToQuery\` + \`getPaginatedResult\` from
125
+ \`src/common/utils/pagination\` for pagination.
126
+
127
+ **DTO pattern:** \`class-validator\` decorators + \`@ApiProperty\` for Swagger.
128
+ Update DTOs use \`PartialType\` from \`@nestjs/swagger\`.
129
+
130
+ **Exception pattern:**
131
+ \`\`\`typescript
132
+ export class ItemNotFoundException extends NotFoundException {
133
+ constructor() { super('Item not found.') }
134
+ }
135
+ \`\`\`
136
+
137
+ ---
138
+
139
+ ### Web (Next.js) Patterns
140
+
141
+ **API endpoint pattern** (\`apps/web/src/api/*.ts\`):
142
+ \`\`\`typescript
143
+ export const GetItemsEndpoint = async (
144
+ payload: { client: typeof fetch } & PaginationOptions
145
+ ): Promise<PaginatedResponse<Item>> => {
146
+ // build URLSearchParams, call client(), return handleResponse()
147
+ }
148
+ \`\`\`
149
+
150
+ **Hook pattern** (\`apps/web/src/hooks/*/\`):
151
+ \`\`\`typescript
152
+ export const useItems = (opts) => {
153
+ const query = useQuery({ queryKey: ['key', opts], queryFn: ... })
154
+ return {
155
+ itemsState: { isLoading, isError, error, data },
156
+ refetchItems: query.refetch,
157
+ }
158
+ }
159
+ \`\`\`
160
+
161
+ **Context pattern** (\`apps/web/src/components/*/\`):
162
+ \`\`\`typescript
163
+ export const ContextProvider = ({ children }) => {
164
+ // useQueryState from nuqs for URL-synced page/limit/search/sort
165
+ // useReactTable from @tanstack/react-table
166
+ // expose via Context.Provider
167
+ }
168
+ export const useModuleContext = () => { /* guard + return */ }
169
+ \`\`\`
170
+
171
+ **Query key convention:** \`'{module-name}-items'\` (kebab-case, \`-items\` suffix).
172
+
173
+ **URL query param convention:** \`{moduleCamel}_page\`, \`{moduleCamel}_limit\`,
174
+ \`{moduleCamel}_q\`, \`{moduleCamel}_sort\`.
175
+
176
+ ---
177
+
178
+ ## Common Extension Tasks
179
+
180
+ ### Add a new field to the entity
181
+ 1. Add \`@Column()\` to \`apps/api/src/{module}/entities/{module}-item.entity.ts\`
182
+ 2. Add field to \`packages/types/{module}/src/types.ts\`
183
+ 3. Add to \`dto/create-{module}.dto.ts\` (with validator) — update DTO inherits via \`PartialType\`
184
+ 4. Generate a migration: \`yarn workspace api database:migration:generate\`
185
+ 5. Run it: \`yarn workspace api database:migration:run\`
186
+
187
+ ### Add a new API endpoint
188
+ 1. Add method to \`apps/api/src/{module}/{module}.service.ts\`
189
+ 2. Add route to \`apps/api/src/{module}/{module}.controller.ts\` using the decoration stack above
190
+ 3. Add fetch function to \`apps/web/src/api/{module}.ts\`
191
+ 4. Add React Query hook in \`apps/web/src/hooks/{module}/\`
192
+
193
+ ### Add a table column
194
+ Add to the \`columns: ColumnDef<Item>[]\` array in
195
+ \`apps/web/src/components/{module}/{module}-context.tsx\`.
196
+
197
+ ### Replace the placeholder form with the design system Drawer
198
+ Replace the plain HTML form in \`create-{module}-item-drawer.tsx\` with the \`Drawer\`
199
+ component from \`@fuel/design-system\`. Follow the pattern in
200
+ \`apps/web/src/components/teams/invitations/invite-member-drawer.tsx\`.
201
+ `;
202
+ async function updateSkill(projectRoot, vars, _withAdmin) {
203
+ const skillDir = path.join(projectRoot, '.claude', 'skills', 'fuel-module');
204
+ const skillPath = path.join(skillDir, 'SKILL.md');
205
+ if (!(await fs.pathExists(skillPath))) {
206
+ await fs.ensureDir(skillDir);
207
+ await fs.writeFile(skillPath, (0, render_1.render)(fullSkillTemplate, vars), 'utf-8');
208
+ return;
209
+ }
210
+ let content = await fs.readFile(skillPath, 'utf-8');
211
+ // Skip if module section already present
212
+ if (content.includes(`\`${vars.kebab}\``))
213
+ return;
214
+ const newSection = (0, render_1.render)(moduleEntryTemplate, vars);
215
+ if (content.includes(MODULES_END_MARKER)) {
216
+ content = content.replace(MODULES_END_MARKER, `${newSection}\n\n${MODULES_END_MARKER}`);
217
+ }
218
+ else {
219
+ content += `\n\n${newSection}`;
220
+ }
221
+ await fs.writeFile(skillPath, content, 'utf-8');
222
+ }
223
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../../src/generators/module/skill.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyKA,kCA+BC;AAxMD,6CAA8B;AAC9B,2CAA4B;AAC5B,qCAAkD;AAElD,MAAM,kBAAkB,GAAG,2BAA2B,CAAA;AAEtD,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wGAyC4E,CAAA;AAExG,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;EAaxB,mBAAmB;;EAEnB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuGnB,CAAA;AAEM,KAAK,UAAU,WAAW,CAC/B,WAAmB,EACnB,IAAgB,EAChB,UAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAA;IAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IAEjD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QAC5B,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAA,eAAM,EAAC,iBAAiB,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAA;QACvE,OAAM;IACR,CAAC;IAED,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAEnD,yCAAyC;IACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;QAAE,OAAM;IAEjD,MAAM,UAAU,GAAG,IAAA,eAAM,EAAC,mBAAmB,EAAE,IAAI,CAAC,CAAA;IAEpD,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACzC,OAAO,GAAG,OAAO,CAAC,OAAO,CACvB,kBAAkB,EAClB,GAAG,UAAU,OAAO,kBAAkB,EAAE,CACzC,CAAA;IACH,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,OAAO,UAAU,EAAE,CAAA;IAChC,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACjD,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare const apiTemplates: {
2
+ module: string;
3
+ controller: string;
4
+ service: string;
5
+ repository: string;
6
+ entity: string;
7
+ dtoCreate: string;
8
+ dtoUpdate: string;
9
+ dtoListQuery: string;
10
+ exceptions: string;
11
+ adminController: string;
12
+ adminModule: string;
13
+ };
14
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/generators/module/templates/api.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;;;;;;;;;;CAgXxB,CAAA"}