@bleedingdev/modern-js-backend-federation-contracts 0.0.0 → 3.9.0-ultramodern.5
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/LICENSE +21 -0
- package/dist/cjs/backend-federation-contract/build-artifact.js +185 -0
- package/dist/cjs/backend-federation-contract/constants.js +92 -0
- package/dist/cjs/backend-federation-contract/delivery-unit.js +130 -0
- package/dist/cjs/backend-federation-contract/index.js +137 -0
- package/dist/cjs/backend-federation-contract/metadata.js +133 -0
- package/dist/cjs/backend-federation-contract/types.js +18 -0
- package/dist/cjs/backend-federation-contract/validation-core.js +85 -0
- package/dist/esm/backend-federation-contract/build-artifact.mjs +135 -0
- package/dist/esm/backend-federation-contract/constants.mjs +18 -0
- package/dist/esm/backend-federation-contract/delivery-unit.mjs +74 -0
- package/dist/esm/backend-federation-contract/index.mjs +5 -0
- package/dist/esm/backend-federation-contract/metadata.mjs +80 -0
- package/dist/esm/backend-federation-contract/types.mjs +0 -0
- package/dist/esm/backend-federation-contract/validation-core.mjs +29 -0
- package/dist/esm-node/backend-federation-contract/build-artifact.mjs +136 -0
- package/dist/esm-node/backend-federation-contract/constants.mjs +19 -0
- package/dist/esm-node/backend-federation-contract/delivery-unit.mjs +75 -0
- package/dist/esm-node/backend-federation-contract/index.mjs +6 -0
- package/dist/esm-node/backend-federation-contract/metadata.mjs +81 -0
- package/dist/esm-node/backend-federation-contract/types.mjs +1 -0
- package/dist/esm-node/backend-federation-contract/validation-core.mjs +30 -0
- package/dist/types/backend-federation-contract/build-artifact.d.ts +9 -0
- package/dist/types/backend-federation-contract/constants.d.ts +14 -0
- package/dist/types/backend-federation-contract/delivery-unit.d.ts +9 -0
- package/dist/types/backend-federation-contract/index.d.ts +7 -0
- package/dist/types/backend-federation-contract/metadata.d.ts +7 -0
- package/dist/types/backend-federation-contract/types.d.ts +60 -0
- package/dist/types/backend-federation-contract/validation-core.d.ts +8 -0
- package/package.json +38 -5
- package/src/backend-federation-contract/build-artifact.ts +224 -0
- package/src/backend-federation-contract/constants.ts +33 -0
- package/src/backend-federation-contract/delivery-unit.ts +170 -0
- package/src/backend-federation-contract/index.ts +56 -0
- package/src/backend-federation-contract/metadata.ts +225 -0
- package/src/backend-federation-contract/types.ts +73 -0
- package/src/backend-federation-contract/validation-core.ts +67 -0
- package/README.md +0 -3
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
31
|
+
backendFederationExposeNames: ()=>backendFederationExposeNames,
|
|
32
|
+
backendFederationMetadata: ()=>backendFederationMetadata,
|
|
33
|
+
backendFederationVersionBoundary: ()=>backendFederationVersionBoundary,
|
|
34
|
+
toBackendFederationExposeNames: ()=>toBackendFederationExposeNames,
|
|
35
|
+
validateBackendFederationManifest: ()=>validateBackendFederationManifest,
|
|
36
|
+
validateBackendFederationMetadata: ()=>validateBackendFederationMetadata
|
|
37
|
+
});
|
|
38
|
+
const external_constants_js_namespaceObject = require("./constants.js");
|
|
39
|
+
const external_delivery_unit_js_namespaceObject = require("./delivery-unit.js");
|
|
40
|
+
const external_validation_core_js_namespaceObject = require("./validation-core.js");
|
|
41
|
+
const toBackendFederationExposeNames = (value)=>{
|
|
42
|
+
const names = [];
|
|
43
|
+
if (Array.isArray(value)) for (const expose of value){
|
|
44
|
+
const name = (0, external_validation_core_js_namespaceObject.nonEmptyString)(expose) ?? ((0, external_validation_core_js_namespaceObject.isRecord)(expose) ? (0, external_validation_core_js_namespaceObject.nonEmptyString)(expose.name) : void 0);
|
|
45
|
+
if (name) names.push(name);
|
|
46
|
+
}
|
|
47
|
+
else if ((0, external_validation_core_js_namespaceObject.isRecord)(value)) names.push(...Object.keys(value).filter((name)=>name.length > 0));
|
|
48
|
+
return Array.from(new Set(names));
|
|
49
|
+
};
|
|
50
|
+
const backendFederationExposeNames = (value)=>{
|
|
51
|
+
if (!(0, external_validation_core_js_namespaceObject.isRecord)(value)) return [];
|
|
52
|
+
const exposes = toBackendFederationExposeNames(value.exposes);
|
|
53
|
+
const expose = (0, external_validation_core_js_namespaceObject.nonEmptyString)(value.expose);
|
|
54
|
+
return Array.from(new Set([
|
|
55
|
+
...exposes,
|
|
56
|
+
...expose ? [
|
|
57
|
+
expose
|
|
58
|
+
] : []
|
|
59
|
+
]));
|
|
60
|
+
};
|
|
61
|
+
const backendFederationMetadata = (value)=>(0, external_validation_core_js_namespaceObject.isRecord)(value) ? (0, external_validation_core_js_namespaceObject.recordField)(value, 'backendFederation') : void 0;
|
|
62
|
+
const backendFederationVersionBoundary = (value)=>(0, external_validation_core_js_namespaceObject.recordField)(backendFederationMetadata(value), 'versionBoundary');
|
|
63
|
+
const validateBackendFederationMetadata = (value, options = {})=>{
|
|
64
|
+
const path = options.path ?? 'backendFederation';
|
|
65
|
+
const errors = [];
|
|
66
|
+
if (!(0, external_validation_core_js_namespaceObject.isRecord)(value)) {
|
|
67
|
+
(0, external_validation_core_js_namespaceObject.addError)(errors, path, 'must be an object.');
|
|
68
|
+
return (0, external_validation_core_js_namespaceObject.validationResult)(errors);
|
|
69
|
+
}
|
|
70
|
+
if (options.requireEffectRuntime && 'effect' !== value.runtimeFramework) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.runtimeFramework`, 'must be "effect".');
|
|
71
|
+
if (options.requireEffectRuntime && true !== value.strictEffectApproach) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.strictEffectApproach`, 'must be true.');
|
|
72
|
+
(0, external_validation_core_js_namespaceObject.validateVersionField)(errors, value, 'contractVersion', options.expectedContractVersion ?? external_constants_js_namespaceObject.BACKEND_FEDERATION_CONTRACT_VERSION, path, options.requireVersionFields ?? false);
|
|
73
|
+
(0, external_validation_core_js_namespaceObject.validateVersionField)(errors, value, 'nodeAdapterVersion', options.expectedNodeAdapterVersion ?? external_constants_js_namespaceObject.BACKEND_FEDERATION_NODE_ADAPTER_VERSION, path, options.requireVersionFields ?? false);
|
|
74
|
+
if (options.requireEffectExpose && !backendFederationExposeNames(value).includes(external_constants_js_namespaceObject.BACKEND_FEDERATION_EFFECT_EXPOSE)) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.expose`, `must include "${external_constants_js_namespaceObject.BACKEND_FEDERATION_EFFECT_EXPOSE}".`);
|
|
75
|
+
if (options.validateDeliveryUnit ?? true) {
|
|
76
|
+
const deliveryUnit = (0, external_validation_core_js_namespaceObject.recordField)(value, 'deliveryUnit');
|
|
77
|
+
if (deliveryUnit) errors.push(...(0, external_delivery_unit_js_namespaceObject.validateDeliveryUnitContractBlock)(deliveryUnit, {
|
|
78
|
+
path: `${path}.deliveryUnit`
|
|
79
|
+
}).errors);
|
|
80
|
+
const versionBoundary = (0, external_validation_core_js_namespaceObject.recordField)(value, 'versionBoundary');
|
|
81
|
+
const versionBoundaryDeliveryUnit = (0, external_validation_core_js_namespaceObject.recordField)(versionBoundary, 'deliveryUnit');
|
|
82
|
+
if (versionBoundaryDeliveryUnit) errors.push(...(0, external_delivery_unit_js_namespaceObject.validateDeliveryUnitBoundaryIdentity)(versionBoundaryDeliveryUnit, `${path}.versionBoundary.deliveryUnit`));
|
|
83
|
+
if (deliveryUnit && versionBoundaryDeliveryUnit) for (const field of external_constants_js_namespaceObject.DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
84
|
+
const deliveryUnitValue = (0, external_delivery_unit_js_namespaceObject.deliveryUnitIdentityFieldValue)(deliveryUnit, field);
|
|
85
|
+
const versionBoundaryDeliveryUnitValue = (0, external_delivery_unit_js_namespaceObject.deliveryUnitIdentityFieldValue)(versionBoundaryDeliveryUnit, field);
|
|
86
|
+
if (deliveryUnitValue && versionBoundaryDeliveryUnitValue && deliveryUnitValue !== versionBoundaryDeliveryUnitValue) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.versionBoundary.deliveryUnit.${field}`, `must match ${path}.deliveryUnit.${field}.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return (0, external_validation_core_js_namespaceObject.validationResult)(errors);
|
|
90
|
+
};
|
|
91
|
+
const validateBackendFederationManifest = (value, options = {})=>{
|
|
92
|
+
const path = options.path ?? 'manifest';
|
|
93
|
+
const errors = [];
|
|
94
|
+
if (!(0, external_validation_core_js_namespaceObject.isRecord)(value)) {
|
|
95
|
+
(0, external_validation_core_js_namespaceObject.addError)(errors, path, 'must be an object.');
|
|
96
|
+
return (0, external_validation_core_js_namespaceObject.validationResult)(errors);
|
|
97
|
+
}
|
|
98
|
+
if (void 0 !== value.schemaVersion && value.schemaVersion !== external_constants_js_namespaceObject.DELIVERY_UNIT_SCHEMA_VERSION) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.schemaVersion`, `must be ${external_constants_js_namespaceObject.DELIVERY_UNIT_SCHEMA_VERSION}.`);
|
|
99
|
+
const metadata = backendFederationMetadata(value);
|
|
100
|
+
if (metadata) errors.push(...validateBackendFederationMetadata(metadata, {
|
|
101
|
+
...options,
|
|
102
|
+
path: `${path}.backendFederation`,
|
|
103
|
+
requireEffectExpose: false
|
|
104
|
+
}).errors);
|
|
105
|
+
else if (options.requireBackendFederation ?? true) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.backendFederation`, 'must be an object.');
|
|
106
|
+
if (options.requireEffectExpose) {
|
|
107
|
+
const topLevelExposeNames = toBackendFederationExposeNames(value.exposes);
|
|
108
|
+
const metadataExposeNames = backendFederationExposeNames(metadata);
|
|
109
|
+
const exposeNames = new Set([
|
|
110
|
+
...topLevelExposeNames,
|
|
111
|
+
...metadataExposeNames
|
|
112
|
+
]);
|
|
113
|
+
if (!exposeNames.has(external_constants_js_namespaceObject.BACKEND_FEDERATION_EFFECT_EXPOSE)) (0, external_validation_core_js_namespaceObject.addError)(errors, `${path}.exposes`, `must include "${external_constants_js_namespaceObject.BACKEND_FEDERATION_EFFECT_EXPOSE}".`);
|
|
114
|
+
}
|
|
115
|
+
return (0, external_validation_core_js_namespaceObject.validationResult)(errors);
|
|
116
|
+
};
|
|
117
|
+
exports.backendFederationExposeNames = __webpack_exports__.backendFederationExposeNames;
|
|
118
|
+
exports.backendFederationMetadata = __webpack_exports__.backendFederationMetadata;
|
|
119
|
+
exports.backendFederationVersionBoundary = __webpack_exports__.backendFederationVersionBoundary;
|
|
120
|
+
exports.toBackendFederationExposeNames = __webpack_exports__.toBackendFederationExposeNames;
|
|
121
|
+
exports.validateBackendFederationManifest = __webpack_exports__.validateBackendFederationManifest;
|
|
122
|
+
exports.validateBackendFederationMetadata = __webpack_exports__.validateBackendFederationMetadata;
|
|
123
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
124
|
+
"backendFederationExposeNames",
|
|
125
|
+
"backendFederationMetadata",
|
|
126
|
+
"backendFederationVersionBoundary",
|
|
127
|
+
"toBackendFederationExposeNames",
|
|
128
|
+
"validateBackendFederationManifest",
|
|
129
|
+
"validateBackendFederationMetadata"
|
|
130
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
131
|
+
Object.defineProperty(exports, '__esModule', {
|
|
132
|
+
value: true
|
|
133
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.r = (exports1)=>{
|
|
5
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
6
|
+
value: 'Module'
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
})();
|
|
13
|
+
var __webpack_exports__ = {};
|
|
14
|
+
__webpack_require__.r(__webpack_exports__);
|
|
15
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
const isRecord = (value)=>'object' == typeof value && null !== value && !Array.isArray(value);
|
|
31
|
+
const nonEmptyString = (value)=>'string' == typeof value && value.trim().length > 0 ? value : void 0;
|
|
32
|
+
const validationResult = (errors)=>({
|
|
33
|
+
ok: 0 === errors.length,
|
|
34
|
+
errors
|
|
35
|
+
});
|
|
36
|
+
const addError = (errors, path, message)=>{
|
|
37
|
+
errors.push({
|
|
38
|
+
path,
|
|
39
|
+
message
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const recordField = (value, field)=>{
|
|
43
|
+
const fieldValue = value?.[field];
|
|
44
|
+
return isRecord(fieldValue) ? fieldValue : void 0;
|
|
45
|
+
};
|
|
46
|
+
const formatBackendFederationValidationErrors = (errors)=>errors.map((error)=>`${error.path}: ${error.message}`).join('; ');
|
|
47
|
+
const validateVersionField = (errors, record, field, expected, path, required)=>{
|
|
48
|
+
const compatibility = recordField(record, 'compatibility');
|
|
49
|
+
const executionSurfaces = recordField(record, 'executionSurfaces');
|
|
50
|
+
const nodeSurface = recordField(executionSurfaces, 'node');
|
|
51
|
+
const actual = nonEmptyString(record[field]) ?? nonEmptyString(compatibility?.[field]) ?? ('nodeAdapterVersion' === field ? nonEmptyString(nodeSurface?.adapterVersion) : void 0);
|
|
52
|
+
if (!actual) {
|
|
53
|
+
if (required) addError(errors, `${path}.${field}`, 'must be a non-empty string.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (false !== expected && actual !== expected) addError(errors, `${path}.${field}`, `must be "${expected}".`);
|
|
57
|
+
};
|
|
58
|
+
__webpack_require__.d(__webpack_exports__, {}, {
|
|
59
|
+
addError: addError,
|
|
60
|
+
formatBackendFederationValidationErrors: formatBackendFederationValidationErrors,
|
|
61
|
+
isRecord: isRecord,
|
|
62
|
+
nonEmptyString: nonEmptyString,
|
|
63
|
+
recordField: recordField,
|
|
64
|
+
validateVersionField: validateVersionField,
|
|
65
|
+
validationResult: validationResult
|
|
66
|
+
});
|
|
67
|
+
exports.addError = __webpack_exports__.addError;
|
|
68
|
+
exports.formatBackendFederationValidationErrors = __webpack_exports__.formatBackendFederationValidationErrors;
|
|
69
|
+
exports.isRecord = __webpack_exports__.isRecord;
|
|
70
|
+
exports.nonEmptyString = __webpack_exports__.nonEmptyString;
|
|
71
|
+
exports.recordField = __webpack_exports__.recordField;
|
|
72
|
+
exports.validateVersionField = __webpack_exports__.validateVersionField;
|
|
73
|
+
exports.validationResult = __webpack_exports__.validationResult;
|
|
74
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
75
|
+
"addError",
|
|
76
|
+
"formatBackendFederationValidationErrors",
|
|
77
|
+
"isRecord",
|
|
78
|
+
"nonEmptyString",
|
|
79
|
+
"recordField",
|
|
80
|
+
"validateVersionField",
|
|
81
|
+
"validationResult"
|
|
82
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
83
|
+
Object.defineProperty(exports, '__esModule', {
|
|
84
|
+
value: true
|
|
85
|
+
});
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { DELIVERY_UNIT_IDENTITY_FIELDS, DELIVERY_UNIT_SCHEMA_VERSION } from "./constants.mjs";
|
|
2
|
+
import { deliveryUnitIdentityFieldValue, validateDeliveryUnitRecord } from "./delivery-unit.mjs";
|
|
3
|
+
import { addError, isRecord, nonEmptyString, recordField, validationResult } from "./validation-core.mjs";
|
|
4
|
+
const createUltramodernBuildArtifact = (record)=>{
|
|
5
|
+
const deliveryUnit = {
|
|
6
|
+
appId: record.appId,
|
|
7
|
+
build: record.buildMarker,
|
|
8
|
+
buildMarker: record.buildMarker,
|
|
9
|
+
deployProfile: record.deployProfile,
|
|
10
|
+
kind: record.kind,
|
|
11
|
+
packageName: record.packageName,
|
|
12
|
+
schemaVersion: record.schemaVersion,
|
|
13
|
+
sourceRevision: record.sourceRevision,
|
|
14
|
+
unitId: record.unitId,
|
|
15
|
+
version: record.version
|
|
16
|
+
};
|
|
17
|
+
const api = {
|
|
18
|
+
appId: deliveryUnit.appId,
|
|
19
|
+
build: deliveryUnit.build,
|
|
20
|
+
buildMarker: deliveryUnit.buildMarker,
|
|
21
|
+
deployProfile: deliveryUnit.deployProfile,
|
|
22
|
+
kind: deliveryUnit.kind,
|
|
23
|
+
packageName: deliveryUnit.packageName,
|
|
24
|
+
schemaVersion: deliveryUnit.schemaVersion,
|
|
25
|
+
sourceRevision: deliveryUnit.sourceRevision,
|
|
26
|
+
surface: 'api',
|
|
27
|
+
unitId: deliveryUnit.unitId,
|
|
28
|
+
version: deliveryUnit.version
|
|
29
|
+
};
|
|
30
|
+
const ui = {
|
|
31
|
+
appId: deliveryUnit.appId,
|
|
32
|
+
build: deliveryUnit.build,
|
|
33
|
+
buildMarker: deliveryUnit.buildMarker,
|
|
34
|
+
deployProfile: deliveryUnit.deployProfile,
|
|
35
|
+
kind: deliveryUnit.kind,
|
|
36
|
+
packageName: deliveryUnit.packageName,
|
|
37
|
+
schemaVersion: deliveryUnit.schemaVersion,
|
|
38
|
+
sourceRevision: deliveryUnit.sourceRevision,
|
|
39
|
+
surface: 'ui',
|
|
40
|
+
unitId: deliveryUnit.unitId,
|
|
41
|
+
version: deliveryUnit.version
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
deliveryUnit,
|
|
45
|
+
kind: 'ultramodern-build-artifact',
|
|
46
|
+
schemaVersion: DELIVERY_UNIT_SCHEMA_VERSION,
|
|
47
|
+
surfaces: {
|
|
48
|
+
api,
|
|
49
|
+
ui
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const validateUltramodernBuildArtifact = (value, path = 'artifact')=>{
|
|
54
|
+
const errors = [];
|
|
55
|
+
if (!isRecord(value)) {
|
|
56
|
+
addError(errors, path, 'must be an object.');
|
|
57
|
+
return validationResult(errors);
|
|
58
|
+
}
|
|
59
|
+
if (value.schemaVersion !== DELIVERY_UNIT_SCHEMA_VERSION) addError(errors, `${path}.schemaVersion`, `must be ${DELIVERY_UNIT_SCHEMA_VERSION}.`);
|
|
60
|
+
if ('ultramodern-build-artifact' !== value.kind) addError(errors, `${path}.kind`, 'must be "ultramodern-build-artifact".');
|
|
61
|
+
const deliveryUnit = value.deliveryUnit;
|
|
62
|
+
errors.push(...validateDeliveryUnitRecord(deliveryUnit, {
|
|
63
|
+
path: `${path}.deliveryUnit`,
|
|
64
|
+
allowBuildAlias: true
|
|
65
|
+
}).errors);
|
|
66
|
+
if (isRecord(deliveryUnit)) {
|
|
67
|
+
const build = nonEmptyString(deliveryUnit.build);
|
|
68
|
+
const buildMarker = nonEmptyString(deliveryUnit.buildMarker);
|
|
69
|
+
if (build) {
|
|
70
|
+
if (buildMarker && build !== buildMarker) addError(errors, `${path}.deliveryUnit.build`, 'must match deliveryUnit.buildMarker.');
|
|
71
|
+
} else addError(errors, `${path}.deliveryUnit.build`, 'must be a non-empty string.');
|
|
72
|
+
}
|
|
73
|
+
const surfaces = recordField(value, 'surfaces');
|
|
74
|
+
if (!surfaces) {
|
|
75
|
+
addError(errors, `${path}.surfaces`, 'must be an object.');
|
|
76
|
+
return validationResult(errors);
|
|
77
|
+
}
|
|
78
|
+
for (const surface of [
|
|
79
|
+
'ui',
|
|
80
|
+
'api'
|
|
81
|
+
]){
|
|
82
|
+
const marker = surfaces[surface];
|
|
83
|
+
const markerPath = `${path}.surfaces.${surface}`;
|
|
84
|
+
errors.push(...validateDeliveryUnitRecord(marker, {
|
|
85
|
+
path: markerPath,
|
|
86
|
+
allowBuildAlias: true
|
|
87
|
+
}).errors);
|
|
88
|
+
if (!isRecord(marker)) continue;
|
|
89
|
+
const markerBuild = nonEmptyString(marker.build);
|
|
90
|
+
const markerBuildMarker = nonEmptyString(marker.buildMarker);
|
|
91
|
+
if (markerBuild) {
|
|
92
|
+
if (markerBuildMarker && markerBuild !== markerBuildMarker) addError(errors, `${markerPath}.build`, 'must match buildMarker.');
|
|
93
|
+
} else addError(errors, `${markerPath}.build`, 'must be non-empty string.');
|
|
94
|
+
if (marker.surface !== surface) addError(errors, `${markerPath}.surface`, `must be "${surface}".`);
|
|
95
|
+
for (const field of DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
96
|
+
const deliveryUnitValue = deliveryUnitIdentityFieldValue(deliveryUnit, field, {
|
|
97
|
+
allowBuildAlias: true
|
|
98
|
+
});
|
|
99
|
+
const markerValue = deliveryUnitIdentityFieldValue(marker, field, {
|
|
100
|
+
allowBuildAlias: true
|
|
101
|
+
});
|
|
102
|
+
if (void 0 !== deliveryUnitValue && void 0 !== markerValue && deliveryUnitValue !== markerValue) addError(errors, `${markerPath}.${field}`, `must match ${path}.deliveryUnit.${field}.`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return validationResult(errors);
|
|
106
|
+
};
|
|
107
|
+
const isUltramodernBuildArtifact = (value)=>validateUltramodernBuildArtifact(value).ok;
|
|
108
|
+
const stampUltramodernBuildArtifactIdentity = (artifact, identity)=>({
|
|
109
|
+
...artifact,
|
|
110
|
+
deliveryUnit: {
|
|
111
|
+
...artifact.deliveryUnit,
|
|
112
|
+
build: identity.buildMarker,
|
|
113
|
+
buildMarker: identity.buildMarker,
|
|
114
|
+
sourceRevision: identity.sourceRevision
|
|
115
|
+
},
|
|
116
|
+
surfaces: {
|
|
117
|
+
ui: {
|
|
118
|
+
...artifact.surfaces.ui,
|
|
119
|
+
build: identity.buildMarker,
|
|
120
|
+
buildMarker: identity.buildMarker,
|
|
121
|
+
sourceRevision: identity.sourceRevision
|
|
122
|
+
},
|
|
123
|
+
api: {
|
|
124
|
+
...artifact.surfaces.api,
|
|
125
|
+
build: identity.buildMarker,
|
|
126
|
+
buildMarker: identity.buildMarker,
|
|
127
|
+
sourceRevision: identity.sourceRevision
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
const stampUltramodernBuildArtifactSourceRevision = (artifact, sourceRevision)=>stampUltramodernBuildArtifactIdentity(artifact, {
|
|
132
|
+
buildMarker: artifact.deliveryUnit.buildMarker,
|
|
133
|
+
sourceRevision
|
|
134
|
+
});
|
|
135
|
+
export { createUltramodernBuildArtifact, isUltramodernBuildArtifact, stampUltramodernBuildArtifactIdentity, stampUltramodernBuildArtifactSourceRevision, validateUltramodernBuildArtifact };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const BACKEND_FEDERATION_EFFECT_EXPOSE = './effect-api';
|
|
2
|
+
const BACKEND_FEDERATION_MANIFEST_FILE = 'backend-mf-manifest.json';
|
|
3
|
+
const BACKEND_FEDERATION_REMOTE_ENTRY_FILE = 'backendRemoteEntry.cjs';
|
|
4
|
+
const BACKEND_FEDERATION_CONTRACT_VERSION = 'microvertical-server-effect-v1';
|
|
5
|
+
const BACKEND_FEDERATION_NODE_ADAPTER_VERSION = 'backend-mf-effect-v1';
|
|
6
|
+
const DELIVERY_UNIT_SCHEMA_VERSION = 1;
|
|
7
|
+
const DELIVERY_UNIT_KIND = 'microvertical-delivery-unit';
|
|
8
|
+
const DELIVERY_UNIT_DEPLOY_PROFILE = 'cloudflare-ssr-mf-effect-v1';
|
|
9
|
+
const DELIVERY_UNIT_IDENTITY_FIELDS = [
|
|
10
|
+
'unitId',
|
|
11
|
+
'buildMarker',
|
|
12
|
+
'sourceRevision'
|
|
13
|
+
];
|
|
14
|
+
const ULTRAMODERN_BUILD_ARTIFACT_FILE = 'ultramodern-build.json';
|
|
15
|
+
const ULTRAMODERN_BUILD_ARTIFACT_PATH = `shared/${ULTRAMODERN_BUILD_ARTIFACT_FILE}`;
|
|
16
|
+
const ULTRAMODERN_BUILD_MODULE_FILE = 'ultramodern-build.ts';
|
|
17
|
+
const ULTRAMODERN_BUILD_MODULE_PATH = `shared/${ULTRAMODERN_BUILD_MODULE_FILE}`;
|
|
18
|
+
export { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION, BACKEND_FEDERATION_REMOTE_ENTRY_FILE, DELIVERY_UNIT_DEPLOY_PROFILE, DELIVERY_UNIT_IDENTITY_FIELDS, DELIVERY_UNIT_KIND, DELIVERY_UNIT_SCHEMA_VERSION, ULTRAMODERN_BUILD_ARTIFACT_FILE, ULTRAMODERN_BUILD_ARTIFACT_PATH, ULTRAMODERN_BUILD_MODULE_FILE, ULTRAMODERN_BUILD_MODULE_PATH };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { DELIVERY_UNIT_DEPLOY_PROFILE, DELIVERY_UNIT_IDENTITY_FIELDS, DELIVERY_UNIT_KIND, DELIVERY_UNIT_SCHEMA_VERSION } from "./constants.mjs";
|
|
2
|
+
import { addError, isRecord, nonEmptyString, validationResult } from "./validation-core.mjs";
|
|
3
|
+
const deliveryUnitIdentityFieldValue = (value, field, options = {})=>{
|
|
4
|
+
if (!isRecord(value)) return;
|
|
5
|
+
if ('buildMarker' === field && options.allowBuildAlias) return nonEmptyString(value.buildMarker) ?? nonEmptyString(value.build);
|
|
6
|
+
return nonEmptyString(value[field]);
|
|
7
|
+
};
|
|
8
|
+
const validateDeliveryUnitIdentity = (value, options = {})=>{
|
|
9
|
+
const path = options.path ?? 'deliveryUnit';
|
|
10
|
+
const errors = [];
|
|
11
|
+
if (!isRecord(value)) {
|
|
12
|
+
addError(errors, path, 'must be an object.');
|
|
13
|
+
return validationResult(errors);
|
|
14
|
+
}
|
|
15
|
+
for (const field of DELIVERY_UNIT_IDENTITY_FIELDS)if (!deliveryUnitIdentityFieldValue(value, field, options)) addError(errors, `${path}.${field}`, 'must be a non-empty string.');
|
|
16
|
+
return validationResult(errors);
|
|
17
|
+
};
|
|
18
|
+
const validateDeliveryUnitContractBlock = (value, options = {})=>{
|
|
19
|
+
const path = options.path ?? 'deliveryUnit';
|
|
20
|
+
const errors = [
|
|
21
|
+
...validateDeliveryUnitIdentity(value, options).errors
|
|
22
|
+
];
|
|
23
|
+
if (!isRecord(value)) return validationResult(errors);
|
|
24
|
+
if (value.schemaVersion !== DELIVERY_UNIT_SCHEMA_VERSION) addError(errors, `${path}.schemaVersion`, `must be ${DELIVERY_UNIT_SCHEMA_VERSION}.`);
|
|
25
|
+
if (value.kind !== DELIVERY_UNIT_KIND) addError(errors, `${path}.kind`, `must be "${DELIVERY_UNIT_KIND}".`);
|
|
26
|
+
if (!nonEmptyString(value.packageName)) addError(errors, `${path}.packageName`, 'must be a non-empty string.');
|
|
27
|
+
if (!nonEmptyString(value.version)) addError(errors, `${path}.version`, 'must be a non-empty string.');
|
|
28
|
+
return validationResult(errors);
|
|
29
|
+
};
|
|
30
|
+
const validateDeliveryUnitRecord = (value, options = {})=>{
|
|
31
|
+
const path = options.path ?? 'deliveryUnit';
|
|
32
|
+
const errors = [
|
|
33
|
+
...validateDeliveryUnitContractBlock(value, {
|
|
34
|
+
...options,
|
|
35
|
+
path
|
|
36
|
+
}).errors
|
|
37
|
+
];
|
|
38
|
+
if (!isRecord(value)) return validationResult(errors);
|
|
39
|
+
if (!nonEmptyString(value.appId)) addError(errors, `${path}.appId`, 'must be a non-empty string.');
|
|
40
|
+
if (value.deployProfile !== DELIVERY_UNIT_DEPLOY_PROFILE) addError(errors, `${path}.deployProfile`, `must be "${DELIVERY_UNIT_DEPLOY_PROFILE}".`);
|
|
41
|
+
return validationResult(errors);
|
|
42
|
+
};
|
|
43
|
+
const validateDeliveryUnitBoundaryIdentity = (value, path)=>{
|
|
44
|
+
const errors = [];
|
|
45
|
+
if (!isRecord(value)) {
|
|
46
|
+
addError(errors, path, 'must be an object.');
|
|
47
|
+
return errors;
|
|
48
|
+
}
|
|
49
|
+
for (const field of DELIVERY_UNIT_IDENTITY_FIELDS)if (!deliveryUnitIdentityFieldValue(value, field)) addError(errors, `${path}.${field}`, 'must be a non-empty string.');
|
|
50
|
+
return errors;
|
|
51
|
+
};
|
|
52
|
+
const deliveryUnitContractBlock = (record)=>({
|
|
53
|
+
schemaVersion: record.schemaVersion,
|
|
54
|
+
kind: record.kind,
|
|
55
|
+
unitId: record.unitId,
|
|
56
|
+
packageName: record.packageName,
|
|
57
|
+
version: record.version,
|
|
58
|
+
buildMarker: record.buildMarker,
|
|
59
|
+
sourceRevision: record.sourceRevision
|
|
60
|
+
});
|
|
61
|
+
const toDeliveryUnitIdentity = (value)=>{
|
|
62
|
+
const unitId = deliveryUnitIdentityFieldValue(value, 'unitId');
|
|
63
|
+
const buildMarker = deliveryUnitIdentityFieldValue(value, 'buildMarker', {
|
|
64
|
+
allowBuildAlias: true
|
|
65
|
+
});
|
|
66
|
+
const sourceRevision = deliveryUnitIdentityFieldValue(value, 'sourceRevision');
|
|
67
|
+
if (!unitId || !buildMarker || !sourceRevision) return;
|
|
68
|
+
return {
|
|
69
|
+
unitId,
|
|
70
|
+
buildMarker,
|
|
71
|
+
sourceRevision
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
export { deliveryUnitContractBlock, deliveryUnitIdentityFieldValue, toDeliveryUnitIdentity, validateDeliveryUnitBoundaryIdentity, validateDeliveryUnitContractBlock, validateDeliveryUnitIdentity, validateDeliveryUnitRecord };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createUltramodernBuildArtifact, isUltramodernBuildArtifact, stampUltramodernBuildArtifactIdentity, stampUltramodernBuildArtifactSourceRevision, validateUltramodernBuildArtifact } from "./build-artifact.mjs";
|
|
2
|
+
export { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION, BACKEND_FEDERATION_REMOTE_ENTRY_FILE, DELIVERY_UNIT_DEPLOY_PROFILE, DELIVERY_UNIT_IDENTITY_FIELDS, DELIVERY_UNIT_KIND, DELIVERY_UNIT_SCHEMA_VERSION, ULTRAMODERN_BUILD_ARTIFACT_FILE, ULTRAMODERN_BUILD_ARTIFACT_PATH, ULTRAMODERN_BUILD_MODULE_FILE, ULTRAMODERN_BUILD_MODULE_PATH } from "./constants.mjs";
|
|
3
|
+
export { deliveryUnitContractBlock, deliveryUnitIdentityFieldValue, toDeliveryUnitIdentity, validateDeliveryUnitContractBlock, validateDeliveryUnitIdentity, validateDeliveryUnitRecord } from "./delivery-unit.mjs";
|
|
4
|
+
export { backendFederationExposeNames, backendFederationMetadata, backendFederationVersionBoundary, toBackendFederationExposeNames, validateBackendFederationManifest, validateBackendFederationMetadata } from "./metadata.mjs";
|
|
5
|
+
export { formatBackendFederationValidationErrors, nonEmptyString } from "./validation-core.mjs";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { BACKEND_FEDERATION_CONTRACT_VERSION, BACKEND_FEDERATION_EFFECT_EXPOSE, BACKEND_FEDERATION_NODE_ADAPTER_VERSION, DELIVERY_UNIT_IDENTITY_FIELDS, DELIVERY_UNIT_SCHEMA_VERSION } from "./constants.mjs";
|
|
2
|
+
import { deliveryUnitIdentityFieldValue, validateDeliveryUnitBoundaryIdentity, validateDeliveryUnitContractBlock } from "./delivery-unit.mjs";
|
|
3
|
+
import { addError, isRecord, nonEmptyString, recordField, validateVersionField, validationResult } from "./validation-core.mjs";
|
|
4
|
+
const toBackendFederationExposeNames = (value)=>{
|
|
5
|
+
const names = [];
|
|
6
|
+
if (Array.isArray(value)) for (const expose of value){
|
|
7
|
+
const name = nonEmptyString(expose) ?? (isRecord(expose) ? nonEmptyString(expose.name) : void 0);
|
|
8
|
+
if (name) names.push(name);
|
|
9
|
+
}
|
|
10
|
+
else if (isRecord(value)) names.push(...Object.keys(value).filter((name)=>name.length > 0));
|
|
11
|
+
return Array.from(new Set(names));
|
|
12
|
+
};
|
|
13
|
+
const backendFederationExposeNames = (value)=>{
|
|
14
|
+
if (!isRecord(value)) return [];
|
|
15
|
+
const exposes = toBackendFederationExposeNames(value.exposes);
|
|
16
|
+
const expose = nonEmptyString(value.expose);
|
|
17
|
+
return Array.from(new Set([
|
|
18
|
+
...exposes,
|
|
19
|
+
...expose ? [
|
|
20
|
+
expose
|
|
21
|
+
] : []
|
|
22
|
+
]));
|
|
23
|
+
};
|
|
24
|
+
const backendFederationMetadata = (value)=>isRecord(value) ? recordField(value, 'backendFederation') : void 0;
|
|
25
|
+
const backendFederationVersionBoundary = (value)=>recordField(backendFederationMetadata(value), 'versionBoundary');
|
|
26
|
+
const validateBackendFederationMetadata = (value, options = {})=>{
|
|
27
|
+
const path = options.path ?? 'backendFederation';
|
|
28
|
+
const errors = [];
|
|
29
|
+
if (!isRecord(value)) {
|
|
30
|
+
addError(errors, path, 'must be an object.');
|
|
31
|
+
return validationResult(errors);
|
|
32
|
+
}
|
|
33
|
+
if (options.requireEffectRuntime && 'effect' !== value.runtimeFramework) addError(errors, `${path}.runtimeFramework`, 'must be "effect".');
|
|
34
|
+
if (options.requireEffectRuntime && true !== value.strictEffectApproach) addError(errors, `${path}.strictEffectApproach`, 'must be true.');
|
|
35
|
+
validateVersionField(errors, value, 'contractVersion', options.expectedContractVersion ?? BACKEND_FEDERATION_CONTRACT_VERSION, path, options.requireVersionFields ?? false);
|
|
36
|
+
validateVersionField(errors, value, 'nodeAdapterVersion', options.expectedNodeAdapterVersion ?? BACKEND_FEDERATION_NODE_ADAPTER_VERSION, path, options.requireVersionFields ?? false);
|
|
37
|
+
if (options.requireEffectExpose && !backendFederationExposeNames(value).includes(BACKEND_FEDERATION_EFFECT_EXPOSE)) addError(errors, `${path}.expose`, `must include "${BACKEND_FEDERATION_EFFECT_EXPOSE}".`);
|
|
38
|
+
if (options.validateDeliveryUnit ?? true) {
|
|
39
|
+
const deliveryUnit = recordField(value, 'deliveryUnit');
|
|
40
|
+
if (deliveryUnit) errors.push(...validateDeliveryUnitContractBlock(deliveryUnit, {
|
|
41
|
+
path: `${path}.deliveryUnit`
|
|
42
|
+
}).errors);
|
|
43
|
+
const versionBoundary = recordField(value, 'versionBoundary');
|
|
44
|
+
const versionBoundaryDeliveryUnit = recordField(versionBoundary, 'deliveryUnit');
|
|
45
|
+
if (versionBoundaryDeliveryUnit) errors.push(...validateDeliveryUnitBoundaryIdentity(versionBoundaryDeliveryUnit, `${path}.versionBoundary.deliveryUnit`));
|
|
46
|
+
if (deliveryUnit && versionBoundaryDeliveryUnit) for (const field of DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
47
|
+
const deliveryUnitValue = deliveryUnitIdentityFieldValue(deliveryUnit, field);
|
|
48
|
+
const versionBoundaryDeliveryUnitValue = deliveryUnitIdentityFieldValue(versionBoundaryDeliveryUnit, field);
|
|
49
|
+
if (deliveryUnitValue && versionBoundaryDeliveryUnitValue && deliveryUnitValue !== versionBoundaryDeliveryUnitValue) addError(errors, `${path}.versionBoundary.deliveryUnit.${field}`, `must match ${path}.deliveryUnit.${field}.`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return validationResult(errors);
|
|
53
|
+
};
|
|
54
|
+
const validateBackendFederationManifest = (value, options = {})=>{
|
|
55
|
+
const path = options.path ?? 'manifest';
|
|
56
|
+
const errors = [];
|
|
57
|
+
if (!isRecord(value)) {
|
|
58
|
+
addError(errors, path, 'must be an object.');
|
|
59
|
+
return validationResult(errors);
|
|
60
|
+
}
|
|
61
|
+
if (void 0 !== value.schemaVersion && value.schemaVersion !== DELIVERY_UNIT_SCHEMA_VERSION) addError(errors, `${path}.schemaVersion`, `must be ${DELIVERY_UNIT_SCHEMA_VERSION}.`);
|
|
62
|
+
const metadata = backendFederationMetadata(value);
|
|
63
|
+
if (metadata) errors.push(...validateBackendFederationMetadata(metadata, {
|
|
64
|
+
...options,
|
|
65
|
+
path: `${path}.backendFederation`,
|
|
66
|
+
requireEffectExpose: false
|
|
67
|
+
}).errors);
|
|
68
|
+
else if (options.requireBackendFederation ?? true) addError(errors, `${path}.backendFederation`, 'must be an object.');
|
|
69
|
+
if (options.requireEffectExpose) {
|
|
70
|
+
const topLevelExposeNames = toBackendFederationExposeNames(value.exposes);
|
|
71
|
+
const metadataExposeNames = backendFederationExposeNames(metadata);
|
|
72
|
+
const exposeNames = new Set([
|
|
73
|
+
...topLevelExposeNames,
|
|
74
|
+
...metadataExposeNames
|
|
75
|
+
]);
|
|
76
|
+
if (!exposeNames.has(BACKEND_FEDERATION_EFFECT_EXPOSE)) addError(errors, `${path}.exposes`, `must include "${BACKEND_FEDERATION_EFFECT_EXPOSE}".`);
|
|
77
|
+
}
|
|
78
|
+
return validationResult(errors);
|
|
79
|
+
};
|
|
80
|
+
export { backendFederationExposeNames, backendFederationMetadata, backendFederationVersionBoundary, toBackendFederationExposeNames, validateBackendFederationManifest, validateBackendFederationMetadata };
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const isRecord = (value)=>'object' == typeof value && null !== value && !Array.isArray(value);
|
|
2
|
+
const nonEmptyString = (value)=>'string' == typeof value && value.trim().length > 0 ? value : void 0;
|
|
3
|
+
const validationResult = (errors)=>({
|
|
4
|
+
ok: 0 === errors.length,
|
|
5
|
+
errors
|
|
6
|
+
});
|
|
7
|
+
const addError = (errors, path, message)=>{
|
|
8
|
+
errors.push({
|
|
9
|
+
path,
|
|
10
|
+
message
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
const recordField = (value, field)=>{
|
|
14
|
+
const fieldValue = value?.[field];
|
|
15
|
+
return isRecord(fieldValue) ? fieldValue : void 0;
|
|
16
|
+
};
|
|
17
|
+
const formatBackendFederationValidationErrors = (errors)=>errors.map((error)=>`${error.path}: ${error.message}`).join('; ');
|
|
18
|
+
const validateVersionField = (errors, record, field, expected, path, required)=>{
|
|
19
|
+
const compatibility = recordField(record, 'compatibility');
|
|
20
|
+
const executionSurfaces = recordField(record, 'executionSurfaces');
|
|
21
|
+
const nodeSurface = recordField(executionSurfaces, 'node');
|
|
22
|
+
const actual = nonEmptyString(record[field]) ?? nonEmptyString(compatibility?.[field]) ?? ('nodeAdapterVersion' === field ? nonEmptyString(nodeSurface?.adapterVersion) : void 0);
|
|
23
|
+
if (!actual) {
|
|
24
|
+
if (required) addError(errors, `${path}.${field}`, 'must be a non-empty string.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (false !== expected && actual !== expected) addError(errors, `${path}.${field}`, `must be "${expected}".`);
|
|
28
|
+
};
|
|
29
|
+
export { addError, formatBackendFederationValidationErrors, isRecord, nonEmptyString, recordField, validateVersionField, validationResult };
|