@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.
Files changed (204) hide show
  1. package/dist/autogen/index.d.ts +2 -0
  2. package/dist/autogen/index.js +3 -0
  3. package/dist/commands/server/new.d.ts +4 -1
  4. package/dist/commands/server/new.js +115 -22
  5. package/dist/commands/server/scaffold.d.ts +11 -0
  6. package/dist/commands/server/scaffold.js +213 -12
  7. package/dist/lib/api/client.d.ts +65 -0
  8. package/dist/lib/api/client.js +305 -0
  9. package/dist/lib/api/index.d.ts +8 -0
  10. package/dist/lib/api/index.js +22 -0
  11. package/dist/lib/api/services.d.ts +166 -0
  12. package/dist/lib/api/services.js +202 -0
  13. package/dist/lib/api/types.d.ts +212 -0
  14. package/dist/lib/api/types.js +7 -0
  15. package/dist/lib/apsorc-parser.d.ts +3 -0
  16. package/dist/lib/apsorc-parser.js +4 -0
  17. package/dist/lib/config/index.d.ts +8 -0
  18. package/dist/lib/config/index.js +17 -0
  19. package/dist/lib/config/manager.d.ts +127 -0
  20. package/dist/lib/config/manager.js +304 -0
  21. package/dist/lib/config/paths.d.ts +65 -0
  22. package/dist/lib/config/paths.js +127 -0
  23. package/dist/lib/config/types.d.ts +230 -0
  24. package/dist/lib/config/types.js +30 -0
  25. package/dist/lib/generators/base.d.ts +93 -0
  26. package/dist/lib/generators/base.js +90 -0
  27. package/dist/lib/generators/go.d.ts +37 -0
  28. package/dist/lib/generators/go.js +340 -0
  29. package/dist/lib/generators/index.d.ts +21 -0
  30. package/dist/lib/generators/index.js +51 -0
  31. package/dist/lib/generators/python.d.ts +21 -0
  32. package/dist/lib/generators/python.js +253 -0
  33. package/dist/lib/generators/typescript.d.ts +25 -0
  34. package/dist/lib/generators/typescript.js +373 -0
  35. package/dist/lib/index.d.ts +2 -0
  36. package/dist/lib/index.js +9 -1
  37. package/dist/lib/templates/entities/entity-col-timestamp.eta +9 -2
  38. package/dist/lib/templates/entities/entity-col-timestamptz.eta +9 -2
  39. package/dist/lib/templates/entities/entity.eta +18 -5
  40. package/dist/lib/templates/go/dto/dto-col-array.eta +7 -0
  41. package/dist/lib/templates/go/dto/dto-col-boolean.eta +7 -0
  42. package/dist/lib/templates/go/dto/dto-col-date.eta +7 -0
  43. package/dist/lib/templates/go/dto/dto-col-decimal.eta +7 -0
  44. package/dist/lib/templates/go/dto/dto-col-enum.eta +8 -0
  45. package/dist/lib/templates/go/dto/dto-col-float.eta +7 -0
  46. package/dist/lib/templates/go/dto/dto-col-integer.eta +7 -0
  47. package/dist/lib/templates/go/dto/dto-col-json.eta +7 -0
  48. package/dist/lib/templates/go/dto/dto-col-jsonb.eta +7 -0
  49. package/dist/lib/templates/go/dto/dto-col-numeric.eta +7 -0
  50. package/dist/lib/templates/go/dto/dto-col-string.eta +7 -0
  51. package/dist/lib/templates/go/dto/dto-col-text.eta +7 -0
  52. package/dist/lib/templates/go/dto/dto-col-timestamp.eta +7 -0
  53. package/dist/lib/templates/go/dto/dto-col-timestamptz.eta +7 -0
  54. package/dist/lib/templates/go/dto/dto-col-uuid.eta +7 -0
  55. package/dist/lib/templates/go/dto/dto-col-varchar.eta +7 -0
  56. package/dist/lib/templates/go/dto/dto.eta +78 -0
  57. package/dist/lib/templates/go/enums.eta +44 -0
  58. package/dist/lib/templates/go/handlers/handler.eta +212 -0
  59. package/dist/lib/templates/go/header.eta +3 -0
  60. package/dist/lib/templates/go/index-module.eta +53 -0
  61. package/dist/lib/templates/go/middleware/auth.eta +101 -0
  62. package/dist/lib/templates/go/models/model-col-array.eta +1 -0
  63. package/dist/lib/templates/go/models/model-col-boolean.eta +1 -0
  64. package/dist/lib/templates/go/models/model-col-date.eta +1 -0
  65. package/dist/lib/templates/go/models/model-col-decimal.eta +1 -0
  66. package/dist/lib/templates/go/models/model-col-enum.eta +2 -0
  67. package/dist/lib/templates/go/models/model-col-float.eta +1 -0
  68. package/dist/lib/templates/go/models/model-col-integer.eta +1 -0
  69. package/dist/lib/templates/go/models/model-col-json.eta +1 -0
  70. package/dist/lib/templates/go/models/model-col-jsonb.eta +1 -0
  71. package/dist/lib/templates/go/models/model-col-numeric.eta +1 -0
  72. package/dist/lib/templates/go/models/model-col-string.eta +1 -0
  73. package/dist/lib/templates/go/models/model-col-text.eta +1 -0
  74. package/dist/lib/templates/go/models/model-col-timestamp.eta +1 -0
  75. package/dist/lib/templates/go/models/model-col-timestamptz.eta +1 -0
  76. package/dist/lib/templates/go/models/model-col-uuid.eta +1 -0
  77. package/dist/lib/templates/go/models/model-col-varchar.eta +1 -0
  78. package/dist/lib/templates/go/models/model.eta +53 -0
  79. package/dist/lib/templates/go/services/service.eta +190 -0
  80. package/dist/lib/templates/python/enums.eta +10 -0
  81. package/dist/lib/templates/python/header.eta +6 -0
  82. package/dist/lib/templates/python/index-module.eta +18 -0
  83. package/dist/lib/templates/python/models/model-col-array.eta +4 -0
  84. package/dist/lib/templates/python/models/model-col-boolean.eta +5 -0
  85. package/dist/lib/templates/python/models/model-col-date.eta +4 -0
  86. package/dist/lib/templates/python/models/model-col-decimal.eta +4 -0
  87. package/dist/lib/templates/python/models/model-col-enum.eta +16 -0
  88. package/dist/lib/templates/python/models/model-col-float.eta +5 -0
  89. package/dist/lib/templates/python/models/model-col-integer.eta +6 -0
  90. package/dist/lib/templates/python/models/model-col-json.eta +4 -0
  91. package/dist/lib/templates/python/models/model-col-jsonb.eta +4 -0
  92. package/dist/lib/templates/python/models/model-col-numeric.eta +4 -0
  93. package/dist/lib/templates/python/models/model-col-string.eta +6 -0
  94. package/dist/lib/templates/python/models/model-col-text.eta +6 -0
  95. package/dist/lib/templates/python/models/model-col-timestamp.eta +11 -0
  96. package/dist/lib/templates/python/models/model-col-timestamptz.eta +11 -0
  97. package/dist/lib/templates/python/models/model-col-uuid.eta +5 -0
  98. package/dist/lib/templates/python/models/model-col-varchar.eta +6 -0
  99. package/dist/lib/templates/python/models/model.eta +124 -0
  100. package/dist/lib/templates/python/routers/router.eta +206 -0
  101. package/dist/lib/templates/python/schemas/schema-col-array.eta +1 -0
  102. package/dist/lib/templates/python/schemas/schema-col-boolean.eta +1 -0
  103. package/dist/lib/templates/python/schemas/schema-col-date.eta +1 -0
  104. package/dist/lib/templates/python/schemas/schema-col-decimal.eta +1 -0
  105. package/dist/lib/templates/python/schemas/schema-col-enum.eta +6 -0
  106. package/dist/lib/templates/python/schemas/schema-col-float.eta +1 -0
  107. package/dist/lib/templates/python/schemas/schema-col-integer.eta +1 -0
  108. package/dist/lib/templates/python/schemas/schema-col-json.eta +1 -0
  109. package/dist/lib/templates/python/schemas/schema-col-jsonb.eta +1 -0
  110. package/dist/lib/templates/python/schemas/schema-col-numeric.eta +1 -0
  111. package/dist/lib/templates/python/schemas/schema-col-string.eta +1 -0
  112. package/dist/lib/templates/python/schemas/schema-col-text.eta +1 -0
  113. package/dist/lib/templates/python/schemas/schema-col-timestamp.eta +1 -0
  114. package/dist/lib/templates/python/schemas/schema-col-timestamptz.eta +1 -0
  115. package/dist/lib/templates/python/schemas/schema-col-uuid.eta +1 -0
  116. package/dist/lib/templates/python/schemas/schema-col-varchar.eta +1 -0
  117. package/dist/lib/templates/python/schemas/schema.eta +87 -0
  118. package/dist/lib/templates/python/services/service.eta +163 -0
  119. package/dist/lib/templates/rest/controller-rest.eta +13 -12
  120. package/dist/lib/templates/rest/dto-rest.eta +173 -59
  121. package/dist/lib/templates/rest/service-rest.eta +50 -10
  122. package/dist/lib/types/generator.d.ts +241 -0
  123. package/dist/lib/types/generator.js +2 -0
  124. package/dist/lib/types/index.d.ts +1 -0
  125. package/dist/lib/utils/casing.d.ts +1 -0
  126. package/dist/lib/utils/casing.js +11 -1
  127. package/oclif.manifest.json +39 -3
  128. package/package.json +4 -2
  129. package/dist/lib/utils/relationships/parse.spec.d.ts +0 -1
  130. package/dist/lib/utils/relationships/parse.spec.js +0 -402
  131. package/dist/tests/templates/entities/types/array-template.spec.d.ts +0 -1
  132. package/dist/tests/templates/entities/types/array-template.spec.js +0 -82
  133. package/dist/tests/templates/entities/types/bigint-template.spec.d.ts +0 -1
  134. package/dist/tests/templates/entities/types/bigint-template.spec.js +0 -82
  135. package/dist/tests/templates/entities/types/boolean-template.spec.d.ts +0 -1
  136. package/dist/tests/templates/entities/types/boolean-template.spec.js +0 -77
  137. package/dist/tests/templates/entities/types/bytea-template.spec.d.ts +0 -1
  138. package/dist/tests/templates/entities/types/bytea-template.spec.js +0 -68
  139. package/dist/tests/templates/entities/types/char-template.spec.d.ts +0 -1
  140. package/dist/tests/templates/entities/types/char-template.spec.js +0 -68
  141. package/dist/tests/templates/entities/types/date-template.spec.d.ts +0 -1
  142. package/dist/tests/templates/entities/types/date-template.spec.js +0 -56
  143. package/dist/tests/templates/entities/types/decimal-field-validation.spec.d.ts +0 -1
  144. package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +0 -100
  145. package/dist/tests/templates/entities/types/decimal-template.spec.d.ts +0 -1
  146. package/dist/tests/templates/entities/types/decimal-template.spec.js +0 -86
  147. package/dist/tests/templates/entities/types/double-template.spec.d.ts +0 -1
  148. package/dist/tests/templates/entities/types/double-template.spec.js +0 -70
  149. package/dist/tests/templates/entities/types/enum-template.spec.d.ts +0 -1
  150. package/dist/tests/templates/entities/types/enum-template.spec.js +0 -85
  151. package/dist/tests/templates/entities/types/float-template.spec.d.ts +0 -1
  152. package/dist/tests/templates/entities/types/float-template.spec.js +0 -70
  153. package/dist/tests/templates/entities/types/geometry-template.spec.d.ts +0 -1
  154. package/dist/tests/templates/entities/types/geometry-template.spec.js +0 -58
  155. package/dist/tests/templates/entities/types/inet-template.spec.d.ts +0 -1
  156. package/dist/tests/templates/entities/types/inet-template.spec.js +0 -69
  157. package/dist/tests/templates/entities/types/int4range-template.spec.d.ts +0 -1
  158. package/dist/tests/templates/entities/types/int4range-template.spec.js +0 -72
  159. package/dist/tests/templates/entities/types/integer-template.spec.d.ts +0 -1
  160. package/dist/tests/templates/entities/types/integer-template.spec.js +0 -79
  161. package/dist/tests/templates/entities/types/interval-template.spec.d.ts +0 -1
  162. package/dist/tests/templates/entities/types/interval-template.spec.js +0 -68
  163. package/dist/tests/templates/entities/types/json-plain-template.spec.d.ts +0 -1
  164. package/dist/tests/templates/entities/types/json-plain-template.spec.js +0 -54
  165. package/dist/tests/templates/entities/types/json-template.spec.d.ts +0 -1
  166. package/dist/tests/templates/entities/types/json-template.spec.js +0 -40
  167. package/dist/tests/templates/entities/types/jsonb-template.spec.d.ts +0 -1
  168. package/dist/tests/templates/entities/types/jsonb-template.spec.js +0 -40
  169. package/dist/tests/templates/entities/types/money-template.spec.d.ts +0 -1
  170. package/dist/tests/templates/entities/types/money-template.spec.js +0 -68
  171. package/dist/tests/templates/entities/types/numeric-template.spec.d.ts +0 -1
  172. package/dist/tests/templates/entities/types/numeric-template.spec.js +0 -84
  173. package/dist/tests/templates/entities/types/point-template.spec.d.ts +0 -1
  174. package/dist/tests/templates/entities/types/point-template.spec.js +0 -64
  175. package/dist/tests/templates/entities/types/polygon-template.spec.d.ts +0 -1
  176. package/dist/tests/templates/entities/types/polygon-template.spec.js +0 -70
  177. package/dist/tests/templates/entities/types/real-template.spec.d.ts +0 -1
  178. package/dist/tests/templates/entities/types/real-template.spec.js +0 -67
  179. package/dist/tests/templates/entities/types/serial-template.spec.d.ts +0 -1
  180. package/dist/tests/templates/entities/types/serial-template.spec.js +0 -113
  181. package/dist/tests/templates/entities/types/smallint-template.spec.d.ts +0 -1
  182. package/dist/tests/templates/entities/types/smallint-template.spec.js +0 -82
  183. package/dist/tests/templates/entities/types/string-template.spec.d.ts +0 -1
  184. package/dist/tests/templates/entities/types/string-template.spec.js +0 -111
  185. package/dist/tests/templates/entities/types/text-template.spec.d.ts +0 -1
  186. package/dist/tests/templates/entities/types/text-template.spec.js +0 -70
  187. package/dist/tests/templates/entities/types/time-template.spec.d.ts +0 -1
  188. package/dist/tests/templates/entities/types/time-template.spec.js +0 -68
  189. package/dist/tests/templates/entities/types/timestamp-template.spec.d.ts +0 -1
  190. package/dist/tests/templates/entities/types/timestamp-template.spec.js +0 -74
  191. package/dist/tests/templates/entities/types/timetz-template.spec.d.ts +0 -1
  192. package/dist/tests/templates/entities/types/timetz-template.spec.js +0 -68
  193. package/dist/tests/templates/entities/types/tsvector-template.spec.d.ts +0 -1
  194. package/dist/tests/templates/entities/types/tsvector-template.spec.js +0 -55
  195. package/dist/tests/templates/entities/types/uuid-template.spec.d.ts +0 -1
  196. package/dist/tests/templates/entities/types/uuid-template.spec.js +0 -82
  197. package/dist/tests/templates/entities/types/varchar-template.spec.d.ts +0 -1
  198. package/dist/tests/templates/entities/types/varchar-template.spec.js +0 -105
  199. package/dist/tests/templates/entities/types/xml-template.spec.d.ts +0 -1
  200. package/dist/tests/templates/entities/types/xml-template.spec.js +0 -55
  201. package/dist/tests/templates/entities/uuid-entity-template.spec.d.ts +0 -1
  202. package/dist/tests/templates/entities/uuid-entity-template.spec.js +0 -277
  203. package/dist/tests/utils/relationship-deduplication.spec.d.ts +0 -1
  204. 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;