@xeno-js/cli 0.1.0 → 0.1.1

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 (91) hide show
  1. package/dist/index.js +3675 -18
  2. package/dist/index.js.map +1 -0
  3. package/eslint.config.mjs +1 -0
  4. package/package.json +4 -3
  5. package/tsup.config.ts +13 -0
  6. package/dist/domain/contracts/icommand-cli.contracts.js +0 -2
  7. package/dist/domain/contracts/icommand-runner.contracts.js +0 -2
  8. package/dist/domain/contracts/idispatch.contracts.js +0 -2
  9. package/dist/domain/contracts/ifile-service.contracts.js +0 -2
  10. package/dist/domain/contracts/igenerator.contracts.js +0 -2
  11. package/dist/domain/contracts/index.js +0 -2
  12. package/dist/domain/contracts/iscaffold-strategy.contracts.js +0 -2
  13. package/dist/domain/index.js +0 -2
  14. package/dist/generator.contracts.js +0 -13
  15. package/dist/infrastructure/bootstrap/bootstrapper.js +0 -32
  16. package/dist/infrastructure/bootstrap/index.js +0 -17
  17. package/dist/infrastructure/builder/builder.js +0 -16
  18. package/dist/infrastructure/builder/builder.test.js +0 -30
  19. package/dist/infrastructure/builder/index.js +0 -17
  20. package/dist/infrastructure/command_launcher/command.utils.js +0 -30
  21. package/dist/infrastructure/command_launcher/index.js +0 -2
  22. package/dist/infrastructure/commands/command-runner.service.js +0 -36
  23. package/dist/infrastructure/commands/generate.command.js +0 -48
  24. package/dist/infrastructure/commands/help.command.js +0 -44
  25. package/dist/infrastructure/commands/index.js +0 -20
  26. package/dist/infrastructure/commands/new-project.command.js +0 -43
  27. package/dist/infrastructure/dispatcher/dispatcher.js +0 -39
  28. package/dist/infrastructure/dispatcher/index.js +0 -17
  29. package/dist/infrastructure/file/file.service.js +0 -13
  30. package/dist/infrastructure/file/index.js +0 -17
  31. package/dist/infrastructure/generators/bootstrap.generator.js +0 -118
  32. package/dist/infrastructure/generators/core/bootstrap.generator.js +0 -118
  33. package/dist/infrastructure/generators/core/command/cqrs.generator.js +0 -49
  34. package/dist/infrastructure/generators/core/command/generate-command.generator.js +0 -163
  35. package/dist/infrastructure/generators/core/command/generate-query.generator.js +0 -131
  36. package/dist/infrastructure/generators/core/drizzle-sql-lite.generator.js +0 -78
  37. package/dist/infrastructure/generators/core/drizzle.generator.js +0 -85
  38. package/dist/infrastructure/generators/core/env.generator.js +0 -69
  39. package/dist/infrastructure/generators/core/index.js +0 -25
  40. package/dist/infrastructure/generators/core/main.generator.js +0 -45
  41. package/dist/infrastructure/generators/core/packagejson.generator.js +0 -78
  42. package/dist/infrastructure/generators/core/readme.generator.js +0 -431
  43. package/dist/infrastructure/generators/core/registry.generator.js +0 -46
  44. package/dist/infrastructure/generators/core/tsconfig.generator.js +0 -41
  45. package/dist/infrastructure/generators/core-packagejson.generator.js +0 -78
  46. package/dist/infrastructure/generators/drizzle-sql-lite.generator.js +0 -78
  47. package/dist/infrastructure/generators/drizzle.generator.js +0 -85
  48. package/dist/infrastructure/generators/env-vue.generator.js +0 -40
  49. package/dist/infrastructure/generators/env.generator.js +0 -71
  50. package/dist/infrastructure/generators/gitignore.generator.js +0 -62
  51. package/dist/infrastructure/generators/index.js +0 -26
  52. package/dist/infrastructure/generators/main.generator.js +0 -45
  53. package/dist/infrastructure/generators/readme.generator.js +0 -431
  54. package/dist/infrastructure/generators/registry.generator.js +0 -46
  55. package/dist/infrastructure/generators/tsconfig-vue.generator.js +0 -39
  56. package/dist/infrastructure/generators/tsconfig.generator.js +0 -41
  57. package/dist/infrastructure/generators/vite-config.generator.js +0 -39
  58. package/dist/infrastructure/generators/vue/app-vue.generator.js +0 -26
  59. package/dist/infrastructure/generators/vue/bootstrap-ts.generator.js +0 -59
  60. package/dist/infrastructure/generators/vue/command_query/cqrs.generator.js +0 -36
  61. package/dist/infrastructure/generators/vue/command_query/generate-command-vue.generator.js +0 -139
  62. package/dist/infrastructure/generators/vue/command_query/generate-query-vue.generator.js +0 -147
  63. package/dist/infrastructure/generators/vue/env.generator.js +0 -40
  64. package/dist/infrastructure/generators/vue/index-html.generator.js +0 -29
  65. package/dist/infrastructure/generators/vue/index.js +0 -28
  66. package/dist/infrastructure/generators/vue/main.generator.js +0 -45
  67. package/dist/infrastructure/generators/vue/packagejson.generator.js +0 -59
  68. package/dist/infrastructure/generators/vue/readme.generator.js +0 -394
  69. package/dist/infrastructure/generators/vue/registry-ts.generator.js +0 -28
  70. package/dist/infrastructure/generators/vue/router.generator.js +0 -33
  71. package/dist/infrastructure/generators/vue/tailwind.generator.js +0 -19
  72. package/dist/infrastructure/generators/vue/tsconfig.generator.js +0 -39
  73. package/dist/infrastructure/generators/vue/use-app.generator.js +0 -43
  74. package/dist/infrastructure/generators/vue/vite-config.generator.js +0 -39
  75. package/dist/infrastructure/generators/vue-packagejson.generator.js +0 -59
  76. package/dist/infrastructure/generators/vue-readme.generator.js +0 -53
  77. package/dist/infrastructure/generators/vue-source-files.generator.js +0 -136
  78. package/dist/infrastructure/index.js +0 -21
  79. package/dist/infrastructure/strategies/core-scaffold.strategy.js +0 -99
  80. package/dist/infrastructure/strategies/index.js +0 -18
  81. package/dist/infrastructure/strategies/vue-scaffold.strategy.js +0 -79
  82. package/dist/scaffolding.engine.js +0 -60
  83. package/dist/shared/constants/command.constants.js +0 -19
  84. package/dist/shared/constants/core.constants.js +0 -10
  85. package/dist/shared/constants/index.js +0 -18
  86. package/dist/shared/index.js +0 -18
  87. package/dist/shared/types/common.types.js +0 -2
  88. package/dist/shared/types/index.js +0 -2
  89. package/dist/shared/utils/guards.utils.js +0 -310
  90. package/dist/shared/utils/index.js +0 -18
  91. package/dist/shared/utils/string.utils.js +0 -62
@@ -1,49 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CqrsGenerator = void 0;
7
- const promises_1 = __importDefault(require("node:fs/promises"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- const shared_1 = require("../../../../shared");
10
- class CqrsGenerator {
11
- _fileService;
12
- constructor(_fileService) {
13
- this._fileService = _fileService;
14
- }
15
- async generate(targetDir, name, type, outputPath) {
16
- const pascalName = shared_1.StringUtils.pascalCase(name);
17
- const tokenPrefix = shared_1.StringUtils.splitCamelCaseWithUnderscore(pascalName).toUpperCase();
18
- const lowerName = name.toLowerCase();
19
- const destinationFolder = outputPath ?? lowerName;
20
- const componentDir = node_path_1.default.join(targetDir, 'src', destinationFolder);
21
- let hasZod = false;
22
- let hasDrizzle = false;
23
- try {
24
- const pkgJsonStr = await promises_1.default.readFile(node_path_1.default.join(targetDir, 'package.json'), 'utf8');
25
- const pkgJson = JSON.parse(pkgJsonStr);
26
- const deps = { ...(pkgJson.dependencies ?? {}), ...(pkgJson.devDependencies ?? {}) };
27
- hasZod = !!shared_1.Guards.isDefined(deps['zod']);
28
- hasDrizzle = !!shared_1.Guards.isDefined(deps['drizzle-orm']);
29
- }
30
- catch (error) {
31
- console.warn(' Warning: Could not read package.json. Assuming Zod and Drizzle are not installed.', error);
32
- }
33
- switch (type) {
34
- case shared_1.COMMAND_CONSTANTS.COMMAND: {
35
- const { GenerateCommandCoreGenerator } = await import('./generate-command.generator.js');
36
- const generator = new GenerateCommandCoreGenerator(this._fileService);
37
- return generator.generate(pascalName, lowerName, tokenPrefix, componentDir, hasZod, hasDrizzle);
38
- }
39
- case shared_1.COMMAND_CONSTANTS.QUERY: {
40
- const { GenerateQueryCoreGenerator } = await import('./generate-query.generator.js');
41
- const generatorQuery = new GenerateQueryCoreGenerator(this._fileService);
42
- return generatorQuery.generate(pascalName, lowerName, tokenPrefix, componentDir, hasZod);
43
- }
44
- default:
45
- throw new Error(`Unsupported generator type: '${String(type)}'. Use 'command' or 'query'.`);
46
- }
47
- }
48
- }
49
- exports.CqrsGenerator = CqrsGenerator;
@@ -1,163 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.GenerateCommandCoreGenerator = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- class GenerateCommandCoreGenerator {
9
- _fileService;
10
- constructor(_fileService) {
11
- this._fileService = _fileService;
12
- }
13
- async generate(pascalName, lowerName, tokenPrefix, componentDir, hasZod, hasDrizzle) {
14
- // 1. Command
15
- const commandContent = `import { Command } from '@xeno-js/core';
16
-
17
- /*
18
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
19
- * Please replace <any> with your specific payload and response types.
20
- */
21
- export class ${pascalName}Command extends Command<any> {
22
- constructor(public readonly payload: any) {
23
- super('${tokenPrefix}_COMMAND_HANDLER');
24
- }
25
- }
26
- `;
27
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.command.ts`), commandContent);
28
- // 2. Handler
29
- const handlerContent = `import type { IFactory, ResultType, UserContext } from '@xeno-js/core';
30
- import { AppError, BaseHandler, Result } from '@xeno-js/core';
31
- import { ${pascalName}Command } from './${lowerName}.command';
32
-
33
- /*
34
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
35
- * Please replace <any> with your specific response type.
36
- */
37
- export class ${pascalName}Handler extends BaseHandler<${pascalName}Command, any> {
38
- constructor(
39
- identityFactory: IFactory<void, UserContext>
40
- ) {
41
- super(identityFactory);
42
- }
43
-
44
- public async executeAsync(request: ${pascalName}Command, singal: AbortSignal): Promise<ResultType<any>> {
45
- // TODO: Implement your business logic here
46
-
47
- return Result.ok();
48
- }
49
- }
50
- `;
51
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.handler.ts`), handlerContent);
52
- // 3. Controller
53
- const controllerContent = `import type { IContextAccessor, IMediator, RequestContext, ResponseDto } from '@xeno-js/core';
54
- import { BaseController } from '@xeno-js/core';
55
- import { ${pascalName}Command } from './${lowerName}.command';
56
-
57
- /*
58
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
59
- * Please replace <any, any> with your specific request and response types.
60
- */
61
- export class ${pascalName}Controller extends BaseController<any, any> {
62
- constructor(
63
- requestContext: IContextAccessor<RequestContext>,
64
- mediator: IMediator,
65
- ) {
66
- super(requestContext, mediator);
67
- }
68
-
69
- public async handle(request: any): Promise<ResponseDto<any>> {
70
- const cmd = new ${pascalName}Command(request);
71
- const result = await this._send(cmd);
72
-
73
- if (!result.isOk()) {
74
- return this.fail(result.getErrorOrThrow(), 'Error during ${pascalName} operation');
75
- }
76
-
77
- return this.ok(result.getValueOrThrow());
78
- }
79
- }
80
- `;
81
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.controller.ts`), controllerContent);
82
- // 4. Entity
83
- const entityContent = `import { Entity } from '@xeno-js/core';
84
-
85
- export interface ${pascalName}Props {
86
- // TODO: Define your entity properties
87
- }
88
-
89
- /*
90
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
91
- * Adjust the properties and types according to your domain logic.
92
- */
93
- export class ${pascalName} extends Entity<${pascalName}Props> {
94
- private constructor(props: ${pascalName}Props, id?: string) {
95
- super(props, id);
96
- }
97
-
98
- static create(props: ${pascalName}Props, id?: string): ${pascalName} {
99
- return new ${pascalName}(props, id);
100
- }
101
- }
102
- `;
103
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.entity.ts`), entityContent);
104
- // 5. Schema Zod (Condizionale)
105
- if (hasZod) {
106
- const zodContent = `import { z } from 'zod';
107
- import { ZodUtils } from '@xeno-js/core';
108
-
109
- /*
110
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
111
- * Define the actual Zod validation schema for your command payload.
112
- */
113
- export const ${pascalName}Schema = ZodUtils.createCommandSchema({
114
- payload: z.any() // TODO: Update with strict validation
115
- });
116
- `;
117
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.schema-zod.ts`), zodContent);
118
- }
119
- // 6. Schema DB (Condizionale)
120
- if (hasDrizzle) {
121
- const dbContent = `import { pgTable, text, timestamp } from 'drizzle-orm/pg-core';
122
- // Note: If you are using SQLite, change the import to 'drizzle-orm/sqlite-core' and update the table definition.
123
-
124
- /*
125
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
126
- * Update the schema definition with your actual database columns.
127
- */
128
- export const ${lowerName}s = pgTable('${lowerName}s', {
129
- id: text('id').primaryKey(),
130
- createdAt: timestamp('created_at').defaultNow(),
131
- updatedAt: timestamp('updated_at').defaultNow().$onUpdate(() => new Date()),
132
- });
133
-
134
- export type ${pascalName}Dto = typeof ${lowerName}s.$inferSelect;
135
- export type New${pascalName}Dto = typeof ${lowerName}s.$inferInsert;
136
- `;
137
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.schema-db.ts`), dbContent);
138
- }
139
- // 7. Module
140
- const moduleContent = `import type { IServiceContainer, IConfigurationService } from '@xeno-js/core';
141
- import { TOKENS } from '@xeno-js/core';
142
- import { ${pascalName}Controller } from './${lowerName}.controller';
143
- import { ${pascalName}Handler } from './${lowerName}.handler';
144
-
145
- export const ${pascalName}Module = Object.freeze({
146
- register(opts: IServiceContainer<any>, _config: IConfigurationService): void {
147
- opts.addTransient('${tokenPrefix}_COMMAND_CONTROLLER', (c) => new ${pascalName}Controller(c.resolve(TOKENS.REQUEST_CONTEXT), c.resolve(TOKENS.MEDIATOR)));
148
- opts.addScoped('${tokenPrefix}_COMMAND_HANDLER', (c) => new ${pascalName}Handler(c.resolve(TOKENS.USER_CONTEXT_FACTORY)));
149
-
150
- /*
151
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
152
- * Please copy and paste the following tokens to your MyRegistry interface (usually in src/registry.ts):
153
- *
154
- * ${tokenPrefix}_COMMAND_CONTROLLER: IController<any, any>;
155
- * ${tokenPrefix}_COMMAND_HANDLER: IHandler<${pascalName}Command, any>;
156
- */
157
- }
158
- } as const);
159
- `;
160
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.module.ts`), moduleContent);
161
- }
162
- }
163
- exports.GenerateCommandCoreGenerator = GenerateCommandCoreGenerator;
@@ -1,131 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.GenerateQueryCoreGenerator = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- class GenerateQueryCoreGenerator {
9
- _fileService;
10
- constructor(_fileService) {
11
- this._fileService = _fileService;
12
- }
13
- async generate(pascalName, lowerName, tokenPrefix, componentDir, hasZod) {
14
- const queryContent = `import { BaseQuery } from '@xeno-js/core';
15
-
16
- /*
17
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
18
- * Please replace <any> with your specific payload and response types.
19
- */
20
- export class ${pascalName}Query extends BaseQuery<any> {
21
- constructor(public readonly payload: any) {
22
- super(
23
- '${tokenPrefix}_QUERY_HANDLER',
24
- // Default cache options:
25
- {
26
- ttl: 60,
27
- cacheKey: \`${lowerName}:\${JSON.stringify(payload)}\`,
28
- bypassCache: false,
29
- consistentRead: false
30
- isUserScoped: false,
31
- }
32
- );
33
- }
34
- }
35
- `;
36
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.query.ts`), queryContent);
37
- // 2. Handler
38
- const handlerContent = `import type { IFactory, ResultType, UserContext } from '@xeno-js/core';
39
- import { AppError, BaseHandler, Result } from '@xeno-js/core';
40
- import { ${pascalName}Query } from './${lowerName}.query';
41
-
42
- /*
43
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
44
- * Please replace <any> with your specific response type.
45
- */
46
- export class ${pascalName}Handler extends BaseHandler<${pascalName}Query, any> {
47
- constructor(
48
- identityFactory: IFactory<void, UserContext>
49
- // TODO: Inject your ReadDao or DataSource here
50
- ) {
51
- super(identityFactory);
52
- }
53
-
54
- public async executeAsync(request: ${pascalName}Query, singal: AbortSignal): Promise<ResultType<any>> {
55
- // TODO: Implement your query logic here
56
-
57
- return Result.ok();
58
- }
59
- }
60
- `;
61
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.handler.ts`), handlerContent);
62
- // 3. Controller
63
- const controllerContent = `import type { IContextAccessor, IMediator, RequestContext, ResponseDto } from '@xeno-js/core';
64
- import { BaseController } from '@xeno-js/core';
65
- import { ${pascalName}Query } from './${lowerName}.query';
66
-
67
- /*
68
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
69
- * Please replace <any, any> with your specific request and response types.
70
- */
71
- export class ${pascalName}Controller extends BaseController<any, any> {
72
- constructor(
73
- requestContext: IContextAccessor<RequestContext>,
74
- mediator: IMediator,
75
- ) {
76
- super(requestContext, mediator);
77
- }
78
-
79
- public async handle(request: any): Promise<ResponseDto<any>> {
80
- const query = new ${pascalName}Query(request);
81
- const result = await this._query(query);
82
-
83
- if (!result.isOk()) {
84
- return this.fail(result.getErrorOrThrow(), 'Error during ${pascalName} operation');
85
- }
86
-
87
- return this.ok(result.getValueOrThrow());
88
- }
89
- }
90
- `;
91
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.controller.ts`), controllerContent);
92
- // 4. Schema Zod
93
- if (hasZod) {
94
- const zodContent = `import { z } from 'zod';
95
- import { ZodUtils } from '@xeno-js/core';
96
-
97
- /*
98
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
99
- * Define the actual Zod validation schema for your query payload.
100
- */
101
- export const ${pascalName}Schema = ZodUtils.createQuerySchema({
102
- payload: z.any() // TODO: Update with strict validation
103
- });
104
- `;
105
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.schema-zod.ts`), zodContent);
106
- }
107
- // 5. Module
108
- const moduleContent = `import type { IServiceContainer, IConfigurationService } from '@xeno-js/core';
109
- import { TOKENS } from '@xeno-js/core';
110
- import { ${pascalName}Controller } from './${lowerName}.controller';
111
- import { ${pascalName}Handler } from './${lowerName}.handler';
112
-
113
- export const ${pascalName}Module = Object.freeze({
114
- register(opts: IServiceContainer<any>, _config: IConfigurationService): void {
115
- opts.addTransient('${tokenPrefix}_QUERY_CONTROLLER', (c) => new ${pascalName}Controller(c.resolve(TOKENS.REQUEST_CONTEXT), c.resolve(TOKENS.MEDIATOR)));
116
- opts.addScoped('${tokenPrefix}_QUERY_HANDLER', (c) => new ${pascalName}Handler(c.resolve(TOKENS.USER_CONTEXT_FACTORY)));
117
-
118
- /*
119
- * ⚠️ WARNING: ACTION REQUIRED ⚠️
120
- * Please copy and paste the following tokens to your MyRegistry interface (usually in src/registry.ts):
121
- *
122
- * ${tokenPrefix}_QUERY_CONTROLLER: IController<any, any>;
123
- * ${tokenPrefix}_QUERY_HANDLER: IHandler<${pascalName}Query, any>;
124
- */
125
- }
126
- } as const);
127
- `;
128
- await this._fileService.writeFileRecursive(node_path_1.default.join(componentDir, `${lowerName}.module.ts`), moduleContent);
129
- }
130
- }
131
- exports.GenerateQueryCoreGenerator = GenerateQueryCoreGenerator;
@@ -1,78 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DrizzleSqlLiteGenerator = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- /**
9
- * @class DrizzleSqlLiteGenerator
10
- * @description Generates a Drizzle configuration file (drizzle.config.ts) and a
11
- * SQLite schema example (src/infrastructure/db/sqlite-schema.ts) when the user
12
- * opts to use SQLite/libSQL instead of Postgres.
13
- */
14
- class DrizzleSqlLiteGenerator {
15
- _fileService;
16
- constructor(_fileService) {
17
- this._fileService = _fileService;
18
- }
19
- async generate(projectPath, _options) {
20
- const configContent = this.composeDrizzleConfig();
21
- const filePath = node_path_1.default.join(projectPath, 'drizzle.config.ts');
22
- await this._fileService.writeFileRecursive(filePath, configContent);
23
- const schemaPath = node_path_1.default.join(projectPath, 'src', 'schema.ts');
24
- const schemaContent = this.composeSchema();
25
- await this._fileService.writeFileRecursive(schemaPath, schemaContent);
26
- }
27
- composeDrizzleConfig() {
28
- return `import 'dotenv/config';
29
- import { defineConfig } from 'drizzle-kit';
30
-
31
- /**
32
- * Drizzle Kit configuration for SQLite / libSQL.
33
- * Uses environment variable SQLITE_DATABASE_URL to locate the database.
34
- */
35
- export default defineConfig({
36
- schema: './src/schema.ts',
37
- out: './drizzle',
38
- dialect: 'sqlite',
39
- dbCredentials: {
40
- url: process.env.SQLITE_DATABASE_URL!,
41
- },
42
- verbose: true,
43
- strict: true,
44
- });
45
- `;
46
- }
47
- composeSchema() {
48
- return `import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
49
-
50
- /**
51
- * Example SQLite schema using Drizzle's libsql primitives.
52
- * Place your application tables here (this file is scaffolded by the CLI when
53
- * the user opts into SQLite support).
54
- */
55
- export const usersTable = sqliteTable('users', {
56
- id: integer('id').primaryKey().notNull(),
57
- name: text('name').notNull(),
58
- description: text('description'),
59
- });
60
-
61
- /**
62
- * Types inferred from the schema.
63
- * - UserDto: Represents the shape of the data retrieved from the database ($inferSelect).
64
- * - NewUserDto: Represents the shape of the data required to insert a new record ($inferInsert).
65
- */
66
- export type UserDto = typeof usersTable.$inferSelect;
67
- export type NewUserDto = typeof usersTable.$inferInsert;
68
-
69
- /**
70
- * Centralized Database Schema dictionary.
71
- */
72
- export type SqliteSchema = {
73
- users: typeof usersTable;
74
- };
75
- `;
76
- }
77
- }
78
- exports.DrizzleSqlLiteGenerator = DrizzleSqlLiteGenerator;
@@ -1,85 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DrizzleGenerator = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- /**
9
- * @class DrizzleGenerator
10
- * @description Generates the Drizzle configuration file (drizzle.config.ts) and a basic schema file (src/schema.ts) for database scaffolding.
11
- * The generator is only invoked if the user has opted to include database support in their project.
12
- *
13
- * @author Xeno
14
- * @version 1.0.0
15
- * @license ISC
16
- * @since 2025-09-30
17
- * @link https://github.com/xeno-js/xeno-js
18
- */
19
- class DrizzleGenerator {
20
- _fileService;
21
- constructor(_fileService) {
22
- this._fileService = _fileService;
23
- }
24
- async generate(projectPath, _options) {
25
- const configContent = this.composeDrizzleConfig();
26
- const filePath = node_path_1.default.join(projectPath, 'drizzle.config.ts');
27
- await this._fileService.writeFileRecursive(filePath, configContent);
28
- const schemaContent = this.composeSchema();
29
- await this._fileService.writeFileRecursive(node_path_1.default.join(projectPath, 'src', 'schema.ts'), schemaContent);
30
- }
31
- composeDrizzleConfig() {
32
- return `import 'dotenv/config';
33
- import { defineConfig } from 'drizzle-kit';
34
-
35
- /**
36
- * Drizzle Kit configuration file.
37
- * Defines the schema location, migration output directory, and database connection.
38
- */
39
- export default defineConfig({
40
- schema: './src/schema.ts',
41
- out: './drizzle',
42
- dialect: 'postgresql',
43
- dbCredentials: {
44
- url: process.env.DATABASE_URL!,
45
- },
46
- verbose: true,
47
- strict: true,
48
- });
49
- `;
50
- }
51
- composeSchema() {
52
- return `import { boolean, pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
53
-
54
- /**
55
- * @description Define your database tables here.
56
- * The 'usersTable' serves as a baseline example.
57
- * You can add more tables, relations, and indexes according to your domain requirements.
58
- */
59
- export const usersTable = pgTable('users', {
60
- id: serial('id').primaryKey(),
61
- name: text('name').notNull(),
62
- email: text('email').notNull().unique(),
63
- isDeleted: boolean('is_deleted').notNull().default(false),
64
- deletedAt: timestamp('deleted_at'),
65
- createdAt: timestamp('created_at').defaultNow(),
66
- });
67
-
68
- /**
69
- * Types inferred from the schema.
70
- * - UserDto: Represents the shape of the data retrieved from the database ($inferSelect).
71
- * - NewUserDto: Represents the shape of the data required to insert a new record ($inferInsert).
72
- */
73
- export type UserDto = typeof usersTable.$inferSelect;
74
- export type NewUserDto = typeof usersTable.$inferInsert;
75
-
76
- /**
77
- * Centralized Database Schema dictionary.
78
- */
79
- export type DbSchema = {
80
- users: typeof usersTable;
81
- };
82
- `;
83
- }
84
- }
85
- exports.DrizzleGenerator = DrizzleGenerator;
@@ -1,69 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.EnvGenerator = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- const shared_1 = require("../../../shared");
9
- class EnvGenerator {
10
- _fileService;
11
- constructor(_fileService) {
12
- this._fileService = _fileService;
13
- }
14
- async generate(projectPath, options) {
15
- let content = `# ─────────────────────────────────────────────────────────────────────────────
16
- # Xeno APPLICATION ENVIRONMENT VARIABLES
17
- # ─────────────────────────────────────────────────────────────────────────────
18
- NODE_ENV=development
19
- `;
20
- // Configurazione Database
21
- if (options.database !== shared_1.CORE_CONSTANTS.NONE) {
22
- if (options.database === shared_1.CORE_CONSTANTS.DRIZZLE) {
23
- content += `\n# --- Database (PostgreSQL) ---
24
- DATABASE_URL=postgres://postgres:password@localhost:5432/xeno_db
25
- `;
26
- }
27
- else if (options.database === shared_1.CORE_CONSTANTS.SQL_LITE) {
28
- content += `\n# --- Database (SQLite) ---
29
- SQLITE_DATABASE_URL=file:./dev.sqlite
30
- `;
31
- }
32
- }
33
- if (options.axios) {
34
- content += `\n# --- Axios ---
35
- BASE_URL=
36
- `;
37
- }
38
- // Configurazione Redis (Caching, Idempotenza, Concorrenza)
39
- if (options.redis) {
40
- content += `\n# --- Cache (Redis) ---
41
- REDIS_HOST=localhost
42
- REDIS_PORT=6379
43
- REDIS_PASSWORD=
44
- REDIS_USERNAME=
45
- REDIS_TLS=false
46
- `;
47
- }
48
- // Configurazione Supabase (Autenticazione)
49
- if (options.supabase) {
50
- content += `\n# --- Authentication (Supabase) ---
51
- SUPABASE_URL=https://your-project.supabase.co
52
- SUPABASE_KEY=your-anon-key
53
- `;
54
- }
55
- // Configurazione Logging & Observability
56
- if (options.sentry) {
57
- content += `\n# --- Error Tracking (Sentry) ---
58
- SENTRY_DSN=https://your-sentry-dsn@o0.ingest.sentry.io/0
59
- SENTRY_ENVIRONMENT=development
60
- `;
61
- }
62
- // Creiamo sia il file effettivo che il file di esempio
63
- const envPath = node_path_1.default.join(projectPath, '.env');
64
- const envExamplePath = node_path_1.default.join(projectPath, '.env.example');
65
- await this._fileService.writeFileRecursive(envPath, content);
66
- await this._fileService.writeFileRecursive(envExamplePath, content);
67
- }
68
- }
69
- exports.EnvGenerator = EnvGenerator;
@@ -1,25 +0,0 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./bootstrap.generator"), exports);
18
- __exportStar(require("./drizzle.generator"), exports);
19
- __exportStar(require("./drizzle-sql-lite.generator"), exports);
20
- __exportStar(require("./env.generator"), exports);
21
- __exportStar(require("./main.generator"), exports);
22
- __exportStar(require("./packagejson.generator"), exports);
23
- __exportStar(require("./readme.generator"), exports);
24
- __exportStar(require("./registry.generator"), exports);
25
- __exportStar(require("./tsconfig.generator"), exports);
@@ -1,45 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.MainGenerator = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- class MainGenerator {
9
- _fileService;
10
- constructor(_fileService) {
11
- this._fileService = _fileService;
12
- }
13
- async generate(projectPath, options) {
14
- const content = `import 'dotenv/config';
15
- import { bootstrap } from './bootstrap';
16
- import { TOKENS } from '@xeno-js/core';
17
-
18
- /**
19
- * Main Application Entry Point
20
- */
21
- async function main() {
22
- try {
23
- console.info('⏳ Bootstrapping ${options.targetDir} application...');
24
-
25
- // Initialize the dependency injection container and infrastructure modules
26
- const container = await bootstrap();
27
-
28
- const logger = container.resolve(TOKENS.LOGGER)
29
- logger.info('✅ Application started successfully!');
30
-
31
- // TODO: Implement your logic here
32
-
33
- } catch (error) {
34
- console.error('❌ Critical error during startup:', error);
35
- process.exit(1);
36
- }
37
- }
38
-
39
- main();
40
- `;
41
- const filePath = node_path_1.default.join(projectPath, 'src', 'main.ts');
42
- await this._fileService.writeFileRecursive(filePath, content);
43
- }
44
- }
45
- exports.MainGenerator = MainGenerator;