@an5/orm 1.0.3 → 1.0.5

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.
@@ -20,10 +20,18 @@ class MetadataGenerator {
20
20
  }
21
21
  }
22
22
  metaContent += '};\n\n';
23
- metaContent += 'export const modelFields: Record<string, Record<string, { ts: string; sql: string }>> = {\n';
23
+ metaContent += 'export const modelDescriptions: Record<string, string | undefined> = {\n';
24
24
  for (const model of models) {
25
25
  const props = this.getAllPropertyVariations(model.name);
26
- const fieldsStr = `{ ${model.fields.map(f => `${f.name}: { ts: "${f.type}${f.isOptional ? '?' : ''}", sql: "${f.sqlType}" }`).join(', ')} }`;
26
+ for (const prop of props) {
27
+ metaContent += ` ${prop}: ${model.description ? JSON.stringify(model.description) : 'undefined'},\n`;
28
+ }
29
+ }
30
+ metaContent += '};\n\n';
31
+ metaContent += 'export const modelFields: Record<string, Record<string, { ts: string; sql: string; description?: string }>> = {\n';
32
+ for (const model of models) {
33
+ const props = this.getAllPropertyVariations(model.name);
34
+ const fieldsStr = `{ ${model.fields.map(f => `${f.name}: ${this.formatFieldMetadata(f)}`).join(', ')} }`;
27
35
  for (const prop of props) {
28
36
  metaContent += ` ${prop}: ${fieldsStr},\n`;
29
37
  }
@@ -63,6 +71,16 @@ class MetadataGenerator {
63
71
  }
64
72
  return Array.from(variations);
65
73
  }
74
+ formatFieldMetadata(field) {
75
+ const entries = [
76
+ `ts: ${JSON.stringify(`${field.type}${field.isOptional ? '?' : ''}`)}`,
77
+ `sql: ${JSON.stringify(field.sqlType)}`,
78
+ ];
79
+ if (field.description) {
80
+ entries.push(`description: ${JSON.stringify(field.description)}`);
81
+ }
82
+ return `{ ${entries.join(', ')} }`;
83
+ }
66
84
  toCamelCase(str) {
67
85
  if (!str)
68
86
  return '';
@@ -21,17 +21,26 @@ class PythonGenerator {
21
21
  }
22
22
  }
23
23
  pyContent += '}\n\n';
24
- // 2. MODEL_FIELDS
24
+ // 2. MODEL_DESCRIPTIONS
25
+ pyContent += 'MODEL_DESCRIPTIONS = {\n';
26
+ for (const model of models) {
27
+ const props = this.getAllPropertyVariations(model.name);
28
+ for (const prop of props) {
29
+ pyContent += ` "${prop}": ${this.pyString(model.description)},\n`;
30
+ }
31
+ }
32
+ pyContent += '}\n\n';
33
+ // 3. MODEL_FIELDS
25
34
  pyContent += 'MODEL_FIELDS = {\n';
26
35
  for (const model of models) {
27
36
  const props = this.getAllPropertyVariations(model.name);
28
- const fieldsStr = `{ ${model.fields.map(f => `"${f.name}": "${f.type}${f.isOptional ? '?' : ''}"`).join(', ')} }`;
37
+ const fieldsStr = this.formatFields(model);
29
38
  for (const prop of props) {
30
39
  pyContent += ` "${prop}": ${fieldsStr},\n`;
31
40
  }
32
41
  }
33
42
  pyContent += '}\n\n';
34
- // 3. RELATION_MAP
43
+ // 4. RELATION_MAP
35
44
  pyContent += 'RELATION_MAP = {\n';
36
45
  for (const model of models) {
37
46
  const props = this.getAllPropertyVariations(model.name);
@@ -68,6 +77,17 @@ class PythonGenerator {
68
77
  }
69
78
  return Array.from(variations);
70
79
  }
80
+ formatFields(model) {
81
+ if (model.fields.length === 0)
82
+ return '[]';
83
+ const fields = model.fields.map(f => {
84
+ return ` { "name": "${f.name}", "type": "${f.type}${f.isOptional ? '?' : ''}", "sql": "${f.sqlType}", "isOptional": ${f.isOptional ? 'True' : 'False'}, "hasDefault": ${f.hasDefault ? 'True' : 'False'}, "isId": ${f.isId ? 'True' : 'False'}, "description": ${this.pyString(f.description)} }`;
85
+ });
86
+ return `[\n${fields.join(',\n')}\n ]`;
87
+ }
88
+ pyString(value) {
89
+ return value ? JSON.stringify(value) : 'None';
90
+ }
71
91
  toCamelCase(str) {
72
92
  if (!str)
73
93
  return '';
@@ -15,13 +15,22 @@ export class MetadataGenerator {
15
15
  for (const prop of props) {
16
16
  metaContent += ` ${prop}: "${fullTableName}",\n`;
17
17
  }
18
- }
19
- metaContent += '};\n\n';
20
-
21
- metaContent += 'export const modelFields: Record<string, Record<string, { ts: string; sql: string }>> = {\n';
22
- for (const model of models) {
23
- const props = this.getAllPropertyVariations(model.name);
24
- const fieldsStr = `{ ${model.fields.map(f => `${f.name}: { ts: "${f.type}${f.isOptional ? '?' : ''}", sql: "${f.sqlType}" }`).join(', ')} }`;
18
+ }
19
+ metaContent += '};\n\n';
20
+
21
+ metaContent += 'export const modelDescriptions: Record<string, string | undefined> = {\n';
22
+ for (const model of models) {
23
+ const props = this.getAllPropertyVariations(model.name);
24
+ for (const prop of props) {
25
+ metaContent += ` ${prop}: ${model.description ? JSON.stringify(model.description) : 'undefined'},\n`;
26
+ }
27
+ }
28
+ metaContent += '};\n\n';
29
+
30
+ metaContent += 'export const modelFields: Record<string, Record<string, { ts: string; sql: string; description?: string }>> = {\n';
31
+ for (const model of models) {
32
+ const props = this.getAllPropertyVariations(model.name);
33
+ const fieldsStr = `{ ${model.fields.map(f => `${f.name}: ${this.formatFieldMetadata(f)}`).join(', ')} }`;
25
34
  for (const prop of props) {
26
35
  metaContent += ` ${prop}: ${fieldsStr},\n`;
27
36
  }
@@ -48,7 +57,7 @@ export class MetadataGenerator {
48
57
  fs.writeFileSync(this.outputPath, metaContent);
49
58
  }
50
59
 
51
- private getAllPropertyVariations(modelName: string): string[] {
60
+ private getAllPropertyVariations(modelName: string): string[] {
52
61
  const variations = new Set<string>();
53
62
 
54
63
  // 1. Standard camelCase (e.g. User -> user, McpServer -> mcpServer)
@@ -68,11 +77,22 @@ export class MetadataGenerator {
68
77
  variations.add(acronym[0].toLowerCase() + acronym.slice(1) + modelName.slice(acronym.length));
69
78
  }
70
79
  }
71
-
72
- return Array.from(variations);
73
- }
74
-
75
- private toCamelCase(str: string): string {
80
+
81
+ return Array.from(variations);
82
+ }
83
+
84
+ private formatFieldMetadata(field: Model['fields'][number]): string {
85
+ const entries = [
86
+ `ts: ${JSON.stringify(`${field.type}${field.isOptional ? '?' : ''}`)}`,
87
+ `sql: ${JSON.stringify(field.sqlType)}`,
88
+ ];
89
+ if (field.description) {
90
+ entries.push(`description: ${JSON.stringify(field.description)}`);
91
+ }
92
+ return `{ ${entries.join(', ')} }`;
93
+ }
94
+
95
+ private toCamelCase(str: string): string {
76
96
  if (!str) return '';
77
97
  return str[0].toLowerCase() + str.slice(1);
78
98
  }
@@ -16,21 +16,31 @@ export class PythonGenerator {
16
16
  for (const prop of props) {
17
17
  pyContent += ` "${prop}": "${fullTableName}",\n`;
18
18
  }
19
+ }
20
+ pyContent += '}\n\n';
21
+
22
+ // 2. MODEL_DESCRIPTIONS
23
+ pyContent += 'MODEL_DESCRIPTIONS = {\n';
24
+ for (const model of models) {
25
+ const props = this.getAllPropertyVariations(model.name);
26
+ for (const prop of props) {
27
+ pyContent += ` "${prop}": ${this.pyString(model.description)},\n`;
28
+ }
29
+ }
30
+ pyContent += '}\n\n';
31
+
32
+ // 3. MODEL_FIELDS
33
+ pyContent += 'MODEL_FIELDS = {\n';
34
+ for (const model of models) {
35
+ const props = this.getAllPropertyVariations(model.name);
36
+ const fieldsStr = this.formatFields(model);
37
+ for (const prop of props) {
38
+ pyContent += ` "${prop}": ${fieldsStr},\n`;
39
+ }
19
40
  }
20
41
  pyContent += '}\n\n';
21
42
 
22
- // 2. MODEL_FIELDS
23
- pyContent += 'MODEL_FIELDS = {\n';
24
- for (const model of models) {
25
- const props = this.getAllPropertyVariations(model.name);
26
- const fieldsStr = `{ ${model.fields.map(f => `"${f.name}": "${f.type}${f.isOptional ? '?' : ''}"`).join(', ')} }`;
27
- for (const prop of props) {
28
- pyContent += ` "${prop}": ${fieldsStr},\n`;
29
- }
30
- }
31
- pyContent += '}\n\n';
32
-
33
- // 3. RELATION_MAP
43
+ // 4. RELATION_MAP
34
44
  pyContent += 'RELATION_MAP = {\n';
35
45
  for (const model of models) {
36
46
  const props = this.getAllPropertyVariations(model.name);
@@ -54,7 +64,7 @@ export class PythonGenerator {
54
64
  fs.writeFileSync(this.outputPath, pyContent);
55
65
  }
56
66
 
57
- private getAllPropertyVariations(modelName: string): string[] {
67
+ private getAllPropertyVariations(modelName: string): string[] {
58
68
  const variations = new Set<string>();
59
69
 
60
70
  // 1. camelCase (User -> user, McpServer -> mcpServer)
@@ -73,9 +83,23 @@ export class PythonGenerator {
73
83
  }
74
84
 
75
85
  return Array.from(variations);
76
- }
77
-
78
- private toCamelCase(str: string): string {
86
+ }
87
+
88
+ private formatFields(model: Model): string {
89
+ if (model.fields.length === 0) return '[]';
90
+
91
+ const fields = model.fields.map(f => {
92
+ return ` { "name": "${f.name}", "type": "${f.type}${f.isOptional ? '?' : ''}", "sql": "${f.sqlType}", "isOptional": ${f.isOptional ? 'True' : 'False'}, "hasDefault": ${f.hasDefault ? 'True' : 'False'}, "isId": ${f.isId ? 'True' : 'False'}, "description": ${this.pyString(f.description)} }`;
93
+ });
94
+
95
+ return `[\n${fields.join(',\n')}\n ]`;
96
+ }
97
+
98
+ private pyString(value?: string): string {
99
+ return value ? JSON.stringify(value) : 'None';
100
+ }
101
+
102
+ private toCamelCase(str: string): string {
79
103
  if (!str) return '';
80
104
  return str[0].toLowerCase() + str.slice(1);
81
105
  }
package/package.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
- "name": "@an5/orm",
3
- "version": "1.0.3",
2
+ "name": "@an5/orm",
3
+ "version": "1.0.5",
4
4
  "description": "The lightweight ORM for SQL Server with support for TypeScript, Python, and .NET (C#).",
5
- "license": "MIT",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "bin": {
9
- "an5": "./dist/cli.js",
10
- "an5-orm": "./dist/cli.js"
11
- },
12
- "files": [
13
- "dist/**/*.{js,d.ts}",
14
- "generator/src/**/*.ts",
15
- "README.md"
16
- ],
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "an5": "./dist/cli.js",
10
+ "an5-orm": "./dist/cli.js"
11
+ },
12
+ "files": [
13
+ "dist/**/*.{js,d.ts}",
14
+ "generator/src/**/*.ts",
15
+ "README.md"
16
+ ],
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "https://github.com/an5ORM/an5Orm.git"
20
20
  },
21
- "scripts": {
22
- "generate": "npx tsx generator/src/index.ts",
21
+ "scripts": {
22
+ "generate": "npx tsx generator/src/index.ts",
23
23
  "db:push": "npx tsx push.ts",
24
24
  "db:pull": "npx tsx pull.ts",
25
25
  "db:seed": "npx tsx seed.ts",
@@ -35,7 +35,7 @@
35
35
  "test:generator": "node test/generator.test.js"
36
36
  },
37
37
  "dependencies": {
38
- "@an5/adapters": "^0.1.2",
38
+ "@an5/adapters": "^0.2.0",
39
39
  "bcryptjs": "^2.4.3",
40
40
  "dotenv": "^16.4.5",
41
41
  "mssql": "^12.5.5"
@@ -43,7 +43,7 @@
43
43
  "devDependencies": {
44
44
  "@types/bcryptjs": "^2.4.6",
45
45
  "@types/mssql": "^9.1.8",
46
- "@types/node": "^20.11.0",
46
+ "@types/node": "^20.19.43",
47
47
  "tsx": "^4.7.1",
48
48
  "typescript": "^6.0.3"
49
49
  },