@jskit-ai/crud-server-generator 0.1.58 → 0.1.60
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/crud-server-generator",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.60",
|
|
5
5
|
kind: "generator",
|
|
6
6
|
description: "CRUD server generator with routes, actions, and persistence scaffolding.",
|
|
7
7
|
options: {
|
|
@@ -151,13 +151,13 @@ export default Object.freeze({
|
|
|
151
151
|
mutations: {
|
|
152
152
|
dependencies: {
|
|
153
153
|
runtime: {
|
|
154
|
-
"@jskit-ai/auth-core": "0.1.
|
|
155
|
-
"@jskit-ai/crud-core": "0.1.
|
|
156
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
157
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
158
|
-
"@jskit-ai/kernel": "0.1.
|
|
159
|
-
"@jskit-ai/realtime": "0.1.
|
|
160
|
-
"@jskit-ai/users-core": "0.1.
|
|
154
|
+
"@jskit-ai/auth-core": "0.1.51",
|
|
155
|
+
"@jskit-ai/crud-core": "0.1.60",
|
|
156
|
+
"@jskit-ai/database-runtime": "0.1.52",
|
|
157
|
+
"@jskit-ai/http-runtime": "0.1.51",
|
|
158
|
+
"@jskit-ai/kernel": "0.1.52",
|
|
159
|
+
"@jskit-ai/realtime": "0.1.51",
|
|
160
|
+
"@jskit-ai/users-core": "0.1.62",
|
|
161
161
|
"@local/${option:namespace|kebab}": "file:packages/${option:namespace|kebab}",
|
|
162
162
|
"typebox": "^1.0.81"
|
|
163
163
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/crud-server-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.60",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@babel/parser": "^7.29.2",
|
|
16
|
-
"@jskit-ai/crud-core": "0.1.
|
|
17
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
18
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
19
|
-
"@jskit-ai/kernel": "0.1.
|
|
20
|
-
"@jskit-ai/users-core": "0.1.
|
|
16
|
+
"@jskit-ai/crud-core": "0.1.60",
|
|
17
|
+
"@jskit-ai/database-runtime": "0.1.52",
|
|
18
|
+
"@jskit-ai/http-runtime": "0.1.51",
|
|
19
|
+
"@jskit-ai/kernel": "0.1.52",
|
|
20
|
+
"@jskit-ai/users-core": "0.1.62",
|
|
21
21
|
"recast": "^0.23.11",
|
|
22
22
|
"typebox": "^1.0.81"
|
|
23
23
|
}
|
|
@@ -392,6 +392,7 @@ function resolveColumnKey(column, idColumn) {
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
const NUMERIC_CHECK_CONSTRAINT_PATTERN = /(?:`([^`]+)`|([A-Za-z_][A-Za-z0-9_]*))\s*(>=|>|<=|<)\s*(-?\d+(?:\.\d+)?)/g;
|
|
395
|
+
const NUMERIC_CHECK_CONSTRAINT_BETWEEN_PATTERN = /(?:`([^`]+)`|([A-Za-z_][A-Za-z0-9_]*))\s+between\s+(-?\d+(?:\.\d+)?)\s+and\s+(-?\d+(?:\.\d+)?)/gi;
|
|
395
396
|
|
|
396
397
|
function normalizeNumericBoundValue(value, scale = null) {
|
|
397
398
|
const parsed = Number(value);
|
|
@@ -452,6 +453,83 @@ function applyUpperBound(current = null, candidate = null) {
|
|
|
452
453
|
return current;
|
|
453
454
|
}
|
|
454
455
|
|
|
456
|
+
function applyNumericConstraintBound(target = {}, column = null, operator = "", rawValue = null) {
|
|
457
|
+
if (!column || !Number.isFinite(rawValue)) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (operator === ">=" || operator === ">") {
|
|
462
|
+
let candidate = null;
|
|
463
|
+
if (operator === ">=") {
|
|
464
|
+
candidate = {
|
|
465
|
+
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
466
|
+
exclusive: false
|
|
467
|
+
};
|
|
468
|
+
} else {
|
|
469
|
+
const exclusiveStep = resolveNumericExclusiveStep(column);
|
|
470
|
+
if (exclusiveStep != null) {
|
|
471
|
+
candidate = {
|
|
472
|
+
value: normalizeNumericBoundValue(rawValue + exclusiveStep, column.numericScale),
|
|
473
|
+
exclusive: false
|
|
474
|
+
};
|
|
475
|
+
} else {
|
|
476
|
+
candidate = {
|
|
477
|
+
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
478
|
+
exclusive: true
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const nextBound = applyLowerBound(
|
|
484
|
+
target.minimum != null || target.exclusiveMinimum != null
|
|
485
|
+
? {
|
|
486
|
+
value: target.minimum ?? target.exclusiveMinimum,
|
|
487
|
+
exclusive: target.exclusiveMinimum != null
|
|
488
|
+
}
|
|
489
|
+
: null,
|
|
490
|
+
candidate
|
|
491
|
+
);
|
|
492
|
+
target.minimum = nextBound?.exclusive === true ? null : nextBound?.value ?? null;
|
|
493
|
+
target.exclusiveMinimum = nextBound?.exclusive === true ? nextBound?.value ?? null : null;
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (operator === "<=" || operator === "<") {
|
|
498
|
+
let candidate = null;
|
|
499
|
+
if (operator === "<=") {
|
|
500
|
+
candidate = {
|
|
501
|
+
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
502
|
+
exclusive: false
|
|
503
|
+
};
|
|
504
|
+
} else {
|
|
505
|
+
const exclusiveStep = resolveNumericExclusiveStep(column);
|
|
506
|
+
if (exclusiveStep != null) {
|
|
507
|
+
candidate = {
|
|
508
|
+
value: normalizeNumericBoundValue(rawValue - exclusiveStep, column.numericScale),
|
|
509
|
+
exclusive: false
|
|
510
|
+
};
|
|
511
|
+
} else {
|
|
512
|
+
candidate = {
|
|
513
|
+
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
514
|
+
exclusive: true
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const nextBound = applyUpperBound(
|
|
520
|
+
target.maximum != null || target.exclusiveMaximum != null
|
|
521
|
+
? {
|
|
522
|
+
value: target.maximum ?? target.exclusiveMaximum,
|
|
523
|
+
exclusive: target.exclusiveMaximum != null
|
|
524
|
+
}
|
|
525
|
+
: null,
|
|
526
|
+
candidate
|
|
527
|
+
);
|
|
528
|
+
target.maximum = nextBound?.exclusive === true ? null : nextBound?.value ?? null;
|
|
529
|
+
target.exclusiveMaximum = nextBound?.exclusive === true ? nextBound?.value ?? null : null;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
455
533
|
function resolveColumnNumericBounds(snapshot = {}) {
|
|
456
534
|
const byColumnName = new Map();
|
|
457
535
|
const columns = Array.isArray(snapshot.columns) ? snapshot.columns : [];
|
|
@@ -487,6 +565,22 @@ function resolveColumnNumericBounds(snapshot = {}) {
|
|
|
487
565
|
continue;
|
|
488
566
|
}
|
|
489
567
|
|
|
568
|
+
let betweenMatch = null;
|
|
569
|
+
while ((betweenMatch = NUMERIC_CHECK_CONSTRAINT_BETWEEN_PATTERN.exec(clause)) != null) {
|
|
570
|
+
const columnName = String(betweenMatch[1] || betweenMatch[2] || "");
|
|
571
|
+
const lowerValue = Number(betweenMatch[3]);
|
|
572
|
+
const upperValue = Number(betweenMatch[4]);
|
|
573
|
+
const column = numericColumnsByName.get(columnName) || null;
|
|
574
|
+
if (!column || !Number.isFinite(lowerValue) || !Number.isFinite(upperValue)) {
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
const target = getColumnBounds(columnName);
|
|
579
|
+
applyNumericConstraintBound(target, column, ">=", lowerValue);
|
|
580
|
+
applyNumericConstraintBound(target, column, "<=", upperValue);
|
|
581
|
+
}
|
|
582
|
+
NUMERIC_CHECK_CONSTRAINT_BETWEEN_PATTERN.lastIndex = 0;
|
|
583
|
+
|
|
490
584
|
let match = null;
|
|
491
585
|
while ((match = NUMERIC_CHECK_CONSTRAINT_PATTERN.exec(clause)) != null) {
|
|
492
586
|
const columnName = String(match[1] || match[2] || "");
|
|
@@ -498,76 +592,7 @@ function resolveColumnNumericBounds(snapshot = {}) {
|
|
|
498
592
|
}
|
|
499
593
|
|
|
500
594
|
const target = getColumnBounds(columnName);
|
|
501
|
-
|
|
502
|
-
let candidate = null;
|
|
503
|
-
if (operator === ">=") {
|
|
504
|
-
candidate = {
|
|
505
|
-
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
506
|
-
exclusive: false
|
|
507
|
-
};
|
|
508
|
-
} else {
|
|
509
|
-
const exclusiveStep = resolveNumericExclusiveStep(column);
|
|
510
|
-
if (exclusiveStep != null) {
|
|
511
|
-
candidate = {
|
|
512
|
-
value: normalizeNumericBoundValue(rawValue + exclusiveStep, column.numericScale),
|
|
513
|
-
exclusive: false
|
|
514
|
-
};
|
|
515
|
-
} else {
|
|
516
|
-
candidate = {
|
|
517
|
-
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
518
|
-
exclusive: true
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
const nextBound = applyLowerBound(
|
|
524
|
-
target.minimum != null || target.exclusiveMinimum != null
|
|
525
|
-
? {
|
|
526
|
-
value: target.minimum ?? target.exclusiveMinimum,
|
|
527
|
-
exclusive: target.exclusiveMinimum != null
|
|
528
|
-
}
|
|
529
|
-
: null,
|
|
530
|
-
candidate
|
|
531
|
-
);
|
|
532
|
-
target.minimum = nextBound?.exclusive === true ? null : nextBound?.value ?? null;
|
|
533
|
-
target.exclusiveMinimum = nextBound?.exclusive === true ? nextBound?.value ?? null : null;
|
|
534
|
-
continue;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
if (operator === "<=" || operator === "<") {
|
|
538
|
-
let candidate = null;
|
|
539
|
-
if (operator === "<=") {
|
|
540
|
-
candidate = {
|
|
541
|
-
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
542
|
-
exclusive: false
|
|
543
|
-
};
|
|
544
|
-
} else {
|
|
545
|
-
const exclusiveStep = resolveNumericExclusiveStep(column);
|
|
546
|
-
if (exclusiveStep != null) {
|
|
547
|
-
candidate = {
|
|
548
|
-
value: normalizeNumericBoundValue(rawValue - exclusiveStep, column.numericScale),
|
|
549
|
-
exclusive: false
|
|
550
|
-
};
|
|
551
|
-
} else {
|
|
552
|
-
candidate = {
|
|
553
|
-
value: normalizeNumericBoundValue(rawValue, column.numericScale),
|
|
554
|
-
exclusive: true
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
const nextBound = applyUpperBound(
|
|
560
|
-
target.maximum != null || target.exclusiveMaximum != null
|
|
561
|
-
? {
|
|
562
|
-
value: target.maximum ?? target.exclusiveMaximum,
|
|
563
|
-
exclusive: target.exclusiveMaximum != null
|
|
564
|
-
}
|
|
565
|
-
: null,
|
|
566
|
-
candidate
|
|
567
|
-
);
|
|
568
|
-
target.maximum = nextBound?.exclusive === true ? null : nextBound?.value ?? null;
|
|
569
|
-
target.exclusiveMaximum = nextBound?.exclusive === true ? nextBound?.value ?? null : null;
|
|
570
|
-
}
|
|
595
|
+
applyNumericConstraintBound(target, column, operator, rawValue);
|
|
571
596
|
}
|
|
572
597
|
NUMERIC_CHECK_CONSTRAINT_PATTERN.lastIndex = 0;
|
|
573
598
|
}
|
|
@@ -731,7 +756,7 @@ function renderResourceFieldSchema(column, { forOutput = false } = {}) {
|
|
|
731
756
|
return schemaExpression;
|
|
732
757
|
}
|
|
733
758
|
|
|
734
|
-
function renderResourceValidatorsImport({
|
|
759
|
+
function renderResourceValidatorsImport({ htmlTimeSchemaImports = [], recordIdValidatorImports = [] } = {}) {
|
|
735
760
|
const imports = [
|
|
736
761
|
"normalizeObjectInput",
|
|
737
762
|
"createCursorListValidator"
|
|
@@ -741,12 +766,30 @@ function renderResourceValidatorsImport({ needsHtmlTimeSchemas = false, recordId
|
|
|
741
766
|
imports.push(importName);
|
|
742
767
|
}
|
|
743
768
|
}
|
|
744
|
-
|
|
745
|
-
imports.
|
|
769
|
+
for (const importName of Array.isArray(htmlTimeSchemaImports) ? htmlTimeSchemaImports : []) {
|
|
770
|
+
if (!imports.includes(importName)) {
|
|
771
|
+
imports.push(importName);
|
|
772
|
+
}
|
|
746
773
|
}
|
|
747
774
|
return `import {\n ${imports.join(",\n ")}\n} from "@jskit-ai/kernel/shared/validators";`;
|
|
748
775
|
}
|
|
749
776
|
|
|
777
|
+
function resolveHtmlTimeSchemaImports(columns = []) {
|
|
778
|
+
const imports = [];
|
|
779
|
+
for (const column of Array.isArray(columns) ? columns : []) {
|
|
780
|
+
if (column?.typeKind !== "time") {
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
const importName = column.nullable === true
|
|
784
|
+
? "NULLABLE_HTML_TIME_STRING_SCHEMA"
|
|
785
|
+
: "HTML_TIME_STRING_SCHEMA";
|
|
786
|
+
if (!imports.includes(importName)) {
|
|
787
|
+
imports.push(importName);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return imports;
|
|
791
|
+
}
|
|
792
|
+
|
|
750
793
|
function resolveRecordIdValidatorImports(...sources) {
|
|
751
794
|
const imports = ["recordIdSchema"];
|
|
752
795
|
const joinedSource = sources
|
|
@@ -1788,7 +1831,7 @@ function buildReplacementsFromSnapshot({
|
|
|
1788
1831
|
const needsNullableDateInput = writableColumns.some(
|
|
1789
1832
|
(column) => column.typeKind === "date" && column.nullable === true
|
|
1790
1833
|
);
|
|
1791
|
-
const
|
|
1834
|
+
const htmlTimeSchemaImports = resolveHtmlTimeSchemaImports(resourceColumns);
|
|
1792
1835
|
const needsDate = resourceColumns.some((column) => column.typeKind === "date");
|
|
1793
1836
|
const needsJson = resourceColumns.some((column) => column.typeKind === "json");
|
|
1794
1837
|
const needsNormalizeText = resourceColumns.some((column) =>
|
|
@@ -1882,7 +1925,7 @@ function buildReplacementsFromSnapshot({
|
|
|
1882
1925
|
surfaceRequiresWorkspace
|
|
1883
1926
|
}),
|
|
1884
1927
|
__JSKIT_CRUD_RESOURCE_VALIDATORS_IMPORT__: renderResourceValidatorsImport({
|
|
1885
|
-
|
|
1928
|
+
htmlTimeSchemaImports,
|
|
1886
1929
|
recordIdValidatorImports: resolveRecordIdValidatorImports(
|
|
1887
1930
|
renderResourceSchemaPropertyLines(outputColumns, {
|
|
1888
1931
|
forOutput: true
|
|
@@ -808,13 +808,35 @@ test("resolveScaffoldColumns derives resource numeric bounds from check constrai
|
|
|
808
808
|
enumValues: Object.freeze([])
|
|
809
809
|
});
|
|
810
810
|
|
|
811
|
+
const severityColumn = Object.freeze({
|
|
812
|
+
name: "severity",
|
|
813
|
+
key: "severity",
|
|
814
|
+
dataType: "tinyint",
|
|
815
|
+
columnType: "tinyint unsigned",
|
|
816
|
+
typeKind: "integer",
|
|
817
|
+
nullable: true,
|
|
818
|
+
hasDefault: false,
|
|
819
|
+
defaultValue: null,
|
|
820
|
+
autoIncrement: false,
|
|
821
|
+
unsigned: true,
|
|
822
|
+
extra: "",
|
|
823
|
+
maxLength: null,
|
|
824
|
+
numericPrecision: 3,
|
|
825
|
+
numericScale: 0,
|
|
826
|
+
datetimePrecision: null,
|
|
827
|
+
characterSetName: "",
|
|
828
|
+
collationName: "",
|
|
829
|
+
enumValues: Object.freeze([])
|
|
830
|
+
});
|
|
831
|
+
|
|
811
832
|
const scaffoldColumns = __testables.resolveScaffoldColumns({
|
|
812
833
|
...snapshot,
|
|
813
834
|
columns: Object.freeze([
|
|
814
835
|
snapshot.columns[0],
|
|
815
836
|
inputWeightColumn,
|
|
816
837
|
batchedDailySequenceColumn,
|
|
817
|
-
moistureLevelColumn
|
|
838
|
+
moistureLevelColumn,
|
|
839
|
+
severityColumn
|
|
818
840
|
]),
|
|
819
841
|
checkConstraints: Object.freeze([
|
|
820
842
|
Object.freeze({
|
|
@@ -828,6 +850,10 @@ test("resolveScaffoldColumns derives resource numeric bounds from check constrai
|
|
|
828
850
|
Object.freeze({
|
|
829
851
|
name: "chk_batches_moisture_level",
|
|
830
852
|
clause: "`moisture_level` is null or `moisture_level` >= 0 and `moisture_level` <= 100"
|
|
853
|
+
}),
|
|
854
|
+
Object.freeze({
|
|
855
|
+
name: "chk_pet_notes_severity",
|
|
856
|
+
clause: "`severity` is null or `severity` between 1 and 10"
|
|
831
857
|
})
|
|
832
858
|
])
|
|
833
859
|
});
|
|
@@ -835,6 +861,7 @@ test("resolveScaffoldColumns derives resource numeric bounds from check constrai
|
|
|
835
861
|
const inputWeight = scaffoldColumns.find((column) => column.name === "input_weight");
|
|
836
862
|
const batchedDailySequence = scaffoldColumns.find((column) => column.name === "batched_daily_sequence");
|
|
837
863
|
const moistureLevel = scaffoldColumns.find((column) => column.name === "moisture_level");
|
|
864
|
+
const severity = scaffoldColumns.find((column) => column.name === "severity");
|
|
838
865
|
|
|
839
866
|
assert.equal(
|
|
840
867
|
__testables.renderResourceFieldSchema(inputWeight),
|
|
@@ -848,6 +875,10 @@ test("resolveScaffoldColumns derives resource numeric bounds from check constrai
|
|
|
848
875
|
__testables.renderResourceFieldSchema(moistureLevel),
|
|
849
876
|
"Type.Union([Type.Number({ minimum: 0, maximum: 100 }), Type.Null()])"
|
|
850
877
|
);
|
|
878
|
+
assert.equal(
|
|
879
|
+
__testables.renderResourceFieldSchema(severity),
|
|
880
|
+
"Type.Union([Type.Integer({ minimum: 1, maximum: 10 }), Type.Null()])"
|
|
881
|
+
);
|
|
851
882
|
});
|
|
852
883
|
|
|
853
884
|
test("buildReplacementsFromSnapshot normalizes nullable temporal inputs without invalid date errors", () => {
|
|
@@ -1056,7 +1087,11 @@ test("buildReplacementsFromSnapshot uses shared framework time schemas in genera
|
|
|
1056
1087
|
|
|
1057
1088
|
assert.match(
|
|
1058
1089
|
replacements.__JSKIT_CRUD_RESOURCE_VALIDATORS_IMPORT__,
|
|
1059
|
-
/NULLABLE_HTML_TIME_STRING_SCHEMA/
|
|
1090
|
+
/(^|\n)\s*NULLABLE_HTML_TIME_STRING_SCHEMA(,|\n)/m
|
|
1091
|
+
);
|
|
1092
|
+
assert.doesNotMatch(
|
|
1093
|
+
replacements.__JSKIT_CRUD_RESOURCE_VALIDATORS_IMPORT__,
|
|
1094
|
+
/(^|\n)\s*HTML_TIME_STRING_SCHEMA(,|\n)/m
|
|
1060
1095
|
);
|
|
1061
1096
|
assert.match(
|
|
1062
1097
|
replacements.__JSKIT_CRUD_RESOURCE_OUTPUT_SCHEMA_PROPERTIES__,
|
|
@@ -1072,6 +1107,54 @@ test("buildReplacementsFromSnapshot uses shared framework time schemas in genera
|
|
|
1072
1107
|
);
|
|
1073
1108
|
});
|
|
1074
1109
|
|
|
1110
|
+
test("buildReplacementsFromSnapshot imports only the non-nullable time schema when nullable time fields are absent", () => {
|
|
1111
|
+
const snapshot = createSnapshot({
|
|
1112
|
+
tableName: "opening_hours"
|
|
1113
|
+
});
|
|
1114
|
+
const timeColumn = Object.freeze({
|
|
1115
|
+
name: "from_time",
|
|
1116
|
+
key: "fromTime",
|
|
1117
|
+
dataType: "time",
|
|
1118
|
+
columnType: "time",
|
|
1119
|
+
typeKind: "time",
|
|
1120
|
+
nullable: false,
|
|
1121
|
+
hasDefault: false,
|
|
1122
|
+
defaultValue: null,
|
|
1123
|
+
autoIncrement: false,
|
|
1124
|
+
unsigned: false,
|
|
1125
|
+
extra: "",
|
|
1126
|
+
maxLength: null,
|
|
1127
|
+
numericPrecision: null,
|
|
1128
|
+
numericScale: null,
|
|
1129
|
+
enumValues: Object.freeze([])
|
|
1130
|
+
});
|
|
1131
|
+
const replacements = __testables.buildReplacementsFromSnapshot({
|
|
1132
|
+
namespace: "opening-hours",
|
|
1133
|
+
snapshot: {
|
|
1134
|
+
...snapshot,
|
|
1135
|
+
columns: Object.freeze([...snapshot.columns, timeColumn])
|
|
1136
|
+
},
|
|
1137
|
+
resolvedOwnershipFilter: "workspace_user"
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
assert.match(
|
|
1141
|
+
replacements.__JSKIT_CRUD_RESOURCE_VALIDATORS_IMPORT__,
|
|
1142
|
+
/(^|\n)\s*HTML_TIME_STRING_SCHEMA(,|\n)/m
|
|
1143
|
+
);
|
|
1144
|
+
assert.doesNotMatch(
|
|
1145
|
+
replacements.__JSKIT_CRUD_RESOURCE_VALIDATORS_IMPORT__,
|
|
1146
|
+
/(^|\n)\s*NULLABLE_HTML_TIME_STRING_SCHEMA(,|\n)/m
|
|
1147
|
+
);
|
|
1148
|
+
assert.match(
|
|
1149
|
+
replacements.__JSKIT_CRUD_RESOURCE_OUTPUT_SCHEMA_PROPERTIES__,
|
|
1150
|
+
/fromTime: HTML_TIME_STRING_SCHEMA/
|
|
1151
|
+
);
|
|
1152
|
+
assert.match(
|
|
1153
|
+
replacements.__JSKIT_CRUD_RESOURCE_CREATE_SCHEMA_PROPERTIES__,
|
|
1154
|
+
/fromTime: HTML_TIME_STRING_SCHEMA/
|
|
1155
|
+
);
|
|
1156
|
+
});
|
|
1157
|
+
|
|
1075
1158
|
test("buildReplacementsFromSnapshot only imports record-id validator helpers that the resource actually uses", () => {
|
|
1076
1159
|
const snapshot = createSnapshot({
|
|
1077
1160
|
tableName: "pollen_types",
|