space-data-module-sdk 0.2.6 → 0.2.8
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 +73 -0
- package/package.json +5 -1
- package/schemas/PluginManifest.fbs +10 -0
- package/src/bundle/constants.js +4 -1
- package/src/bundle/wasm.js +30 -2
- package/src/compliance/index.js +2 -1
- package/src/compliance/pluginCompliance.js +391 -2
- package/src/deployment/index.d.ts +224 -0
- package/src/deployment/index.js +1552 -0
- package/src/generated/orbpro/manifest/plugin-manifest.d.ts +10 -3
- package/src/generated/orbpro/manifest/plugin-manifest.js +32 -6
- package/src/generated/orbpro/manifest/plugin-manifest.ts +42 -5
- package/src/generated/orbpro/manifest/protocol-spec.d.ts +35 -3
- package/src/generated/orbpro/manifest/protocol-spec.js +120 -6
- package/src/generated/orbpro/manifest/protocol-spec.ts +191 -1
- package/src/index.d.ts +138 -3
- package/src/index.js +4 -0
- package/src/manifest/index.js +7 -0
- package/src/manifest/normalize.js +82 -11
- package/src/manifest/typeRefs.js +143 -0
- package/src/runtime/constants.js +14 -0
- package/src/runtime/index.d.ts +2 -0
- package/src/testing/index.d.ts +86 -0
- package/src/testing/index.js +473 -0
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
ExternalInterfaceDirection,
|
|
9
9
|
ExternalInterfaceKind,
|
|
10
10
|
InvokeSurface,
|
|
11
|
+
ProtocolRole,
|
|
12
|
+
ProtocolTransportKind,
|
|
11
13
|
RuntimeTarget,
|
|
12
14
|
} from "../runtime/constants.js";
|
|
13
15
|
|
|
@@ -50,7 +52,16 @@ export const RecommendedCapabilityIds = Object.freeze([
|
|
|
50
52
|
"render_hooks",
|
|
51
53
|
]);
|
|
52
54
|
|
|
55
|
+
export const StandaloneWasiCapabilityIds = Object.freeze([
|
|
56
|
+
"logging",
|
|
57
|
+
"clock",
|
|
58
|
+
"random",
|
|
59
|
+
"filesystem",
|
|
60
|
+
"pipe",
|
|
61
|
+
]);
|
|
62
|
+
|
|
53
63
|
const RecommendedCapabilitySet = new Set(RecommendedCapabilityIds);
|
|
64
|
+
const StandaloneWasiCapabilitySet = new Set(StandaloneWasiCapabilityIds);
|
|
54
65
|
const RecommendedRuntimeTargets = Object.freeze(Object.values(RuntimeTarget));
|
|
55
66
|
const RecommendedRuntimeTargetSet = new Set(RecommendedRuntimeTargets);
|
|
56
67
|
const DrainPolicySet = new Set(Object.values(DrainPolicy));
|
|
@@ -59,6 +70,8 @@ const ExternalInterfaceDirectionSet = new Set(
|
|
|
59
70
|
Object.values(ExternalInterfaceDirection),
|
|
60
71
|
);
|
|
61
72
|
const ExternalInterfaceKindSet = new Set(Object.values(ExternalInterfaceKind));
|
|
73
|
+
const ProtocolRoleSet = new Set(Object.values(ProtocolRole));
|
|
74
|
+
const ProtocolTransportKindSet = new Set(Object.values(ProtocolTransportKind));
|
|
62
75
|
const BrowserIncompatibleCapabilitySet = new Set([
|
|
63
76
|
"filesystem",
|
|
64
77
|
"pipe",
|
|
@@ -79,6 +92,9 @@ const BrowserIncompatibleCapabilitySet = new Set([
|
|
|
79
92
|
"entity_access",
|
|
80
93
|
"render_hooks",
|
|
81
94
|
]);
|
|
95
|
+
const StandaloneWasiProtocolTransportKindSet = new Set([
|
|
96
|
+
ProtocolTransportKind.WASI_PIPE,
|
|
97
|
+
]);
|
|
82
98
|
const IgnoredDirectoryNames = new Set([
|
|
83
99
|
".git",
|
|
84
100
|
".hg",
|
|
@@ -120,6 +136,57 @@ function hasNonEmptyByteSequence(value) {
|
|
|
120
136
|
return false;
|
|
121
137
|
}
|
|
122
138
|
|
|
139
|
+
function normalizeTypeIdentityString(value) {
|
|
140
|
+
if (!isNonEmptyString(value)) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
return value.trim().toLowerCase();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function normalizeTypeIdentityBytes(value) {
|
|
147
|
+
if (typeof value === "string") {
|
|
148
|
+
const trimmed = value.trim().toLowerCase();
|
|
149
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
150
|
+
}
|
|
151
|
+
const bytes = ArrayBuffer.isView(value)
|
|
152
|
+
? Array.from(value)
|
|
153
|
+
: Array.isArray(value)
|
|
154
|
+
? value
|
|
155
|
+
: null;
|
|
156
|
+
if (!bytes || bytes.length === 0) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
return bytes
|
|
160
|
+
.map((entry) => Number(entry).toString(16).padStart(2, "0"))
|
|
161
|
+
.join("");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function allowedTypesReferToSameLogicalSchema(left, right) {
|
|
165
|
+
const leftSchemaName = normalizeTypeIdentityString(left?.schemaName);
|
|
166
|
+
const rightSchemaName = normalizeTypeIdentityString(right?.schemaName);
|
|
167
|
+
if (leftSchemaName && rightSchemaName && leftSchemaName === rightSchemaName) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const leftFileIdentifier = normalizeTypeIdentityString(left?.fileIdentifier);
|
|
172
|
+
const rightFileIdentifier = normalizeTypeIdentityString(right?.fileIdentifier);
|
|
173
|
+
if (
|
|
174
|
+
leftFileIdentifier &&
|
|
175
|
+
rightFileIdentifier &&
|
|
176
|
+
leftFileIdentifier === rightFileIdentifier
|
|
177
|
+
) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const leftSchemaHash = normalizeTypeIdentityBytes(left?.schemaHash);
|
|
182
|
+
const rightSchemaHash = normalizeTypeIdentityBytes(right?.schemaHash);
|
|
183
|
+
if (leftSchemaHash && rightSchemaHash && leftSchemaHash === rightSchemaHash) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
|
|
123
190
|
function normalizePayloadWireFormatName(value) {
|
|
124
191
|
if (value === undefined || value === null || value === "") {
|
|
125
192
|
return "flatbuffer";
|
|
@@ -151,7 +218,13 @@ function validateStringField(issues, value, location, label) {
|
|
|
151
218
|
return true;
|
|
152
219
|
}
|
|
153
220
|
|
|
154
|
-
function validateIntegerField(
|
|
221
|
+
function validateIntegerField(
|
|
222
|
+
issues,
|
|
223
|
+
value,
|
|
224
|
+
location,
|
|
225
|
+
label,
|
|
226
|
+
{ min = null, max = null } = {},
|
|
227
|
+
) {
|
|
155
228
|
if (!Number.isInteger(value)) {
|
|
156
229
|
pushIssue(issues, "error", "invalid-integer", `${label} must be an integer.`, location);
|
|
157
230
|
return false;
|
|
@@ -166,6 +239,16 @@ function validateIntegerField(issues, value, location, label, { min = null } = {
|
|
|
166
239
|
);
|
|
167
240
|
return false;
|
|
168
241
|
}
|
|
242
|
+
if (max !== null && value > max) {
|
|
243
|
+
pushIssue(
|
|
244
|
+
issues,
|
|
245
|
+
"error",
|
|
246
|
+
"integer-range",
|
|
247
|
+
`${label} must be less than or equal to ${max}.`,
|
|
248
|
+
location,
|
|
249
|
+
);
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
169
252
|
return true;
|
|
170
253
|
}
|
|
171
254
|
|
|
@@ -182,6 +265,61 @@ function validateOptionalIntegerField(
|
|
|
182
265
|
return validateIntegerField(issues, value, location, label, options);
|
|
183
266
|
}
|
|
184
267
|
|
|
268
|
+
function validateOptionalBooleanField(issues, value, location, label) {
|
|
269
|
+
if (value === undefined || value === null) {
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
if (typeof value !== "boolean") {
|
|
273
|
+
pushIssue(
|
|
274
|
+
issues,
|
|
275
|
+
"error",
|
|
276
|
+
"invalid-boolean",
|
|
277
|
+
`${label} must be a boolean when present.`,
|
|
278
|
+
location,
|
|
279
|
+
);
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function validateOptionalStringField(issues, value, location, label) {
|
|
286
|
+
if (value === undefined || value === null) {
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
return validateStringField(issues, value, location, label);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function normalizeProtocolTransportKind(value) {
|
|
293
|
+
if (value === undefined || value === null || value === "") {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
const normalized = String(value)
|
|
297
|
+
.trim()
|
|
298
|
+
.toLowerCase()
|
|
299
|
+
.replace(/_/g, "-");
|
|
300
|
+
if (normalized === "websocket") {
|
|
301
|
+
return ProtocolTransportKind.WS;
|
|
302
|
+
}
|
|
303
|
+
if (normalized === "pipe") {
|
|
304
|
+
return ProtocolTransportKind.WASI_PIPE;
|
|
305
|
+
}
|
|
306
|
+
return normalized;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function normalizeProtocolRole(value) {
|
|
310
|
+
if (value === undefined || value === null || value === "") {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
const normalized = String(value)
|
|
314
|
+
.trim()
|
|
315
|
+
.toLowerCase()
|
|
316
|
+
.replace(/_/g, "-");
|
|
317
|
+
if (normalized === "handler") {
|
|
318
|
+
return ProtocolRole.HANDLE;
|
|
319
|
+
}
|
|
320
|
+
return normalized;
|
|
321
|
+
}
|
|
322
|
+
|
|
185
323
|
function validateAllowedType(type, issues, location) {
|
|
186
324
|
if (!type || typeof type !== "object" || Array.isArray(type)) {
|
|
187
325
|
pushIssue(issues, "error", "invalid-type-record", "Allowed type entries must be objects.", location);
|
|
@@ -307,6 +445,35 @@ function validateAcceptedTypeSet(typeSet, issues, location) {
|
|
|
307
445
|
typeSet.allowedTypes.forEach((allowedType, index) => {
|
|
308
446
|
validateAllowedType(allowedType, issues, `${location}.allowedTypes[${index}]`);
|
|
309
447
|
});
|
|
448
|
+
|
|
449
|
+
const regularConcreteTypes = [];
|
|
450
|
+
const alignedTypes = [];
|
|
451
|
+
|
|
452
|
+
typeSet.allowedTypes.forEach((allowedType, index) => {
|
|
453
|
+
const wireFormat = normalizePayloadWireFormatName(allowedType?.wireFormat);
|
|
454
|
+
if (wireFormat === "aligned-binary") {
|
|
455
|
+
alignedTypes.push({ allowedType, index });
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
if (wireFormat === "flatbuffer" && allowedType?.acceptsAnyFlatbuffer !== true) {
|
|
459
|
+
regularConcreteTypes.push({ allowedType, index });
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
alignedTypes.forEach(({ allowedType, index }) => {
|
|
464
|
+
const hasRegularFallback = regularConcreteTypes.some(({ allowedType: regularType }) =>
|
|
465
|
+
allowedTypesReferToSameLogicalSchema(allowedType, regularType),
|
|
466
|
+
);
|
|
467
|
+
if (!hasRegularFallback) {
|
|
468
|
+
pushIssue(
|
|
469
|
+
issues,
|
|
470
|
+
"error",
|
|
471
|
+
"missing-flatbuffer-fallback",
|
|
472
|
+
"Aligned-binary allowed types must be paired with a regular flatbuffer fallback for the same schema in the same acceptedTypeSet.",
|
|
473
|
+
`${location}.allowedTypes[${index}]`,
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
});
|
|
310
477
|
}
|
|
311
478
|
|
|
312
479
|
function validatePort(port, issues, location, label) {
|
|
@@ -576,6 +743,85 @@ function validateProtocol(protocol, issues, location, methodLookup, declaredCapa
|
|
|
576
743
|
);
|
|
577
744
|
}
|
|
578
745
|
}
|
|
746
|
+
const wireIdValid = validateStringField(
|
|
747
|
+
issues,
|
|
748
|
+
protocol.wireId,
|
|
749
|
+
`${location}.wireId`,
|
|
750
|
+
"Protocol wireId",
|
|
751
|
+
);
|
|
752
|
+
const normalizedTransportKind = normalizeProtocolTransportKind(
|
|
753
|
+
protocol.transportKind,
|
|
754
|
+
);
|
|
755
|
+
if (!validateStringField(
|
|
756
|
+
issues,
|
|
757
|
+
protocol.transportKind,
|
|
758
|
+
`${location}.transportKind`,
|
|
759
|
+
"Protocol transportKind",
|
|
760
|
+
)) {
|
|
761
|
+
// already reported
|
|
762
|
+
} else if (!ProtocolTransportKindSet.has(normalizedTransportKind)) {
|
|
763
|
+
pushIssue(
|
|
764
|
+
issues,
|
|
765
|
+
"error",
|
|
766
|
+
"unknown-protocol-transport-kind",
|
|
767
|
+
`Protocol "${protocol.protocolId ?? "protocol"}" transportKind must be one of: ${Array.from(ProtocolTransportKindSet).join(", ")}.`,
|
|
768
|
+
`${location}.transportKind`,
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
const normalizedRole = normalizeProtocolRole(protocol.role);
|
|
772
|
+
if (!validateStringField(
|
|
773
|
+
issues,
|
|
774
|
+
protocol.role,
|
|
775
|
+
`${location}.role`,
|
|
776
|
+
"Protocol role",
|
|
777
|
+
)) {
|
|
778
|
+
// already reported
|
|
779
|
+
} else if (!ProtocolRoleSet.has(normalizedRole)) {
|
|
780
|
+
pushIssue(
|
|
781
|
+
issues,
|
|
782
|
+
"error",
|
|
783
|
+
"unknown-protocol-role",
|
|
784
|
+
`Protocol "${protocol.protocolId ?? "protocol"}" role must be one of: ${Array.from(ProtocolRoleSet).join(", ")}.`,
|
|
785
|
+
`${location}.role`,
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
validateOptionalStringField(
|
|
789
|
+
issues,
|
|
790
|
+
protocol.specUri,
|
|
791
|
+
`${location}.specUri`,
|
|
792
|
+
"Protocol specUri",
|
|
793
|
+
);
|
|
794
|
+
validateOptionalStringField(
|
|
795
|
+
issues,
|
|
796
|
+
protocol.discoveryKey,
|
|
797
|
+
`${location}.discoveryKey`,
|
|
798
|
+
"Protocol discoveryKey",
|
|
799
|
+
);
|
|
800
|
+
validateOptionalBooleanField(
|
|
801
|
+
issues,
|
|
802
|
+
protocol.autoInstall,
|
|
803
|
+
`${location}.autoInstall`,
|
|
804
|
+
"Protocol autoInstall",
|
|
805
|
+
);
|
|
806
|
+
validateOptionalBooleanField(
|
|
807
|
+
issues,
|
|
808
|
+
protocol.advertise,
|
|
809
|
+
`${location}.advertise`,
|
|
810
|
+
"Protocol advertise",
|
|
811
|
+
);
|
|
812
|
+
validateOptionalBooleanField(
|
|
813
|
+
issues,
|
|
814
|
+
protocol.requireSecureTransport,
|
|
815
|
+
`${location}.requireSecureTransport`,
|
|
816
|
+
"Protocol requireSecureTransport",
|
|
817
|
+
);
|
|
818
|
+
validateOptionalIntegerField(
|
|
819
|
+
issues,
|
|
820
|
+
protocol.defaultPort,
|
|
821
|
+
`${location}.defaultPort`,
|
|
822
|
+
"Protocol defaultPort",
|
|
823
|
+
{ min: 0, max: 65535 },
|
|
824
|
+
);
|
|
579
825
|
if (
|
|
580
826
|
protocolIdValid &&
|
|
581
827
|
Array.isArray(declaredCapabilities) &&
|
|
@@ -590,6 +836,77 @@ function validateProtocol(protocol, issues, location, methodLookup, declaredCapa
|
|
|
590
836
|
location,
|
|
591
837
|
);
|
|
592
838
|
}
|
|
839
|
+
if (
|
|
840
|
+
protocolIdValid &&
|
|
841
|
+
normalizedRole &&
|
|
842
|
+
(normalizedRole === ProtocolRole.HANDLE ||
|
|
843
|
+
normalizedRole === ProtocolRole.BOTH) &&
|
|
844
|
+
Array.isArray(declaredCapabilities) &&
|
|
845
|
+
!declaredCapabilities.includes("protocol_handle")
|
|
846
|
+
) {
|
|
847
|
+
pushIssue(
|
|
848
|
+
issues,
|
|
849
|
+
"error",
|
|
850
|
+
"missing-handle-protocol-capability",
|
|
851
|
+
`Protocol "${protocol.protocolId}" with role "${normalizedRole}" requires the "protocol_handle" capability.`,
|
|
852
|
+
location,
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
if (
|
|
856
|
+
protocolIdValid &&
|
|
857
|
+
normalizedRole &&
|
|
858
|
+
(normalizedRole === ProtocolRole.DIAL ||
|
|
859
|
+
normalizedRole === ProtocolRole.BOTH) &&
|
|
860
|
+
Array.isArray(declaredCapabilities) &&
|
|
861
|
+
!declaredCapabilities.includes("protocol_dial")
|
|
862
|
+
) {
|
|
863
|
+
pushIssue(
|
|
864
|
+
issues,
|
|
865
|
+
"error",
|
|
866
|
+
"missing-dial-protocol-capability",
|
|
867
|
+
`Protocol "${protocol.protocolId}" with role "${normalizedRole}" requires the "protocol_dial" capability.`,
|
|
868
|
+
location,
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
if (
|
|
872
|
+
protocol.advertise === true &&
|
|
873
|
+
normalizedRole === ProtocolRole.DIAL
|
|
874
|
+
) {
|
|
875
|
+
pushIssue(
|
|
876
|
+
issues,
|
|
877
|
+
"error",
|
|
878
|
+
"protocol-advertise-role-conflict",
|
|
879
|
+
`Protocol "${protocol.protocolId ?? "protocol"}" cannot advertise when role is "dial".`,
|
|
880
|
+
`${location}.advertise`,
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
if (
|
|
884
|
+
normalizedTransportKind === ProtocolTransportKind.LIBP2P &&
|
|
885
|
+
Array.isArray(declaredCapabilities) &&
|
|
886
|
+
!declaredCapabilities.includes("ipfs")
|
|
887
|
+
) {
|
|
888
|
+
pushIssue(
|
|
889
|
+
issues,
|
|
890
|
+
"error",
|
|
891
|
+
"missing-ipfs-capability",
|
|
892
|
+
`Protocol "${protocol.protocolId ?? "protocol"}" with transportKind "libp2p" requires the "ipfs" capability.`,
|
|
893
|
+
location,
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
if (
|
|
897
|
+
wireIdValid &&
|
|
898
|
+
normalizedTransportKind === ProtocolTransportKind.WS &&
|
|
899
|
+
protocol.defaultPort === 443 &&
|
|
900
|
+
protocol.requireSecureTransport !== true
|
|
901
|
+
) {
|
|
902
|
+
pushIssue(
|
|
903
|
+
issues,
|
|
904
|
+
"warning",
|
|
905
|
+
"insecure-secure-port-hint",
|
|
906
|
+
`Protocol "${protocol.protocolId ?? "protocol"}" uses defaultPort 443 without requireSecureTransport=true.`,
|
|
907
|
+
`${location}.defaultPort`,
|
|
908
|
+
);
|
|
909
|
+
}
|
|
593
910
|
}
|
|
594
911
|
|
|
595
912
|
function validateRuntimeTargets(runtimeTargets, declaredCapabilities, issues, sourceName) {
|
|
@@ -658,6 +975,66 @@ function validateRuntimeTargets(runtimeTargets, declaredCapabilities, issues, so
|
|
|
658
975
|
}
|
|
659
976
|
}
|
|
660
977
|
|
|
978
|
+
function validateStandaloneWasiTarget(
|
|
979
|
+
manifest,
|
|
980
|
+
normalizedInvokeSurfaces,
|
|
981
|
+
declaredCapabilities,
|
|
982
|
+
issues,
|
|
983
|
+
sourceName,
|
|
984
|
+
) {
|
|
985
|
+
const runtimeTargets = Array.isArray(manifest?.runtimeTargets)
|
|
986
|
+
? manifest.runtimeTargets
|
|
987
|
+
: [];
|
|
988
|
+
if (!runtimeTargets.includes(RuntimeTarget.WASI)) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
if (!normalizedInvokeSurfaces.includes(InvokeSurface.COMMAND)) {
|
|
993
|
+
pushIssue(
|
|
994
|
+
issues,
|
|
995
|
+
"error",
|
|
996
|
+
"missing-wasi-command-surface",
|
|
997
|
+
'Artifacts targeting the canonical "wasi" runtime must declare the "command" invoke surface so they can run as standalone WASI programs without host wrappers.',
|
|
998
|
+
`${sourceName}.invokeSurfaces`,
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
if (Array.isArray(declaredCapabilities)) {
|
|
1003
|
+
for (const capability of declaredCapabilities) {
|
|
1004
|
+
if (!StandaloneWasiCapabilitySet.has(capability)) {
|
|
1005
|
+
pushIssue(
|
|
1006
|
+
issues,
|
|
1007
|
+
"error",
|
|
1008
|
+
"capability-wasi-standalone-conflict",
|
|
1009
|
+
`Capability "${capability}" is not available to a standalone WASI artifact without host wrappers.`,
|
|
1010
|
+
`${sourceName}.capabilities`,
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
if (!Array.isArray(manifest?.protocols)) {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
manifest.protocols.forEach((protocol, index) => {
|
|
1020
|
+
const normalizedTransportKind = normalizeProtocolTransportKind(
|
|
1021
|
+
protocol?.transportKind,
|
|
1022
|
+
);
|
|
1023
|
+
if (
|
|
1024
|
+
normalizedTransportKind &&
|
|
1025
|
+
!StandaloneWasiProtocolTransportKindSet.has(normalizedTransportKind)
|
|
1026
|
+
) {
|
|
1027
|
+
pushIssue(
|
|
1028
|
+
issues,
|
|
1029
|
+
"error",
|
|
1030
|
+
"protocol-wasi-standalone-conflict",
|
|
1031
|
+
`Protocol "${protocol?.protocolId ?? "protocol"}" uses transportKind "${protocol?.transportKind}", which requires a host wrapper rather than a standalone WASI runtime.`,
|
|
1032
|
+
`${sourceName}.protocols[${index}].transportKind`,
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
|
|
661
1038
|
function validateInvokeSurfaces(invokeSurfaces, issues, sourceName) {
|
|
662
1039
|
if (invokeSurfaces === undefined) {
|
|
663
1040
|
return [];
|
|
@@ -781,7 +1158,11 @@ export function validatePluginManifest(manifest, options = {}) {
|
|
|
781
1158
|
issues,
|
|
782
1159
|
sourceName,
|
|
783
1160
|
);
|
|
784
|
-
validateInvokeSurfaces(
|
|
1161
|
+
const normalizedInvokeSurfaces = validateInvokeSurfaces(
|
|
1162
|
+
manifest.invokeSurfaces,
|
|
1163
|
+
issues,
|
|
1164
|
+
sourceName,
|
|
1165
|
+
);
|
|
785
1166
|
|
|
786
1167
|
if (!Array.isArray(manifest.externalInterfaces)) {
|
|
787
1168
|
pushIssue(
|
|
@@ -922,6 +1303,14 @@ export function validatePluginManifest(manifest, options = {}) {
|
|
|
922
1303
|
}
|
|
923
1304
|
}
|
|
924
1305
|
|
|
1306
|
+
validateStandaloneWasiTarget(
|
|
1307
|
+
manifest,
|
|
1308
|
+
normalizedInvokeSurfaces,
|
|
1309
|
+
declaredCapabilities,
|
|
1310
|
+
issues,
|
|
1311
|
+
sourceName,
|
|
1312
|
+
);
|
|
1313
|
+
|
|
925
1314
|
if (manifest.schemasUsed !== undefined && !Array.isArray(manifest.schemasUsed)) {
|
|
926
1315
|
pushIssue(
|
|
927
1316
|
issues,
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PluginManifest,
|
|
3
|
+
ProtocolRoleName,
|
|
4
|
+
ProtocolSpec,
|
|
5
|
+
ProtocolTransportKindName,
|
|
6
|
+
} from "../index.js";
|
|
7
|
+
|
|
8
|
+
export type InputBindingSourceKindName =
|
|
9
|
+
| "pubsub"
|
|
10
|
+
| "protocol-stream"
|
|
11
|
+
| "catalog-sync";
|
|
12
|
+
export type DeploymentBindingModeName = "local" | "delegated";
|
|
13
|
+
export type ScheduleBindingKindName = "interval" | "cron" | "once";
|
|
14
|
+
|
|
15
|
+
export interface ResolvedProtocolInstallation {
|
|
16
|
+
protocolId: string;
|
|
17
|
+
wireId: string;
|
|
18
|
+
transportKind: ProtocolTransportKindName | string;
|
|
19
|
+
role: ProtocolRoleName | string;
|
|
20
|
+
peerId?: string | null;
|
|
21
|
+
listenMultiaddrs?: string[];
|
|
22
|
+
advertisedMultiaddrs?: string[];
|
|
23
|
+
nodeInfoUrl?: string | null;
|
|
24
|
+
serviceName?: string | null;
|
|
25
|
+
resolvedPort?: number;
|
|
26
|
+
artifactCid?: string | null;
|
|
27
|
+
description?: string | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface InputBinding {
|
|
31
|
+
bindingId: string;
|
|
32
|
+
targetPluginId?: string | null;
|
|
33
|
+
targetMethodId: string;
|
|
34
|
+
targetInputPortId: string;
|
|
35
|
+
sourceKind: InputBindingSourceKindName | string;
|
|
36
|
+
topic?: string | null;
|
|
37
|
+
wireId?: string | null;
|
|
38
|
+
nodeInfoUrl?: string | null;
|
|
39
|
+
multiaddrs?: string[];
|
|
40
|
+
allowPeerIds?: string[];
|
|
41
|
+
allowServerKeys?: string[];
|
|
42
|
+
deliveryMode?: string | null;
|
|
43
|
+
description?: string | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ScheduleBinding {
|
|
47
|
+
scheduleId: string;
|
|
48
|
+
bindingMode: DeploymentBindingModeName | string;
|
|
49
|
+
triggerId?: string | null;
|
|
50
|
+
targetMethodId?: string | null;
|
|
51
|
+
targetInputPortId?: string | null;
|
|
52
|
+
scheduleKind: ScheduleBindingKindName | string;
|
|
53
|
+
cron?: string | null;
|
|
54
|
+
intervalMs?: number;
|
|
55
|
+
runAtStartup?: boolean;
|
|
56
|
+
startupDelayMs?: number;
|
|
57
|
+
timezone?: string | null;
|
|
58
|
+
description?: string | null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ServiceBinding {
|
|
62
|
+
serviceId: string;
|
|
63
|
+
bindingMode: DeploymentBindingModeName | string;
|
|
64
|
+
serviceKind: string;
|
|
65
|
+
triggerId?: string | null;
|
|
66
|
+
protocolId?: string | null;
|
|
67
|
+
routePath?: string | null;
|
|
68
|
+
method?: string | null;
|
|
69
|
+
transportKind?: ProtocolTransportKindName | string | null;
|
|
70
|
+
adapter?: string | null;
|
|
71
|
+
listenHost?: string | null;
|
|
72
|
+
listenPort?: number;
|
|
73
|
+
remoteUrl?: string | null;
|
|
74
|
+
allowTransports?: string[];
|
|
75
|
+
authPolicyId?: string | null;
|
|
76
|
+
description?: string | null;
|
|
77
|
+
properties?: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface AuthPolicy {
|
|
81
|
+
policyId: string;
|
|
82
|
+
bindingMode: DeploymentBindingModeName | string;
|
|
83
|
+
targetKind: string;
|
|
84
|
+
targetId?: string | null;
|
|
85
|
+
adapter?: string | null;
|
|
86
|
+
walletProfileId?: string | null;
|
|
87
|
+
trustMapId?: string | null;
|
|
88
|
+
allowPeerIds?: string[];
|
|
89
|
+
allowServerKeys?: string[];
|
|
90
|
+
allowEntityIds?: string[];
|
|
91
|
+
requireSignedRequests?: boolean;
|
|
92
|
+
requireEncryptedTransport?: boolean;
|
|
93
|
+
description?: string | null;
|
|
94
|
+
properties?: Record<string, unknown>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface PublicationBinding {
|
|
98
|
+
publicationId: string;
|
|
99
|
+
bindingMode: DeploymentBindingModeName | string;
|
|
100
|
+
sourceKind: string;
|
|
101
|
+
sourceMethodId?: string | null;
|
|
102
|
+
sourceOutputPortId?: string | null;
|
|
103
|
+
sourceNodeId?: string | null;
|
|
104
|
+
sourceTriggerId?: string | null;
|
|
105
|
+
topic?: string | null;
|
|
106
|
+
wireId?: string | null;
|
|
107
|
+
schemaName?: string | null;
|
|
108
|
+
mediaType?: string | null;
|
|
109
|
+
archivePath?: string | null;
|
|
110
|
+
queryServiceId?: string | null;
|
|
111
|
+
emitPnm?: boolean;
|
|
112
|
+
emitFlatbufferArchive?: boolean;
|
|
113
|
+
pinPolicy?: string | null;
|
|
114
|
+
maxRecords?: number;
|
|
115
|
+
maxBytes?: number;
|
|
116
|
+
minLivelinessSeconds?: number;
|
|
117
|
+
recordRangeStartField?: string | null;
|
|
118
|
+
recordRangeStopField?: string | null;
|
|
119
|
+
description?: string | null;
|
|
120
|
+
properties?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface ModuleDeploymentPlan {
|
|
124
|
+
formatVersion?: number;
|
|
125
|
+
pluginId?: string | null;
|
|
126
|
+
version?: string | null;
|
|
127
|
+
artifactCid?: string | null;
|
|
128
|
+
bundleCid?: string | null;
|
|
129
|
+
environmentId?: string | null;
|
|
130
|
+
protocolInstallations?: ResolvedProtocolInstallation[];
|
|
131
|
+
inputBindings?: InputBinding[];
|
|
132
|
+
scheduleBindings?: ScheduleBinding[];
|
|
133
|
+
serviceBindings?: ServiceBinding[];
|
|
134
|
+
authPolicies?: AuthPolicy[];
|
|
135
|
+
publicationBindings?: PublicationBinding[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface DeploymentPlanIssue {
|
|
139
|
+
severity: "error" | "warning";
|
|
140
|
+
code: string;
|
|
141
|
+
message: string;
|
|
142
|
+
location?: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface DeploymentPlanValidationReport {
|
|
146
|
+
ok: boolean;
|
|
147
|
+
plan: ModuleDeploymentPlan;
|
|
148
|
+
issues: DeploymentPlanIssue[];
|
|
149
|
+
errors: DeploymentPlanIssue[];
|
|
150
|
+
warnings: DeploymentPlanIssue[];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export const DEPLOYMENT_PLAN_FORMAT_VERSION: number;
|
|
154
|
+
|
|
155
|
+
export const InputBindingSourceKind: {
|
|
156
|
+
PUBSUB: InputBindingSourceKindName;
|
|
157
|
+
PROTOCOL_STREAM: InputBindingSourceKindName;
|
|
158
|
+
CATALOG_SYNC: InputBindingSourceKindName;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const DeploymentBindingMode: {
|
|
162
|
+
LOCAL: DeploymentBindingModeName;
|
|
163
|
+
DELEGATED: DeploymentBindingModeName;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const ScheduleBindingKind: {
|
|
167
|
+
INTERVAL: ScheduleBindingKindName;
|
|
168
|
+
CRON: ScheduleBindingKindName;
|
|
169
|
+
ONCE: ScheduleBindingKindName;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export function normalizeProtocolTransportKindName(
|
|
173
|
+
value: ProtocolTransportKindName | string | null | undefined,
|
|
174
|
+
): ProtocolTransportKindName | string | null;
|
|
175
|
+
|
|
176
|
+
export function normalizeProtocolRoleName(
|
|
177
|
+
value: ProtocolRoleName | string | null | undefined,
|
|
178
|
+
): ProtocolRoleName | string | null;
|
|
179
|
+
|
|
180
|
+
export function normalizeInputBindingSourceKindName(
|
|
181
|
+
value: InputBindingSourceKindName | string | null | undefined,
|
|
182
|
+
): InputBindingSourceKindName | string | null;
|
|
183
|
+
|
|
184
|
+
export function normalizeDeploymentBindingModeName(
|
|
185
|
+
value: DeploymentBindingModeName | string | null | undefined,
|
|
186
|
+
): DeploymentBindingModeName | string | null;
|
|
187
|
+
|
|
188
|
+
export function normalizeScheduleBindingKindName(
|
|
189
|
+
value: ScheduleBindingKindName | string | null | undefined,
|
|
190
|
+
): ScheduleBindingKindName | string | null;
|
|
191
|
+
|
|
192
|
+
export function normalizeDeploymentPlan(
|
|
193
|
+
plan: ModuleDeploymentPlan | null | undefined,
|
|
194
|
+
): ModuleDeploymentPlan;
|
|
195
|
+
|
|
196
|
+
export function validateDeploymentPlan(
|
|
197
|
+
plan: ModuleDeploymentPlan | null | undefined,
|
|
198
|
+
options?: { manifest?: PluginManifest | null },
|
|
199
|
+
): DeploymentPlanValidationReport;
|
|
200
|
+
|
|
201
|
+
export function createDeploymentPlanBundleEntry(
|
|
202
|
+
plan: ModuleDeploymentPlan | null | undefined,
|
|
203
|
+
options?: {
|
|
204
|
+
entryId?: string;
|
|
205
|
+
role?: string;
|
|
206
|
+
sectionName?: string;
|
|
207
|
+
mediaType?: string;
|
|
208
|
+
description?: string;
|
|
209
|
+
},
|
|
210
|
+
): {
|
|
211
|
+
entryId: string;
|
|
212
|
+
role: string;
|
|
213
|
+
sectionName: string;
|
|
214
|
+
payloadEncoding: "json-utf8";
|
|
215
|
+
mediaType: string;
|
|
216
|
+
payload: ModuleDeploymentPlan;
|
|
217
|
+
description: string;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
export function findDeploymentPlanEntry(bundleLike: unknown): unknown | null;
|
|
221
|
+
|
|
222
|
+
export function readDeploymentPlanFromBundle(
|
|
223
|
+
bundleLike: unknown,
|
|
224
|
+
): ModuleDeploymentPlan | null;
|