space-data-module-sdk 0.7.0 → 0.8.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 +16 -23
- package/bin/space-data-module.js +5 -3
- package/package.json +2 -2
- package/schemas/spacedatastandards/PLG.fbs +191 -0
- package/src/AGENTS.md +1 -1
- package/src/bundle/AGENTS.md +6 -5
- package/src/bundle/codec.js +163 -48
- package/src/bundle/constants.js +1 -1
- package/src/bundle/wasm.js +53 -32
- package/src/compiler/compileModule.js +9 -1
- package/src/compliance/index.js +4 -0
- package/src/compliance/pluginCompliance.js +158 -2
- package/src/embeddedManifest.js +25 -5
- package/src/generated/orbpro/invoke/plugin-invoke-request.js +2 -2
- package/src/generated/orbpro/invoke/plugin-invoke-response.js +2 -2
- package/src/generated/orbpro/stream/flat-buffer-type-ref.js +2 -2
- package/src/generated/orbpro/stream/typed-arena-buffer.js +2 -2
- package/src/generated/spacedatastandards/plg/entry-function.js +86 -0
- package/src/generated/spacedatastandards/plg/entry-function.ts +119 -0
- package/src/generated/spacedatastandards/plg/index.js +16 -0
- package/src/generated/spacedatastandards/plg/index.ts +11 -0
- package/src/generated/spacedatastandards/plg/plg.js +657 -0
- package/src/generated/spacedatastandards/plg/plg.ts +924 -0
- package/src/generated/spacedatastandards/plg/plugin-capability.js +66 -0
- package/src/generated/spacedatastandards/plg/plugin-capability.ts +84 -0
- package/src/generated/spacedatastandards/plg/plugin-category.js +15 -0
- package/src/generated/spacedatastandards/plg/plugin-category.ts +53 -0
- package/src/generated/spacedatastandards/plg/plugin-dependency.js +63 -0
- package/src/generated/spacedatastandards/plg/plugin-dependency.ts +86 -0
- package/src/generated/spacedatastandards/plg/publication-state.js +9 -0
- package/src/generated/spacedatastandards/plg/publication-state.ts +23 -0
- package/src/generated/spacedatastandards/plg/purchase-tier.js +9 -0
- package/src/generated/spacedatastandards/plg/purchase-tier.ts +23 -0
- package/src/index.d.ts +1 -1
- package/src/invoke/codec.js +1 -1
- package/src/manifest/browser.js +7 -0
- package/src/manifest/index.js +7 -0
- package/src/manifest/legacyToPlg.js +249 -0
- package/src/manifest/plgCodec.js +826 -0
- package/src/standards/sharedCatalog.js +132 -0
- package/src/transport/records.js +34 -3
- package/src/vendor/flatbuffers/LICENSE +202 -0
- package/src/vendor/flatbuffers/builder.js +534 -0
- package/src/vendor/flatbuffers/byte-buffer.js +253 -0
- package/src/vendor/flatbuffers/constants.js +4 -0
- package/src/vendor/flatbuffers/encoding.js +5 -0
- package/src/vendor/flatbuffers/flatbuffers.js +5 -0
- package/src/vendor/flatbuffers/utils.js +4 -0
- package/schemas/ModuleBundle.fbs +0 -108
- package/src/generated/orbpro/module/canonicalization-rule.d.ts +0 -48
- package/src/generated/orbpro/module/canonicalization-rule.js +0 -95
- package/src/generated/orbpro/module/canonicalization-rule.ts +0 -142
- package/src/generated/orbpro/module/module-bundle-entry-role.d.ts +0 -11
- package/src/generated/orbpro/module/module-bundle-entry-role.js +0 -14
- package/src/generated/orbpro/module/module-bundle-entry-role.ts +0 -15
- package/src/generated/orbpro/module/module-bundle-entry.d.ts +0 -97
- package/src/generated/orbpro/module/module-bundle-entry.js +0 -219
- package/src/generated/orbpro/module/module-bundle-entry.ts +0 -287
- package/src/generated/orbpro/module/module-bundle.d.ts +0 -86
- package/src/generated/orbpro/module/module-bundle.js +0 -213
- package/src/generated/orbpro/module/module-bundle.ts +0 -277
- package/src/generated/orbpro/module/module-payload-encoding.d.ts +0 -9
- package/src/generated/orbpro/module/module-payload-encoding.js +0 -12
- package/src/generated/orbpro/module/module-payload-encoding.ts +0 -13
- package/src/generated/orbpro/module.d.ts +0 -5
- package/src/generated/orbpro/module.js +0 -7
- package/src/generated/orbpro/module.ts +0 -9
package/src/bundle/wasm.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { canonicalBytes } from "../auth/canonicalize.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
decodePluginManifest,
|
|
4
|
+
decodePlgManifest,
|
|
5
|
+
encodePlgManifest,
|
|
6
|
+
isPlgManifestBuffer,
|
|
7
|
+
legacyManifestToPlg,
|
|
8
|
+
} from "../manifest/index.js";
|
|
3
9
|
import { toUint8Array } from "../runtime/bufferLike.js";
|
|
4
10
|
import { sha256Bytes } from "../utils/crypto.js";
|
|
5
11
|
import { bytesToHex } from "../utils/encoding.js";
|
|
@@ -7,10 +13,10 @@ import { createDeploymentPlanBundleEntry } from "../deployment/index.js";
|
|
|
7
13
|
import {
|
|
8
14
|
DEFAULT_MANIFEST_EXPORT_SYMBOL,
|
|
9
15
|
DEFAULT_MANIFEST_SIZE_SYMBOL,
|
|
10
|
-
SDS_BUNDLE_SECTION_NAME,
|
|
11
16
|
SDS_CUSTOM_SECTION_PREFIX,
|
|
12
17
|
SDS_DEPLOYMENT_ENTRY_ID,
|
|
13
18
|
SDS_DEPLOYMENT_SECTION_NAME,
|
|
19
|
+
SDS_MBL_CONTAINER_NAME,
|
|
14
20
|
} from "./constants.js";
|
|
15
21
|
import {
|
|
16
22
|
decodeModuleBundle,
|
|
@@ -20,7 +26,11 @@ import {
|
|
|
20
26
|
moduleBundleEncodingToName,
|
|
21
27
|
moduleBundleRoleToName,
|
|
22
28
|
} from "./codec.js";
|
|
23
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
appendPublicationRecordCollection,
|
|
31
|
+
encodePublicationRecordCollection,
|
|
32
|
+
extractPublicationRecordCollection,
|
|
33
|
+
} from "../transport/records.js";
|
|
24
34
|
|
|
25
35
|
const textDecoder = new TextDecoder();
|
|
26
36
|
const textEncoder = new TextEncoder();
|
|
@@ -222,20 +232,36 @@ function normalizeJsonPayload(value) {
|
|
|
222
232
|
return new Uint8Array(canonicalBytes(value));
|
|
223
233
|
}
|
|
224
234
|
|
|
235
|
+
function encodeBundleManifest(manifest) {
|
|
236
|
+
return encodePlgManifest(legacyManifestToPlg(manifest));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function decodeBundleManifest(payloadBytes) {
|
|
240
|
+
return isPlgManifestBuffer(payloadBytes)
|
|
241
|
+
? decodePlgManifest(payloadBytes)
|
|
242
|
+
: decodePluginManifest(payloadBytes);
|
|
243
|
+
}
|
|
244
|
+
|
|
225
245
|
function normalizeManifestEntry(manifest, manifestBytes) {
|
|
226
246
|
if (!manifest && !manifestBytes) {
|
|
227
247
|
return null;
|
|
228
248
|
}
|
|
229
|
-
const payload = manifestBytes ??
|
|
249
|
+
const payload = manifestBytes ?? encodeBundleManifest(manifest);
|
|
250
|
+
const isPlg = isPlgManifestBuffer(payload);
|
|
230
251
|
return {
|
|
231
252
|
entryId: "manifest",
|
|
232
253
|
role: "manifest",
|
|
233
254
|
sectionName: "sds.manifest",
|
|
234
255
|
payloadEncoding: "flatbuffer",
|
|
235
|
-
typeRef:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
256
|
+
typeRef: isPlg
|
|
257
|
+
? {
|
|
258
|
+
schemaName: "PLG.fbs",
|
|
259
|
+
fileIdentifier: "$PLG",
|
|
260
|
+
}
|
|
261
|
+
: {
|
|
262
|
+
schemaName: "PluginManifest.fbs",
|
|
263
|
+
fileIdentifier: "PMAN",
|
|
264
|
+
},
|
|
239
265
|
payload,
|
|
240
266
|
description: "Canonical plugin manifest.",
|
|
241
267
|
};
|
|
@@ -326,7 +352,7 @@ function buildParsedEntries(bundle) {
|
|
|
326
352
|
parsedEntry.payloadEncodingName === "flatbuffer"
|
|
327
353
|
) {
|
|
328
354
|
try {
|
|
329
|
-
parsedEntry.decodedManifest =
|
|
355
|
+
parsedEntry.decodedManifest = decodeBundleManifest(payloadBytes);
|
|
330
356
|
} catch {
|
|
331
357
|
parsedEntry.decodedManifest = null;
|
|
332
358
|
}
|
|
@@ -376,7 +402,7 @@ export async function createSingleFileBundle(options = {}) {
|
|
|
376
402
|
options.manifestBytes !== undefined
|
|
377
403
|
? normalizeBytes(options.manifestBytes, "manifestBytes")
|
|
378
404
|
: options.manifest
|
|
379
|
-
?
|
|
405
|
+
? encodeBundleManifest(options.manifest)
|
|
380
406
|
: null;
|
|
381
407
|
const manifestEntry = normalizeManifestEntry(options.manifest, manifestBytes);
|
|
382
408
|
const rawEntries = [
|
|
@@ -392,7 +418,7 @@ export async function createSingleFileBundle(options = {}) {
|
|
|
392
418
|
version: 1,
|
|
393
419
|
strippedCustomSectionPrefix:
|
|
394
420
|
options.customSectionPrefix ?? SDS_CUSTOM_SECTION_PREFIX,
|
|
395
|
-
bundleSectionName: options.bundleSectionName ??
|
|
421
|
+
bundleSectionName: options.bundleSectionName ?? SDS_MBL_CONTAINER_NAME,
|
|
396
422
|
hashAlgorithm: "sha256",
|
|
397
423
|
};
|
|
398
424
|
const canonical = await computeCanonicalModuleHash(wasmBytes, {
|
|
@@ -415,10 +441,14 @@ export async function createSingleFileBundle(options = {}) {
|
|
|
415
441
|
const baseWasmBytes = stripWasmCustomSections(wasmBytes, (section) =>
|
|
416
442
|
section.name.startsWith(canonicalization.strippedCustomSectionPrefix),
|
|
417
443
|
);
|
|
418
|
-
const outputWasmBytes =
|
|
444
|
+
const outputWasmBytes = appendPublicationRecordCollection(
|
|
419
445
|
baseWasmBytes,
|
|
420
|
-
|
|
421
|
-
|
|
446
|
+
encodePublicationRecordCollection({
|
|
447
|
+
version: protectedArtifact?.version,
|
|
448
|
+
mbl: bundle,
|
|
449
|
+
enc: protectedArtifact?.enc,
|
|
450
|
+
pnm: protectedArtifact?.pnm,
|
|
451
|
+
}),
|
|
422
452
|
);
|
|
423
453
|
return {
|
|
424
454
|
bundle,
|
|
@@ -434,25 +464,16 @@ export async function createSingleFileBundle(options = {}) {
|
|
|
434
464
|
|
|
435
465
|
export async function parseSingleFileBundle(bytes, options = {}) {
|
|
436
466
|
const protectedArtifact = extractPublicationRecordCollection(bytes);
|
|
467
|
+
if (!protectedArtifact?.mbl) {
|
|
468
|
+
throw new Error("Missing required REC trailer containing an MBL record.");
|
|
469
|
+
}
|
|
437
470
|
const wasmBytes = normalizeBytes(
|
|
438
|
-
protectedArtifact
|
|
471
|
+
protectedArtifact.payloadBytes,
|
|
439
472
|
"wasm bytes",
|
|
440
473
|
);
|
|
441
474
|
const customSections = listWasmCustomSections(wasmBytes);
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
);
|
|
445
|
-
const bundleSections = customSections.filter(
|
|
446
|
-
(section) => section.name === bundleSectionName,
|
|
447
|
-
);
|
|
448
|
-
if (bundleSections.length === 0) {
|
|
449
|
-
throw new Error(`Missing required custom section "${bundleSectionName}".`);
|
|
450
|
-
}
|
|
451
|
-
if (bundleSections.length > 1) {
|
|
452
|
-
throw new Error(`Expected one "${bundleSectionName}" section, found ${bundleSections.length}.`);
|
|
453
|
-
}
|
|
454
|
-
const bundleBytes = bundleSections[0].dataBytes;
|
|
455
|
-
const bundle = decodeModuleBundle(bundleBytes);
|
|
475
|
+
const bundle = protectedArtifact.mbl;
|
|
476
|
+
const bundleBytes = protectedArtifact.mblBytes ?? encodeModuleBundle(bundle);
|
|
456
477
|
const prefix =
|
|
457
478
|
bundle.canonicalization?.strippedCustomSectionPrefix ??
|
|
458
479
|
SDS_CUSTOM_SECTION_PREFIX;
|
|
@@ -464,7 +485,7 @@ export async function parseSingleFileBundle(bytes, options = {}) {
|
|
|
464
485
|
let manifest = null;
|
|
465
486
|
if (manifestEntry) {
|
|
466
487
|
try {
|
|
467
|
-
manifest =
|
|
488
|
+
manifest = decodeBundleManifest(new Uint8Array(manifestEntry.payload ?? []));
|
|
468
489
|
} catch {
|
|
469
490
|
manifest = null;
|
|
470
491
|
}
|
|
@@ -477,8 +498,8 @@ export async function parseSingleFileBundle(bytes, options = {}) {
|
|
|
477
498
|
) ?? null;
|
|
478
499
|
return {
|
|
479
500
|
wasmBytes,
|
|
480
|
-
protectedArtifactBytes: protectedArtifact
|
|
481
|
-
publicationRecords: protectedArtifact
|
|
501
|
+
protectedArtifactBytes: protectedArtifact.protectedBytes,
|
|
502
|
+
publicationRecords: protectedArtifact,
|
|
482
503
|
bundleBytes,
|
|
483
504
|
bundle,
|
|
484
505
|
entries: parsedEntries,
|
|
@@ -894,6 +894,7 @@ export async function protectModuleArtifact(options = {}) {
|
|
|
894
894
|
};
|
|
895
895
|
|
|
896
896
|
let singleFileBundle = null;
|
|
897
|
+
let singleFileBundleRecords = null;
|
|
897
898
|
if (options.singleFileBundle === true) {
|
|
898
899
|
const additionalEntries = [
|
|
899
900
|
...(Array.isArray(options.bundleEntries) ? options.bundleEntries : []),
|
|
@@ -905,9 +906,13 @@ export async function protectModuleArtifact(options = {}) {
|
|
|
905
906
|
authorization: signedAuthorization,
|
|
906
907
|
entries: additionalEntries,
|
|
907
908
|
});
|
|
909
|
+
singleFileBundleRecords = extractPublicationRecordCollection(
|
|
910
|
+
singleFileBundle.wasmBytes,
|
|
911
|
+
);
|
|
908
912
|
}
|
|
909
913
|
|
|
910
|
-
const bundleBytes =
|
|
914
|
+
const bundleBytes = singleFileBundleRecords?.payloadBytes ?? wasmBytes;
|
|
915
|
+
const bundleRecord = singleFileBundleRecords?.mbl ?? null;
|
|
911
916
|
let publicationNotice = null;
|
|
912
917
|
let publicationRecordsBytes = null;
|
|
913
918
|
let protectedArtifactBytes = null;
|
|
@@ -931,6 +936,7 @@ export async function protectModuleArtifact(options = {}) {
|
|
|
931
936
|
signer,
|
|
932
937
|
});
|
|
933
938
|
publicationRecordsBytes = encodePublicationRecordCollection({
|
|
939
|
+
mbl: bundleRecord,
|
|
934
940
|
enc: parsedEncryptedBase.enc,
|
|
935
941
|
pnm: publicationNotice,
|
|
936
942
|
});
|
|
@@ -943,6 +949,7 @@ export async function protectModuleArtifact(options = {}) {
|
|
|
943
949
|
parsedProtectedBlob: {
|
|
944
950
|
payloadBytes: parsedEncryptedBase.payloadBytes,
|
|
945
951
|
recordCollectionBytes: publicationRecordsBytes,
|
|
952
|
+
mbl: bundleRecord,
|
|
946
953
|
enc: parsedEncryptedBase.enc,
|
|
947
954
|
pnm: publicationNotice,
|
|
948
955
|
},
|
|
@@ -959,6 +966,7 @@ export async function protectModuleArtifact(options = {}) {
|
|
|
959
966
|
signer,
|
|
960
967
|
});
|
|
961
968
|
publicationRecordsBytes = encodePublicationRecordCollection({
|
|
969
|
+
mbl: bundleRecord,
|
|
962
970
|
pnm: publicationNotice,
|
|
963
971
|
});
|
|
964
972
|
protectedArtifactBytes = appendPublicationRecordCollection(
|
package/src/compliance/index.js
CHANGED
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
findManifestFiles,
|
|
3
3
|
getWasmExportNames,
|
|
4
4
|
getWasmExportNamesFromFile,
|
|
5
|
+
hasLegacyPmanManifest,
|
|
5
6
|
loadManifestFromFile,
|
|
6
7
|
loadComplianceConfig,
|
|
8
|
+
locateEmbeddedPlgManifest,
|
|
7
9
|
resolveManifestFiles,
|
|
8
10
|
validatePluginArtifact,
|
|
9
11
|
validatePluginManifest,
|
|
@@ -49,8 +51,10 @@ export {
|
|
|
49
51
|
findManifestFiles,
|
|
50
52
|
getWasmExportNames,
|
|
51
53
|
getWasmExportNamesFromFile,
|
|
54
|
+
hasLegacyPmanManifest,
|
|
52
55
|
loadManifestFromFile,
|
|
53
56
|
loadComplianceConfig,
|
|
57
|
+
locateEmbeddedPlgManifest,
|
|
54
58
|
RecommendedCapabilityIds,
|
|
55
59
|
StandaloneWasiCapabilityIds,
|
|
56
60
|
resolveManifestFiles,
|
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
RecommendedCapabilityIds,
|
|
17
17
|
StandaloneWasiCapabilityIds,
|
|
18
18
|
} from "../capabilities.js";
|
|
19
|
+
import {
|
|
20
|
+
PLG_FILE_IDENTIFIER,
|
|
21
|
+
decodePlgManifest,
|
|
22
|
+
isPlgManifestBuffer,
|
|
23
|
+
} from "../manifest/plgCodec.js";
|
|
19
24
|
|
|
20
25
|
const RecommendedCapabilitySet = new Set(RecommendedCapabilityIds);
|
|
21
26
|
const StandaloneWasiCapabilitySet = new Set(StandaloneWasiCapabilityIds);
|
|
@@ -1356,11 +1361,143 @@ export async function getWasmExportNamesFromFile(wasmPath) {
|
|
|
1356
1361
|
return getWasmExportNames(wasmBytes);
|
|
1357
1362
|
}
|
|
1358
1363
|
|
|
1364
|
+
const PLG_IDENTIFIER_BYTES = Uint8Array.from(
|
|
1365
|
+
Array.from(PLG_FILE_IDENTIFIER, (ch) => ch.charCodeAt(0)),
|
|
1366
|
+
);
|
|
1367
|
+
const LEGACY_PMAN_IDENTIFIER_BYTES = Uint8Array.from([0x50, 0x4d, 0x41, 0x4e]);
|
|
1368
|
+
|
|
1369
|
+
function indexOfBytes(haystack, needle, startIndex = 0) {
|
|
1370
|
+
if (!haystack || needle.length === 0 || haystack.length < needle.length) {
|
|
1371
|
+
return -1;
|
|
1372
|
+
}
|
|
1373
|
+
for (let i = startIndex; i <= haystack.length - needle.length; i += 1) {
|
|
1374
|
+
let matched = true;
|
|
1375
|
+
for (let j = 0; j < needle.length; j += 1) {
|
|
1376
|
+
if (haystack[i + j] !== needle[j]) {
|
|
1377
|
+
matched = false;
|
|
1378
|
+
break;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
if (matched) {
|
|
1382
|
+
return i;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
return -1;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
/**
|
|
1389
|
+
* Scan wasm bytes for the canonical `$PLG` FlatBuffer identifier and, when
|
|
1390
|
+
* found, return both the raw offset and the smallest aligned candidate buffer
|
|
1391
|
+
* that a downstream decoder can try to parse. The wasm `data` sections embed
|
|
1392
|
+
* the manifest bytes verbatim; FlatBuffer headers are `<root_offset:u32><$PLG>`
|
|
1393
|
+
* so we walk backwards one 4-byte word and hand the caller a slice starting
|
|
1394
|
+
* there.
|
|
1395
|
+
*/
|
|
1396
|
+
export function locateEmbeddedPlgManifest(wasmBytes) {
|
|
1397
|
+
const bytes = wasmBytes instanceof Uint8Array
|
|
1398
|
+
? wasmBytes
|
|
1399
|
+
: new Uint8Array(wasmBytes);
|
|
1400
|
+
const identifierOffset = indexOfBytes(bytes, PLG_IDENTIFIER_BYTES);
|
|
1401
|
+
if (identifierOffset < 4) {
|
|
1402
|
+
return null;
|
|
1403
|
+
}
|
|
1404
|
+
const start = identifierOffset - 4;
|
|
1405
|
+
// Upper bound on the manifest size — grab up to 64KB and let the caller
|
|
1406
|
+
// decide how much to trim. FlatBuffer decoders only read what they need.
|
|
1407
|
+
const end = Math.min(bytes.length, start + 65536);
|
|
1408
|
+
const candidate = bytes.subarray(start, end);
|
|
1409
|
+
if (!isPlgManifestBuffer(candidate)) {
|
|
1410
|
+
return null;
|
|
1411
|
+
}
|
|
1412
|
+
return { start, identifierOffset, bytes: candidate };
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
export function hasLegacyPmanManifest(wasmBytes) {
|
|
1416
|
+
const bytes = wasmBytes instanceof Uint8Array
|
|
1417
|
+
? wasmBytes
|
|
1418
|
+
: new Uint8Array(wasmBytes);
|
|
1419
|
+
return indexOfBytes(bytes, LEGACY_PMAN_IDENTIFIER_BYTES) !== -1;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
function validateEmbeddedManifestBytes({
|
|
1423
|
+
wasmBytes,
|
|
1424
|
+
manifest,
|
|
1425
|
+
issues,
|
|
1426
|
+
sourceLabel,
|
|
1427
|
+
}) {
|
|
1428
|
+
if (hasLegacyPmanManifest(wasmBytes)) {
|
|
1429
|
+
pushIssue(
|
|
1430
|
+
issues,
|
|
1431
|
+
"error",
|
|
1432
|
+
"legacy-pman-manifest-embedded",
|
|
1433
|
+
"Plugin artifact embeds legacy PMAN manifest bytes — rebuild with the PLG codec.",
|
|
1434
|
+
sourceLabel,
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
const located = locateEmbeddedPlgManifest(wasmBytes);
|
|
1439
|
+
if (!located) {
|
|
1440
|
+
pushIssue(
|
|
1441
|
+
issues,
|
|
1442
|
+
"error",
|
|
1443
|
+
"missing-plg-manifest-bytes",
|
|
1444
|
+
`Plugin artifact does not embed a canonical \"${PLG_FILE_IDENTIFIER}\" manifest buffer.`,
|
|
1445
|
+
sourceLabel,
|
|
1446
|
+
);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
let decoded;
|
|
1451
|
+
try {
|
|
1452
|
+
decoded = decodePlgManifest(located.bytes);
|
|
1453
|
+
} catch (error) {
|
|
1454
|
+
pushIssue(
|
|
1455
|
+
issues,
|
|
1456
|
+
"error",
|
|
1457
|
+
"plg-manifest-decode-failed",
|
|
1458
|
+
`Failed to decode embedded PLG manifest: ${error?.message ?? error}`,
|
|
1459
|
+
sourceLabel,
|
|
1460
|
+
);
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
const sourcePluginId = manifest?.pluginId ?? manifest?.plugin_id ?? null;
|
|
1465
|
+
if (
|
|
1466
|
+
isNonEmptyString(sourcePluginId) &&
|
|
1467
|
+
isNonEmptyString(decoded?.pluginId) &&
|
|
1468
|
+
sourcePluginId !== decoded.pluginId
|
|
1469
|
+
) {
|
|
1470
|
+
pushIssue(
|
|
1471
|
+
issues,
|
|
1472
|
+
"error",
|
|
1473
|
+
"plg-manifest-plugin-id-mismatch",
|
|
1474
|
+
`Embedded PLG manifest pluginId \"${decoded.pluginId}\" does not match source manifest pluginId \"${sourcePluginId}\".`,
|
|
1475
|
+
sourceLabel,
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
const sourceVersion = manifest?.version ?? null;
|
|
1480
|
+
if (
|
|
1481
|
+
isNonEmptyString(sourceVersion) &&
|
|
1482
|
+
isNonEmptyString(decoded?.version) &&
|
|
1483
|
+
sourceVersion !== decoded.version
|
|
1484
|
+
) {
|
|
1485
|
+
pushIssue(
|
|
1486
|
+
issues,
|
|
1487
|
+
"warning",
|
|
1488
|
+
"plg-manifest-version-mismatch",
|
|
1489
|
+
`Embedded PLG manifest version \"${decoded.version}\" does not match source manifest version \"${sourceVersion}\".`,
|
|
1490
|
+
sourceLabel,
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1359
1495
|
export async function validatePluginArtifact(options) {
|
|
1360
1496
|
const {
|
|
1361
1497
|
manifest,
|
|
1362
1498
|
manifestPath = null,
|
|
1363
1499
|
wasmPath = null,
|
|
1500
|
+
wasmBytes: inputWasmBytes = null,
|
|
1364
1501
|
exportNames = null,
|
|
1365
1502
|
sourceName = manifestPath ?? "manifest",
|
|
1366
1503
|
} = options;
|
|
@@ -1368,15 +1505,26 @@ export async function validatePluginArtifact(options) {
|
|
|
1368
1505
|
const issues = [...report.issues];
|
|
1369
1506
|
let resolvedExportNames = [];
|
|
1370
1507
|
let checkedArtifact = false;
|
|
1508
|
+
let loadedWasmBytes = null;
|
|
1371
1509
|
const declaredInvokeSurfaces = Array.isArray(manifest?.invokeSurfaces)
|
|
1372
1510
|
? manifest.invokeSurfaces.filter((surface) => InvokeSurfaceSet.has(surface))
|
|
1373
1511
|
: [];
|
|
1374
1512
|
|
|
1375
|
-
if (
|
|
1513
|
+
if (inputWasmBytes) {
|
|
1514
|
+
loadedWasmBytes =
|
|
1515
|
+
inputWasmBytes instanceof Uint8Array
|
|
1516
|
+
? inputWasmBytes
|
|
1517
|
+
: new Uint8Array(inputWasmBytes);
|
|
1518
|
+
resolvedExportNames = Array.isArray(exportNames)
|
|
1519
|
+
? [...exportNames]
|
|
1520
|
+
: getWasmExportNames(loadedWasmBytes);
|
|
1521
|
+
checkedArtifact = true;
|
|
1522
|
+
} else if (Array.isArray(exportNames)) {
|
|
1376
1523
|
resolvedExportNames = [...exportNames];
|
|
1377
1524
|
checkedArtifact = true;
|
|
1378
1525
|
} else if (isNonEmptyString(wasmPath)) {
|
|
1379
|
-
|
|
1526
|
+
loadedWasmBytes = new Uint8Array(await readFile(wasmPath));
|
|
1527
|
+
resolvedExportNames = getWasmExportNames(loadedWasmBytes);
|
|
1380
1528
|
checkedArtifact = true;
|
|
1381
1529
|
}
|
|
1382
1530
|
|
|
@@ -1424,6 +1572,14 @@ export async function validatePluginArtifact(options) {
|
|
|
1424
1572
|
wasmPath ?? sourceName,
|
|
1425
1573
|
);
|
|
1426
1574
|
}
|
|
1575
|
+
if (loadedWasmBytes) {
|
|
1576
|
+
validateEmbeddedManifestBytes({
|
|
1577
|
+
wasmBytes: loadedWasmBytes,
|
|
1578
|
+
manifest,
|
|
1579
|
+
issues,
|
|
1580
|
+
sourceLabel: wasmPath ?? sourceName,
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1427
1583
|
} else {
|
|
1428
1584
|
pushIssue(
|
|
1429
1585
|
issues,
|
package/src/embeddedManifest.js
CHANGED
|
@@ -2,8 +2,19 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
import { encodePluginManifest } from "./manifest/index.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { legacyManifestToPlg } from "./manifest/legacyToPlg.js";
|
|
6
|
+
import { encodePlgManifest } from "./manifest/plgCodec.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Convert a manifest input to the raw FlatBuffer bytes that will be
|
|
10
|
+
* embedded in the plugin artifact.
|
|
11
|
+
*
|
|
12
|
+
* The embedded manifest is the canonical spacedatastandards.org PLG
|
|
13
|
+
* schema (`$PLG` file_identifier) by default. Pass `format: "pman"` to
|
|
14
|
+
* emit the internal PluginManifest schema instead (legacy path, retained
|
|
15
|
+
* for tests that still compare against PMAN bytes).
|
|
16
|
+
*/
|
|
17
|
+
function toManifestBytes(manifest, format = "plg") {
|
|
7
18
|
if (manifest instanceof Uint8Array) {
|
|
8
19
|
return manifest;
|
|
9
20
|
}
|
|
@@ -17,7 +28,13 @@ function toManifestBytes(manifest) {
|
|
|
17
28
|
manifest.byteLength,
|
|
18
29
|
);
|
|
19
30
|
}
|
|
20
|
-
|
|
31
|
+
if (format === "pman") {
|
|
32
|
+
return encodePluginManifest(manifest);
|
|
33
|
+
}
|
|
34
|
+
// Default: PLG. Accept both PLG-shaped and legacy PluginManifest-shaped
|
|
35
|
+
// inputs; the converter is a no-op for PLG-native shapes.
|
|
36
|
+
const plgShape = legacyManifestToPlg(manifest);
|
|
37
|
+
return encodePlgManifest(plgShape);
|
|
21
38
|
}
|
|
22
39
|
|
|
23
40
|
function renderByteRows(bytes) {
|
|
@@ -34,7 +51,10 @@ function renderByteRows(bytes) {
|
|
|
34
51
|
}
|
|
35
52
|
|
|
36
53
|
export function generateEmbeddedManifestSource(options = {}) {
|
|
37
|
-
const manifestBytes = toManifestBytes(
|
|
54
|
+
const manifestBytes = toManifestBytes(
|
|
55
|
+
options.manifest,
|
|
56
|
+
options.format ?? "plg",
|
|
57
|
+
);
|
|
38
58
|
if (manifestBytes.length === 0) {
|
|
39
59
|
throw new Error("generateEmbeddedManifestSource requires manifest bytes.");
|
|
40
60
|
}
|
|
@@ -91,7 +111,7 @@ export function writeEmbeddedManifestArtifacts(options = {}) {
|
|
|
91
111
|
throw new Error("writeEmbeddedManifestArtifacts requires outputDir.");
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
const manifestBytes = toManifestBytes(manifest);
|
|
114
|
+
const manifestBytes = toManifestBytes(manifest, options.format ?? "plg");
|
|
95
115
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
96
116
|
|
|
97
117
|
const binaryPath = path.join(outputDir, binaryFileName);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
3
|
-
import * as flatbuffers from "flatbuffers/
|
|
3
|
+
import * as flatbuffers from "../../../vendor/flatbuffers/flatbuffers.js";
|
|
4
4
|
import { TypedArenaBuffer } from '../../orbpro/stream/typed-arena-buffer.js';
|
|
5
5
|
/**
|
|
6
6
|
* Canonical invoke envelope consumed by direct ABI and command-mode execution.
|
|
@@ -128,4 +128,4 @@ export class PluginInvokeRequestT {
|
|
|
128
128
|
return PluginInvokeRequest.createPluginInvokeRequest(builder, methodId, inputFrames, payloadArena);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
//# sourceMappingURL=plugin-invoke-request.js.map
|
|
131
|
+
//# sourceMappingURL=plugin-invoke-request.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
3
|
-
import * as flatbuffers from "flatbuffers/
|
|
3
|
+
import * as flatbuffers from "../../../vendor/flatbuffers/flatbuffers.js";
|
|
4
4
|
import { TypedArenaBuffer } from '../../orbpro/stream/typed-arena-buffer.js';
|
|
5
5
|
/**
|
|
6
6
|
* Canonical invoke result emitted by direct ABI and command-mode execution.
|
|
@@ -181,4 +181,4 @@ export class PluginInvokeResponseT {
|
|
|
181
181
|
return PluginInvokeResponse.createPluginInvokeResponse(builder, this.statusCode, this.yielded, this.backlogRemaining, outputFrames, payloadArena, errorCode, errorMessage);
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
|
-
//# sourceMappingURL=plugin-invoke-response.js.map
|
|
184
|
+
//# sourceMappingURL=plugin-invoke-response.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
3
|
-
import * as flatbuffers from "flatbuffers/
|
|
3
|
+
import * as flatbuffers from "../../../vendor/flatbuffers/flatbuffers.js";
|
|
4
4
|
import { PayloadWireFormat } from "../../orbpro/stream/payload-wire-format.js";
|
|
5
5
|
function normalizePayloadWireFormat(value) {
|
|
6
6
|
if (value === PayloadWireFormat.ALIGNED_BINARY) {
|
|
@@ -202,4 +202,4 @@ export class FlatBufferTypeRefT {
|
|
|
202
202
|
return FlatBufferTypeRef.createFlatBufferTypeRef(builder, schemaName, fileIdentifier, schemaHash, this.acceptsAnyFlatbuffer, normalizePayloadWireFormat(this.wireFormat), rootTypeName, this.fixedStringLength, this.byteLength, this.requiredAlignment);
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
|
-
//# sourceMappingURL=flat-buffer-type-ref.js.map
|
|
205
|
+
//# sourceMappingURL=flat-buffer-type-ref.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
3
|
-
import * as flatbuffers from "flatbuffers/
|
|
3
|
+
import * as flatbuffers from "../../../vendor/flatbuffers/flatbuffers.js";
|
|
4
4
|
import { BufferMutability } from "../../orbpro/stream/buffer-mutability.js";
|
|
5
5
|
import { BufferOwnership } from "../../orbpro/stream/buffer-ownership.js";
|
|
6
6
|
import { FlatBufferTypeRef, } from "../../orbpro/stream/flat-buffer-type-ref.js";
|
|
@@ -230,4 +230,4 @@ export class TypedArenaBufferT {
|
|
|
230
230
|
return TypedArenaBuffer.createTypedArenaBuffer(builder, typeRef, portId, this.alignment, this.offset, this.size, this.ownership, this.generation, this.mutability, this.traceId, this.streamId, this.sequence, this.endOfStream);
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
|
-
//# sourceMappingURL=typed-arena-buffer.js.map
|
|
233
|
+
//# sourceMappingURL=typed-arena-buffer.js.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => {
|
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
return value;
|
|
6
|
+
};
|
|
7
|
+
import * as flatbuffers from "flatbuffers";
|
|
8
|
+
class EntryFunction {
|
|
9
|
+
constructor() {
|
|
10
|
+
__publicField(this, "bb", null);
|
|
11
|
+
__publicField(this, "bb_pos", 0);
|
|
12
|
+
}
|
|
13
|
+
__init(i, bb) {
|
|
14
|
+
this.bb_pos = i;
|
|
15
|
+
this.bb = bb;
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
static getRootAsEntryFunction(bb, obj) {
|
|
19
|
+
return (obj || new EntryFunction()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
20
|
+
}
|
|
21
|
+
static getSizePrefixedRootAsEntryFunction(bb, obj) {
|
|
22
|
+
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
|
23
|
+
return (obj || new EntryFunction()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
24
|
+
}
|
|
25
|
+
name(optionalEncoding) {
|
|
26
|
+
const offset = this.bb.__offset(this.bb_pos, 4);
|
|
27
|
+
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
28
|
+
}
|
|
29
|
+
description(optionalEncoding) {
|
|
30
|
+
const offset = this.bb.__offset(this.bb_pos, 6);
|
|
31
|
+
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
32
|
+
}
|
|
33
|
+
inputSchemas(index, optionalEncoding) {
|
|
34
|
+
const offset = this.bb.__offset(this.bb_pos, 8);
|
|
35
|
+
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
36
|
+
}
|
|
37
|
+
inputSchemasLength() {
|
|
38
|
+
const offset = this.bb.__offset(this.bb_pos, 8);
|
|
39
|
+
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
40
|
+
}
|
|
41
|
+
outputSchema(optionalEncoding) {
|
|
42
|
+
const offset = this.bb.__offset(this.bb_pos, 10);
|
|
43
|
+
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
44
|
+
}
|
|
45
|
+
static startEntryFunction(builder) {
|
|
46
|
+
builder.startObject(4);
|
|
47
|
+
}
|
|
48
|
+
static addName(builder, nameOffset) {
|
|
49
|
+
builder.addFieldOffset(0, nameOffset, 0);
|
|
50
|
+
}
|
|
51
|
+
static addDescription(builder, descriptionOffset) {
|
|
52
|
+
builder.addFieldOffset(1, descriptionOffset, 0);
|
|
53
|
+
}
|
|
54
|
+
static addInputSchemas(builder, inputSchemasOffset) {
|
|
55
|
+
builder.addFieldOffset(2, inputSchemasOffset, 0);
|
|
56
|
+
}
|
|
57
|
+
static createInputSchemasVector(builder, data) {
|
|
58
|
+
builder.startVector(4, data.length, 4);
|
|
59
|
+
for (let i = data.length - 1; i >= 0; i--) {
|
|
60
|
+
builder.addOffset(data[i]);
|
|
61
|
+
}
|
|
62
|
+
return builder.endVector();
|
|
63
|
+
}
|
|
64
|
+
static startInputSchemasVector(builder, numElems) {
|
|
65
|
+
builder.startVector(4, numElems, 4);
|
|
66
|
+
}
|
|
67
|
+
static addOutputSchema(builder, outputSchemaOffset) {
|
|
68
|
+
builder.addFieldOffset(3, outputSchemaOffset, 0);
|
|
69
|
+
}
|
|
70
|
+
static endEntryFunction(builder) {
|
|
71
|
+
const offset = builder.endObject();
|
|
72
|
+
builder.requiredField(offset, 4);
|
|
73
|
+
return offset;
|
|
74
|
+
}
|
|
75
|
+
static createEntryFunction(builder, nameOffset, descriptionOffset, inputSchemasOffset, outputSchemaOffset) {
|
|
76
|
+
EntryFunction.startEntryFunction(builder);
|
|
77
|
+
EntryFunction.addName(builder, nameOffset);
|
|
78
|
+
EntryFunction.addDescription(builder, descriptionOffset);
|
|
79
|
+
EntryFunction.addInputSchemas(builder, inputSchemasOffset);
|
|
80
|
+
EntryFunction.addOutputSchema(builder, outputSchemaOffset);
|
|
81
|
+
return EntryFunction.endEntryFunction(builder);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
EntryFunction
|
|
86
|
+
};
|