@rvoh/psychic 2.2.0 → 2.2.1-alpha.1
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.
|
@@ -14,6 +14,10 @@ ${INDENT}all properties default to not nullable; null can be allowed by appendin
|
|
|
14
14
|
${INDENT} subtitle:string:optional
|
|
15
15
|
${INDENT}
|
|
16
16
|
${INDENT}supported types:
|
|
17
|
+
${INDENT} - uuid:
|
|
18
|
+
${INDENT} - uuid[]:
|
|
19
|
+
${INDENT} a column optimized for storing UUIDs
|
|
20
|
+
${INDENT}
|
|
17
21
|
${INDENT} - citext:
|
|
18
22
|
${INDENT} - citext[]:
|
|
19
23
|
${INDENT} case insensitive text (indexes and queries are automatically case insensitive)
|
|
@@ -7,7 +7,7 @@ export default function generateResourceControllerSpecContent(options) {
|
|
|
7
7
|
const modelConfig = createModelConfiguration(options);
|
|
8
8
|
const actionConfig = createActionConfiguration(options);
|
|
9
9
|
const attributeData = processAttributes(options.columnsWithTypes, modelConfig, options.fullyQualifiedModelName);
|
|
10
|
-
const imports = generateImportStatements(modelConfig, attributeData.dreamImports, options.owningModel);
|
|
10
|
+
const imports = generateImportStatements(modelConfig, attributeData.dreamImports, options.owningModel, attributeData.uuidAttributeIncluded);
|
|
11
11
|
return generateSpecTemplate({
|
|
12
12
|
...options,
|
|
13
13
|
path,
|
|
@@ -62,6 +62,8 @@ function processAttributes(columnsWithTypes, modelConfig, fullyQualifiedModelNam
|
|
|
62
62
|
originalValueVariableAssignments: [],
|
|
63
63
|
dateAttributeIncluded: false,
|
|
64
64
|
datetimeAttributeIncluded: false,
|
|
65
|
+
uuidAttributeIncluded: false,
|
|
66
|
+
uuidArrayAttributes: [],
|
|
65
67
|
dreamImports: [],
|
|
66
68
|
};
|
|
67
69
|
for (const attribute of columnsWithTypes) {
|
|
@@ -102,7 +104,8 @@ function parseAttribute(attribute) {
|
|
|
102
104
|
return null;
|
|
103
105
|
const arrayBracketRegexp = /\[\]$/;
|
|
104
106
|
const isArray = arrayBracketRegexp.test(rawAttributeType);
|
|
105
|
-
const
|
|
107
|
+
const _attributeType = rawAttributeType.replace(arrayBracketRegexp, '');
|
|
108
|
+
const attributeType = /uuid$/.test(rawAttributeName) ? 'uuid' : _attributeType;
|
|
106
109
|
return { attributeName, attributeType, isArray, enumValues };
|
|
107
110
|
}
|
|
108
111
|
function processAttributeByType({ attributeType, attributeName, isArray, enumValues, dotNotationVariable, fullyQualifiedModelName, attributeData, }) {
|
|
@@ -137,6 +140,9 @@ function processAttributeByType({ attributeType, attributeName, isArray, enumVal
|
|
|
137
140
|
case 'datetime':
|
|
138
141
|
processDateTimeAttribute({ attributeName, isArray, dotNotationVariable, attributeData });
|
|
139
142
|
break;
|
|
143
|
+
case 'uuid':
|
|
144
|
+
processUuidAttribute({ attributeName, isArray, dotNotationVariable, attributeData });
|
|
145
|
+
break;
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
function processEnumAttribute({ attributeName, isArray, enumValues, dotNotationVariable, attributeData, }) {
|
|
@@ -192,6 +198,21 @@ function processDateTimeAttribute({ attributeName, isArray, dotNotationVariable,
|
|
|
192
198
|
attributeData.expectEqualOriginalValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualDateTime(now)`);
|
|
193
199
|
attributeData.expectEqualUpdatedValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualDateTime(lastHour)`);
|
|
194
200
|
}
|
|
201
|
+
function processUuidAttribute({ attributeName, isArray, dotNotationVariable, attributeData, }) {
|
|
202
|
+
attributeData.uuidAttributeIncluded = true;
|
|
203
|
+
if (isArray) {
|
|
204
|
+
attributeData.uuidArrayAttributes.push(attributeName);
|
|
205
|
+
}
|
|
206
|
+
const newUuidVariableName = `new${capitalize(attributeName)}`;
|
|
207
|
+
// For arrays, the variable itself is an array, so we use it directly without brackets
|
|
208
|
+
const uuidValue = attributeName;
|
|
209
|
+
const newUuidValue = newUuidVariableName;
|
|
210
|
+
attributeData.attributeCreationKeyValues.push(`${attributeName}: ${uuidValue},`);
|
|
211
|
+
attributeData.attributeUpdateKeyValues.push(`${attributeName}: ${newUuidValue},`);
|
|
212
|
+
attributeData.comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
213
|
+
attributeData.expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual(${attributeName})`);
|
|
214
|
+
attributeData.expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(${newUuidVariableName})`);
|
|
215
|
+
}
|
|
195
216
|
function addOriginalValueTracking(attributeType, attributeName, isArray, dotNotationVariable, attributeData) {
|
|
196
217
|
const hardToCompareArray = (attributeType === 'date' || attributeType === 'datetime') && isArray;
|
|
197
218
|
// Exclude belongs_to relationships from original value tracking
|
|
@@ -201,7 +222,7 @@ function addOriginalValueTracking(attributeType, attributeName, isArray, dotNota
|
|
|
201
222
|
attributeData.expectEqualOriginalNamedVariable.push(`expect(${dotNotationVariable}).toEqual(${originalAttributeVariableName})`);
|
|
202
223
|
}
|
|
203
224
|
}
|
|
204
|
-
function generateImportStatements(modelConfig, dreamImports, owningModel) {
|
|
225
|
+
function generateImportStatements(modelConfig, dreamImports, owningModel, uuidAttributeIncluded) {
|
|
205
226
|
const importStatements = compact([
|
|
206
227
|
importStatementForModel(modelConfig.fullyQualifiedModelName),
|
|
207
228
|
importStatementForModel(modelConfig.userModelName),
|
|
@@ -210,10 +231,11 @@ function generateImportStatements(modelConfig, dreamImports, owningModel) {
|
|
|
210
231
|
importStatementForModelFactory(modelConfig.userModelName),
|
|
211
232
|
owningModel ? importStatementForModelFactory(owningModel) : undefined,
|
|
212
233
|
]);
|
|
234
|
+
const cryptoImportLine = uuidAttributeIncluded ? `import { randomUUID } from 'node:crypto'\n` : '';
|
|
213
235
|
const dreamImportLine = dreamImports.length
|
|
214
236
|
? `import { ${uniq(dreamImports).join(', ')} } from '@rvoh/dream'\n`
|
|
215
237
|
: '';
|
|
216
|
-
return `${dreamImportLine}${uniq(importStatements).join('\n')}
|
|
238
|
+
return `${cryptoImportLine}${dreamImportLine}${uniq(importStatements).join('\n')}
|
|
217
239
|
import { RequestBody, session, SpecRequestType } from '@spec/unit/helpers/${addImportSuffix('authentication.js')}'`;
|
|
218
240
|
}
|
|
219
241
|
function generateSpecTemplate(options) {
|
|
@@ -314,13 +336,28 @@ function generateCreateActionSpec(options) {
|
|
|
314
336
|
return '';
|
|
315
337
|
const { path, pathParams, modelConfig, fullyQualifiedModelName, forAdmin, singular, attributeData } = options;
|
|
316
338
|
const subjectFunctionName = `create${modelConfig.modelClassName}`;
|
|
317
|
-
const
|
|
339
|
+
const uuidAttributeNames = attributeData.attributeCreationKeyValues
|
|
340
|
+
.map(kv => {
|
|
341
|
+
const match = kv.match(/^(\w+):\s*\1,?$/);
|
|
342
|
+
return match?.[1];
|
|
343
|
+
})
|
|
344
|
+
.filter((name) => Boolean(name));
|
|
345
|
+
const uuidSetup = uuidAttributeNames
|
|
346
|
+
.map(attrName => {
|
|
347
|
+
const isArray = attributeData.uuidArrayAttributes.includes(attrName);
|
|
348
|
+
return isArray ? `const ${attrName} = [randomUUID()]` : `const ${attrName} = randomUUID()`;
|
|
349
|
+
})
|
|
350
|
+
.join('\n ');
|
|
351
|
+
const dateTimeSetup = `${uuidSetup
|
|
352
|
+
? `
|
|
353
|
+
${uuidSetup}`
|
|
354
|
+
: ''}${attributeData.dateAttributeIncluded
|
|
318
355
|
? `
|
|
319
356
|
const today = CalendarDate.today()`
|
|
320
357
|
: ''}${attributeData.datetimeAttributeIncluded
|
|
321
358
|
? `
|
|
322
359
|
const now = DateTime.now()`
|
|
323
|
-
: ''}${attributeData.dateAttributeIncluded || attributeData.datetimeAttributeIncluded ? '\n' : ''}`;
|
|
360
|
+
: ''}${uuidSetup || attributeData.dateAttributeIncluded || attributeData.datetimeAttributeIncluded ? '\n' : ''}`;
|
|
324
361
|
const modelQuery = forAdmin
|
|
325
362
|
? `${modelConfig.modelClassName}.firstOrFail()`
|
|
326
363
|
: `${modelConfig.owningModelVariableName}.associationQuery('${singular ? modelConfig.modelVariableName : pluralize(modelConfig.modelVariableName)}').firstOrFail()`;
|
|
@@ -356,7 +393,28 @@ function generateUpdateActionSpec(options) {
|
|
|
356
393
|
return '';
|
|
357
394
|
const { path, pathParams, modelConfig, fullyQualifiedModelName, singular, forAdmin, attributeData } = options;
|
|
358
395
|
const subjectFunctionName = `update${modelConfig.modelClassName}`;
|
|
359
|
-
const
|
|
396
|
+
const uuidAttributeNames = attributeData.attributeUpdateKeyValues
|
|
397
|
+
.filter(kv => {
|
|
398
|
+
const match = kv.match(/^(\w+):\s*new([A-Z]\w+),?$/);
|
|
399
|
+
return match && match[1] && camelize(match[1]) === camelize(match[2]);
|
|
400
|
+
})
|
|
401
|
+
.map(kv => {
|
|
402
|
+
const match = kv.match(/^(\w+):/);
|
|
403
|
+
return match?.[1];
|
|
404
|
+
})
|
|
405
|
+
.filter(Boolean);
|
|
406
|
+
const uuidSetup = uuidAttributeNames
|
|
407
|
+
.map(attrName => {
|
|
408
|
+
const isArray = attributeData.uuidArrayAttributes.includes(attrName);
|
|
409
|
+
return isArray
|
|
410
|
+
? `const new${capitalize(attrName)} = [randomUUID()]`
|
|
411
|
+
: `const new${capitalize(attrName)} = randomUUID()`;
|
|
412
|
+
})
|
|
413
|
+
.join('\n ');
|
|
414
|
+
const dateTimeSetup = `${uuidSetup
|
|
415
|
+
? `
|
|
416
|
+
${uuidSetup}`
|
|
417
|
+
: ''}${attributeData.dateAttributeIncluded
|
|
360
418
|
? `
|
|
361
419
|
const yesterday = CalendarDate.yesterday()`
|
|
362
420
|
: ''}${attributeData.datetimeAttributeIncluded
|
|
@@ -400,7 +458,21 @@ function generateUpdateActionSpec(options) {
|
|
|
400
458
|
${attributeData.originalValueVariableAssignments.length ? attributeData.originalValueVariableAssignments.join('\n ') : ''}
|
|
401
459
|
|
|
402
460
|
await ${subjectFunctionName}(${modelConfig.modelVariableName}, {
|
|
403
|
-
${attributeData.attributeUpdateKeyValues.length
|
|
461
|
+
${attributeData.attributeUpdateKeyValues.length
|
|
462
|
+
? attributeData.attributeUpdateKeyValues
|
|
463
|
+
.map(kv => {
|
|
464
|
+
const match = kv.match(/^(\w+):\s*new([A-Z]\w+),?$/);
|
|
465
|
+
if (match && match[1]) {
|
|
466
|
+
const attrName = match[1];
|
|
467
|
+
const isArray = attributeData.uuidArrayAttributes.includes(attrName);
|
|
468
|
+
return isArray
|
|
469
|
+
? kv.replace(/\bnew[A-Z]\w+\b/g, '[randomUUID()]')
|
|
470
|
+
: kv.replace(/\bnew[A-Z]\w+\b/g, 'randomUUID()');
|
|
471
|
+
}
|
|
472
|
+
return kv;
|
|
473
|
+
})
|
|
474
|
+
.join('\n ')
|
|
475
|
+
: ''}
|
|
404
476
|
}, 404)
|
|
405
477
|
|
|
406
478
|
await ${modelConfig.modelVariableName}.reload()
|
|
@@ -14,6 +14,10 @@ ${INDENT}all properties default to not nullable; null can be allowed by appendin
|
|
|
14
14
|
${INDENT} subtitle:string:optional
|
|
15
15
|
${INDENT}
|
|
16
16
|
${INDENT}supported types:
|
|
17
|
+
${INDENT} - uuid:
|
|
18
|
+
${INDENT} - uuid[]:
|
|
19
|
+
${INDENT} a column optimized for storing UUIDs
|
|
20
|
+
${INDENT}
|
|
17
21
|
${INDENT} - citext:
|
|
18
22
|
${INDENT} - citext[]:
|
|
19
23
|
${INDENT} case insensitive text (indexes and queries are automatically case insensitive)
|
|
@@ -7,7 +7,7 @@ export default function generateResourceControllerSpecContent(options) {
|
|
|
7
7
|
const modelConfig = createModelConfiguration(options);
|
|
8
8
|
const actionConfig = createActionConfiguration(options);
|
|
9
9
|
const attributeData = processAttributes(options.columnsWithTypes, modelConfig, options.fullyQualifiedModelName);
|
|
10
|
-
const imports = generateImportStatements(modelConfig, attributeData.dreamImports, options.owningModel);
|
|
10
|
+
const imports = generateImportStatements(modelConfig, attributeData.dreamImports, options.owningModel, attributeData.uuidAttributeIncluded);
|
|
11
11
|
return generateSpecTemplate({
|
|
12
12
|
...options,
|
|
13
13
|
path,
|
|
@@ -62,6 +62,8 @@ function processAttributes(columnsWithTypes, modelConfig, fullyQualifiedModelNam
|
|
|
62
62
|
originalValueVariableAssignments: [],
|
|
63
63
|
dateAttributeIncluded: false,
|
|
64
64
|
datetimeAttributeIncluded: false,
|
|
65
|
+
uuidAttributeIncluded: false,
|
|
66
|
+
uuidArrayAttributes: [],
|
|
65
67
|
dreamImports: [],
|
|
66
68
|
};
|
|
67
69
|
for (const attribute of columnsWithTypes) {
|
|
@@ -102,7 +104,8 @@ function parseAttribute(attribute) {
|
|
|
102
104
|
return null;
|
|
103
105
|
const arrayBracketRegexp = /\[\]$/;
|
|
104
106
|
const isArray = arrayBracketRegexp.test(rawAttributeType);
|
|
105
|
-
const
|
|
107
|
+
const _attributeType = rawAttributeType.replace(arrayBracketRegexp, '');
|
|
108
|
+
const attributeType = /uuid$/.test(rawAttributeName) ? 'uuid' : _attributeType;
|
|
106
109
|
return { attributeName, attributeType, isArray, enumValues };
|
|
107
110
|
}
|
|
108
111
|
function processAttributeByType({ attributeType, attributeName, isArray, enumValues, dotNotationVariable, fullyQualifiedModelName, attributeData, }) {
|
|
@@ -137,6 +140,9 @@ function processAttributeByType({ attributeType, attributeName, isArray, enumVal
|
|
|
137
140
|
case 'datetime':
|
|
138
141
|
processDateTimeAttribute({ attributeName, isArray, dotNotationVariable, attributeData });
|
|
139
142
|
break;
|
|
143
|
+
case 'uuid':
|
|
144
|
+
processUuidAttribute({ attributeName, isArray, dotNotationVariable, attributeData });
|
|
145
|
+
break;
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
function processEnumAttribute({ attributeName, isArray, enumValues, dotNotationVariable, attributeData, }) {
|
|
@@ -192,6 +198,21 @@ function processDateTimeAttribute({ attributeName, isArray, dotNotationVariable,
|
|
|
192
198
|
attributeData.expectEqualOriginalValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualDateTime(now)`);
|
|
193
199
|
attributeData.expectEqualUpdatedValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualDateTime(lastHour)`);
|
|
194
200
|
}
|
|
201
|
+
function processUuidAttribute({ attributeName, isArray, dotNotationVariable, attributeData, }) {
|
|
202
|
+
attributeData.uuidAttributeIncluded = true;
|
|
203
|
+
if (isArray) {
|
|
204
|
+
attributeData.uuidArrayAttributes.push(attributeName);
|
|
205
|
+
}
|
|
206
|
+
const newUuidVariableName = `new${capitalize(attributeName)}`;
|
|
207
|
+
// For arrays, the variable itself is an array, so we use it directly without brackets
|
|
208
|
+
const uuidValue = attributeName;
|
|
209
|
+
const newUuidValue = newUuidVariableName;
|
|
210
|
+
attributeData.attributeCreationKeyValues.push(`${attributeName}: ${uuidValue},`);
|
|
211
|
+
attributeData.attributeUpdateKeyValues.push(`${attributeName}: ${newUuidValue},`);
|
|
212
|
+
attributeData.comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
213
|
+
attributeData.expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual(${attributeName})`);
|
|
214
|
+
attributeData.expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(${newUuidVariableName})`);
|
|
215
|
+
}
|
|
195
216
|
function addOriginalValueTracking(attributeType, attributeName, isArray, dotNotationVariable, attributeData) {
|
|
196
217
|
const hardToCompareArray = (attributeType === 'date' || attributeType === 'datetime') && isArray;
|
|
197
218
|
// Exclude belongs_to relationships from original value tracking
|
|
@@ -201,7 +222,7 @@ function addOriginalValueTracking(attributeType, attributeName, isArray, dotNota
|
|
|
201
222
|
attributeData.expectEqualOriginalNamedVariable.push(`expect(${dotNotationVariable}).toEqual(${originalAttributeVariableName})`);
|
|
202
223
|
}
|
|
203
224
|
}
|
|
204
|
-
function generateImportStatements(modelConfig, dreamImports, owningModel) {
|
|
225
|
+
function generateImportStatements(modelConfig, dreamImports, owningModel, uuidAttributeIncluded) {
|
|
205
226
|
const importStatements = compact([
|
|
206
227
|
importStatementForModel(modelConfig.fullyQualifiedModelName),
|
|
207
228
|
importStatementForModel(modelConfig.userModelName),
|
|
@@ -210,10 +231,11 @@ function generateImportStatements(modelConfig, dreamImports, owningModel) {
|
|
|
210
231
|
importStatementForModelFactory(modelConfig.userModelName),
|
|
211
232
|
owningModel ? importStatementForModelFactory(owningModel) : undefined,
|
|
212
233
|
]);
|
|
234
|
+
const cryptoImportLine = uuidAttributeIncluded ? `import { randomUUID } from 'node:crypto'\n` : '';
|
|
213
235
|
const dreamImportLine = dreamImports.length
|
|
214
236
|
? `import { ${uniq(dreamImports).join(', ')} } from '@rvoh/dream'\n`
|
|
215
237
|
: '';
|
|
216
|
-
return `${dreamImportLine}${uniq(importStatements).join('\n')}
|
|
238
|
+
return `${cryptoImportLine}${dreamImportLine}${uniq(importStatements).join('\n')}
|
|
217
239
|
import { RequestBody, session, SpecRequestType } from '@spec/unit/helpers/${addImportSuffix('authentication.js')}'`;
|
|
218
240
|
}
|
|
219
241
|
function generateSpecTemplate(options) {
|
|
@@ -314,13 +336,28 @@ function generateCreateActionSpec(options) {
|
|
|
314
336
|
return '';
|
|
315
337
|
const { path, pathParams, modelConfig, fullyQualifiedModelName, forAdmin, singular, attributeData } = options;
|
|
316
338
|
const subjectFunctionName = `create${modelConfig.modelClassName}`;
|
|
317
|
-
const
|
|
339
|
+
const uuidAttributeNames = attributeData.attributeCreationKeyValues
|
|
340
|
+
.map(kv => {
|
|
341
|
+
const match = kv.match(/^(\w+):\s*\1,?$/);
|
|
342
|
+
return match?.[1];
|
|
343
|
+
})
|
|
344
|
+
.filter((name) => Boolean(name));
|
|
345
|
+
const uuidSetup = uuidAttributeNames
|
|
346
|
+
.map(attrName => {
|
|
347
|
+
const isArray = attributeData.uuidArrayAttributes.includes(attrName);
|
|
348
|
+
return isArray ? `const ${attrName} = [randomUUID()]` : `const ${attrName} = randomUUID()`;
|
|
349
|
+
})
|
|
350
|
+
.join('\n ');
|
|
351
|
+
const dateTimeSetup = `${uuidSetup
|
|
352
|
+
? `
|
|
353
|
+
${uuidSetup}`
|
|
354
|
+
: ''}${attributeData.dateAttributeIncluded
|
|
318
355
|
? `
|
|
319
356
|
const today = CalendarDate.today()`
|
|
320
357
|
: ''}${attributeData.datetimeAttributeIncluded
|
|
321
358
|
? `
|
|
322
359
|
const now = DateTime.now()`
|
|
323
|
-
: ''}${attributeData.dateAttributeIncluded || attributeData.datetimeAttributeIncluded ? '\n' : ''}`;
|
|
360
|
+
: ''}${uuidSetup || attributeData.dateAttributeIncluded || attributeData.datetimeAttributeIncluded ? '\n' : ''}`;
|
|
324
361
|
const modelQuery = forAdmin
|
|
325
362
|
? `${modelConfig.modelClassName}.firstOrFail()`
|
|
326
363
|
: `${modelConfig.owningModelVariableName}.associationQuery('${singular ? modelConfig.modelVariableName : pluralize(modelConfig.modelVariableName)}').firstOrFail()`;
|
|
@@ -356,7 +393,28 @@ function generateUpdateActionSpec(options) {
|
|
|
356
393
|
return '';
|
|
357
394
|
const { path, pathParams, modelConfig, fullyQualifiedModelName, singular, forAdmin, attributeData } = options;
|
|
358
395
|
const subjectFunctionName = `update${modelConfig.modelClassName}`;
|
|
359
|
-
const
|
|
396
|
+
const uuidAttributeNames = attributeData.attributeUpdateKeyValues
|
|
397
|
+
.filter(kv => {
|
|
398
|
+
const match = kv.match(/^(\w+):\s*new([A-Z]\w+),?$/);
|
|
399
|
+
return match && match[1] && camelize(match[1]) === camelize(match[2]);
|
|
400
|
+
})
|
|
401
|
+
.map(kv => {
|
|
402
|
+
const match = kv.match(/^(\w+):/);
|
|
403
|
+
return match?.[1];
|
|
404
|
+
})
|
|
405
|
+
.filter(Boolean);
|
|
406
|
+
const uuidSetup = uuidAttributeNames
|
|
407
|
+
.map(attrName => {
|
|
408
|
+
const isArray = attributeData.uuidArrayAttributes.includes(attrName);
|
|
409
|
+
return isArray
|
|
410
|
+
? `const new${capitalize(attrName)} = [randomUUID()]`
|
|
411
|
+
: `const new${capitalize(attrName)} = randomUUID()`;
|
|
412
|
+
})
|
|
413
|
+
.join('\n ');
|
|
414
|
+
const dateTimeSetup = `${uuidSetup
|
|
415
|
+
? `
|
|
416
|
+
${uuidSetup}`
|
|
417
|
+
: ''}${attributeData.dateAttributeIncluded
|
|
360
418
|
? `
|
|
361
419
|
const yesterday = CalendarDate.yesterday()`
|
|
362
420
|
: ''}${attributeData.datetimeAttributeIncluded
|
|
@@ -400,7 +458,21 @@ function generateUpdateActionSpec(options) {
|
|
|
400
458
|
${attributeData.originalValueVariableAssignments.length ? attributeData.originalValueVariableAssignments.join('\n ') : ''}
|
|
401
459
|
|
|
402
460
|
await ${subjectFunctionName}(${modelConfig.modelVariableName}, {
|
|
403
|
-
${attributeData.attributeUpdateKeyValues.length
|
|
461
|
+
${attributeData.attributeUpdateKeyValues.length
|
|
462
|
+
? attributeData.attributeUpdateKeyValues
|
|
463
|
+
.map(kv => {
|
|
464
|
+
const match = kv.match(/^(\w+):\s*new([A-Z]\w+),?$/);
|
|
465
|
+
if (match && match[1]) {
|
|
466
|
+
const attrName = match[1];
|
|
467
|
+
const isArray = attributeData.uuidArrayAttributes.includes(attrName);
|
|
468
|
+
return isArray
|
|
469
|
+
? kv.replace(/\bnew[A-Z]\w+\b/g, '[randomUUID()]')
|
|
470
|
+
: kv.replace(/\bnew[A-Z]\w+\b/g, 'randomUUID()');
|
|
471
|
+
}
|
|
472
|
+
return kv;
|
|
473
|
+
})
|
|
474
|
+
.join('\n ')
|
|
475
|
+
: ''}
|
|
404
476
|
}, 404)
|
|
405
477
|
|
|
406
478
|
await ${modelConfig.modelVariableName}.reload()
|