domain-driver 0.1.0 → 0.3.0

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 (85) hide show
  1. package/README.md +159 -145
  2. package/dist/cli.js +208 -0
  3. package/dist/commands/action.js +118 -0
  4. package/dist/commands/component.js +18 -19
  5. package/dist/commands/container.js +10 -31
  6. package/dist/commands/controller.js +85 -0
  7. package/dist/commands/feature.js +59 -51
  8. package/dist/commands/hints.js +28 -0
  9. package/dist/commands/hook.js +10 -111
  10. package/dist/commands/repository.js +17 -115
  11. package/dist/commands/resolve.js +61 -0
  12. package/dist/commands/schema.js +22 -69
  13. package/dist/commands/service.js +15 -113
  14. package/dist/commands/sides.js +34 -0
  15. package/dist/commands/target.js +32 -0
  16. package/dist/commands/types.js +9 -17
  17. package/dist/commands/update.js +148 -0
  18. package/dist/commands/write.js +66 -0
  19. package/dist/index.js +8 -122
  20. package/dist/init/content.js +73 -0
  21. package/dist/init/init.js +66 -0
  22. package/dist/init/markers.js +21 -0
  23. package/dist/postinstall.js +80 -0
  24. package/dist/stack/detect.js +125 -0
  25. package/dist/stack/profiles/nest.js +18 -0
  26. package/dist/stack/profiles/next-frontend.js +28 -0
  27. package/dist/stack/profiles/next-fullstack.js +44 -0
  28. package/dist/stack/profiles/node.js +17 -0
  29. package/dist/stack/profiles/react.js +19 -0
  30. package/dist/stack/registry.js +63 -0
  31. package/dist/stack/types.js +24 -0
  32. package/dist/templates/actions.js +68 -0
  33. package/dist/templates/backend/server-repository.js +22 -0
  34. package/dist/templates/context.js +52 -0
  35. package/dist/templates/controllers/express.js +60 -0
  36. package/dist/templates/controllers/fastify.js +54 -0
  37. package/dist/templates/controllers/generic.js +30 -0
  38. package/dist/templates/controllers/hono.js +52 -0
  39. package/dist/templates/controllers/nest.js +63 -0
  40. package/dist/templates/controllers/next-action-route.js +40 -0
  41. package/dist/templates/controllers/next-route.js +62 -0
  42. package/dist/templates/controllers/node.js +46 -0
  43. package/dist/templates/controllers/shape.js +28 -0
  44. package/dist/templates/frontend/client-repository.js +38 -0
  45. package/dist/templates/frontend/component.js +18 -0
  46. package/dist/templates/frontend/container.js +28 -0
  47. package/{src/commands/hook.ts → dist/templates/frontend/hook.js} +28 -41
  48. package/dist/templates/frontend/page.js +26 -0
  49. package/dist/templates/nest/dto.js +12 -0
  50. package/dist/templates/nest/injectable.js +4 -0
  51. package/dist/templates/nest/module.js +41 -0
  52. package/dist/templates/service.js +40 -0
  53. package/dist/templates/shared/schema.js +13 -0
  54. package/dist/templates/shared/types.js +12 -0
  55. package/dist/templates/signatures.js +15 -0
  56. package/dist/update/cache.js +80 -0
  57. package/dist/update/check.js +47 -0
  58. package/dist/update/install-mode.js +96 -0
  59. package/dist/update/package-manager.js +99 -0
  60. package/dist/update/registry.js +77 -0
  61. package/dist/update/version.js +70 -0
  62. package/dist/utils/alias.js +80 -0
  63. package/dist/utils/fs.js +70 -0
  64. package/dist/utils/imports.js +61 -0
  65. package/dist/utils/naming.js +31 -0
  66. package/dist/utils/paths.js +44 -0
  67. package/package.json +27 -6
  68. package/scripts/postinstall.js +7 -0
  69. package/.github/workflows/publish.yml +0 -28
  70. package/dist/utils.js +0 -132
  71. package/src/__tests__/utils.test.ts +0 -128
  72. package/src/commands/__tests__/feature.test.ts +0 -85
  73. package/src/commands/__tests__/imports.test.ts +0 -115
  74. package/src/commands/__tests__/individual.test.ts +0 -137
  75. package/src/commands/component.ts +0 -33
  76. package/src/commands/container.ts +0 -42
  77. package/src/commands/feature.ts +0 -74
  78. package/src/commands/repository.ts +0 -95
  79. package/src/commands/schema.ts +0 -47
  80. package/src/commands/service.ts +0 -93
  81. package/src/commands/types.ts +0 -25
  82. package/src/index.ts +0 -126
  83. package/src/utils.ts +0 -115
  84. package/tsconfig.json +0 -13
  85. package/vitest.config.ts +0 -7
@@ -0,0 +1,118 @@
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.parseReturns = parseReturns;
37
+ exports.makeAction = makeAction;
38
+ const path = __importStar(require("path"));
39
+ const registry_1 = require("../stack/registry");
40
+ const actions_1 = require("../templates/actions");
41
+ const server_repository_1 = require("../templates/backend/server-repository");
42
+ const nest_1 = require("../templates/controllers/nest");
43
+ const next_action_route_1 = require("../templates/controllers/next-action-route");
44
+ const node_1 = require("../templates/controllers/node");
45
+ const client_repository_1 = require("../templates/frontend/client-repository");
46
+ const dto_1 = require("../templates/nest/dto");
47
+ const service_1 = require("../templates/service");
48
+ const schema_1 = require("../templates/shared/schema");
49
+ const fs_1 = require("../utils/fs");
50
+ const naming_1 = require("../utils/naming");
51
+ const paths_1 = require("../utils/paths");
52
+ const hints_1 = require("./hints");
53
+ const resolve_1 = require("./resolve");
54
+ const write_1 = require("./write");
55
+ function parseReturns(value) {
56
+ if (actions_1.RETURN_KINDS.includes(value))
57
+ return value;
58
+ throw new Error(`Invalid --returns "${value}". Use list, one, or void.`);
59
+ }
60
+ function makeAction(feature, entity, actionName, options) {
61
+ const ctx = (0, resolve_1.requireFeature)(feature);
62
+ const spec = (0, actions_1.customAction)(entity, actionName, options);
63
+ hintMissingTypes(ctx, entity);
64
+ let wroteAny = false;
65
+ if (spec.schema !== null)
66
+ wroteAny = writeInput(ctx, spec) || wroteAny;
67
+ if ((0, registry_1.hasLayer)(ctx.profile, 'serverRepository'))
68
+ wroteAny = writeSide(ctx, spec, entity, 'server') || wroteAny;
69
+ if ((0, registry_1.hasLayer)(ctx.profile, 'controller'))
70
+ wroteAny = writeController(ctx, spec, entity) || wroteAny;
71
+ if ((0, registry_1.hasLayer)(ctx.profile, 'clientRepository'))
72
+ wroteAny = writeSide(ctx, spec, entity, 'client') || wroteAny;
73
+ if (wroteAny)
74
+ console.log(`✅ Action "${spec.name}" scaffolded in "${feature}"`);
75
+ return wroteAny;
76
+ }
77
+ function hintMissingTypes(ctx, entity) {
78
+ const typesFile = path.join(ctx.featureDir, (0, registry_1.layerDir)(ctx.profile, 'types'), `${entity}.types.ts`);
79
+ if ((0, fs_1.fileExists)(typesFile))
80
+ return;
81
+ console.log(`ℹ️ types/${entity}.types.ts not found. Run: domain-driver make:types ${ctx.feature}/${entity}`);
82
+ }
83
+ function writeInput(ctx, spec) {
84
+ const schemaFile = path.join((0, resolve_1.ensureLayerDir)(ctx, 'schema'), `${spec.name}.schema.ts`);
85
+ const wroteSchema = (0, write_1.writeIfAbsent)(schemaFile, () => (0, schema_1.renderSchema)(spec.name, (0, naming_1.lowerFirst)(spec.name)));
86
+ if (!(0, registry_1.hasLayer)(ctx.profile, 'dto'))
87
+ return wroteSchema;
88
+ const dtoFile = path.join((0, resolve_1.ensureLayerDir)(ctx, 'dto'), `${spec.name}.dto.ts`);
89
+ const wroteDto = (0, write_1.writeIfAbsent)(dtoFile, () => (0, dto_1.renderDto)(ctx, spec.name, dtoFile));
90
+ (0, hints_1.hintNestjsZod)(ctx.stack);
91
+ return wroteSchema || wroteDto;
92
+ }
93
+ function writeSide(ctx, spec, entity, side) {
94
+ const repositoryLayer = side === 'client' ? 'clientRepository' : 'serverRepository';
95
+ const serviceLayer = side === 'client' ? 'clientService' : 'serverService';
96
+ const renderRepository = side === 'client' ? client_repository_1.renderClientRepository : server_repository_1.renderServerRepository;
97
+ const repositoryFile = path.join((0, resolve_1.ensureLayerDir)(ctx, repositoryLayer), `${spec.name}.repository.ts`);
98
+ const wroteRepository = (0, write_1.writeIfAbsent)(repositoryFile, () => renderRepository(ctx, spec, entity, repositoryFile));
99
+ const serviceFile = path.join((0, resolve_1.ensureLayerDir)(ctx, serviceLayer), `${spec.name}.service.ts`);
100
+ const wroteService = (0, write_1.writeIfAbsent)(serviceFile, () => (0, service_1.renderService)(ctx, spec, entity, serviceFile, side));
101
+ return wroteRepository || wroteService;
102
+ }
103
+ function writeController(ctx, spec, entity) {
104
+ if (ctx.profile.name === 'next-fullstack') {
105
+ const routeDir = path.join((0, paths_1.apiRouteDir)(ctx.stack, ctx.feature), spec.path.slice(1));
106
+ (0, fs_1.mkdirSafe)(routeDir);
107
+ const routeFile = path.join(routeDir, 'route.ts');
108
+ return (0, write_1.writeIfAbsent)(routeFile, () => (0, next_action_route_1.renderActionRoute)(ctx, spec, routeFile));
109
+ }
110
+ const controllerFile = path.join((0, resolve_1.ensureLayerDir)(ctx, 'controller'), `${spec.name}.controller.ts`);
111
+ const render = ctx.profile.name === 'nest' ? nest_1.renderNestController : node_1.renderNodeController;
112
+ const wroteController = (0, write_1.writeIfAbsent)(controllerFile, () => render(ctx, spec, entity, controllerFile));
113
+ const line = ctx.profile.name === 'node' ? (0, node_1.renderNodeRouteLine)(ctx, spec, entity) : null;
114
+ if (wroteController && line !== null) {
115
+ console.log(`ℹ️ Add to ${ctx.feature}.routes.ts above the '/:id' routes: ${line}`);
116
+ }
117
+ return wroteController;
118
+ }
@@ -33,30 +33,29 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseComponentType = parseComponentType;
36
37
  exports.makeComponent = makeComponent;
37
38
  const path = __importStar(require("path"));
38
- const utils_1 = require("../utils");
39
- function renderComponent(name, type) {
40
- const directive = type === 'client' ? "'use client';\n\n" : '';
41
- return `${directive}interface ${name}Props {
42
- id: string;
43
- }
44
-
45
- export default function ${name}({ id }: ${name}Props) {
46
- return (
47
- <div>
48
- <h1>${name}</h1>
49
- </div>
50
- );
51
- }
52
- `;
39
+ const registry_1 = require("../stack/registry");
40
+ const component_1 = require("../templates/frontend/component");
41
+ const fs_1 = require("../utils/fs");
42
+ const resolve_1 = require("./resolve");
43
+ function parseComponentType(value) {
44
+ return value === 'server' ? 'server' : 'client';
53
45
  }
54
46
  function makeComponent(feature, name, type = 'client') {
55
- const base = (0, utils_1.ensureFeatureExists)(feature, `components/${type}`);
56
- const filePath = path.join(base, `${name}.tsx`);
57
- if ((0, utils_1.fileExists)(filePath)) {
47
+ const ctx = (0, resolve_1.requireFeature)(feature);
48
+ (0, registry_1.assertLayer)(ctx.profile, 'component', 'make:component');
49
+ if (type === 'server' && !ctx.profile.serverComponents) {
50
+ throw new Error(`The ${ctx.profile.name} stack has no server components.`);
51
+ }
52
+ const dir = path.join(ctx.featureDir, (0, registry_1.componentDir)(ctx.profile, type));
53
+ (0, fs_1.mkdirSafe)(dir);
54
+ const filePath = path.join(dir, `${name}.tsx`);
55
+ if ((0, fs_1.fileExists)(filePath)) {
58
56
  throw new Error(`Component "${name}" already exists at ${filePath}`);
59
57
  }
60
- (0, utils_1.writeFileSafe)(filePath, renderComponent(name, type));
58
+ const directive = type === 'client' && ctx.profile.clientDirective;
59
+ (0, fs_1.writeFileSafe)(filePath, (0, component_1.renderComponent)(name, directive));
61
60
  console.log(`✅ Component "${name}" created at ${filePath}`);
62
61
  }
@@ -35,39 +35,18 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.makeContainer = makeContainer;
37
37
  const path = __importStar(require("path"));
38
- const utils_1 = require("../utils");
39
- function renderContainer(containerName, name, feature) {
40
- const hookName = `use${name}`;
41
- const hookPath = (0, utils_1.resolveImport)(feature, `hooks/${hookName}`);
42
- const componentPath = (0, utils_1.resolveImport)(feature, `components/client/${name}`);
43
- return `'use client';
44
-
45
- import { ${hookName} } from '${hookPath}';
46
- import ${name} from '${componentPath}';
47
-
48
- export default function ${containerName}() {
49
- const { items, loading, error } = ${hookName}();
50
-
51
- if (loading) return <div>Loading...</div>;
52
- if (error) return <div>Error: {error}</div>;
53
-
54
- return (
55
- <div>
56
- {items.map((item) => (
57
- <${name} key={item.id} {...item} />
58
- ))}
59
- </div>
60
- );
61
- }
62
- `;
63
- }
38
+ const registry_1 = require("../stack/registry");
39
+ const container_1 = require("../templates/frontend/container");
40
+ const fs_1 = require("../utils/fs");
41
+ const resolve_1 = require("./resolve");
64
42
  function makeContainer(feature, name, pascalName) {
65
- const base = (0, utils_1.ensureFeatureExists)(feature, 'containers');
66
- const filePath = path.join(base, `${name}.tsx`);
67
- if ((0, utils_1.fileExists)(filePath)) {
43
+ const ctx = (0, resolve_1.requireFeature)(feature);
44
+ (0, registry_1.assertLayer)(ctx.profile, 'container', 'make:container');
45
+ const filePath = path.join((0, resolve_1.ensureLayerDir)(ctx, 'container'), `${name}.tsx`);
46
+ if ((0, fs_1.fileExists)(filePath)) {
68
47
  throw new Error(`Container "${name}" already exists at ${filePath}`);
69
48
  }
70
- const entityName = pascalName ?? name.replace(/Container$/, '');
71
- (0, utils_1.writeFileSafe)(filePath, renderContainer(name, entityName, feature));
49
+ const entity = pascalName ?? name.replace(/Container$/, '');
50
+ (0, fs_1.writeFileSafe)(filePath, (0, container_1.renderContainer)(ctx, name, entity, filePath));
72
51
  console.log(`✅ Container "${name}" created at ${filePath}`);
73
52
  }
@@ -0,0 +1,85 @@
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.makeController = makeController;
37
+ const path = __importStar(require("path"));
38
+ const registry_1 = require("../stack/registry");
39
+ const actions_1 = require("../templates/actions");
40
+ const nest_1 = require("../templates/controllers/nest");
41
+ const next_route_1 = require("../templates/controllers/next-route");
42
+ const node_1 = require("../templates/controllers/node");
43
+ const fs_1 = require("../utils/fs");
44
+ const paths_1 = require("../utils/paths");
45
+ const resolve_1 = require("./resolve");
46
+ const write_1 = require("./write");
47
+ function makeController(feature, name) {
48
+ const ctx = (0, resolve_1.requireFeature)(feature);
49
+ (0, registry_1.assertLayer)(ctx.profile, 'controller', 'make:controller');
50
+ if (ctx.profile.name === 'next-fullstack') {
51
+ return writeNextRoutes(ctx, name);
52
+ }
53
+ const dir = (0, resolve_1.ensureLayerDir)(ctx, 'controller');
54
+ const render = ctx.profile.name === 'nest' ? nest_1.renderNestController : node_1.renderNodeController;
55
+ const written = (0, write_1.writeSpecFiles)(dir, (0, actions_1.standardActions)(name), 'controller', (spec, filePath) => render(ctx, spec, name, filePath));
56
+ if (written > 0)
57
+ console.log(`✅ Controllers for "${name}" created at ${dir}`);
58
+ const wroteRoutes = ctx.profile.name === 'node' ? writeNodeRoutes(ctx, name) : false;
59
+ return written > 0 || wroteRoutes;
60
+ }
61
+ function writeNodeRoutes(ctx, name) {
62
+ const filePath = path.join(ctx.featureDir, `${ctx.feature}.routes.ts`);
63
+ const content = (0, node_1.renderNodeRoutes)(ctx, name, filePath);
64
+ if (content === null) {
65
+ console.log('ℹ️ No HTTP framework detected, generating framework-agnostic controllers.');
66
+ return false;
67
+ }
68
+ const wrote = (0, write_1.writeIfAbsent)(filePath, () => content);
69
+ if (wrote)
70
+ console.log(`✅ Routes for "${name}" created at ${filePath}`);
71
+ return wrote;
72
+ }
73
+ function writeNextRoutes(ctx, name) {
74
+ const collectionDir = (0, paths_1.apiRouteDir)(ctx.stack, ctx.feature);
75
+ const itemDir = path.join(collectionDir, '[id]');
76
+ (0, fs_1.mkdirSafe)(itemDir);
77
+ const collectionFile = path.join(collectionDir, 'route.ts');
78
+ const itemFile = path.join(itemDir, 'route.ts');
79
+ const wroteCollection = (0, write_1.writeIfAbsent)(collectionFile, () => (0, next_route_1.renderCollectionRoute)(ctx, name, collectionFile));
80
+ const wroteItem = (0, write_1.writeIfAbsent)(itemFile, () => (0, next_route_1.renderItemRoute)(ctx, name, itemFile));
81
+ const wroteAny = wroteCollection || wroteItem;
82
+ if (wroteAny)
83
+ console.log(`✅ Route handlers for "${name}" created at ${collectionDir}`);
84
+ return wroteAny;
85
+ }
@@ -35,64 +35,72 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.makeFeature = makeFeature;
37
37
  const path = __importStar(require("path"));
38
- const utils_1 = require("../utils");
38
+ const registry_1 = require("../stack/registry");
39
+ const page_1 = require("../templates/frontend/page");
40
+ const module_1 = require("../templates/nest/module");
41
+ const fs_1 = require("../utils/fs");
42
+ const naming_1 = require("../utils/naming");
39
43
  const component_1 = require("./component");
44
+ const container_1 = require("./container");
45
+ const controller_1 = require("./controller");
40
46
  const hook_1 = require("./hook");
41
- const service_1 = require("./service");
42
47
  const repository_1 = require("./repository");
48
+ const resolve_1 = require("./resolve");
43
49
  const schema_1 = require("./schema");
44
- const container_1 = require("./container");
50
+ const service_1 = require("./service");
45
51
  const types_1 = require("./types");
46
- const FEATURE_DIRS = [
47
- 'components/server',
48
- 'components/client',
49
- 'containers',
50
- 'hooks',
51
- 'services',
52
- 'repositories',
53
- 'schemas',
54
- 'types',
55
- ];
56
- function renderPage(name, pascalName) {
57
- const containerPath = (0, utils_1.resolveImport)(name, `containers/${pascalName}Container`, true);
58
- return `import ${pascalName}Container from '${containerPath}';
59
-
60
- export default function ${pascalName}Page() {
61
- return (
62
- <div>
63
- <${pascalName}Container />
64
- </div>
65
- );
66
- }
67
- `;
68
- }
69
- async function makeFeature(name, all = false) {
70
- const base = (0, utils_1.featureBasePath)(name);
71
- const pascalName = (0, utils_1.toPascalCase)(name);
72
- if ((0, utils_1.fileExists)(base)) {
73
- throw new Error(`Feature "${name}" already exists at ${base}`);
52
+ async function makeFeature(name, all = false, entityName) {
53
+ const ctx = (0, resolve_1.resolveFeature)(name);
54
+ if ((0, fs_1.fileExists)(ctx.featureDir)) {
55
+ throw new Error(`Feature "${name}" already exists at ${ctx.featureDir}`);
74
56
  }
75
- for (const dir of FEATURE_DIRS) {
76
- (0, utils_1.mkdirSafe)(path.join(base, dir));
77
- if (!all) {
78
- (0, utils_1.writeFileSafe)(path.join(base, dir, '.gitkeep'), '');
79
- }
80
- }
81
- if (all) {
82
- (0, utils_1.writeFileSafe)(path.join(base, 'page.tsx'), renderPage(name, pascalName));
57
+ const entity = entityName ?? (0, naming_1.toPascalCase)(name);
58
+ createFolders(ctx, all);
59
+ console.log(`✅ Feature "${name}" scaffolded at ${ctx.featureDir}`);
60
+ if (all)
61
+ scaffoldLayers(ctx, entity);
62
+ writeEntryFile(ctx, entity, all);
63
+ if (all)
64
+ console.log(`✅ All files scaffolded for "${name}"`);
65
+ }
66
+ function createFolders(ctx, all) {
67
+ for (const folder of ctx.profile.folders) {
68
+ const dir = path.join(ctx.featureDir, folder);
69
+ (0, fs_1.mkdirSafe)(dir);
70
+ if (!all)
71
+ (0, fs_1.writeFileSafe)(path.join(dir, '.gitkeep'), '');
83
72
  }
84
- else {
85
- (0, utils_1.writeFileSafe)(path.join(base, 'page.tsx'), `export default function ${pascalName}Page() {\n return (\n <div>\n <h1>${pascalName}</h1>\n </div>\n );\n}\n`);
73
+ }
74
+ function scaffoldLayers(ctx, entity) {
75
+ const { feature, profile } = ctx;
76
+ if ((0, registry_1.hasLayer)(profile, 'types'))
77
+ (0, types_1.makeTypes)(feature, entity);
78
+ if ((0, registry_1.hasLayer)(profile, 'schema'))
79
+ (0, schema_1.makeSchema)(feature, entity);
80
+ if ((0, registry_1.hasLayer)(profile, 'serverRepository'))
81
+ (0, repository_1.makeRepository)(feature, entity, 'server');
82
+ if ((0, registry_1.hasLayer)(profile, 'serverService'))
83
+ (0, service_1.makeService)(feature, entity, 'server');
84
+ if ((0, registry_1.hasLayer)(profile, 'controller'))
85
+ (0, controller_1.makeController)(feature, entity);
86
+ if ((0, registry_1.hasLayer)(profile, 'clientRepository'))
87
+ (0, repository_1.makeRepository)(feature, entity, 'client');
88
+ if ((0, registry_1.hasLayer)(profile, 'clientService'))
89
+ (0, service_1.makeService)(feature, entity, 'client');
90
+ if ((0, registry_1.hasLayer)(profile, 'hook'))
91
+ (0, hook_1.makeHook)(feature, `use${entity}`, entity);
92
+ if ((0, registry_1.hasLayer)(profile, 'component'))
93
+ (0, component_1.makeComponent)(feature, entity, 'client');
94
+ if ((0, registry_1.hasLayer)(profile, 'container'))
95
+ (0, container_1.makeContainer)(feature, `${entity}Container`, entity);
96
+ }
97
+ function writeEntryFile(ctx, entity, all) {
98
+ if ((0, registry_1.hasLayer)(ctx.profile, 'page')) {
99
+ const filePath = path.join(ctx.featureDir, 'page.tsx');
100
+ (0, fs_1.writeFileSafe)(filePath, (0, page_1.renderPage)(ctx, entity, filePath, all));
86
101
  }
87
- console.log(`✅ Feature "${name}" scaffolded at ${base}`);
88
- if (all) {
89
- (0, types_1.makeTypes)(name, pascalName);
90
- (0, schema_1.makeSchema)(name, pascalName);
91
- (0, repository_1.makeRepository)(name, pascalName);
92
- (0, service_1.makeService)(name, pascalName);
93
- (0, hook_1.makeHook)(name, `use${pascalName}`, pascalName);
94
- (0, component_1.makeComponent)(name, pascalName, 'client');
95
- (0, container_1.makeContainer)(name, `${pascalName}Container`, pascalName);
96
- console.log(`✅ All files scaffolded for "${name}"`);
102
+ if ((0, registry_1.hasLayer)(ctx.profile, 'module')) {
103
+ const filePath = path.join(ctx.featureDir, `${ctx.feature}.module.ts`);
104
+ (0, fs_1.writeFileSafe)(filePath, (0, module_1.renderModule)(ctx, entity, filePath, all));
97
105
  }
98
106
  }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resetHints = resetHints;
4
+ exports.hintNestjsZod = hintNestjsZod;
5
+ exports.standardClassNames = standardClassNames;
6
+ exports.hintRegisterInModule = hintRegisterInModule;
7
+ const detect_1 = require("../stack/detect");
8
+ const actions_1 = require("../templates/actions");
9
+ let nestjsZodHinted = false;
10
+ function resetHints() {
11
+ nestjsZodHinted = false;
12
+ }
13
+ function hintNestjsZod(stack) {
14
+ if (stack.stack !== 'nest' || stack.hasNestjsZod || nestjsZodHinted)
15
+ return;
16
+ nestjsZodHinted = true;
17
+ console.log('ℹ️ nestjs-zod is not installed. Run: npm install nestjs-zod');
18
+ console.log(' Then register the pipe in AppModule: { provide: APP_PIPE, useClass: ZodValidationPipe }');
19
+ }
20
+ function standardClassNames(name, suffix) {
21
+ return actions_1.ACTIONS.map((action) => `${action}${name}${suffix}`);
22
+ }
23
+ function hintRegisterInModule(feature, classNames, note) {
24
+ if ((0, detect_1.detectStack)().stack !== 'nest')
25
+ return;
26
+ const suffix = note !== undefined ? ` (${note})` : '';
27
+ console.log(`ℹ️ Register ${classNames.join(', ')} in ${feature}.module.ts${suffix}`);
28
+ }
@@ -35,119 +35,18 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.makeHook = makeHook;
37
37
  const path = __importStar(require("path"));
38
- const utils_1 = require("../utils");
39
- function renderHook(hookName, name, feature) {
40
- const typePath = (0, utils_1.resolveImport)(feature, `types/${name}.types`);
41
- const svcPath = (op) => (0, utils_1.resolveImport)(feature, `services/${op}${name}.service`);
42
- const schemaPath = (op) => (0, utils_1.resolveImport)(feature, `schemas/${op}${name}.schema`);
43
- return `'use client';
44
-
45
- import { useState, useEffect, useCallback } from 'react';
46
- import { ${name} } from '${typePath}';
47
- import { List${name}Service } from '${svcPath('List')}';
48
- import { Show${name}Service } from '${svcPath('Show')}';
49
- import { Create${name}Service } from '${svcPath('Create')}';
50
- import { Update${name}Service } from '${svcPath('Update')}';
51
- import { Delete${name}Service } from '${svcPath('Delete')}';
52
- import { Create${name} } from '${schemaPath('Create')}';
53
- import { Update${name} } from '${schemaPath('Update')}';
54
-
55
- const listService = new List${name}Service();
56
- const showService = new Show${name}Service();
57
- const createService = new Create${name}Service();
58
- const updateService = new Update${name}Service();
59
- const deleteService = new Delete${name}Service();
60
-
61
- export function ${hookName}() {
62
- const [items, setItems] = useState<${name}[]>([]);
63
- const [selected, setSelected] = useState<${name} | null>(null);
64
- const [loading, setLoading] = useState(false);
65
- const [error, setError] = useState<string | null>(null);
66
-
67
- const fetchAll = useCallback(async () => {
68
- setLoading(true);
69
- setError(null);
70
- try {
71
- const data = await listService.handle();
72
- setItems(data);
73
- } catch (err: unknown) {
74
- setError(err instanceof Error ? err.message : 'Failed to fetch');
75
- } finally {
76
- setLoading(false);
77
- }
78
- }, []);
79
-
80
- const fetchOne = useCallback(async (id: string) => {
81
- setLoading(true);
82
- setError(null);
83
- try {
84
- const data = await showService.handle(id);
85
- setSelected(data);
86
- } catch (err: unknown) {
87
- setError(err instanceof Error ? err.message : 'Failed to fetch');
88
- } finally {
89
- setLoading(false);
90
- }
91
- }, []);
92
-
93
- const create = useCallback(async (data: Create${name}) => {
94
- setLoading(true);
95
- setError(null);
96
- try {
97
- const created = await createService.handle(data);
98
- setItems((prev) => [...prev, created]);
99
- return created;
100
- } catch (err: unknown) {
101
- setError(err instanceof Error ? err.message : 'Failed to create');
102
- return null;
103
- } finally {
104
- setLoading(false);
105
- }
106
- }, []);
107
-
108
- const update = useCallback(async (id: string, data: Update${name}) => {
109
- setLoading(true);
110
- setError(null);
111
- try {
112
- const updated = await updateService.handle(id, data);
113
- setItems((prev) => prev.map((item) => (item.id === id ? updated : item)));
114
- return updated;
115
- } catch (err: unknown) {
116
- setError(err instanceof Error ? err.message : 'Failed to update');
117
- return null;
118
- } finally {
119
- setLoading(false);
120
- }
121
- }, []);
122
-
123
- const remove = useCallback(async (id: string) => {
124
- setLoading(true);
125
- setError(null);
126
- try {
127
- await deleteService.handle(id);
128
- setItems((prev) => prev.filter((item) => item.id !== id));
129
- } catch (err: unknown) {
130
- setError(err instanceof Error ? err.message : 'Failed to delete');
131
- } finally {
132
- setLoading(false);
133
- }
134
- }, []);
135
-
136
- useEffect(() => {
137
- fetchAll();
138
- }, [fetchAll]);
139
-
140
- return { items, selected, loading, error, fetchAll, fetchOne, create, update, remove };
141
- }
142
- `;
143
- }
38
+ const registry_1 = require("../stack/registry");
39
+ const hook_1 = require("../templates/frontend/hook");
40
+ const fs_1 = require("../utils/fs");
41
+ const resolve_1 = require("./resolve");
144
42
  function makeHook(feature, name, pascalName) {
145
- const base = (0, utils_1.ensureFeatureExists)(feature, 'hooks');
146
- const filePath = path.join(base, `${name}.ts`);
147
- if ((0, utils_1.fileExists)(filePath)) {
43
+ const ctx = (0, resolve_1.requireFeature)(feature);
44
+ (0, registry_1.assertLayer)(ctx.profile, 'hook', 'make:hook');
45
+ const filePath = path.join((0, resolve_1.ensureLayerDir)(ctx, 'hook'), `${name}.ts`);
46
+ if ((0, fs_1.fileExists)(filePath)) {
148
47
  throw new Error(`Hook "${name}" already exists at ${filePath}`);
149
48
  }
150
- const entityName = pascalName ?? name.replace(/^use/, '');
151
- (0, utils_1.writeFileSafe)(filePath, renderHook(name, entityName, feature));
49
+ const entity = pascalName ?? name.replace(/^use/, '');
50
+ (0, fs_1.writeFileSafe)(filePath, (0, hook_1.renderHook)(ctx, name, entity, filePath));
152
51
  console.log(`✅ Hook "${name}" created at ${filePath}`);
153
52
  }