@an5/orm 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -175
- package/dist/an5Metadata.js +64 -0
- package/dist/an5Orm.d.ts +92 -3
- package/dist/an5Orm.js +697 -206
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/generator/src/code-generator.d.ts +14 -13
- package/dist/generator/src/code-generator.js +249 -225
- package/dist/generator/src/dotnet-generator.d.ts +13 -11
- package/dist/generator/src/dotnet-generator.js +872 -546
- package/dist/generator/src/index.d.ts +1 -1
- package/dist/generator/src/index.js +104 -88
- package/dist/generator/src/metadata-generator.d.ts +11 -8
- package/dist/generator/src/metadata-generator.js +104 -90
- package/dist/generator/src/parser.d.ts +11 -11
- package/dist/generator/src/parser.js +206 -206
- package/dist/generator/src/python-generator.d.ts +19 -9
- package/dist/generator/src/python-generator.js +345 -105
- package/dist/generator/src/types.d.ts +27 -27
- package/dist/generator/src/types.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +19 -8
- package/dist/logger.js +1 -1
- package/dist/migration-core.d.ts +87 -0
- package/dist/migration-core.js +692 -0
- package/dist/scripts/release-cli.d.ts +2 -2
- package/dist/scripts/release-cli.js +115 -115
- package/dist/sql-utils.d.ts +3 -1
- package/dist/sql-utils.js +94 -24
- package/generator/src/code-generator.ts +259 -230
- package/generator/src/dotnet-generator.ts +882 -544
- package/generator/src/golang-generator.ts +1242 -0
- package/generator/src/index.ts +111 -116
- package/generator/src/metadata-generator.ts +116 -101
- package/generator/src/parser.ts +202 -202
- package/generator/src/python-generator.ts +424 -114
- package/generator/src/types.ts +29 -29
- package/package.json +12 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|
|
@@ -1,88 +1,104 @@
|
|
|
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
|
-
const path_1 = __importDefault(require("path"));
|
|
7
|
-
const parser_1 = require("./parser");
|
|
8
|
-
const code_generator_1 = require("./code-generator");
|
|
9
|
-
const metadata_generator_1 = require("./metadata-generator");
|
|
10
|
-
const python_generator_1 = require("./python-generator");
|
|
11
|
-
const dotnet_generator_1 = require("./dotnet-generator");
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
fs_1.default.
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
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
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const parser_1 = require("./parser");
|
|
8
|
+
const code_generator_1 = require("./code-generator");
|
|
9
|
+
const metadata_generator_1 = require("./metadata-generator");
|
|
10
|
+
const python_generator_1 = require("./python-generator");
|
|
11
|
+
const dotnet_generator_1 = require("./dotnet-generator");
|
|
12
|
+
const golang_generator_1 = require("./golang-generator");
|
|
13
|
+
const fs_1 = __importDefault(require("fs"));
|
|
14
|
+
function clearGeneratedFiles(outputDir, extension) {
|
|
15
|
+
if (!fs_1.default.existsSync(outputDir)) {
|
|
16
|
+
fs_1.default.mkdirSync(outputDir, { recursive: true });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
for (const entry of fs_1.default.readdirSync(outputDir)) {
|
|
20
|
+
const fullPath = path_1.default.join(outputDir, entry);
|
|
21
|
+
const stat = fs_1.default.statSync(fullPath);
|
|
22
|
+
if (stat.isDirectory())
|
|
23
|
+
continue;
|
|
24
|
+
if (entry.endsWith(extension)) {
|
|
25
|
+
fs_1.default.unlinkSync(fullPath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function main() {
|
|
30
|
+
let rootDir = process.cwd();
|
|
31
|
+
let config = {};
|
|
32
|
+
try {
|
|
33
|
+
let configPath = path_1.default.join(rootDir, 'an5Orm.config.js');
|
|
34
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
35
|
+
configPath = path_1.default.join(rootDir, 'an5Orm.config.cjs');
|
|
36
|
+
}
|
|
37
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
38
|
+
configPath = path_1.default.join(rootDir, '..', 'an5Orm.config.js');
|
|
39
|
+
}
|
|
40
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
41
|
+
configPath = path_1.default.join(rootDir, '..', 'an5Orm.config.cjs');
|
|
42
|
+
}
|
|
43
|
+
if (fs_1.default.existsSync(configPath)) {
|
|
44
|
+
config = require(configPath);
|
|
45
|
+
rootDir = path_1.default.dirname(configPath);
|
|
46
|
+
}
|
|
47
|
+
else if (fs_1.default.existsSync(path_1.default.join(rootDir, '..', 'an5Schema'))) {
|
|
48
|
+
rootDir = path_1.default.resolve(rootDir, '..');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
console.warn('⚠️ Could not load an5Orm.config.js/.cjs, using defaults.', err);
|
|
53
|
+
}
|
|
54
|
+
const schemaDir = path_1.default.resolve(rootDir, config.schemaDir || 'an5Schema');
|
|
55
|
+
const outputTypesDir = path_1.default.resolve(rootDir, config.outputs?.typescript?.outputDir || 'an5Client/typescript');
|
|
56
|
+
const outputMetadataPath = path_1.default.resolve(rootDir, config.outputs?.typescript?.metadataFile || 'an5Client/typescript/an5Metadata.ts');
|
|
57
|
+
const outputPythonMetadataPath = path_1.default.resolve(rootDir, config.outputs?.python?.metadataFile || 'an5Client/python/an5_metadata.py');
|
|
58
|
+
const outputDotnetDir = path_1.default.resolve(rootDir, config.outputs?.dotnet?.outputDir || 'an5Client/dotnet');
|
|
59
|
+
const outputGolangDir = path_1.default.resolve(rootDir, config.outputs?.golang?.outputDir || 'an5Client/golang');
|
|
60
|
+
console.log('🚀 Starting ORM generation...');
|
|
61
|
+
try {
|
|
62
|
+
clearGeneratedFiles(outputTypesDir, '.ts');
|
|
63
|
+
clearGeneratedFiles(outputDotnetDir, '.cs');
|
|
64
|
+
clearGeneratedFiles(outputGolangDir, '.go');
|
|
65
|
+
if (fs_1.default.existsSync(outputMetadataPath)) {
|
|
66
|
+
fs_1.default.unlinkSync(outputMetadataPath);
|
|
67
|
+
}
|
|
68
|
+
if (fs_1.default.existsSync(outputPythonMetadataPath)) {
|
|
69
|
+
fs_1.default.unlinkSync(outputPythonMetadataPath);
|
|
70
|
+
}
|
|
71
|
+
const parser = new parser_1.SchemaParser(schemaDir);
|
|
72
|
+
const models = await parser.parse();
|
|
73
|
+
console.log(`📦 Parsed ${models.length} models from schema.`);
|
|
74
|
+
const codeGen = new code_generator_1.CodeGenerator(outputTypesDir);
|
|
75
|
+
codeGen.generate(models);
|
|
76
|
+
console.log(`✨ Generated modular types in ${outputTypesDir}`);
|
|
77
|
+
const metadataDir = path_1.default.dirname(outputMetadataPath);
|
|
78
|
+
if (!fs_1.default.existsSync(metadataDir)) {
|
|
79
|
+
fs_1.default.mkdirSync(metadataDir, { recursive: true });
|
|
80
|
+
}
|
|
81
|
+
const metadataGen = new metadata_generator_1.MetadataGenerator(outputMetadataPath);
|
|
82
|
+
metadataGen.generate(models);
|
|
83
|
+
console.log(`✨ Generated metadata in ${outputMetadataPath}`);
|
|
84
|
+
const pythonDir = path_1.default.dirname(outputPythonMetadataPath);
|
|
85
|
+
if (!fs_1.default.existsSync(pythonDir)) {
|
|
86
|
+
fs_1.default.mkdirSync(pythonDir, { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
const pythonGen = new python_generator_1.PythonGenerator(outputPythonMetadataPath);
|
|
89
|
+
pythonGen.generate(models);
|
|
90
|
+
console.log(`✨ Generated Python metadata and client models in ${pythonDir}`);
|
|
91
|
+
const dotnetGen = new dotnet_generator_1.DotnetGenerator(outputDotnetDir);
|
|
92
|
+
dotnetGen.generate(models);
|
|
93
|
+
console.log(`✨ Generated .NET models in ${outputDotnetDir}`);
|
|
94
|
+
const golangGen = new golang_generator_1.GolangGenerator(outputGolangDir);
|
|
95
|
+
golangGen.generate(models);
|
|
96
|
+
console.log(`✨ Generated Golang models in ${outputGolangDir}`);
|
|
97
|
+
console.log('✅ ORM generation completed successfully.');
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error('❌ ORM generation failed:', error);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
main();
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { Model } from './types';
|
|
2
|
-
export declare class MetadataGenerator {
|
|
3
|
-
private outputPath;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
private
|
|
8
|
-
|
|
1
|
+
import { Model } from './types';
|
|
2
|
+
export declare class MetadataGenerator {
|
|
3
|
+
private outputPath;
|
|
4
|
+
private relationImport;
|
|
5
|
+
constructor(outputPath: string, relationImport?: string);
|
|
6
|
+
generate(models: Model[]): void;
|
|
7
|
+
private getAllPropertyVariations;
|
|
8
|
+
private toSnakeCase;
|
|
9
|
+
private formatFieldMetadata;
|
|
10
|
+
private toCamelCase;
|
|
11
|
+
}
|
|
@@ -1,90 +1,104 @@
|
|
|
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.MetadataGenerator = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
class MetadataGenerator {
|
|
9
|
-
constructor(outputPath) {
|
|
10
|
-
this.outputPath = outputPath;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
metaContent
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
metaContent += '
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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.MetadataGenerator = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
class MetadataGenerator {
|
|
9
|
+
constructor(outputPath, relationImport = 'import type { RelationDef } from "@an5/orm";') {
|
|
10
|
+
this.outputPath = outputPath;
|
|
11
|
+
this.relationImport = relationImport;
|
|
12
|
+
}
|
|
13
|
+
generate(models) {
|
|
14
|
+
let metaContent = '// This file is auto-generated. Do not edit directly.\n\n';
|
|
15
|
+
metaContent += `${this.relationImport}\n\n`;
|
|
16
|
+
metaContent += 'export const modelToTable: Record<string, string> = {\n';
|
|
17
|
+
for (const model of models) {
|
|
18
|
+
const props = this.getAllPropertyVariations(model.name);
|
|
19
|
+
const fullTableName = `[${model.schemaName}].[${model.tableName}]`;
|
|
20
|
+
for (const prop of props) {
|
|
21
|
+
metaContent += ` ${prop}: "${fullTableName}",\n`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
metaContent += '};\n\n';
|
|
25
|
+
metaContent += 'export const modelDescriptions: Record<string, string | undefined> = {\n';
|
|
26
|
+
for (const model of models) {
|
|
27
|
+
const props = this.getAllPropertyVariations(model.name);
|
|
28
|
+
for (const prop of props) {
|
|
29
|
+
metaContent += ` ${prop}: ${model.description ? JSON.stringify(model.description) : 'undefined'},\n`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
metaContent += '};\n\n';
|
|
33
|
+
metaContent += 'export const modelFields: Record<string, Record<string, { ts: string; sql: string; description?: string }>> = {\n';
|
|
34
|
+
for (const model of models) {
|
|
35
|
+
const props = this.getAllPropertyVariations(model.name);
|
|
36
|
+
const fieldsStr = `{ ${model.fields.map(f => `${f.name}: ${this.formatFieldMetadata(f)}`).join(', ')} }`;
|
|
37
|
+
for (const prop of props) {
|
|
38
|
+
metaContent += ` ${prop}: ${fieldsStr},\n`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
metaContent += '};\n\n';
|
|
42
|
+
metaContent += 'export const relationMap: Record<string, Record<string, RelationDef>> = {\n';
|
|
43
|
+
for (const model of models) {
|
|
44
|
+
const props = this.getAllPropertyVariations(model.name);
|
|
45
|
+
let relationsContent = ` {\n`;
|
|
46
|
+
for (const rel of model.relations) {
|
|
47
|
+
relationsContent += ` ${rel.name}: { modelName: "${this.toCamelCase(rel.type)}", relationType: "${rel.isArray ? 'many' : 'one'}", foreignKey: "${rel.foreignKey || 'id'}", localKey: "${rel.localKey || 'id'}" },\n`;
|
|
48
|
+
}
|
|
49
|
+
relationsContent += ` }`;
|
|
50
|
+
for (const prop of props) {
|
|
51
|
+
metaContent += ` ${prop}: ${relationsContent},\n`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
metaContent += '};\n';
|
|
55
|
+
fs_1.default.writeFileSync(this.outputPath, metaContent);
|
|
56
|
+
}
|
|
57
|
+
getAllPropertyVariations(modelName) {
|
|
58
|
+
const variations = new Set();
|
|
59
|
+
// 1. PascalCase (User)
|
|
60
|
+
variations.add(modelName);
|
|
61
|
+
// 2. camelCase (user)
|
|
62
|
+
variations.add(this.toCamelCase(modelName));
|
|
63
|
+
// 3. Plural PascalCase (Users)
|
|
64
|
+
variations.add(modelName + 's');
|
|
65
|
+
// 4. Plural camelCase (users)
|
|
66
|
+
variations.add(this.toCamelCase(modelName) + 's');
|
|
67
|
+
// 5. snake_case (user, mc_server)
|
|
68
|
+
variations.add(this.toSnakeCase(modelName));
|
|
69
|
+
variations.add(this.toSnakeCase(modelName) + 's');
|
|
70
|
+
const acronyms = ['LLM', 'AI', 'MCP', 'IT', 'QC', 'HR', 'MR', 'WH', 'SSIS', 'API', 'URL', 'ID', 'JSON'];
|
|
71
|
+
for (const acronym of acronyms) {
|
|
72
|
+
if (modelName.startsWith(acronym)) {
|
|
73
|
+
variations.add(acronym.toLowerCase() + modelName.slice(acronym.length));
|
|
74
|
+
variations.add(acronym[0].toLowerCase() + acronym.slice(1) + modelName.slice(acronym.length));
|
|
75
|
+
variations.add(acronym.toLowerCase() + modelName.slice(acronym.length) + 's');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return Array.from(variations);
|
|
79
|
+
}
|
|
80
|
+
toSnakeCase(str) {
|
|
81
|
+
if (!str)
|
|
82
|
+
return '';
|
|
83
|
+
return str
|
|
84
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
|
|
85
|
+
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
|
|
86
|
+
.toLowerCase();
|
|
87
|
+
}
|
|
88
|
+
formatFieldMetadata(field) {
|
|
89
|
+
const entries = [
|
|
90
|
+
`ts: ${JSON.stringify(`${field.type}${field.isOptional ? '?' : ''}`)}`,
|
|
91
|
+
`sql: ${JSON.stringify(field.sqlType)}`,
|
|
92
|
+
];
|
|
93
|
+
if (field.description) {
|
|
94
|
+
entries.push(`description: ${JSON.stringify(field.description)}`);
|
|
95
|
+
}
|
|
96
|
+
return `{ ${entries.join(', ')} }`;
|
|
97
|
+
}
|
|
98
|
+
toCamelCase(str) {
|
|
99
|
+
if (!str)
|
|
100
|
+
return '';
|
|
101
|
+
return str[0].toLowerCase() + str.slice(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.MetadataGenerator = MetadataGenerator;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Model } from './types';
|
|
2
|
-
export declare function sqlTypeToTs(sqlType: string): string;
|
|
3
|
-
export declare class SchemaParser {
|
|
4
|
-
private schemaDir;
|
|
5
|
-
private schemaText;
|
|
6
|
-
constructor(schemaDir: string);
|
|
7
|
-
parse(): Promise<Model[]>;
|
|
8
|
-
private loadSchema;
|
|
9
|
-
private parseModelLine;
|
|
10
|
-
private postProcessRelations;
|
|
11
|
-
}
|
|
1
|
+
import { Model } from './types';
|
|
2
|
+
export declare function sqlTypeToTs(sqlType: string): string;
|
|
3
|
+
export declare class SchemaParser {
|
|
4
|
+
private schemaDir;
|
|
5
|
+
private schemaText;
|
|
6
|
+
constructor(schemaDir: string);
|
|
7
|
+
parse(): Promise<Model[]>;
|
|
8
|
+
private loadSchema;
|
|
9
|
+
private parseModelLine;
|
|
10
|
+
private postProcessRelations;
|
|
11
|
+
}
|