@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.
Files changed (98) hide show
  1. package/build.js +22 -0
  2. package/dist/main.js +4464 -0
  3. package/dist/main.js.map +7 -0
  4. package/dist/types/add/component/component.d.ts +5 -0
  5. package/dist/types/add/component/component.d.ts.map +1 -0
  6. package/dist/types/add/component/index.d.ts +2 -0
  7. package/dist/types/add/component/index.d.ts.map +1 -0
  8. package/dist/types/add/index.d.ts +4 -0
  9. package/dist/types/add/index.d.ts.map +1 -0
  10. package/dist/types/add/module/index.d.ts +2 -0
  11. package/dist/types/add/module/index.d.ts.map +1 -0
  12. package/dist/types/add/module/module.d.ts +3 -0
  13. package/dist/types/add/module/module.d.ts.map +1 -0
  14. package/dist/types/add/new/index.d.ts +2 -0
  15. package/dist/types/add/new/index.d.ts.map +1 -0
  16. package/dist/types/config/config.d.ts +18 -0
  17. package/dist/types/config/config.d.ts.map +1 -0
  18. package/dist/types/config/index.d.ts +2 -0
  19. package/dist/types/config/index.d.ts.map +1 -0
  20. package/dist/types/dev/index.d.ts +2 -0
  21. package/dist/types/dev/index.d.ts.map +1 -0
  22. package/dist/types/dev/project.d.ts +9 -0
  23. package/dist/types/dev/project.d.ts.map +1 -0
  24. package/dist/types/dev/server.d.ts +2 -0
  25. package/dist/types/dev/server.d.ts.map +1 -0
  26. package/dist/types/docker/docker.d.ts +2 -0
  27. package/dist/types/docker/docker.d.ts.map +1 -0
  28. package/dist/types/docker/index.d.ts +2 -0
  29. package/dist/types/docker/index.d.ts.map +1 -0
  30. package/dist/types/macros/expand_macros.d.ts +48 -0
  31. package/dist/types/macros/expand_macros.d.ts.map +1 -0
  32. package/dist/types/macros/index.d.ts +3 -0
  33. package/dist/types/macros/index.d.ts.map +1 -0
  34. package/dist/types/macros/macro_executer.d.ts +12 -0
  35. package/dist/types/macros/macro_executer.d.ts.map +1 -0
  36. package/dist/types/main.d.ts +13 -0
  37. package/dist/types/main.d.ts.map +1 -0
  38. package/dist/types/plugins/analyzers/graph.d.ts +25 -0
  39. package/dist/types/plugins/analyzers/graph.d.ts.map +1 -0
  40. package/dist/types/plugins/css/index.d.ts +7 -0
  41. package/dist/types/plugins/css/index.d.ts.map +1 -0
  42. package/dist/types/plugins/generators/generate_controller.d.ts +2 -0
  43. package/dist/types/plugins/generators/generate_controller.d.ts.map +1 -0
  44. package/dist/types/plugins/generators/generate_rsc.d.ts +2 -0
  45. package/dist/types/plugins/generators/generate_rsc.d.ts.map +1 -0
  46. package/dist/types/plugins/generators/generate_server_component.d.ts +2 -0
  47. package/dist/types/plugins/generators/generate_server_component.d.ts.map +1 -0
  48. package/dist/types/plugins/generators/tsx_server_stub.d.ts +2 -0
  49. package/dist/types/plugins/generators/tsx_server_stub.d.ts.map +1 -0
  50. package/dist/types/plugins/index.d.ts +4 -0
  51. package/dist/types/plugins/index.d.ts.map +1 -0
  52. package/dist/types/plugins/my.d.ts +10 -0
  53. package/dist/types/plugins/my.d.ts.map +1 -0
  54. package/dist/types/plugins/transformers/j2d.d.ts +11 -0
  55. package/dist/types/plugins/transformers/j2d.d.ts.map +1 -0
  56. package/dist/types/store/index.d.ts +2 -0
  57. package/dist/types/store/index.d.ts.map +1 -0
  58. package/dist/types/store/store.d.ts +14 -0
  59. package/dist/types/store/store.d.ts.map +1 -0
  60. package/dist/types/utils/cases.d.ts +4 -0
  61. package/dist/types/utils/cases.d.ts.map +1 -0
  62. package/dist/types/utils/create.d.ts +12 -0
  63. package/dist/types/utils/create.d.ts.map +1 -0
  64. package/dist/types/utils/index.d.ts +3 -0
  65. package/dist/types/utils/index.d.ts.map +1 -0
  66. package/package.json +44 -0
  67. package/src/add/component/component.ts +496 -0
  68. package/src/add/component/index.ts +1 -0
  69. package/src/add/index.ts +3 -0
  70. package/src/add/module/index.ts +1 -0
  71. package/src/add/module/module.ts +521 -0
  72. package/src/add/new/index.ts +135 -0
  73. package/src/config/config.ts +141 -0
  74. package/src/config/index.ts +1 -0
  75. package/src/dev/index.ts +1 -0
  76. package/src/dev/project.ts +45 -0
  77. package/src/dev/server.ts +190 -0
  78. package/src/docker/docker.ts +452 -0
  79. package/src/docker/index.ts +1 -0
  80. package/src/macros/expand_macros.ts +791 -0
  81. package/src/macros/index.ts +2 -0
  82. package/src/macros/macro_executer.ts +189 -0
  83. package/src/main.ts +95 -0
  84. package/src/plugins/analyzers/graph.ts +291 -0
  85. package/src/plugins/css/index.ts +25 -0
  86. package/src/plugins/generators/generate_controller.ts +308 -0
  87. package/src/plugins/generators/generate_rsc.ts +274 -0
  88. package/src/plugins/generators/generate_server_component.ts +279 -0
  89. package/src/plugins/generators/tsx_server_stub.ts +295 -0
  90. package/src/plugins/index.ts +3 -0
  91. package/src/plugins/my.ts +274 -0
  92. package/src/plugins/transformers/j2d.ts +1014 -0
  93. package/src/store/index.ts +1 -0
  94. package/src/store/store.ts +44 -0
  95. package/src/utils/cases.ts +15 -0
  96. package/src/utils/create.ts +26 -0
  97. package/src/utils/index.ts +2 -0
  98. package/tsconfig.json +27 -0
@@ -0,0 +1,496 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as ts from "typescript";
4
+
5
+ abstract class ComponentDefinition {
6
+ abstract name: string;
7
+ abstract dependencies: string[];
8
+ abstract generate(): string;
9
+ }
10
+
11
+ class ButtonComponent extends ComponentDefinition {
12
+ name = "button";
13
+ dependencies: string[] = [];
14
+
15
+ generate(): string {
16
+ return `"use interactive";
17
+
18
+ import { Component, JSX } from "@kithinji/orca";
19
+
20
+ @Component()
21
+ export class Button {
22
+ props!: {
23
+ children: any
24
+ };
25
+
26
+ build() {
27
+ return (
28
+ <button>
29
+ {this.props.children}
30
+ </button>
31
+ );
32
+ }
33
+ }
34
+ `;
35
+ }
36
+ }
37
+
38
+ class InputComponent extends ComponentDefinition {
39
+ name = "input";
40
+ dependencies: string[] = [];
41
+
42
+ generate(): string {
43
+ return `"use interactive";
44
+
45
+ import { Component } from "@kithinji/orca";
46
+
47
+ @Component()
48
+ export class Input {
49
+ build() {
50
+ return (
51
+ <input />
52
+ );
53
+ }
54
+ }
55
+ `;
56
+ }
57
+ }
58
+
59
+ class FormComponent extends ComponentDefinition {
60
+ name = "form";
61
+ dependencies = ["button", "input"];
62
+
63
+ generate(): string {
64
+ return `"use interactive";
65
+
66
+ import { Component } from "@kithinji/orca";
67
+ import { Button } from "./button.component";
68
+ import { Input } from "./input.component";
69
+
70
+ @Component()
71
+ export class Form {
72
+ props!: {
73
+ onSubmit?: () => void;
74
+ };
75
+
76
+ build() {
77
+ return (
78
+ <form onSubmit={this.props.onSubmit}>
79
+ <Input />
80
+ <Button>Submit</Button>
81
+ </form>
82
+ );
83
+ }
84
+ }
85
+ `;
86
+ }
87
+ }
88
+
89
+ class CardComponent extends ComponentDefinition {
90
+ name = "card";
91
+ dependencies = ["button"];
92
+
93
+ generate(): string {
94
+ return `"use interactive";
95
+
96
+ import { Component } from "@kithinji/orca";
97
+ import { Button } from "./button.component";
98
+
99
+ @Component()
100
+ export class Card {
101
+ props!: {
102
+ title: string;
103
+ children: any;
104
+ onAction?: () => void;
105
+ };
106
+
107
+ build() {
108
+ return (
109
+ <div className="card">
110
+ <h3>{this.props.title}</h3>
111
+ <div>{this.props.children}</div>
112
+ {this.props.onAction && (
113
+ <Button onClick={this.props.onAction}>Action</Button>
114
+ )}
115
+ </div>
116
+ );
117
+ }
118
+ }
119
+ `;
120
+ }
121
+ }
122
+
123
+ class ComponentRegistry {
124
+ private static components = new Map<string, ComponentDefinition>([
125
+ ["button", new ButtonComponent()],
126
+ ["input", new InputComponent()],
127
+ ["form", new FormComponent()],
128
+ ["card", new CardComponent()],
129
+ ]);
130
+
131
+ static get(name: string): ComponentDefinition | undefined {
132
+ return this.components.get(name);
133
+ }
134
+
135
+ static has(name: string): boolean {
136
+ return this.components.has(name);
137
+ }
138
+
139
+ static getAll(): string[] {
140
+ return Array.from(this.components.keys());
141
+ }
142
+
143
+ static register(component: ComponentDefinition): void {
144
+ this.components.set(component.name, component);
145
+ }
146
+ }
147
+
148
+ export function addComponent(
149
+ name: string,
150
+ processedComponents: Set<string> = new Set()
151
+ ) {
152
+ if (processedComponents.has(name)) {
153
+ return;
154
+ }
155
+
156
+ const component = ComponentRegistry.get(name);
157
+ if (!component) {
158
+ throw new Error(
159
+ `Component "${name}" not found. Available components: ${ComponentRegistry.getAll().join(
160
+ ", "
161
+ )}`
162
+ );
163
+ }
164
+
165
+ processedComponents.add(name);
166
+
167
+ if (component.dependencies.length > 0) {
168
+ console.log(
169
+ `\nProcessing dependencies for "${name}": [${component.dependencies.join(
170
+ ", "
171
+ )}]`
172
+ );
173
+ for (const dependency of component.dependencies) {
174
+ addComponent(dependency, processedComponents);
175
+ }
176
+ }
177
+
178
+ const componentModulePath = path.join(
179
+ process.cwd(),
180
+ "src/component/component.module.ts"
181
+ );
182
+ const componentPath = path.join(
183
+ process.cwd(),
184
+ `src/component/component/${name}.component.tsx`
185
+ );
186
+ const componentDir = path.dirname(componentPath);
187
+ const appModulePath = path.join(process.cwd(), "src/app/app.module.ts");
188
+
189
+ if (!fs.existsSync(componentModulePath)) {
190
+ const moduleDir = path.dirname(componentModulePath);
191
+ if (!fs.existsSync(moduleDir)) {
192
+ fs.mkdirSync(moduleDir, { recursive: true });
193
+ }
194
+ fs.writeFileSync(componentModulePath, createModule(), "utf-8");
195
+ }
196
+
197
+ if (!fs.existsSync(componentDir)) {
198
+ fs.mkdirSync(componentDir, { recursive: true });
199
+ }
200
+
201
+ if (!fs.existsSync(componentPath)) {
202
+ fs.writeFileSync(componentPath, component.generate(), "utf-8");
203
+ console.log(`Created ${name}.component.tsx`);
204
+ } else {
205
+ console.log(`${name}.component.tsx already exists, skipping file creation`);
206
+ }
207
+
208
+ const moduleContent = fs.readFileSync(componentModulePath, "utf-8");
209
+ const updatedModule = updateModuleWithComponent(moduleContent, name);
210
+ fs.writeFileSync(componentModulePath, updatedModule, "utf-8");
211
+
212
+ if (fs.existsSync(appModulePath)) {
213
+ const appModuleContent = fs.readFileSync(appModulePath, "utf-8");
214
+ const updatedAppModule = ensureComponentModuleImported(appModuleContent);
215
+ if (updatedAppModule !== appModuleContent) {
216
+ fs.writeFileSync(appModulePath, updatedAppModule, "utf-8");
217
+ }
218
+ }
219
+ }
220
+
221
+ export function getComponentDependencies(
222
+ name: string,
223
+ visited: Set<string> = new Set()
224
+ ): string[] {
225
+ if (visited.has(name)) {
226
+ return [];
227
+ }
228
+
229
+ const component = ComponentRegistry.get(name);
230
+ if (!component) {
231
+ return [];
232
+ }
233
+
234
+ visited.add(name);
235
+ const allDeps: string[] = [];
236
+
237
+ for (const dep of component.dependencies) {
238
+ allDeps.push(dep);
239
+ allDeps.push(...getComponentDependencies(dep, visited));
240
+ }
241
+
242
+ return [...new Set(allDeps)];
243
+ }
244
+
245
+ export function printDependencyTree(name: string, indent: string = ""): void {
246
+ const component = ComponentRegistry.get(name);
247
+ if (!component) {
248
+ console.log(`${indent}${name} (not found)`);
249
+ return;
250
+ }
251
+
252
+ console.log(`${indent}${name}`);
253
+ for (const dep of component.dependencies) {
254
+ printDependencyTree(dep, indent + " ├─ ");
255
+ }
256
+ }
257
+
258
+ export function listComponents(): void {
259
+ console.log("\nAvailable components:");
260
+ for (const name of ComponentRegistry.getAll()) {
261
+ const component = ComponentRegistry.get(name)!;
262
+ const depsInfo =
263
+ component.dependencies.length > 0
264
+ ? ` (depends on: ${component.dependencies.join(", ")})`
265
+ : " (no dependencies)";
266
+ console.log(` - ${name}${depsInfo}`);
267
+ }
268
+ }
269
+
270
+ function updateModuleWithComponent(
271
+ moduleContent: string,
272
+ componentName: string
273
+ ): string {
274
+ const className = capitalize(componentName);
275
+ const importPath = `./component/${componentName}.component`;
276
+
277
+ const sourceFile = ts.createSourceFile(
278
+ "component.module.ts",
279
+ moduleContent,
280
+ ts.ScriptTarget.Latest,
281
+ true
282
+ );
283
+
284
+ const hasImport = sourceFile.statements.some((statement) => {
285
+ if (ts.isImportDeclaration(statement)) {
286
+ const moduleSpecifier = statement.moduleSpecifier;
287
+ if (ts.isStringLiteral(moduleSpecifier)) {
288
+ return moduleSpecifier.text === importPath;
289
+ }
290
+ }
291
+ return false;
292
+ });
293
+
294
+ if (hasImport) {
295
+ return moduleContent;
296
+ }
297
+
298
+ let lastImportEnd = 0;
299
+ sourceFile.statements.forEach((statement) => {
300
+ if (ts.isImportDeclaration(statement)) {
301
+ lastImportEnd = statement.end;
302
+ }
303
+ });
304
+
305
+ const importStatement = `import { ${className} } from "${importPath}";\n`;
306
+ let updatedContent =
307
+ moduleContent.slice(0, lastImportEnd) +
308
+ "\n" +
309
+ importStatement +
310
+ moduleContent.slice(lastImportEnd);
311
+
312
+ const newSourceFile = ts.createSourceFile(
313
+ "component.module.ts",
314
+ updatedContent,
315
+ ts.ScriptTarget.Latest,
316
+ true
317
+ );
318
+
319
+ updatedContent = addToDecoratorArray(
320
+ updatedContent,
321
+ newSourceFile,
322
+ "declarations",
323
+ className
324
+ );
325
+ updatedContent = addToDecoratorArray(
326
+ updatedContent,
327
+ ts.createSourceFile(
328
+ "component.module.ts",
329
+ updatedContent,
330
+ ts.ScriptTarget.Latest,
331
+ true
332
+ ),
333
+ "exports",
334
+ className
335
+ );
336
+
337
+ return updatedContent;
338
+ }
339
+
340
+ function addToDecoratorArray(
341
+ content: string,
342
+ sourceFile: ts.SourceFile,
343
+ arrayName: string,
344
+ className: string
345
+ ): string {
346
+ let decoratorNode: ts.Decorator | undefined;
347
+
348
+ sourceFile.statements.forEach((statement) => {
349
+ if (ts.isClassDeclaration(statement) && statement.modifiers) {
350
+ statement.modifiers.forEach((modifier) => {
351
+ if (ts.isDecorator(modifier)) {
352
+ const expression = modifier.expression;
353
+ if (ts.isCallExpression(expression)) {
354
+ const expressionText = expression.expression.getText(sourceFile);
355
+ if (expressionText === "Module") {
356
+ decoratorNode = modifier;
357
+ }
358
+ }
359
+ }
360
+ });
361
+ }
362
+ });
363
+
364
+ if (!decoratorNode) {
365
+ console.warn("Could not find @Module decorator");
366
+ return content;
367
+ }
368
+
369
+ const callExpression = decoratorNode.expression as ts.CallExpression;
370
+ const objectLiteral = callExpression
371
+ .arguments[0] as ts.ObjectLiteralExpression;
372
+
373
+ if (!objectLiteral || !ts.isObjectLiteralExpression(objectLiteral)) {
374
+ return content;
375
+ }
376
+
377
+ let targetProperty: ts.PropertyAssignment | undefined;
378
+ objectLiteral.properties.forEach((prop) => {
379
+ if (ts.isPropertyAssignment(prop)) {
380
+ const propName = prop.name.getText(sourceFile);
381
+ if (propName === arrayName) {
382
+ targetProperty = prop;
383
+ }
384
+ }
385
+ });
386
+
387
+ if (!targetProperty) {
388
+ console.warn(`Could not find ${arrayName} property`);
389
+ return content;
390
+ }
391
+
392
+ const arrayLiteral = targetProperty.initializer;
393
+ if (!ts.isArrayLiteralExpression(arrayLiteral)) {
394
+ return content;
395
+ }
396
+
397
+ const hasClassName = arrayLiteral.elements.some((element) => {
398
+ return element.getText(sourceFile).trim() === className;
399
+ });
400
+
401
+ if (hasClassName) {
402
+ return content;
403
+ }
404
+
405
+ const arrayStart = arrayLiteral.getStart(sourceFile);
406
+ const arrayEnd = arrayLiteral.getEnd();
407
+
408
+ if (arrayLiteral.elements.length === 0) {
409
+ const newArray = `[${className}]`;
410
+ return (
411
+ content.substring(0, arrayStart) + newArray + content.substring(arrayEnd)
412
+ );
413
+ }
414
+
415
+ const lastElement = arrayLiteral.elements[arrayLiteral.elements.length - 1];
416
+ const insertPos = lastElement.getEnd();
417
+ const newElement = `, ${className}`;
418
+
419
+ return (
420
+ content.substring(0, insertPos) + newElement + content.substring(insertPos)
421
+ );
422
+ }
423
+
424
+ function ensureComponentModuleImported(appModuleContent: string): string {
425
+ const sourceFile = ts.createSourceFile(
426
+ "app.module.ts",
427
+ appModuleContent,
428
+ ts.ScriptTarget.Latest,
429
+ true
430
+ );
431
+
432
+ const hasComponentModuleImport = sourceFile.statements.some((statement) => {
433
+ if (ts.isImportDeclaration(statement) && statement.importClause) {
434
+ const namedBindings = statement.importClause.namedBindings;
435
+ if (namedBindings && ts.isNamedImports(namedBindings)) {
436
+ return namedBindings.elements.some(
437
+ (element) => element.name.text === "ComponentModule"
438
+ );
439
+ }
440
+ }
441
+ return false;
442
+ });
443
+
444
+ if (hasComponentModuleImport) {
445
+ return ensureInImportsArray(appModuleContent, sourceFile);
446
+ }
447
+
448
+ let lastImportEnd = 0;
449
+ sourceFile.statements.forEach((statement) => {
450
+ if (ts.isImportDeclaration(statement)) {
451
+ lastImportEnd = statement.end;
452
+ }
453
+ });
454
+
455
+ const importStatement = `import { ComponentModule } from "../component/component.module";\n`;
456
+ let updatedContent =
457
+ appModuleContent.slice(0, lastImportEnd) +
458
+ "\n" +
459
+ importStatement +
460
+ appModuleContent.slice(lastImportEnd);
461
+
462
+ const newSourceFile = ts.createSourceFile(
463
+ "app.module.ts",
464
+ updatedContent,
465
+ ts.ScriptTarget.Latest,
466
+ true
467
+ );
468
+
469
+ updatedContent = ensureInImportsArray(updatedContent, newSourceFile);
470
+
471
+ return updatedContent;
472
+ }
473
+
474
+ function ensureInImportsArray(
475
+ content: string,
476
+ sourceFile: ts.SourceFile
477
+ ): string {
478
+ return addToDecoratorArray(content, sourceFile, "imports", "ComponentModule");
479
+ }
480
+
481
+ function capitalize(str: string): string {
482
+ return str.charAt(0).toUpperCase() + str.slice(1);
483
+ }
484
+
485
+ function createModule() {
486
+ return `import { Module } from "@kithinji/orca";
487
+
488
+ @Module({
489
+ imports: [],
490
+ providers: [],
491
+ declarations: [],
492
+ exports: [],
493
+ })
494
+ export class ComponentModule {}
495
+ `;
496
+ }
@@ -0,0 +1 @@
1
+ export * from "./component";
@@ -0,0 +1,3 @@
1
+ export * from "./component";
2
+ export * from "./new";
3
+ export * from "./module";
@@ -0,0 +1 @@
1
+ export * from "./module";