@ghentcdh/crouton-api 0.0.1-alpha.37 → 0.0.1-alpha.39
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/index.cjs +1403 -888
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +131 -162
- package/dist/index.d.ts +131 -162
- package/dist/index.js +1410 -895
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,157 +52,6 @@ module.exports = __toCommonJS(index_exports);
|
|
|
52
52
|
var getImportMetaUrl = /* @__PURE__ */ __name(() => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href, "getImportMetaUrl");
|
|
53
53
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
54
54
|
|
|
55
|
-
// src/lib/crud/builder/column-predicates.ts
|
|
56
|
-
var isBoolean = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "boolean" || col.columnType === "boolean", "isBoolean");
|
|
57
|
-
var isRelation = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "relation", "isRelation");
|
|
58
|
-
var isAutocomplete = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "autocomplete", "isAutocomplete");
|
|
59
|
-
var isRecordCell = /* @__PURE__ */ __name((col) => isRelation(col) || isAutocomplete(col), "isRecordCell");
|
|
60
|
-
var isDateRange = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "date-range", "isDateRange");
|
|
61
|
-
|
|
62
|
-
// src/lib/crud/builder/column.utils.ts
|
|
63
|
-
var colPosition = /* @__PURE__ */ __name((col, i) => col.fieldInput?.position ?? i, "colPosition");
|
|
64
|
-
var sortByPosition = /* @__PURE__ */ __name((cols) => cols.map((col, i) => ({
|
|
65
|
-
col,
|
|
66
|
-
i
|
|
67
|
-
})).sort((a, b) => colPosition(a.col, a.i) - colPosition(b.col, b.i)).map(({ col }) => col), "sortByPosition");
|
|
68
|
-
var columnForContext = /* @__PURE__ */ __name((col, ctx) => {
|
|
69
|
-
if (ctx === "view") return {
|
|
70
|
-
...col,
|
|
71
|
-
fieldInput: col.fieldView ?? col.fieldInput
|
|
72
|
-
};
|
|
73
|
-
if (ctx === "table") return {
|
|
74
|
-
...col,
|
|
75
|
-
fieldInput: col.fieldTable ?? col.fieldInput
|
|
76
|
-
};
|
|
77
|
-
return col;
|
|
78
|
-
}, "columnForContext");
|
|
79
|
-
var toViewColumn = /* @__PURE__ */ __name((col) => ({
|
|
80
|
-
id: col.id,
|
|
81
|
-
...col.label && {
|
|
82
|
-
label: col.label
|
|
83
|
-
},
|
|
84
|
-
...col.sortable != null && {
|
|
85
|
-
sortable: col.sortable
|
|
86
|
-
},
|
|
87
|
-
...col.searchable != null && {
|
|
88
|
-
searchable: col.searchable
|
|
89
|
-
},
|
|
90
|
-
...col.fieldInput && {
|
|
91
|
-
fieldInput: col.fieldInput
|
|
92
|
-
}
|
|
93
|
-
}), "toViewColumn");
|
|
94
|
-
|
|
95
|
-
// src/lib/crud/builder/sort.helpers.ts
|
|
96
|
-
var deriveSortId = /* @__PURE__ */ __name((col) => {
|
|
97
|
-
if (col.sortable === false) return null;
|
|
98
|
-
if (col.sortId) return col.sortId;
|
|
99
|
-
const base = col.column ?? col.id;
|
|
100
|
-
const fi = col.fieldInput;
|
|
101
|
-
const opts = fi?.options ?? {};
|
|
102
|
-
const isRelation2 = fi?.format === "relation" || !!fi?.relationType || fi?.type === "autocomplete" || typeof opts.resource === "string";
|
|
103
|
-
if (isRelation2) {
|
|
104
|
-
const key = (typeof col.displayKey === "string" ? col.displayKey : void 0) ?? (typeof opts.displayKey === "string" ? opts.displayKey : void 0) ?? (typeof opts.labelKey === "string" ? opts.labelKey : void 0);
|
|
105
|
-
if (!key) return null;
|
|
106
|
-
const path2 = key.includes(".") ? key : `${base}.${key}`;
|
|
107
|
-
return path2.endsWith(".label") ? path2.slice(0, -".label".length) : path2;
|
|
108
|
-
}
|
|
109
|
-
if (!col.displayKey) return base;
|
|
110
|
-
const path = `${base}.${col.displayKey}`;
|
|
111
|
-
const isValueLabel = !!col.enum || opts.emitObject === true;
|
|
112
|
-
if (isValueLabel && path.endsWith(".label")) return path.slice(0, -".label".length);
|
|
113
|
-
return path;
|
|
114
|
-
}, "deriveSortId");
|
|
115
|
-
var resolveDefaultSort = /* @__PURE__ */ __name((tableCols, allColumns) => {
|
|
116
|
-
const isSortable = /* @__PURE__ */ __name((c) => c.sortable !== false, "isSortable");
|
|
117
|
-
const sortCol = tableCols.find((c) => c.defaultSort && isSortable(c)) ?? tableCols.find(isSortable) ?? allColumns?.find((c) => c.idField);
|
|
118
|
-
return sortCol ? deriveSortId(sortCol) ?? sortCol.id : void 0;
|
|
119
|
-
}, "resolveDefaultSort");
|
|
120
|
-
|
|
121
|
-
// src/lib/crud/builder/schema-transforms.ts
|
|
122
|
-
var allowAdditionalProperties = /* @__PURE__ */ __name((schema) => {
|
|
123
|
-
if (schema["type"] === "object") {
|
|
124
|
-
schema["additionalProperties"] = true;
|
|
125
|
-
const props = schema["properties"];
|
|
126
|
-
if (props) {
|
|
127
|
-
for (const value of Object.values(props)) {
|
|
128
|
-
allowAdditionalProperties(value);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (schema["type"] === "array" && schema["items"]) {
|
|
133
|
-
allowAdditionalProperties(schema["items"]);
|
|
134
|
-
}
|
|
135
|
-
}, "allowAdditionalProperties");
|
|
136
|
-
var isNullableProperty = /* @__PURE__ */ __name((prop) => {
|
|
137
|
-
const anyOf = prop?.["anyOf"];
|
|
138
|
-
return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
|
|
139
|
-
}, "isNullableProperty");
|
|
140
|
-
var dropNullableFromRequired = /* @__PURE__ */ __name((schema) => {
|
|
141
|
-
if (schema["type"] !== "object") return;
|
|
142
|
-
const props = schema["properties"];
|
|
143
|
-
if (!props) return;
|
|
144
|
-
const required = schema["required"];
|
|
145
|
-
if (Array.isArray(required)) {
|
|
146
|
-
schema["required"] = required.filter((key) => !isNullableProperty(props[key]));
|
|
147
|
-
}
|
|
148
|
-
for (const value of Object.values(props)) {
|
|
149
|
-
dropNullableFromRequired(value);
|
|
150
|
-
}
|
|
151
|
-
}, "dropNullableFromRequired");
|
|
152
|
-
var enforceRequiredMinLength = /* @__PURE__ */ __name((schema) => {
|
|
153
|
-
if (schema["type"] !== "object") return;
|
|
154
|
-
const props = schema["properties"];
|
|
155
|
-
if (!props) return;
|
|
156
|
-
for (const prop of Object.values(props)) {
|
|
157
|
-
if (prop?.["type"] === "string" && !("minLength" in prop)) {
|
|
158
|
-
prop["minLength"] = 1;
|
|
159
|
-
} else if (prop?.["type"] === "object") {
|
|
160
|
-
enforceRequiredMinLength(prop);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}, "enforceRequiredMinLength");
|
|
164
|
-
var applySchemaTransforms = /* @__PURE__ */ __name((schema) => {
|
|
165
|
-
allowAdditionalProperties(schema);
|
|
166
|
-
dropNullableFromRequired(schema);
|
|
167
|
-
enforceRequiredMinLength(schema);
|
|
168
|
-
}, "applySchemaTransforms");
|
|
169
|
-
|
|
170
|
-
// src/lib/crud/builder/schema.helpers.ts
|
|
171
|
-
var pickByColumns = /* @__PURE__ */ __name((schema, columns, filter) => {
|
|
172
|
-
if (!schema) return void 0;
|
|
173
|
-
if (!columns?.length) return schema;
|
|
174
|
-
const baseFilter = /* @__PURE__ */ __name((c) => !isRelation(c) && (filter ? filter(c) : true), "baseFilter");
|
|
175
|
-
const schemaKeys = new Set(Object.keys(schema.shape));
|
|
176
|
-
const filtered = columns.filter((c) => baseFilter(c) && schemaKeys.has(c.id));
|
|
177
|
-
if (!filtered.length) return void 0;
|
|
178
|
-
const mask = Object.fromEntries(filtered.map((c) => [
|
|
179
|
-
c.id,
|
|
180
|
-
true
|
|
181
|
-
]));
|
|
182
|
-
return schema.pick(mask);
|
|
183
|
-
}, "pickByColumns");
|
|
184
|
-
var opWithSchema = /* @__PURE__ */ __name((enabled, schema) => {
|
|
185
|
-
if (enabled === false) return void 0;
|
|
186
|
-
return schema ? {
|
|
187
|
-
schema
|
|
188
|
-
} : true;
|
|
189
|
-
}, "opWithSchema");
|
|
190
|
-
var upsertOp = /* @__PURE__ */ __name((entry, schema) => {
|
|
191
|
-
if (!entry) return void 0;
|
|
192
|
-
if (entry === true) {
|
|
193
|
-
throw new Error("`operations.upsert` must be an object with `upsertOn`, not `true`.");
|
|
194
|
-
}
|
|
195
|
-
if (typeof entry === "object") {
|
|
196
|
-
return {
|
|
197
|
-
upsertOn: entry.upsertOn,
|
|
198
|
-
...schema && {
|
|
199
|
-
schema
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
return void 0;
|
|
204
|
-
}, "upsertOp");
|
|
205
|
-
|
|
206
55
|
// ../crouton-core/src/lib/request.model.ts
|
|
207
56
|
var import_zod2 = require("zod");
|
|
208
57
|
|
|
@@ -334,10 +183,10 @@ var ElementBuilder = class extends Builder {
|
|
|
334
183
|
return this;
|
|
335
184
|
}
|
|
336
185
|
/** Merge a patch into the typed options bag. */
|
|
337
|
-
opt(
|
|
186
|
+
opt(patch) {
|
|
338
187
|
this.options = {
|
|
339
188
|
...this.options,
|
|
340
|
-
...
|
|
189
|
+
...patch
|
|
341
190
|
};
|
|
342
191
|
return this;
|
|
343
192
|
}
|
|
@@ -835,8 +684,18 @@ var FieldInputSchema = import_zod9.z.object({
|
|
|
835
684
|
relationType: RelationType.optional(),
|
|
836
685
|
/** FK field on the child model pointing back to the parent, e.g. `"workId"`. Defaults to `${parentModel}Id`. */
|
|
837
686
|
foreignKey: import_zod9.z.string().optional(),
|
|
687
|
+
/** Override the Prisma relation field name when it differs from the column id. */
|
|
688
|
+
relation: import_zod9.z.string().optional(),
|
|
838
689
|
/** Override the display order in form views. Lower values come first. */
|
|
839
690
|
position: import_zod9.z.number().optional(),
|
|
691
|
+
/**
|
|
692
|
+
* Value to pre-fill this field with on the create form. Injected into the
|
|
693
|
+
* generated form view's JSON Schema as `properties[id].default`, which
|
|
694
|
+
* `parseValue({})` (see `@ghentcdh/crouton-vue`'s `form-def.ts`) applies when
|
|
695
|
+
* opening a blank record. Not applicable to `format: "relation"` fields —
|
|
696
|
+
* relation columns are excluded from the picked data schema entirely.
|
|
697
|
+
*/
|
|
698
|
+
defaultValue: import_zod9.z.unknown().optional(),
|
|
840
699
|
options: import_zod9.z.union([
|
|
841
700
|
RelationFieldInputOptionsSchema,
|
|
842
701
|
import_zod9.z.unknown()
|
|
@@ -1284,7 +1143,122 @@ var CONFIG_FILES = [
|
|
|
1284
1143
|
"crouton.js"
|
|
1285
1144
|
];
|
|
1286
1145
|
|
|
1287
|
-
// src/lib/
|
|
1146
|
+
// ../crouton-core/src/lib/view/column-predicates.ts
|
|
1147
|
+
var isBoolean = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "boolean" || col.columnType === "boolean", "isBoolean");
|
|
1148
|
+
var isRelation = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "relation", "isRelation");
|
|
1149
|
+
var isAutocomplete = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "autocomplete", "isAutocomplete");
|
|
1150
|
+
var isRecordCell = /* @__PURE__ */ __name((col) => isRelation(col) || isAutocomplete(col), "isRecordCell");
|
|
1151
|
+
var isDateRange = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "date-range", "isDateRange");
|
|
1152
|
+
|
|
1153
|
+
// ../crouton-core/src/lib/view/column.utils.ts
|
|
1154
|
+
var colPosition = /* @__PURE__ */ __name((col, i) => col.fieldInput?.position ?? i, "colPosition");
|
|
1155
|
+
var sortByPosition = /* @__PURE__ */ __name((cols) => cols.map((col, i) => ({
|
|
1156
|
+
col,
|
|
1157
|
+
i
|
|
1158
|
+
})).sort((a, b) => colPosition(a.col, a.i) - colPosition(b.col, b.i)).map(({ col }) => col), "sortByPosition");
|
|
1159
|
+
var columnForContext = /* @__PURE__ */ __name((col, ctx) => {
|
|
1160
|
+
if (ctx === "view") return {
|
|
1161
|
+
...col,
|
|
1162
|
+
fieldInput: col.fieldView ?? col.fieldInput
|
|
1163
|
+
};
|
|
1164
|
+
if (ctx === "table") return {
|
|
1165
|
+
...col,
|
|
1166
|
+
fieldInput: col.fieldTable ?? col.fieldInput
|
|
1167
|
+
};
|
|
1168
|
+
return col;
|
|
1169
|
+
}, "columnForContext");
|
|
1170
|
+
var toViewColumn = /* @__PURE__ */ __name((col) => ({
|
|
1171
|
+
id: col.id,
|
|
1172
|
+
...col.label && {
|
|
1173
|
+
label: col.label
|
|
1174
|
+
},
|
|
1175
|
+
...col.sortable != null && {
|
|
1176
|
+
sortable: col.sortable
|
|
1177
|
+
},
|
|
1178
|
+
...col.searchable != null && {
|
|
1179
|
+
searchable: col.searchable
|
|
1180
|
+
},
|
|
1181
|
+
...col.fieldInput && {
|
|
1182
|
+
fieldInput: col.fieldInput
|
|
1183
|
+
}
|
|
1184
|
+
}), "toViewColumn");
|
|
1185
|
+
|
|
1186
|
+
// ../crouton-core/src/lib/view/sort.helpers.ts
|
|
1187
|
+
var deriveSortId = /* @__PURE__ */ __name((col) => {
|
|
1188
|
+
if (col.sortable === false) return null;
|
|
1189
|
+
if (col.sortId) return col.sortId;
|
|
1190
|
+
const base = col.column ?? col.id;
|
|
1191
|
+
const fi = col.fieldInput;
|
|
1192
|
+
const opts = fi?.options ?? {};
|
|
1193
|
+
const isRelation2 = fi?.format === "relation" || !!fi?.relationType || fi?.type === "autocomplete" || typeof opts.resource === "string";
|
|
1194
|
+
if (isRelation2) {
|
|
1195
|
+
const key = (typeof col.displayKey === "string" ? col.displayKey : void 0) ?? (typeof opts.displayKey === "string" ? opts.displayKey : void 0) ?? (typeof opts.labelKey === "string" ? opts.labelKey : void 0);
|
|
1196
|
+
if (!key) return null;
|
|
1197
|
+
const path2 = key.includes(".") ? key : `${base}.${key}`;
|
|
1198
|
+
return path2.endsWith(".label") ? path2.slice(0, -".label".length) : path2;
|
|
1199
|
+
}
|
|
1200
|
+
if (!col.displayKey) return base;
|
|
1201
|
+
const path = `${base}.${col.displayKey}`;
|
|
1202
|
+
const isValueLabel = !!col.enum || opts.emitObject === true;
|
|
1203
|
+
if (isValueLabel && path.endsWith(".label")) return path.slice(0, -".label".length);
|
|
1204
|
+
return path;
|
|
1205
|
+
}, "deriveSortId");
|
|
1206
|
+
var resolveDefaultSort = /* @__PURE__ */ __name((tableCols, allColumns) => {
|
|
1207
|
+
const isSortable = /* @__PURE__ */ __name((c) => c.sortable !== false, "isSortable");
|
|
1208
|
+
const sortCol = tableCols.find((c) => c.defaultSort && isSortable(c)) ?? tableCols.find(isSortable) ?? allColumns?.find((c) => c.idField);
|
|
1209
|
+
return sortCol ? deriveSortId(sortCol) ?? sortCol.id : void 0;
|
|
1210
|
+
}, "resolveDefaultSort");
|
|
1211
|
+
|
|
1212
|
+
// ../crouton-core/src/lib/view/schema-transforms.ts
|
|
1213
|
+
var allowAdditionalProperties = /* @__PURE__ */ __name((schema) => {
|
|
1214
|
+
if (schema["type"] === "object") {
|
|
1215
|
+
schema["additionalProperties"] = true;
|
|
1216
|
+
const props = schema["properties"];
|
|
1217
|
+
if (props) {
|
|
1218
|
+
for (const value of Object.values(props)) {
|
|
1219
|
+
allowAdditionalProperties(value);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
if (schema["type"] === "array" && schema["items"]) {
|
|
1224
|
+
allowAdditionalProperties(schema["items"]);
|
|
1225
|
+
}
|
|
1226
|
+
}, "allowAdditionalProperties");
|
|
1227
|
+
var isNullableProperty = /* @__PURE__ */ __name((prop) => {
|
|
1228
|
+
const anyOf = prop?.["anyOf"];
|
|
1229
|
+
return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
|
|
1230
|
+
}, "isNullableProperty");
|
|
1231
|
+
var dropNullableFromRequired = /* @__PURE__ */ __name((schema) => {
|
|
1232
|
+
if (schema["type"] !== "object") return;
|
|
1233
|
+
const props = schema["properties"];
|
|
1234
|
+
if (!props) return;
|
|
1235
|
+
const required = schema["required"];
|
|
1236
|
+
if (Array.isArray(required)) {
|
|
1237
|
+
schema["required"] = required.filter((key) => !isNullableProperty(props[key]));
|
|
1238
|
+
}
|
|
1239
|
+
for (const value of Object.values(props)) {
|
|
1240
|
+
dropNullableFromRequired(value);
|
|
1241
|
+
}
|
|
1242
|
+
}, "dropNullableFromRequired");
|
|
1243
|
+
var enforceRequiredMinLength = /* @__PURE__ */ __name((schema) => {
|
|
1244
|
+
if (schema["type"] !== "object") return;
|
|
1245
|
+
const props = schema["properties"];
|
|
1246
|
+
if (!props) return;
|
|
1247
|
+
for (const prop of Object.values(props)) {
|
|
1248
|
+
if (prop?.["type"] === "string" && !("minLength" in prop)) {
|
|
1249
|
+
prop["minLength"] = 1;
|
|
1250
|
+
} else if (prop?.["type"] === "object") {
|
|
1251
|
+
enforceRequiredMinLength(prop);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}, "enforceRequiredMinLength");
|
|
1255
|
+
var applySchemaTransforms = /* @__PURE__ */ __name((schema) => {
|
|
1256
|
+
allowAdditionalProperties(schema);
|
|
1257
|
+
dropNullableFromRequired(schema);
|
|
1258
|
+
enforceRequiredMinLength(schema);
|
|
1259
|
+
}, "applySchemaTransforms");
|
|
1260
|
+
|
|
1261
|
+
// ../crouton-core/src/lib/view/table-schema.builder.ts
|
|
1288
1262
|
var SHARED_CELL_OPTION_KEYS = [
|
|
1289
1263
|
"values",
|
|
1290
1264
|
"storeValue",
|
|
@@ -1353,7 +1327,7 @@ var buildTableUiSchema = /* @__PURE__ */ __name((cols) => {
|
|
|
1353
1327
|
return layout;
|
|
1354
1328
|
}, "buildTableUiSchema");
|
|
1355
1329
|
|
|
1356
|
-
// src/lib/
|
|
1330
|
+
// ../crouton-core/src/lib/view/form-schema.builder.ts
|
|
1357
1331
|
var buildConditionSchema = /* @__PURE__ */ __name((when) => {
|
|
1358
1332
|
if (when.notExists) return {
|
|
1359
1333
|
not: {
|
|
@@ -1447,7 +1421,7 @@ var buildFormUiSchema = /* @__PURE__ */ __name((cols) => {
|
|
|
1447
1421
|
return layout.build();
|
|
1448
1422
|
}, "buildFormUiSchema");
|
|
1449
1423
|
|
|
1450
|
-
// src/lib/
|
|
1424
|
+
// ../crouton-core/src/lib/view/calculated-columns.builder.ts
|
|
1451
1425
|
var isVisibleInMode = /* @__PURE__ */ __name((c, mode) => mode === "table" ? !c.hiddenInTable : !c.hiddenInView, "isVisibleInMode");
|
|
1452
1426
|
var buildCalculatedElement = /* @__PURE__ */ __name((c, mode) => mode === "table" ? {
|
|
1453
1427
|
type: c.type === "boolean" ? "BooleanCell" : "TextCell",
|
|
@@ -1505,111 +1479,45 @@ var injectCalculatedColumnsIntoView = /* @__PURE__ */ __name((viewConfig, calcul
|
|
|
1505
1479
|
const columns = [
|
|
1506
1480
|
...viewConfig.columns
|
|
1507
1481
|
];
|
|
1508
|
-
for (const c of visible) {
|
|
1509
|
-
const pos = calcPosition(c);
|
|
1510
|
-
const entry = {
|
|
1511
|
-
id: c.id,
|
|
1512
|
-
label: c.label
|
|
1513
|
-
};
|
|
1514
|
-
if (pos !== void 0) {
|
|
1515
|
-
columns.splice(pos, 0, entry);
|
|
1516
|
-
} else {
|
|
1517
|
-
columns.push(entry);
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
return {
|
|
1521
|
-
...viewConfig,
|
|
1522
|
-
json_schema: jsonSchema,
|
|
1523
|
-
ui_schema: uiSchema,
|
|
1524
|
-
columns
|
|
1525
|
-
};
|
|
1526
|
-
}, "injectCalculatedColumnsIntoView");
|
|
1527
|
-
var injectCalculatedColumns = /* @__PURE__ */ __name((tableView, calculated) => injectCalculatedColumnsIntoView(tableView, calculated, "table"), "injectCalculatedColumns");
|
|
1528
|
-
var injectCalculatedColumnsToView = /* @__PURE__ */ __name((viewConfig, calculated) => injectCalculatedColumnsIntoView(viewConfig, calculated, "view"), "injectCalculatedColumnsToView");
|
|
1529
|
-
|
|
1530
|
-
// src/lib/crud/builder/view.builder.ts
|
|
1531
|
-
var import_zod18 = require("zod");
|
|
1532
|
-
|
|
1533
|
-
// src/lib/crud/schema.utils.ts
|
|
1534
|
-
var import_zod17 = require("zod");
|
|
1535
|
-
var dateOverride = /* @__PURE__ */ __name(({ zodSchema, jsonSchema }) => {
|
|
1536
|
-
if (zodSchema instanceof import_zod17.z.ZodDate) {
|
|
1537
|
-
jsonSchema.type = "string";
|
|
1538
|
-
jsonSchema.format = "date-time";
|
|
1539
|
-
}
|
|
1540
|
-
}, "dateOverride");
|
|
1541
|
-
var jsonSchemaOpts = {
|
|
1542
|
-
unrepresentable: "any",
|
|
1543
|
-
override: dateOverride
|
|
1544
|
-
};
|
|
1545
|
-
function isZodSchema(schema) {
|
|
1546
|
-
return schema instanceof import_zod17.ZodObject;
|
|
1547
|
-
}
|
|
1548
|
-
__name(isZodSchema, "isZodSchema");
|
|
1549
|
-
var isNullableProperty2 = /* @__PURE__ */ __name((property) => {
|
|
1550
|
-
const anyOf = property?.["anyOf"];
|
|
1551
|
-
return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
|
|
1552
|
-
}, "isNullableProperty");
|
|
1553
|
-
var dropNullableFromRequired2 = /* @__PURE__ */ __name((jsonSchema) => {
|
|
1554
|
-
const { properties, required } = jsonSchema;
|
|
1555
|
-
if (!properties || !Array.isArray(required)) return;
|
|
1556
|
-
jsonSchema.required = required.filter((key) => !isNullableProperty2(properties[key]));
|
|
1557
|
-
}, "dropNullableFromRequired");
|
|
1558
|
-
function toJsonSchema(schema) {
|
|
1559
|
-
if (isZodSchema(schema)) {
|
|
1560
|
-
const jsonSchema = (0, import_zod17.toJSONSchema)(schema, {
|
|
1561
|
-
target: "openApi3",
|
|
1562
|
-
...jsonSchemaOpts
|
|
1563
|
-
});
|
|
1564
|
-
dropNullableFromRequired2(jsonSchema);
|
|
1565
|
-
return jsonSchema;
|
|
1566
|
-
}
|
|
1567
|
-
return schema;
|
|
1568
|
-
}
|
|
1569
|
-
__name(toJsonSchema, "toJsonSchema");
|
|
1570
|
-
var unwrap = /* @__PURE__ */ __name((schema) => {
|
|
1571
|
-
let s = schema;
|
|
1572
|
-
let t = s?._zod?.def?.type;
|
|
1573
|
-
while (t === "optional" || t === "nullable" || t === "default" || t === "readonly") {
|
|
1574
|
-
s = s._zod.def.innerType;
|
|
1575
|
-
t = s?._zod?.def?.type;
|
|
1576
|
-
}
|
|
1577
|
-
return s;
|
|
1578
|
-
}, "unwrap");
|
|
1579
|
-
var typeOf = /* @__PURE__ */ __name((schema) => schema?._zod?.def?.type, "typeOf");
|
|
1580
|
-
function toSelectFields(schema) {
|
|
1581
|
-
if (!isZodSchema(schema)) {
|
|
1582
|
-
return Object.keys(schema.properties).reduce((acc, key) => {
|
|
1583
|
-
acc[key] = true;
|
|
1584
|
-
return acc;
|
|
1585
|
-
}, {});
|
|
1586
|
-
}
|
|
1587
|
-
const result = {};
|
|
1588
|
-
for (const [key, value] of Object.entries(schema.shape)) {
|
|
1589
|
-
const inner = unwrap(value);
|
|
1590
|
-
const t = typeOf(inner);
|
|
1591
|
-
if (t === "object") {
|
|
1592
|
-
result[key] = {
|
|
1593
|
-
select: toSelectFields(inner)
|
|
1594
|
-
};
|
|
1595
|
-
continue;
|
|
1596
|
-
}
|
|
1597
|
-
if (t === "array") {
|
|
1598
|
-
const element = unwrap(inner._zod.def.element);
|
|
1599
|
-
if (typeOf(element) === "object") {
|
|
1600
|
-
result[key] = {
|
|
1601
|
-
select: toSelectFields(element)
|
|
1602
|
-
};
|
|
1603
|
-
continue;
|
|
1604
|
-
}
|
|
1482
|
+
for (const c of visible) {
|
|
1483
|
+
const pos = calcPosition(c);
|
|
1484
|
+
const entry = {
|
|
1485
|
+
id: c.id,
|
|
1486
|
+
label: c.label
|
|
1487
|
+
};
|
|
1488
|
+
if (pos !== void 0) {
|
|
1489
|
+
columns.splice(pos, 0, entry);
|
|
1490
|
+
} else {
|
|
1491
|
+
columns.push(entry);
|
|
1605
1492
|
}
|
|
1606
|
-
result[key] = true;
|
|
1607
1493
|
}
|
|
1608
|
-
return
|
|
1609
|
-
|
|
1610
|
-
|
|
1494
|
+
return {
|
|
1495
|
+
...viewConfig,
|
|
1496
|
+
json_schema: jsonSchema,
|
|
1497
|
+
ui_schema: uiSchema,
|
|
1498
|
+
columns
|
|
1499
|
+
};
|
|
1500
|
+
}, "injectCalculatedColumnsIntoView");
|
|
1501
|
+
var injectCalculatedColumns = /* @__PURE__ */ __name((tableView, calculated) => injectCalculatedColumnsIntoView(tableView, calculated, "table"), "injectCalculatedColumns");
|
|
1502
|
+
var injectCalculatedColumnsToView = /* @__PURE__ */ __name((viewConfig, calculated) => injectCalculatedColumnsIntoView(viewConfig, calculated, "view"), "injectCalculatedColumnsToView");
|
|
1503
|
+
|
|
1504
|
+
// ../crouton-core/src/lib/view/view.builder.ts
|
|
1505
|
+
var import_zod18 = require("zod");
|
|
1506
|
+
|
|
1507
|
+
// ../crouton-core/src/lib/view/json-schema.opts.ts
|
|
1508
|
+
var import_zod17 = require("zod");
|
|
1509
|
+
var dateOverride = /* @__PURE__ */ __name(({ zodSchema, jsonSchema }) => {
|
|
1510
|
+
if (zodSchema instanceof import_zod17.z.ZodDate) {
|
|
1511
|
+
jsonSchema.type = "string";
|
|
1512
|
+
jsonSchema.format = "date-time";
|
|
1513
|
+
}
|
|
1514
|
+
}, "dateOverride");
|
|
1515
|
+
var jsonSchemaOpts = {
|
|
1516
|
+
unrepresentable: "any",
|
|
1517
|
+
override: dateOverride
|
|
1518
|
+
};
|
|
1611
1519
|
|
|
1612
|
-
// src/lib/
|
|
1520
|
+
// ../crouton-core/src/lib/view/view.builder.ts
|
|
1613
1521
|
var patchFilterProperties = /* @__PURE__ */ __name((jsonSchema, columns) => {
|
|
1614
1522
|
if (!columns?.length) return;
|
|
1615
1523
|
const properties = jsonSchema.properties;
|
|
@@ -1650,6 +1558,15 @@ var patchFilterProperties = /* @__PURE__ */ __name((jsonSchema, columns) => {
|
|
|
1650
1558
|
}
|
|
1651
1559
|
}
|
|
1652
1560
|
}, "patchFilterProperties");
|
|
1561
|
+
var injectFieldDefaults = /* @__PURE__ */ __name((jsonSchema, columns) => {
|
|
1562
|
+
const properties = jsonSchema.properties;
|
|
1563
|
+
if (!properties) return;
|
|
1564
|
+
for (const col of columns) {
|
|
1565
|
+
if (col.fieldInput?.defaultValue === void 0) continue;
|
|
1566
|
+
const prop = properties[col.id];
|
|
1567
|
+
if (prop) prop.default = col.fieldInput.defaultValue;
|
|
1568
|
+
}
|
|
1569
|
+
}, "injectFieldDefaults");
|
|
1653
1570
|
var buildView = /* @__PURE__ */ __name((schema, columns, visible, buildUiSchema, sort = false, schemaVisible) => {
|
|
1654
1571
|
if (!schema || !columns?.length) return void 0;
|
|
1655
1572
|
const visibleCols = sort ? sortByPosition(columns.filter(visible)) : columns.filter(visible);
|
|
@@ -1668,6 +1585,7 @@ var buildView = /* @__PURE__ */ __name((schema, columns, visible, buildUiSchema,
|
|
|
1668
1585
|
...jsonSchemaOpts
|
|
1669
1586
|
});
|
|
1670
1587
|
applySchemaTransforms(jsonSchema);
|
|
1588
|
+
injectFieldDefaults(jsonSchema, visibleCols);
|
|
1671
1589
|
if (schemaVisible) {
|
|
1672
1590
|
const nonEditableIds = new Set(schemaCols.filter((c) => c.idField || c.createable === false && c.updateable === false).map((c) => c.id));
|
|
1673
1591
|
const required = jsonSchema["required"];
|
|
@@ -1715,7 +1633,7 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
1715
1633
|
const buildJsonSchema = /* @__PURE__ */ __name((cols) => {
|
|
1716
1634
|
const properties = {};
|
|
1717
1635
|
for (const c of cols) {
|
|
1718
|
-
if (c.column) {
|
|
1636
|
+
if (c.column && c.column !== c.id) {
|
|
1719
1637
|
if (!properties[c.column]) {
|
|
1720
1638
|
properties[c.column] = {
|
|
1721
1639
|
type: "object",
|
|
@@ -1745,7 +1663,10 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
1745
1663
|
...isObject ? {} : {
|
|
1746
1664
|
type: c.columnType ?? "string"
|
|
1747
1665
|
},
|
|
1748
|
-
title: c.label ?? c.id
|
|
1666
|
+
title: c.label ?? c.id,
|
|
1667
|
+
...c.fieldInput?.defaultValue !== void 0 ? {
|
|
1668
|
+
default: c.fieldInput.defaultValue
|
|
1669
|
+
} : {}
|
|
1749
1670
|
};
|
|
1750
1671
|
}
|
|
1751
1672
|
}
|
|
@@ -1768,7 +1689,7 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
1768
1689
|
elements: elements.map((el) => {
|
|
1769
1690
|
const id = el.scope?.replace("#/properties/", "");
|
|
1770
1691
|
const col = id ? colMap[id] : void 0;
|
|
1771
|
-
if (!col?.column) return el;
|
|
1692
|
+
if (!col?.column || col.column === col.id) return el;
|
|
1772
1693
|
const keyPath = (col.displayKey ?? col.id).split(".");
|
|
1773
1694
|
const propPath = keyPath.map((k) => `properties/${k}`).join("/");
|
|
1774
1695
|
return {
|
|
@@ -1804,26 +1725,42 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
1804
1725
|
return Object.keys(views).length ? views : void 0;
|
|
1805
1726
|
}, "buildViewsFromColumns");
|
|
1806
1727
|
|
|
1728
|
+
// ../crouton-core/src/lib/view/view.schema.ts
|
|
1729
|
+
var import_zod19 = require("zod");
|
|
1730
|
+
var ViewColumnConfigSchema = import_zod19.z.object({
|
|
1731
|
+
id: import_zod19.z.string(),
|
|
1732
|
+
label: import_zod19.z.string().optional(),
|
|
1733
|
+
sortable: import_zod19.z.boolean().optional(),
|
|
1734
|
+
searchable: import_zod19.z.boolean().optional(),
|
|
1735
|
+
fieldInput: FieldInputSchema.optional()
|
|
1736
|
+
});
|
|
1737
|
+
var ViewConfigSchema = import_zod19.z.object({
|
|
1738
|
+
json_schema: import_zod19.z.record(import_zod19.z.string(), import_zod19.z.unknown()),
|
|
1739
|
+
ui_schema: import_zod19.z.record(import_zod19.z.string(), import_zod19.z.unknown()),
|
|
1740
|
+
columns: import_zod19.z.array(ViewColumnConfigSchema),
|
|
1741
|
+
defaultSort: import_zod19.z.string().optional()
|
|
1742
|
+
});
|
|
1743
|
+
|
|
1807
1744
|
// src/lib/crouton-api.module.ts
|
|
1808
|
-
var
|
|
1745
|
+
var import_common19 = require("@nestjs/common");
|
|
1809
1746
|
var import_core = require("@nestjs/core");
|
|
1810
1747
|
|
|
1811
1748
|
// src/lib/crud/app-layout/app-layout.types.ts
|
|
1812
|
-
var
|
|
1813
|
-
var SidebarLeafSchema =
|
|
1814
|
-
kind:
|
|
1815
|
-
id:
|
|
1816
|
-
label:
|
|
1817
|
-
position:
|
|
1749
|
+
var import_zod20 = require("zod");
|
|
1750
|
+
var SidebarLeafSchema = import_zod20.z.object({
|
|
1751
|
+
kind: import_zod20.z.literal("item").default("item"),
|
|
1752
|
+
id: import_zod20.z.string(),
|
|
1753
|
+
label: import_zod20.z.string(),
|
|
1754
|
+
position: import_zod20.z.number().optional()
|
|
1818
1755
|
});
|
|
1819
|
-
var SidebarGroupSchema2 =
|
|
1820
|
-
kind:
|
|
1821
|
-
id:
|
|
1822
|
-
label:
|
|
1823
|
-
position:
|
|
1824
|
-
children:
|
|
1756
|
+
var SidebarGroupSchema2 = import_zod20.z.object({
|
|
1757
|
+
kind: import_zod20.z.literal("group").default("group"),
|
|
1758
|
+
id: import_zod20.z.string(),
|
|
1759
|
+
label: import_zod20.z.string(),
|
|
1760
|
+
position: import_zod20.z.number().optional(),
|
|
1761
|
+
children: import_zod20.z.array(SidebarLeafSchema).default([])
|
|
1825
1762
|
});
|
|
1826
|
-
var SidebarNodeSchema =
|
|
1763
|
+
var SidebarNodeSchema = import_zod20.z.discriminatedUnion("kind", [
|
|
1827
1764
|
SidebarLeafSchema,
|
|
1828
1765
|
SidebarGroupSchema2
|
|
1829
1766
|
]);
|
|
@@ -2089,51 +2026,51 @@ CroutonValidationExceptionFilter = _ts_decorate3([
|
|
|
2089
2026
|
], CroutonValidationExceptionFilter);
|
|
2090
2027
|
|
|
2091
2028
|
// src/lib/crud/crud-controller.factory.ts
|
|
2092
|
-
var
|
|
2093
|
-
var
|
|
2029
|
+
var import_common16 = require("@nestjs/common");
|
|
2030
|
+
var import_swagger11 = require("@nestjs/swagger");
|
|
2094
2031
|
|
|
2095
2032
|
// src/lib/crud/action/action.types.ts
|
|
2096
|
-
var
|
|
2097
|
-
var ActionMetadataSchema =
|
|
2033
|
+
var import_zod21 = require("zod");
|
|
2034
|
+
var ActionMetadataSchema = import_zod21.z.object({
|
|
2098
2035
|
/** URL segment used in the endpoint. */
|
|
2099
|
-
id:
|
|
2036
|
+
id: import_zod21.z.string(),
|
|
2100
2037
|
/** Human-readable label shown as a button. */
|
|
2101
|
-
label:
|
|
2038
|
+
label: import_zod21.z.string().optional(),
|
|
2102
2039
|
/** MDI icon name, e.g. `"mdi:open-in-new"`. */
|
|
2103
|
-
icon:
|
|
2040
|
+
icon: import_zod21.z.string().optional(),
|
|
2104
2041
|
/** Tooltip text. Falls back to `label` when omitted. */
|
|
2105
|
-
tooltip:
|
|
2042
|
+
tooltip: import_zod21.z.string().optional(),
|
|
2106
2043
|
/** Per-row condition — button is hidden when false. */
|
|
2107
|
-
condition:
|
|
2044
|
+
condition: import_zod21.z.custom().optional()
|
|
2108
2045
|
});
|
|
2109
2046
|
var ResourceLinkActionSchema = ActionMetadataSchema.extend({
|
|
2110
|
-
type:
|
|
2047
|
+
type: import_zod21.z.literal("link"),
|
|
2111
2048
|
/** URL to open. May contain `{id}` or `{env.VAR}` placeholders. */
|
|
2112
|
-
href:
|
|
2049
|
+
href: import_zod21.z.string()
|
|
2113
2050
|
});
|
|
2114
2051
|
var ResourceRowProcedureActionSchema = ActionMetadataSchema.extend({
|
|
2115
|
-
type:
|
|
2052
|
+
type: import_zod21.z.literal("procedure").optional(),
|
|
2116
2053
|
/** HTTP method for the endpoint. Defaults to `"post"`. */
|
|
2117
|
-
method:
|
|
2054
|
+
method: import_zod21.z.string().optional(),
|
|
2118
2055
|
/** Static data payload merged into the request body by the frontend. */
|
|
2119
|
-
data:
|
|
2056
|
+
data: import_zod21.z.record(import_zod21.z.string(), import_zod21.z.unknown()).optional(),
|
|
2120
2057
|
/** Procedure called with `(prisma, recordId)`. */
|
|
2121
|
-
procedure:
|
|
2058
|
+
procedure: import_zod21.z.custom((v) => typeof v === "function")
|
|
2122
2059
|
});
|
|
2123
2060
|
var ResourceTableProcedureActionSchema = ActionMetadataSchema.extend({
|
|
2124
|
-
type:
|
|
2061
|
+
type: import_zod21.z.literal("procedure").optional(),
|
|
2125
2062
|
/** HTTP method for the endpoint. Defaults to `"post"`. */
|
|
2126
|
-
method:
|
|
2063
|
+
method: import_zod21.z.string().optional(),
|
|
2127
2064
|
/** Static data payload merged into the request body by the frontend. */
|
|
2128
|
-
data:
|
|
2065
|
+
data: import_zod21.z.record(import_zod21.z.string(), import_zod21.z.unknown()).optional(),
|
|
2129
2066
|
/** Procedure called with `(prisma)` — no record id. */
|
|
2130
|
-
procedure:
|
|
2067
|
+
procedure: import_zod21.z.custom((v) => typeof v === "function")
|
|
2131
2068
|
});
|
|
2132
|
-
var ResourceRowActionSchema =
|
|
2069
|
+
var ResourceRowActionSchema = import_zod21.z.union([
|
|
2133
2070
|
ResourceRowProcedureActionSchema,
|
|
2134
2071
|
ResourceLinkActionSchema
|
|
2135
2072
|
]);
|
|
2136
|
-
var ResourceTableActionSchema =
|
|
2073
|
+
var ResourceTableActionSchema = import_zod21.z.union([
|
|
2137
2074
|
ResourceTableProcedureActionSchema,
|
|
2138
2075
|
ResourceLinkActionSchema
|
|
2139
2076
|
]);
|
|
@@ -2325,6 +2262,23 @@ var buildChildSortClause = /* @__PURE__ */ __name((sort, sortDir) => {
|
|
|
2325
2262
|
[part]: acc
|
|
2326
2263
|
}, {});
|
|
2327
2264
|
}, "buildChildSortClause");
|
|
2265
|
+
var buildFindOneIncludes = /* @__PURE__ */ __name((subResources, configInclude) => {
|
|
2266
|
+
const autoSubs = subResources.filter((s) => s.includeInFindOne);
|
|
2267
|
+
const flatIncludes = autoSubs.length ? Object.fromEntries(autoSubs.map((s) => s.findOneOrderBy ? [
|
|
2268
|
+
s.relation,
|
|
2269
|
+
{
|
|
2270
|
+
orderBy: s.findOneOrderBy
|
|
2271
|
+
}
|
|
2272
|
+
] : [
|
|
2273
|
+
s.relation,
|
|
2274
|
+
true
|
|
2275
|
+
])) : void 0;
|
|
2276
|
+
if (!flatIncludes && !configInclude) return void 0;
|
|
2277
|
+
return {
|
|
2278
|
+
...flatIncludes,
|
|
2279
|
+
...configInclude
|
|
2280
|
+
};
|
|
2281
|
+
}, "buildFindOneIncludes");
|
|
2328
2282
|
|
|
2329
2283
|
// src/lib/crud/read.repository.ts
|
|
2330
2284
|
var parseFilterString = /* @__PURE__ */ __name((raw) => {
|
|
@@ -2587,7 +2541,6 @@ var ReadRepository = class {
|
|
|
2587
2541
|
* @throws {NotFoundException} When no record exists for the given id.
|
|
2588
2542
|
*/
|
|
2589
2543
|
async findOne(id) {
|
|
2590
|
-
const formIncludes = (this.config.subResources ?? []).filter((s) => s.includeInFindOne).map((s) => s.relation);
|
|
2591
2544
|
const projection = this.projection("findOne");
|
|
2592
2545
|
const idField = this.config.idField ?? "id";
|
|
2593
2546
|
const query = {
|
|
@@ -2596,15 +2549,7 @@ var ReadRepository = class {
|
|
|
2596
2549
|
},
|
|
2597
2550
|
...projection
|
|
2598
2551
|
};
|
|
2599
|
-
const
|
|
2600
|
-
r,
|
|
2601
|
-
true
|
|
2602
|
-
])) : void 0;
|
|
2603
|
-
const configInclude = buildIncludeClause(this.config.include);
|
|
2604
|
-
const mergedInclude = flatIncludes || configInclude ? {
|
|
2605
|
-
...flatIncludes,
|
|
2606
|
-
...configInclude
|
|
2607
|
-
} : void 0;
|
|
2552
|
+
const mergedInclude = buildFindOneIncludes(this.config.subResources ?? [], buildIncludeClause(this.config.include));
|
|
2608
2553
|
if (mergedInclude) {
|
|
2609
2554
|
if (projection.select) {
|
|
2610
2555
|
query.select = {
|
|
@@ -2708,6 +2653,75 @@ var ReadRepository = class {
|
|
|
2708
2653
|
}
|
|
2709
2654
|
};
|
|
2710
2655
|
|
|
2656
|
+
// src/lib/crud/schema.utils.ts
|
|
2657
|
+
var import_zod22 = require("zod");
|
|
2658
|
+
function isZodSchema(schema) {
|
|
2659
|
+
return schema instanceof import_zod22.ZodObject;
|
|
2660
|
+
}
|
|
2661
|
+
__name(isZodSchema, "isZodSchema");
|
|
2662
|
+
var isNullableProperty2 = /* @__PURE__ */ __name((property) => {
|
|
2663
|
+
const anyOf = property?.["anyOf"];
|
|
2664
|
+
return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
|
|
2665
|
+
}, "isNullableProperty");
|
|
2666
|
+
var dropNullableFromRequired2 = /* @__PURE__ */ __name((jsonSchema) => {
|
|
2667
|
+
const { properties, required } = jsonSchema;
|
|
2668
|
+
if (!properties || !Array.isArray(required)) return;
|
|
2669
|
+
jsonSchema.required = required.filter((key) => !isNullableProperty2(properties[key]));
|
|
2670
|
+
}, "dropNullableFromRequired");
|
|
2671
|
+
function toJsonSchema(schema) {
|
|
2672
|
+
if (isZodSchema(schema)) {
|
|
2673
|
+
const jsonSchema = (0, import_zod22.toJSONSchema)(schema, {
|
|
2674
|
+
target: "openApi3",
|
|
2675
|
+
...jsonSchemaOpts
|
|
2676
|
+
});
|
|
2677
|
+
dropNullableFromRequired2(jsonSchema);
|
|
2678
|
+
return jsonSchema;
|
|
2679
|
+
}
|
|
2680
|
+
return schema;
|
|
2681
|
+
}
|
|
2682
|
+
__name(toJsonSchema, "toJsonSchema");
|
|
2683
|
+
var unwrap = /* @__PURE__ */ __name((schema) => {
|
|
2684
|
+
let s = schema;
|
|
2685
|
+
let t = s?._zod?.def?.type;
|
|
2686
|
+
while (t === "optional" || t === "nullable" || t === "default" || t === "readonly") {
|
|
2687
|
+
s = s._zod.def.innerType;
|
|
2688
|
+
t = s?._zod?.def?.type;
|
|
2689
|
+
}
|
|
2690
|
+
return s;
|
|
2691
|
+
}, "unwrap");
|
|
2692
|
+
var typeOf = /* @__PURE__ */ __name((schema) => schema?._zod?.def?.type, "typeOf");
|
|
2693
|
+
function toSelectFields(schema) {
|
|
2694
|
+
if (!isZodSchema(schema)) {
|
|
2695
|
+
return Object.keys(schema.properties).reduce((acc, key) => {
|
|
2696
|
+
acc[key] = true;
|
|
2697
|
+
return acc;
|
|
2698
|
+
}, {});
|
|
2699
|
+
}
|
|
2700
|
+
const result = {};
|
|
2701
|
+
for (const [key, value] of Object.entries(schema.shape)) {
|
|
2702
|
+
const inner = unwrap(value);
|
|
2703
|
+
const t = typeOf(inner);
|
|
2704
|
+
if (t === "object") {
|
|
2705
|
+
result[key] = {
|
|
2706
|
+
select: toSelectFields(inner)
|
|
2707
|
+
};
|
|
2708
|
+
continue;
|
|
2709
|
+
}
|
|
2710
|
+
if (t === "array") {
|
|
2711
|
+
const element = unwrap(inner._zod.def.element);
|
|
2712
|
+
if (typeOf(element) === "object") {
|
|
2713
|
+
result[key] = {
|
|
2714
|
+
select: toSelectFields(element)
|
|
2715
|
+
};
|
|
2716
|
+
continue;
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
result[key] = true;
|
|
2720
|
+
}
|
|
2721
|
+
return result;
|
|
2722
|
+
}
|
|
2723
|
+
__name(toSelectFields, "toSelectFields");
|
|
2724
|
+
|
|
2711
2725
|
// src/lib/crud/write.repository.ts
|
|
2712
2726
|
var import_common5 = require("@nestjs/common");
|
|
2713
2727
|
|
|
@@ -3202,9 +3216,125 @@ var registerTableActionRoutes = /* @__PURE__ */ __name((ctx) => {
|
|
|
3202
3216
|
}
|
|
3203
3217
|
}, "registerTableActionRoutes");
|
|
3204
3218
|
|
|
3205
|
-
// src/lib/crud/operations/register-
|
|
3219
|
+
// src/lib/crud/operations/register-create.ts
|
|
3206
3220
|
var import_common8 = require("@nestjs/common");
|
|
3207
3221
|
var import_swagger3 = require("@nestjs/swagger");
|
|
3222
|
+
var defaultCreate = /* @__PURE__ */ __name((ctx) => {
|
|
3223
|
+
if (!isOperationEnabled(ctx.definition, "create")) return null;
|
|
3224
|
+
const { cls, config, createSchema, bodyDecorator } = ctx;
|
|
3225
|
+
const methodName = "create";
|
|
3226
|
+
return {
|
|
3227
|
+
route: "",
|
|
3228
|
+
methodName,
|
|
3229
|
+
name: config.name,
|
|
3230
|
+
createFn: /* @__PURE__ */ __name(function(body) {
|
|
3231
|
+
return this.repo.create(body);
|
|
3232
|
+
}, "createFn"),
|
|
3233
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
3234
|
+
bodyDecorator(createSchema, {
|
|
3235
|
+
coerceNullableUndefinedToNull: true
|
|
3236
|
+
})(cls.prototype, methodName, 0);
|
|
3237
|
+
}, "decorators")
|
|
3238
|
+
};
|
|
3239
|
+
}, "defaultCreate");
|
|
3240
|
+
var childCreate = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
3241
|
+
if (!isOperationEnabled(sub.operations, "create")) return null;
|
|
3242
|
+
const { cls } = ctx;
|
|
3243
|
+
const methodName = `createChild_${sub.childRoute}`;
|
|
3244
|
+
const createFn = /* @__PURE__ */ __name(async function(id, body) {
|
|
3245
|
+
return this.repo.createChild(id, sub, body);
|
|
3246
|
+
}, "createFn");
|
|
3247
|
+
const decorators = /* @__PURE__ */ __name(() => {
|
|
3248
|
+
(0, import_common8.Param)("id")(cls.prototype, methodName, 0);
|
|
3249
|
+
(0, import_common8.Body)()(cls.prototype, methodName, 1);
|
|
3250
|
+
}, "decorators");
|
|
3251
|
+
return {
|
|
3252
|
+
route: `:id/${sub.childRoute}`,
|
|
3253
|
+
methodName,
|
|
3254
|
+
name: sub.childRoute,
|
|
3255
|
+
createFn,
|
|
3256
|
+
decorators
|
|
3257
|
+
};
|
|
3258
|
+
}, "childCreate");
|
|
3259
|
+
var registerCreate = /* @__PURE__ */ __name((ctx, sub) => {
|
|
3260
|
+
const operationFn = sub ? childCreate(sub) : defaultCreate;
|
|
3261
|
+
const properties = operationFn(ctx);
|
|
3262
|
+
if (!properties) return;
|
|
3263
|
+
const { methodName, route, name } = properties;
|
|
3264
|
+
const { cls } = ctx;
|
|
3265
|
+
def(cls, methodName, properties.createFn);
|
|
3266
|
+
const d = desc(cls, methodName);
|
|
3267
|
+
(0, import_common8.Post)(route)(cls.prototype, methodName, d);
|
|
3268
|
+
(0, import_swagger3.ApiOperation)({
|
|
3269
|
+
summary: `Create a ${name}`
|
|
3270
|
+
})(cls.prototype, methodName, d);
|
|
3271
|
+
(0, import_swagger3.ApiResponse)({
|
|
3272
|
+
status: 201,
|
|
3273
|
+
description: `${name} created`
|
|
3274
|
+
})(cls.prototype, methodName, d);
|
|
3275
|
+
properties.decorators();
|
|
3276
|
+
}, "registerCreate");
|
|
3277
|
+
|
|
3278
|
+
// src/lib/crud/operations/register-delete.ts
|
|
3279
|
+
var import_common9 = require("@nestjs/common");
|
|
3280
|
+
var import_swagger4 = require("@nestjs/swagger");
|
|
3281
|
+
var defaultDelete = /* @__PURE__ */ __name((ctx) => {
|
|
3282
|
+
if (!isOperationEnabled(ctx.definition, "delete")) return null;
|
|
3283
|
+
const { config } = ctx;
|
|
3284
|
+
const methodName = "delete";
|
|
3285
|
+
const { name } = config;
|
|
3286
|
+
return {
|
|
3287
|
+
route: ":id",
|
|
3288
|
+
methodName,
|
|
3289
|
+
name,
|
|
3290
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
3291
|
+
}, "decorators"),
|
|
3292
|
+
deleteFn: /* @__PURE__ */ __name(function(id) {
|
|
3293
|
+
return this.repo.delete(id);
|
|
3294
|
+
}, "deleteFn")
|
|
3295
|
+
};
|
|
3296
|
+
}, "defaultDelete");
|
|
3297
|
+
var deleteChild = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
3298
|
+
if (!isOperationEnabled(sub.operations, "delete")) return null;
|
|
3299
|
+
const { cls } = ctx;
|
|
3300
|
+
const methodName = `deleteChild_${sub.childRoute}`;
|
|
3301
|
+
const deleteFn = /* @__PURE__ */ __name(async function(childId, parentId) {
|
|
3302
|
+
return this.repo.deleteChild(sub, childId, parentId);
|
|
3303
|
+
}, "deleteFn");
|
|
3304
|
+
const decorators = /* @__PURE__ */ __name(() => {
|
|
3305
|
+
(0, import_common9.Param)("childId")(cls.prototype, methodName, 0);
|
|
3306
|
+
}, "decorators");
|
|
3307
|
+
return {
|
|
3308
|
+
route: `:id/${sub.childRoute}/:childId`,
|
|
3309
|
+
methodName,
|
|
3310
|
+
name: sub.childRoute,
|
|
3311
|
+
deleteFn,
|
|
3312
|
+
decorators
|
|
3313
|
+
};
|
|
3314
|
+
}, "deleteChild");
|
|
3315
|
+
var registerDelete = /* @__PURE__ */ __name((ctx, sub) => {
|
|
3316
|
+
const operationFn = sub ? deleteChild(sub) : defaultDelete;
|
|
3317
|
+
const { cls } = ctx;
|
|
3318
|
+
const properties = operationFn(ctx);
|
|
3319
|
+
if (!properties) return;
|
|
3320
|
+
const { methodName, route, name } = properties;
|
|
3321
|
+
def(cls, methodName, properties.deleteFn);
|
|
3322
|
+
const d = desc(cls, methodName);
|
|
3323
|
+
(0, import_common9.Delete)(route)(cls.prototype, methodName, d);
|
|
3324
|
+
(0, import_common9.Param)("id")(cls.prototype, methodName, 0);
|
|
3325
|
+
(0, import_swagger4.ApiOperation)({
|
|
3326
|
+
summary: `Delete ${name} record`
|
|
3327
|
+
})(cls.prototype, methodName, d);
|
|
3328
|
+
(0, import_swagger4.ApiParam)(ctx.idParamMeta)(cls.prototype, methodName, d);
|
|
3329
|
+
(0, import_swagger4.ApiResponse)({
|
|
3330
|
+
status: 200
|
|
3331
|
+
})(cls.prototype, methodName, d);
|
|
3332
|
+
properties.decorators();
|
|
3333
|
+
}, "registerDelete");
|
|
3334
|
+
|
|
3335
|
+
// src/lib/crud/operations/register-findall.ts
|
|
3336
|
+
var import_common10 = require("@nestjs/common");
|
|
3337
|
+
var import_swagger5 = require("@nestjs/swagger");
|
|
3208
3338
|
|
|
3209
3339
|
// src/lib/crud/request.dto.ts
|
|
3210
3340
|
var import_zod_nestjs = require("@anatine/zod-nestjs");
|
|
@@ -3285,8 +3415,8 @@ var ZodValidationPipe = class {
|
|
|
3285
3415
|
}
|
|
3286
3416
|
};
|
|
3287
3417
|
|
|
3288
|
-
// src/lib/crud/operations/register-
|
|
3289
|
-
var
|
|
3418
|
+
// src/lib/crud/operations/register-findall.ts
|
|
3419
|
+
var _findAll = /* @__PURE__ */ __name(async (repo, params, q, lookupLabel) => {
|
|
3290
3420
|
const effectiveParams = {
|
|
3291
3421
|
...params
|
|
3292
3422
|
};
|
|
@@ -3313,41 +3443,74 @@ var findAll = /* @__PURE__ */ __name(async (repo, params, q, lookupLabel) => {
|
|
|
3313
3443
|
filter: params.filter
|
|
3314
3444
|
}
|
|
3315
3445
|
};
|
|
3316
|
-
}, "
|
|
3317
|
-
var
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
}, "del");
|
|
3335
|
-
var registerFindAll = /* @__PURE__ */ __name((ctx) => {
|
|
3446
|
+
}, "_findAll");
|
|
3447
|
+
var findAllByParent = /* @__PURE__ */ __name(async (repo, id, childRoute, params) => {
|
|
3448
|
+
const { data, count } = await repo.findAllByParent(id, childRoute, params);
|
|
3449
|
+
const totalPages = Math.max(1, Math.ceil(count / params.pageSize));
|
|
3450
|
+
return {
|
|
3451
|
+
data,
|
|
3452
|
+
request: {
|
|
3453
|
+
count,
|
|
3454
|
+
page: params.page,
|
|
3455
|
+
pageSize: params.pageSize,
|
|
3456
|
+
totalPages,
|
|
3457
|
+
sort: params.sort,
|
|
3458
|
+
sortDir: params.sortDir,
|
|
3459
|
+
filter: params.filter
|
|
3460
|
+
}
|
|
3461
|
+
};
|
|
3462
|
+
}, "findAllByParent");
|
|
3463
|
+
var defaultFindAll = /* @__PURE__ */ __name((ctx) => {
|
|
3336
3464
|
if (!isOperationEnabled(ctx.definition, "findAll")) return;
|
|
3337
|
-
const {
|
|
3338
|
-
const { name } = config;
|
|
3465
|
+
const { config } = ctx;
|
|
3339
3466
|
const lookupLabel = config.lookup?.label;
|
|
3340
|
-
|
|
3341
|
-
return
|
|
3342
|
-
});
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3467
|
+
const findAll = /* @__PURE__ */ __name(async function(params, q) {
|
|
3468
|
+
return _findAll(this.repo, params, q, lookupLabel);
|
|
3469
|
+
}, "findAll");
|
|
3470
|
+
return {
|
|
3471
|
+
route: "",
|
|
3472
|
+
name: config.name,
|
|
3473
|
+
methodName: "findAll",
|
|
3474
|
+
findAll,
|
|
3475
|
+
listSchema: ctx.listSchema,
|
|
3476
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
3477
|
+
}, "decorators")
|
|
3478
|
+
};
|
|
3479
|
+
}, "defaultFindAll");
|
|
3480
|
+
var childFindAll = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
3481
|
+
if (!isOperationEnabled(sub.operations, "findAll")) return;
|
|
3482
|
+
const { cls } = ctx;
|
|
3483
|
+
const methodName = `findAllBy_${sub.childRoute}`;
|
|
3484
|
+
const findAll = /* @__PURE__ */ __name(async function(params, q, id) {
|
|
3485
|
+
return findAllByParent(this.repo, id, sub.childRoute, params);
|
|
3486
|
+
}, "findAll");
|
|
3487
|
+
const decorators = /* @__PURE__ */ __name(() => {
|
|
3488
|
+
(0, import_common10.Param)("id")(cls.prototype, methodName, 2);
|
|
3489
|
+
}, "decorators");
|
|
3490
|
+
return {
|
|
3491
|
+
name: sub.childRoute,
|
|
3492
|
+
methodName,
|
|
3493
|
+
findAll,
|
|
3494
|
+
route: `:id/${sub.childRoute}`,
|
|
3495
|
+
decorators,
|
|
3496
|
+
listSchema: ctx.listSchema
|
|
3497
|
+
};
|
|
3498
|
+
}, "childFindAll");
|
|
3499
|
+
var registerFindAll = /* @__PURE__ */ __name((ctx, sub) => {
|
|
3500
|
+
const operationFn = sub ? childFindAll(sub) : defaultFindAll;
|
|
3501
|
+
const properties = operationFn(ctx);
|
|
3502
|
+
if (!properties) return;
|
|
3503
|
+
const { methodName, route, name, listSchema } = properties;
|
|
3504
|
+
const { cls } = ctx;
|
|
3505
|
+
def(cls, methodName, properties.findAll);
|
|
3506
|
+
const d = desc(cls, methodName);
|
|
3507
|
+
(0, import_common10.Get)(route)(cls.prototype, methodName, d);
|
|
3508
|
+
(0, import_common10.Query)(new ZodValidationPipe(RequestDtoNoOffset.zodSchema))(cls.prototype, methodName, 0);
|
|
3509
|
+
(0, import_common10.Query)("q")(cls.prototype, methodName, 1);
|
|
3510
|
+
(0, import_swagger5.ApiOperation)({
|
|
3348
3511
|
summary: `List all ${name}s`
|
|
3349
|
-
})(cls.prototype,
|
|
3350
|
-
(0,
|
|
3512
|
+
})(cls.prototype, methodName, d);
|
|
3513
|
+
(0, import_swagger5.ApiResponse)({
|
|
3351
3514
|
status: 200,
|
|
3352
3515
|
description: `Array of ${name}`,
|
|
3353
3516
|
...listSchema && {
|
|
@@ -3356,179 +3519,161 @@ var registerFindAll = /* @__PURE__ */ __name((ctx) => {
|
|
|
3356
3519
|
items: toJsonSchema(listSchema)
|
|
3357
3520
|
}
|
|
3358
3521
|
}
|
|
3359
|
-
})(cls.prototype,
|
|
3522
|
+
})(cls.prototype, methodName, d);
|
|
3523
|
+
properties.decorators();
|
|
3360
3524
|
}, "registerFindAll");
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
}
|
|
3368
|
-
const
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3525
|
+
|
|
3526
|
+
// src/lib/crud/operations/register-findone.ts
|
|
3527
|
+
var import_common11 = require("@nestjs/common");
|
|
3528
|
+
var import_swagger6 = require("@nestjs/swagger");
|
|
3529
|
+
var defaultFindOne = /* @__PURE__ */ __name((ctx) => {
|
|
3530
|
+
if (!isOperationEnabled(ctx.definition, "findOne")) return null;
|
|
3531
|
+
const { cls, config } = ctx;
|
|
3532
|
+
const methodName = "findOne";
|
|
3533
|
+
return {
|
|
3534
|
+
route: ":id",
|
|
3535
|
+
methodName,
|
|
3536
|
+
name: config.name,
|
|
3537
|
+
findOneFn: /* @__PURE__ */ __name(function(id) {
|
|
3538
|
+
return this.repo.findOne(id);
|
|
3539
|
+
}, "findOneFn"),
|
|
3540
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
3541
|
+
(0, import_common11.Param)("id")(cls.prototype, methodName, 0);
|
|
3542
|
+
}, "decorators")
|
|
3543
|
+
};
|
|
3544
|
+
}, "defaultFindOne");
|
|
3545
|
+
var childFindOne = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
3546
|
+
if (!isOperationEnabled(sub.operations, "findOne")) return null;
|
|
3547
|
+
const { cls } = ctx;
|
|
3548
|
+
const methodName = `findOneChild_${sub.childRoute}`;
|
|
3549
|
+
const findOneFn = /* @__PURE__ */ __name(async function(parentId, childId) {
|
|
3550
|
+
return this.repo.findOneChild(sub, childId, parentId);
|
|
3551
|
+
}, "findOneFn");
|
|
3552
|
+
const decorators = /* @__PURE__ */ __name(() => {
|
|
3553
|
+
(0, import_common11.Param)("id")(cls.prototype, methodName, 0);
|
|
3554
|
+
(0, import_common11.Param)("childId")(cls.prototype, methodName, 1);
|
|
3555
|
+
}, "decorators");
|
|
3556
|
+
return {
|
|
3557
|
+
route: `:id/${sub.childRoute}/:childId`,
|
|
3558
|
+
methodName,
|
|
3559
|
+
name: sub.childRoute,
|
|
3560
|
+
findOneFn,
|
|
3561
|
+
decorators
|
|
3562
|
+
};
|
|
3563
|
+
}, "childFindOne");
|
|
3564
|
+
var registerFindOne = /* @__PURE__ */ __name((ctx, sub) => {
|
|
3565
|
+
const operationFn = sub ? childFindOne(sub) : defaultFindOne;
|
|
3566
|
+
const properties = operationFn(ctx);
|
|
3567
|
+
if (!properties) return;
|
|
3568
|
+
const { methodName, route, name } = properties;
|
|
3569
|
+
const { cls } = ctx;
|
|
3570
|
+
def(cls, methodName, properties.findOneFn);
|
|
3571
|
+
const d = desc(cls, methodName);
|
|
3572
|
+
(0, import_common11.Get)(route)(cls.prototype, methodName, d);
|
|
3573
|
+
(0, import_swagger6.ApiOperation)({
|
|
3372
3574
|
summary: `Get one ${name} by id`
|
|
3373
|
-
})(cls.prototype,
|
|
3374
|
-
(0,
|
|
3375
|
-
(0,
|
|
3376
|
-
status: 200,
|
|
3377
|
-
description: `The ${name}`,
|
|
3378
|
-
...oneSchema && {
|
|
3379
|
-
schema: toJsonSchema(oneSchema)
|
|
3380
|
-
}
|
|
3381
|
-
})(cls.prototype, "findOne", d);
|
|
3382
|
-
(0, import_swagger3.ApiNotFoundResponse)({
|
|
3383
|
-
description: "Not found"
|
|
3384
|
-
})(cls.prototype, "findOne", d);
|
|
3385
|
-
}, "registerFindOne");
|
|
3386
|
-
var registerCreate = /* @__PURE__ */ __name((ctx) => {
|
|
3387
|
-
if (!isOperationEnabled(ctx.definition, "create")) return;
|
|
3388
|
-
const { cls, config, createSchema, bodyDecorator } = ctx;
|
|
3389
|
-
const { name } = config;
|
|
3390
|
-
def(cls, "create", function(body) {
|
|
3391
|
-
return create(this.repo, body);
|
|
3392
|
-
});
|
|
3393
|
-
const d = desc(cls, "create");
|
|
3394
|
-
(0, import_common8.Post)()(cls.prototype, "create", d);
|
|
3395
|
-
bodyDecorator(createSchema, {
|
|
3396
|
-
coerceNullableUndefinedToNull: true
|
|
3397
|
-
})(cls.prototype, "create", 0);
|
|
3398
|
-
(0, import_swagger3.ApiOperation)({
|
|
3399
|
-
summary: `Create a ${name}`
|
|
3400
|
-
})(cls.prototype, "create", d);
|
|
3401
|
-
if (createSchema) (0, import_swagger3.ApiBody)({
|
|
3402
|
-
schema: toJsonSchema(createSchema)
|
|
3403
|
-
})(cls.prototype, "create", d);
|
|
3404
|
-
(0, import_swagger3.ApiResponse)({
|
|
3405
|
-
status: 201,
|
|
3406
|
-
description: `${name} created`
|
|
3407
|
-
})(cls.prototype, "create", d);
|
|
3408
|
-
}, "registerCreate");
|
|
3409
|
-
var registerUpdate = /* @__PURE__ */ __name((ctx) => {
|
|
3410
|
-
if (!isOperationEnabled(ctx.definition, "update")) return;
|
|
3411
|
-
const { cls, config, updateSchema, idParamMeta, bodyDecorator } = ctx;
|
|
3412
|
-
const { name } = config;
|
|
3413
|
-
def(cls, "update", function(id, body) {
|
|
3414
|
-
return update(this.repo, id, body);
|
|
3415
|
-
});
|
|
3416
|
-
const d = desc(cls, "update");
|
|
3417
|
-
(0, import_common8.Put)(":id")(cls.prototype, "update", d);
|
|
3418
|
-
(0, import_common8.Param)("id")(cls.prototype, "update", 0);
|
|
3419
|
-
bodyDecorator(updateSchema)(cls.prototype, "update", 1);
|
|
3420
|
-
(0, import_swagger3.ApiOperation)({
|
|
3421
|
-
summary: `Replace a ${name}`
|
|
3422
|
-
})(cls.prototype, "update", d);
|
|
3423
|
-
(0, import_swagger3.ApiParam)(idParamMeta)(cls.prototype, "update", d);
|
|
3424
|
-
if (updateSchema) (0, import_swagger3.ApiBody)({
|
|
3425
|
-
schema: toJsonSchema(updateSchema)
|
|
3426
|
-
})(cls.prototype, "update", d);
|
|
3427
|
-
(0, import_swagger3.ApiResponse)({
|
|
3575
|
+
})(cls.prototype, methodName, d);
|
|
3576
|
+
(0, import_swagger6.ApiParam)(ctx.idParamMeta)(cls.prototype, methodName, d);
|
|
3577
|
+
(0, import_swagger6.ApiResponse)({
|
|
3428
3578
|
status: 200,
|
|
3429
|
-
description:
|
|
3430
|
-
|
|
3431
|
-
|
|
3579
|
+
description: `The ${name}`,
|
|
3580
|
+
...ctx.oneSchema && {
|
|
3581
|
+
schema: toJsonSchema(ctx.oneSchema)
|
|
3582
|
+
}
|
|
3583
|
+
})(cls.prototype, methodName, d);
|
|
3584
|
+
(0, import_swagger6.ApiNotFoundResponse)({
|
|
3432
3585
|
description: "Not found"
|
|
3433
|
-
})(cls.prototype,
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
const
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3586
|
+
})(cls.prototype, methodName, d);
|
|
3587
|
+
properties.decorators();
|
|
3588
|
+
}, "registerFindOne");
|
|
3589
|
+
|
|
3590
|
+
// src/lib/crud/operations/register-patch.ts
|
|
3591
|
+
var import_common12 = require("@nestjs/common");
|
|
3592
|
+
var import_swagger7 = require("@nestjs/swagger");
|
|
3593
|
+
var defaultPatch = /* @__PURE__ */ __name((ctx) => {
|
|
3594
|
+
if (!isOperationEnabled(ctx.definition, "patch")) return null;
|
|
3595
|
+
const { cls, config, patchSchema, bodyDecorator } = ctx;
|
|
3596
|
+
const methodName = "patch";
|
|
3597
|
+
return {
|
|
3598
|
+
route: ":id",
|
|
3599
|
+
methodName,
|
|
3600
|
+
name: config.name,
|
|
3601
|
+
patchFn: /* @__PURE__ */ __name(function(id, body) {
|
|
3602
|
+
return this.repo.patch(id, body);
|
|
3603
|
+
}, "patchFn"),
|
|
3604
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
3605
|
+
(0, import_common12.Param)("id")(cls.prototype, methodName, 0);
|
|
3606
|
+
bodyDecorator(patchSchema)(cls.prototype, methodName, 1);
|
|
3607
|
+
}, "decorators")
|
|
3608
|
+
};
|
|
3609
|
+
}, "defaultPatch");
|
|
3610
|
+
var childPatch = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
3611
|
+
if (!isOperationEnabled(sub.operations, "patch")) return null;
|
|
3612
|
+
const { cls } = ctx;
|
|
3613
|
+
const methodName = `patchChild_${sub.childRoute}`;
|
|
3614
|
+
const patchFn = /* @__PURE__ */ __name(async function(_id, childId, body) {
|
|
3615
|
+
return this.repo.updateChild(sub, childId, body);
|
|
3616
|
+
}, "patchFn");
|
|
3617
|
+
const decorators = /* @__PURE__ */ __name(() => {
|
|
3618
|
+
(0, import_common12.Param)("id")(cls.prototype, methodName, 0);
|
|
3619
|
+
(0, import_common12.Param)("childId")(cls.prototype, methodName, 1);
|
|
3620
|
+
(0, import_common12.Body)()(cls.prototype, methodName, 2);
|
|
3621
|
+
}, "decorators");
|
|
3622
|
+
return {
|
|
3623
|
+
route: `:id/${sub.childRoute}/:childId`,
|
|
3624
|
+
methodName,
|
|
3625
|
+
name: sub.childRoute,
|
|
3626
|
+
patchFn,
|
|
3627
|
+
decorators
|
|
3628
|
+
};
|
|
3629
|
+
}, "childPatch");
|
|
3630
|
+
var registerPatch = /* @__PURE__ */ __name((ctx, sub) => {
|
|
3631
|
+
const operationFn = sub ? childPatch(sub) : defaultPatch;
|
|
3632
|
+
const properties = operationFn(ctx);
|
|
3633
|
+
if (!properties) return;
|
|
3634
|
+
const { methodName, route, name } = properties;
|
|
3635
|
+
const { cls } = ctx;
|
|
3636
|
+
def(cls, methodName, properties.patchFn);
|
|
3637
|
+
const d = desc(cls, methodName);
|
|
3638
|
+
(0, import_common12.Patch)(route)(cls.prototype, methodName, d);
|
|
3639
|
+
(0, import_swagger7.ApiOperation)({
|
|
3447
3640
|
summary: `Update a ${name}`
|
|
3448
|
-
})(cls.prototype,
|
|
3449
|
-
(0,
|
|
3450
|
-
if (patchSchema) (0, import_swagger3.ApiBody)({
|
|
3451
|
-
schema: toJsonSchema(patchSchema)
|
|
3452
|
-
})(cls.prototype, "patch", d);
|
|
3453
|
-
(0, import_swagger3.ApiResponse)({
|
|
3641
|
+
})(cls.prototype, methodName, d);
|
|
3642
|
+
(0, import_swagger7.ApiResponse)({
|
|
3454
3643
|
status: 200,
|
|
3455
3644
|
description: `${name} updated`
|
|
3456
|
-
})(cls.prototype,
|
|
3457
|
-
(0,
|
|
3645
|
+
})(cls.prototype, methodName, d);
|
|
3646
|
+
(0, import_swagger7.ApiNotFoundResponse)({
|
|
3458
3647
|
description: "Not found"
|
|
3459
|
-
})(cls.prototype,
|
|
3648
|
+
})(cls.prototype, methodName, d);
|
|
3649
|
+
properties.decorators();
|
|
3460
3650
|
}, "registerPatch");
|
|
3461
|
-
var registerUpsert = /* @__PURE__ */ __name((ctx) => {
|
|
3462
|
-
if (!isOperationEnabled(ctx.definition, "upsert")) return;
|
|
3463
|
-
const { cls, config, upsertSchema, bodyDecorator } = ctx;
|
|
3464
|
-
const { name } = config;
|
|
3465
|
-
def(cls, "upsert", function(body) {
|
|
3466
|
-
return upsert(this.repo, body);
|
|
3467
|
-
});
|
|
3468
|
-
const d = desc(cls, "upsert");
|
|
3469
|
-
(0, import_common8.Put)()(cls.prototype, "upsert", d);
|
|
3470
|
-
bodyDecorator(upsertSchema, {
|
|
3471
|
-
coerceNullableUndefinedToNull: true
|
|
3472
|
-
})(cls.prototype, "upsert", 0);
|
|
3473
|
-
(0, import_swagger3.ApiOperation)({
|
|
3474
|
-
summary: `Upsert a ${name}`
|
|
3475
|
-
})(cls.prototype, "upsert", d);
|
|
3476
|
-
if (upsertSchema) (0, import_swagger3.ApiBody)({
|
|
3477
|
-
schema: toJsonSchema(upsertSchema)
|
|
3478
|
-
})(cls.prototype, "upsert", d);
|
|
3479
|
-
(0, import_swagger3.ApiResponse)({
|
|
3480
|
-
status: 200,
|
|
3481
|
-
description: `${name} upserted`
|
|
3482
|
-
})(cls.prototype, "upsert", d);
|
|
3483
|
-
}, "registerUpsert");
|
|
3484
|
-
var registerDelete = /* @__PURE__ */ __name((ctx) => {
|
|
3485
|
-
if (!isOperationEnabled(ctx.definition, "delete")) return;
|
|
3486
|
-
const { cls, config, idParamMeta } = ctx;
|
|
3487
|
-
const { name } = config;
|
|
3488
|
-
def(cls, "delete", function(id) {
|
|
3489
|
-
return del(this.repo, id);
|
|
3490
|
-
});
|
|
3491
|
-
const d = desc(cls, "delete");
|
|
3492
|
-
(0, import_common8.Delete)(":id")(cls.prototype, "delete", d);
|
|
3493
|
-
(0, import_common8.Param)("id")(cls.prototype, "delete", 0);
|
|
3494
|
-
(0, import_swagger3.ApiOperation)({
|
|
3495
|
-
summary: `Delete a ${name}`
|
|
3496
|
-
})(cls.prototype, "delete", d);
|
|
3497
|
-
(0, import_swagger3.ApiParam)(idParamMeta)(cls.prototype, "delete", d);
|
|
3498
|
-
(0, import_swagger3.ApiResponse)({
|
|
3499
|
-
status: 200,
|
|
3500
|
-
description: `${name} deleted`
|
|
3501
|
-
})(cls.prototype, "delete", d);
|
|
3502
|
-
(0, import_swagger3.ApiNotFoundResponse)({
|
|
3503
|
-
description: "Not found"
|
|
3504
|
-
})(cls.prototype, "delete", d);
|
|
3505
|
-
}, "registerDelete");
|
|
3506
3651
|
|
|
3507
3652
|
// src/lib/crud/operations/register-schema-endpoints.ts
|
|
3508
|
-
var
|
|
3509
|
-
var
|
|
3653
|
+
var import_common13 = require("@nestjs/common");
|
|
3654
|
+
var import_swagger8 = require("@nestjs/swagger");
|
|
3510
3655
|
|
|
3511
3656
|
// src/lib/crud/resource/PatchResourceJson.schema.ts
|
|
3512
|
-
var
|
|
3513
|
-
var FieldVariantPatchSchema =
|
|
3514
|
-
type:
|
|
3515
|
-
format:
|
|
3516
|
-
resource:
|
|
3517
|
-
position:
|
|
3518
|
-
options:
|
|
3657
|
+
var import_zod23 = require("zod");
|
|
3658
|
+
var FieldVariantPatchSchema = import_zod23.z.object({
|
|
3659
|
+
type: import_zod23.z.string().nullable().optional(),
|
|
3660
|
+
format: import_zod23.z.string().nullable().optional(),
|
|
3661
|
+
resource: import_zod23.z.string().nullable().optional(),
|
|
3662
|
+
position: import_zod23.z.number().nullable().optional(),
|
|
3663
|
+
options: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.unknown().nullable()).optional()
|
|
3519
3664
|
}).partial();
|
|
3520
|
-
var PatchColumnSchema =
|
|
3521
|
-
label:
|
|
3522
|
-
column:
|
|
3523
|
-
hiddenInTable:
|
|
3524
|
-
hiddenInForm:
|
|
3525
|
-
hiddenInView:
|
|
3665
|
+
var PatchColumnSchema = import_zod23.z.object({
|
|
3666
|
+
label: import_zod23.z.string().optional(),
|
|
3667
|
+
column: import_zod23.z.string().optional(),
|
|
3668
|
+
hiddenInTable: import_zod23.z.boolean().optional(),
|
|
3669
|
+
hiddenInForm: import_zod23.z.boolean().optional(),
|
|
3670
|
+
hiddenInView: import_zod23.z.boolean().optional(),
|
|
3526
3671
|
fieldInput: FieldVariantPatchSchema.optional(),
|
|
3527
3672
|
fieldView: FieldVariantPatchSchema.optional(),
|
|
3528
3673
|
fieldTable: FieldVariantPatchSchema.optional()
|
|
3529
3674
|
}).partial();
|
|
3530
|
-
var PatchResourceJsonSchema =
|
|
3531
|
-
columns:
|
|
3675
|
+
var PatchResourceJsonSchema = import_zod23.z.object({
|
|
3676
|
+
columns: import_zod23.z.record(import_zod23.z.string(), PatchColumnSchema)
|
|
3532
3677
|
});
|
|
3533
3678
|
|
|
3534
3679
|
// src/lib/crud/resource/WriteResourceJson.ts
|
|
@@ -3542,8 +3687,8 @@ var FIELD_VARIANT_KEYS = [
|
|
|
3542
3687
|
"fieldView",
|
|
3543
3688
|
"fieldTable"
|
|
3544
3689
|
];
|
|
3545
|
-
var mergeColumn = /* @__PURE__ */ __name((existing,
|
|
3546
|
-
const { fieldInput, fieldView, fieldTable, ...rest } =
|
|
3690
|
+
var mergeColumn = /* @__PURE__ */ __name((existing, patch) => {
|
|
3691
|
+
const { fieldInput, fieldView, fieldTable, ...rest } = patch;
|
|
3547
3692
|
const variantPatches = {
|
|
3548
3693
|
fieldInput,
|
|
3549
3694
|
fieldView,
|
|
@@ -3560,11 +3705,11 @@ var mergeColumn = /* @__PURE__ */ __name((existing, patch2) => {
|
|
|
3560
3705
|
}
|
|
3561
3706
|
return merged;
|
|
3562
3707
|
}, "mergeColumn");
|
|
3563
|
-
var applyColumnPatch = /* @__PURE__ */ __name((raw,
|
|
3708
|
+
var applyColumnPatch = /* @__PURE__ */ __name((raw, patch) => {
|
|
3564
3709
|
const columns = raw["columns"];
|
|
3565
3710
|
if (Array.isArray(columns)) {
|
|
3566
3711
|
const updated = columns.map((col) => {
|
|
3567
|
-
const columnPatch =
|
|
3712
|
+
const columnPatch = patch.columns[col["id"]];
|
|
3568
3713
|
return columnPatch ? mergeColumn(col, columnPatch) : col;
|
|
3569
3714
|
});
|
|
3570
3715
|
return {
|
|
@@ -3576,7 +3721,7 @@ var applyColumnPatch = /* @__PURE__ */ __name((raw, patch2) => {
|
|
|
3576
3721
|
const updated = {
|
|
3577
3722
|
...columns
|
|
3578
3723
|
};
|
|
3579
|
-
for (const [id, columnPatch] of Object.entries(
|
|
3724
|
+
for (const [id, columnPatch] of Object.entries(patch.columns)) {
|
|
3580
3725
|
if (!(id in updated)) continue;
|
|
3581
3726
|
updated[id] = mergeColumn(updated[id], columnPatch);
|
|
3582
3727
|
}
|
|
@@ -3795,6 +3940,35 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
|
|
|
3795
3940
|
tableActions: resolveActions(baseAction, config.tableActions)
|
|
3796
3941
|
};
|
|
3797
3942
|
}, "buildViewsPayload");
|
|
3943
|
+
var buildSubResourceViewsPayload = /* @__PURE__ */ __name((config, sub, baseUrl) => {
|
|
3944
|
+
if (!sub.views) return void 0;
|
|
3945
|
+
const { route } = config;
|
|
3946
|
+
const childUri = `${baseUrl}/${route}/{parent.id}/${sub.childRoute}`;
|
|
3947
|
+
return {
|
|
3948
|
+
id: `${route}/${sub.childRoute}`,
|
|
3949
|
+
name: sub.name ?? sub.childRoute,
|
|
3950
|
+
route: sub.childRoute,
|
|
3951
|
+
uri: childUri,
|
|
3952
|
+
title: sub.title ?? sub.childRoute,
|
|
3953
|
+
idField: sub.idField ?? "id",
|
|
3954
|
+
idType: sub.idType ?? "string",
|
|
3955
|
+
...sub.modalSize && {
|
|
3956
|
+
modalSize: sub.modalSize
|
|
3957
|
+
},
|
|
3958
|
+
operations: buildSubResourceOperations(sub.operations, childUri, sub.idField ?? "id"),
|
|
3959
|
+
schemas: Object.fromEntries(Object.entries(sub.views).map(([key, v]) => [
|
|
3960
|
+
key,
|
|
3961
|
+
{
|
|
3962
|
+
data: v.json_schema,
|
|
3963
|
+
ui: v.ui_schema,
|
|
3964
|
+
...v.defaultSort !== void 0 && {
|
|
3965
|
+
defaultSort: v.defaultSort
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
])),
|
|
3969
|
+
actions: resolveActions(`${baseUrl}/${sub.childRoute}`, sub.actions)
|
|
3970
|
+
};
|
|
3971
|
+
}, "buildSubResourceViewsPayload");
|
|
3798
3972
|
var buildEditableColumnsPayload = /* @__PURE__ */ __name((config) => {
|
|
3799
3973
|
const columns = config.columns ?? [];
|
|
3800
3974
|
return {
|
|
@@ -3834,36 +4008,15 @@ var registerDefinitionEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
3834
4008
|
return definitionPayload;
|
|
3835
4009
|
});
|
|
3836
4010
|
const d = desc(cls, "getDefinition");
|
|
3837
|
-
(0,
|
|
3838
|
-
(0,
|
|
4011
|
+
(0, import_common13.Get)("definition")(cls.prototype, "getDefinition", d);
|
|
4012
|
+
(0, import_swagger8.ApiOperation)({
|
|
3839
4013
|
summary: `Get the resource definition for ${name}`
|
|
3840
4014
|
})(cls.prototype, "getDefinition", d);
|
|
3841
|
-
(0,
|
|
4015
|
+
(0, import_swagger8.ApiResponse)({
|
|
3842
4016
|
status: 200,
|
|
3843
4017
|
description: `Definition (operations + schemas) for ${name}`
|
|
3844
4018
|
})(cls.prototype, "getDefinition", d);
|
|
3845
4019
|
}, "registerDefinitionEndpoint");
|
|
3846
|
-
var registerSchemasEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
3847
|
-
const { cls, config, baseUrl } = ctx;
|
|
3848
|
-
const { route, name } = config;
|
|
3849
|
-
const viewsPayload = buildViewsPayload(config, baseUrl);
|
|
3850
|
-
def(cls, "getSchemas", async function() {
|
|
3851
|
-
if (IS_DEV) {
|
|
3852
|
-
const fresh = await this.configRegistry.getByRoute(route);
|
|
3853
|
-
if (fresh) return buildViewsPayload(fresh, baseUrl) ?? viewsPayload;
|
|
3854
|
-
}
|
|
3855
|
-
return viewsPayload;
|
|
3856
|
-
});
|
|
3857
|
-
const d = desc(cls, "getSchemas");
|
|
3858
|
-
(0, import_common9.Get)("schemas")(cls.prototype, "getSchemas", d);
|
|
3859
|
-
(0, import_swagger4.ApiOperation)({
|
|
3860
|
-
summary: `Get view schemas (table/form) for ${name}`
|
|
3861
|
-
})(cls.prototype, "getSchemas", d);
|
|
3862
|
-
(0, import_swagger4.ApiResponse)({
|
|
3863
|
-
status: 200,
|
|
3864
|
-
description: `View schemas for ${name}`
|
|
3865
|
-
})(cls.prototype, "getSchemas", d);
|
|
3866
|
-
}, "registerSchemasEndpoint");
|
|
3867
4020
|
var registerResourceJsonEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
3868
4021
|
const { cls, config, baseUrl } = ctx;
|
|
3869
4022
|
const { route, name } = config;
|
|
@@ -3876,11 +4029,11 @@ var registerResourceJsonEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
3876
4029
|
return resourceJsonPayload;
|
|
3877
4030
|
});
|
|
3878
4031
|
const d = desc(cls, "getResourceJson");
|
|
3879
|
-
(0,
|
|
3880
|
-
(0,
|
|
4032
|
+
(0, import_common13.Get)("resource.json")(cls.prototype, "getResourceJson", d);
|
|
4033
|
+
(0, import_swagger8.ApiOperation)({
|
|
3881
4034
|
summary: `Get resource descriptor for ${name}`
|
|
3882
4035
|
})(cls.prototype, "getResourceJson", d);
|
|
3883
|
-
(0,
|
|
4036
|
+
(0, import_swagger8.ApiResponse)({
|
|
3884
4037
|
status: 200,
|
|
3885
4038
|
description: `Resource descriptor (operations + JSON Schema) for ${name}`
|
|
3886
4039
|
})(cls.prototype, "getResourceJson", d);
|
|
@@ -3890,17 +4043,17 @@ var registerResourceColumnsEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
3890
4043
|
const { route, name } = config;
|
|
3891
4044
|
def(cls, "getResourceColumns", async function() {
|
|
3892
4045
|
if (!IS_DEV) {
|
|
3893
|
-
throw new
|
|
4046
|
+
throw new import_common13.ForbiddenException("The resource schema editor is only available when the backend is running in local dev mode.");
|
|
3894
4047
|
}
|
|
3895
4048
|
const fresh = await this.configRegistry.getByRoute(route);
|
|
3896
4049
|
return buildEditableColumnsPayload(fresh ?? config);
|
|
3897
4050
|
});
|
|
3898
4051
|
const d = desc(cls, "getResourceColumns");
|
|
3899
|
-
(0,
|
|
3900
|
-
(0,
|
|
4052
|
+
(0, import_common13.Get)("resource-columns")(cls.prototype, "getResourceColumns", d);
|
|
4053
|
+
(0, import_swagger8.ApiOperation)({
|
|
3901
4054
|
summary: `Dev-only: get the editable column list for ${name}`
|
|
3902
4055
|
})(cls.prototype, "getResourceColumns", d);
|
|
3903
|
-
(0,
|
|
4056
|
+
(0, import_swagger8.ApiResponse)({
|
|
3904
4057
|
status: 200,
|
|
3905
4058
|
description: `Editable column list for ${name}`
|
|
3906
4059
|
})(cls.prototype, "getResourceColumns", d);
|
|
@@ -3910,34 +4063,34 @@ var registerResourceJsonPatchEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
3910
4063
|
const { route, name } = config;
|
|
3911
4064
|
def(cls, "patchResourceJson", async function(body) {
|
|
3912
4065
|
if (!IS_DEV) {
|
|
3913
|
-
throw new
|
|
4066
|
+
throw new import_common13.ForbiddenException("Editing resource.json is only available when the backend is running in local dev mode.");
|
|
3914
4067
|
}
|
|
3915
4068
|
await this.configRegistry.getByRoute(route);
|
|
3916
4069
|
const dir = this.configRegistry.getResourceDir(route);
|
|
3917
4070
|
if (!dir) {
|
|
3918
|
-
throw new
|
|
4071
|
+
throw new import_common13.NotFoundException(`No resource.json on disk for "${name}" (route "${route}").`);
|
|
3919
4072
|
}
|
|
3920
4073
|
const jsonPath = (0, import_node_path5.join)(dir, "resource.json");
|
|
3921
4074
|
const raw = readRawResourceJson(jsonPath);
|
|
3922
4075
|
if (!raw) {
|
|
3923
|
-
throw new
|
|
4076
|
+
throw new import_common13.NotFoundException(`resource.json not found at ${jsonPath}`);
|
|
3924
4077
|
}
|
|
3925
4078
|
const merged = applyColumnPatch(raw, body);
|
|
3926
4079
|
const validated = validateResourceJson(merged);
|
|
3927
4080
|
if (!validated.success) {
|
|
3928
|
-
throw new
|
|
4081
|
+
throw new import_common13.BadRequestException(validated.error.issues);
|
|
3929
4082
|
}
|
|
3930
4083
|
writeRawResourceJson(jsonPath, merged);
|
|
3931
4084
|
const fresh = await this.configRegistry.getByRoute(route);
|
|
3932
4085
|
return buildEditableColumnsPayload(fresh ?? config);
|
|
3933
4086
|
});
|
|
3934
4087
|
const d = desc(cls, "patchResourceJson");
|
|
3935
|
-
(0,
|
|
3936
|
-
(0,
|
|
3937
|
-
(0,
|
|
4088
|
+
(0, import_common13.Patch)("resource.json")(cls.prototype, "patchResourceJson", d);
|
|
4089
|
+
(0, import_common13.Body)(new ZodValidationPipe(PatchResourceJsonSchema))(cls.prototype, "patchResourceJson", 0);
|
|
4090
|
+
(0, import_swagger8.ApiOperation)({
|
|
3938
4091
|
summary: `Dev-only: patch column layout in resource.json for ${name}`
|
|
3939
4092
|
})(cls.prototype, "patchResourceJson", d);
|
|
3940
|
-
(0,
|
|
4093
|
+
(0, import_swagger8.ApiResponse)({
|
|
3941
4094
|
status: 200,
|
|
3942
4095
|
description: `Updated resource descriptor for ${name}`
|
|
3943
4096
|
})(cls.prototype, "patchResourceJson", d);
|
|
@@ -3947,26 +4100,26 @@ var registerResourceJsonRawGetEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
3947
4100
|
const { route, name } = config;
|
|
3948
4101
|
def(cls, "getResourceJsonRaw", async function() {
|
|
3949
4102
|
if (!IS_DEV) {
|
|
3950
|
-
throw new
|
|
4103
|
+
throw new import_common13.ForbiddenException("The resource JSON editor is only available when the backend is running in local dev mode.");
|
|
3951
4104
|
}
|
|
3952
4105
|
await this.configRegistry.getByRoute(route);
|
|
3953
4106
|
const dir = this.configRegistry.getResourceDir(route);
|
|
3954
4107
|
if (!dir) {
|
|
3955
|
-
throw new
|
|
4108
|
+
throw new import_common13.NotFoundException(`No resource.json on disk for "${name}" (route "${route}").`);
|
|
3956
4109
|
}
|
|
3957
4110
|
const jsonPath = (0, import_node_path5.join)(dir, "resource.json");
|
|
3958
4111
|
const raw = readRawResourceJson(jsonPath);
|
|
3959
4112
|
if (!raw) {
|
|
3960
|
-
throw new
|
|
4113
|
+
throw new import_common13.NotFoundException(`resource.json not found at ${jsonPath}`);
|
|
3961
4114
|
}
|
|
3962
4115
|
return raw;
|
|
3963
4116
|
});
|
|
3964
4117
|
const d = desc(cls, "getResourceJsonRaw");
|
|
3965
|
-
(0,
|
|
3966
|
-
(0,
|
|
4118
|
+
(0, import_common13.Get)("resource-json-raw")(cls.prototype, "getResourceJsonRaw", d);
|
|
4119
|
+
(0, import_swagger8.ApiOperation)({
|
|
3967
4120
|
summary: `Dev-only: get the raw resource.json for ${name}`
|
|
3968
4121
|
})(cls.prototype, "getResourceJsonRaw", d);
|
|
3969
|
-
(0,
|
|
4122
|
+
(0, import_swagger8.ApiResponse)({
|
|
3970
4123
|
status: 200,
|
|
3971
4124
|
description: `Raw resource.json for ${name}`
|
|
3972
4125
|
})(cls.prototype, "getResourceJsonRaw", d);
|
|
@@ -3976,243 +4129,179 @@ var registerResourceJsonRawPutEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
3976
4129
|
const { route, name } = config;
|
|
3977
4130
|
def(cls, "putResourceJsonRaw", async function(body) {
|
|
3978
4131
|
if (!IS_DEV) {
|
|
3979
|
-
throw new
|
|
4132
|
+
throw new import_common13.ForbiddenException("Editing resource.json is only available when the backend is running in local dev mode.");
|
|
3980
4133
|
}
|
|
3981
4134
|
await this.configRegistry.getByRoute(route);
|
|
3982
4135
|
const dir = this.configRegistry.getResourceDir(route);
|
|
3983
4136
|
if (!dir) {
|
|
3984
|
-
throw new
|
|
4137
|
+
throw new import_common13.NotFoundException(`No resource.json on disk for "${name}" (route "${route}").`);
|
|
3985
4138
|
}
|
|
3986
4139
|
const validated = validateResourceJson(body);
|
|
3987
4140
|
if (!validated.success) {
|
|
3988
|
-
throw new
|
|
4141
|
+
throw new import_common13.BadRequestException(validated.error.issues);
|
|
3989
4142
|
}
|
|
3990
4143
|
const jsonPath = (0, import_node_path5.join)(dir, "resource.json");
|
|
3991
4144
|
writeRawResourceJson(jsonPath, body);
|
|
3992
4145
|
return body;
|
|
3993
4146
|
});
|
|
3994
4147
|
const d = desc(cls, "putResourceJsonRaw");
|
|
3995
|
-
(0,
|
|
3996
|
-
(0,
|
|
3997
|
-
(0,
|
|
4148
|
+
(0, import_common13.Put)("resource-json-raw")(cls.prototype, "putResourceJsonRaw", d);
|
|
4149
|
+
(0, import_common13.Body)()(cls.prototype, "putResourceJsonRaw", 0);
|
|
4150
|
+
(0, import_swagger8.ApiOperation)({
|
|
3998
4151
|
summary: `Dev-only: replace the full resource.json for ${name}`
|
|
3999
4152
|
})(cls.prototype, "putResourceJsonRaw", d);
|
|
4000
|
-
(0,
|
|
4153
|
+
(0, import_swagger8.ApiResponse)({
|
|
4001
4154
|
status: 200,
|
|
4002
4155
|
description: `Updated raw resource.json for ${name}`
|
|
4003
4156
|
})(cls.prototype, "putResourceJsonRaw", d);
|
|
4004
4157
|
}, "registerResourceJsonRawPutEndpoint");
|
|
4005
4158
|
|
|
4006
|
-
// src/lib/crud/operations/register-
|
|
4007
|
-
var
|
|
4008
|
-
var
|
|
4009
|
-
var
|
|
4010
|
-
const {
|
|
4011
|
-
const
|
|
4159
|
+
// src/lib/crud/operations/register-schemas.ts
|
|
4160
|
+
var import_common14 = require("@nestjs/common");
|
|
4161
|
+
var import_swagger9 = require("@nestjs/swagger");
|
|
4162
|
+
var defaultSchemas = /* @__PURE__ */ __name((ctx) => {
|
|
4163
|
+
const { config, baseUrl } = ctx;
|
|
4164
|
+
const { route, name } = config;
|
|
4165
|
+
const viewsPayload = buildViewsPayload(config, baseUrl);
|
|
4012
4166
|
return {
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
sortDir: params.sortDir,
|
|
4021
|
-
filter: params.filter
|
|
4022
|
-
}
|
|
4023
|
-
};
|
|
4024
|
-
}, "findAllByParent");
|
|
4025
|
-
var createChild = /* @__PURE__ */ __name(async (repo, id, sub, body) => {
|
|
4026
|
-
return repo.createChild(id, sub, body);
|
|
4027
|
-
}, "createChild");
|
|
4028
|
-
var findOneChild = /* @__PURE__ */ __name(async (repo, sub, childId, parentId) => {
|
|
4029
|
-
return repo.findOneChild(sub, childId, parentId);
|
|
4030
|
-
}, "findOneChild");
|
|
4031
|
-
var updateChild = /* @__PURE__ */ __name(async (repo, sub, childId, body) => {
|
|
4032
|
-
return repo.updateChild(sub, childId, body);
|
|
4033
|
-
}, "updateChild");
|
|
4034
|
-
var deleteChild = /* @__PURE__ */ __name(async (repo, sub, childId, parentId) => {
|
|
4035
|
-
return repo.deleteChild(sub, childId, parentId);
|
|
4036
|
-
}, "deleteChild");
|
|
4037
|
-
var registerSubResourceSchemas = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4038
|
-
if (!sub.views) return;
|
|
4039
|
-
const { cls, config, baseUrl } = ctx;
|
|
4040
|
-
const { route } = config;
|
|
4041
|
-
const methodName = `getSchemas_${sub.childRoute}`;
|
|
4042
|
-
const childUri = `${baseUrl}/${route}/{parent.id}/${sub.childRoute}`;
|
|
4043
|
-
const schemasPayload = {
|
|
4044
|
-
id: sub.name ?? sub.childRoute,
|
|
4045
|
-
name: sub.name ?? sub.childRoute,
|
|
4046
|
-
route: sub.childRoute,
|
|
4047
|
-
uri: childUri,
|
|
4048
|
-
title: sub.title ?? sub.childRoute,
|
|
4049
|
-
idField: sub.idField ?? "id",
|
|
4050
|
-
idType: sub.idType ?? "string",
|
|
4051
|
-
...sub.modalSize && {
|
|
4052
|
-
modalSize: sub.modalSize
|
|
4053
|
-
},
|
|
4054
|
-
operations: buildSubResourceOperations(sub.operations, childUri, sub.idField ?? "id"),
|
|
4055
|
-
schemas: Object.fromEntries(Object.entries(sub.views).map(([key, v]) => [
|
|
4056
|
-
key,
|
|
4057
|
-
{
|
|
4058
|
-
data: v.json_schema,
|
|
4059
|
-
ui: v.ui_schema,
|
|
4060
|
-
...v.defaultSort !== void 0 && {
|
|
4061
|
-
defaultSort: v.defaultSort
|
|
4062
|
-
}
|
|
4167
|
+
route: "schemas",
|
|
4168
|
+
methodName: "getSchemas",
|
|
4169
|
+
name,
|
|
4170
|
+
schemasFn: /* @__PURE__ */ __name(async function() {
|
|
4171
|
+
if (IS_DEV) {
|
|
4172
|
+
const fresh = await this.configRegistry.getByRoute(route);
|
|
4173
|
+
if (fresh) return buildViewsPayload(fresh, baseUrl) ?? viewsPayload;
|
|
4063
4174
|
}
|
|
4064
|
-
|
|
4065
|
-
|
|
4175
|
+
return viewsPayload;
|
|
4176
|
+
}, "schemasFn"),
|
|
4177
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
4178
|
+
}, "decorators")
|
|
4066
4179
|
};
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
const
|
|
4071
|
-
(
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
const
|
|
4085
|
-
const
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
});
|
|
4089
|
-
const d = desc(cls, methodName);
|
|
4090
|
-
(0, import_common10.Get)(`:id/${sub.childRoute}`)(cls.prototype, methodName, d);
|
|
4091
|
-
(0, import_common10.Param)("id")(cls.prototype, methodName, 0);
|
|
4092
|
-
(0, import_common10.Query)(new ZodValidationPipe(RequestDtoNoOffset.zodSchema))(cls.prototype, methodName, 1);
|
|
4093
|
-
(0, import_swagger5.ApiOperation)({
|
|
4094
|
-
summary: `List ${sub.childRoute} for a ${name}`
|
|
4095
|
-
})(cls.prototype, methodName, d);
|
|
4096
|
-
(0, import_swagger5.ApiParam)(idParamMeta)(cls.prototype, methodName, d);
|
|
4097
|
-
(0, import_swagger5.ApiResponse)({
|
|
4098
|
-
status: 200,
|
|
4099
|
-
description: `${sub.childRoute} list`
|
|
4100
|
-
})(cls.prototype, methodName, d);
|
|
4101
|
-
}, "registerSubResourceFindAll");
|
|
4102
|
-
var registerSubResourceCreate = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4103
|
-
if (!sub.operations?.create) return;
|
|
4104
|
-
const { cls, config } = ctx;
|
|
4105
|
-
const { name } = config;
|
|
4106
|
-
const methodName = `createChild_${sub.childRoute}`;
|
|
4107
|
-
def(cls, methodName, async function(id, body) {
|
|
4108
|
-
return createChild(this.repo, id, sub, body);
|
|
4109
|
-
});
|
|
4110
|
-
const d = desc(cls, methodName);
|
|
4111
|
-
(0, import_common10.Post)(`:id/${sub.childRoute}`)(cls.prototype, methodName, d);
|
|
4112
|
-
(0, import_common10.Param)("id")(cls.prototype, methodName, 0);
|
|
4113
|
-
(0, import_common10.Body)()(cls.prototype, methodName, 1);
|
|
4114
|
-
(0, import_swagger5.ApiOperation)({
|
|
4115
|
-
summary: `Create ${sub.childRoute} for a ${name}`
|
|
4116
|
-
})(cls.prototype, methodName, d);
|
|
4117
|
-
(0, import_swagger5.ApiParam)(ctx.idParamMeta)(cls.prototype, methodName, d);
|
|
4118
|
-
(0, import_swagger5.ApiResponse)({
|
|
4119
|
-
status: 201,
|
|
4120
|
-
description: `${sub.childRoute} created`
|
|
4121
|
-
})(cls.prototype, methodName, d);
|
|
4122
|
-
}, "registerSubResourceCreate");
|
|
4123
|
-
var registerSubResourceFindOne = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4124
|
-
if (!sub.operations?.findOne) return;
|
|
4180
|
+
}, "defaultSchemas");
|
|
4181
|
+
var childSchemas = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
4182
|
+
if (!sub.views) return null;
|
|
4183
|
+
const { config, baseUrl } = ctx;
|
|
4184
|
+
const schemasPayload = buildSubResourceViewsPayload(config, sub, baseUrl);
|
|
4185
|
+
return {
|
|
4186
|
+
route: `${sub.childRoute}/schemas`,
|
|
4187
|
+
methodName: `getSchemas_${sub.childRoute}`,
|
|
4188
|
+
name: sub.childRoute,
|
|
4189
|
+
schemasFn: /* @__PURE__ */ __name(async function() {
|
|
4190
|
+
return schemasPayload;
|
|
4191
|
+
}, "schemasFn"),
|
|
4192
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
4193
|
+
}, "decorators")
|
|
4194
|
+
};
|
|
4195
|
+
}, "childSchemas");
|
|
4196
|
+
var registerSchemas = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4197
|
+
const operationFn = sub ? childSchemas(sub) : defaultSchemas;
|
|
4198
|
+
const properties = operationFn(ctx);
|
|
4199
|
+
if (!properties) return;
|
|
4200
|
+
const { methodName, route, name } = properties;
|
|
4125
4201
|
const { cls } = ctx;
|
|
4126
|
-
|
|
4127
|
-
def(cls, methodName, async function(parentId, childId) {
|
|
4128
|
-
return findOneChild(this.repo, sub, childId, parentId);
|
|
4129
|
-
});
|
|
4202
|
+
def(cls, methodName, properties.schemasFn);
|
|
4130
4203
|
const d = desc(cls, methodName);
|
|
4131
|
-
(0,
|
|
4132
|
-
(0,
|
|
4133
|
-
|
|
4134
|
-
(0, import_swagger5.ApiOperation)({
|
|
4135
|
-
summary: `Get a ${sub.childRoute} record`
|
|
4204
|
+
(0, import_common14.Get)(route)(cls.prototype, methodName, d);
|
|
4205
|
+
(0, import_swagger9.ApiOperation)({
|
|
4206
|
+
summary: `Get view schemas for ${name}`
|
|
4136
4207
|
})(cls.prototype, methodName, d);
|
|
4137
|
-
(0,
|
|
4138
|
-
(0, import_swagger5.ApiResponse)({
|
|
4208
|
+
(0, import_swagger9.ApiResponse)({
|
|
4139
4209
|
status: 200,
|
|
4140
|
-
description:
|
|
4210
|
+
description: `View schemas for ${name}`
|
|
4141
4211
|
})(cls.prototype, methodName, d);
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4212
|
+
properties.decorators();
|
|
4213
|
+
}, "registerSchemas");
|
|
4214
|
+
|
|
4215
|
+
// src/lib/crud/operations/register-update.ts
|
|
4216
|
+
var import_common15 = require("@nestjs/common");
|
|
4217
|
+
var import_swagger10 = require("@nestjs/swagger");
|
|
4218
|
+
var defaultUpdate = /* @__PURE__ */ __name((ctx) => {
|
|
4219
|
+
if (!isOperationEnabled(ctx.definition, "update")) return null;
|
|
4220
|
+
const { cls, config, updateSchema, bodyDecorator } = ctx;
|
|
4221
|
+
const methodName = "update";
|
|
4222
|
+
return {
|
|
4223
|
+
route: ":id",
|
|
4224
|
+
methodName,
|
|
4225
|
+
name: config.name,
|
|
4226
|
+
updateFn: /* @__PURE__ */ __name(function(id, body) {
|
|
4227
|
+
return this.repo.update(id, body);
|
|
4228
|
+
}, "updateFn"),
|
|
4229
|
+
decorators: /* @__PURE__ */ __name(() => {
|
|
4230
|
+
(0, import_common15.Param)("id")(cls.prototype, methodName, 0);
|
|
4231
|
+
bodyDecorator(updateSchema)(cls.prototype, methodName, 1);
|
|
4232
|
+
}, "decorators")
|
|
4233
|
+
};
|
|
4234
|
+
}, "defaultUpdate");
|
|
4235
|
+
var childUpdate = /* @__PURE__ */ __name((sub) => (ctx) => {
|
|
4236
|
+
if (!isOperationEnabled(sub.operations, "update")) return null;
|
|
4145
4237
|
const { cls } = ctx;
|
|
4146
4238
|
const methodName = `updateChild_${sub.childRoute}`;
|
|
4147
|
-
|
|
4148
|
-
return
|
|
4149
|
-
});
|
|
4150
|
-
const
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4239
|
+
const updateFn = /* @__PURE__ */ __name(async function(_id, childId, body) {
|
|
4240
|
+
return this.repo.updateChild(sub, childId, body);
|
|
4241
|
+
}, "updateFn");
|
|
4242
|
+
const decorators = /* @__PURE__ */ __name(() => {
|
|
4243
|
+
(0, import_common15.Param)("id")(cls.prototype, methodName, 0);
|
|
4244
|
+
(0, import_common15.Param)("childId")(cls.prototype, methodName, 1);
|
|
4245
|
+
(0, import_common15.Body)()(cls.prototype, methodName, 2);
|
|
4246
|
+
}, "decorators");
|
|
4247
|
+
return {
|
|
4248
|
+
route: `:id/${sub.childRoute}/:childId`,
|
|
4249
|
+
methodName,
|
|
4250
|
+
name: sub.childRoute,
|
|
4251
|
+
updateFn,
|
|
4252
|
+
decorators
|
|
4253
|
+
};
|
|
4254
|
+
}, "childUpdate");
|
|
4255
|
+
var registerUpdate = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4256
|
+
const operationFn = sub ? childUpdate(sub) : defaultUpdate;
|
|
4257
|
+
const properties = operationFn(ctx);
|
|
4258
|
+
if (!properties) return;
|
|
4259
|
+
const { methodName, route, name } = properties;
|
|
4166
4260
|
const { cls } = ctx;
|
|
4167
|
-
|
|
4168
|
-
def(cls, methodName, async function(_id, childId, body) {
|
|
4169
|
-
return updateChild(this.repo, sub, childId, body);
|
|
4170
|
-
});
|
|
4261
|
+
def(cls, methodName, properties.updateFn);
|
|
4171
4262
|
const d = desc(cls, methodName);
|
|
4172
|
-
(0,
|
|
4173
|
-
(0,
|
|
4174
|
-
|
|
4175
|
-
(0, import_common10.Body)()(cls.prototype, methodName, 2);
|
|
4176
|
-
(0, import_swagger5.ApiOperation)({
|
|
4177
|
-
summary: `Update a ${sub.childRoute} record`
|
|
4263
|
+
(0, import_common15.Put)(route)(cls.prototype, methodName, d);
|
|
4264
|
+
(0, import_swagger10.ApiOperation)({
|
|
4265
|
+
summary: `Replace a ${name}`
|
|
4178
4266
|
})(cls.prototype, methodName, d);
|
|
4179
|
-
(0,
|
|
4180
|
-
(0, import_swagger5.ApiResponse)({
|
|
4267
|
+
(0, import_swagger10.ApiResponse)({
|
|
4181
4268
|
status: 200,
|
|
4182
|
-
description: `${
|
|
4183
|
-
})(cls.prototype, methodName, d);
|
|
4184
|
-
}, "registerSubResourcePatch");
|
|
4185
|
-
var registerSubResourceDelete = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4186
|
-
if (!sub.operations?.delete) return;
|
|
4187
|
-
const { cls } = ctx;
|
|
4188
|
-
const methodName = `deleteChild_${sub.childRoute}`;
|
|
4189
|
-
def(cls, methodName, async function(parentId, childId) {
|
|
4190
|
-
return deleteChild(this.repo, sub, childId, parentId);
|
|
4191
|
-
});
|
|
4192
|
-
const d = desc(cls, methodName);
|
|
4193
|
-
(0, import_common10.Delete)(`:id/${sub.childRoute}/:childId`)(cls.prototype, methodName, d);
|
|
4194
|
-
(0, import_common10.Param)("id")(cls.prototype, methodName, 0);
|
|
4195
|
-
(0, import_common10.Param)("childId")(cls.prototype, methodName, 1);
|
|
4196
|
-
(0, import_swagger5.ApiOperation)({
|
|
4197
|
-
summary: `Delete ${sub.childRoute} record`
|
|
4269
|
+
description: `${name} replaced`
|
|
4198
4270
|
})(cls.prototype, methodName, d);
|
|
4199
|
-
(0,
|
|
4200
|
-
|
|
4201
|
-
status: 200,
|
|
4202
|
-
description: `${sub.childRoute} deleted`
|
|
4271
|
+
(0, import_swagger10.ApiNotFoundResponse)({
|
|
4272
|
+
description: "Not found"
|
|
4203
4273
|
})(cls.prototype, methodName, d);
|
|
4204
|
-
|
|
4274
|
+
properties.decorators();
|
|
4275
|
+
}, "registerUpdate");
|
|
4276
|
+
|
|
4277
|
+
// src/lib/crud/operations/register-endpoints.ts
|
|
4278
|
+
var registerEndpoints = /* @__PURE__ */ __name((ctx) => {
|
|
4279
|
+
registerSubResourceRoutes(ctx);
|
|
4280
|
+
registerFindAll(ctx);
|
|
4281
|
+
registerResourceJsonRawGetEndpoint(ctx);
|
|
4282
|
+
registerResourceJsonRawPutEndpoint(ctx);
|
|
4283
|
+
registerResourceJsonPatchEndpoint(ctx);
|
|
4284
|
+
registerResourceJsonEndpoint(ctx);
|
|
4285
|
+
registerResourceColumnsEndpoint(ctx);
|
|
4286
|
+
registerDefinitionEndpoint(ctx);
|
|
4287
|
+
registerEndpoint(ctx);
|
|
4288
|
+
registerActionRoutes(ctx);
|
|
4289
|
+
registerTableActionRoutes(ctx);
|
|
4290
|
+
}, "registerEndpoints");
|
|
4205
4291
|
var registerSubResourceRoutes = /* @__PURE__ */ __name((ctx) => {
|
|
4206
4292
|
for (const sub of ctx.config.subResources ?? []) {
|
|
4207
|
-
|
|
4208
|
-
registerSubResourceFindAll(ctx, sub);
|
|
4209
|
-
registerSubResourceCreate(ctx, sub);
|
|
4210
|
-
registerSubResourceFindOne(ctx, sub);
|
|
4211
|
-
registerSubResourceUpdate(ctx, sub);
|
|
4212
|
-
registerSubResourcePatch(ctx, sub);
|
|
4213
|
-
registerSubResourceDelete(ctx, sub);
|
|
4293
|
+
registerEndpoint(ctx, sub);
|
|
4214
4294
|
}
|
|
4215
4295
|
}, "registerSubResourceRoutes");
|
|
4296
|
+
var registerEndpoint = /* @__PURE__ */ __name((ctx, sub) => {
|
|
4297
|
+
registerSchemas(ctx, sub);
|
|
4298
|
+
registerFindAll(ctx, sub);
|
|
4299
|
+
registerFindOne(ctx, sub);
|
|
4300
|
+
registerCreate(ctx, sub);
|
|
4301
|
+
registerUpdate(ctx, sub);
|
|
4302
|
+
registerPatch(ctx, sub);
|
|
4303
|
+
registerDelete(ctx, sub);
|
|
4304
|
+
}, "registerEndpoint");
|
|
4216
4305
|
|
|
4217
4306
|
// src/lib/crud/crud-controller.factory.ts
|
|
4218
4307
|
function createCrudController(config, baseUrl) {
|
|
@@ -4229,9 +4318,9 @@ function createCrudController(config, baseUrl) {
|
|
|
4229
4318
|
throw new Error(`Resource "${name}" declares 'upsert' but no upsertOn`);
|
|
4230
4319
|
}
|
|
4231
4320
|
const bodyDecorator = /* @__PURE__ */ __name((schema, options) => {
|
|
4232
|
-
if (!schema) return (0,
|
|
4233
|
-
if (isZodSchema(schema)) return (0,
|
|
4234
|
-
return (0,
|
|
4321
|
+
if (!schema) return (0, import_common16.Body)();
|
|
4322
|
+
if (isZodSchema(schema)) return (0, import_common16.Body)(new ZodValidationPipe(schema, options));
|
|
4323
|
+
return (0, import_common16.Body)();
|
|
4235
4324
|
}, "bodyDecorator");
|
|
4236
4325
|
let CrudControllerBase = class CrudControllerBase {
|
|
4237
4326
|
static {
|
|
@@ -4262,25 +4351,9 @@ function createCrudController(config, baseUrl) {
|
|
|
4262
4351
|
bodyDecorator,
|
|
4263
4352
|
baseUrl
|
|
4264
4353
|
};
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
registerResourceJsonEndpoint(ctx);
|
|
4269
|
-
registerResourceColumnsEndpoint(ctx);
|
|
4270
|
-
registerResourceJsonPatchEndpoint(ctx);
|
|
4271
|
-
registerResourceJsonRawGetEndpoint(ctx);
|
|
4272
|
-
registerResourceJsonRawPutEndpoint(ctx);
|
|
4273
|
-
registerActionRoutes(ctx);
|
|
4274
|
-
registerTableActionRoutes(ctx);
|
|
4275
|
-
registerSubResourceRoutes(ctx);
|
|
4276
|
-
registerFindOne(ctx);
|
|
4277
|
-
registerCreate(ctx);
|
|
4278
|
-
registerUpdate(ctx);
|
|
4279
|
-
registerPatch(ctx);
|
|
4280
|
-
registerUpsert(ctx);
|
|
4281
|
-
registerDelete(ctx);
|
|
4282
|
-
(0, import_common11.Controller)(route)(CrudControllerBase);
|
|
4283
|
-
(0, import_swagger6.ApiTags)(tag)(CrudControllerBase);
|
|
4354
|
+
registerEndpoints(ctx);
|
|
4355
|
+
(0, import_common16.Controller)(route)(CrudControllerBase);
|
|
4356
|
+
(0, import_swagger11.ApiTags)(tag)(CrudControllerBase);
|
|
4284
4357
|
Object.defineProperty(CrudControllerBase, "name", {
|
|
4285
4358
|
value: `${name.charAt(0).toUpperCase() + name.slice(1)}Controller`
|
|
4286
4359
|
});
|
|
@@ -4293,8 +4366,8 @@ function createCrudController(config, baseUrl) {
|
|
|
4293
4366
|
__name(createCrudController, "createCrudController");
|
|
4294
4367
|
|
|
4295
4368
|
// src/lib/crud/dev-tools/dev-resources.controller.ts
|
|
4296
|
-
var
|
|
4297
|
-
var
|
|
4369
|
+
var import_common17 = require("@nestjs/common");
|
|
4370
|
+
var import_swagger12 = require("@nestjs/swagger");
|
|
4298
4371
|
|
|
4299
4372
|
// ../crouton-codegen/src/naming.ts
|
|
4300
4373
|
var clientAccessor = /* @__PURE__ */ __name((prismaModelName) => {
|
|
@@ -4368,6 +4441,20 @@ var resolveRelationType = /* @__PURE__ */ __name((field, index) => {
|
|
|
4368
4441
|
if (field.isList) return otherIsList ? "manyToMany" : "oneToMany";
|
|
4369
4442
|
return otherIsList ? "manyToOne" : "oneToOne";
|
|
4370
4443
|
}, "resolveRelationType");
|
|
4444
|
+
var literalDefault = /* @__PURE__ */ __name((value) => {
|
|
4445
|
+
if (value === void 0 || value === null) return void 0;
|
|
4446
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
4447
|
+
return value;
|
|
4448
|
+
}
|
|
4449
|
+
if (Array.isArray(value) && value.every((v) => [
|
|
4450
|
+
"string",
|
|
4451
|
+
"number",
|
|
4452
|
+
"boolean"
|
|
4453
|
+
].includes(typeof v))) {
|
|
4454
|
+
return value;
|
|
4455
|
+
}
|
|
4456
|
+
return void 0;
|
|
4457
|
+
}, "literalDefault");
|
|
4371
4458
|
var dmmfToDbModels = /* @__PURE__ */ __name((dmmf) => {
|
|
4372
4459
|
const { models, enums } = dmmf.datamodel;
|
|
4373
4460
|
const enumNames = new Set(enums.map((e) => e.name));
|
|
@@ -4401,6 +4488,9 @@ var dmmfToDbModels = /* @__PURE__ */ __name((dmmf) => {
|
|
|
4401
4488
|
isUnique: f.isUnique,
|
|
4402
4489
|
isUpdatedAt: f.isUpdatedAt,
|
|
4403
4490
|
hasDefault: f.hasDefaultValue,
|
|
4491
|
+
...f.hasDefaultValue && literalDefault(f.default) !== void 0 ? {
|
|
4492
|
+
defaultValue: literalDefault(f.default)
|
|
4493
|
+
} : {},
|
|
4404
4494
|
isTimestamp: kind === "scalar" && isTimestampField({
|
|
4405
4495
|
name: f.name,
|
|
4406
4496
|
type: f.type,
|
|
@@ -4482,7 +4572,10 @@ var classify = /* @__PURE__ */ __name((model, ctx = {}) => {
|
|
|
4482
4572
|
} : {
|
|
4483
4573
|
fieldInput: {
|
|
4484
4574
|
type: "date",
|
|
4485
|
-
position: position
|
|
4575
|
+
position: position++,
|
|
4576
|
+
...field.defaultValue !== void 0 ? {
|
|
4577
|
+
defaultValue: field.defaultValue
|
|
4578
|
+
} : {}
|
|
4486
4579
|
}
|
|
4487
4580
|
};
|
|
4488
4581
|
} else if (field.kind === "foreignKey") {
|
|
@@ -4494,7 +4587,10 @@ var classify = /* @__PURE__ */ __name((model, ctx = {}) => {
|
|
|
4494
4587
|
} : {
|
|
4495
4588
|
fieldInput: {
|
|
4496
4589
|
type: "text",
|
|
4497
|
-
position: position
|
|
4590
|
+
position: position++,
|
|
4591
|
+
...field.defaultValue !== void 0 ? {
|
|
4592
|
+
defaultValue: field.defaultValue
|
|
4593
|
+
} : {}
|
|
4498
4594
|
}
|
|
4499
4595
|
};
|
|
4500
4596
|
} else if (field.kind === "relation") {
|
|
@@ -4503,7 +4599,6 @@ var classify = /* @__PURE__ */ __name((model, ctx = {}) => {
|
|
|
4503
4599
|
col = {
|
|
4504
4600
|
hiddenInTable: ruleset.hideRelationsInTable,
|
|
4505
4601
|
fieldInput: {
|
|
4506
|
-
type: "relation",
|
|
4507
4602
|
format: "relation",
|
|
4508
4603
|
resource: target,
|
|
4509
4604
|
relationType: field.relationType
|
|
@@ -4539,14 +4634,20 @@ var classify = /* @__PURE__ */ __name((model, ctx = {}) => {
|
|
|
4539
4634
|
fieldInput: {
|
|
4540
4635
|
type: "select",
|
|
4541
4636
|
position: position++,
|
|
4542
|
-
options
|
|
4637
|
+
options,
|
|
4638
|
+
...field.defaultValue !== void 0 ? {
|
|
4639
|
+
defaultValue: field.defaultValue
|
|
4640
|
+
} : {}
|
|
4543
4641
|
}
|
|
4544
4642
|
};
|
|
4545
4643
|
} else {
|
|
4546
4644
|
col = {
|
|
4547
4645
|
fieldInput: {
|
|
4548
4646
|
type: scalarFieldInputType(field.name, field.type),
|
|
4549
|
-
position: position
|
|
4647
|
+
position: position++,
|
|
4648
|
+
...field.defaultValue !== void 0 ? {
|
|
4649
|
+
defaultValue: field.defaultValue
|
|
4650
|
+
} : {}
|
|
4550
4651
|
}
|
|
4551
4652
|
};
|
|
4552
4653
|
}
|
|
@@ -4952,12 +5053,12 @@ var makeSchemaExportName = /* @__PURE__ */ __name((config) => {
|
|
|
4952
5053
|
var resolveFromRoot = /* @__PURE__ */ __name((root, p) => (0, import_node_path7.isAbsolute)(p) ? p : (0, import_node_path7.join)(root, p), "resolveFromRoot");
|
|
4953
5054
|
|
|
4954
5055
|
// ../crouton-codegen/src/scaffold.ts
|
|
4955
|
-
var
|
|
5056
|
+
var import_zod24 = require("zod");
|
|
4956
5057
|
var import_promises5 = require("fs/promises");
|
|
4957
5058
|
var import_node_path8 = require("path");
|
|
4958
5059
|
var ScallfoldDatasourceSchema = DataSourceShape.extend({
|
|
4959
5060
|
/** Folder name under `dataSourcesDir`. */
|
|
4960
|
-
folder:
|
|
5061
|
+
folder: import_zod24.z.string().default("default")
|
|
4961
5062
|
}).transform(transformDataSource);
|
|
4962
5063
|
|
|
4963
5064
|
// ../crouton-codegen/src/datasource-scaffold.ts
|
|
@@ -5026,7 +5127,7 @@ var import_node_child_process = require("child_process");
|
|
|
5026
5127
|
var import_node_fs4 = require("fs");
|
|
5027
5128
|
var import_promises7 = require("fs/promises");
|
|
5028
5129
|
var import_node_path11 = require("path");
|
|
5029
|
-
var run = /* @__PURE__ */ __name((cmd, args, cwd) => new Promise((
|
|
5130
|
+
var run = /* @__PURE__ */ __name((cmd, args, cwd) => new Promise((resolve7) => {
|
|
5030
5131
|
const child = (0, import_node_child_process.spawn)(cmd, args, {
|
|
5031
5132
|
cwd,
|
|
5032
5133
|
shell: process.platform === "win32"
|
|
@@ -5035,12 +5136,12 @@ var run = /* @__PURE__ */ __name((cmd, args, cwd) => new Promise((resolve6) => {
|
|
|
5035
5136
|
let stderr = "";
|
|
5036
5137
|
child.stdout?.on("data", (d) => stdout += d.toString());
|
|
5037
5138
|
child.stderr?.on("data", (d) => stderr += d.toString());
|
|
5038
|
-
child.on("error", (err) =>
|
|
5139
|
+
child.on("error", (err) => resolve7({
|
|
5039
5140
|
code: 1,
|
|
5040
5141
|
stdout,
|
|
5041
5142
|
stderr: stderr + String(err)
|
|
5042
5143
|
}));
|
|
5043
|
-
child.on("close", (code) =>
|
|
5144
|
+
child.on("close", (code) => resolve7({
|
|
5044
5145
|
code: code ?? 0,
|
|
5045
5146
|
stdout,
|
|
5046
5147
|
stderr
|
|
@@ -5183,13 +5284,85 @@ var normalizeSchema = /* @__PURE__ */ __name(async (schemaPath, configDir) => {
|
|
|
5183
5284
|
return `${head}${body}${tail}`;
|
|
5184
5285
|
});
|
|
5185
5286
|
}
|
|
5186
|
-
if (renamed > 0) {
|
|
5187
|
-
await (0, import_promises7.writeFile)(schemaPath, schema, "utf-8");
|
|
5287
|
+
if (renamed > 0) {
|
|
5288
|
+
await (0, import_promises7.writeFile)(schemaPath, schema, "utf-8");
|
|
5289
|
+
}
|
|
5290
|
+
return {
|
|
5291
|
+
renamed
|
|
5292
|
+
};
|
|
5293
|
+
}, "normalizeSchema");
|
|
5294
|
+
|
|
5295
|
+
// src/lib/crud/resource/ResourceFlags.ts
|
|
5296
|
+
var import_node_path12 = require("path");
|
|
5297
|
+
var applyResourceFlagPatch = /* @__PURE__ */ __name((raw, patch) => {
|
|
5298
|
+
const result = {
|
|
5299
|
+
...raw
|
|
5300
|
+
};
|
|
5301
|
+
if (patch.draft !== void 0) {
|
|
5302
|
+
if (patch.draft) {
|
|
5303
|
+
result["draft"] = true;
|
|
5304
|
+
} else {
|
|
5305
|
+
delete result["draft"];
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
if (patch.sidebar !== void 0) {
|
|
5309
|
+
const existing = raw["sidebar"] && typeof raw["sidebar"] === "object" ? {
|
|
5310
|
+
...raw["sidebar"]
|
|
5311
|
+
} : {};
|
|
5312
|
+
if (patch.sidebar.hide !== void 0) {
|
|
5313
|
+
if (patch.sidebar.hide) {
|
|
5314
|
+
existing["hide"] = true;
|
|
5315
|
+
} else {
|
|
5316
|
+
delete existing["hide"];
|
|
5317
|
+
}
|
|
5318
|
+
}
|
|
5319
|
+
if (patch.sidebar.group !== void 0) {
|
|
5320
|
+
existing["group"] = patch.sidebar.group;
|
|
5321
|
+
}
|
|
5322
|
+
if (patch.sidebar.position !== void 0) {
|
|
5323
|
+
existing["position"] = patch.sidebar.position;
|
|
5324
|
+
}
|
|
5325
|
+
if (patch.sidebar.label !== void 0) {
|
|
5326
|
+
existing["label"] = patch.sidebar.label;
|
|
5327
|
+
}
|
|
5328
|
+
if (Object.keys(existing).length === 0) {
|
|
5329
|
+
delete result["sidebar"];
|
|
5330
|
+
} else {
|
|
5331
|
+
result["sidebar"] = existing;
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
return result;
|
|
5335
|
+
}, "applyResourceFlagPatch");
|
|
5336
|
+
var resolveResourcePath = /* @__PURE__ */ __name((resourcesDir, name) => {
|
|
5337
|
+
const resolved = (0, import_node_path12.resolve)(resourcesDir, name, "resource.json");
|
|
5338
|
+
if (!resolved.startsWith((0, import_node_path12.resolve)(resourcesDir) + "/")) {
|
|
5339
|
+
throw new Error(`Invalid resource name: "${name}"`);
|
|
5188
5340
|
}
|
|
5189
|
-
return
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5341
|
+
return resolved;
|
|
5342
|
+
}, "resolveResourcePath");
|
|
5343
|
+
|
|
5344
|
+
// src/lib/crud/resource/resource-load-report.registry.ts
|
|
5345
|
+
var ResourceLoadReportRegistry = class ResourceLoadReportRegistry2 {
|
|
5346
|
+
static {
|
|
5347
|
+
__name(this, "ResourceLoadReportRegistry");
|
|
5348
|
+
}
|
|
5349
|
+
notices = [];
|
|
5350
|
+
record(n) {
|
|
5351
|
+
this.notices.push(n);
|
|
5352
|
+
}
|
|
5353
|
+
getAll() {
|
|
5354
|
+
return [
|
|
5355
|
+
...this.notices
|
|
5356
|
+
];
|
|
5357
|
+
}
|
|
5358
|
+
getByState(state) {
|
|
5359
|
+
return this.notices.filter((n) => n.state === state);
|
|
5360
|
+
}
|
|
5361
|
+
clear() {
|
|
5362
|
+
this.notices = [];
|
|
5363
|
+
}
|
|
5364
|
+
};
|
|
5365
|
+
var resourceLoadReportRegistry = new ResourceLoadReportRegistry();
|
|
5193
5366
|
|
|
5194
5367
|
// src/lib/crud/dev-tools/dev-resources.controller.ts
|
|
5195
5368
|
function _ts_decorate5(decorators, target, key, desc2) {
|
|
@@ -5214,12 +5387,14 @@ var DevResourcesController = class {
|
|
|
5214
5387
|
__name(this, "DevResourcesController");
|
|
5215
5388
|
}
|
|
5216
5389
|
dataSourceRegistry;
|
|
5217
|
-
|
|
5390
|
+
resourceConfigRegistry;
|
|
5391
|
+
constructor(dataSourceRegistry, resourceConfigRegistry) {
|
|
5218
5392
|
this.dataSourceRegistry = dataSourceRegistry;
|
|
5393
|
+
this.resourceConfigRegistry = resourceConfigRegistry;
|
|
5219
5394
|
}
|
|
5220
5395
|
assertDev() {
|
|
5221
5396
|
if (!IS_DEV) {
|
|
5222
|
-
throw new
|
|
5397
|
+
throw new import_common17.ForbiddenException("The database sync tools are only available when CROUTON_SCHEMA_EDITOR is enabled.");
|
|
5223
5398
|
}
|
|
5224
5399
|
}
|
|
5225
5400
|
/** Loads project config + resolves the datasource + Prisma schema path. Throws 404/400 with a clear message on misconfiguration. */
|
|
@@ -5228,14 +5403,14 @@ var DevResourcesController = class {
|
|
|
5228
5403
|
try {
|
|
5229
5404
|
loaded = await loadConfig2(process.cwd());
|
|
5230
5405
|
} catch (e) {
|
|
5231
|
-
throw new
|
|
5406
|
+
throw new import_common17.NotFoundException(e.message ?? "No crouton.json config found.");
|
|
5232
5407
|
}
|
|
5233
5408
|
const datasources = await loadDatasources(loaded);
|
|
5234
5409
|
let ds;
|
|
5235
5410
|
try {
|
|
5236
5411
|
ds = resolveDatasource(datasources, datasourceName);
|
|
5237
5412
|
} catch (e) {
|
|
5238
|
-
throw new
|
|
5413
|
+
throw new import_common17.BadRequestException(e.message);
|
|
5239
5414
|
}
|
|
5240
5415
|
const schemaPath = resolveFromRoot(loaded.root, ds.prismaSchema);
|
|
5241
5416
|
return {
|
|
@@ -5250,7 +5425,7 @@ var DevResourcesController = class {
|
|
|
5250
5425
|
schemaPath
|
|
5251
5426
|
});
|
|
5252
5427
|
} catch (e) {
|
|
5253
|
-
throw new
|
|
5428
|
+
throw new import_common17.BadRequestException(`Failed to read Prisma schema at ${schemaPath}: ${e.message}`);
|
|
5254
5429
|
}
|
|
5255
5430
|
}
|
|
5256
5431
|
buildApplyContext(loaded, ds) {
|
|
@@ -5320,7 +5495,7 @@ var DevResourcesController = class {
|
|
|
5320
5495
|
zodOutputDir: zodDir
|
|
5321
5496
|
});
|
|
5322
5497
|
if (!result.ok) {
|
|
5323
|
-
throw new
|
|
5498
|
+
throw new import_common17.BadRequestException(`prisma db pull failed:
|
|
5324
5499
|
${result.dbPull.output}`);
|
|
5325
5500
|
}
|
|
5326
5501
|
return {
|
|
@@ -5337,13 +5512,13 @@ ${result.dbPull.output}`);
|
|
|
5337
5512
|
async sync(body) {
|
|
5338
5513
|
this.assertDev();
|
|
5339
5514
|
if (!body?.model) {
|
|
5340
|
-
throw new
|
|
5515
|
+
throw new import_common17.BadRequestException('"model" is required.');
|
|
5341
5516
|
}
|
|
5342
5517
|
const { loaded, ds, schemaPath } = await this.loadProject(body.datasource);
|
|
5343
5518
|
const models = await this.introspectModels(schemaPath);
|
|
5344
5519
|
const model = models.find((m) => m.prismaName === body.model || m.clientAccessor === body.model);
|
|
5345
5520
|
if (!model) {
|
|
5346
|
-
throw new
|
|
5521
|
+
throw new import_common17.NotFoundException(`Model "${body.model}" not found in ${schemaPath}.`);
|
|
5347
5522
|
}
|
|
5348
5523
|
const resolveRelationResource = await makeRelationResolver(loaded);
|
|
5349
5524
|
const diff2 = await buildResourceDiff(model, {
|
|
@@ -5423,13 +5598,136 @@ ${result.dbPull.output}`);
|
|
|
5423
5598
|
results
|
|
5424
5599
|
};
|
|
5425
5600
|
}
|
|
5601
|
+
// ─── Visibility & flag endpoints ────────────────────────────────────
|
|
5602
|
+
async visibility() {
|
|
5603
|
+
this.assertDev();
|
|
5604
|
+
const loaded = await this.resourceConfigRegistry.getAll();
|
|
5605
|
+
const fromLoaded = loaded.map((c) => ({
|
|
5606
|
+
name: c.name,
|
|
5607
|
+
path: c.route,
|
|
5608
|
+
state: c.sidebar?.hide ? "hidden" : "in-menu",
|
|
5609
|
+
group: c.sidebar?.group,
|
|
5610
|
+
position: c.sidebar?.position,
|
|
5611
|
+
editable: true
|
|
5612
|
+
}));
|
|
5613
|
+
const drafts = resourceLoadReportRegistry.getByState("draft").map((d) => ({
|
|
5614
|
+
name: d.name,
|
|
5615
|
+
path: d.path,
|
|
5616
|
+
state: "draft",
|
|
5617
|
+
group: void 0,
|
|
5618
|
+
position: void 0,
|
|
5619
|
+
editable: !d.path.endsWith(".ts")
|
|
5620
|
+
}));
|
|
5621
|
+
const errors = resourceLoadErrorsRegistry.getAll().map((e) => ({
|
|
5622
|
+
name: e.name,
|
|
5623
|
+
path: e.path,
|
|
5624
|
+
state: "error",
|
|
5625
|
+
group: void 0,
|
|
5626
|
+
position: void 0,
|
|
5627
|
+
editable: !e.path.endsWith(".ts")
|
|
5628
|
+
}));
|
|
5629
|
+
return {
|
|
5630
|
+
resources: [
|
|
5631
|
+
...fromLoaded,
|
|
5632
|
+
...drafts,
|
|
5633
|
+
...errors
|
|
5634
|
+
]
|
|
5635
|
+
};
|
|
5636
|
+
}
|
|
5637
|
+
async publish(name) {
|
|
5638
|
+
this.assertDev();
|
|
5639
|
+
const { loaded } = await this.loadProject();
|
|
5640
|
+
const resourcesDir = resolveFromRoot(loaded.root, loaded.config.resourcesDir);
|
|
5641
|
+
const jsonPath = resolveResourcePath(resourcesDir, name);
|
|
5642
|
+
const raw = readRawResourceJson(jsonPath);
|
|
5643
|
+
if (!raw) throw new import_common17.NotFoundException(`Resource "${name}" not found.`);
|
|
5644
|
+
if (jsonPath.endsWith(".ts")) throw new import_common17.ForbiddenException("TypeScript resources cannot be edited.");
|
|
5645
|
+
const patched = applyResourceFlagPatch(raw, {
|
|
5646
|
+
draft: false
|
|
5647
|
+
});
|
|
5648
|
+
const result = validateResourceJson(patched);
|
|
5649
|
+
if (!result.success) {
|
|
5650
|
+
throw new import_common17.BadRequestException(`Validation failed: ${result.error.message}`);
|
|
5651
|
+
}
|
|
5652
|
+
writeRawResourceJson(jsonPath, patched);
|
|
5653
|
+
return {
|
|
5654
|
+
ok: true
|
|
5655
|
+
};
|
|
5656
|
+
}
|
|
5657
|
+
async removeFromMenu(name) {
|
|
5658
|
+
this.assertDev();
|
|
5659
|
+
const { loaded } = await this.loadProject();
|
|
5660
|
+
const resourcesDir = resolveFromRoot(loaded.root, loaded.config.resourcesDir);
|
|
5661
|
+
const jsonPath = resolveResourcePath(resourcesDir, name);
|
|
5662
|
+
const raw = readRawResourceJson(jsonPath);
|
|
5663
|
+
if (!raw) throw new import_common17.NotFoundException(`Resource "${name}" not found.`);
|
|
5664
|
+
if (jsonPath.endsWith(".ts")) throw new import_common17.ForbiddenException("TypeScript resources cannot be edited.");
|
|
5665
|
+
const patched = applyResourceFlagPatch(raw, {
|
|
5666
|
+
sidebar: {
|
|
5667
|
+
hide: true
|
|
5668
|
+
}
|
|
5669
|
+
});
|
|
5670
|
+
const result = validateResourceJson(patched);
|
|
5671
|
+
if (!result.success) {
|
|
5672
|
+
throw new import_common17.BadRequestException(`Validation failed: ${result.error.message}`);
|
|
5673
|
+
}
|
|
5674
|
+
writeRawResourceJson(jsonPath, patched);
|
|
5675
|
+
return {
|
|
5676
|
+
ok: true
|
|
5677
|
+
};
|
|
5678
|
+
}
|
|
5679
|
+
async addToMenu(name, body = {}) {
|
|
5680
|
+
this.assertDev();
|
|
5681
|
+
const { loaded } = await this.loadProject();
|
|
5682
|
+
const resourcesDir = resolveFromRoot(loaded.root, loaded.config.resourcesDir);
|
|
5683
|
+
const jsonPath = resolveResourcePath(resourcesDir, name);
|
|
5684
|
+
const raw = readRawResourceJson(jsonPath);
|
|
5685
|
+
if (!raw) throw new import_common17.NotFoundException(`Resource "${name}" not found.`);
|
|
5686
|
+
if (jsonPath.endsWith(".ts")) throw new import_common17.ForbiddenException("TypeScript resources cannot be edited.");
|
|
5687
|
+
const sidebarPatch = {
|
|
5688
|
+
hide: false
|
|
5689
|
+
};
|
|
5690
|
+
if (body.group !== void 0) sidebarPatch.group = body.group;
|
|
5691
|
+
if (body.position !== void 0) sidebarPatch.position = body.position;
|
|
5692
|
+
if (body.label !== void 0) sidebarPatch.label = body.label;
|
|
5693
|
+
const patched = applyResourceFlagPatch(raw, {
|
|
5694
|
+
draft: false,
|
|
5695
|
+
sidebar: sidebarPatch
|
|
5696
|
+
});
|
|
5697
|
+
const result = validateResourceJson(patched);
|
|
5698
|
+
if (!result.success) {
|
|
5699
|
+
throw new import_common17.BadRequestException(`Validation failed: ${result.error.message}`);
|
|
5700
|
+
}
|
|
5701
|
+
writeRawResourceJson(jsonPath, patched);
|
|
5702
|
+
return {
|
|
5703
|
+
ok: true
|
|
5704
|
+
};
|
|
5705
|
+
}
|
|
5706
|
+
async updateFlags(name, body) {
|
|
5707
|
+
this.assertDev();
|
|
5708
|
+
const { loaded } = await this.loadProject();
|
|
5709
|
+
const resourcesDir = resolveFromRoot(loaded.root, loaded.config.resourcesDir);
|
|
5710
|
+
const jsonPath = resolveResourcePath(resourcesDir, name);
|
|
5711
|
+
const raw = readRawResourceJson(jsonPath);
|
|
5712
|
+
if (!raw) throw new import_common17.NotFoundException(`Resource "${name}" not found.`);
|
|
5713
|
+
if (jsonPath.endsWith(".ts")) throw new import_common17.ForbiddenException("TypeScript resources cannot be edited.");
|
|
5714
|
+
const patched = applyResourceFlagPatch(raw, body);
|
|
5715
|
+
const result = validateResourceJson(patched);
|
|
5716
|
+
if (!result.success) {
|
|
5717
|
+
throw new import_common17.BadRequestException(`Validation failed: ${result.error.message}`);
|
|
5718
|
+
}
|
|
5719
|
+
writeRawResourceJson(jsonPath, patched);
|
|
5720
|
+
return {
|
|
5721
|
+
ok: true
|
|
5722
|
+
};
|
|
5723
|
+
}
|
|
5426
5724
|
};
|
|
5427
5725
|
_ts_decorate5([
|
|
5428
|
-
(0,
|
|
5429
|
-
(0,
|
|
5726
|
+
(0, import_common17.Get)("models"),
|
|
5727
|
+
(0, import_swagger12.ApiOperation)({
|
|
5430
5728
|
summary: "Dev-only: list DB models from the Prisma schema, flagging which already have a resource.json and whether the running backend can actually use them yet"
|
|
5431
5729
|
}),
|
|
5432
|
-
(0,
|
|
5730
|
+
(0, import_swagger12.ApiResponse)({
|
|
5433
5731
|
status: 200,
|
|
5434
5732
|
description: "DB models and their resource/client status"
|
|
5435
5733
|
}),
|
|
@@ -5438,11 +5736,11 @@ _ts_decorate5([
|
|
|
5438
5736
|
_ts_metadata4("design:returntype", Promise)
|
|
5439
5737
|
], DevResourcesController.prototype, "listModels", null);
|
|
5440
5738
|
_ts_decorate5([
|
|
5441
|
-
(0,
|
|
5442
|
-
(0,
|
|
5739
|
+
(0, import_common17.Post)("restart"),
|
|
5740
|
+
(0, import_swagger12.ApiOperation)({
|
|
5443
5741
|
summary: "Dev-only: exit this process so a dev watcher/process manager (nodemon, `nest start --watch`, pm2, a Docker restart policy, ...) restarts it with a fresh Prisma client. Does nothing useful if this process isn't supervised by one of those."
|
|
5444
5742
|
}),
|
|
5445
|
-
(0,
|
|
5743
|
+
(0, import_swagger12.ApiResponse)({
|
|
5446
5744
|
status: 200,
|
|
5447
5745
|
description: "Restart scheduled \u2014 the connection will drop shortly after"
|
|
5448
5746
|
}),
|
|
@@ -5451,15 +5749,15 @@ _ts_decorate5([
|
|
|
5451
5749
|
_ts_metadata4("design:returntype", Object)
|
|
5452
5750
|
], DevResourcesController.prototype, "restart", null);
|
|
5453
5751
|
_ts_decorate5([
|
|
5454
|
-
(0,
|
|
5455
|
-
(0,
|
|
5752
|
+
(0, import_common17.Post)("pull"),
|
|
5753
|
+
(0, import_swagger12.ApiOperation)({
|
|
5456
5754
|
summary: "Dev-only: run `prisma db pull` + case-format + `prisma generate` for a datasource, refreshing schema.prisma and the generated Prisma client/Zod types from the live database"
|
|
5457
5755
|
}),
|
|
5458
|
-
(0,
|
|
5756
|
+
(0, import_swagger12.ApiResponse)({
|
|
5459
5757
|
status: 200,
|
|
5460
5758
|
description: "Result of each step, or requiresConfirmation if schema.prisma has uncommitted changes"
|
|
5461
5759
|
}),
|
|
5462
|
-
_ts_param(0, (0,
|
|
5760
|
+
_ts_param(0, (0, import_common17.Body)()),
|
|
5463
5761
|
_ts_metadata4("design:type", Function),
|
|
5464
5762
|
_ts_metadata4("design:paramtypes", [
|
|
5465
5763
|
Object
|
|
@@ -5467,15 +5765,15 @@ _ts_decorate5([
|
|
|
5467
5765
|
_ts_metadata4("design:returntype", Promise)
|
|
5468
5766
|
], DevResourcesController.prototype, "pull", null);
|
|
5469
5767
|
_ts_decorate5([
|
|
5470
|
-
(0,
|
|
5471
|
-
(0,
|
|
5768
|
+
(0, import_common17.Post)("sync"),
|
|
5769
|
+
(0, import_swagger12.ApiOperation)({
|
|
5472
5770
|
summary: "Dev-only: generate or update a single resource.json from its DB model, using recommended defaults (non-interactive)"
|
|
5473
5771
|
}),
|
|
5474
|
-
(0,
|
|
5772
|
+
(0, import_swagger12.ApiResponse)({
|
|
5475
5773
|
status: 200,
|
|
5476
5774
|
description: "Files written for this resource"
|
|
5477
5775
|
}),
|
|
5478
|
-
_ts_param(0, (0,
|
|
5776
|
+
_ts_param(0, (0, import_common17.Body)()),
|
|
5479
5777
|
_ts_metadata4("design:type", Function),
|
|
5480
5778
|
_ts_metadata4("design:paramtypes", [
|
|
5481
5779
|
Object
|
|
@@ -5483,15 +5781,15 @@ _ts_decorate5([
|
|
|
5483
5781
|
_ts_metadata4("design:returntype", Promise)
|
|
5484
5782
|
], DevResourcesController.prototype, "sync", null);
|
|
5485
5783
|
_ts_decorate5([
|
|
5486
|
-
(0,
|
|
5487
|
-
(0,
|
|
5784
|
+
(0, import_common17.Post)("plan"),
|
|
5785
|
+
(0, import_swagger12.ApiOperation)({
|
|
5488
5786
|
summary: "Dev-only: dry-run introspect + diff across all (or selected) DB models using recommended defaults \u2014 computes what would change, writes nothing"
|
|
5489
5787
|
}),
|
|
5490
|
-
(0,
|
|
5788
|
+
(0, import_swagger12.ApiResponse)({
|
|
5491
5789
|
status: 200,
|
|
5492
5790
|
description: "Proposed per-resource changes"
|
|
5493
5791
|
}),
|
|
5494
|
-
_ts_param(0, (0,
|
|
5792
|
+
_ts_param(0, (0, import_common17.Body)()),
|
|
5495
5793
|
_ts_metadata4("design:type", Function),
|
|
5496
5794
|
_ts_metadata4("design:paramtypes", [
|
|
5497
5795
|
Object
|
|
@@ -5499,53 +5797,135 @@ _ts_decorate5([
|
|
|
5499
5797
|
_ts_metadata4("design:returntype", Promise)
|
|
5500
5798
|
], DevResourcesController.prototype, "plan", null);
|
|
5501
5799
|
_ts_decorate5([
|
|
5502
|
-
(0,
|
|
5503
|
-
(0,
|
|
5800
|
+
(0, import_common17.Post)("apply"),
|
|
5801
|
+
(0, import_swagger12.ApiOperation)({
|
|
5504
5802
|
summary: "Dev-only: commit resource.json/schema.ts changes to disk for the given resources (or all, if omitted), using recommended defaults"
|
|
5505
5803
|
}),
|
|
5506
|
-
(0,
|
|
5804
|
+
(0, import_swagger12.ApiResponse)({
|
|
5507
5805
|
status: 200,
|
|
5508
5806
|
description: "Per-resource commit results"
|
|
5509
5807
|
}),
|
|
5510
|
-
_ts_param(0, (0,
|
|
5808
|
+
_ts_param(0, (0, import_common17.Body)()),
|
|
5511
5809
|
_ts_metadata4("design:type", Function),
|
|
5512
5810
|
_ts_metadata4("design:paramtypes", [
|
|
5513
5811
|
Object
|
|
5514
5812
|
]),
|
|
5515
5813
|
_ts_metadata4("design:returntype", Promise)
|
|
5516
5814
|
], DevResourcesController.prototype, "apply", null);
|
|
5815
|
+
_ts_decorate5([
|
|
5816
|
+
(0, import_common17.Get)("visibility"),
|
|
5817
|
+
(0, import_swagger12.ApiOperation)({
|
|
5818
|
+
summary: "Dev-only: list all resources with their menu visibility state (in-menu, hidden, draft, error)"
|
|
5819
|
+
}),
|
|
5820
|
+
(0, import_swagger12.ApiResponse)({
|
|
5821
|
+
status: 200,
|
|
5822
|
+
description: "Resource visibility list"
|
|
5823
|
+
}),
|
|
5824
|
+
_ts_metadata4("design:type", Function),
|
|
5825
|
+
_ts_metadata4("design:paramtypes", []),
|
|
5826
|
+
_ts_metadata4("design:returntype", Promise)
|
|
5827
|
+
], DevResourcesController.prototype, "visibility", null);
|
|
5828
|
+
_ts_decorate5([
|
|
5829
|
+
(0, import_common17.Post)(":name/publish"),
|
|
5830
|
+
(0, import_swagger12.ApiOperation)({
|
|
5831
|
+
summary: "Dev-only: publish a draft resource (removes `draft: true` from resource.json)"
|
|
5832
|
+
}),
|
|
5833
|
+
(0, import_swagger12.ApiResponse)({
|
|
5834
|
+
status: 200,
|
|
5835
|
+
description: "Resource published"
|
|
5836
|
+
}),
|
|
5837
|
+
_ts_param(0, (0, import_common17.Param)("name")),
|
|
5838
|
+
_ts_metadata4("design:type", Function),
|
|
5839
|
+
_ts_metadata4("design:paramtypes", [
|
|
5840
|
+
String
|
|
5841
|
+
]),
|
|
5842
|
+
_ts_metadata4("design:returntype", Promise)
|
|
5843
|
+
], DevResourcesController.prototype, "publish", null);
|
|
5844
|
+
_ts_decorate5([
|
|
5845
|
+
(0, import_common17.Post)(":name/remove-from-menu"),
|
|
5846
|
+
(0, import_swagger12.ApiOperation)({
|
|
5847
|
+
summary: "Dev-only: hide a resource from the sidebar menu (sets `sidebar.hide: true` in resource.json)"
|
|
5848
|
+
}),
|
|
5849
|
+
(0, import_swagger12.ApiResponse)({
|
|
5850
|
+
status: 200,
|
|
5851
|
+
description: "Resource removed from menu"
|
|
5852
|
+
}),
|
|
5853
|
+
_ts_param(0, (0, import_common17.Param)("name")),
|
|
5854
|
+
_ts_metadata4("design:type", Function),
|
|
5855
|
+
_ts_metadata4("design:paramtypes", [
|
|
5856
|
+
String
|
|
5857
|
+
]),
|
|
5858
|
+
_ts_metadata4("design:returntype", Promise)
|
|
5859
|
+
], DevResourcesController.prototype, "removeFromMenu", null);
|
|
5860
|
+
_ts_decorate5([
|
|
5861
|
+
(0, import_common17.Post)(":name/add-to-menu"),
|
|
5862
|
+
(0, import_swagger12.ApiOperation)({
|
|
5863
|
+
summary: "Dev-only: publish + un-hide a resource and optionally set sidebar group/position/label"
|
|
5864
|
+
}),
|
|
5865
|
+
(0, import_swagger12.ApiResponse)({
|
|
5866
|
+
status: 200,
|
|
5867
|
+
description: "Resource added to menu"
|
|
5868
|
+
}),
|
|
5869
|
+
_ts_param(0, (0, import_common17.Param)("name")),
|
|
5870
|
+
_ts_param(1, (0, import_common17.Body)()),
|
|
5871
|
+
_ts_metadata4("design:type", Function),
|
|
5872
|
+
_ts_metadata4("design:paramtypes", [
|
|
5873
|
+
String,
|
|
5874
|
+
Object
|
|
5875
|
+
]),
|
|
5876
|
+
_ts_metadata4("design:returntype", Promise)
|
|
5877
|
+
], DevResourcesController.prototype, "addToMenu", null);
|
|
5878
|
+
_ts_decorate5([
|
|
5879
|
+
(0, import_common17.Patch)(":name/flags"),
|
|
5880
|
+
(0, import_swagger12.ApiOperation)({
|
|
5881
|
+
summary: "Dev-only: set arbitrary resource flags (draft, sidebar.hide, group, position, label)"
|
|
5882
|
+
}),
|
|
5883
|
+
(0, import_swagger12.ApiResponse)({
|
|
5884
|
+
status: 200,
|
|
5885
|
+
description: "Flags updated"
|
|
5886
|
+
}),
|
|
5887
|
+
_ts_param(0, (0, import_common17.Param)("name")),
|
|
5888
|
+
_ts_param(1, (0, import_common17.Body)()),
|
|
5889
|
+
_ts_metadata4("design:type", Function),
|
|
5890
|
+
_ts_metadata4("design:paramtypes", [
|
|
5891
|
+
String,
|
|
5892
|
+
typeof ResourceFlagPatch === "undefined" ? Object : ResourceFlagPatch
|
|
5893
|
+
]),
|
|
5894
|
+
_ts_metadata4("design:returntype", Promise)
|
|
5895
|
+
], DevResourcesController.prototype, "updateFlags", null);
|
|
5517
5896
|
DevResourcesController = _ts_decorate5([
|
|
5518
|
-
(0,
|
|
5519
|
-
(0,
|
|
5897
|
+
(0, import_common17.Controller)("_app/resources"),
|
|
5898
|
+
(0, import_swagger12.ApiTags)("Dev tools"),
|
|
5520
5899
|
_ts_metadata4("design:type", Function),
|
|
5521
5900
|
_ts_metadata4("design:paramtypes", [
|
|
5522
|
-
typeof DataSourceRegistry === "undefined" ? Object : DataSourceRegistry
|
|
5901
|
+
typeof DataSourceRegistry === "undefined" ? Object : DataSourceRegistry,
|
|
5902
|
+
typeof ResourceConfigRegistry === "undefined" ? Object : ResourceConfigRegistry
|
|
5523
5903
|
])
|
|
5524
5904
|
], DevResourcesController);
|
|
5525
5905
|
|
|
5526
5906
|
// src/lib/crud/enum-registry/enum-registry.types.ts
|
|
5527
|
-
var
|
|
5528
|
-
var EnumEntrySchema =
|
|
5529
|
-
value:
|
|
5530
|
-
label:
|
|
5907
|
+
var import_zod25 = require("zod");
|
|
5908
|
+
var EnumEntrySchema = import_zod25.z.object({
|
|
5909
|
+
value: import_zod25.z.unknown(),
|
|
5910
|
+
label: import_zod25.z.string()
|
|
5531
5911
|
});
|
|
5532
|
-
var EnumRegistrySchema =
|
|
5912
|
+
var EnumRegistrySchema = import_zod25.z.record(import_zod25.z.string(), import_zod25.z.array(EnumEntrySchema)).default({});
|
|
5533
5913
|
|
|
5534
5914
|
// src/lib/crud/enum-registry/enum-registry.loader.ts
|
|
5535
5915
|
var import_node_fs5 = require("fs");
|
|
5536
|
-
var
|
|
5916
|
+
var import_node_path13 = require("path");
|
|
5537
5917
|
var ENUMS_FILE = "crouton.enums.json";
|
|
5538
5918
|
var loadEnumRegistry = /* @__PURE__ */ __name((startDir, enumsFile) => {
|
|
5539
5919
|
let file = enumsFile;
|
|
5540
5920
|
if (!file) {
|
|
5541
5921
|
let dir = startDir;
|
|
5542
5922
|
while (true) {
|
|
5543
|
-
const candidate = (0,
|
|
5923
|
+
const candidate = (0, import_node_path13.join)(dir, ENUMS_FILE);
|
|
5544
5924
|
if ((0, import_node_fs5.existsSync)(candidate)) {
|
|
5545
5925
|
file = candidate;
|
|
5546
5926
|
break;
|
|
5547
5927
|
}
|
|
5548
|
-
const parent = (0,
|
|
5928
|
+
const parent = (0, import_node_path13.dirname)(dir);
|
|
5549
5929
|
if (parent === dir) break;
|
|
5550
5930
|
dir = parent;
|
|
5551
5931
|
}
|
|
@@ -5574,10 +5954,46 @@ var injectEnumValues = /* @__PURE__ */ __name((columns, enums) => {
|
|
|
5574
5954
|
}
|
|
5575
5955
|
}, "injectEnumValues");
|
|
5576
5956
|
|
|
5957
|
+
// src/lib/crud/builder/schema.helpers.ts
|
|
5958
|
+
var pickByColumns = /* @__PURE__ */ __name((schema, columns, filter) => {
|
|
5959
|
+
if (!schema) return void 0;
|
|
5960
|
+
if (!columns?.length) return schema;
|
|
5961
|
+
const baseFilter = /* @__PURE__ */ __name((c) => !isRelation(c) && (filter ? filter(c) : true), "baseFilter");
|
|
5962
|
+
const schemaKeys = new Set(Object.keys(schema.shape));
|
|
5963
|
+
const filtered = columns.filter((c) => baseFilter(c) && schemaKeys.has(c.id));
|
|
5964
|
+
if (!filtered.length) return void 0;
|
|
5965
|
+
const mask = Object.fromEntries(filtered.map((c) => [
|
|
5966
|
+
c.id,
|
|
5967
|
+
true
|
|
5968
|
+
]));
|
|
5969
|
+
return schema.pick(mask);
|
|
5970
|
+
}, "pickByColumns");
|
|
5971
|
+
var opWithSchema = /* @__PURE__ */ __name((enabled, schema) => {
|
|
5972
|
+
if (enabled === false) return void 0;
|
|
5973
|
+
return schema ? {
|
|
5974
|
+
schema
|
|
5975
|
+
} : true;
|
|
5976
|
+
}, "opWithSchema");
|
|
5977
|
+
var upsertOp = /* @__PURE__ */ __name((entry, schema) => {
|
|
5978
|
+
if (!entry) return void 0;
|
|
5979
|
+
if (entry === true) {
|
|
5980
|
+
throw new Error("`operations.upsert` must be an object with `upsertOn`, not `true`.");
|
|
5981
|
+
}
|
|
5982
|
+
if (typeof entry === "object") {
|
|
5983
|
+
return {
|
|
5984
|
+
upsertOn: entry.upsertOn,
|
|
5985
|
+
...schema && {
|
|
5986
|
+
schema
|
|
5987
|
+
}
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
return void 0;
|
|
5991
|
+
}, "upsertOp");
|
|
5992
|
+
|
|
5577
5993
|
// src/lib/crud/adapter/relation-type.ts
|
|
5578
|
-
var
|
|
5994
|
+
var import_zod26 = require("zod");
|
|
5579
5995
|
var unwrapZodType = /* @__PURE__ */ __name((type) => {
|
|
5580
|
-
if (type instanceof
|
|
5996
|
+
if (type instanceof import_zod26.ZodOptional || type instanceof import_zod26.ZodNullable) {
|
|
5581
5997
|
return unwrapZodType(type.unwrap());
|
|
5582
5998
|
}
|
|
5583
5999
|
return type;
|
|
@@ -5587,7 +6003,7 @@ var deriveRelationType = /* @__PURE__ */ __name((schema, columnId) => {
|
|
|
5587
6003
|
const field = schema.shape[columnId];
|
|
5588
6004
|
if (!field) return void 0;
|
|
5589
6005
|
const inner = unwrapZodType(field);
|
|
5590
|
-
return inner instanceof
|
|
6006
|
+
return inner instanceof import_zod26.ZodArray ? "oneToMany" : "manyToOne";
|
|
5591
6007
|
}, "deriveRelationType");
|
|
5592
6008
|
var deriveRelationTypeFromColumns = /* @__PURE__ */ __name((col, cols) => {
|
|
5593
6009
|
const base = col.column ?? col.id;
|
|
@@ -5619,7 +6035,7 @@ var enrichRelationTypes = /* @__PURE__ */ __name((columns, schema) => {
|
|
|
5619
6035
|
|
|
5620
6036
|
// src/lib/crud/resource/ReadResourceJson.ts
|
|
5621
6037
|
var import_node_fs6 = require("fs");
|
|
5622
|
-
var
|
|
6038
|
+
var import_node_path14 = require("path");
|
|
5623
6039
|
var readResourceJson = /* @__PURE__ */ __name((jsonPath) => {
|
|
5624
6040
|
if (!(0, import_node_fs6.existsSync)(jsonPath)) return void 0;
|
|
5625
6041
|
let fileContent;
|
|
@@ -5642,26 +6058,26 @@ var readResourceJson = /* @__PURE__ */ __name((jsonPath) => {
|
|
|
5642
6058
|
success: true,
|
|
5643
6059
|
data: {
|
|
5644
6060
|
json: resource.data,
|
|
5645
|
-
dir: (0,
|
|
6061
|
+
dir: (0, import_node_path14.dirname)(jsonPath)
|
|
5646
6062
|
}
|
|
5647
6063
|
};
|
|
5648
6064
|
}, "readResourceJson");
|
|
5649
6065
|
|
|
5650
6066
|
// src/lib/crud/adapter/resource-resolver.ts
|
|
5651
6067
|
var import_node_fs7 = require("fs");
|
|
5652
|
-
var
|
|
6068
|
+
var import_node_path15 = require("path");
|
|
5653
6069
|
var unwrap2 = /* @__PURE__ */ __name((result) => {
|
|
5654
6070
|
if (result?.success) return result.data;
|
|
5655
6071
|
return void 0;
|
|
5656
6072
|
}, "unwrap");
|
|
5657
6073
|
var resolveChildResource = /* @__PURE__ */ __name((resourcePath, parentDir) => {
|
|
5658
|
-
const directPath = (0,
|
|
6074
|
+
const directPath = (0, import_node_path15.resolve)(parentDir, resourcePath);
|
|
5659
6075
|
try {
|
|
5660
6076
|
if (resourcePath.endsWith(".json") && (0, import_node_fs7.existsSync)(directPath)) {
|
|
5661
6077
|
return unwrap2(readResourceJson(directPath));
|
|
5662
6078
|
}
|
|
5663
6079
|
const childName = resourcePath.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
5664
|
-
const childJsonPath = (0,
|
|
6080
|
+
const childJsonPath = (0, import_node_path15.resolve)((0, import_node_path15.dirname)(parentDir), childName, "resource.json");
|
|
5665
6081
|
return unwrap2(readResourceJson(childJsonPath));
|
|
5666
6082
|
} catch {
|
|
5667
6083
|
return void 0;
|
|
@@ -5875,7 +6291,7 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
|
|
|
5875
6291
|
const childOps = childJson?.operations ?? {};
|
|
5876
6292
|
return {
|
|
5877
6293
|
column: c.id,
|
|
5878
|
-
relation: c.id,
|
|
6294
|
+
relation: c.fieldInput?.relation ?? c.id,
|
|
5879
6295
|
childRoute,
|
|
5880
6296
|
childModel: c.id,
|
|
5881
6297
|
foreignKey: c.fieldInput?.foreignKey ?? `${parentModel}Id`,
|
|
@@ -5908,7 +6324,14 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
|
|
|
5908
6324
|
calculatedColumns: childJson.calculatedColumns
|
|
5909
6325
|
},
|
|
5910
6326
|
...(c.hiddenInForm === false || c.hiddenInView === false) && {
|
|
5911
|
-
includeInFindOne: true
|
|
6327
|
+
includeInFindOne: true,
|
|
6328
|
+
...(() => {
|
|
6329
|
+
const opts = c.fieldInput?.options;
|
|
6330
|
+
if (opts?.sort) return {
|
|
6331
|
+
findOneOrderBy: buildChildSortClause(opts.sort, opts.sortDir)
|
|
6332
|
+
};
|
|
6333
|
+
return {};
|
|
6334
|
+
})()
|
|
5912
6335
|
},
|
|
5913
6336
|
...buildValueLabelColumns(childColumns).length && {
|
|
5914
6337
|
valueLabelColumns: buildValueLabelColumns(childColumns)
|
|
@@ -6031,33 +6454,33 @@ var buildLookup = /* @__PURE__ */ __name((columns) => {
|
|
|
6031
6454
|
}, "buildLookup");
|
|
6032
6455
|
|
|
6033
6456
|
// src/lib/crud/hooks/hooks.types.ts
|
|
6034
|
-
var
|
|
6035
|
-
var WriteOpSchema =
|
|
6457
|
+
var import_zod27 = require("zod");
|
|
6458
|
+
var WriteOpSchema = import_zod27.z.enum([
|
|
6036
6459
|
"create",
|
|
6037
6460
|
"update",
|
|
6038
6461
|
"patch",
|
|
6039
6462
|
"upsert",
|
|
6040
6463
|
"delete"
|
|
6041
6464
|
]);
|
|
6042
|
-
var ReadOpSchema =
|
|
6465
|
+
var ReadOpSchema = import_zod27.z.enum([
|
|
6043
6466
|
"findAll",
|
|
6044
6467
|
"findOne"
|
|
6045
6468
|
]);
|
|
6046
|
-
var ResourceHooksSchema =
|
|
6047
|
-
beforeWrite:
|
|
6048
|
-
afterWrite:
|
|
6049
|
-
afterRead:
|
|
6469
|
+
var ResourceHooksSchema = import_zod27.z.object({
|
|
6470
|
+
beforeWrite: import_zod27.z.custom().optional(),
|
|
6471
|
+
afterWrite: import_zod27.z.custom().optional(),
|
|
6472
|
+
afterRead: import_zod27.z.custom().optional()
|
|
6050
6473
|
});
|
|
6051
6474
|
|
|
6052
6475
|
// src/lib/crud/hooks/hooks.loader.ts
|
|
6053
|
-
var
|
|
6476
|
+
var import_node_path16 = require("path");
|
|
6054
6477
|
var loadResourceHooks = /* @__PURE__ */ __name(async (basePath) => {
|
|
6055
6478
|
const file = findModule(basePath, "hooks");
|
|
6056
6479
|
return file ? importDefault(file) : void 0;
|
|
6057
6480
|
}, "loadResourceHooks");
|
|
6058
6481
|
var loadSubResourceHooks = /* @__PURE__ */ __name(async (subResources, basePath) => {
|
|
6059
6482
|
for (const sub of subResources) {
|
|
6060
|
-
const file = sub.name ? findModule((0,
|
|
6483
|
+
const file = sub.name ? findModule((0, import_node_path16.join)(basePath, "hooks"), sub.name) : void 0;
|
|
6061
6484
|
if (!file) continue;
|
|
6062
6485
|
const hooks = await importDefault(file);
|
|
6063
6486
|
if (hooks) sub.hooks = hooks;
|
|
@@ -6124,32 +6547,9 @@ var migrateResourceJsonFile = /* @__PURE__ */ __name((jsonPath, opts) => {
|
|
|
6124
6547
|
}
|
|
6125
6548
|
}, "migrateResourceJsonFile");
|
|
6126
6549
|
|
|
6127
|
-
// src/lib/crud/resource/resource-load-report.registry.ts
|
|
6128
|
-
var ResourceLoadReportRegistry = class ResourceLoadReportRegistry2 {
|
|
6129
|
-
static {
|
|
6130
|
-
__name(this, "ResourceLoadReportRegistry");
|
|
6131
|
-
}
|
|
6132
|
-
notices = [];
|
|
6133
|
-
record(n) {
|
|
6134
|
-
this.notices.push(n);
|
|
6135
|
-
}
|
|
6136
|
-
getAll() {
|
|
6137
|
-
return [
|
|
6138
|
-
...this.notices
|
|
6139
|
-
];
|
|
6140
|
-
}
|
|
6141
|
-
getByState(state) {
|
|
6142
|
-
return this.notices.filter((n) => n.state === state);
|
|
6143
|
-
}
|
|
6144
|
-
clear() {
|
|
6145
|
-
this.notices = [];
|
|
6146
|
-
}
|
|
6147
|
-
};
|
|
6148
|
-
var resourceLoadReportRegistry = new ResourceLoadReportRegistry();
|
|
6149
|
-
|
|
6150
6550
|
// src/lib/crud/loader/index.ts
|
|
6151
6551
|
var import_node_fs9 = require("fs");
|
|
6152
|
-
var
|
|
6552
|
+
var import_node_path17 = require("path");
|
|
6153
6553
|
var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl, enumsFile, onResourceDir) => {
|
|
6154
6554
|
if (!(0, import_node_fs9.existsSync)(dirPath)) return [];
|
|
6155
6555
|
resourceLoadErrorsRegistry.clear();
|
|
@@ -6161,11 +6561,11 @@ var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl,
|
|
|
6161
6561
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
6162
6562
|
const configs = [];
|
|
6163
6563
|
for (const dir of dirs) {
|
|
6164
|
-
const basePath = (0,
|
|
6564
|
+
const basePath = (0, import_node_path17.join)(dirPath, dir);
|
|
6165
6565
|
const schemaFile = findModule(basePath, "schema");
|
|
6166
6566
|
const schema = schemaFile ? await importDefault(schemaFile) : void 0;
|
|
6167
6567
|
const hooks = await loadResourceHooks(basePath);
|
|
6168
|
-
const jsonFile = (0,
|
|
6568
|
+
const jsonFile = (0, import_node_path17.join)(basePath, "resource.json");
|
|
6169
6569
|
if ((0, import_node_fs9.existsSync)(jsonFile)) {
|
|
6170
6570
|
const migration = migrateResourceJsonFile(jsonFile, {
|
|
6171
6571
|
isDev: IS_DEV
|
|
@@ -6284,22 +6684,22 @@ var FileSystemResourceConfigLoader = class extends ResourceConfigLoader2 {
|
|
|
6284
6684
|
|
|
6285
6685
|
// src/lib/crud/status/status.service.ts
|
|
6286
6686
|
var import_node_fs10 = require("fs");
|
|
6287
|
-
var
|
|
6687
|
+
var import_node_path18 = require("path");
|
|
6288
6688
|
var import_node_url = require("url");
|
|
6289
6689
|
var DB_CHECK_TIMEOUT_MS = 3e3;
|
|
6290
6690
|
var CONNECTION_STRING_PATTERN = /(?:postgresql|postgres|mysql|mongodb|sqlserver|sqlite):\/\/[^\s"')]+/gi;
|
|
6291
6691
|
var stripConnectionStrings = /* @__PURE__ */ __name((message) => message.replace(CONNECTION_STRING_PATTERN, "[REDACTED]"), "stripConnectionStrings");
|
|
6292
6692
|
var getCroutonVersion = /* @__PURE__ */ __name(() => {
|
|
6293
6693
|
try {
|
|
6294
|
-
const startDir = typeof __dirname !== "undefined" ? __dirname : (0,
|
|
6694
|
+
const startDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path18.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
6295
6695
|
let dir = startDir;
|
|
6296
|
-
while (dir !== (0,
|
|
6297
|
-
const pkgPath = (0,
|
|
6696
|
+
while (dir !== (0, import_node_path18.dirname)(dir)) {
|
|
6697
|
+
const pkgPath = (0, import_node_path18.join)(dir, "package.json");
|
|
6298
6698
|
if ((0, import_node_fs10.existsSync)(pkgPath)) {
|
|
6299
6699
|
const pkg = JSON.parse((0, import_node_fs10.readFileSync)(pkgPath, "utf-8"));
|
|
6300
6700
|
if (pkg.name === "@ghentcdh/crouton-api") return pkg.version;
|
|
6301
6701
|
}
|
|
6302
|
-
dir = (0,
|
|
6702
|
+
dir = (0, import_node_path18.dirname)(dir);
|
|
6303
6703
|
}
|
|
6304
6704
|
} catch {
|
|
6305
6705
|
}
|
|
@@ -6335,7 +6735,10 @@ var getResourceStatus = /* @__PURE__ */ __name((loadedConfigs) => {
|
|
|
6335
6735
|
name: c.name,
|
|
6336
6736
|
path: c.route,
|
|
6337
6737
|
valid: true,
|
|
6338
|
-
version: c.schemaVersion ?? CURRENT_RESOURCE_VERSION
|
|
6738
|
+
version: c.schemaVersion ?? CURRENT_RESOURCE_VERSION,
|
|
6739
|
+
...c.sidebar?.hide ? {
|
|
6740
|
+
hidden: true
|
|
6741
|
+
} : {}
|
|
6339
6742
|
}));
|
|
6340
6743
|
const failed = resourceLoadErrorsRegistry.getAll().map((e) => ({
|
|
6341
6744
|
name: e.name,
|
|
@@ -6367,7 +6770,114 @@ var buildSummary = /* @__PURE__ */ __name((databases, resources) => {
|
|
|
6367
6770
|
resourceErrors
|
|
6368
6771
|
};
|
|
6369
6772
|
}, "buildSummary");
|
|
6370
|
-
var
|
|
6773
|
+
var getSystemEnums = /* @__PURE__ */ __name(() => {
|
|
6774
|
+
return [
|
|
6775
|
+
{
|
|
6776
|
+
name: "RelationType",
|
|
6777
|
+
category: "Relationships",
|
|
6778
|
+
values: [
|
|
6779
|
+
{
|
|
6780
|
+
value: "oneToOne",
|
|
6781
|
+
label: "One to One"
|
|
6782
|
+
},
|
|
6783
|
+
{
|
|
6784
|
+
value: "manyToOne",
|
|
6785
|
+
label: "Many to One"
|
|
6786
|
+
},
|
|
6787
|
+
{
|
|
6788
|
+
value: "oneToMany",
|
|
6789
|
+
label: "One to Many"
|
|
6790
|
+
},
|
|
6791
|
+
{
|
|
6792
|
+
value: "manyToMany",
|
|
6793
|
+
label: "Many to Many"
|
|
6794
|
+
}
|
|
6795
|
+
]
|
|
6796
|
+
},
|
|
6797
|
+
{
|
|
6798
|
+
name: "DetailLayout",
|
|
6799
|
+
category: "Layout",
|
|
6800
|
+
values: [
|
|
6801
|
+
{
|
|
6802
|
+
value: "collapse",
|
|
6803
|
+
label: "Collapse"
|
|
6804
|
+
},
|
|
6805
|
+
{
|
|
6806
|
+
value: "row",
|
|
6807
|
+
label: "Row"
|
|
6808
|
+
}
|
|
6809
|
+
]
|
|
6810
|
+
},
|
|
6811
|
+
{
|
|
6812
|
+
name: "SortDirection",
|
|
6813
|
+
category: "Sorting",
|
|
6814
|
+
values: [
|
|
6815
|
+
{
|
|
6816
|
+
value: "asc",
|
|
6817
|
+
label: "Ascending"
|
|
6818
|
+
},
|
|
6819
|
+
{
|
|
6820
|
+
value: "desc",
|
|
6821
|
+
label: "Descending"
|
|
6822
|
+
}
|
|
6823
|
+
]
|
|
6824
|
+
},
|
|
6825
|
+
{
|
|
6826
|
+
name: "DisplayMode",
|
|
6827
|
+
category: "Display",
|
|
6828
|
+
values: [
|
|
6829
|
+
{
|
|
6830
|
+
value: "page",
|
|
6831
|
+
label: "Page"
|
|
6832
|
+
},
|
|
6833
|
+
{
|
|
6834
|
+
value: "modal",
|
|
6835
|
+
label: "Modal"
|
|
6836
|
+
}
|
|
6837
|
+
]
|
|
6838
|
+
},
|
|
6839
|
+
{
|
|
6840
|
+
name: "ModalSize",
|
|
6841
|
+
category: "Display",
|
|
6842
|
+
values: [
|
|
6843
|
+
{
|
|
6844
|
+
value: "xs",
|
|
6845
|
+
label: "Extra Small"
|
|
6846
|
+
},
|
|
6847
|
+
{
|
|
6848
|
+
value: "sm",
|
|
6849
|
+
label: "Small"
|
|
6850
|
+
},
|
|
6851
|
+
{
|
|
6852
|
+
value: "lg",
|
|
6853
|
+
label: "Large"
|
|
6854
|
+
},
|
|
6855
|
+
{
|
|
6856
|
+
value: "xl",
|
|
6857
|
+
label: "Extra Large"
|
|
6858
|
+
}
|
|
6859
|
+
]
|
|
6860
|
+
}
|
|
6861
|
+
];
|
|
6862
|
+
}, "getSystemEnums");
|
|
6863
|
+
var getProjectEnums = /* @__PURE__ */ __name((enumRegistry) => {
|
|
6864
|
+
if (!enumRegistry) return [];
|
|
6865
|
+
return Object.entries(enumRegistry).map(([name, entries]) => ({
|
|
6866
|
+
name,
|
|
6867
|
+
category: "Project",
|
|
6868
|
+
values: entries.map((entry) => ({
|
|
6869
|
+
value: entry.value,
|
|
6870
|
+
label: entry.label
|
|
6871
|
+
}))
|
|
6872
|
+
}));
|
|
6873
|
+
}, "getProjectEnums");
|
|
6874
|
+
var getEnums = /* @__PURE__ */ __name((enumRegistry) => {
|
|
6875
|
+
return {
|
|
6876
|
+
system: getSystemEnums(),
|
|
6877
|
+
project: getProjectEnums(enumRegistry)
|
|
6878
|
+
};
|
|
6879
|
+
}, "getEnums");
|
|
6880
|
+
var buildStatus = /* @__PURE__ */ __name(async (registry, loadedConfigs, enumRegistry) => {
|
|
6371
6881
|
const databases = await checkDatabases(registry);
|
|
6372
6882
|
const resources = getResourceStatus(loadedConfigs);
|
|
6373
6883
|
const summary = buildSummary(databases, resources);
|
|
@@ -6377,13 +6887,14 @@ var buildStatus = /* @__PURE__ */ __name(async (registry, loadedConfigs) => {
|
|
|
6377
6887
|
environment: getEnvironment(),
|
|
6378
6888
|
summary,
|
|
6379
6889
|
databases,
|
|
6380
|
-
resources
|
|
6890
|
+
resources,
|
|
6891
|
+
enums: getEnums(enumRegistry)
|
|
6381
6892
|
};
|
|
6382
6893
|
}, "buildStatus");
|
|
6383
6894
|
|
|
6384
6895
|
// src/lib/crud/status/status.controller.ts
|
|
6385
|
-
var
|
|
6386
|
-
var
|
|
6896
|
+
var import_common18 = require("@nestjs/common");
|
|
6897
|
+
var import_swagger13 = require("@nestjs/swagger");
|
|
6387
6898
|
function _ts_decorate6(decorators, target, key, desc2) {
|
|
6388
6899
|
var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
|
|
6389
6900
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
|
|
@@ -6395,7 +6906,7 @@ function _ts_metadata5(k, v) {
|
|
|
6395
6906
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
6396
6907
|
}
|
|
6397
6908
|
__name(_ts_metadata5, "_ts_metadata");
|
|
6398
|
-
var createStatusController = /* @__PURE__ */ __name(() => {
|
|
6909
|
+
var createStatusController = /* @__PURE__ */ __name((enumRegistry) => {
|
|
6399
6910
|
let StatusController = class StatusController {
|
|
6400
6911
|
static {
|
|
6401
6912
|
__name(this, "StatusController");
|
|
@@ -6408,15 +6919,15 @@ var createStatusController = /* @__PURE__ */ __name(() => {
|
|
|
6408
6919
|
}
|
|
6409
6920
|
async getStatus() {
|
|
6410
6921
|
const configs = await this.configRegistry.getAll();
|
|
6411
|
-
return buildStatus(this.dataSourceRegistry, configs);
|
|
6922
|
+
return buildStatus(this.dataSourceRegistry, configs, enumRegistry);
|
|
6412
6923
|
}
|
|
6413
6924
|
};
|
|
6414
6925
|
_ts_decorate6([
|
|
6415
|
-
(0,
|
|
6416
|
-
(0,
|
|
6926
|
+
(0, import_common18.Get)("status.json"),
|
|
6927
|
+
(0, import_swagger13.ApiOperation)({
|
|
6417
6928
|
summary: "Crouton system status (db, resources, version)"
|
|
6418
6929
|
}),
|
|
6419
|
-
(0,
|
|
6930
|
+
(0, import_swagger13.ApiResponse)({
|
|
6420
6931
|
status: 200,
|
|
6421
6932
|
description: "System status"
|
|
6422
6933
|
}),
|
|
@@ -6425,8 +6936,8 @@ var createStatusController = /* @__PURE__ */ __name(() => {
|
|
|
6425
6936
|
_ts_metadata5("design:returntype", Promise)
|
|
6426
6937
|
], StatusController.prototype, "getStatus", null);
|
|
6427
6938
|
StatusController = _ts_decorate6([
|
|
6428
|
-
(0,
|
|
6429
|
-
(0,
|
|
6939
|
+
(0, import_common18.Controller)("crouton"),
|
|
6940
|
+
(0, import_swagger13.ApiTags)("Status"),
|
|
6430
6941
|
_ts_metadata5("design:type", Function),
|
|
6431
6942
|
_ts_metadata5("design:paramtypes", [
|
|
6432
6943
|
typeof DataSourceRegistry === "undefined" ? Object : DataSourceRegistry,
|
|
@@ -6441,6 +6952,8 @@ var createStatusController = /* @__PURE__ */ __name(() => {
|
|
|
6441
6952
|
}, "createStatusController");
|
|
6442
6953
|
|
|
6443
6954
|
// src/lib/crouton-api.module.ts
|
|
6955
|
+
var import_node_path19 = require("path");
|
|
6956
|
+
var import_node_url2 = require("url");
|
|
6444
6957
|
function _ts_decorate7(decorators, target, key, desc2) {
|
|
6445
6958
|
var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
|
|
6446
6959
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
|
|
@@ -6461,6 +6974,8 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
6461
6974
|
}
|
|
6462
6975
|
static forResources(configs, dataSources, loader, { baseUrl }, config) {
|
|
6463
6976
|
const dataSourceRegistry = new DataSourceRegistry(dataSources);
|
|
6977
|
+
const startDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path19.dirname)((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
6978
|
+
const enumRegistry = loadEnumRegistry(startDir, config.enumsFile);
|
|
6464
6979
|
const validConfigs = [];
|
|
6465
6980
|
for (const c of configs) {
|
|
6466
6981
|
try {
|
|
@@ -6492,7 +7007,7 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
6492
7007
|
...IS_DEV ? [
|
|
6493
7008
|
DevResourcesController
|
|
6494
7009
|
] : [],
|
|
6495
|
-
createStatusController()
|
|
7010
|
+
createStatusController(enumRegistry)
|
|
6496
7011
|
];
|
|
6497
7012
|
return {
|
|
6498
7013
|
module: _CroutonApiModule,
|
|
@@ -6528,7 +7043,7 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
6528
7043
|
}
|
|
6529
7044
|
};
|
|
6530
7045
|
CroutonApiModule = _ts_decorate7([
|
|
6531
|
-
(0,
|
|
7046
|
+
(0, import_common19.Module)({
|
|
6532
7047
|
controllers: [],
|
|
6533
7048
|
providers: [],
|
|
6534
7049
|
exports: []
|