space-data-module-sdk 0.5.10 → 0.5.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "space-data-module-sdk",
3
- "version": "0.5.10",
3
+ "version": "0.5.13",
4
4
  "description": "Module SDK for building, validating, signing, and deploying WebAssembly modules on the Space Data Network.",
5
5
  "type": "module",
6
6
  "types": "./src/index.d.ts",
@@ -40,6 +40,9 @@
40
40
  "schemas/",
41
41
  "src/"
42
42
  ],
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
43
46
  "scripts": {
44
47
  "test": "node --test",
45
48
  "test:host-surfaces": "node --test test/node-host.test.js test/host-abi.test.js",
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { readFile } from "node:fs/promises";
2
+ import { readFile, readdir, stat } from "node:fs/promises";
3
3
  import { fileURLToPath } from "node:url";
4
4
 
5
5
  import { FlatcRunner } from "flatc-wasm";
@@ -18,6 +18,48 @@ function loadFlatcRunner() {
18
18
  return flatcRunnerPromise;
19
19
  }
20
20
 
21
+ const FLATBUFFERS_INCLUDE_ROOT_CANDIDATES = [
22
+ process.env.FLATBUFFERS_INCLUDE_DIR,
23
+ "/opt/homebrew/include",
24
+ "/usr/local/include",
25
+ "/usr/include",
26
+ ].filter(Boolean);
27
+
28
+ async function findFlatbuffersIncludeRoot() {
29
+ for (const candidate of FLATBUFFERS_INCLUDE_ROOT_CANDIDATES) {
30
+ const headerPath = path.join(candidate, "flatbuffers", "flatbuffers.h");
31
+ try {
32
+ const headerStat = await stat(headerPath);
33
+ if (headerStat.isFile()) {
34
+ return candidate;
35
+ }
36
+ } catch {
37
+ // Try the next candidate.
38
+ }
39
+ }
40
+ throw new Error(
41
+ "Unable to locate the installed flatbuffers C++ headers. Set FLATBUFFERS_INCLUDE_DIR to the directory containing flatbuffers/flatbuffers.h.",
42
+ );
43
+ }
44
+
45
+ async function readDirectoryTree(rootDir, currentDir = rootDir) {
46
+ const entries = await readdir(currentDir, { withFileTypes: true });
47
+ const files = [];
48
+ for (const entry of entries) {
49
+ const fullPath = path.join(currentDir, entry.name);
50
+ if (entry.isDirectory()) {
51
+ files.push(...(await readDirectoryTree(rootDir, fullPath)));
52
+ continue;
53
+ }
54
+ if (!entry.isFile()) {
55
+ continue;
56
+ }
57
+ const relativePath = path.relative(rootDir, fullPath).split(path.sep).join("/");
58
+ files.push([`/${relativePath}`, await readFile(fullPath, "utf8")]);
59
+ }
60
+ return files;
61
+ }
62
+
21
63
  async function loadInvokeSchemaFiles() {
22
64
  const filenames = [
23
65
  "TypedArenaBuffer.fbs",
@@ -36,8 +78,10 @@ async function loadInvokeSchemaFiles() {
36
78
  export async function getFlatbuffersCppRuntimeHeaders() {
37
79
  if (!flatbuffersCppRuntimeHeadersPromise) {
38
80
  flatbuffersCppRuntimeHeadersPromise = (async () => {
39
- const flatc = await loadFlatcRunner();
40
- return flatc.getEmbeddedRuntime("cpp");
81
+ const includeRoot = await findFlatbuffersIncludeRoot();
82
+ return Object.fromEntries(
83
+ await readDirectoryTree(includeRoot, path.join(includeRoot, "flatbuffers")),
84
+ );
41
85
  })();
42
86
  }
43
87
  return flatbuffersCppRuntimeHeadersPromise;
@@ -366,7 +366,7 @@ function validateAllowedType(type, issues, location) {
366
366
  "Allowed type fixedStringLength",
367
367
  { min: 0 },
368
368
  );
369
- validateIntegerField(
369
+ validateOptionalIntegerField(
370
370
  issues,
371
371
  type.byteLength,
372
372
  `${location}.byteLength`,
@@ -1,31 +1,62 @@
1
1
  function cloneSchemaHash(value) {
2
2
  if (value instanceof Uint8Array) {
3
- return new Uint8Array(value);
3
+ return value.byteLength > 0 ? new Uint8Array(value) : undefined;
4
4
  }
5
5
  if (Array.isArray(value)) {
6
- return [...value];
6
+ return value.length > 0 ? [...value] : undefined;
7
7
  }
8
8
  return value ?? undefined;
9
9
  }
10
10
 
11
+ function normalizeNullableString(value) {
12
+ if (value === undefined || value === null) {
13
+ return null;
14
+ }
15
+ const normalized = String(value).trim();
16
+ return normalized.length > 0 ? normalized : null;
17
+ }
18
+
19
+ function normalizeAlignedMetadataScalar(value) {
20
+ if (value === undefined || value === null || value === "") {
21
+ return undefined;
22
+ }
23
+ const numeric = Number(value);
24
+ if (Number.isFinite(numeric)) {
25
+ return numeric === 0 ? undefined : numeric;
26
+ }
27
+ return value;
28
+ }
29
+
11
30
  export function clonePayloadTypeRef(value = null) {
12
31
  if (!value || typeof value !== "object") {
13
- return { acceptsAnyFlatbuffer: true };
32
+ return { acceptsAnyFlatbuffer: true, fileIdentifier: null };
14
33
  }
15
34
  return {
16
- schemaName: value.schemaName ?? value.schema_name ?? undefined,
17
- fileIdentifier: value.fileIdentifier ?? value.file_identifier ?? undefined,
35
+ schemaName: normalizeNullableString(
36
+ value.schemaName ?? value.schema_name,
37
+ ),
38
+ fileIdentifier: normalizeNullableString(
39
+ value.fileIdentifier ?? value.file_identifier,
40
+ ),
18
41
  schemaHash: cloneSchemaHash(value.schemaHash ?? value.schema_hash),
19
42
  acceptsAnyFlatbuffer: Boolean(
20
43
  value.acceptsAnyFlatbuffer ?? value.accepts_any_flatbuffer ?? false,
21
44
  ),
22
- wireFormat: value.wireFormat ?? value.wire_format ?? undefined,
23
- rootTypeName: value.rootTypeName ?? value.root_type_name ?? undefined,
24
- fixedStringLength:
25
- value.fixedStringLength ?? value.fixed_string_length ?? undefined,
26
- byteLength: value.byteLength ?? value.byte_length ?? undefined,
27
- requiredAlignment:
28
- value.requiredAlignment ?? value.required_alignment ?? undefined,
45
+ wireFormat: normalizePayloadWireFormatName(
46
+ value.wireFormat ?? value.wire_format,
47
+ ),
48
+ rootTypeName: normalizeNullableString(
49
+ value.rootTypeName ?? value.root_type_name,
50
+ ),
51
+ fixedStringLength: normalizeAlignedMetadataScalar(
52
+ value.fixedStringLength ?? value.fixed_string_length,
53
+ ),
54
+ byteLength: normalizeAlignedMetadataScalar(
55
+ value.byteLength ?? value.byte_length,
56
+ ),
57
+ requiredAlignment: normalizeAlignedMetadataScalar(
58
+ value.requiredAlignment ?? value.required_alignment,
59
+ ),
29
60
  };
30
61
  }
31
62
 
@@ -33,6 +64,12 @@ export function normalizePayloadWireFormatName(value) {
33
64
  if (value === undefined || value === null || value === "") {
34
65
  return null;
35
66
  }
67
+ if (value === 1 || value === "1") {
68
+ return "aligned-binary";
69
+ }
70
+ if (value === 0 || value === "0") {
71
+ return "flatbuffer";
72
+ }
36
73
  const normalized = String(value).trim().toLowerCase().replace(/_/g, "-");
37
74
  if (normalized === "aligned-binary") {
38
75
  return "aligned-binary";
@@ -609,7 +609,16 @@ export function decodePublicationRecordCollection(bytes) {
609
609
  8,
610
610
  `REC trailer record ${index} standard`,
611
611
  );
612
- const recordType = recordTable.value_type();
612
+ const recordType =
613
+ typeof recordTable.valueType === "function"
614
+ ? recordTable.valueType()
615
+ : typeof recordTable.value_type === "function"
616
+ ? recordTable.value_type()
617
+ : (() => {
618
+ throw new TypeError(
619
+ "REC Record wrapper is missing both valueType() and value_type() accessors.",
620
+ );
621
+ })();
613
622
  const standard =
614
623
  normalizeStringField(recordTable.standard()) ??
615
624
  STANDARD_BY_RECORD_TYPE[recordType] ??