domain-driver 0.0.4 → 0.1.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.
- package/README.md +173 -28
- package/dist/commands/component.js +62 -0
- package/dist/commands/container.js +73 -0
- package/dist/commands/feature.js +41 -14
- package/dist/commands/hook.js +153 -0
- package/dist/commands/repository.js +121 -0
- package/dist/commands/schema.js +74 -0
- package/dist/commands/service.js +119 -0
- package/dist/commands/types.js +57 -0
- package/dist/index.js +121 -12
- package/dist/utils.js +132 -0
- package/package.json +10 -9
- package/src/__tests__/utils.test.ts +128 -0
- package/src/commands/__tests__/feature.test.ts +85 -0
- package/src/commands/__tests__/imports.test.ts +115 -0
- package/src/commands/__tests__/individual.test.ts +137 -0
- package/src/commands/component.ts +33 -0
- package/src/commands/container.ts +42 -0
- package/src/commands/feature.ts +47 -15
- package/src/commands/hook.ts +122 -0
- package/src/commands/repository.ts +95 -0
- package/src/commands/schema.ts +47 -0
- package/src/commands/service.ts +93 -0
- package/src/commands/types.ts +25 -0
- package/src/index.ts +121 -11
- package/src/utils.ts +115 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,121 @@
|
|
|
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.makeRepository = makeRepository;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const utils_1 = require("../utils");
|
|
39
|
+
const REPOSITORY_ACTIONS = ['List', 'Create', 'Update', 'Delete', 'Show'];
|
|
40
|
+
function renderRepository(action, name, feature) {
|
|
41
|
+
const typePath = (0, utils_1.resolveImport)(feature, `types/${name}.types`);
|
|
42
|
+
const schemaPath = (op) => (0, utils_1.resolveImport)(feature, `schemas/${op}${name}.schema`);
|
|
43
|
+
switch (action) {
|
|
44
|
+
case 'List':
|
|
45
|
+
return `import { ${name} } from '${typePath}';
|
|
46
|
+
|
|
47
|
+
export class List${name}Repository {
|
|
48
|
+
async handle(): Promise<${name}[]> {
|
|
49
|
+
const response = await fetch('/api/${feature}');
|
|
50
|
+
if (!response.ok) throw new Error('Failed to fetch ${name} list');
|
|
51
|
+
return response.json();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
case 'Show':
|
|
56
|
+
return `import { ${name} } from '${typePath}';
|
|
57
|
+
|
|
58
|
+
export class Show${name}Repository {
|
|
59
|
+
async handle(id: string): Promise<${name}> {
|
|
60
|
+
const response = await fetch(\`/api/${feature}/\${id}\`);
|
|
61
|
+
if (!response.ok) throw new Error('Failed to fetch ${name}');
|
|
62
|
+
return response.json();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
case 'Create':
|
|
67
|
+
return `import { ${name} } from '${typePath}';
|
|
68
|
+
import { Create${name} } from '${schemaPath('Create')}';
|
|
69
|
+
|
|
70
|
+
export class Create${name}Repository {
|
|
71
|
+
async handle(data: Create${name}): Promise<${name}> {
|
|
72
|
+
const response = await fetch('/api/${feature}', {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: { 'Content-Type': 'application/json' },
|
|
75
|
+
body: JSON.stringify(data),
|
|
76
|
+
});
|
|
77
|
+
if (!response.ok) throw new Error('Failed to create ${name}');
|
|
78
|
+
return response.json();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
case 'Update':
|
|
83
|
+
return `import { ${name} } from '${typePath}';
|
|
84
|
+
import { Update${name} } from '${schemaPath('Update')}';
|
|
85
|
+
|
|
86
|
+
export class Update${name}Repository {
|
|
87
|
+
async handle(id: string, data: Update${name}): Promise<${name}> {
|
|
88
|
+
const response = await fetch(\`/api/${feature}/\${id}\`, {
|
|
89
|
+
method: 'PUT',
|
|
90
|
+
headers: { 'Content-Type': 'application/json' },
|
|
91
|
+
body: JSON.stringify(data),
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) throw new Error('Failed to update ${name}');
|
|
94
|
+
return response.json();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
98
|
+
case 'Delete':
|
|
99
|
+
return `export class Delete${name}Repository {
|
|
100
|
+
async handle(id: string): Promise<void> {
|
|
101
|
+
const response = await fetch(\`/api/${feature}/\${id}\`, {
|
|
102
|
+
method: 'DELETE',
|
|
103
|
+
});
|
|
104
|
+
if (!response.ok) throw new Error('Failed to delete ${name}');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function makeRepository(feature, name) {
|
|
111
|
+
const base = (0, utils_1.ensureFeatureExists)(feature, 'repositories');
|
|
112
|
+
for (const action of REPOSITORY_ACTIONS) {
|
|
113
|
+
const filePath = path.join(base, `${action}${name}.repository.ts`);
|
|
114
|
+
if ((0, utils_1.fileExists)(filePath)) {
|
|
115
|
+
console.warn(`⚠️ Skipping "${action}${name}.repository.ts" — already exists`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
(0, utils_1.writeFileSafe)(filePath, renderRepository(action, name, feature));
|
|
119
|
+
}
|
|
120
|
+
console.log(`✅ Repositories for "${name}" created at ${base}`);
|
|
121
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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.makeSchema = makeSchema;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const utils_1 = require("../utils");
|
|
39
|
+
const SCHEMA_ACTIONS = ['Create', 'Update'];
|
|
40
|
+
function renderSchema(action, name) {
|
|
41
|
+
switch (action) {
|
|
42
|
+
case 'Create':
|
|
43
|
+
return `import { z } from 'zod';
|
|
44
|
+
|
|
45
|
+
export const Create${name}Schema = z.object({
|
|
46
|
+
// add create fields here
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export type Create${name} = z.infer<typeof Create${name}Schema>;
|
|
50
|
+
`;
|
|
51
|
+
case 'Update':
|
|
52
|
+
return `import { z } from 'zod';
|
|
53
|
+
|
|
54
|
+
export const Update${name}Schema = z.object({
|
|
55
|
+
id: z.string(),
|
|
56
|
+
// add update fields here
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export type Update${name} = z.infer<typeof Update${name}Schema>;
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function makeSchema(feature, name) {
|
|
64
|
+
const base = (0, utils_1.ensureFeatureExists)(feature, 'schemas');
|
|
65
|
+
for (const action of SCHEMA_ACTIONS) {
|
|
66
|
+
const filePath = path.join(base, `${action}${name}.schema.ts`);
|
|
67
|
+
if ((0, utils_1.fileExists)(filePath)) {
|
|
68
|
+
console.warn(`⚠️ Skipping "${action}${name}.schema.ts" — already exists`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
(0, utils_1.writeFileSafe)(filePath, renderSchema(action, name));
|
|
72
|
+
}
|
|
73
|
+
console.log(`✅ Schemas for "${name}" created at ${base}`);
|
|
74
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
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.makeService = makeService;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const utils_1 = require("../utils");
|
|
39
|
+
const SERVICE_ACTIONS = ['List', 'Create', 'Update', 'Delete', 'Show'];
|
|
40
|
+
function renderService(action, name, feature) {
|
|
41
|
+
const typePath = (0, utils_1.resolveImport)(feature, `types/${name}.types`);
|
|
42
|
+
const repoPath = (op) => (0, utils_1.resolveImport)(feature, `repositories/${op}${name}.repository`);
|
|
43
|
+
const schemaPath = (op) => (0, utils_1.resolveImport)(feature, `schemas/${op}${name}.schema`);
|
|
44
|
+
switch (action) {
|
|
45
|
+
case 'List':
|
|
46
|
+
return `import { ${name} } from '${typePath}';
|
|
47
|
+
import { List${name}Repository } from '${repoPath('List')}';
|
|
48
|
+
|
|
49
|
+
const repository = new List${name}Repository();
|
|
50
|
+
|
|
51
|
+
export class List${name}Service {
|
|
52
|
+
async handle(): Promise<${name}[]> {
|
|
53
|
+
return repository.handle();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
case 'Show':
|
|
58
|
+
return `import { ${name} } from '${typePath}';
|
|
59
|
+
import { Show${name}Repository } from '${repoPath('Show')}';
|
|
60
|
+
|
|
61
|
+
const repository = new Show${name}Repository();
|
|
62
|
+
|
|
63
|
+
export class Show${name}Service {
|
|
64
|
+
async handle(id: string): Promise<${name}> {
|
|
65
|
+
return repository.handle(id);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
case 'Create':
|
|
70
|
+
return `import { ${name} } from '${typePath}';
|
|
71
|
+
import { Create${name} } from '${schemaPath('Create')}';
|
|
72
|
+
import { Create${name}Repository } from '${repoPath('Create')}';
|
|
73
|
+
|
|
74
|
+
const repository = new Create${name}Repository();
|
|
75
|
+
|
|
76
|
+
export class Create${name}Service {
|
|
77
|
+
async handle(data: Create${name}): Promise<${name}> {
|
|
78
|
+
return repository.handle(data);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
case 'Update':
|
|
83
|
+
return `import { ${name} } from '${typePath}';
|
|
84
|
+
import { Update${name} } from '${schemaPath('Update')}';
|
|
85
|
+
import { Update${name}Repository } from '${repoPath('Update')}';
|
|
86
|
+
|
|
87
|
+
const repository = new Update${name}Repository();
|
|
88
|
+
|
|
89
|
+
export class Update${name}Service {
|
|
90
|
+
async handle(id: string, data: Update${name}): Promise<${name}> {
|
|
91
|
+
return repository.handle(id, data);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
`;
|
|
95
|
+
case 'Delete':
|
|
96
|
+
return `import { Delete${name}Repository } from '${repoPath('Delete')}';
|
|
97
|
+
|
|
98
|
+
const repository = new Delete${name}Repository();
|
|
99
|
+
|
|
100
|
+
export class Delete${name}Service {
|
|
101
|
+
async handle(id: string): Promise<void> {
|
|
102
|
+
return repository.handle(id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function makeService(feature, name) {
|
|
109
|
+
const base = (0, utils_1.ensureFeatureExists)(feature, 'services');
|
|
110
|
+
for (const action of SERVICE_ACTIONS) {
|
|
111
|
+
const filePath = path.join(base, `${action}${name}.service.ts`);
|
|
112
|
+
if ((0, utils_1.fileExists)(filePath)) {
|
|
113
|
+
console.warn(`⚠️ Skipping "${action}${name}.service.ts" — already exists`);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
(0, utils_1.writeFileSafe)(filePath, renderService(action, name, feature));
|
|
117
|
+
}
|
|
118
|
+
console.log(`✅ Services for "${name}" created at ${base}`);
|
|
119
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
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.makeTypes = makeTypes;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const utils_1 = require("../utils");
|
|
39
|
+
function renderTypes(name) {
|
|
40
|
+
return `export interface ${name} {
|
|
41
|
+
id: string;
|
|
42
|
+
// add ${name} fields here
|
|
43
|
+
createdAt: string;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
function makeTypes(feature, name) {
|
|
49
|
+
const base = (0, utils_1.ensureFeatureExists)(feature, 'types');
|
|
50
|
+
const filePath = path.join(base, `${name}.types.ts`);
|
|
51
|
+
if ((0, utils_1.fileExists)(filePath)) {
|
|
52
|
+
console.warn(`⚠️ Skipping "${name}.types.ts" — already exists`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
(0, utils_1.writeFileSafe)(filePath, renderTypes(name));
|
|
56
|
+
console.log(`✅ Types for "${name}" created at ${filePath}`);
|
|
57
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,125 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
4
5
|
const feature_1 = require("./commands/feature");
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
const component_1 = require("./commands/component");
|
|
7
|
+
const hook_1 = require("./commands/hook");
|
|
8
|
+
const service_1 = require("./commands/service");
|
|
9
|
+
const schema_1 = require("./commands/schema");
|
|
10
|
+
const repository_1 = require("./commands/repository");
|
|
11
|
+
const container_1 = require("./commands/container");
|
|
12
|
+
const types_1 = require("./commands/types");
|
|
13
|
+
const program = new commander_1.Command();
|
|
14
|
+
program
|
|
15
|
+
.name('domain-driver')
|
|
16
|
+
.description('CLI scaffolding tool for domain-driven development in Next.js')
|
|
17
|
+
.version('0.1.0');
|
|
18
|
+
program
|
|
19
|
+
.command('make:feature <name>')
|
|
20
|
+
.description('Scaffold a full feature folder structure')
|
|
21
|
+
.option('-a, --all', 'Scaffold all files inside each folder')
|
|
22
|
+
.action(async (name, options) => {
|
|
23
|
+
try {
|
|
24
|
+
await (0, feature_1.makeFeature)(name, options.all ?? false);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
28
|
+
console.error(`❌ ${message}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
program
|
|
33
|
+
.command('make:component <feature> <name>')
|
|
34
|
+
.description('Scaffold a component inside an existing feature')
|
|
35
|
+
.argument('[type]', 'Component type: client or server', 'client')
|
|
36
|
+
.action((feature, name, type) => {
|
|
37
|
+
try {
|
|
38
|
+
const componentType = type === 'server' ? 'server' : 'client';
|
|
39
|
+
(0, component_1.makeComponent)(feature, name, componentType);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
43
|
+
console.error(`❌ ${message}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
program
|
|
48
|
+
.command('make:container <feature> <name>')
|
|
49
|
+
.description('Scaffold a smart container component inside an existing feature')
|
|
50
|
+
.action((feature, name) => {
|
|
51
|
+
try {
|
|
52
|
+
(0, container_1.makeContainer)(feature, name);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
56
|
+
console.error(`❌ ${message}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
program
|
|
61
|
+
.command('make:hook <feature> <name>')
|
|
62
|
+
.description('Scaffold a custom hook inside an existing feature')
|
|
63
|
+
.action((feature, name) => {
|
|
64
|
+
try {
|
|
65
|
+
(0, hook_1.makeHook)(feature, name);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
69
|
+
console.error(`❌ ${message}`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
program
|
|
74
|
+
.command('make:service <feature> <name>')
|
|
75
|
+
.description('Scaffold single-responsibility service files inside an existing feature')
|
|
76
|
+
.action((feature, name) => {
|
|
77
|
+
try {
|
|
78
|
+
(0, service_1.makeService)(feature, name);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
82
|
+
console.error(`❌ ${message}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
program
|
|
87
|
+
.command('make:repository <feature> <name>')
|
|
88
|
+
.description('Scaffold single-responsibility repository files inside an existing feature')
|
|
89
|
+
.action((feature, name) => {
|
|
90
|
+
try {
|
|
91
|
+
(0, repository_1.makeRepository)(feature, name);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
95
|
+
console.error(`❌ ${message}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
program
|
|
100
|
+
.command('make:schema <feature> <name>')
|
|
101
|
+
.description('Scaffold Zod schemas for create and update operations')
|
|
102
|
+
.action((feature, name) => {
|
|
103
|
+
try {
|
|
104
|
+
(0, schema_1.makeSchema)(feature, name);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
108
|
+
console.error(`❌ ${message}`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
program
|
|
113
|
+
.command('make:types <feature> <name>')
|
|
114
|
+
.description('Scaffold a types file inside an existing feature')
|
|
115
|
+
.action((feature, name) => {
|
|
116
|
+
try {
|
|
117
|
+
(0, types_1.makeTypes)(feature, name);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
121
|
+
console.error(`❌ ${message}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
program.parse();
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
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.toPascalCase = toPascalCase;
|
|
37
|
+
exports.featureBasePath = featureBasePath;
|
|
38
|
+
exports.ensureFeatureExists = ensureFeatureExists;
|
|
39
|
+
exports.writeFileSafe = writeFileSafe;
|
|
40
|
+
exports.mkdirSafe = mkdirSafe;
|
|
41
|
+
exports.fileExists = fileExists;
|
|
42
|
+
exports.detectAlias = detectAlias;
|
|
43
|
+
exports.resetAliasCache = resetAliasCache;
|
|
44
|
+
exports.resolveImport = resolveImport;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
function toPascalCase(name) {
|
|
48
|
+
return name
|
|
49
|
+
.split('-')
|
|
50
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
51
|
+
.join('');
|
|
52
|
+
}
|
|
53
|
+
function featureBasePath(feature) {
|
|
54
|
+
return path.join(process.cwd(), 'app', feature);
|
|
55
|
+
}
|
|
56
|
+
function ensureFeatureExists(feature, subdir) {
|
|
57
|
+
const base = path.join(featureBasePath(feature), subdir);
|
|
58
|
+
if (!fs.existsSync(base)) {
|
|
59
|
+
throw new Error(`Feature "${feature}" does not exist. Run: domain-driver make:feature ${feature}`);
|
|
60
|
+
}
|
|
61
|
+
return base;
|
|
62
|
+
}
|
|
63
|
+
function writeFileSafe(filePath, content) {
|
|
64
|
+
try {
|
|
65
|
+
fs.writeFileSync(filePath, content);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
69
|
+
throw new Error(`Failed to write ${filePath}: ${message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function mkdirSafe(dirPath) {
|
|
73
|
+
try {
|
|
74
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
78
|
+
throw new Error(`Failed to create directory ${dirPath}: ${message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function fileExists(filePath) {
|
|
82
|
+
return fs.existsSync(filePath);
|
|
83
|
+
}
|
|
84
|
+
let cachedAlias;
|
|
85
|
+
function detectAlias() {
|
|
86
|
+
if (cachedAlias)
|
|
87
|
+
return cachedAlias;
|
|
88
|
+
const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');
|
|
89
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
90
|
+
cachedAlias = { alias: null, appDir: 'app' };
|
|
91
|
+
return cachedAlias;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const raw = fs.readFileSync(tsconfigPath, 'utf-8');
|
|
95
|
+
const stripped = raw.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
96
|
+
const tsconfig = JSON.parse(stripped);
|
|
97
|
+
const paths = tsconfig?.compilerOptions?.paths;
|
|
98
|
+
if (paths) {
|
|
99
|
+
for (const [key, values] of Object.entries(paths)) {
|
|
100
|
+
const targets = values;
|
|
101
|
+
const hasAppMapping = targets.some((v) => v === './app/*' || v === 'app/*' || v === './src/app/*' || v === 'src/app/*');
|
|
102
|
+
if (hasAppMapping && key.endsWith('/*')) {
|
|
103
|
+
const prefix = key.slice(0, -1);
|
|
104
|
+
const appDir = targets[0].replace('/*', '').replace('./', '');
|
|
105
|
+
cachedAlias = { alias: prefix, appDir };
|
|
106
|
+
return cachedAlias;
|
|
107
|
+
}
|
|
108
|
+
const hasSrcMapping = targets.some((v) => v === './src/*' || v === 'src/*' || v === './*');
|
|
109
|
+
if (hasSrcMapping && key.endsWith('/*')) {
|
|
110
|
+
const prefix = key.slice(0, -1);
|
|
111
|
+
cachedAlias = { alias: prefix, appDir: 'app' };
|
|
112
|
+
return cachedAlias;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// tsconfig parse failed, fall back to relative imports
|
|
119
|
+
}
|
|
120
|
+
cachedAlias = { alias: null, appDir: 'app' };
|
|
121
|
+
return cachedAlias;
|
|
122
|
+
}
|
|
123
|
+
function resetAliasCache() {
|
|
124
|
+
cachedAlias = undefined;
|
|
125
|
+
}
|
|
126
|
+
function resolveImport(fromFeature, relativePath, fromRoot = false) {
|
|
127
|
+
const { alias } = detectAlias();
|
|
128
|
+
if (alias) {
|
|
129
|
+
return `${alias}app/${fromFeature}/${relativePath}`;
|
|
130
|
+
}
|
|
131
|
+
return fromRoot ? `./${relativePath}` : `../${relativePath}`;
|
|
132
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domain-driver",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI scaffolding tool for domain-driven development in Next.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"domain-driver": "./dist/index.js"
|
|
@@ -11,17 +11,18 @@
|
|
|
11
11
|
"url": "https://github.com/IsaacHatilima/domain-driver"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
|
-
"build": "
|
|
15
|
-
"
|
|
16
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "vitest run"
|
|
17
16
|
},
|
|
18
17
|
"keywords": [],
|
|
19
|
-
"author": "",
|
|
20
|
-
"license": "
|
|
18
|
+
"author": "Isaac Hatilima",
|
|
19
|
+
"license": "MIT",
|
|
21
20
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^25.4.0"
|
|
21
|
+
"@types/node": "^25.4.0",
|
|
22
|
+
"typescript": "^5.9.3",
|
|
23
|
+
"vitest": "^4.1.2"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
|
-
"
|
|
26
|
+
"commander": "^14.0.3"
|
|
26
27
|
}
|
|
27
28
|
}
|