@apso/cli 0.7.3 → 0.8.2
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/dist/autogen/index.d.ts +2 -0
- package/dist/autogen/index.js +3 -0
- package/dist/commands/server/new.d.ts +4 -1
- package/dist/commands/server/new.js +115 -22
- package/dist/commands/server/scaffold.d.ts +11 -0
- package/dist/commands/server/scaffold.js +213 -12
- package/dist/lib/api/client.d.ts +65 -0
- package/dist/lib/api/client.js +305 -0
- package/dist/lib/api/index.d.ts +8 -0
- package/dist/lib/api/index.js +22 -0
- package/dist/lib/api/services.d.ts +166 -0
- package/dist/lib/api/services.js +202 -0
- package/dist/lib/api/types.d.ts +212 -0
- package/dist/lib/api/types.js +7 -0
- package/dist/lib/apsorc-parser.d.ts +3 -0
- package/dist/lib/apsorc-parser.js +4 -0
- package/dist/lib/config/index.d.ts +8 -0
- package/dist/lib/config/index.js +17 -0
- package/dist/lib/config/manager.d.ts +127 -0
- package/dist/lib/config/manager.js +304 -0
- package/dist/lib/config/paths.d.ts +65 -0
- package/dist/lib/config/paths.js +127 -0
- package/dist/lib/config/types.d.ts +230 -0
- package/dist/lib/config/types.js +30 -0
- package/dist/lib/generators/base.d.ts +93 -0
- package/dist/lib/generators/base.js +90 -0
- package/dist/lib/generators/go.d.ts +37 -0
- package/dist/lib/generators/go.js +340 -0
- package/dist/lib/generators/index.d.ts +21 -0
- package/dist/lib/generators/index.js +51 -0
- package/dist/lib/generators/python.d.ts +21 -0
- package/dist/lib/generators/python.js +253 -0
- package/dist/lib/generators/typescript.d.ts +25 -0
- package/dist/lib/generators/typescript.js +373 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +9 -1
- package/dist/lib/templates/entities/entity-col-timestamp.eta +9 -2
- package/dist/lib/templates/entities/entity-col-timestamptz.eta +9 -2
- package/dist/lib/templates/entities/entity.eta +18 -5
- package/dist/lib/templates/go/dto/dto-col-array.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-boolean.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-date.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-decimal.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-enum.eta +8 -0
- package/dist/lib/templates/go/dto/dto-col-float.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-integer.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-json.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-jsonb.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-numeric.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-string.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-text.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-timestamp.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-timestamptz.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-uuid.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-varchar.eta +7 -0
- package/dist/lib/templates/go/dto/dto.eta +78 -0
- package/dist/lib/templates/go/enums.eta +44 -0
- package/dist/lib/templates/go/handlers/handler.eta +212 -0
- package/dist/lib/templates/go/header.eta +3 -0
- package/dist/lib/templates/go/index-module.eta +53 -0
- package/dist/lib/templates/go/middleware/auth.eta +101 -0
- package/dist/lib/templates/go/models/model-col-array.eta +1 -0
- package/dist/lib/templates/go/models/model-col-boolean.eta +1 -0
- package/dist/lib/templates/go/models/model-col-date.eta +1 -0
- package/dist/lib/templates/go/models/model-col-decimal.eta +1 -0
- package/dist/lib/templates/go/models/model-col-enum.eta +2 -0
- package/dist/lib/templates/go/models/model-col-float.eta +1 -0
- package/dist/lib/templates/go/models/model-col-integer.eta +1 -0
- package/dist/lib/templates/go/models/model-col-json.eta +1 -0
- package/dist/lib/templates/go/models/model-col-jsonb.eta +1 -0
- package/dist/lib/templates/go/models/model-col-numeric.eta +1 -0
- package/dist/lib/templates/go/models/model-col-string.eta +1 -0
- package/dist/lib/templates/go/models/model-col-text.eta +1 -0
- package/dist/lib/templates/go/models/model-col-timestamp.eta +1 -0
- package/dist/lib/templates/go/models/model-col-timestamptz.eta +1 -0
- package/dist/lib/templates/go/models/model-col-uuid.eta +1 -0
- package/dist/lib/templates/go/models/model-col-varchar.eta +1 -0
- package/dist/lib/templates/go/models/model.eta +53 -0
- package/dist/lib/templates/go/services/service.eta +190 -0
- package/dist/lib/templates/python/enums.eta +10 -0
- package/dist/lib/templates/python/header.eta +6 -0
- package/dist/lib/templates/python/index-module.eta +18 -0
- package/dist/lib/templates/python/models/model-col-array.eta +4 -0
- package/dist/lib/templates/python/models/model-col-boolean.eta +5 -0
- package/dist/lib/templates/python/models/model-col-date.eta +4 -0
- package/dist/lib/templates/python/models/model-col-decimal.eta +4 -0
- package/dist/lib/templates/python/models/model-col-enum.eta +16 -0
- package/dist/lib/templates/python/models/model-col-float.eta +5 -0
- package/dist/lib/templates/python/models/model-col-integer.eta +6 -0
- package/dist/lib/templates/python/models/model-col-json.eta +4 -0
- package/dist/lib/templates/python/models/model-col-jsonb.eta +4 -0
- package/dist/lib/templates/python/models/model-col-numeric.eta +4 -0
- package/dist/lib/templates/python/models/model-col-string.eta +6 -0
- package/dist/lib/templates/python/models/model-col-text.eta +6 -0
- package/dist/lib/templates/python/models/model-col-timestamp.eta +11 -0
- package/dist/lib/templates/python/models/model-col-timestamptz.eta +11 -0
- package/dist/lib/templates/python/models/model-col-uuid.eta +5 -0
- package/dist/lib/templates/python/models/model-col-varchar.eta +6 -0
- package/dist/lib/templates/python/models/model.eta +124 -0
- package/dist/lib/templates/python/routers/router.eta +206 -0
- package/dist/lib/templates/python/schemas/schema-col-array.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-boolean.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-date.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-decimal.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-enum.eta +6 -0
- package/dist/lib/templates/python/schemas/schema-col-float.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-integer.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-json.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-jsonb.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-numeric.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-string.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-text.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-timestamp.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-timestamptz.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-uuid.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-varchar.eta +1 -0
- package/dist/lib/templates/python/schemas/schema.eta +87 -0
- package/dist/lib/templates/python/services/service.eta +163 -0
- package/dist/lib/templates/rest/controller-rest.eta +13 -12
- package/dist/lib/templates/rest/dto-rest.eta +173 -59
- package/dist/lib/templates/rest/service-rest.eta +50 -10
- package/dist/lib/types/generator.d.ts +241 -0
- package/dist/lib/types/generator.js +2 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/utils/casing.d.ts +1 -0
- package/dist/lib/utils/casing.js +11 -1
- package/oclif.manifest.json +39 -3
- package/package.json +4 -2
- package/dist/lib/utils/relationships/parse.spec.d.ts +0 -1
- package/dist/lib/utils/relationships/parse.spec.js +0 -402
- package/dist/tests/templates/entities/types/array-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/array-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/bigint-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/bigint-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/boolean-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/boolean-template.spec.js +0 -77
- package/dist/tests/templates/entities/types/bytea-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/bytea-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/char-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/char-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/date-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/date-template.spec.js +0 -56
- package/dist/tests/templates/entities/types/decimal-field-validation.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +0 -100
- package/dist/tests/templates/entities/types/decimal-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/decimal-template.spec.js +0 -86
- package/dist/tests/templates/entities/types/double-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/double-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/enum-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/enum-template.spec.js +0 -85
- package/dist/tests/templates/entities/types/float-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/float-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/geometry-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/geometry-template.spec.js +0 -58
- package/dist/tests/templates/entities/types/inet-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/inet-template.spec.js +0 -69
- package/dist/tests/templates/entities/types/int4range-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/int4range-template.spec.js +0 -72
- package/dist/tests/templates/entities/types/integer-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/integer-template.spec.js +0 -79
- package/dist/tests/templates/entities/types/interval-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/interval-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/json-plain-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/json-plain-template.spec.js +0 -54
- package/dist/tests/templates/entities/types/json-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/json-template.spec.js +0 -40
- package/dist/tests/templates/entities/types/jsonb-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/jsonb-template.spec.js +0 -40
- package/dist/tests/templates/entities/types/money-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/money-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/numeric-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/numeric-template.spec.js +0 -84
- package/dist/tests/templates/entities/types/point-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/point-template.spec.js +0 -64
- package/dist/tests/templates/entities/types/polygon-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/polygon-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/real-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/real-template.spec.js +0 -67
- package/dist/tests/templates/entities/types/serial-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/serial-template.spec.js +0 -113
- package/dist/tests/templates/entities/types/smallint-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/smallint-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/string-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/string-template.spec.js +0 -111
- package/dist/tests/templates/entities/types/text-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/text-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/time-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/time-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/timestamp-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/timestamp-template.spec.js +0 -74
- package/dist/tests/templates/entities/types/timetz-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/timetz-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/tsvector-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/tsvector-template.spec.js +0 -55
- package/dist/tests/templates/entities/types/uuid-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/uuid-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/varchar-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/varchar-template.spec.js +0 -105
- package/dist/tests/templates/entities/types/xml-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/xml-template.spec.js +0 -55
- package/dist/tests/templates/entities/uuid-entity-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/uuid-entity-template.spec.js +0 -277
- package/dist/tests/utils/relationship-deduplication.spec.d.ts +0 -1
- package/dist/tests/utils/relationship-deduplication.spec.js +0 -98
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GoGenerator = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
|
+
const Eta = tslib_1.__importStar(require("eta"));
|
|
7
|
+
const base_1 = require("./base");
|
|
8
|
+
const field_1 = require("../utils/field");
|
|
9
|
+
const relationships_1 = require("../utils/relationships");
|
|
10
|
+
const casing_1 = require("../utils/casing");
|
|
11
|
+
const pluralize_1 = tslib_1.__importDefault(require("pluralize"));
|
|
12
|
+
/**
|
|
13
|
+
* Go/Gin generator that produces GORM models, DTOs, Gin handlers,
|
|
14
|
+
* and service layer code.
|
|
15
|
+
*/
|
|
16
|
+
class GoGenerator extends base_1.BaseGenerator {
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super(config);
|
|
19
|
+
this.templateBasePath = path.join(__dirname, "../templates/go");
|
|
20
|
+
Eta.configure({
|
|
21
|
+
views: this.templateBasePath,
|
|
22
|
+
cache: false,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
getLanguage() {
|
|
26
|
+
return "go";
|
|
27
|
+
}
|
|
28
|
+
getFileExtension() {
|
|
29
|
+
return ".go";
|
|
30
|
+
}
|
|
31
|
+
validateConfig(config) {
|
|
32
|
+
var _a;
|
|
33
|
+
const errors = [];
|
|
34
|
+
const warnings = [];
|
|
35
|
+
// Validate that entities are provided
|
|
36
|
+
if (!config.entities || config.entities.length === 0) {
|
|
37
|
+
errors.push("No entities defined in configuration");
|
|
38
|
+
}
|
|
39
|
+
// Validate each entity
|
|
40
|
+
for (const entity of config.entities) {
|
|
41
|
+
if (!entity.name) {
|
|
42
|
+
errors.push("Entity missing required 'name' property");
|
|
43
|
+
}
|
|
44
|
+
// Validate field types
|
|
45
|
+
for (const field of (_a = entity.fields) !== null && _a !== void 0 ? _a : []) {
|
|
46
|
+
if (!field.name) {
|
|
47
|
+
errors.push(`Entity '${entity.name}' has a field without a name`);
|
|
48
|
+
}
|
|
49
|
+
if (!field.type) {
|
|
50
|
+
errors.push(`Entity '${entity.name}' field '${field.name}' missing type`);
|
|
51
|
+
}
|
|
52
|
+
// Check for unsupported types
|
|
53
|
+
const supportedTypes = [
|
|
54
|
+
"text",
|
|
55
|
+
"varchar",
|
|
56
|
+
"string",
|
|
57
|
+
"integer",
|
|
58
|
+
"boolean",
|
|
59
|
+
"float",
|
|
60
|
+
"decimal",
|
|
61
|
+
"numeric",
|
|
62
|
+
"date",
|
|
63
|
+
"timestamp",
|
|
64
|
+
"timestamptz",
|
|
65
|
+
"json",
|
|
66
|
+
"jsonb",
|
|
67
|
+
"uuid",
|
|
68
|
+
"enum",
|
|
69
|
+
"array",
|
|
70
|
+
];
|
|
71
|
+
if (field.type && !supportedTypes.includes(field.type)) {
|
|
72
|
+
warnings.push(`Entity '${entity.name}' field '${field.name}' has type '${field.type}' which may not be fully supported`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Go-specific validation
|
|
77
|
+
if (config.apiType === "graphql") {
|
|
78
|
+
warnings.push("GraphQL support for Go is limited. REST API with Swagger is recommended.");
|
|
79
|
+
}
|
|
80
|
+
return this.createValidationResult(errors, warnings);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Maps .apsorc field types to Go types
|
|
84
|
+
*/
|
|
85
|
+
mapFieldToGoType(field) {
|
|
86
|
+
const typeMap = {
|
|
87
|
+
text: "string",
|
|
88
|
+
varchar: "string",
|
|
89
|
+
string: "string",
|
|
90
|
+
integer: "int",
|
|
91
|
+
boolean: "bool",
|
|
92
|
+
float: "float64",
|
|
93
|
+
decimal: "float64",
|
|
94
|
+
numeric: "float64",
|
|
95
|
+
date: "time.Time",
|
|
96
|
+
timestamp: "time.Time",
|
|
97
|
+
timestamptz: "time.Time",
|
|
98
|
+
json: "map[string]interface{}",
|
|
99
|
+
jsonb: "map[string]interface{}",
|
|
100
|
+
uuid: "string",
|
|
101
|
+
enum: "string",
|
|
102
|
+
array: "[]string",
|
|
103
|
+
};
|
|
104
|
+
return typeMap[field.type || "string"] || "string";
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Gets the Go type for primary keys
|
|
108
|
+
*/
|
|
109
|
+
getPrimaryKeyGoType(primaryKeyType) {
|
|
110
|
+
return primaryKeyType === "uuid" ? "string" : "uint";
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Gets the Swagger type for primary keys
|
|
114
|
+
*/
|
|
115
|
+
getPrimaryKeySwaggerType(primaryKeyType) {
|
|
116
|
+
return primaryKeyType === "uuid" ? "string" : "integer";
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Transforms fields for Go templates with additional Go-specific properties
|
|
120
|
+
*/
|
|
121
|
+
getGoFieldsForTemplate(fields, entityName) {
|
|
122
|
+
const baseFields = (0, field_1.getFieldForTemplate)(fields, entityName);
|
|
123
|
+
return baseFields.map((field) => ({
|
|
124
|
+
...field,
|
|
125
|
+
goType: this.mapFieldToGoType(field),
|
|
126
|
+
pascalName: (0, casing_1.pascalCase)(field.name),
|
|
127
|
+
snakeName: (0, casing_1.snakeCase)(field.name),
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
async generateEntity(options) {
|
|
131
|
+
const { entity, relationships, allEntities, apiType } = options;
|
|
132
|
+
const { name, fields = [], indexes, uniques } = entity;
|
|
133
|
+
const columns = this.getGoFieldsForTemplate(fields, name);
|
|
134
|
+
const createPrimaryKey = columns.filter((column) => column.primary === true).length === 0;
|
|
135
|
+
const createdAt = entity.created_at;
|
|
136
|
+
const updatedAt = entity.updated_at;
|
|
137
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
138
|
+
const relationshipsForTemplate = (0, relationships_1.getRelationshipForTemplate)(name, relationships, allEntities);
|
|
139
|
+
// Add Go-specific properties to relationships
|
|
140
|
+
const goRelationships = relationshipsForTemplate.map((rel) => ({
|
|
141
|
+
...rel,
|
|
142
|
+
primaryKeyGoType: this.getPrimaryKeyGoType(primaryKeyType),
|
|
143
|
+
camelReferenceName: (0, casing_1.camelCase)(rel.referenceName || rel.name),
|
|
144
|
+
snakeReferenceName: (0, casing_1.snakeCase)(rel.referenceName || rel.name),
|
|
145
|
+
}));
|
|
146
|
+
const entitiesToImport = (0, relationships_1.getRelationshipsForImport)(name, relationshipsForTemplate);
|
|
147
|
+
const data = {
|
|
148
|
+
name,
|
|
149
|
+
indexes: indexes || [],
|
|
150
|
+
uniques: uniques || [],
|
|
151
|
+
createPrimaryKey,
|
|
152
|
+
primaryKeyType,
|
|
153
|
+
snakeCasedName: (0, casing_1.snakeCase)(name),
|
|
154
|
+
createdAt,
|
|
155
|
+
updatedAt,
|
|
156
|
+
pluralizedName: (0, casing_1.camelCase)((0, pluralize_1.default)(name)),
|
|
157
|
+
pluralName: (0, casing_1.pascalCase)((0, pluralize_1.default)(name)),
|
|
158
|
+
columns,
|
|
159
|
+
associations: [...new Set(goRelationships)],
|
|
160
|
+
entitiesToImport,
|
|
161
|
+
importEnums: (0, field_1.typeExistsInEntity)(entity, "enum") !== -1,
|
|
162
|
+
apiType,
|
|
163
|
+
};
|
|
164
|
+
const content = await this.renderTemplate("./models/model", data);
|
|
165
|
+
return [
|
|
166
|
+
{
|
|
167
|
+
path: `models/${(0, casing_1.snakeCase)(name)}.go`,
|
|
168
|
+
content,
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
async generateController(options) {
|
|
173
|
+
const { entity, relationships } = options;
|
|
174
|
+
const { name: entityName } = entity;
|
|
175
|
+
const relationshipsForTemplate = (0, relationships_1.getRelationshipForTemplate)(entityName, relationships);
|
|
176
|
+
const pluralEntityName = (0, pluralize_1.default)(entityName);
|
|
177
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
178
|
+
const data = {
|
|
179
|
+
entityName,
|
|
180
|
+
pluralName: (0, casing_1.pascalCase)(pluralEntityName),
|
|
181
|
+
kebabPluralName: (0, casing_1.kebabCase)(pluralEntityName),
|
|
182
|
+
primaryKeyType,
|
|
183
|
+
primaryKeyGoType: this.getPrimaryKeyGoType(primaryKeyType),
|
|
184
|
+
primaryKeySwaggerType: this.getPrimaryKeySwaggerType(primaryKeyType),
|
|
185
|
+
associations: [...new Set(relationshipsForTemplate)],
|
|
186
|
+
};
|
|
187
|
+
const content = await this.renderTemplate("./handlers/handler", data);
|
|
188
|
+
return [
|
|
189
|
+
{
|
|
190
|
+
path: `handlers/${(0, casing_1.snakeCase)(entityName)}.go`,
|
|
191
|
+
content,
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
async generateService(options) {
|
|
196
|
+
const { entity, relationships, allEntities } = options;
|
|
197
|
+
const { name: entityName, fields = [] } = entity;
|
|
198
|
+
const columns = this.getGoFieldsForTemplate(fields, entityName);
|
|
199
|
+
const relationshipsForTemplate = (0, relationships_1.getRelationshipForTemplate)(entityName, relationships, allEntities);
|
|
200
|
+
// Add Go-specific properties to relationships
|
|
201
|
+
const goRelationships = relationshipsForTemplate.map((rel) => {
|
|
202
|
+
const referencedEntity = allEntities === null || allEntities === void 0 ? void 0 : allEntities.find((e) => e.name === rel.name);
|
|
203
|
+
const referencedPrimaryKeyType = (referencedEntity === null || referencedEntity === void 0 ? void 0 : referencedEntity.primaryKeyType) || "serial";
|
|
204
|
+
return {
|
|
205
|
+
...rel,
|
|
206
|
+
primaryKeyGoType: this.getPrimaryKeyGoType(referencedPrimaryKeyType),
|
|
207
|
+
snakeReferenceName: (0, casing_1.snakeCase)(rel.referenceName || rel.name),
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
const pluralEntityName = (0, pluralize_1.default)(entityName);
|
|
211
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
212
|
+
const createdAt = entity.created_at;
|
|
213
|
+
const updatedAt = entity.updated_at;
|
|
214
|
+
const data = {
|
|
215
|
+
entityName,
|
|
216
|
+
pluralName: (0, casing_1.pascalCase)(pluralEntityName),
|
|
217
|
+
primaryKeyType,
|
|
218
|
+
createdAt,
|
|
219
|
+
updatedAt,
|
|
220
|
+
columns,
|
|
221
|
+
associations: [...new Set(goRelationships)],
|
|
222
|
+
};
|
|
223
|
+
const content = await this.renderTemplate("./services/service", data);
|
|
224
|
+
return [
|
|
225
|
+
{
|
|
226
|
+
path: `services/${(0, casing_1.snakeCase)(entityName)}.go`,
|
|
227
|
+
content,
|
|
228
|
+
},
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
async generateDto(options) {
|
|
232
|
+
const { entity, relationships, allEntities, apiType } = options;
|
|
233
|
+
const { name: entityName, fields = [] } = entity;
|
|
234
|
+
const columns = this.getGoFieldsForTemplate(fields, entityName);
|
|
235
|
+
const relationshipsTemplate = (0, relationships_1.getRelationshipForTemplate)(entityName, relationships, allEntities);
|
|
236
|
+
// Add Go-specific properties to relationships
|
|
237
|
+
const goRelationships = relationshipsTemplate.map((rel) => {
|
|
238
|
+
const referencedEntity = allEntities === null || allEntities === void 0 ? void 0 : allEntities.find((e) => e.name === rel.name);
|
|
239
|
+
const referencedPrimaryKeyType = (referencedEntity === null || referencedEntity === void 0 ? void 0 : referencedEntity.primaryKeyType) || "serial";
|
|
240
|
+
return {
|
|
241
|
+
...rel,
|
|
242
|
+
primaryKeyGoType: this.getPrimaryKeyGoType(referencedPrimaryKeyType),
|
|
243
|
+
camelReferenceName: (0, casing_1.camelCase)(rel.referenceName || rel.name),
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
const primaryKeyColumns = columns.filter((column) => column.primary === true);
|
|
247
|
+
const addDefaultPKProperty = primaryKeyColumns.length === 0;
|
|
248
|
+
const createdAt = entity.created_at;
|
|
249
|
+
const updatedAt = entity.updated_at;
|
|
250
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
251
|
+
const data = {
|
|
252
|
+
entityName,
|
|
253
|
+
addDefaultPKProperty,
|
|
254
|
+
primaryKeyType,
|
|
255
|
+
createdAt,
|
|
256
|
+
updatedAt,
|
|
257
|
+
columns,
|
|
258
|
+
associations: goRelationships,
|
|
259
|
+
apiType: apiType !== null && apiType !== void 0 ? apiType : "rest",
|
|
260
|
+
importEnums: (0, field_1.typeExistsInEntity)(entity, "enum") !== -1,
|
|
261
|
+
};
|
|
262
|
+
const content = await this.renderTemplate("./dto/dto", data);
|
|
263
|
+
return [
|
|
264
|
+
{
|
|
265
|
+
path: `dto/${(0, casing_1.snakeCase)(entityName)}.go`,
|
|
266
|
+
content,
|
|
267
|
+
},
|
|
268
|
+
];
|
|
269
|
+
}
|
|
270
|
+
async generateModule(_options) {
|
|
271
|
+
// Go doesn't have a module concept like NestJS
|
|
272
|
+
// Route registration is handled in the index module
|
|
273
|
+
return [];
|
|
274
|
+
}
|
|
275
|
+
async generateMigration(_options) {
|
|
276
|
+
// Goose handles migrations differently
|
|
277
|
+
// This is a placeholder for future migration template generation
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
async generateEnums(entities, _apiType) {
|
|
281
|
+
if (entities.length === 0) {
|
|
282
|
+
return [];
|
|
283
|
+
}
|
|
284
|
+
const allEnumsFields = entities
|
|
285
|
+
.flatMap((entity) => (entity.fields || []).map((field) => {
|
|
286
|
+
if (field.type === "enum") {
|
|
287
|
+
return {
|
|
288
|
+
...field,
|
|
289
|
+
name: (0, field_1.fieldToEnumType)(field.name, entity.name),
|
|
290
|
+
values: (field.values || []).map((value) => ({
|
|
291
|
+
value,
|
|
292
|
+
pascalCase: (0, casing_1.pascalCase)(value),
|
|
293
|
+
})),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}))
|
|
298
|
+
.filter(Boolean);
|
|
299
|
+
if (allEnumsFields.length === 0) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
const content = await this.renderTemplate("./enums", {
|
|
303
|
+
enums: allEnumsFields,
|
|
304
|
+
});
|
|
305
|
+
return [
|
|
306
|
+
{
|
|
307
|
+
path: "models/enums/enums.go",
|
|
308
|
+
content,
|
|
309
|
+
},
|
|
310
|
+
];
|
|
311
|
+
}
|
|
312
|
+
async generateIndexModule(entities, _apiType) {
|
|
313
|
+
const entitiesData = entities.map((entity) => ({
|
|
314
|
+
name: entity.name,
|
|
315
|
+
camelName: (0, casing_1.camelCase)(entity.name),
|
|
316
|
+
kebabName: (0, casing_1.kebabCase)(entity.name),
|
|
317
|
+
}));
|
|
318
|
+
const content = await this.renderTemplate("./index-module", {
|
|
319
|
+
entities: entitiesData,
|
|
320
|
+
});
|
|
321
|
+
return [
|
|
322
|
+
{
|
|
323
|
+
path: "routes/routes.go",
|
|
324
|
+
content,
|
|
325
|
+
},
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
async generateGuards(_entities, auth) {
|
|
329
|
+
const content = await this.renderTemplate("./middleware/auth", {
|
|
330
|
+
auth,
|
|
331
|
+
});
|
|
332
|
+
return [
|
|
333
|
+
{
|
|
334
|
+
path: "middleware/auth.go",
|
|
335
|
+
content,
|
|
336
|
+
},
|
|
337
|
+
];
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
exports.GoGenerator = GoGenerator;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { BaseGenerator } from "./base";
|
|
2
|
+
export { TypeScriptGenerator } from "./typescript";
|
|
3
|
+
export { PythonGenerator } from "./python";
|
|
4
|
+
export { GoGenerator } from "./go";
|
|
5
|
+
import { TargetLanguage, GeneratorConfig, LanguageGenerator } from "../types";
|
|
6
|
+
/**
|
|
7
|
+
* Factory function to create the appropriate generator for the target language
|
|
8
|
+
*/
|
|
9
|
+
export declare function createGenerator(config: GeneratorConfig): LanguageGenerator;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a language is supported
|
|
12
|
+
*/
|
|
13
|
+
export declare function isLanguageSupported(language: string): language is TargetLanguage;
|
|
14
|
+
/**
|
|
15
|
+
* Get list of all supported languages
|
|
16
|
+
*/
|
|
17
|
+
export declare function getSupportedLanguages(): TargetLanguage[];
|
|
18
|
+
/**
|
|
19
|
+
* Get list of currently implemented languages
|
|
20
|
+
*/
|
|
21
|
+
export declare function getImplementedLanguages(): TargetLanguage[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getImplementedLanguages = exports.getSupportedLanguages = exports.isLanguageSupported = exports.createGenerator = exports.GoGenerator = exports.PythonGenerator = exports.TypeScriptGenerator = exports.BaseGenerator = void 0;
|
|
4
|
+
var base_1 = require("./base");
|
|
5
|
+
Object.defineProperty(exports, "BaseGenerator", { enumerable: true, get: function () { return base_1.BaseGenerator; } });
|
|
6
|
+
var typescript_1 = require("./typescript");
|
|
7
|
+
Object.defineProperty(exports, "TypeScriptGenerator", { enumerable: true, get: function () { return typescript_1.TypeScriptGenerator; } });
|
|
8
|
+
var python_1 = require("./python");
|
|
9
|
+
Object.defineProperty(exports, "PythonGenerator", { enumerable: true, get: function () { return python_1.PythonGenerator; } });
|
|
10
|
+
var go_1 = require("./go");
|
|
11
|
+
Object.defineProperty(exports, "GoGenerator", { enumerable: true, get: function () { return go_1.GoGenerator; } });
|
|
12
|
+
const typescript_2 = require("./typescript");
|
|
13
|
+
const python_2 = require("./python");
|
|
14
|
+
const go_2 = require("./go");
|
|
15
|
+
/**
|
|
16
|
+
* Factory function to create the appropriate generator for the target language
|
|
17
|
+
*/
|
|
18
|
+
function createGenerator(config) {
|
|
19
|
+
switch (config.language) {
|
|
20
|
+
case "typescript":
|
|
21
|
+
return new typescript_2.TypeScriptGenerator(config);
|
|
22
|
+
case "python":
|
|
23
|
+
return new python_2.PythonGenerator(config);
|
|
24
|
+
case "go":
|
|
25
|
+
return new go_2.GoGenerator(config);
|
|
26
|
+
default:
|
|
27
|
+
throw new Error(`Unsupported language: ${config.language}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.createGenerator = createGenerator;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a language is supported
|
|
33
|
+
*/
|
|
34
|
+
function isLanguageSupported(language) {
|
|
35
|
+
return ["typescript", "python", "go"].includes(language);
|
|
36
|
+
}
|
|
37
|
+
exports.isLanguageSupported = isLanguageSupported;
|
|
38
|
+
/**
|
|
39
|
+
* Get list of all supported languages
|
|
40
|
+
*/
|
|
41
|
+
function getSupportedLanguages() {
|
|
42
|
+
return ["typescript", "python", "go"];
|
|
43
|
+
}
|
|
44
|
+
exports.getSupportedLanguages = getSupportedLanguages;
|
|
45
|
+
/**
|
|
46
|
+
* Get list of currently implemented languages
|
|
47
|
+
*/
|
|
48
|
+
function getImplementedLanguages() {
|
|
49
|
+
return ["typescript", "python", "go"];
|
|
50
|
+
}
|
|
51
|
+
exports.getImplementedLanguages = getImplementedLanguages;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseGenerator } from "./base";
|
|
2
|
+
import { TargetLanguage, GeneratedFile, ValidationResult, GeneratorConfig, EntityGenerationOptions, ControllerGenerationOptions, ServiceGenerationOptions, DtoGenerationOptions, MigrationGenerationOptions, Entity, AuthConfig } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Python/FastAPI generator that produces SQLAlchemy models, Pydantic schemas,
|
|
5
|
+
* and FastAPI routers.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PythonGenerator extends BaseGenerator {
|
|
8
|
+
constructor(config: GeneratorConfig);
|
|
9
|
+
getLanguage(): TargetLanguage;
|
|
10
|
+
getFileExtension(): string;
|
|
11
|
+
validateConfig(config: GeneratorConfig): ValidationResult;
|
|
12
|
+
generateEntity(options: EntityGenerationOptions): Promise<GeneratedFile[]>;
|
|
13
|
+
generateController(options: ControllerGenerationOptions): Promise<GeneratedFile[]>;
|
|
14
|
+
generateService(options: ServiceGenerationOptions): Promise<GeneratedFile[]>;
|
|
15
|
+
generateDto(options: DtoGenerationOptions): Promise<GeneratedFile[]>;
|
|
16
|
+
generateModule(_options: EntityGenerationOptions): Promise<GeneratedFile[]>;
|
|
17
|
+
generateMigration(_options: MigrationGenerationOptions): Promise<GeneratedFile[]>;
|
|
18
|
+
generateEnums(entities: Entity[], _apiType: string): Promise<GeneratedFile[]>;
|
|
19
|
+
generateIndexModule(entities: Entity[], _apiType: string): Promise<GeneratedFile[]>;
|
|
20
|
+
generateGuards(_entities: Entity[], _auth?: AuthConfig): Promise<GeneratedFile[]>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PythonGenerator = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
|
+
const Eta = tslib_1.__importStar(require("eta"));
|
|
7
|
+
const base_1 = require("./base");
|
|
8
|
+
const field_1 = require("../utils/field");
|
|
9
|
+
const relationships_1 = require("../utils/relationships");
|
|
10
|
+
const casing_1 = require("../utils/casing");
|
|
11
|
+
const pluralize_1 = tslib_1.__importDefault(require("pluralize"));
|
|
12
|
+
/**
|
|
13
|
+
* Python/FastAPI generator that produces SQLAlchemy models, Pydantic schemas,
|
|
14
|
+
* and FastAPI routers.
|
|
15
|
+
*/
|
|
16
|
+
class PythonGenerator extends base_1.BaseGenerator {
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super(config);
|
|
19
|
+
this.templateBasePath = path.join(__dirname, "../templates/python");
|
|
20
|
+
Eta.configure({
|
|
21
|
+
views: this.templateBasePath,
|
|
22
|
+
cache: false,
|
|
23
|
+
autoTrim: false,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
getLanguage() {
|
|
27
|
+
return "python";
|
|
28
|
+
}
|
|
29
|
+
getFileExtension() {
|
|
30
|
+
return ".py";
|
|
31
|
+
}
|
|
32
|
+
validateConfig(config) {
|
|
33
|
+
var _a;
|
|
34
|
+
const errors = [];
|
|
35
|
+
const warnings = [];
|
|
36
|
+
// Validate that entities are provided
|
|
37
|
+
if (!config.entities || config.entities.length === 0) {
|
|
38
|
+
errors.push("No entities defined in configuration");
|
|
39
|
+
}
|
|
40
|
+
// Validate each entity
|
|
41
|
+
for (const entity of config.entities) {
|
|
42
|
+
if (!entity.name) {
|
|
43
|
+
errors.push("Entity missing required 'name' property");
|
|
44
|
+
}
|
|
45
|
+
// Validate field types
|
|
46
|
+
for (const field of (_a = entity.fields) !== null && _a !== void 0 ? _a : []) {
|
|
47
|
+
if (!field.name) {
|
|
48
|
+
errors.push(`Entity '${entity.name}' has a field without a name`);
|
|
49
|
+
}
|
|
50
|
+
if (!field.type) {
|
|
51
|
+
errors.push(`Entity '${entity.name}' field '${field.name}' missing type`);
|
|
52
|
+
}
|
|
53
|
+
// Check for unsupported types
|
|
54
|
+
const supportedTypes = [
|
|
55
|
+
"text",
|
|
56
|
+
"varchar",
|
|
57
|
+
"string",
|
|
58
|
+
"integer",
|
|
59
|
+
"boolean",
|
|
60
|
+
"float",
|
|
61
|
+
"decimal",
|
|
62
|
+
"numeric",
|
|
63
|
+
"date",
|
|
64
|
+
"timestamp",
|
|
65
|
+
"timestamptz",
|
|
66
|
+
"json",
|
|
67
|
+
"jsonb",
|
|
68
|
+
"uuid",
|
|
69
|
+
"enum",
|
|
70
|
+
"array",
|
|
71
|
+
];
|
|
72
|
+
if (field.type && !supportedTypes.includes(field.type)) {
|
|
73
|
+
warnings.push(`Entity '${entity.name}' field '${field.name}' has type '${field.type}' which may not be fully supported`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Python-specific validation
|
|
78
|
+
if (config.apiType === "graphql") {
|
|
79
|
+
warnings.push("GraphQL support for Python is limited. REST API is recommended.");
|
|
80
|
+
}
|
|
81
|
+
return this.createValidationResult(errors, warnings);
|
|
82
|
+
}
|
|
83
|
+
async generateEntity(options) {
|
|
84
|
+
const { entity, relationships, allEntities, apiType } = options;
|
|
85
|
+
const { name, fields = [], indexes, uniques } = entity;
|
|
86
|
+
const columns = (0, field_1.getFieldForTemplate)(fields, name);
|
|
87
|
+
const createPrimaryKey = columns.filter((column) => column.primary === true).length === 0;
|
|
88
|
+
const createdAt = entity.created_at;
|
|
89
|
+
const updatedAt = entity.updated_at;
|
|
90
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
91
|
+
const relationshipsForTemplate = (0, relationships_1.getRelationshipForTemplate)(name, relationships, allEntities);
|
|
92
|
+
const entitiesToImport = (0, relationships_1.getRelationshipsForImport)(name, relationshipsForTemplate);
|
|
93
|
+
const data = {
|
|
94
|
+
name,
|
|
95
|
+
indexes: indexes || [],
|
|
96
|
+
uniques: uniques || [],
|
|
97
|
+
createPrimaryKey,
|
|
98
|
+
primaryKeyType,
|
|
99
|
+
snakeCasedName: (0, casing_1.snakeCase)(name),
|
|
100
|
+
createdAt,
|
|
101
|
+
updatedAt,
|
|
102
|
+
pluralizedName: (0, casing_1.camelCase)((0, pluralize_1.default)(name)),
|
|
103
|
+
columns,
|
|
104
|
+
associations: [...new Set(relationshipsForTemplate)],
|
|
105
|
+
entitiesToImport,
|
|
106
|
+
importEnums: (0, field_1.typeExistsInEntity)(entity, "enum") !== -1,
|
|
107
|
+
apiType,
|
|
108
|
+
};
|
|
109
|
+
const content = await this.renderTemplate("./models/model", data);
|
|
110
|
+
return [
|
|
111
|
+
{
|
|
112
|
+
path: `models/${name.toLowerCase()}.py`,
|
|
113
|
+
content,
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
async generateController(options) {
|
|
118
|
+
const { entity, relationships } = options;
|
|
119
|
+
const { name: entityName } = entity;
|
|
120
|
+
const relationshipsForTemplate = (0, relationships_1.getRelationshipForTemplate)(entityName, relationships);
|
|
121
|
+
const pluralEntityName = (0, pluralize_1.default)(entityName);
|
|
122
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
123
|
+
const data = {
|
|
124
|
+
entityName,
|
|
125
|
+
pluralEntityName,
|
|
126
|
+
primaryKeyType,
|
|
127
|
+
associations: [...new Set(relationshipsForTemplate)],
|
|
128
|
+
};
|
|
129
|
+
const content = await this.renderTemplate("./routers/router", data);
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
path: `routers/${entityName.toLowerCase()}.py`,
|
|
133
|
+
content,
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
async generateService(options) {
|
|
138
|
+
const { entity, relationships } = options;
|
|
139
|
+
const { name: entityName } = entity;
|
|
140
|
+
const relationshipsForTemplate = (0, relationships_1.getRelationshipForTemplate)(entityName, relationships);
|
|
141
|
+
const pluralEntityName = (0, pluralize_1.default)(entityName);
|
|
142
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
143
|
+
const data = {
|
|
144
|
+
entityName,
|
|
145
|
+
pluralEntityName,
|
|
146
|
+
primaryKeyType,
|
|
147
|
+
associations: [...new Set(relationshipsForTemplate)],
|
|
148
|
+
};
|
|
149
|
+
const content = await this.renderTemplate("./services/service", data);
|
|
150
|
+
return [
|
|
151
|
+
{
|
|
152
|
+
path: `services/${entityName.toLowerCase()}.py`,
|
|
153
|
+
content,
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
async generateDto(options) {
|
|
158
|
+
const { entity, relationships, allEntities, apiType } = options;
|
|
159
|
+
const { name: entityName, fields = [] } = entity;
|
|
160
|
+
const columns = (0, field_1.getFieldForTemplate)(fields, entityName);
|
|
161
|
+
const relationshipsTemplate = (0, relationships_1.getRelationshipForTemplate)(entityName, relationships);
|
|
162
|
+
// Add foreign key columns for ManyToOne relationships
|
|
163
|
+
relationshipsTemplate.forEach((rel) => {
|
|
164
|
+
if (rel.type === "ManyToOne") {
|
|
165
|
+
const fkName = (0, casing_1.camelCase)(rel.referenceName || rel.name) + "Id";
|
|
166
|
+
const referencedEntity = allEntities === null || allEntities === void 0 ? void 0 : allEntities.find((e) => e.name === rel.name);
|
|
167
|
+
const referencedPrimaryKeyType = (referencedEntity === null || referencedEntity === void 0 ? void 0 : referencedEntity.primaryKeyType) || "serial";
|
|
168
|
+
const fkDataType = referencedPrimaryKeyType === "uuid" ? "string" : "number";
|
|
169
|
+
const fkType = referencedPrimaryKeyType === "uuid" ? "text" : "integer";
|
|
170
|
+
if (!columns.some((col) => col.name === fkName)) {
|
|
171
|
+
columns.push({
|
|
172
|
+
name: fkName,
|
|
173
|
+
dataType: fkDataType,
|
|
174
|
+
type: fkType,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
const primaryKeyColumns = columns.filter((column) => column.primary === true);
|
|
180
|
+
const addDefaultPKProperty = primaryKeyColumns.length === 0;
|
|
181
|
+
const createdAt = entity.created_at;
|
|
182
|
+
const updatedAt = entity.updated_at;
|
|
183
|
+
const primaryKeyType = entity.primaryKeyType || "serial";
|
|
184
|
+
const data = {
|
|
185
|
+
entityName,
|
|
186
|
+
addDefaultPKProperty,
|
|
187
|
+
primaryKeyType,
|
|
188
|
+
createdAt,
|
|
189
|
+
updatedAt,
|
|
190
|
+
columns,
|
|
191
|
+
associations: relationshipsTemplate,
|
|
192
|
+
apiType: apiType !== null && apiType !== void 0 ? apiType : "rest",
|
|
193
|
+
importEnums: (0, field_1.typeExistsInEntity)(entity, "enum") !== -1,
|
|
194
|
+
};
|
|
195
|
+
const content = await this.renderTemplate("./schemas/schema", data);
|
|
196
|
+
return [
|
|
197
|
+
{
|
|
198
|
+
path: `schemas/${entityName.toLowerCase()}.py`,
|
|
199
|
+
content,
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
async generateModule(_options) {
|
|
204
|
+
// Python doesn't have a module concept like NestJS
|
|
205
|
+
// The router registration is handled in the index module
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
async generateMigration(_options) {
|
|
209
|
+
// Alembic handles migrations differently
|
|
210
|
+
// This is a placeholder for future migration template generation
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
async generateEnums(entities, _apiType) {
|
|
214
|
+
if (entities.length === 0) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
const allEnumsFields = entities
|
|
218
|
+
.flatMap((entity) => (entity.fields || []).map((field) => {
|
|
219
|
+
if (field.type === "enum") {
|
|
220
|
+
return { ...field, name: (0, field_1.fieldToEnumType)(field.name, entity.name) };
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}))
|
|
224
|
+
.filter(Boolean);
|
|
225
|
+
if (allEnumsFields.length === 0) {
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
const content = await this.renderTemplate("./enums", {
|
|
229
|
+
allEnumsFields,
|
|
230
|
+
});
|
|
231
|
+
return [
|
|
232
|
+
{
|
|
233
|
+
path: "models/enums.py",
|
|
234
|
+
content,
|
|
235
|
+
},
|
|
236
|
+
];
|
|
237
|
+
}
|
|
238
|
+
async generateIndexModule(entities, _apiType) {
|
|
239
|
+
const content = await this.renderTemplate("./index-module", { entities });
|
|
240
|
+
return [
|
|
241
|
+
{
|
|
242
|
+
path: "__init__.py",
|
|
243
|
+
content,
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
async generateGuards(_entities, _auth) {
|
|
248
|
+
// Python auth/guards would be implemented differently (e.g., FastAPI dependencies)
|
|
249
|
+
// This is a placeholder for future implementation
|
|
250
|
+
return [];
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.PythonGenerator = PythonGenerator;
|