@arcforges/api-client 1.0.0-ci.89.1 → 1.0.0-ci.92.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/NOTICE CHANGED
@@ -1,10 +1,10 @@
1
1
  ArcForges Contracts
2
2
  Copyright 2026 ArcForges contributors
3
3
 
4
- @arcforges/api-client 1.0.0-ci.89.1 (Apache-2.0)
4
+ @arcforges/api-client 1.0.0-ci.92.1 (Apache-2.0)
5
5
 
6
6
  Resolved runtime dependency inventory (dependencies retain their own licences):
7
- - @arcforges/proto 1.0.0-ci.89.1: Apache-2.0 (pkg:npm/%40arcforges/proto@1.0.0-ci.89.1)
7
+ - @arcforges/proto 1.0.0-ci.92.1: Apache-2.0 (pkg:npm/%40arcforges/proto@1.0.0-ci.92.1)
8
8
  - @bufbuild/protobuf 2.15.0: (Apache-2.0 AND BSD-3-Clause) (pkg:npm/%40bufbuild/protobuf@2.15.0)
9
9
  - @connectrpc/connect 2.2.0: Apache-2.0 (pkg:npm/%40connectrpc/connect@2.2.0)
10
10
  - @connectrpc/connect-web 2.2.0: Apache-2.0 (pkg:npm/%40connectrpc/connect-web@2.2.0)
@@ -15,8 +15,8 @@ ArcForges source provenance notices
15
15
 
16
16
  Generated from reviewed active records. Original licence files and dependency notices remain authoritative.
17
17
 
18
- contract-bindings-r4
19
- Source: https://github.com/ArcForges/Contracts @ af7b6cca5e14a51735512d283b03d3ae9d96d170
18
+ contract-bindings-r5
19
+ Source: https://github.com/ArcForges/Contracts @ b6795dc55852e16bcd555751a58bd494958e3917
20
20
  Material licence: Apache-2.0
21
21
  Notice scope: packages
22
22
  Copyright 2026 ArcForges contributors.
package/README.md CHANGED
@@ -12,6 +12,13 @@ const reply = await client.sayHello({ name: "World" }, { timeoutMs: 5000 });
12
12
  console.log(reply.message);
13
13
  ```
14
14
 
15
+ `createPublicGrpcWebTransport` is the public business transport: binary gRPC-Web
16
+ only, unknown fields retained and the shared 100-level nesting bound. It refuses
17
+ `useBinaryFormat`, `jsonOptions` and `binaryOptions` overrides. The declared HTTP
18
+ exception records have strict codecs such as `tryParsePartReceiptJson` and
19
+ `serializePartReceiptJson`; they enforce the schema byte limit, UTF-8, JSON depth 32,
20
+ duplicate-property and integer-lexeme rules before the closed schema check.
21
+
15
22
  The endpoint must serve gRPC-Web. Browser cross-origin access also requires
16
23
  server CORS configuration. The demo host binds to loopback for tests.
17
24
 
@@ -3,17 +3,17 @@
3
3
  "owner": "Contracts",
4
4
  "artifact": {
5
5
  "id": "@arcforges/api-client",
6
- "version": "1.0.0-ci.89.1"
6
+ "version": "1.0.0-ci.92.1"
7
7
  },
8
8
  "build": {
9
- "sourceCommit": "4b8134eaf8a4174922d6378da003ed390b85a94a",
9
+ "sourceCommit": "e6c4a77f3ba48d70de4bf524623985b29278c784",
10
10
  "dirty": false,
11
11
  "kind": "ci",
12
- "buildId": "35730204418.1",
13
- "runId": "35730204418",
12
+ "buildId": "35797272606.1",
13
+ "runId": "35797272606",
14
14
  "runAttempt": 1,
15
- "pipelineRun": "https://github.com/ArcForges/Contracts/actions/runs/35730204418",
16
- "sourceDateEpoch": 1790081756
15
+ "pipelineRun": "https://github.com/ArcForges/Contracts/actions/runs/35797272606",
16
+ "sourceDateEpoch": 1790119475
17
17
  },
18
18
  "axes": {
19
19
  "AppVersion": {
@@ -64,7 +64,7 @@
64
64
  "version": "1",
65
65
  "source": {
66
66
  "path": "public/http/v1/inventory.schema.json",
67
- "sha256": "fb6929548278f6e16e61491001fecae4143882efbfe732950a1584e1e2f80a5d"
67
+ "sha256": "2d17acc663de43ff847e522ddb16f32b1e7ec356df7db7dcafe8342d3fb014ce"
68
68
  }
69
69
  },
70
70
  {
@@ -72,7 +72,7 @@
72
72
  "version": "1",
73
73
  "source": {
74
74
  "path": "public/http/v1/schema.json",
75
- "sha256": "23587b33320fcbe4a917c2839552984eb40e716c4ce317a5c218f35bedf06751"
75
+ "sha256": "8d4c1282c0f93452a0304e44c832179d4c6f65fa563ae53517aa324af87105ce"
76
76
  }
77
77
  }
78
78
  ]
@@ -110,10 +110,10 @@
110
110
  "values": [
111
111
  {
112
112
  "subject": "pkg:npm/%40arcforges/proto",
113
- "version": "1.0.0-ci.89.1",
113
+ "version": "1.0.0-ci.92.1",
114
114
  "source": {
115
115
  "path": "sbom.cdx.json#components",
116
- "sha256": "f8baed3a3ad5bfb9c3b996f0a47d5dbfc75f954982156af49e3bdb0f473c6a7c"
116
+ "sha256": "eed9ce9eb5fd29191d6c222746b88c1eb893704ba3a009478d57b93e03701f4d"
117
117
  }
118
118
  },
119
119
  {
@@ -121,7 +121,7 @@
121
121
  "version": "2.15.0",
122
122
  "source": {
123
123
  "path": "sbom.cdx.json#components",
124
- "sha256": "f8baed3a3ad5bfb9c3b996f0a47d5dbfc75f954982156af49e3bdb0f473c6a7c"
124
+ "sha256": "eed9ce9eb5fd29191d6c222746b88c1eb893704ba3a009478d57b93e03701f4d"
125
125
  }
126
126
  },
127
127
  {
@@ -129,7 +129,7 @@
129
129
  "version": "2.2.0",
130
130
  "source": {
131
131
  "path": "sbom.cdx.json#components",
132
- "sha256": "f8baed3a3ad5bfb9c3b996f0a47d5dbfc75f954982156af49e3bdb0f473c6a7c"
132
+ "sha256": "eed9ce9eb5fd29191d6c222746b88c1eb893704ba3a009478d57b93e03701f4d"
133
133
  }
134
134
  },
135
135
  {
@@ -137,7 +137,7 @@
137
137
  "version": "2.2.0",
138
138
  "source": {
139
139
  "path": "sbom.cdx.json#components",
140
- "sha256": "f8baed3a3ad5bfb9c3b996f0a47d5dbfc75f954982156af49e3bdb0f473c6a7c"
140
+ "sha256": "eed9ce9eb5fd29191d6c222746b88c1eb893704ba3a009478d57b93e03701f4d"
141
141
  }
142
142
  }
143
143
  ]
package/dist/index.d.ts CHANGED
@@ -1,6 +1,14 @@
1
+ import type { Transport } from "@connectrpc/connect";
1
2
  import type { GrpcWebTransportOptions } from "@connectrpc/connect-web";
3
+ /** Caller-owned endpoint, fetch, interceptors and timeout; the wire format is fixed. */
4
+ export type PublicGrpcWebTransportOptions = Omit<GrpcWebTransportOptions, "useBinaryFormat" | "jsonOptions" | "binaryOptions">;
5
+ /**
6
+ * Creates the public business transport: binary gRPC-Web only, unknown fields
7
+ * retained and the shared nesting bound. JSON selection is refused.
8
+ */
9
+ export declare function createPublicGrpcWebTransport(options: PublicGrpcWebTransportOptions): Transport;
2
10
  /** Creates the example client using the caller's gRPC-Web endpoint and fetch. */
3
- export declare function createHelloClient(options: GrpcWebTransportOptions): import("@connectrpc/connect").Client<import("@bufbuild/protobuf/codegenv2").GenService<{
11
+ export declare function createHelloClient(options: PublicGrpcWebTransportOptions): import("@connectrpc/connect").Client<import("@bufbuild/protobuf/codegenv2").GenService<{
4
12
  sayHello: {
5
13
  methodKind: "unary";
6
14
  input: typeof import("@arcforges/proto").SayHelloRequestSchema;
package/dist/index.js CHANGED
@@ -1,9 +1,26 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- import { HelloService } from "@arcforges/proto";
2
+ import { contractBinaryReadOptions, HelloService } from "@arcforges/proto";
3
3
  import { createClient } from "@connectrpc/connect";
4
4
  import { createGrpcWebTransport } from "@connectrpc/connect-web";
5
+ /**
6
+ * Creates the public business transport: binary gRPC-Web only, unknown fields
7
+ * retained and the shared nesting bound. JSON selection is refused.
8
+ */
9
+ export function createPublicGrpcWebTransport(options) {
10
+ const selected = options;
11
+ if (selected.useBinaryFormat !== undefined ||
12
+ selected.jsonOptions !== undefined ||
13
+ selected.binaryOptions !== undefined) {
14
+ throw new TypeError("Public ArcForges business calls use binary gRPC-Web with fixed codec options.");
15
+ }
16
+ return createGrpcWebTransport({
17
+ ...options,
18
+ useBinaryFormat: true,
19
+ binaryOptions: { ...contractBinaryReadOptions, writeUnknownFields: true },
20
+ });
21
+ }
5
22
  /** Creates the example client using the caller's gRPC-Web endpoint and fetch. */
6
23
  export function createHelloClient(options) {
7
- return createClient(HelloService, createGrpcWebTransport(options));
24
+ return createClient(HelloService, createPublicGrpcWebTransport(options));
8
25
  }
9
26
  export * from "./gen/http.js";
@@ -8,3 +8,17 @@ export interface InventoryFile {
8
8
  sha256: string;
9
9
  }
10
10
  export declare function isPackageInventory(value: unknown): value is PackageInventory;
11
+ /** The schema's declared UTF-8 document bound in bytes. */
12
+ export declare const packageInventoryJsonMaxBytes = 4194304;
13
+ /** Parses one strict PackageInventory document; refusal kinds match the C# codec. */
14
+ export declare function tryParsePackageInventoryJson(input: Uint8Array | string): {
15
+ ok: true;
16
+ value: PackageInventory;
17
+ } | {
18
+ ok: false;
19
+ failure: "tooLarge" | "malformed" | "invalid";
20
+ };
21
+ /** Parses one strict PackageInventory document or throws an error carrying the refusal kind. */
22
+ export declare function parsePackageInventoryJson(input: Uint8Array | string): PackageInventory;
23
+ /** Writes compact UTF-8 in schema property order and refuses output the schema rejects. */
24
+ export declare function serializePackageInventoryJson(value: PackageInventory): Uint8Array;
@@ -1,4 +1,41 @@
1
1
  export function isPackageInventory(value) { return check0(value); }
2
+ /** The schema's declared UTF-8 document bound in bytes. */
3
+ export const packageInventoryJsonMaxBytes = 4194304;
4
+ /** Parses one strict PackageInventory document; refusal kinds match the C# codec. */
5
+ export function tryParsePackageInventoryJson(input) {
6
+ const parsed = strictJson(input, 4194304);
7
+ if (!parsed.ok)
8
+ return parsed;
9
+ return isPackageInventory(parsed.value) ? { ok: true, value: parsed.value } : { ok: false, failure: "invalid" };
10
+ }
11
+ /** Parses one strict PackageInventory document or throws an error carrying the refusal kind. */
12
+ export function parsePackageInventoryJson(input) {
13
+ const result = tryParsePackageInventoryJson(input);
14
+ if (!result.ok)
15
+ throw Object.assign(new Error(`PackageInventory JSON refused: ${result.failure}.`), { failure: result.failure });
16
+ return result.value;
17
+ }
18
+ /** Writes compact UTF-8 in schema property order and refuses output the schema rejects. */
19
+ export function serializePackageInventoryJson(value) {
20
+ const bytes = new TextEncoder().encode(JSON.stringify(orderPackageInventory(value)));
21
+ const result = tryParsePackageInventoryJson(bytes);
22
+ if (!result.ok)
23
+ throw Object.assign(new Error(`PackageInventory JSON refused: ${result.failure}.`), { failure: result.failure });
24
+ return bytes;
25
+ }
26
+ function orderInventoryFile(value) {
27
+ const out = {};
28
+ out["path"] = value["path"];
29
+ out["size"] = value["size"];
30
+ out["sha256"] = value["sha256"];
31
+ return out;
32
+ }
33
+ function orderPackageInventory(value) {
34
+ const out = {};
35
+ out["schemaVersion"] = value["schemaVersion"];
36
+ out["files"] = value["files"].map(item => orderInventoryFile(item));
37
+ return out;
38
+ }
2
39
  function check0(value) {
3
40
  if (typeof value !== 'object' || value === null || Array.isArray(value))
4
41
  return false;
@@ -98,6 +135,163 @@ function check6(value) {
98
135
  return false;
99
136
  return true;
100
137
  }
138
+ /** Strict UTF-8 JSON: no BOM, comments, trailing commas or duplicate properties; depth <= 32; integer lexemes only. */
139
+ function strictJson(input, maxBytes) {
140
+ let text;
141
+ if (typeof input === "string") {
142
+ if (!validText(input))
143
+ return { ok: false, failure: "malformed" };
144
+ if (new TextEncoder().encode(input).byteLength > maxBytes)
145
+ return { ok: false, failure: "tooLarge" };
146
+ text = input;
147
+ }
148
+ else {
149
+ if (input.byteLength > maxBytes)
150
+ return { ok: false, failure: "tooLarge" };
151
+ try {
152
+ text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input);
153
+ }
154
+ catch {
155
+ return { ok: false, failure: "malformed" };
156
+ }
157
+ }
158
+ try {
159
+ return { ok: true, value: new StrictJsonReader(text).document() };
160
+ }
161
+ catch {
162
+ return { ok: false, failure: "malformed" };
163
+ }
164
+ }
165
+ class StrictJsonReader {
166
+ text;
167
+ index = 0;
168
+ constructor(text) {
169
+ this.text = text;
170
+ }
171
+ document() {
172
+ this.space();
173
+ const value = this.value(0);
174
+ this.space();
175
+ if (this.index !== this.text.length)
176
+ throw new SyntaxError("Trailing JSON content");
177
+ return value;
178
+ }
179
+ value(depth) {
180
+ switch (this.text[this.index]) {
181
+ case "{": return this.object(depth + 1);
182
+ case "[": return this.array(depth + 1);
183
+ case '"': return this.string();
184
+ case "t": return this.literal("true", true);
185
+ case "f": return this.literal("false", false);
186
+ case "n": return this.literal("null", null);
187
+ default: return this.number();
188
+ }
189
+ }
190
+ object(depth) {
191
+ if (depth > 32)
192
+ throw new SyntaxError("JSON depth exceeded");
193
+ this.index++;
194
+ const out = {};
195
+ const keys = new Set();
196
+ this.space();
197
+ if (this.text[this.index] === "}") {
198
+ this.index++;
199
+ return out;
200
+ }
201
+ for (;;) {
202
+ this.space();
203
+ if (this.text[this.index] !== '"')
204
+ throw new SyntaxError("Expected property name");
205
+ const key = this.string();
206
+ if (keys.has(key))
207
+ throw new SyntaxError("Duplicate JSON property");
208
+ keys.add(key);
209
+ this.space();
210
+ if (this.text[this.index++] !== ":")
211
+ throw new SyntaxError("Expected colon");
212
+ this.space();
213
+ // defineProperty keeps names such as __proto__ as ordinary own properties.
214
+ Object.defineProperty(out, key, { value: this.value(depth), enumerable: true, writable: true, configurable: true });
215
+ this.space();
216
+ const next = this.text[this.index++];
217
+ if (next === "}")
218
+ return out;
219
+ if (next !== ",")
220
+ throw new SyntaxError("Expected comma");
221
+ }
222
+ }
223
+ array(depth) {
224
+ if (depth > 32)
225
+ throw new SyntaxError("JSON depth exceeded");
226
+ this.index++;
227
+ const out = [];
228
+ this.space();
229
+ if (this.text[this.index] === "]") {
230
+ this.index++;
231
+ return out;
232
+ }
233
+ for (;;) {
234
+ this.space();
235
+ out.push(this.value(depth));
236
+ this.space();
237
+ const next = this.text[this.index++];
238
+ if (next === "]")
239
+ return out;
240
+ if (next !== ",")
241
+ throw new SyntaxError("Expected comma");
242
+ }
243
+ }
244
+ string() {
245
+ this.index++;
246
+ let out = "";
247
+ for (;;) {
248
+ const c = this.text[this.index++];
249
+ if (c === undefined)
250
+ throw new SyntaxError("Unterminated string");
251
+ if (c === '"')
252
+ break;
253
+ if (c < " ")
254
+ throw new SyntaxError("Unescaped control character");
255
+ if (c !== "\\") {
256
+ out += c;
257
+ continue;
258
+ }
259
+ const e = this.text[this.index++];
260
+ const simple = { '"': '"', "\\": "\\", "/": "/", b: "\b", f: "\f", n: "\n", r: "\r", t: "\t" };
261
+ if (e !== undefined && e in simple) {
262
+ out += simple[e];
263
+ continue;
264
+ }
265
+ if (e !== "u" || !/^[0-9a-fA-F]{4}$/.test(this.text.slice(this.index, this.index + 4)))
266
+ throw new SyntaxError("Invalid escape");
267
+ out += String.fromCharCode(parseInt(this.text.slice(this.index, this.index + 4), 16));
268
+ this.index += 4;
269
+ }
270
+ if (!validText(out))
271
+ throw new SyntaxError("Lone surrogate escape");
272
+ return out;
273
+ }
274
+ number() {
275
+ const match = /-?(?:0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?/y;
276
+ match.lastIndex = this.index;
277
+ const found = match.exec(this.text);
278
+ if (found === null)
279
+ throw new SyntaxError("Invalid JSON value");
280
+ this.index = match.lastIndex;
281
+ // Selected schemas have no fractional numbers; fraction/exponent lexemes never satisfy an integer.
282
+ return found[1] !== undefined || found[2] !== undefined ? Number.NaN : Number(found[0]);
283
+ }
284
+ literal(word, value) {
285
+ if (this.text.slice(this.index, this.index + word.length) !== word)
286
+ throw new SyntaxError("Invalid JSON literal");
287
+ this.index += word.length;
288
+ return value;
289
+ }
290
+ space() {
291
+ while (this.text[this.index] === " " || this.text[this.index] === "\t" || this.text[this.index] === "\n" || this.text[this.index] === "\r")
292
+ this.index++;
293
+ }
294
+ }
101
295
  function validText(value) {
102
296
  for (const scalar of value) {
103
297
  const point = scalar.codePointAt(0);
@@ -5,3 +5,17 @@ export interface PartReceipt {
5
5
  etag: string;
6
6
  }
7
7
  export declare function isPartReceipt(value: unknown): value is PartReceipt;
8
+ /** The schema's declared UTF-8 document bound in bytes. */
9
+ export declare const partReceiptJsonMaxBytes = 65536;
10
+ /** Parses one strict PartReceipt document; refusal kinds match the C# codec. */
11
+ export declare function tryParsePartReceiptJson(input: Uint8Array | string): {
12
+ ok: true;
13
+ value: PartReceipt;
14
+ } | {
15
+ ok: false;
16
+ failure: "tooLarge" | "malformed" | "invalid";
17
+ };
18
+ /** Parses one strict PartReceipt document or throws an error carrying the refusal kind. */
19
+ export declare function parsePartReceiptJson(input: Uint8Array | string): PartReceipt;
20
+ /** Writes compact UTF-8 in schema property order and refuses output the schema rejects. */
21
+ export declare function serializePartReceiptJson(value: PartReceipt): Uint8Array;
@@ -1,4 +1,36 @@
1
1
  export function isPartReceipt(value) { return check0(value); }
2
+ /** The schema's declared UTF-8 document bound in bytes. */
3
+ export const partReceiptJsonMaxBytes = 65536;
4
+ /** Parses one strict PartReceipt document; refusal kinds match the C# codec. */
5
+ export function tryParsePartReceiptJson(input) {
6
+ const parsed = strictJson(input, 65536);
7
+ if (!parsed.ok)
8
+ return parsed;
9
+ return isPartReceipt(parsed.value) ? { ok: true, value: parsed.value } : { ok: false, failure: "invalid" };
10
+ }
11
+ /** Parses one strict PartReceipt document or throws an error carrying the refusal kind. */
12
+ export function parsePartReceiptJson(input) {
13
+ const result = tryParsePartReceiptJson(input);
14
+ if (!result.ok)
15
+ throw Object.assign(new Error(`PartReceipt JSON refused: ${result.failure}.`), { failure: result.failure });
16
+ return result.value;
17
+ }
18
+ /** Writes compact UTF-8 in schema property order and refuses output the schema rejects. */
19
+ export function serializePartReceiptJson(value) {
20
+ const bytes = new TextEncoder().encode(JSON.stringify(orderPartReceipt(value)));
21
+ const result = tryParsePartReceiptJson(bytes);
22
+ if (!result.ok)
23
+ throw Object.assign(new Error(`PartReceipt JSON refused: ${result.failure}.`), { failure: result.failure });
24
+ return bytes;
25
+ }
26
+ function orderPartReceipt(value) {
27
+ const out = {};
28
+ out["partNumber"] = value["partNumber"];
29
+ out["size"] = value["size"];
30
+ out["sha256"] = value["sha256"];
31
+ out["etag"] = value["etag"];
32
+ return out;
33
+ }
2
34
  function check0(value) {
3
35
  if (typeof value !== 'object' || value === null || Array.isArray(value))
4
36
  return false;
@@ -66,6 +98,163 @@ function check4(value) {
66
98
  return false;
67
99
  return true;
68
100
  }
101
+ /** Strict UTF-8 JSON: no BOM, comments, trailing commas or duplicate properties; depth <= 32; integer lexemes only. */
102
+ function strictJson(input, maxBytes) {
103
+ let text;
104
+ if (typeof input === "string") {
105
+ if (!validText(input))
106
+ return { ok: false, failure: "malformed" };
107
+ if (new TextEncoder().encode(input).byteLength > maxBytes)
108
+ return { ok: false, failure: "tooLarge" };
109
+ text = input;
110
+ }
111
+ else {
112
+ if (input.byteLength > maxBytes)
113
+ return { ok: false, failure: "tooLarge" };
114
+ try {
115
+ text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input);
116
+ }
117
+ catch {
118
+ return { ok: false, failure: "malformed" };
119
+ }
120
+ }
121
+ try {
122
+ return { ok: true, value: new StrictJsonReader(text).document() };
123
+ }
124
+ catch {
125
+ return { ok: false, failure: "malformed" };
126
+ }
127
+ }
128
+ class StrictJsonReader {
129
+ text;
130
+ index = 0;
131
+ constructor(text) {
132
+ this.text = text;
133
+ }
134
+ document() {
135
+ this.space();
136
+ const value = this.value(0);
137
+ this.space();
138
+ if (this.index !== this.text.length)
139
+ throw new SyntaxError("Trailing JSON content");
140
+ return value;
141
+ }
142
+ value(depth) {
143
+ switch (this.text[this.index]) {
144
+ case "{": return this.object(depth + 1);
145
+ case "[": return this.array(depth + 1);
146
+ case '"': return this.string();
147
+ case "t": return this.literal("true", true);
148
+ case "f": return this.literal("false", false);
149
+ case "n": return this.literal("null", null);
150
+ default: return this.number();
151
+ }
152
+ }
153
+ object(depth) {
154
+ if (depth > 32)
155
+ throw new SyntaxError("JSON depth exceeded");
156
+ this.index++;
157
+ const out = {};
158
+ const keys = new Set();
159
+ this.space();
160
+ if (this.text[this.index] === "}") {
161
+ this.index++;
162
+ return out;
163
+ }
164
+ for (;;) {
165
+ this.space();
166
+ if (this.text[this.index] !== '"')
167
+ throw new SyntaxError("Expected property name");
168
+ const key = this.string();
169
+ if (keys.has(key))
170
+ throw new SyntaxError("Duplicate JSON property");
171
+ keys.add(key);
172
+ this.space();
173
+ if (this.text[this.index++] !== ":")
174
+ throw new SyntaxError("Expected colon");
175
+ this.space();
176
+ // defineProperty keeps names such as __proto__ as ordinary own properties.
177
+ Object.defineProperty(out, key, { value: this.value(depth), enumerable: true, writable: true, configurable: true });
178
+ this.space();
179
+ const next = this.text[this.index++];
180
+ if (next === "}")
181
+ return out;
182
+ if (next !== ",")
183
+ throw new SyntaxError("Expected comma");
184
+ }
185
+ }
186
+ array(depth) {
187
+ if (depth > 32)
188
+ throw new SyntaxError("JSON depth exceeded");
189
+ this.index++;
190
+ const out = [];
191
+ this.space();
192
+ if (this.text[this.index] === "]") {
193
+ this.index++;
194
+ return out;
195
+ }
196
+ for (;;) {
197
+ this.space();
198
+ out.push(this.value(depth));
199
+ this.space();
200
+ const next = this.text[this.index++];
201
+ if (next === "]")
202
+ return out;
203
+ if (next !== ",")
204
+ throw new SyntaxError("Expected comma");
205
+ }
206
+ }
207
+ string() {
208
+ this.index++;
209
+ let out = "";
210
+ for (;;) {
211
+ const c = this.text[this.index++];
212
+ if (c === undefined)
213
+ throw new SyntaxError("Unterminated string");
214
+ if (c === '"')
215
+ break;
216
+ if (c < " ")
217
+ throw new SyntaxError("Unescaped control character");
218
+ if (c !== "\\") {
219
+ out += c;
220
+ continue;
221
+ }
222
+ const e = this.text[this.index++];
223
+ const simple = { '"': '"', "\\": "\\", "/": "/", b: "\b", f: "\f", n: "\n", r: "\r", t: "\t" };
224
+ if (e !== undefined && e in simple) {
225
+ out += simple[e];
226
+ continue;
227
+ }
228
+ if (e !== "u" || !/^[0-9a-fA-F]{4}$/.test(this.text.slice(this.index, this.index + 4)))
229
+ throw new SyntaxError("Invalid escape");
230
+ out += String.fromCharCode(parseInt(this.text.slice(this.index, this.index + 4), 16));
231
+ this.index += 4;
232
+ }
233
+ if (!validText(out))
234
+ throw new SyntaxError("Lone surrogate escape");
235
+ return out;
236
+ }
237
+ number() {
238
+ const match = /-?(?:0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?/y;
239
+ match.lastIndex = this.index;
240
+ const found = match.exec(this.text);
241
+ if (found === null)
242
+ throw new SyntaxError("Invalid JSON value");
243
+ this.index = match.lastIndex;
244
+ // Selected schemas have no fractional numbers; fraction/exponent lexemes never satisfy an integer.
245
+ return found[1] !== undefined || found[2] !== undefined ? Number.NaN : Number(found[0]);
246
+ }
247
+ literal(word, value) {
248
+ if (this.text.slice(this.index, this.index + word.length) !== word)
249
+ throw new SyntaxError("Invalid JSON literal");
250
+ this.index += word.length;
251
+ return value;
252
+ }
253
+ space() {
254
+ while (this.text[this.index] === " " || this.text[this.index] === "\t" || this.text[this.index] === "\n" || this.text[this.index] === "\r")
255
+ this.index++;
256
+ }
257
+ }
69
258
  function validText(value) {
70
259
  for (const scalar of value) {
71
260
  const point = scalar.codePointAt(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcforges/api-client",
3
- "version": "1.0.0-ci.89.1",
3
+ "version": "1.0.0-ci.92.1",
4
4
  "description": "ArcForges public gRPC-Web client entry point; initial Hello World example.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -33,7 +33,7 @@
33
33
  "source.json"
34
34
  ],
35
35
  "dependencies": {
36
- "@arcforges/proto": "1.0.0-ci.89.1",
36
+ "@arcforges/proto": "1.0.0-ci.92.1",
37
37
  "@bufbuild/protobuf": "2.15.0",
38
38
  "@connectrpc/connect": "2.2.0",
39
39
  "@connectrpc/connect-web": "2.2.0"
package/sbom.cdx.json CHANGED
@@ -5,10 +5,10 @@
5
5
  "metadata": {
6
6
  "component": {
7
7
  "type": "library",
8
- "bom-ref": "pkg:npm/%40arcforges/api-client@1.0.0-ci.89.1",
8
+ "bom-ref": "pkg:npm/%40arcforges/api-client@1.0.0-ci.92.1",
9
9
  "name": "@arcforges/api-client",
10
- "version": "1.0.0-ci.89.1",
11
- "purl": "pkg:npm/%40arcforges/api-client@1.0.0-ci.89.1",
10
+ "version": "1.0.0-ci.92.1",
11
+ "purl": "pkg:npm/%40arcforges/api-client@1.0.0-ci.92.1",
12
12
  "licenses": [
13
13
  {
14
14
  "expression": "Apache-2.0"
@@ -19,10 +19,10 @@
19
19
  "components": [
20
20
  {
21
21
  "type": "library",
22
- "bom-ref": "pkg:npm/%40arcforges/proto@1.0.0-ci.89.1",
22
+ "bom-ref": "pkg:npm/%40arcforges/proto@1.0.0-ci.92.1",
23
23
  "name": "@arcforges/proto",
24
- "version": "1.0.0-ci.89.1",
25
- "purl": "pkg:npm/%40arcforges/proto@1.0.0-ci.89.1",
24
+ "version": "1.0.0-ci.92.1",
25
+ "purl": "pkg:npm/%40arcforges/proto@1.0.0-ci.92.1",
26
26
  "licenses": [
27
27
  {
28
28
  "expression": "Apache-2.0"
@@ -72,7 +72,7 @@
72
72
  "dependsOn": []
73
73
  },
74
74
  {
75
- "ref": "pkg:npm/%40arcforges/proto@1.0.0-ci.89.1",
75
+ "ref": "pkg:npm/%40arcforges/proto@1.0.0-ci.92.1",
76
76
  "dependsOn": [
77
77
  "pkg:npm/%40bufbuild/protobuf@2.15.0"
78
78
  ]
@@ -91,9 +91,9 @@
91
91
  ]
92
92
  },
93
93
  {
94
- "ref": "pkg:npm/%40arcforges/api-client@1.0.0-ci.89.1",
94
+ "ref": "pkg:npm/%40arcforges/api-client@1.0.0-ci.92.1",
95
95
  "dependsOn": [
96
- "pkg:npm/%40arcforges/proto@1.0.0-ci.89.1",
96
+ "pkg:npm/%40arcforges/proto@1.0.0-ci.92.1",
97
97
  "pkg:npm/%40bufbuild/protobuf@2.15.0",
98
98
  "pkg:npm/%40connectrpc/connect@2.2.0",
99
99
  "pkg:npm/%40connectrpc/connect-web@2.2.0"
@@ -44,5 +44,6 @@
44
44
  }
45
45
  },
46
46
  "x-arcforges-rules": ["inventoryPaths", "inventoryBounds"],
47
+ "x-arcforges-max-bytes": 4194304,
47
48
  "x-arcforges-schema-version": "1"
48
49
  }
@@ -25,5 +25,6 @@
25
25
  },
26
26
  "required": ["partNumber", "size", "sha256", "etag"],
27
27
  "additionalProperties": false,
28
+ "x-arcforges-max-bytes": 65536,
28
29
  "x-arcforges-schema-version": "1"
29
30
  }
package/source.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "repository": "https://github.com/ArcForges/Contracts",
3
- "commit": "4b8134eaf8a4174922d6378da003ed390b85a94a",
3
+ "commit": "e6c4a77f3ba48d70de4bf524623985b29278c784",
4
4
  "dirty": false,
5
- "version": "1.0.0-ci.89.1",
5
+ "version": "1.0.0-ci.92.1",
6
6
  "contractAccess": "public",
7
7
  "schemaSources": {
8
- "public/http/v1/inventory.schema.json": "fb6929548278f6e16e61491001fecae4143882efbfe732950a1584e1e2f80a5d",
9
- "public/http/v1/schema.json": "23587b33320fcbe4a917c2839552984eb40e716c4ce317a5c218f35bedf06751",
8
+ "public/http/v1/inventory.schema.json": "2d17acc663de43ff847e522ddb16f32b1e7ec356df7db7dcafe8342d3fb014ce",
9
+ "public/http/v1/schema.json": "8d4c1282c0f93452a0304e44c832179d4c6f65fa563ae53517aa324af87105ce",
10
10
  "public/proto/arcforges/events/v1/events.proto": "ea0ac740c06bbb5b81724b4a7e601110424cabc4940b07e579cf97d852880f43",
11
11
  "public/proto/arcforges/foundation/v1/foundation.proto": "ceda869bf2998ca4bc21c4b7504c365a4662e7f28183e6db81660592d5bcdb3f",
12
12
  "public/proto/arcforges/hello/v1/hello.proto": "92489f89d1898a3d3bbea56c72116416cd0152ae8866c98745739437020c67d9",