@kithinji/pod 1.0.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/build.js +22 -0
- package/dist/main.js +4464 -0
- package/dist/main.js.map +7 -0
- package/dist/types/add/component/component.d.ts +5 -0
- package/dist/types/add/component/component.d.ts.map +1 -0
- package/dist/types/add/component/index.d.ts +2 -0
- package/dist/types/add/component/index.d.ts.map +1 -0
- package/dist/types/add/index.d.ts +4 -0
- package/dist/types/add/index.d.ts.map +1 -0
- package/dist/types/add/module/index.d.ts +2 -0
- package/dist/types/add/module/index.d.ts.map +1 -0
- package/dist/types/add/module/module.d.ts +3 -0
- package/dist/types/add/module/module.d.ts.map +1 -0
- package/dist/types/add/new/index.d.ts +2 -0
- package/dist/types/add/new/index.d.ts.map +1 -0
- package/dist/types/config/config.d.ts +18 -0
- package/dist/types/config/config.d.ts.map +1 -0
- package/dist/types/config/index.d.ts +2 -0
- package/dist/types/config/index.d.ts.map +1 -0
- package/dist/types/dev/index.d.ts +2 -0
- package/dist/types/dev/index.d.ts.map +1 -0
- package/dist/types/dev/project.d.ts +9 -0
- package/dist/types/dev/project.d.ts.map +1 -0
- package/dist/types/dev/server.d.ts +2 -0
- package/dist/types/dev/server.d.ts.map +1 -0
- package/dist/types/docker/docker.d.ts +2 -0
- package/dist/types/docker/docker.d.ts.map +1 -0
- package/dist/types/docker/index.d.ts +2 -0
- package/dist/types/docker/index.d.ts.map +1 -0
- package/dist/types/macros/expand_macros.d.ts +48 -0
- package/dist/types/macros/expand_macros.d.ts.map +1 -0
- package/dist/types/macros/index.d.ts +3 -0
- package/dist/types/macros/index.d.ts.map +1 -0
- package/dist/types/macros/macro_executer.d.ts +12 -0
- package/dist/types/macros/macro_executer.d.ts.map +1 -0
- package/dist/types/main.d.ts +13 -0
- package/dist/types/main.d.ts.map +1 -0
- package/dist/types/plugins/analyzers/graph.d.ts +25 -0
- package/dist/types/plugins/analyzers/graph.d.ts.map +1 -0
- package/dist/types/plugins/css/index.d.ts +7 -0
- package/dist/types/plugins/css/index.d.ts.map +1 -0
- package/dist/types/plugins/generators/generate_controller.d.ts +2 -0
- package/dist/types/plugins/generators/generate_controller.d.ts.map +1 -0
- package/dist/types/plugins/generators/generate_rsc.d.ts +2 -0
- package/dist/types/plugins/generators/generate_rsc.d.ts.map +1 -0
- package/dist/types/plugins/generators/generate_server_component.d.ts +2 -0
- package/dist/types/plugins/generators/generate_server_component.d.ts.map +1 -0
- package/dist/types/plugins/generators/tsx_server_stub.d.ts +2 -0
- package/dist/types/plugins/generators/tsx_server_stub.d.ts.map +1 -0
- package/dist/types/plugins/index.d.ts +4 -0
- package/dist/types/plugins/index.d.ts.map +1 -0
- package/dist/types/plugins/my.d.ts +10 -0
- package/dist/types/plugins/my.d.ts.map +1 -0
- package/dist/types/plugins/transformers/j2d.d.ts +11 -0
- package/dist/types/plugins/transformers/j2d.d.ts.map +1 -0
- package/dist/types/store/index.d.ts +2 -0
- package/dist/types/store/index.d.ts.map +1 -0
- package/dist/types/store/store.d.ts +14 -0
- package/dist/types/store/store.d.ts.map +1 -0
- package/dist/types/utils/cases.d.ts +4 -0
- package/dist/types/utils/cases.d.ts.map +1 -0
- package/dist/types/utils/create.d.ts +12 -0
- package/dist/types/utils/create.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +3 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/package.json +44 -0
- package/src/add/component/component.ts +496 -0
- package/src/add/component/index.ts +1 -0
- package/src/add/index.ts +3 -0
- package/src/add/module/index.ts +1 -0
- package/src/add/module/module.ts +521 -0
- package/src/add/new/index.ts +135 -0
- package/src/config/config.ts +141 -0
- package/src/config/index.ts +1 -0
- package/src/dev/index.ts +1 -0
- package/src/dev/project.ts +45 -0
- package/src/dev/server.ts +190 -0
- package/src/docker/docker.ts +452 -0
- package/src/docker/index.ts +1 -0
- package/src/macros/expand_macros.ts +791 -0
- package/src/macros/index.ts +2 -0
- package/src/macros/macro_executer.ts +189 -0
- package/src/main.ts +95 -0
- package/src/plugins/analyzers/graph.ts +291 -0
- package/src/plugins/css/index.ts +25 -0
- package/src/plugins/generators/generate_controller.ts +308 -0
- package/src/plugins/generators/generate_rsc.ts +274 -0
- package/src/plugins/generators/generate_server_component.ts +279 -0
- package/src/plugins/generators/tsx_server_stub.ts +295 -0
- package/src/plugins/index.ts +3 -0
- package/src/plugins/my.ts +274 -0
- package/src/plugins/transformers/j2d.ts +1014 -0
- package/src/store/index.ts +1 -0
- package/src/store/store.ts +44 -0
- package/src/utils/cases.ts +15 -0
- package/src/utils/create.ts +26 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
import { createStructure, DirEntry, toCamelCase, toPascalCase } from "@/utils";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as ts from "typescript";
|
|
5
|
+
|
|
6
|
+
export function addFeature(name: string) {
|
|
7
|
+
const featureDir = path.join(process.cwd(), "src", "features", name);
|
|
8
|
+
|
|
9
|
+
addModule(name, featureDir);
|
|
10
|
+
|
|
11
|
+
updateFeaturesIndex(name);
|
|
12
|
+
|
|
13
|
+
updateAppModule(name);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function addModule(name: string, baseDir: string) {
|
|
17
|
+
const structure: DirEntry = {
|
|
18
|
+
files: [
|
|
19
|
+
{ name: `${name}.module.ts`, content: createModule(name) },
|
|
20
|
+
{ name: `${name}.service.ts`, content: createService(name) },
|
|
21
|
+
{ name: `${name}.page.tsx`, content: createPage(name) },
|
|
22
|
+
],
|
|
23
|
+
dirs: [
|
|
24
|
+
{
|
|
25
|
+
name: "schemas",
|
|
26
|
+
files: [
|
|
27
|
+
{
|
|
28
|
+
name: "get.ts",
|
|
29
|
+
content: createGetSchema(name),
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "create.ts",
|
|
33
|
+
content: createCreateSchema(name),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "update.ts",
|
|
37
|
+
content: createUpdateSchema(name),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "list.ts",
|
|
41
|
+
content: createListSchema(name),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "delete.ts",
|
|
45
|
+
content: createDeleteSchema(name),
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "components",
|
|
51
|
+
files: [
|
|
52
|
+
{
|
|
53
|
+
name: `${name}-list.component.tsx`,
|
|
54
|
+
content: createListComponent(name),
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
createStructure(baseDir, structure);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function updateFeaturesIndex(featureName: string) {
|
|
65
|
+
const featuresIndexPath = path.join(
|
|
66
|
+
process.cwd(),
|
|
67
|
+
"src",
|
|
68
|
+
"features",
|
|
69
|
+
"index.ts"
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const moduleName = toPascalCase(featureName + "_" + "Module");
|
|
73
|
+
const importPath = `./${featureName}/${featureName}.module`;
|
|
74
|
+
|
|
75
|
+
if (fs.existsSync(featuresIndexPath)) {
|
|
76
|
+
let content = fs.readFileSync(featuresIndexPath, "utf-8");
|
|
77
|
+
const sourceFile = ts.createSourceFile(
|
|
78
|
+
"index.ts",
|
|
79
|
+
content,
|
|
80
|
+
ts.ScriptTarget.Latest,
|
|
81
|
+
true
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const hasExport = sourceFile.statements.some((statement) => {
|
|
85
|
+
if (ts.isExportDeclaration(statement)) {
|
|
86
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
87
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
88
|
+
return moduleSpecifier.text === importPath;
|
|
89
|
+
}
|
|
90
|
+
if (
|
|
91
|
+
statement.exportClause &&
|
|
92
|
+
ts.isNamedExports(statement.exportClause)
|
|
93
|
+
) {
|
|
94
|
+
return statement.exportClause.elements.some(
|
|
95
|
+
(element) => element.name.text === moduleName
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (hasExport) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const exportStatement = `export { ${moduleName} } from "${importPath}";\n`;
|
|
107
|
+
fs.appendFileSync(featuresIndexPath, exportStatement);
|
|
108
|
+
} else {
|
|
109
|
+
const featuresDir = path.dirname(featuresIndexPath);
|
|
110
|
+
if (!fs.existsSync(featuresDir)) {
|
|
111
|
+
fs.mkdirSync(featuresDir, { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const exportStatement = `export { ${moduleName} } from "${importPath}";\n`;
|
|
115
|
+
fs.writeFileSync(featuresIndexPath, exportStatement, "utf-8");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function updateAppModule(featureName: string) {
|
|
120
|
+
const appModulePath = path.join(process.cwd(), "src", "app", "app.module.ts");
|
|
121
|
+
|
|
122
|
+
if (!fs.existsSync(appModulePath)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const moduleName = toPascalCase(featureName + "_" + "Module");
|
|
127
|
+
let content = fs.readFileSync(appModulePath, "utf-8");
|
|
128
|
+
|
|
129
|
+
const sourceFile = ts.createSourceFile(
|
|
130
|
+
"app.module.ts",
|
|
131
|
+
content,
|
|
132
|
+
ts.ScriptTarget.Latest,
|
|
133
|
+
true
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const hasImport = sourceFile.statements.some((statement) => {
|
|
137
|
+
if (ts.isImportDeclaration(statement)) {
|
|
138
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
139
|
+
if (ts.isStringLiteral(moduleSpecifier)) {
|
|
140
|
+
const importPath = moduleSpecifier.text;
|
|
141
|
+
return importPath.includes(`/${featureName}/${featureName}.module`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (
|
|
145
|
+
statement.importClause?.namedBindings &&
|
|
146
|
+
ts.isNamedImports(statement.importClause.namedBindings)
|
|
147
|
+
) {
|
|
148
|
+
return statement.importClause.namedBindings.elements.some(
|
|
149
|
+
(element) => element.name.text === moduleName
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (hasImport) {
|
|
157
|
+
content = addToModuleImportsArray(content, sourceFile, moduleName);
|
|
158
|
+
fs.writeFileSync(appModulePath, content, "utf-8");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let lastImportEnd = 0;
|
|
163
|
+
sourceFile.statements.forEach((statement) => {
|
|
164
|
+
if (ts.isImportDeclaration(statement)) {
|
|
165
|
+
lastImportEnd = statement.end;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const importStatement = `import { ${moduleName} } from "../features/${featureName}/${featureName}.module";\n`;
|
|
170
|
+
content =
|
|
171
|
+
content.slice(0, lastImportEnd) +
|
|
172
|
+
"\n" +
|
|
173
|
+
importStatement +
|
|
174
|
+
content.slice(lastImportEnd);
|
|
175
|
+
|
|
176
|
+
const newSourceFile = ts.createSourceFile(
|
|
177
|
+
"app.module.ts",
|
|
178
|
+
content,
|
|
179
|
+
ts.ScriptTarget.Latest,
|
|
180
|
+
true
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
content = addToModuleImportsArray(content, newSourceFile, moduleName);
|
|
184
|
+
|
|
185
|
+
fs.writeFileSync(appModulePath, content, "utf-8");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function addToModuleImportsArray(
|
|
189
|
+
content: string,
|
|
190
|
+
sourceFile: ts.SourceFile,
|
|
191
|
+
moduleName: string
|
|
192
|
+
): string {
|
|
193
|
+
let decoratorNode: ts.Decorator | undefined;
|
|
194
|
+
|
|
195
|
+
sourceFile.statements.forEach((statement) => {
|
|
196
|
+
if (ts.isClassDeclaration(statement) && statement.modifiers) {
|
|
197
|
+
statement.modifiers.forEach((modifier) => {
|
|
198
|
+
if (ts.isDecorator(modifier)) {
|
|
199
|
+
const expression = modifier.expression;
|
|
200
|
+
if (ts.isCallExpression(expression)) {
|
|
201
|
+
const expressionText = expression.expression.getText(sourceFile);
|
|
202
|
+
if (expressionText === "Module") {
|
|
203
|
+
decoratorNode = modifier;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
if (!decoratorNode) {
|
|
212
|
+
return content;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const callExpression = decoratorNode.expression as ts.CallExpression;
|
|
216
|
+
const objectLiteral = callExpression
|
|
217
|
+
.arguments[0] as ts.ObjectLiteralExpression;
|
|
218
|
+
|
|
219
|
+
if (!objectLiteral || !ts.isObjectLiteralExpression(objectLiteral)) {
|
|
220
|
+
return content;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let importsProperty: ts.PropertyAssignment | undefined;
|
|
224
|
+
objectLiteral.properties.forEach((prop) => {
|
|
225
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
226
|
+
const propName = prop.name.getText(sourceFile);
|
|
227
|
+
if (propName === "imports") {
|
|
228
|
+
importsProperty = prop;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (!importsProperty) {
|
|
234
|
+
return content;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const arrayLiteral = importsProperty.initializer;
|
|
238
|
+
if (!ts.isArrayLiteralExpression(arrayLiteral)) {
|
|
239
|
+
return content;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const hasModule = arrayLiteral.elements.some((element) => {
|
|
243
|
+
return element.getText(sourceFile).trim() === moduleName;
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
if (hasModule) {
|
|
247
|
+
return content;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const arrayStart = arrayLiteral.getStart(sourceFile);
|
|
251
|
+
const arrayEnd = arrayLiteral.getEnd();
|
|
252
|
+
|
|
253
|
+
if (arrayLiteral.elements.length === 0) {
|
|
254
|
+
const newArray = `[${moduleName}]`;
|
|
255
|
+
return (
|
|
256
|
+
content.substring(0, arrayStart) + newArray + content.substring(arrayEnd)
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const lastElement = arrayLiteral.elements[arrayLiteral.elements.length - 1];
|
|
261
|
+
const insertPos = lastElement.getEnd();
|
|
262
|
+
const newElement = `, ${moduleName}`;
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
content.substring(0, insertPos) + newElement + content.substring(insertPos)
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function createModule(name: string) {
|
|
270
|
+
const serviceName = toPascalCase(name + "_" + "Service");
|
|
271
|
+
const pageName = toPascalCase(name + "_" + "Page");
|
|
272
|
+
const moduleName = toPascalCase(name + "_" + "Module");
|
|
273
|
+
const componentName = toPascalCase(name + "_" + "List");
|
|
274
|
+
|
|
275
|
+
return `import { Module } from "@kithinji/orca";
|
|
276
|
+
import { ComponentModule } from "@/component/component.module";
|
|
277
|
+
import { ${serviceName} } from "./${name}.service";
|
|
278
|
+
import { ${pageName} } from "./${name}.page";
|
|
279
|
+
import { ${componentName} } from "./components/${name}-list.component";
|
|
280
|
+
|
|
281
|
+
@Module({
|
|
282
|
+
imports: [ComponentModule],
|
|
283
|
+
providers: [${serviceName}],
|
|
284
|
+
declarations: [${pageName}, ${componentName}],
|
|
285
|
+
exports: [${serviceName}, ${pageName}]
|
|
286
|
+
})
|
|
287
|
+
export class ${moduleName} {}
|
|
288
|
+
`;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function createGetSchema(name: string) {
|
|
292
|
+
return `import { z } from "zod";
|
|
293
|
+
|
|
294
|
+
export const ${toCamelCase(name + "_" + "GetInput")} = z.object({
|
|
295
|
+
id: z.string().uuid(),
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
export const ${toCamelCase(name + "_" + "GetOutput")} = z.object({
|
|
299
|
+
id: z.string().uuid(),
|
|
300
|
+
name: z.string(),
|
|
301
|
+
description: z.string().optional(),
|
|
302
|
+
createdAt: z.date(),
|
|
303
|
+
updatedAt: z.date().optional(),
|
|
304
|
+
});
|
|
305
|
+
`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function createCreateSchema(name: string) {
|
|
309
|
+
return `import { z } from "zod";
|
|
310
|
+
|
|
311
|
+
export const ${toCamelCase(name + "_" + "CreateInput")} = z.object({
|
|
312
|
+
name: z.string().min(1),
|
|
313
|
+
description: z.string().optional(),
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
export const ${toCamelCase(name + "_" + "CreateOutput")} = z.object({
|
|
317
|
+
id: z.string().uuid(),
|
|
318
|
+
name: z.string(),
|
|
319
|
+
description: z.string().optional(),
|
|
320
|
+
createdAt: z.date(),
|
|
321
|
+
});
|
|
322
|
+
`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function createUpdateSchema(name: string) {
|
|
326
|
+
return `import { z } from "zod";
|
|
327
|
+
|
|
328
|
+
export const ${toCamelCase(name + "_" + "UpdateInput")} = z.object({
|
|
329
|
+
id: z.string().uuid(),
|
|
330
|
+
name: z.string().min(1).optional(),
|
|
331
|
+
description: z.string().optional(),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
export const ${toCamelCase(name + "_" + "UpdateOutput")} = z.object({
|
|
335
|
+
id: z.string().uuid(),
|
|
336
|
+
name: z.string(),
|
|
337
|
+
description: z.string().optional(),
|
|
338
|
+
createdAt: z.date(),
|
|
339
|
+
updatedAt: z.date(),
|
|
340
|
+
});
|
|
341
|
+
`;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function createListSchema(name: string) {
|
|
345
|
+
return `import { z } from "zod";
|
|
346
|
+
|
|
347
|
+
export const ${toCamelCase(name + "_" + "ListOutput")} = z.array(
|
|
348
|
+
z.object({
|
|
349
|
+
id: z.string().uuid(),
|
|
350
|
+
name: z.string(),
|
|
351
|
+
description: z.string().optional(),
|
|
352
|
+
createdAt: z.date(),
|
|
353
|
+
updatedAt: z.date().optional(),
|
|
354
|
+
})
|
|
355
|
+
);
|
|
356
|
+
`;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function createDeleteSchema(name: string) {
|
|
360
|
+
return `import { z } from "zod";
|
|
361
|
+
|
|
362
|
+
export const ${toCamelCase(name + "_" + "DeleteInput")} = z.object({
|
|
363
|
+
id: z.string().uuid(),
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
export const ${toCamelCase(name + "_" + "DeleteOutput")} = z.object({
|
|
367
|
+
id: z.string().uuid(),
|
|
368
|
+
name: z.string(),
|
|
369
|
+
description: z.string().optional(),
|
|
370
|
+
createdAt: z.date(),
|
|
371
|
+
updatedAt: z.date().optional(),
|
|
372
|
+
});
|
|
373
|
+
`;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function createService(name: string) {
|
|
377
|
+
const serviceName = toPascalCase(name + "_" + "Service");
|
|
378
|
+
|
|
379
|
+
return `"use public";
|
|
380
|
+
|
|
381
|
+
import { Injectable, Signature } from "@kithinji/orca";
|
|
382
|
+
import {
|
|
383
|
+
${toCamelCase(name + "_" + "CreateInput")},
|
|
384
|
+
${toCamelCase(name + "_" + "CreateOutput")}
|
|
385
|
+
} from "./schemas/create";
|
|
386
|
+
import {
|
|
387
|
+
${toCamelCase(name + "_" + "GetInput")},
|
|
388
|
+
${toCamelCase(name + "_" + "GetOutput")}
|
|
389
|
+
} from "./schemas/get";
|
|
390
|
+
import {
|
|
391
|
+
${toCamelCase(name + "_" + "UpdateInput")},
|
|
392
|
+
${toCamelCase(name + "_" + "UpdateOutput")}
|
|
393
|
+
} from "./schemas/update";
|
|
394
|
+
import { ${toCamelCase(name + "_" + "ListOutput")} } from "./schemas/list";
|
|
395
|
+
import {
|
|
396
|
+
${toCamelCase(name + "_" + "DeleteInput")},
|
|
397
|
+
${toCamelCase(name + "_" + "DeleteOutput")}
|
|
398
|
+
} from "./schemas/delete";
|
|
399
|
+
|
|
400
|
+
@Injectable()
|
|
401
|
+
export class ${serviceName} {
|
|
402
|
+
private items: any[] = [];
|
|
403
|
+
|
|
404
|
+
@Signature(${toCamelCase(name + "_" + "CreateInput")}, ${toCamelCase(
|
|
405
|
+
name + "_" + "CreateOutput"
|
|
406
|
+
)})
|
|
407
|
+
public async create(input: any) {
|
|
408
|
+
const item = {
|
|
409
|
+
id: crypto.randomUUID(),
|
|
410
|
+
...input,
|
|
411
|
+
createdAt: new Date(),
|
|
412
|
+
};
|
|
413
|
+
this.items.push(item);
|
|
414
|
+
return item;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
@Signature(${toCamelCase(name + "_" + "GetInput")}, ${toCamelCase(
|
|
418
|
+
name + "_" + "GetOutput"
|
|
419
|
+
)})
|
|
420
|
+
public async get(input: any) {
|
|
421
|
+
const item = this.items.find((i) => i.id === input.id);
|
|
422
|
+
if (!item) {
|
|
423
|
+
throw new Error("Item not found");
|
|
424
|
+
}
|
|
425
|
+
return item;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
@Signature(${toCamelCase(name + "_" + "ListOutput")})
|
|
429
|
+
public async list() {
|
|
430
|
+
return this.items;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
@Signature(${toCamelCase(name + "_" + "UpdateInput")}, ${toCamelCase(
|
|
434
|
+
name + "_" + "UpdateOutput"
|
|
435
|
+
)})
|
|
436
|
+
public async update(input: any) {
|
|
437
|
+
const index = this.items.findIndex((i) => i.id === input.id);
|
|
438
|
+
if (index === -1) {
|
|
439
|
+
throw new Error("Item not found");
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
this.items[index] = {
|
|
443
|
+
...this.items[index],
|
|
444
|
+
...input,
|
|
445
|
+
updatedAt: new Date(),
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
return this.items[index];
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
@Signature(${toCamelCase(name + "_" + "DeleteInput")}, ${toCamelCase(
|
|
452
|
+
name + "_" + "DeleteOutput"
|
|
453
|
+
)})
|
|
454
|
+
public async delete(input: any) {
|
|
455
|
+
const index = this.items.findIndex((i) => i.id === input.id);
|
|
456
|
+
if (index === -1) {
|
|
457
|
+
throw new Error("Item not found");
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const deleted = this.items.splice(index, 1)[0];
|
|
461
|
+
return deleted;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
`;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function createPage(name: string) {
|
|
468
|
+
const pageName = toPascalCase(name + "_" + "Page");
|
|
469
|
+
const serviceName = toPascalCase(name + "_" + "Service");
|
|
470
|
+
const serviceVar = toCamelCase(name + "_" + "Service");
|
|
471
|
+
const listComponent = toPascalCase(name + "_" + "List");
|
|
472
|
+
|
|
473
|
+
return `import { Component } from "@kithinji/orca";
|
|
474
|
+
import { ${serviceName} } from "./${name}.service";
|
|
475
|
+
import { ${listComponent} } from "./components/${name}-list.component";
|
|
476
|
+
|
|
477
|
+
@Component()
|
|
478
|
+
export class ${pageName} {
|
|
479
|
+
constructor(
|
|
480
|
+
public ${serviceVar}: ${serviceName}
|
|
481
|
+
) {}
|
|
482
|
+
|
|
483
|
+
build() {
|
|
484
|
+
return (
|
|
485
|
+
<div>
|
|
486
|
+
<h1>${toPascalCase(name)} Management</h1>
|
|
487
|
+
<${listComponent} service={this.${serviceVar}} />
|
|
488
|
+
</div>
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
`;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function createListComponent(name: string) {
|
|
496
|
+
const componentName = toPascalCase(name + "_" + "List");
|
|
497
|
+
const serviceName = toPascalCase(name + "_" + "Service");
|
|
498
|
+
|
|
499
|
+
return `"use interactive";
|
|
500
|
+
|
|
501
|
+
import { Component } from "@kithinji/orca";
|
|
502
|
+
import { ${serviceName} } from "../${name}.service";
|
|
503
|
+
|
|
504
|
+
@Component()
|
|
505
|
+
export class ${componentName} {
|
|
506
|
+
props!: {
|
|
507
|
+
service: ${serviceName};
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
build() {
|
|
511
|
+
return (
|
|
512
|
+
<div>
|
|
513
|
+
<h2>${toPascalCase(name)} List</h2>
|
|
514
|
+
<p>List component for ${name}</p>
|
|
515
|
+
{/* Add your list implementation here */}
|
|
516
|
+
</div>
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
`;
|
|
521
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { createStructure, DirEntry } from "@/utils";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { addModule } from "../module";
|
|
4
|
+
import { addComponent } from "../component";
|
|
5
|
+
|
|
6
|
+
export function addNew(name: string) {
|
|
7
|
+
const baseDir = path.join(process.cwd(), name);
|
|
8
|
+
|
|
9
|
+
const structure: DirEntry = {
|
|
10
|
+
files: [
|
|
11
|
+
{ name: "package.json", content: genPackageJson(name) },
|
|
12
|
+
{ name: "tsconfig.json", content: gentsconfig() },
|
|
13
|
+
{ name: "pod.config.ts", content: genPodConfig(name) },
|
|
14
|
+
{ name: "README.md", content: genReadMe() },
|
|
15
|
+
{ name: ".gitignore", content: genGitIgnore() },
|
|
16
|
+
{ name: ".env", content: genEnv() },
|
|
17
|
+
],
|
|
18
|
+
dirs: [
|
|
19
|
+
{
|
|
20
|
+
name: "src",
|
|
21
|
+
files: [{ name: "main.ts", content: genMainTs() }],
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
createStructure(baseDir, structure);
|
|
27
|
+
|
|
28
|
+
const appDir = path.join(process.cwd(), name, "src", "app");
|
|
29
|
+
|
|
30
|
+
addModule("app", appDir);
|
|
31
|
+
|
|
32
|
+
process.chdir(baseDir);
|
|
33
|
+
|
|
34
|
+
addComponent("button");
|
|
35
|
+
|
|
36
|
+
console.log(`App ${name} created successfully`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function genPackageJson(name: string) {
|
|
40
|
+
const pj = {
|
|
41
|
+
name,
|
|
42
|
+
private: true,
|
|
43
|
+
version: "0.0.0",
|
|
44
|
+
type: "module",
|
|
45
|
+
scripts: {
|
|
46
|
+
dev: "pod dev",
|
|
47
|
+
build: "pod build",
|
|
48
|
+
start: "pod start",
|
|
49
|
+
},
|
|
50
|
+
dependencies: {
|
|
51
|
+
"reflect-metadata": "latest",
|
|
52
|
+
zod: "^4.2.1",
|
|
53
|
+
"@kithinji/orca": "latest",
|
|
54
|
+
},
|
|
55
|
+
devDependencies: {
|
|
56
|
+
"@types/node": "^20.19.27",
|
|
57
|
+
typescript: "~5.9.3",
|
|
58
|
+
"@kithinji/pod": "latest",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return JSON.stringify(pj, null, 2);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function gentsconfig() {
|
|
66
|
+
const tsconfig = {
|
|
67
|
+
compilerOptions: {
|
|
68
|
+
target: "ES2020",
|
|
69
|
+
module: "ESNext",
|
|
70
|
+
moduleResolution: "bundler",
|
|
71
|
+
strict: true,
|
|
72
|
+
esModuleInterop: true,
|
|
73
|
+
skipLibCheck: true,
|
|
74
|
+
jsx: "react-jsx",
|
|
75
|
+
jsxImportSource: "@kithinji/orca",
|
|
76
|
+
experimentalDecorators: true,
|
|
77
|
+
emitDecoratorMetadata: true,
|
|
78
|
+
baseUrl: ".",
|
|
79
|
+
paths: {
|
|
80
|
+
"@/*": ["src/*"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
include: ["src"],
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return JSON.stringify(tsconfig, null, 2);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function genPodConfig(name: string) {
|
|
90
|
+
return `import { PodConfig, stylePlugin } from "@kithinji/pod";
|
|
91
|
+
|
|
92
|
+
export default function defaultConfig(): PodConfig {
|
|
93
|
+
return {
|
|
94
|
+
name: "${name}",
|
|
95
|
+
client_plugins: [stylePlugin],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function genReadMe() {
|
|
102
|
+
return `# Pod Project
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function genGitIgnore() {
|
|
107
|
+
return `node_modules
|
|
108
|
+
dist
|
|
109
|
+
build
|
|
110
|
+
.orca
|
|
111
|
+
*.log
|
|
112
|
+
.env
|
|
113
|
+
.DS_Store
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function genEnv() {
|
|
118
|
+
return `NODE_ENV=development
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function genMainTs() {
|
|
123
|
+
return `import { NodeFactory } from "@kithinji/orca";
|
|
124
|
+
import { AppModule } from "./app/app.module";
|
|
125
|
+
|
|
126
|
+
async function bootstrap() {
|
|
127
|
+
const app = await NodeFactory.create(AppModule);
|
|
128
|
+
app.listen(8080, () => {
|
|
129
|
+
console.log("Server started");
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bootstrap();
|
|
134
|
+
`;
|
|
135
|
+
}
|