@currentjs/gen 0.5.5 → 0.5.7

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.
@@ -44,6 +44,7 @@ const typeUtils_1 = require("../utils/typeUtils");
44
44
  class UseCaseGenerator {
45
45
  constructor() {
46
46
  this.availableAggregates = new Map();
47
+ this.identifiers = 'numeric';
47
48
  }
48
49
  generateUseCaseMethod(modelName, actionName, useCaseConfig) {
49
50
  const methodName = actionName;
@@ -100,7 +101,7 @@ class UseCaseGenerator {
100
101
  }).join('\n');
101
102
  const returnStatement = '\n return result;';
102
103
  const methodParams = actionName === 'list'
103
- ? `input: ${inputType}, ownerId?: number`
104
+ ? `input: ${inputType}, ownerId?: ${(0, configTypes_1.idTsType)(this.identifiers)}`
104
105
  : `input: ${inputType}`;
105
106
  return ` async ${methodName}(${methodParams}): Promise<${returnType}> {
106
107
  ${handlerCalls}${returnStatement}
@@ -108,12 +109,13 @@ ${handlerCalls}${returnStatement}
108
109
  }
109
110
  generateGetResourceOwnerMethod(modelName) {
110
111
  const serviceVar = `${modelName.toLowerCase()}Service`;
112
+ const idTs = (0, configTypes_1.idTsType)(this.identifiers);
111
113
  return `
112
114
  /**
113
115
  * Get the owner ID of a resource by its ID.
114
116
  * Used for pre-mutation authorization checks in controllers.
115
117
  */
116
- async getResourceOwner(id: number): Promise<number | null> {
118
+ async getResourceOwner(id: ${idTs}): Promise<${idTs} | null> {
117
119
  return await this.${serviceVar}.getResourceOwner(id);
118
120
  }`;
119
121
  }
@@ -151,9 +153,10 @@ export class ${className} {
151
153
  ${methods}${getResourceOwnerMethod}
152
154
  }`;
153
155
  }
154
- generateFromConfig(config) {
156
+ generateFromConfig(config, identifiers = 'numeric') {
155
157
  var _a;
156
158
  const result = {};
159
+ this.identifiers = identifiers;
157
160
  // Collect all aggregates to know which are roots
158
161
  this.availableAggregates.clear();
159
162
  if ((_a = config.domain) === null || _a === void 0 ? void 0 : _a.aggregates) {
@@ -167,16 +170,16 @@ ${methods}${getResourceOwnerMethod}
167
170
  });
168
171
  return result;
169
172
  }
170
- generateFromYamlFile(yamlFilePath) {
173
+ generateFromYamlFile(yamlFilePath, identifiers = 'numeric') {
171
174
  const yamlContent = fs.readFileSync(yamlFilePath, 'utf8');
172
175
  const config = (0, yaml_1.parse)(yamlContent);
173
176
  if (!(0, configTypes_1.isValidModuleConfig)(config)) {
174
177
  throw new Error('Configuration does not match new module format. Expected useCases structure.');
175
178
  }
176
- return this.generateFromConfig(config);
179
+ return this.generateFromConfig(config, identifiers);
177
180
  }
178
- async generateAndSaveFiles(yamlFilePath, moduleDir, opts) {
179
- const useCasesByModel = this.generateFromYamlFile(yamlFilePath);
181
+ async generateAndSaveFiles(yamlFilePath, moduleDir, opts, identifiers = 'numeric') {
182
+ const useCasesByModel = this.generateFromYamlFile(yamlFilePath, identifiers);
180
183
  const useCasesDir = path.join(moduleDir, 'application', 'useCases');
181
184
  fs.mkdirSync(useCasesDir, { recursive: true });
182
185
  for (const [modelName, code] of Object.entries(useCasesByModel)) {
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Type definitions for the Clean Architecture module configuration
3
3
  */
4
+ export type IdentifierType = 'numeric' | 'uuid' | 'nanoid';
5
+ export declare function normalizeIdentifierType(value: string): IdentifierType;
6
+ export declare function idTsType(identifiers: IdentifierType): 'number' | 'string';
4
7
  export interface FieldDefinition {
5
8
  type: string;
6
9
  constraints?: {
@@ -3,7 +3,22 @@
3
3
  * Type definitions for the Clean Architecture module configuration
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.normalizeIdentifierType = normalizeIdentifierType;
7
+ exports.idTsType = idTsType;
6
8
  exports.isValidModuleConfig = isValidModuleConfig;
9
+ function normalizeIdentifierType(value) {
10
+ const lower = value.toLowerCase();
11
+ if (lower === 'id' || lower === 'numeric')
12
+ return 'numeric';
13
+ if (lower === 'uuid')
14
+ return 'uuid';
15
+ if (lower === 'nanoid')
16
+ return 'nanoid';
17
+ throw new Error(`Unknown identifier type: "${value}". Expected: numeric, uuid, or nanoid`);
18
+ }
19
+ function idTsType(identifiers) {
20
+ return identifiers === 'numeric' ? 'number' : 'string';
21
+ }
7
22
  // Type guard to validate module config (domain + useCases)
8
23
  function isValidModuleConfig(config) {
9
24
  return config && typeof config === 'object' && 'domain' in config && 'useCases' in config;
@@ -28,7 +28,7 @@ export interface ModuleEntryResolved {
28
28
  path: string;
29
29
  database: string;
30
30
  styling: string;
31
- identifiers: string;
31
+ identifiers: import('../types/configTypes').IdentifierType;
32
32
  }
33
33
  export declare function getModuleEntries(config: AppConfig): ModuleEntryResolved[];
34
34
  export declare function shouldIncludeModule(moduleYamlRel: string, moduleName?: string): boolean;
@@ -51,9 +51,10 @@ const serviceGenerator_1 = require("../generators/serviceGenerator");
51
51
  const controllerGenerator_1 = require("../generators/controllerGenerator");
52
52
  const storeGenerator_1 = require("../generators/storeGenerator");
53
53
  const templateGenerator_1 = require("../generators/templateGenerator");
54
+ const configTypes_1 = require("../types/configTypes");
54
55
  const DEFAULT_DATABASE = 'mysql';
55
56
  const DEFAULT_STYLING = 'bootstrap';
56
- const DEFAULT_IDENTIFIERS = 'id';
57
+ const DEFAULT_IDENTIFIERS = 'numeric';
57
58
  function loadAppConfig(yamlPath) {
58
59
  const raw = fs.readFileSync(yamlPath, 'utf8');
59
60
  const parsed = (0, yaml_1.parse)(raw);
@@ -81,7 +82,8 @@ function getModuleEntries(config) {
81
82
  const global = config.config || {};
82
83
  const database = (_a = global.database) !== null && _a !== void 0 ? _a : DEFAULT_DATABASE;
83
84
  const styling = (_b = global.styling) !== null && _b !== void 0 ? _b : DEFAULT_STYLING;
84
- const identifiers = (_c = global.identifiers) !== null && _c !== void 0 ? _c : DEFAULT_IDENTIFIERS;
85
+ const rawIdentifiers = (_c = global.identifiers) !== null && _c !== void 0 ? _c : DEFAULT_IDENTIFIERS;
86
+ const identifiers = (0, configTypes_1.normalizeIdentifierType)(rawIdentifiers);
85
87
  const globalConfig = { database, styling, identifiers };
86
88
  return Object.entries(config.modules).map(([name, entry]) => {
87
89
  var _a, _b, _c;
@@ -90,7 +92,7 @@ function getModuleEntries(config) {
90
92
  path: entry.path,
91
93
  database: (_a = entry.database) !== null && _a !== void 0 ? _a : globalConfig.database,
92
94
  styling: (_b = entry.styling) !== null && _b !== void 0 ? _b : globalConfig.styling,
93
- identifiers: (_c = entry.identifiers) !== null && _c !== void 0 ? _c : globalConfig.identifiers
95
+ identifiers: (0, configTypes_1.normalizeIdentifierType)((_c = entry.identifiers) !== null && _c !== void 0 ? _c : globalConfig.identifiers)
94
96
  });
95
97
  });
96
98
  }
@@ -1,4 +1,4 @@
1
- import { AggregateConfig, AggregateFieldConfig } from '../types/configTypes';
1
+ import { AggregateConfig, AggregateFieldConfig, IdentifierType } from '../types/configTypes';
2
2
  export interface SchemaState {
3
3
  aggregates: Record<string, AggregateConfig>;
4
4
  version: string;
@@ -21,7 +21,9 @@ export interface ForeignKeyInfo {
21
21
  REFERENCED_TABLE_NAME: string;
22
22
  REFERENCED_COLUMN_NAME: string;
23
23
  }
24
- export declare function mapYamlTypeToSql(yamlType: string, availableAggregates: Set<string>, availableValueObjects?: Set<string>): string;
24
+ export declare function getIdColumnDefinition(idType?: IdentifierType): string;
25
+ export declare function getFkColumnType(idType?: IdentifierType): string;
26
+ export declare function mapYamlTypeToSql(yamlType: string, availableAggregates: Set<string>, availableValueObjects?: Set<string>, identifiers?: IdentifierType): string;
25
27
  /** Table name matches the store convention: singular lowercase aggregate name. */
26
28
  export declare function getTableName(aggregateName: string): string;
27
29
  export declare function getForeignKeyFieldName(fieldName: string): string;
@@ -31,15 +33,15 @@ export declare function isRelationshipField(fieldType: string, availableAggregat
31
33
  * Used to determine parent ID column names for child entity tables.
32
34
  */
33
35
  export declare function buildChildToParentMap(aggregates: Record<string, AggregateConfig>): Map<string, string>;
34
- export declare function generateCreateTableSQL(name: string, aggregate: AggregateConfig, availableAggregates: Set<string>, availableValueObjects?: Set<string>, parentIdField?: string): string;
36
+ export declare function generateCreateTableSQL(name: string, aggregate: AggregateConfig, availableAggregates: Set<string>, availableValueObjects?: Set<string>, parentIdField?: string, identifiers?: IdentifierType): string;
35
37
  export declare function generateDropTableSQL(tableName: string): string;
36
- export declare function generateAddColumnSQL(tableName: string, fieldName: string, field: AggregateFieldConfig, availableAggregates: Set<string>, availableValueObjects?: Set<string>): string;
38
+ export declare function generateAddColumnSQL(tableName: string, fieldName: string, field: AggregateFieldConfig, availableAggregates: Set<string>, availableValueObjects?: Set<string>, identifiers?: IdentifierType): string;
37
39
  export declare function generateDropColumnSQL(tableName: string, columnName: string): string;
38
- export declare function generateModifyColumnSQL(tableName: string, fieldName: string, field: AggregateFieldConfig, availableAggregates: Set<string>, availableValueObjects?: Set<string>): string;
40
+ export declare function generateModifyColumnSQL(tableName: string, fieldName: string, field: AggregateFieldConfig, availableAggregates: Set<string>, availableValueObjects?: Set<string>, identifiers?: IdentifierType): string;
39
41
  export declare function loadSchemaState(stateFilePath: string): SchemaState | null;
40
42
  export declare function saveSchemaState(stateFilePath: string, state: SchemaState): void;
41
43
  export declare function loadMigrationLog(logFilePath: string): MigrationLog;
42
44
  export declare function saveMigrationLog(logFilePath: string, log: MigrationLog): void;
43
- export declare function compareSchemas(oldState: SchemaState | null, newAggregates: Record<string, AggregateConfig>, availableValueObjects?: Set<string>): string[];
45
+ export declare function compareSchemas(oldState: SchemaState | null, newAggregates: Record<string, AggregateConfig>, availableValueObjects?: Set<string>, identifiers?: IdentifierType): string[];
44
46
  export declare function generateTimestamp(): string;
45
47
  export declare function getMigrationFileName(timestamp: string): string;
@@ -33,6 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getIdColumnDefinition = getIdColumnDefinition;
37
+ exports.getFkColumnType = getFkColumnType;
36
38
  exports.mapYamlTypeToSql = mapYamlTypeToSql;
37
39
  exports.getTableName = getTableName;
38
40
  exports.getForeignKeyFieldName = getForeignKeyFieldName;
@@ -67,10 +69,24 @@ const TYPE_MAPPING = {
67
69
  array: 'JSON',
68
70
  object: 'JSON'
69
71
  };
70
- function mapYamlTypeToSql(yamlType, availableAggregates, availableValueObjects) {
71
- // Simple aggregate reference → foreign key INT
72
+ function getIdColumnDefinition(idType = 'numeric') {
73
+ switch (idType) {
74
+ case 'uuid': return 'id BINARY(16) PRIMARY KEY DEFAULT (UUID_TO_BIN(UUID(), 1))';
75
+ case 'nanoid': return 'id VARCHAR(21) PRIMARY KEY';
76
+ default: return 'id INT AUTO_INCREMENT PRIMARY KEY';
77
+ }
78
+ }
79
+ function getFkColumnType(idType = 'numeric') {
80
+ switch (idType) {
81
+ case 'uuid': return 'BINARY(16)';
82
+ case 'nanoid': return 'VARCHAR(21)';
83
+ default: return 'INT';
84
+ }
85
+ }
86
+ function mapYamlTypeToSql(yamlType, availableAggregates, availableValueObjects, identifiers = 'numeric') {
87
+ // Simple aggregate reference → foreign key column matching PK type
72
88
  if (availableAggregates.has(yamlType)) {
73
- return 'INT';
89
+ return getFkColumnType(identifiers);
74
90
  }
75
91
  // Compound types: array ("Foo[]") or union ("Foo | Bar") → JSON column
76
92
  const parsed = (0, typeUtils_1.parseFieldType)(yamlType);
@@ -106,26 +122,27 @@ function buildChildToParentMap(aggregates) {
106
122
  }
107
123
  return map;
108
124
  }
109
- function generateCreateTableSQL(name, aggregate, availableAggregates, availableValueObjects, parentIdField) {
125
+ function generateCreateTableSQL(name, aggregate, availableAggregates, availableValueObjects, parentIdField, identifiers = 'numeric') {
110
126
  const tableName = getTableName(name);
111
127
  const columns = [];
112
128
  const indexes = [];
113
129
  const foreignKeys = [];
114
- columns.push(' id INT AUTO_INCREMENT PRIMARY KEY');
130
+ const fkType = getFkColumnType(identifiers);
131
+ columns.push(` ${getIdColumnDefinition(identifiers)}`);
115
132
  // Root aggregates get an ownerId column; child entities get a parent ID column.
116
133
  if (parentIdField) {
117
- columns.push(` ${parentIdField} INT NOT NULL`);
134
+ columns.push(` ${parentIdField} ${fkType} NOT NULL`);
118
135
  indexes.push(` INDEX idx_${tableName}_${parentIdField} (${parentIdField})`);
119
136
  }
120
137
  else if (aggregate.root !== false) {
121
- columns.push(' ownerId INT NOT NULL');
138
+ columns.push(` ownerId ${fkType} NOT NULL`);
122
139
  indexes.push(` INDEX idx_${tableName}_ownerId (ownerId)`);
123
140
  }
124
141
  for (const [fieldName, field] of Object.entries(aggregate.fields)) {
125
142
  if (isRelationshipField(field.type, availableAggregates)) {
126
143
  const foreignKeyName = getForeignKeyFieldName(fieldName);
127
144
  const nullable = field.required === false ? 'NULL DEFAULT NULL' : 'NOT NULL';
128
- columns.push(` ${foreignKeyName} INT ${nullable}`);
145
+ columns.push(` ${foreignKeyName} ${fkType} ${nullable}`);
129
146
  indexes.push(` INDEX idx_${tableName}_${foreignKeyName} (${foreignKeyName})`);
130
147
  const refTableName = getTableName(field.type);
131
148
  foreignKeys.push(` CONSTRAINT fk_${tableName}_${foreignKeyName} \n` +
@@ -135,7 +152,7 @@ function generateCreateTableSQL(name, aggregate, availableAggregates, availableV
135
152
  ` ON UPDATE CASCADE`);
136
153
  }
137
154
  else {
138
- const sqlType = mapYamlTypeToSql(field.type, availableAggregates, availableValueObjects);
155
+ const sqlType = mapYamlTypeToSql(field.type, availableAggregates, availableValueObjects, identifiers);
139
156
  const nullable = field.required === false ? 'NULL DEFAULT NULL' : 'NOT NULL';
140
157
  columns.push(` ${fieldName} ${sqlType} ${nullable}`);
141
158
  if (['string', 'number', 'integer', 'id'].includes(field.type)) {
@@ -154,14 +171,14 @@ function generateCreateTableSQL(name, aggregate, availableAggregates, availableV
154
171
  function generateDropTableSQL(tableName) {
155
172
  return `DROP TABLE IF EXISTS \`${tableName}\`;`;
156
173
  }
157
- function generateAddColumnSQL(tableName, fieldName, field, availableAggregates, availableValueObjects) {
174
+ function generateAddColumnSQL(tableName, fieldName, field, availableAggregates, availableValueObjects, identifiers = 'numeric') {
158
175
  if (isRelationshipField(field.type, availableAggregates)) {
159
176
  const foreignKeyName = getForeignKeyFieldName(fieldName);
160
177
  const nullable = field.required === false ? 'NULL DEFAULT NULL' : 'NOT NULL';
161
- return `ALTER TABLE \`${tableName}\` ADD COLUMN \`${foreignKeyName}\` INT ${nullable};`;
178
+ return `ALTER TABLE \`${tableName}\` ADD COLUMN \`${foreignKeyName}\` ${getFkColumnType(identifiers)} ${nullable};`;
162
179
  }
163
180
  else {
164
- const sqlType = mapYamlTypeToSql(field.type, availableAggregates, availableValueObjects);
181
+ const sqlType = mapYamlTypeToSql(field.type, availableAggregates, availableValueObjects, identifiers);
165
182
  const nullable = field.required === false ? 'NULL DEFAULT NULL' : 'NOT NULL';
166
183
  return `ALTER TABLE \`${tableName}\` ADD COLUMN \`${fieldName}\` ${sqlType} ${nullable};`;
167
184
  }
@@ -169,14 +186,14 @@ function generateAddColumnSQL(tableName, fieldName, field, availableAggregates,
169
186
  function generateDropColumnSQL(tableName, columnName) {
170
187
  return `ALTER TABLE \`${tableName}\` DROP COLUMN \`${columnName}\`;`;
171
188
  }
172
- function generateModifyColumnSQL(tableName, fieldName, field, availableAggregates, availableValueObjects) {
189
+ function generateModifyColumnSQL(tableName, fieldName, field, availableAggregates, availableValueObjects, identifiers = 'numeric') {
173
190
  if (isRelationshipField(field.type, availableAggregates)) {
174
191
  const foreignKeyName = getForeignKeyFieldName(fieldName);
175
192
  const nullable = field.required === false ? 'NULL DEFAULT NULL' : 'NOT NULL';
176
- return `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${foreignKeyName}\` INT ${nullable};`;
193
+ return `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${foreignKeyName}\` ${getFkColumnType(identifiers)} ${nullable};`;
177
194
  }
178
195
  else {
179
- const sqlType = mapYamlTypeToSql(field.type, availableAggregates, availableValueObjects);
196
+ const sqlType = mapYamlTypeToSql(field.type, availableAggregates, availableValueObjects, identifiers);
180
197
  const nullable = field.required === false ? 'NULL DEFAULT NULL' : 'NOT NULL';
181
198
  return `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${fieldName}\` ${sqlType} ${nullable};`;
182
199
  }
@@ -225,7 +242,7 @@ function sortAggregatesByDependencies(aggregates, availableAggregates) {
225
242
  }
226
243
  return sorted;
227
244
  }
228
- function compareSchemas(oldState, newAggregates, availableValueObjects) {
245
+ function compareSchemas(oldState, newAggregates, availableValueObjects, identifiers = 'numeric') {
229
246
  const sqlStatements = [];
230
247
  const availableAggregates = new Set(Object.keys(newAggregates));
231
248
  const childToParent = buildChildToParentMap(newAggregates);
@@ -236,7 +253,7 @@ function compareSchemas(oldState, newAggregates, availableValueObjects) {
236
253
  const parentName = childToParent.get(name);
237
254
  const parentIdField = parentName ? `${parentName.toLowerCase()}Id` : undefined;
238
255
  sqlStatements.push(`-- Create ${tableName} table`);
239
- sqlStatements.push(generateCreateTableSQL(name, aggregate, availableAggregates, availableValueObjects, parentIdField));
256
+ sqlStatements.push(generateCreateTableSQL(name, aggregate, availableAggregates, availableValueObjects, parentIdField, identifiers));
240
257
  sqlStatements.push('');
241
258
  }
242
259
  return sqlStatements;
@@ -259,7 +276,7 @@ function compareSchemas(oldState, newAggregates, availableValueObjects) {
259
276
  const parentIdField = parentName ? `${parentName.toLowerCase()}Id` : undefined;
260
277
  if (!oldAggregate) {
261
278
  sqlStatements.push(`-- Create ${tableName} table`);
262
- sqlStatements.push(generateCreateTableSQL(name, newAggregate, availableAggregates, availableValueObjects, parentIdField));
279
+ sqlStatements.push(generateCreateTableSQL(name, newAggregate, availableAggregates, availableValueObjects, parentIdField, identifiers));
263
280
  sqlStatements.push('');
264
281
  }
265
282
  else {
@@ -281,7 +298,7 @@ function compareSchemas(oldState, newAggregates, availableValueObjects) {
281
298
  const oldField = oldFields[fieldName];
282
299
  if (!oldField) {
283
300
  sqlStatements.push(`-- Add column ${fieldName} to ${tableName}`);
284
- sqlStatements.push(generateAddColumnSQL(tableName, fieldName, newField, availableAggregates, availableValueObjects));
301
+ sqlStatements.push(generateAddColumnSQL(tableName, fieldName, newField, availableAggregates, availableValueObjects, identifiers));
285
302
  sqlStatements.push('');
286
303
  }
287
304
  else {
@@ -289,7 +306,7 @@ function compareSchemas(oldState, newAggregates, availableValueObjects) {
289
306
  const requiredChanged = oldField.required !== newField.required;
290
307
  if (typeChanged || requiredChanged) {
291
308
  sqlStatements.push(`-- Modify column ${fieldName} in ${tableName}`);
292
- sqlStatements.push(generateModifyColumnSQL(tableName, fieldName, newField, availableAggregates, availableValueObjects));
309
+ sqlStatements.push(generateModifyColumnSQL(tableName, fieldName, newField, availableAggregates, availableValueObjects, identifiers));
293
310
  sqlStatements.push('');
294
311
  }
295
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@currentjs/gen",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "CLI code generator",
5
5
  "license": "LGPL-3.0",
6
6
  "author": "Konstantin Zavalny",