@seed-hypermedia/client 0.0.48 → 0.0.50

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/dist/change.d.ts CHANGED
@@ -59,6 +59,7 @@ export declare function createChange(unsignedBytes: Uint8Array, signer: HMSigner
59
59
  bytes: Uint8Array;
60
60
  cid: CID;
61
61
  genesis: CID | null;
62
+ ts: number | undefined;
62
63
  }>;
63
64
  /** @deprecated Use createChange instead */
64
65
  export declare const signPreparedChange: (unsignedBytes: Uint8Array, signer: HMSigner) => Promise<{
package/dist/index.mjs CHANGED
@@ -116,14 +116,15 @@ function buildUnsignedRef({
116
116
  genesis,
117
117
  generation,
118
118
  capability,
119
- visibility
119
+ visibility,
120
+ ts
120
121
  }) {
121
122
  const signerBytes = new Uint8Array(signerKey);
122
123
  const spaceBytes = new Uint8Array(base58btc2.decode(space));
123
124
  const unsigned = {
124
125
  type: "Ref",
125
126
  signer: signerBytes,
126
- ts: BigInt(Date.now()),
127
+ ts: BigInt(ts ?? Date.now()),
127
128
  sig: new Uint8Array(64),
128
129
  genesisBlob: CID.parse(genesis)
129
130
  };
@@ -153,7 +154,8 @@ async function createVersionRef(input, signer) {
153
154
  genesis: input.genesis,
154
155
  generation: input.generation,
155
156
  capability: input.capability,
156
- visibility: input.visibility
157
+ visibility: input.visibility,
158
+ ts: input.ts
157
159
  });
158
160
  unsigned.heads = input.version.split(".").map((v) => CID.parse(v));
159
161
  unsigned.sig = await signObject(signer, unsigned);
@@ -221,11 +223,12 @@ function createChangeOps(input) {
221
223
  async function createChange(unsignedBytes, signer) {
222
224
  const change = cborDecode(unsignedBytes);
223
225
  const genesis = change.genesis instanceof CID2 ? change.genesis : null;
226
+ const ts = timestampToNumber(change.ts);
224
227
  change.signer = new Uint8Array(await signer.getPublicKey());
225
228
  change.sig = new Uint8Array(64);
226
229
  change.sig = await signer.sign(cborEncode4(change));
227
230
  const block = await Block.encode({ value: change, codec: cborCodec, hasher: sha256 });
228
- return { bytes: block.bytes, cid: block.cid, genesis };
231
+ return { bytes: block.bytes, cid: block.cid, genesis, ts };
229
232
  }
230
233
  var signPreparedChange = async (unsignedBytes, signer) => {
231
234
  const result = await createChange(unsignedBytes, signer);
@@ -275,10 +278,20 @@ var RESOURCE_VISIBILITY_PRIVATE = 2;
275
278
  function visibilityToCbor(protoVisibility) {
276
279
  return protoVisibility === RESOURCE_VISIBILITY_PRIVATE ? "Private" : void 0;
277
280
  }
281
+ function timestampToNumber(ts) {
282
+ if (typeof ts === "number") return ts;
283
+ if (typeof ts === "bigint") return Number(ts);
284
+ return void 0;
285
+ }
278
286
  async function signDocumentChange(input, signer) {
279
- const { bytes: signedBytes, cid: changeCid, genesis: changeGenesis } = await createChange(input.unsignedChange, signer);
287
+ const {
288
+ bytes: signedBytes,
289
+ cid: changeCid,
290
+ genesis: changeGenesis,
291
+ ts: changeTs
292
+ } = await createChange(input.unsignedChange, signer);
280
293
  const effectiveGenesis = input.genesis || (changeGenesis ? changeGenesis.toString() : changeCid.toString());
281
- const effectiveGeneration = input.generation != null ? Number(input.generation) : Date.now();
294
+ const effectiveGeneration = input.generation != null ? Number(input.generation) : changeTs ?? Date.now();
282
295
  const refBlobs = await createVersionRef(
283
296
  {
284
297
  space: input.account,
@@ -287,7 +300,8 @@ async function signDocumentChange(input, signer) {
287
300
  version: changeCid.toString(),
288
301
  generation: effectiveGeneration,
289
302
  capability: input.capability,
290
- visibility: visibilityToCbor(input.visibility)
303
+ visibility: visibilityToCbor(input.visibility),
304
+ ts: changeTs
291
305
  },
292
306
  signer
293
307
  );
@@ -446,7 +460,7 @@ function createSeedClient(baseUrl, options) {
446
460
  } catch {
447
461
  }
448
462
  throw new SeedClientError(
449
- `HTTP ${response.status} from ${key}: ${response.statusText}`,
463
+ formatHTTPErrorMessage(key, response.status, response.statusText, errorBody),
450
464
  response.status,
451
465
  errorBody
452
466
  );
@@ -461,34 +475,60 @@ function createSeedClient(baseUrl, options) {
461
475
  async function publishDocument(input, signer) {
462
476
  if (!input.genesis && !input.baseVersion && !input.path) {
463
477
  const genesisChange = await createGenesisChange(signer);
464
- const contentChange = await createDocumentChange(
465
- {
466
- changes: input.changes,
467
- genesisCid: genesisChange.cid,
468
- deps: [genesisChange.cid],
469
- depth: 1
470
- },
471
- signer
472
- );
473
- const ref = await createVersionRef(
478
+ const generation = input.generation != null ? Number(input.generation) : 1;
479
+ if (input.changes.every((change) => {
480
+ var _a;
481
+ return ((_a = change.op) == null ? void 0 : _a.case) === "setMetadata";
482
+ })) {
483
+ const contentChange = await createDocumentChange(
484
+ {
485
+ changes: input.changes,
486
+ genesisCid: genesisChange.cid,
487
+ deps: [genesisChange.cid],
488
+ depth: 1
489
+ },
490
+ signer
491
+ );
492
+ const ref = await createVersionRef(
493
+ {
494
+ space: input.account,
495
+ path: "",
496
+ genesis: genesisChange.cid.toString(),
497
+ version: contentChange.cid.toString(),
498
+ generation,
499
+ capability: input.capability
500
+ },
501
+ signer
502
+ );
503
+ await publish({
504
+ blobs: [
505
+ { data: genesisChange.bytes, cid: genesisChange.cid.toString() },
506
+ { data: contentChange.bytes, cid: contentChange.cid.toString() },
507
+ ...ref.blobs
508
+ ]
509
+ });
510
+ return;
511
+ }
512
+ const genesisRef = await createVersionRef(
474
513
  {
475
514
  space: input.account,
476
515
  path: "",
477
516
  genesis: genesisChange.cid.toString(),
478
- version: contentChange.cid.toString(),
479
- generation: input.generation != null ? Number(input.generation) : 1,
517
+ version: genesisChange.cid.toString(),
518
+ generation,
480
519
  capability: input.capability
481
520
  },
482
521
  signer
483
522
  );
484
523
  await publish({
485
- blobs: [
486
- { data: genesisChange.bytes, cid: genesisChange.cid.toString() },
487
- { data: contentChange.bytes, cid: contentChange.cid.toString() },
488
- ...ref.blobs
489
- ]
524
+ blobs: [{ data: genesisChange.bytes, cid: genesisChange.cid.toString() }, ...genesisRef.blobs]
490
525
  });
491
- return;
526
+ input = {
527
+ ...input,
528
+ baseVersion: genesisChange.cid.toString(),
529
+ genesis: genesisChange.cid.toString(),
530
+ generation
531
+ };
492
532
  }
493
533
  const prepareInput = {
494
534
  account: input.account,
@@ -521,6 +561,19 @@ function createSeedClient(baseUrl, options) {
521
561
  publishDocument
522
562
  };
523
563
  }
564
+ function formatHTTPErrorMessage(key, status, statusText, body) {
565
+ const base = `HTTP ${status} from ${key}: ${statusText}`;
566
+ if (!body) return base;
567
+ try {
568
+ const parsed = JSON.parse(body);
569
+ if (parsed && typeof parsed === "object" && typeof parsed.error === "string" && parsed.error.trim()) {
570
+ return `${base}: ${parsed.error}`;
571
+ }
572
+ } catch {
573
+ }
574
+ const trimmed = body.trim();
575
+ return trimmed ? `${base}: ${trimmed}` : base;
576
+ }
524
577
  function isAbortError(err) {
525
578
  return typeof DOMException !== "undefined" && err instanceof DOMException && err.name === "AbortError";
526
579
  }
package/dist/ref.d.ts CHANGED
@@ -17,6 +17,8 @@ export type CreateVersionRefInput = {
17
17
  capability?: string;
18
18
  /** Optional CBOR visibility value (e.g., "Private"). Omit or leave empty for public. */
19
19
  visibility?: string;
20
+ /** Optional timestamp in Unix milliseconds. Defaults to Date.now(). */
21
+ ts?: number;
20
22
  };
21
23
  export type CreateTombstoneRefInput = {
22
24
  /** Account UID (base58btc-encoded principal) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-hypermedia/client",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/seed-hypermedia/seed",