@jskit-ai/crud-ui-generator 0.1.84 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.descriptor.mjs +2 -2
- package/package.json +4 -4
- package/src/server/buildTemplateContext.js +3 -3
- package/src/server/resourceSupport.js +11 -9
- package/src/server/subcommands/addField.js +128 -4
- package/templates/src/pages/admin/ui-generator/AddEditFormFields.js +6 -6
- package/templates/src/pages/admin/ui-generator/EditElement.vue +3 -3
- package/templates/src/pages/admin/ui-generator/NewElement.vue +3 -3
- package/test/addFieldSubcommand.test.js +61 -14
package/package.descriptor.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { GENERATED_UI_NAVIGATION_ROLE_OPTION } from "@jskit-ai/kernel/shared/sup
|
|
|
3
3
|
export default Object.freeze({
|
|
4
4
|
packageVersion: 1,
|
|
5
5
|
packageId: "@jskit-ai/crud-ui-generator",
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.86",
|
|
7
7
|
kind: "generator",
|
|
8
8
|
description: "Generate CRUD route trees from resource validators at an explicit route root relative to src/pages/.",
|
|
9
9
|
options: {
|
|
@@ -175,7 +175,7 @@ export default Object.freeze({
|
|
|
175
175
|
mutations: {
|
|
176
176
|
dependencies: {
|
|
177
177
|
runtime: {
|
|
178
|
-
"@jskit-ai/users-web": "0.1.
|
|
178
|
+
"@jskit-ai/users-web": "0.1.118"
|
|
179
179
|
},
|
|
180
180
|
dev: {}
|
|
181
181
|
},
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/crud-ui-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.86",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@jskit-ai/crud-core": "0.1.
|
|
10
|
-
"@jskit-ai/kernel": "0.1.
|
|
11
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
9
|
+
"@jskit-ai/crud-core": "0.1.111",
|
|
10
|
+
"@jskit-ai/kernel": "0.1.104",
|
|
11
|
+
"@jskit-ai/resource-crud-core": "0.1.48"
|
|
12
12
|
},
|
|
13
13
|
"exports": {
|
|
14
14
|
"./server/buildTemplateContext": "./src/server/buildTemplateContext.js"
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
buildViewColumns,
|
|
31
31
|
buildFormColumns,
|
|
32
32
|
resolveRecordIdFieldKey,
|
|
33
|
-
|
|
33
|
+
renderObjectArrayEntryLines,
|
|
34
34
|
resolveRecordChangedEventName,
|
|
35
35
|
resolveRecordIdExpression
|
|
36
36
|
} from "./resourceSupport.js";
|
|
@@ -864,8 +864,8 @@ async function buildUiTemplateContext({ appRoot, options } = {}) {
|
|
|
864
864
|
__JSKIT_UI_SHARED_FORM_SLOT_PROPS__: buildCrudFieldsSlotProps(sharedFormFields, { includeMode: true }),
|
|
865
865
|
__JSKIT_UI_CREATE_FORM_FIELDS__: JSON.stringify(createFields),
|
|
866
866
|
__JSKIT_UI_EDIT_FORM_FIELDS__: JSON.stringify(editFields),
|
|
867
|
-
|
|
868
|
-
|
|
867
|
+
__JSKIT_UI_CREATE_FORM_FIELD_ARRAY_ENTRIES__: renderObjectArrayEntryLines(createFields),
|
|
868
|
+
__JSKIT_UI_EDIT_FORM_FIELD_ARRAY_ENTRIES__: renderObjectArrayEntryLines(editFields),
|
|
869
869
|
__JSKIT_UI_CREATE_LOOKUP_IMPORT_LINE__: buildLookupImportLine(createFields),
|
|
870
870
|
__JSKIT_UI_EDIT_LOOKUP_IMPORT_LINE__: buildLookupImportLine(editFields),
|
|
871
871
|
__JSKIT_UI_CREATE_LOOKUP_RUNTIME_SETUP__: buildLookupRuntimeSetup(createFields, {
|
|
@@ -18,6 +18,7 @@ import { normalizeSurfaceId } from "@jskit-ai/kernel/shared/surface/registry";
|
|
|
18
18
|
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
19
19
|
|
|
20
20
|
const JS_IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
21
|
+
const JS_IDENTIFIER_PROPERTY_PATTERN = /^(\s*)"([A-Za-z_$][A-Za-z0-9_$]*)":/gm;
|
|
21
22
|
const JSON_REST_TRANSPORT_EXTENSION_KEY = "x-json-rest-schema";
|
|
22
23
|
|
|
23
24
|
function requireOption(options, optionName, { context = "ui-generator" } = {}) {
|
|
@@ -1045,21 +1046,22 @@ function resolveRecordIdFieldKey(fields = []) {
|
|
|
1045
1046
|
return normalizeText(preferred?.key) || "id";
|
|
1046
1047
|
}
|
|
1047
1048
|
|
|
1048
|
-
function
|
|
1049
|
-
const
|
|
1050
|
-
if (!normalizedArrayName) {
|
|
1051
|
-
return "";
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1049
|
+
function renderObjectArrayEntryLines(entries = [], { indent = " " } = {}) {
|
|
1050
|
+
const entryIndent = String(indent || "");
|
|
1054
1051
|
const lines = [];
|
|
1055
1052
|
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
1056
1053
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
1057
1054
|
continue;
|
|
1058
1055
|
}
|
|
1059
|
-
|
|
1056
|
+
const entrySource = JSON.stringify(entry, null, 2)
|
|
1057
|
+
.replace(JS_IDENTIFIER_PROPERTY_PATTERN, "$1$2:")
|
|
1058
|
+
.split("\n")
|
|
1059
|
+
.map((line) => `${entryIndent}${line}`)
|
|
1060
|
+
.join("\n");
|
|
1061
|
+
lines.push(`${entrySource},`);
|
|
1060
1062
|
}
|
|
1061
1063
|
|
|
1062
|
-
return lines.join("\n\n"
|
|
1064
|
+
return lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
1063
1065
|
}
|
|
1064
1066
|
|
|
1065
1067
|
function resolveRecordIdExpression(fields = []) {
|
|
@@ -1088,7 +1090,7 @@ export {
|
|
|
1088
1090
|
buildViewColumns,
|
|
1089
1091
|
buildFormColumns,
|
|
1090
1092
|
resolveRecordIdFieldKey,
|
|
1091
|
-
|
|
1093
|
+
renderObjectArrayEntryLines,
|
|
1092
1094
|
resolveCrudRecordChangedEvent as resolveRecordChangedEventName,
|
|
1093
1095
|
resolveRecordIdExpression
|
|
1094
1096
|
};
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
buildListRowColumns,
|
|
17
17
|
buildViewColumns,
|
|
18
18
|
buildFormColumns,
|
|
19
|
-
|
|
19
|
+
renderObjectArrayEntryLines
|
|
20
20
|
} from "../resourceSupport.js";
|
|
21
21
|
|
|
22
22
|
const SUPPORTED_OPERATIONS = new Set(["list", "view", "new", "edit"]);
|
|
@@ -217,6 +217,126 @@ function insertBeforeAnchor(source, { anchor = "", snippet = "" } = {}) {
|
|
|
217
217
|
};
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
function findMatchingDelimiter(sourceText = "", openIndex = -1, openChar = "[", closeChar = "]") {
|
|
221
|
+
const source = String(sourceText || "");
|
|
222
|
+
if (openIndex < 0 || source[openIndex] !== openChar) {
|
|
223
|
+
return -1;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let depth = 0;
|
|
227
|
+
let quote = "";
|
|
228
|
+
let inLineComment = false;
|
|
229
|
+
let inBlockComment = false;
|
|
230
|
+
for (let index = openIndex; index < source.length; index += 1) {
|
|
231
|
+
const char = source[index];
|
|
232
|
+
const nextChar = source[index + 1] || "";
|
|
233
|
+
const previousChar = source[index - 1] || "";
|
|
234
|
+
|
|
235
|
+
if (inLineComment) {
|
|
236
|
+
if (char === "\n") {
|
|
237
|
+
inLineComment = false;
|
|
238
|
+
}
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (inBlockComment) {
|
|
242
|
+
if (char === "*" && nextChar === "/") {
|
|
243
|
+
inBlockComment = false;
|
|
244
|
+
index += 1;
|
|
245
|
+
}
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (quote) {
|
|
249
|
+
if (char === "\\" && quote !== "`") {
|
|
250
|
+
index += 1;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (char === quote && previousChar !== "\\") {
|
|
254
|
+
quote = "";
|
|
255
|
+
}
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (char === "/" && nextChar === "/") {
|
|
260
|
+
inLineComment = true;
|
|
261
|
+
index += 1;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (char === "/" && nextChar === "*") {
|
|
265
|
+
inBlockComment = true;
|
|
266
|
+
index += 1;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
270
|
+
quote = char;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (char === openChar) {
|
|
274
|
+
depth += 1;
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (char === closeChar) {
|
|
278
|
+
depth -= 1;
|
|
279
|
+
if (depth === 0) {
|
|
280
|
+
return index;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return -1;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function resolveAnchorLineIndex(sourceText = "", anchor = "") {
|
|
289
|
+
const escapedAnchor = String(anchor || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
290
|
+
const anchorLinePattern = new RegExp(`^[ \\t]*${escapedAnchor}[ \\t]*$`, "m");
|
|
291
|
+
const anchorLineMatch = anchorLinePattern.exec(String(sourceText || ""));
|
|
292
|
+
return Number(anchorLineMatch?.index ?? -1);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function findArrayDeclarationBeforeIndex(sourceText = "", arrayName = "", index = -1) {
|
|
296
|
+
const source = String(sourceText || "");
|
|
297
|
+
const resolvedIndex = Number.isInteger(index) ? index : -1;
|
|
298
|
+
if (resolvedIndex < 0) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const declarationPattern = new RegExp(`\\b(?:const|let)\\s+${arrayName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*=\\s*\\[`, "g");
|
|
303
|
+
let match = null;
|
|
304
|
+
let selected = null;
|
|
305
|
+
while ((match = declarationPattern.exec(source)) != null) {
|
|
306
|
+
if (match.index > resolvedIndex) {
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
selected = match;
|
|
310
|
+
}
|
|
311
|
+
if (!selected) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const openIndex = source.indexOf("[", selected.index);
|
|
316
|
+
const closeIndex = findMatchingDelimiter(source, openIndex, "[", "]");
|
|
317
|
+
if (closeIndex < 0) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
openIndex,
|
|
323
|
+
closeIndex
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function insertFormFieldDefinition(source, insertion = {}) {
|
|
328
|
+
const anchorIndex = resolveAnchorLineIndex(source, insertion.anchor);
|
|
329
|
+
const declaration = findArrayDeclarationBeforeIndex(source, insertion.arrayName, anchorIndex);
|
|
330
|
+
if (!declaration || anchorIndex <= declaration.openIndex || anchorIndex >= declaration.closeIndex) {
|
|
331
|
+
throw new Error(
|
|
332
|
+
`crud-ui-generator field found legacy form-field marker layout for ${insertion.arrayName}. ` +
|
|
333
|
+
"Run `jskit app migrate-source-mutations` before adding more generated form fields."
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return insertBeforeAnchor(source, insertion);
|
|
338
|
+
}
|
|
339
|
+
|
|
220
340
|
function resolveAnchorScopeStart(source = "", { anchorIndex = -1, anchor = "" } = {}) {
|
|
221
341
|
const sourceText = String(source || "");
|
|
222
342
|
const resolvedAnchorIndex = Number.isInteger(anchorIndex) ? anchorIndex : -1;
|
|
@@ -284,7 +404,8 @@ function buildAnchorInsertions(operationName, field) {
|
|
|
284
404
|
{
|
|
285
405
|
targetKind: "form-fields",
|
|
286
406
|
anchor: "// jskit:crud-ui-form-fields:new",
|
|
287
|
-
|
|
407
|
+
arrayName: "UI_CREATE_FORM_FIELDS",
|
|
408
|
+
snippet: renderObjectArrayEntryLines([field])
|
|
288
409
|
}
|
|
289
410
|
];
|
|
290
411
|
}
|
|
@@ -298,7 +419,8 @@ function buildAnchorInsertions(operationName, field) {
|
|
|
298
419
|
{
|
|
299
420
|
targetKind: "form-fields",
|
|
300
421
|
anchor: "// jskit:crud-ui-form-fields:edit",
|
|
301
|
-
|
|
422
|
+
arrayName: "UI_EDIT_FORM_FIELDS",
|
|
423
|
+
snippet: renderObjectArrayEntryLines([field])
|
|
302
424
|
}
|
|
303
425
|
];
|
|
304
426
|
}
|
|
@@ -426,7 +548,9 @@ async function runGeneratorSubcommand({
|
|
|
426
548
|
fileStates.set(targetFile.absolutePath, state);
|
|
427
549
|
}
|
|
428
550
|
|
|
429
|
-
const applied =
|
|
551
|
+
const applied = insertion.targetKind === "form-fields"
|
|
552
|
+
? insertFormFieldDefinition(state.source, insertion)
|
|
553
|
+
: insertBeforeAnchor(state.source, insertion);
|
|
430
554
|
state.source = applied.content;
|
|
431
555
|
state.changed = state.changed || applied.changed;
|
|
432
556
|
changed = changed || applied.changed;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const UI_CREATE_FORM_FIELDS = [
|
|
1
|
+
const UI_CREATE_FORM_FIELDS = [
|
|
2
|
+
__JSKIT_UI_CREATE_FORM_FIELD_ARRAY_ENTRIES__ // jskit:crud-ui-form-fields:new
|
|
3
|
+
];
|
|
2
4
|
|
|
3
5
|
// @jskit-contract crud.ui.form-fields.__JSKIT_UI_RESOURCE_NAMESPACE__.new.v1
|
|
4
6
|
void UI_CREATE_FORM_FIELDS;
|
|
5
|
-
// jskit:crud-ui-form-fields:new
|
|
6
|
-
__JSKIT_UI_CREATE_FORM_FIELD_PUSH_LINES__
|
|
7
7
|
Object.freeze(UI_CREATE_FORM_FIELDS);
|
|
8
8
|
|
|
9
|
-
const UI_EDIT_FORM_FIELDS = [
|
|
9
|
+
const UI_EDIT_FORM_FIELDS = [
|
|
10
|
+
__JSKIT_UI_EDIT_FORM_FIELD_ARRAY_ENTRIES__ // jskit:crud-ui-form-fields:edit
|
|
11
|
+
];
|
|
10
12
|
|
|
11
13
|
// @jskit-contract crud.ui.form-fields.__JSKIT_UI_RESOURCE_NAMESPACE__.edit.v1
|
|
12
14
|
void UI_EDIT_FORM_FIELDS;
|
|
13
|
-
// jskit:crud-ui-form-fields:edit
|
|
14
|
-
__JSKIT_UI_EDIT_FORM_FIELD_PUSH_LINES__
|
|
15
15
|
Object.freeze(UI_EDIT_FORM_FIELDS);
|
|
16
16
|
|
|
17
17
|
export { UI_CREATE_FORM_FIELDS, UI_EDIT_FORM_FIELDS };
|
|
@@ -27,12 +27,12 @@ const UI_LIST_URL = __JSKIT_UI_EDIT_PAGE_LIST_URL__;
|
|
|
27
27
|
const UI_VIEW_URL = __JSKIT_UI_EDIT_PAGE_VIEW_URL__;
|
|
28
28
|
const UI_CANCEL_URL = UI_VIEW_URL || UI_LIST_URL;
|
|
29
29
|
const UI_RECORD_CHANGED_EVENT = __JSKIT_UI_RECORD_CHANGED_EVENT__;
|
|
30
|
-
const UI_EDIT_FORM_FIELDS = [
|
|
30
|
+
const UI_EDIT_FORM_FIELDS = [
|
|
31
|
+
__JSKIT_UI_EDIT_FORM_FIELD_ARRAY_ENTRIES__ // jskit:crud-ui-form-fields:edit
|
|
32
|
+
];
|
|
31
33
|
|
|
32
34
|
// @jskit-contract crud.ui.form-fields.__JSKIT_UI_RESOURCE_NAMESPACE__.edit.v1
|
|
33
35
|
void UI_EDIT_FORM_FIELDS;
|
|
34
|
-
// jskit:crud-ui-form-fields:edit
|
|
35
|
-
__JSKIT_UI_EDIT_FORM_FIELD_PUSH_LINES__
|
|
36
36
|
Object.freeze(UI_EDIT_FORM_FIELDS);
|
|
37
37
|
|
|
38
38
|
const route = useRoute();
|
|
@@ -23,12 +23,12 @@ const UI_CREATE_API_URL = "__JSKIT_UI_API_BASE_URL__";
|
|
|
23
23
|
const UI_LIST_URL = __JSKIT_UI_NEW_PAGE_LIST_URL__;
|
|
24
24
|
const UI_VIEW_URL = __JSKIT_UI_NEW_PAGE_VIEW_URL__;
|
|
25
25
|
const UI_RECORD_CHANGED_EVENT = __JSKIT_UI_RECORD_CHANGED_EVENT__;
|
|
26
|
-
const UI_CREATE_FORM_FIELDS = [
|
|
26
|
+
const UI_CREATE_FORM_FIELDS = [
|
|
27
|
+
__JSKIT_UI_CREATE_FORM_FIELD_ARRAY_ENTRIES__ // jskit:crud-ui-form-fields:new
|
|
28
|
+
];
|
|
27
29
|
|
|
28
30
|
// @jskit-contract crud.ui.form-fields.__JSKIT_UI_RESOURCE_NAMESPACE__.new.v1
|
|
29
31
|
void UI_CREATE_FORM_FIELDS;
|
|
30
|
-
// jskit:crud-ui-form-fields:new
|
|
31
|
-
__JSKIT_UI_CREATE_FORM_FIELD_PUSH_LINES__
|
|
32
32
|
Object.freeze(UI_CREATE_FORM_FIELDS);
|
|
33
33
|
|
|
34
34
|
__JSKIT_UI_CREATE_LOOKUP_RUNTIME_SETUP__
|
|
@@ -104,9 +104,10 @@ test("field patches edit screen using resource metadata and anchors", async () =
|
|
|
104
104
|
</template>
|
|
105
105
|
<script setup>
|
|
106
106
|
import { resource as uiResource } from "/packages/contacts/src/shared/contactResource.js";
|
|
107
|
-
const UI_EDIT_FORM_FIELDS = [
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
const UI_EDIT_FORM_FIELDS = [
|
|
108
|
+
{ key: "firstName", component: "text" },
|
|
109
|
+
// jskit:crud-ui-form-fields:edit
|
|
110
|
+
];
|
|
110
111
|
</script>
|
|
111
112
|
`
|
|
112
113
|
);
|
|
@@ -132,7 +133,8 @@ UI_EDIT_FORM_FIELDS.push({ key: "firstName", component: "text" });
|
|
|
132
133
|
assert.match(editSource, /:search="fieldLookupSearch\('vetId'\)"/);
|
|
133
134
|
assert.match(editSource, /@update:search="setFieldLookupSearch\('vetId', \$event\)"/);
|
|
134
135
|
assert.match(editSource, /:loading="fieldLookupLoading\('vetId'\)"/);
|
|
135
|
-
assert.
|
|
136
|
+
assert.doesNotMatch(editSource, /UI_EDIT_FORM_FIELDS\.push/);
|
|
137
|
+
assert.match(editSource, /const UI_EDIT_FORM_FIELDS = \[[\s\S]*key: "vetId"[\s\S]*\/\/ jskit:crud-ui-form-fields:edit/);
|
|
136
138
|
|
|
137
139
|
const second = await runGeneratorSubcommand({
|
|
138
140
|
appRoot,
|
|
@@ -178,9 +180,10 @@ import { resource as uiResource } from "/packages/contacts/src/shared/contactRes
|
|
|
178
180
|
await writeAppFile(
|
|
179
181
|
appRoot,
|
|
180
182
|
addEditFieldsFile,
|
|
181
|
-
`const UI_EDIT_FORM_FIELDS = [
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
`const UI_EDIT_FORM_FIELDS = [
|
|
184
|
+
{ key: "firstName", component: "text" },
|
|
185
|
+
// jskit:crud-ui-form-fields:edit
|
|
186
|
+
];
|
|
184
187
|
`
|
|
185
188
|
);
|
|
186
189
|
|
|
@@ -200,7 +203,8 @@ UI_EDIT_FORM_FIELDS.push({ key: "firstName", component: "text" });
|
|
|
200
203
|
);
|
|
201
204
|
|
|
202
205
|
const addEditFieldsSource = await readFile(path.join(appRoot, addEditFieldsFile), "utf8");
|
|
203
|
-
assert.
|
|
206
|
+
assert.doesNotMatch(addEditFieldsSource, /UI_EDIT_FORM_FIELDS\.push/);
|
|
207
|
+
assert.match(addEditFieldsSource, /const UI_EDIT_FORM_FIELDS = \[[\s\S]*key: "vetId"[\s\S]*\/\/ jskit:crud-ui-form-fields:edit/);
|
|
204
208
|
});
|
|
205
209
|
});
|
|
206
210
|
|
|
@@ -257,10 +261,12 @@ import { resource as uiResource } from "/packages/contacts/src/shared/contactRes
|
|
|
257
261
|
await writeAppFile(
|
|
258
262
|
appRoot,
|
|
259
263
|
addEditFieldsFile,
|
|
260
|
-
`const UI_CREATE_FORM_FIELDS = [
|
|
261
|
-
// jskit:crud-ui-form-fields:new
|
|
262
|
-
|
|
263
|
-
|
|
264
|
+
`const UI_CREATE_FORM_FIELDS = [
|
|
265
|
+
// jskit:crud-ui-form-fields:new
|
|
266
|
+
];
|
|
267
|
+
const UI_EDIT_FORM_FIELDS = [
|
|
268
|
+
// jskit:crud-ui-form-fields:edit
|
|
269
|
+
];
|
|
264
270
|
`
|
|
265
271
|
);
|
|
266
272
|
|
|
@@ -281,8 +287,49 @@ const UI_EDIT_FORM_FIELDS = [];
|
|
|
281
287
|
assert.equal((addEditFormSource.match(/fieldLookupItems\('vetId'/g) || []).length, 2);
|
|
282
288
|
|
|
283
289
|
const addEditFieldsSource = await readFile(path.join(appRoot, addEditFieldsFile), "utf8");
|
|
284
|
-
assert.
|
|
285
|
-
assert.
|
|
290
|
+
assert.doesNotMatch(addEditFieldsSource, /UI_CREATE_FORM_FIELDS\.push/);
|
|
291
|
+
assert.doesNotMatch(addEditFieldsSource, /UI_EDIT_FORM_FIELDS\.push/);
|
|
292
|
+
assert.match(addEditFieldsSource, /const UI_CREATE_FORM_FIELDS = \[[\s\S]*key: "vetId"[\s\S]*\/\/ jskit:crud-ui-form-fields:new/);
|
|
293
|
+
assert.match(addEditFieldsSource, /const UI_EDIT_FORM_FIELDS = \[[\s\S]*key: "vetId"[\s\S]*\/\/ jskit:crud-ui-form-fields:edit/);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("field rejects legacy form-field marker layouts instead of adding new push calls", async () => {
|
|
298
|
+
await withTempApp(async (appRoot) => {
|
|
299
|
+
const resourceFile = "packages/contacts/src/shared/contactResource.js";
|
|
300
|
+
const editFile = "src/pages/admin/crm/contacts/[recordId]/edit.vue";
|
|
301
|
+
|
|
302
|
+
await writeAppFile(appRoot, resourceFile, RESOURCE_SOURCE);
|
|
303
|
+
await writeAppFile(
|
|
304
|
+
appRoot,
|
|
305
|
+
editFile,
|
|
306
|
+
`<template>
|
|
307
|
+
<v-row>
|
|
308
|
+
<!-- jskit:crud-ui-fields:edit -->
|
|
309
|
+
</v-row>
|
|
310
|
+
</template>
|
|
311
|
+
<script setup>
|
|
312
|
+
import { resource as uiResource } from "/packages/contacts/src/shared/contactResource.js";
|
|
313
|
+
const UI_EDIT_FORM_FIELDS = [];
|
|
314
|
+
// jskit:crud-ui-form-fields:edit
|
|
315
|
+
UI_EDIT_FORM_FIELDS.push({ key: "firstName", component: "text" });
|
|
316
|
+
</script>
|
|
317
|
+
`
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
await assert.rejects(
|
|
321
|
+
() => runGeneratorSubcommand({
|
|
322
|
+
appRoot,
|
|
323
|
+
subcommand: "field",
|
|
324
|
+
args: ["vetId", "edit", editFile],
|
|
325
|
+
options: {}
|
|
326
|
+
}),
|
|
327
|
+
/Run `jskit app migrate-source-mutations` before adding more generated form fields/
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
const editSource = await readFile(path.join(appRoot, editFile), "utf8");
|
|
331
|
+
assert.match(editSource, /UI_EDIT_FORM_FIELDS\.push/);
|
|
332
|
+
assert.doesNotMatch(editSource, /key: "vetId"/);
|
|
286
333
|
});
|
|
287
334
|
});
|
|
288
335
|
|