space-data-module-sdk 0.2.9 → 0.3.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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/deployment/index.d.ts +3 -6
- package/src/deployment/index.js +129 -88
package/README.md
CHANGED
|
@@ -231,7 +231,7 @@ This repo exposes that deployment surface from
|
|
|
231
231
|
`space-data-module-sdk/deployment`. Use it to:
|
|
232
232
|
|
|
233
233
|
- validate resolved protocol installations
|
|
234
|
-
- describe input
|
|
234
|
+
- describe input and publication bindings by declared `interfaceId`
|
|
235
235
|
- attach a deployment plan to `sds.bundle`
|
|
236
236
|
|
|
237
237
|
The full contract split is documented in
|
package/package.json
CHANGED
|
@@ -29,13 +29,11 @@ export interface ResolvedProtocolInstallation {
|
|
|
29
29
|
|
|
30
30
|
export interface InputBinding {
|
|
31
31
|
bindingId: string;
|
|
32
|
+
interfaceId: string;
|
|
32
33
|
targetPluginId?: string | null;
|
|
33
34
|
targetMethodId: string;
|
|
34
35
|
targetInputPortId: string;
|
|
35
36
|
sourceKind: InputBindingSourceKindName | string;
|
|
36
|
-
topic?: string | null;
|
|
37
|
-
wireId?: string | null;
|
|
38
|
-
nodeInfoUrl?: string | null;
|
|
39
37
|
multiaddrs?: string[];
|
|
40
38
|
allowPeerIds?: string[];
|
|
41
39
|
allowServerKeys?: string[];
|
|
@@ -96,18 +94,17 @@ export interface AuthPolicy {
|
|
|
96
94
|
|
|
97
95
|
export interface PublicationBinding {
|
|
98
96
|
publicationId: string;
|
|
97
|
+
interfaceId: string;
|
|
99
98
|
bindingMode: DeploymentBindingModeName | string;
|
|
100
99
|
sourceKind: string;
|
|
101
100
|
sourceMethodId?: string | null;
|
|
102
101
|
sourceOutputPortId?: string | null;
|
|
103
102
|
sourceNodeId?: string | null;
|
|
104
103
|
sourceTriggerId?: string | null;
|
|
105
|
-
topic?: string | null;
|
|
106
|
-
wireId?: string | null;
|
|
107
104
|
schemaName?: string | null;
|
|
108
105
|
mediaType?: string | null;
|
|
109
106
|
archivePath?: string | null;
|
|
110
|
-
|
|
107
|
+
queryInterfaceId?: string | null;
|
|
111
108
|
emitPnm?: boolean;
|
|
112
109
|
emitFlatbufferArchive?: boolean;
|
|
113
110
|
pinPolicy?: string | null;
|
package/src/deployment/index.js
CHANGED
|
@@ -7,7 +7,11 @@ import {
|
|
|
7
7
|
SDS_DEPLOYMENT_MEDIA_TYPE,
|
|
8
8
|
SDS_DEPLOYMENT_SECTION_NAME,
|
|
9
9
|
} from "../bundle/constants.js";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
ExternalInterfaceDirection,
|
|
12
|
+
ProtocolRole,
|
|
13
|
+
ProtocolTransportKind,
|
|
14
|
+
} from "../runtime/constants.js";
|
|
11
15
|
|
|
12
16
|
export const DEPLOYMENT_PLAN_FORMAT_VERSION = 1;
|
|
13
17
|
|
|
@@ -33,6 +37,14 @@ const DeploymentBindingModeSet = new Set(Object.values(DeploymentBindingMode));
|
|
|
33
37
|
const ProtocolRoleSet = new Set(Object.values(ProtocolRole));
|
|
34
38
|
const ProtocolTransportKindSet = new Set(Object.values(ProtocolTransportKind));
|
|
35
39
|
const ScheduleBindingKindSet = new Set(Object.values(ScheduleBindingKind));
|
|
40
|
+
const InputBindingInterfaceDirectionSet = new Set([
|
|
41
|
+
ExternalInterfaceDirection.INPUT,
|
|
42
|
+
ExternalInterfaceDirection.BIDIRECTIONAL,
|
|
43
|
+
]);
|
|
44
|
+
const PublicationBindingInterfaceDirectionSet = new Set([
|
|
45
|
+
ExternalInterfaceDirection.OUTPUT,
|
|
46
|
+
ExternalInterfaceDirection.BIDIRECTIONAL,
|
|
47
|
+
]);
|
|
36
48
|
|
|
37
49
|
function normalizeString(value) {
|
|
38
50
|
if (value === undefined || value === null) {
|
|
@@ -163,13 +175,11 @@ function normalizeProtocolInstallation(value = {}) {
|
|
|
163
175
|
function normalizeInputBinding(value = {}) {
|
|
164
176
|
return {
|
|
165
177
|
bindingId: normalizeString(value.bindingId),
|
|
178
|
+
interfaceId: normalizeString(value.interfaceId),
|
|
166
179
|
targetPluginId: normalizeString(value.targetPluginId),
|
|
167
180
|
targetMethodId: normalizeString(value.targetMethodId),
|
|
168
181
|
targetInputPortId: normalizeString(value.targetInputPortId),
|
|
169
182
|
sourceKind: normalizeInputBindingSourceKindName(value.sourceKind),
|
|
170
|
-
topic: normalizeString(value.topic),
|
|
171
|
-
wireId: normalizeString(value.wireId),
|
|
172
|
-
nodeInfoUrl: normalizeString(value.nodeInfoUrl),
|
|
173
183
|
multiaddrs: normalizeStringArray(value.multiaddrs),
|
|
174
184
|
allowPeerIds: normalizeStringArray(value.allowPeerIds),
|
|
175
185
|
allowServerKeys: normalizeStringArray(value.allowServerKeys),
|
|
@@ -238,18 +248,17 @@ function normalizeAuthPolicy(value = {}) {
|
|
|
238
248
|
function normalizePublicationBinding(value = {}) {
|
|
239
249
|
return {
|
|
240
250
|
publicationId: normalizeString(value.publicationId),
|
|
251
|
+
interfaceId: normalizeString(value.interfaceId),
|
|
241
252
|
bindingMode: normalizeDeploymentBindingModeName(value.bindingMode),
|
|
242
253
|
sourceKind: normalizeString(value.sourceKind),
|
|
243
254
|
sourceMethodId: normalizeString(value.sourceMethodId),
|
|
244
255
|
sourceOutputPortId: normalizeString(value.sourceOutputPortId),
|
|
245
256
|
sourceNodeId: normalizeString(value.sourceNodeId),
|
|
246
257
|
sourceTriggerId: normalizeString(value.sourceTriggerId),
|
|
247
|
-
topic: normalizeString(value.topic),
|
|
248
|
-
wireId: normalizeString(value.wireId),
|
|
249
258
|
schemaName: normalizeString(value.schemaName),
|
|
250
259
|
mediaType: normalizeString(value.mediaType),
|
|
251
260
|
archivePath: normalizeString(value.archivePath),
|
|
252
|
-
|
|
261
|
+
queryInterfaceId: normalizeString(value.queryInterfaceId),
|
|
253
262
|
emitPnm: normalizeBoolean(value.emitPnm),
|
|
254
263
|
emitFlatbufferArchive: normalizeBoolean(value.emitFlatbufferArchive),
|
|
255
264
|
pinPolicy: normalizeString(value.pinPolicy),
|
|
@@ -392,6 +401,68 @@ function buildMethodLookup(manifest) {
|
|
|
392
401
|
return lookup;
|
|
393
402
|
}
|
|
394
403
|
|
|
404
|
+
function buildExternalInterfaceLookup(manifest) {
|
|
405
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
const lookup = new Map();
|
|
409
|
+
if (!Array.isArray(manifest?.externalInterfaces)) {
|
|
410
|
+
return lookup;
|
|
411
|
+
}
|
|
412
|
+
for (const externalInterface of manifest.externalInterfaces) {
|
|
413
|
+
if (
|
|
414
|
+
typeof externalInterface?.interfaceId === "string" &&
|
|
415
|
+
externalInterface.interfaceId.trim().length > 0
|
|
416
|
+
) {
|
|
417
|
+
lookup.set(externalInterface.interfaceId, externalInterface);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return lookup;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function validateDeclaredInterface(
|
|
424
|
+
issues,
|
|
425
|
+
interfaceId,
|
|
426
|
+
location,
|
|
427
|
+
bindingLabel,
|
|
428
|
+
missingCode,
|
|
429
|
+
directionCode,
|
|
430
|
+
externalInterfaceLookup,
|
|
431
|
+
allowedDirections,
|
|
432
|
+
) {
|
|
433
|
+
if (!externalInterfaceLookup) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const normalizedInterfaceId = normalizeString(interfaceId);
|
|
437
|
+
if (!normalizedInterfaceId) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const externalInterface = externalInterfaceLookup.get(normalizedInterfaceId);
|
|
441
|
+
if (!externalInterface) {
|
|
442
|
+
pushIssue(
|
|
443
|
+
issues,
|
|
444
|
+
"error",
|
|
445
|
+
missingCode,
|
|
446
|
+
`${bindingLabel} references unknown interface "${normalizedInterfaceId}".`,
|
|
447
|
+
location,
|
|
448
|
+
);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
if (
|
|
452
|
+
allowedDirections &&
|
|
453
|
+
typeof externalInterface.direction === "string" &&
|
|
454
|
+
!allowedDirections.has(externalInterface.direction)
|
|
455
|
+
) {
|
|
456
|
+
pushIssue(
|
|
457
|
+
issues,
|
|
458
|
+
"error",
|
|
459
|
+
directionCode,
|
|
460
|
+
`${bindingLabel} references interface "${normalizedInterfaceId}" with direction "${externalInterface.direction}", which is incompatible with this binding.`,
|
|
461
|
+
location,
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
395
466
|
function validateProtocolInstallation(
|
|
396
467
|
installation,
|
|
397
468
|
issues,
|
|
@@ -583,6 +654,7 @@ function validateInputBinding(
|
|
|
583
654
|
location,
|
|
584
655
|
manifest,
|
|
585
656
|
manifestMethodLookup,
|
|
657
|
+
externalInterfaceLookup,
|
|
586
658
|
) {
|
|
587
659
|
if (!binding || typeof binding !== "object" || Array.isArray(binding)) {
|
|
588
660
|
pushIssue(
|
|
@@ -600,6 +672,12 @@ function validateInputBinding(
|
|
|
600
672
|
`${location}.bindingId`,
|
|
601
673
|
"Input binding bindingId",
|
|
602
674
|
);
|
|
675
|
+
const interfaceIdValid = validateStringField(
|
|
676
|
+
issues,
|
|
677
|
+
binding.interfaceId,
|
|
678
|
+
`${location}.interfaceId`,
|
|
679
|
+
"Input binding interfaceId",
|
|
680
|
+
);
|
|
603
681
|
const targetPluginId = normalizeString(binding.targetPluginId);
|
|
604
682
|
const targetMethodIdValid = validateStringField(
|
|
605
683
|
issues,
|
|
@@ -639,24 +717,6 @@ function validateInputBinding(
|
|
|
639
717
|
`${location}.targetPluginId`,
|
|
640
718
|
"Input binding targetPluginId",
|
|
641
719
|
);
|
|
642
|
-
validateOptionalStringField(
|
|
643
|
-
issues,
|
|
644
|
-
binding.topic,
|
|
645
|
-
`${location}.topic`,
|
|
646
|
-
"Input binding topic",
|
|
647
|
-
);
|
|
648
|
-
validateOptionalStringField(
|
|
649
|
-
issues,
|
|
650
|
-
binding.wireId,
|
|
651
|
-
`${location}.wireId`,
|
|
652
|
-
"Input binding wireId",
|
|
653
|
-
);
|
|
654
|
-
validateOptionalStringField(
|
|
655
|
-
issues,
|
|
656
|
-
binding.nodeInfoUrl,
|
|
657
|
-
`${location}.nodeInfoUrl`,
|
|
658
|
-
"Input binding nodeInfoUrl",
|
|
659
|
-
);
|
|
660
720
|
validateStringArrayField(
|
|
661
721
|
issues,
|
|
662
722
|
binding.multiaddrs,
|
|
@@ -687,27 +747,17 @@ function validateInputBinding(
|
|
|
687
747
|
`${location}.description`,
|
|
688
748
|
"Input binding description",
|
|
689
749
|
);
|
|
690
|
-
if (
|
|
691
|
-
|
|
692
|
-
!validateStringField(
|
|
750
|
+
if (interfaceIdValid) {
|
|
751
|
+
validateDeclaredInterface(
|
|
693
752
|
issues,
|
|
694
|
-
binding.
|
|
695
|
-
`${location}.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
sourceKind === InputBindingSourceKind.PROTOCOL_STREAM &&
|
|
703
|
-
!validateStringField(
|
|
704
|
-
issues,
|
|
705
|
-
binding.wireId,
|
|
706
|
-
`${location}.wireId`,
|
|
707
|
-
"Protocol-stream input binding wireId",
|
|
708
|
-
)
|
|
709
|
-
) {
|
|
710
|
-
// error already recorded
|
|
753
|
+
binding.interfaceId,
|
|
754
|
+
`${location}.interfaceId`,
|
|
755
|
+
`Input binding "${binding.bindingId ?? "binding"}"`,
|
|
756
|
+
"unknown-input-binding-interface",
|
|
757
|
+
"input-binding-interface-direction-mismatch",
|
|
758
|
+
externalInterfaceLookup,
|
|
759
|
+
InputBindingInterfaceDirectionSet,
|
|
760
|
+
);
|
|
711
761
|
}
|
|
712
762
|
const targetsCurrentManifest =
|
|
713
763
|
!targetPluginId ||
|
|
@@ -1161,6 +1211,7 @@ function validatePublicationBinding(
|
|
|
1161
1211
|
location,
|
|
1162
1212
|
manifest,
|
|
1163
1213
|
manifestMethodLookup,
|
|
1214
|
+
externalInterfaceLookup,
|
|
1164
1215
|
) {
|
|
1165
1216
|
if (!binding || typeof binding !== "object" || Array.isArray(binding)) {
|
|
1166
1217
|
pushIssue(
|
|
@@ -1178,6 +1229,12 @@ function validatePublicationBinding(
|
|
|
1178
1229
|
`${location}.publicationId`,
|
|
1179
1230
|
"Publication binding publicationId",
|
|
1180
1231
|
);
|
|
1232
|
+
const interfaceIdValid = validateStringField(
|
|
1233
|
+
issues,
|
|
1234
|
+
binding.interfaceId,
|
|
1235
|
+
`${location}.interfaceId`,
|
|
1236
|
+
"Publication binding interfaceId",
|
|
1237
|
+
);
|
|
1181
1238
|
validateBindingModeField(
|
|
1182
1239
|
issues,
|
|
1183
1240
|
binding.bindingMode,
|
|
@@ -1214,18 +1271,6 @@ function validatePublicationBinding(
|
|
|
1214
1271
|
`${location}.sourceTriggerId`,
|
|
1215
1272
|
"Publication binding sourceTriggerId",
|
|
1216
1273
|
);
|
|
1217
|
-
validateOptionalStringField(
|
|
1218
|
-
issues,
|
|
1219
|
-
binding.topic,
|
|
1220
|
-
`${location}.topic`,
|
|
1221
|
-
"Publication binding topic",
|
|
1222
|
-
);
|
|
1223
|
-
validateOptionalStringField(
|
|
1224
|
-
issues,
|
|
1225
|
-
binding.wireId,
|
|
1226
|
-
`${location}.wireId`,
|
|
1227
|
-
"Publication binding wireId",
|
|
1228
|
-
);
|
|
1229
1274
|
validateOptionalStringField(
|
|
1230
1275
|
issues,
|
|
1231
1276
|
binding.schemaName,
|
|
@@ -1246,9 +1291,9 @@ function validatePublicationBinding(
|
|
|
1246
1291
|
);
|
|
1247
1292
|
validateOptionalStringField(
|
|
1248
1293
|
issues,
|
|
1249
|
-
binding.
|
|
1250
|
-
`${location}.
|
|
1251
|
-
"Publication binding
|
|
1294
|
+
binding.queryInterfaceId,
|
|
1295
|
+
`${location}.queryInterfaceId`,
|
|
1296
|
+
"Publication binding queryInterfaceId",
|
|
1252
1297
|
);
|
|
1253
1298
|
validateOptionalStringField(
|
|
1254
1299
|
issues,
|
|
@@ -1287,18 +1332,28 @@ function validatePublicationBinding(
|
|
|
1287
1332
|
location,
|
|
1288
1333
|
);
|
|
1289
1334
|
}
|
|
1290
|
-
if (
|
|
1291
|
-
|
|
1292
|
-
!binding.topic &&
|
|
1293
|
-
!binding.wireId &&
|
|
1294
|
-
!binding.schemaName
|
|
1295
|
-
) {
|
|
1296
|
-
pushIssue(
|
|
1335
|
+
if (interfaceIdValid) {
|
|
1336
|
+
validateDeclaredInterface(
|
|
1297
1337
|
issues,
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1338
|
+
binding.interfaceId,
|
|
1339
|
+
`${location}.interfaceId`,
|
|
1340
|
+
`Publication binding "${binding.publicationId ?? "publication"}"`,
|
|
1341
|
+
"unknown-publication-binding-interface",
|
|
1342
|
+
"publication-binding-interface-direction-mismatch",
|
|
1343
|
+
externalInterfaceLookup,
|
|
1344
|
+
PublicationBindingInterfaceDirectionSet,
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
if (binding.queryInterfaceId) {
|
|
1348
|
+
validateDeclaredInterface(
|
|
1349
|
+
issues,
|
|
1350
|
+
binding.queryInterfaceId,
|
|
1351
|
+
`${location}.queryInterfaceId`,
|
|
1352
|
+
`Publication binding "${binding.publicationId ?? "publication"}" query interface`,
|
|
1353
|
+
"unknown-publication-query-interface",
|
|
1354
|
+
"publication-query-interface-direction-mismatch",
|
|
1355
|
+
externalInterfaceLookup,
|
|
1356
|
+
null,
|
|
1302
1357
|
);
|
|
1303
1358
|
}
|
|
1304
1359
|
if (binding.sourceMethodId && manifest) {
|
|
@@ -1344,6 +1399,7 @@ export function validateDeploymentPlan(plan, options = {}) {
|
|
|
1344
1399
|
const issues = [];
|
|
1345
1400
|
const manifest = options.manifest ?? null;
|
|
1346
1401
|
const methodLookup = buildMethodLookup(manifest);
|
|
1402
|
+
const externalInterfaceLookup = buildExternalInterfaceLookup(manifest);
|
|
1347
1403
|
const protocolLookup = new Map(
|
|
1348
1404
|
Array.isArray(manifest?.protocols)
|
|
1349
1405
|
? manifest.protocols
|
|
@@ -1403,6 +1459,7 @@ export function validateDeploymentPlan(plan, options = {}) {
|
|
|
1403
1459
|
`deploymentPlan.inputBindings[${index}]`,
|
|
1404
1460
|
manifest,
|
|
1405
1461
|
methodLookup,
|
|
1462
|
+
externalInterfaceLookup,
|
|
1406
1463
|
);
|
|
1407
1464
|
});
|
|
1408
1465
|
normalizedPlan.scheduleBindings.forEach((binding, index) => {
|
|
@@ -1435,6 +1492,7 @@ export function validateDeploymentPlan(plan, options = {}) {
|
|
|
1435
1492
|
`deploymentPlan.publicationBindings[${index}]`,
|
|
1436
1493
|
manifest,
|
|
1437
1494
|
methodLookup,
|
|
1495
|
+
externalInterfaceLookup,
|
|
1438
1496
|
);
|
|
1439
1497
|
});
|
|
1440
1498
|
|
|
@@ -1454,23 +1512,6 @@ export function validateDeploymentPlan(plan, options = {}) {
|
|
|
1454
1512
|
);
|
|
1455
1513
|
}
|
|
1456
1514
|
});
|
|
1457
|
-
const serviceIds = new Set(
|
|
1458
|
-
normalizedPlan.serviceBindings
|
|
1459
|
-
.map((entry) => entry.serviceId)
|
|
1460
|
-
.filter((entry) => typeof entry === "string" && entry.length > 0),
|
|
1461
|
-
);
|
|
1462
|
-
normalizedPlan.publicationBindings.forEach((binding, index) => {
|
|
1463
|
-
if (binding.queryServiceId && !serviceIds.has(binding.queryServiceId)) {
|
|
1464
|
-
pushIssue(
|
|
1465
|
-
issues,
|
|
1466
|
-
"error",
|
|
1467
|
-
"unknown-publication-query-service",
|
|
1468
|
-
`Publication binding "${binding.publicationId ?? "publication"}" references unknown query service "${binding.queryServiceId}".`,
|
|
1469
|
-
`deploymentPlan.publicationBindings[${index}].queryServiceId`,
|
|
1470
|
-
);
|
|
1471
|
-
}
|
|
1472
|
-
});
|
|
1473
|
-
|
|
1474
1515
|
const errors = issues.filter((issue) => issue.severity === "error");
|
|
1475
1516
|
const warnings = issues.filter((issue) => issue.severity === "warning");
|
|
1476
1517
|
return {
|