@nestledjs/api 0.0.15 → 0.0.17
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/package.json
CHANGED
package/src/custom/generator.js
CHANGED
|
@@ -80,8 +80,8 @@ function generateCustomFiles(tree, customLibraryRoot, models, npmScope, dependen
|
|
|
80
80
|
const pluginsDir = dependencies.join(customLibraryRoot, 'src/lib/plugins');
|
|
81
81
|
yield ensureDirExists(tree, defaultDir);
|
|
82
82
|
yield ensureDirExists(tree, pluginsDir);
|
|
83
|
-
//
|
|
84
|
-
tree.write(dependencies.join(pluginsDir, '.
|
|
83
|
+
// Create empty index.ts in pluginsDir for custom plugins
|
|
84
|
+
tree.write(dependencies.join(pluginsDir, 'index.ts'), '');
|
|
85
85
|
for (const model of models) {
|
|
86
86
|
const kebabModel = toKebabCase(model.modelName);
|
|
87
87
|
const modelFolder = dependencies.join(defaultDir, kebabModel);
|
|
@@ -142,10 +142,15 @@ export class ${model.modelName}Module {}
|
|
|
142
142
|
importPath: `${npmScope}/api/custom`,
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
//
|
|
145
|
+
// Create stable main index.ts that exports from both plugins and default
|
|
146
|
+
const mainIndexContent = `export * from './lib/plugins'
|
|
147
|
+
export * from './lib/default'
|
|
148
|
+
`;
|
|
149
|
+
tree.write(dependencies.join(customLibraryRoot, 'src/index.ts'), mainIndexContent);
|
|
150
|
+
// Update default/index.ts to export all model modules
|
|
146
151
|
const modelFolders = models.map((m) => toKebabCase(m.modelName));
|
|
147
|
-
const
|
|
148
|
-
tree.write(dependencies.join(
|
|
152
|
+
const defaultIndexContent = modelFolders.map((m) => `export * from './${m}/${m}.module'`).join('\n');
|
|
153
|
+
tree.write(dependencies.join(defaultDir, 'index.ts'), defaultIndexContent);
|
|
149
154
|
});
|
|
150
155
|
}
|
|
151
156
|
function customGeneratorLogic(tree_1, schema_1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/custom/generator.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/custom/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,14 +8,136 @@ import * as dto from './dto'
|
|
|
8
8
|
<% if (!model.modelName || !model.pluralModelName) { throw new Error('EJS template error: modelName or pluralModelName missing for model at index ' + idx + ': ' + JSON.stringify(model)); } %>
|
|
9
9
|
<% }) %>
|
|
10
10
|
|
|
11
|
+
<%
|
|
12
|
+
// Helper function to get relation fields for a model
|
|
13
|
+
function getRelationFields(model) {
|
|
14
|
+
return model.fields.filter(field => field.relationName && field.relationName.length > 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Helper function to get virtual relation fields for a model
|
|
18
|
+
function getVirtualRelationFields(model) {
|
|
19
|
+
const relationFields = getRelationFields(model);
|
|
20
|
+
const virtualFields = [];
|
|
21
|
+
|
|
22
|
+
relationFields.forEach(relationField => {
|
|
23
|
+
// Only generate virtual fields for relations that don't have explicit foreign keys
|
|
24
|
+
if (!relationField.relationFromFields || relationField.relationFromFields.length === 0) {
|
|
25
|
+
if (relationField.isList) {
|
|
26
|
+
// This is a multi-relation without foreign keys (many-to-many or one-to-many from parent)
|
|
27
|
+
// Generate a virtual foreign key field for connecting
|
|
28
|
+
const virtualFieldName = relationField.name + 'Ids';
|
|
29
|
+
// Check if there's already a scalar field with this name
|
|
30
|
+
const existingField = model.fields.find(f => f.name === virtualFieldName && (!f.relationName || f.relationName.length === 0));
|
|
31
|
+
if (!existingField) {
|
|
32
|
+
virtualFields.push({
|
|
33
|
+
name: virtualFieldName,
|
|
34
|
+
type: 'String',
|
|
35
|
+
isList: true,
|
|
36
|
+
isOptional: true,
|
|
37
|
+
isVirtual: true,
|
|
38
|
+
relationName: relationField.relationName,
|
|
39
|
+
relatedField: relationField.name
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// This is a single relation without foreign keys (one-to-one or one-to-many from parent)
|
|
44
|
+
// Generate a virtual foreign key field for connecting
|
|
45
|
+
const virtualFieldName = relationField.name + 'Id';
|
|
46
|
+
// Check if there's already a scalar field with this name
|
|
47
|
+
const existingField = model.fields.find(f => f.name === virtualFieldName && (!f.relationName || f.relationName.length === 0));
|
|
48
|
+
if (!existingField) {
|
|
49
|
+
virtualFields.push({
|
|
50
|
+
name: virtualFieldName,
|
|
51
|
+
type: 'String',
|
|
52
|
+
isList: false,
|
|
53
|
+
isOptional: true,
|
|
54
|
+
isVirtual: true,
|
|
55
|
+
relationName: relationField.relationName,
|
|
56
|
+
relatedField: relationField.name
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return virtualFields;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Helper function to get foreign key fields that need relation handling
|
|
67
|
+
function getForeignKeyRelationFields(model) {
|
|
68
|
+
const relationFields = getRelationFields(model);
|
|
69
|
+
const foreignKeyFields = [];
|
|
70
|
+
|
|
71
|
+
relationFields.forEach(relationField => {
|
|
72
|
+
if (relationField.relationFromFields && relationField.relationFromFields.length > 0) {
|
|
73
|
+
// This relation has explicit foreign key fields
|
|
74
|
+
relationField.relationFromFields.forEach(fkFieldName => {
|
|
75
|
+
const fkField = model.fields.find(f => f.name === fkFieldName);
|
|
76
|
+
if (fkField) {
|
|
77
|
+
foreignKeyFields.push({
|
|
78
|
+
fieldName: fkFieldName,
|
|
79
|
+
relationName: relationField.name,
|
|
80
|
+
isRequired: !fkField.isOptional
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return foreignKeyFields;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Helper function to generate relation handling code
|
|
91
|
+
function generateRelationHandling(model, operation) {
|
|
92
|
+
const virtualRelationFields = getVirtualRelationFields(model);
|
|
93
|
+
const foreignKeyFields = getForeignKeyRelationFields(model);
|
|
94
|
+
const allRelationFields = [...virtualRelationFields, ...foreignKeyFields];
|
|
95
|
+
|
|
96
|
+
if (allRelationFields.length === 0) {
|
|
97
|
+
return ' const data = input;';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let code = ' const { ';
|
|
101
|
+
code += virtualRelationFields.map(field => field.name).join(', ');
|
|
102
|
+
if (foreignKeyFields.length > 0) {
|
|
103
|
+
if (virtualRelationFields.length > 0) code += ', ';
|
|
104
|
+
code += foreignKeyFields.map(field => field.fieldName).join(', ');
|
|
105
|
+
}
|
|
106
|
+
code += ', ...regularFields } = input;\n';
|
|
107
|
+
code += ' const data: any = regularFields;\n\n';
|
|
108
|
+
|
|
109
|
+
// Handle virtual relation fields (many-to-many without explicit FKs)
|
|
110
|
+
virtualRelationFields.forEach(field => {
|
|
111
|
+
code += ` if (${field.name}) {\n`;
|
|
112
|
+
if (field.isList) {
|
|
113
|
+
code += ` data.${field.relatedField} = { ${operation === 'create' ? 'connect' : 'set'}: ${field.name}.map(id => ({ id })) };\n`;
|
|
114
|
+
} else {
|
|
115
|
+
code += ` data.${field.relatedField} = { connect: { id: ${field.name} } };\n`;
|
|
116
|
+
}
|
|
117
|
+
code += ' }\n';
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Handle foreign key fields (explicit FK relations)
|
|
121
|
+
foreignKeyFields.forEach(field => {
|
|
122
|
+
code += ` if (${field.fieldName}) {\n`;
|
|
123
|
+
code += ` data.${field.relationName} = { connect: { id: ${field.fieldName} } };\n`;
|
|
124
|
+
code += ' }\n';
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return code;
|
|
128
|
+
}
|
|
129
|
+
%>
|
|
130
|
+
|
|
11
131
|
@Injectable()
|
|
12
132
|
export class ApiCrudDataAccessService {
|
|
13
133
|
constructor(private readonly data: ApiCoreDataAccessService) {}
|
|
14
134
|
|
|
15
135
|
<% for (const model of models) { %>
|
|
16
136
|
async create<%= model.modelName.charAt(0).toUpperCase() + model.modelName.slice(1) %>(info: GraphQLResolveInfo, input: dto.Create<%= model.modelName %>Input) {
|
|
137
|
+
<%- generateRelationHandling(model, 'create') %>
|
|
138
|
+
|
|
17
139
|
return this.data['<%= model.modelPropertyName %>'].create({
|
|
18
|
-
data
|
|
140
|
+
data,
|
|
19
141
|
select: createSelect(info),
|
|
20
142
|
});
|
|
21
143
|
}
|
|
@@ -52,9 +174,11 @@ export class ApiCrudDataAccessService {
|
|
|
52
174
|
}
|
|
53
175
|
|
|
54
176
|
async update<%= model.modelName.charAt(0).toUpperCase() + model.modelName.slice(1) %>(info: GraphQLResolveInfo, id: string, input: dto.Update<%= model.modelName %>Input) {
|
|
177
|
+
<%- generateRelationHandling(model, 'update') %>
|
|
178
|
+
|
|
55
179
|
return this.data['<%= model.modelPropertyName %>'].update({
|
|
56
180
|
where: { id },
|
|
57
|
-
data
|
|
181
|
+
data,
|
|
58
182
|
select: createSelect(info),
|
|
59
183
|
});
|
|
60
184
|
}
|
|
@@ -9,10 +9,64 @@ let enumNames = new Set();
|
|
|
9
9
|
let usesPartialType = false;
|
|
10
10
|
const alwaysOptionalFields = ['id', 'createdAt', 'updatedAt'];
|
|
11
11
|
|
|
12
|
+
// Helper function to get relation fields for a model
|
|
13
|
+
function getRelationFields(model) {
|
|
14
|
+
return model.fields.filter(field => field.relationName && field.relationName.length > 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Helper function to get virtual relation fields for a model
|
|
18
|
+
function getVirtualRelationFields(model) {
|
|
19
|
+
const relationFields = getRelationFields(model);
|
|
20
|
+
const virtualFields = [];
|
|
21
|
+
|
|
22
|
+
relationFields.forEach(relationField => {
|
|
23
|
+
// Only generate virtual fields for relations that don't have explicit foreign keys
|
|
24
|
+
if (!relationField.relationFromFields || relationField.relationFromFields.length === 0) {
|
|
25
|
+
if (relationField.isList) {
|
|
26
|
+
// This is a multi-relation without foreign keys (many-to-many or one-to-many from parent)
|
|
27
|
+
// Generate a virtual foreign key field for connecting
|
|
28
|
+
const virtualFieldName = relationField.name + 'Ids';
|
|
29
|
+
// Check if there's already a scalar field with this name
|
|
30
|
+
const existingField = model.fields.find(f => f.name === virtualFieldName && (!f.relationName || f.relationName.length === 0));
|
|
31
|
+
if (!existingField) {
|
|
32
|
+
virtualFields.push({
|
|
33
|
+
name: virtualFieldName,
|
|
34
|
+
type: 'String',
|
|
35
|
+
isList: true,
|
|
36
|
+
isOptional: true,
|
|
37
|
+
isVirtual: true, // Mark as virtual so we know it's generated
|
|
38
|
+
relationName: relationField.relationName,
|
|
39
|
+
relatedField: relationField.name
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// This is a single relation without foreign keys (one-to-one or one-to-many from parent)
|
|
44
|
+
// Generate a virtual foreign key field for connecting
|
|
45
|
+
const virtualFieldName = relationField.name + 'Id';
|
|
46
|
+
// Check if there's already a scalar field with this name
|
|
47
|
+
const existingField = model.fields.find(f => f.name === virtualFieldName && (!f.relationName || f.relationName.length === 0));
|
|
48
|
+
if (!existingField) {
|
|
49
|
+
virtualFields.push({
|
|
50
|
+
name: virtualFieldName,
|
|
51
|
+
type: 'String',
|
|
52
|
+
isList: false,
|
|
53
|
+
isOptional: true,
|
|
54
|
+
isVirtual: true, // Mark as virtual so we know it's generated
|
|
55
|
+
relationName: relationField.relationName,
|
|
56
|
+
relatedField: relationField.name
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return virtualFields;
|
|
64
|
+
}
|
|
65
|
+
|
|
12
66
|
// First pass to determine necessary imports and enums
|
|
13
67
|
for (const model of models) {
|
|
14
68
|
for (const field of model.fields) {
|
|
15
|
-
if (field.
|
|
69
|
+
if (field.relationName && field.relationName.length > 0) continue; // Skip relation object fields
|
|
16
70
|
if (field.type === 'Int') usesInt = true;
|
|
17
71
|
if (field.type === 'Float' || field.type === 'Decimal') usesFloat = true;
|
|
18
72
|
if (field.type === 'Json') usesGraphQLJSON = true;
|
|
@@ -34,10 +88,15 @@ import { <%= Array.from(gqlImports).join(', ') %> } from '@nestjs/graphql'
|
|
|
34
88
|
import { CorePagingInput } from '@<%= npmScope %>/api/core/data-access'
|
|
35
89
|
|
|
36
90
|
<% for (const model of models) { %>
|
|
91
|
+
<%
|
|
92
|
+
// Get all regular fields (non-relation) and virtual relation fields
|
|
93
|
+
const regularFields = model.fields.filter(field => !field.relationName || field.relationName.length === 0);
|
|
94
|
+
const virtualRelationFields = getVirtualRelationFields(model);
|
|
95
|
+
const allFields = [...regularFields, ...virtualRelationFields];
|
|
96
|
+
%>
|
|
37
97
|
@InputType()
|
|
38
98
|
export class Create<%= model.modelName %>Input {
|
|
39
|
-
<% for (const field of
|
|
40
|
-
<% if (field.kind === 'object') { continue; } %>
|
|
99
|
+
<% for (const field of allFields) { %>
|
|
41
100
|
<%
|
|
42
101
|
let baseGqlType;
|
|
43
102
|
let tsType;
|
|
@@ -66,11 +125,11 @@ export class Create<%= model.modelName %>Input {
|
|
|
66
125
|
fieldDecoratorTypeArg = `() => ${baseGqlType}`;
|
|
67
126
|
}
|
|
68
127
|
}
|
|
69
|
-
// Always optional for id, createdAt, updatedAt
|
|
70
|
-
if (alwaysOptionalFields.includes(field.name)) {
|
|
128
|
+
// Always optional for id, createdAt, updatedAt, and virtual fields
|
|
129
|
+
if (alwaysOptionalFields.includes(field.name) || field.isVirtual) {
|
|
71
130
|
isOptional = true;
|
|
72
131
|
} else {
|
|
73
|
-
isOptional =
|
|
132
|
+
isOptional = field.isOptional;
|
|
74
133
|
}
|
|
75
134
|
%>
|
|
76
135
|
@Field(<% if (fieldDecoratorTypeArg) { %><%- fieldDecoratorTypeArg %>, <% } %>{ nullable: <%= isOptional ? 'true' : 'false' %> })
|
|
@@ -80,8 +139,7 @@ export class Create<%= model.modelName %>Input {
|
|
|
80
139
|
|
|
81
140
|
@InputType()
|
|
82
141
|
export class Update<%= model.modelName %>Input {
|
|
83
|
-
<% for (const field of
|
|
84
|
-
<% if (field.kind === 'object') { continue; } %>
|
|
142
|
+
<% for (const field of allFields) { %>
|
|
85
143
|
<%
|
|
86
144
|
let baseGqlType;
|
|
87
145
|
let tsType;
|
|
@@ -117,8 +175,7 @@ export class Update<%= model.modelName %>Input {
|
|
|
117
175
|
|
|
118
176
|
@InputType()
|
|
119
177
|
export class List<%= model.modelName %>Input extends CorePagingInput {
|
|
120
|
-
<% for (const field of
|
|
121
|
-
<% if (field.kind === 'object') { continue; } %>
|
|
178
|
+
<% for (const field of allFields) { %>
|
|
122
179
|
<%
|
|
123
180
|
let baseGqlType;
|
|
124
181
|
let tsType;
|