@dxos/keys 0.8.4-main.f9ba587 → 0.8.4-main.fffef41

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.
@@ -100,29 +100,70 @@ init_inject_globals();
100
100
 
101
101
  // src/dxn.ts
102
102
  init_inject_globals();
103
- import { Schema as Schema3 } from "effect";
103
+ import * as Schema3 from "effect/Schema";
104
104
  import { devtoolsFormatter, inspectCustom } from "@dxos/debug";
105
- import { invariant as invariant2 } from "@dxos/invariant";
105
+ import { assertArgument, invariant as invariant2 } from "@dxos/invariant";
106
106
 
107
107
  // src/object-id.ts
108
108
  init_inject_globals();
109
- import { Schema } from "effect";
110
- import { ulid } from "ulidx";
109
+ import * as Schema from "effect/Schema";
110
+ import { monotonicFactory } from "ulidx";
111
111
  var ObjectIdSchema = Schema.String.pipe(Schema.pattern(/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i)).annotations({
112
- description: "a Universally Unique Lexicographically Sortable Identifier",
112
+ description: "A Universally Unique Lexicographically Sortable Identifier",
113
113
  pattern: "^[0-7][0-9A-HJKMNP-TV-Z]{25}$"
114
114
  });
115
115
  var ObjectId = class extends ObjectIdSchema {
116
+ static #factory = monotonicFactory();
117
+ static #seedTime = void 0;
116
118
  static isValid(id) {
117
119
  try {
118
120
  Schema.decodeSync(ObjectId)(id);
119
121
  return true;
120
- } catch (err) {
122
+ } catch {
121
123
  return false;
122
124
  }
123
125
  }
124
126
  static random() {
125
- return ulid();
127
+ return this.#factory(this.#seedTime);
128
+ }
129
+ static dangerouslyDisableRandomness() {
130
+ this.#factory = monotonicFactory(makeTestPRNG());
131
+ this.#seedTime = (/* @__PURE__ */ new Date("2025-01-01")).getTime();
132
+ }
133
+ };
134
+ var makeTestPRNG = () => {
135
+ const rng = new SimplePRNG();
136
+ return () => {
137
+ return rng.next();
138
+ };
139
+ };
140
+ var SimplePRNG = class _SimplePRNG {
141
+ #seed;
142
+ // LCG parameters (from Numerical Recipes)
143
+ static #a = 1664525;
144
+ static #c = 1013904223;
145
+ static #m = Math.pow(2, 32);
146
+ /**
147
+ * Creates a new PRNG instance.
148
+ * @param seed - Initial seed value. If not provided, uses 0.
149
+ */
150
+ constructor(seed = 0) {
151
+ this.#seed = seed;
152
+ }
153
+ /**
154
+ * Generates the next pseudo-random number in the range [0, 1).
155
+ * @returns A pseudo-random number between 0 (inclusive) and 1 (exclusive).
156
+ */
157
+ next() {
158
+ this.#seed = (_SimplePRNG.#a * this.#seed + _SimplePRNG.#c) % _SimplePRNG.#m;
159
+ return this.#seed / _SimplePRNG.#m;
160
+ }
161
+ /**
162
+ * Resets the generator with a new seed.
163
+ * @param seed - New seed value.
164
+ */
165
+ reset(seed) {
166
+ this.#seed = seed;
126
167
  }
127
168
  };
128
169
 
@@ -194,7 +235,7 @@ function base32Encode(data, variant, options) {
194
235
  }
195
236
 
196
237
  // src/space-id.ts
197
- import { Schema as Schema2 } from "effect";
238
+ import * as Schema2 from "effect/Schema";
198
239
  import { invariant } from "@dxos/invariant";
199
240
 
200
241
  // src/random-bytes.ts
@@ -214,114 +255,107 @@ var isValid = (value) => {
214
255
  return typeof value === "string" && value.startsWith(MULTIBASE_PREFIX) && value.length === ENCODED_LENGTH;
215
256
  };
216
257
  var SpaceId = class extends Schema2.String.pipe(Schema2.filter(isValid)) {
217
- static {
218
- this.byteLength = 20;
219
- }
220
- static {
221
- this.encode = (value) => {
222
- invariant(value instanceof Uint8Array, "Invalid type", {
223
- F: __dxlog_file,
224
- L: 43,
225
- S: this,
226
- A: [
227
- "value instanceof Uint8Array",
228
- "'Invalid type'"
229
- ]
230
- });
231
- invariant(value.length === SpaceId.byteLength, "Invalid length", {
232
- F: __dxlog_file,
233
- L: 44,
234
- S: this,
235
- A: [
236
- "value.length === SpaceId.byteLength",
237
- "'Invalid length'"
238
- ]
239
- });
240
- return MULTIBASE_PREFIX + base32Encode(value, "RFC4648");
241
- };
242
- }
243
- static {
244
- this.decode = (value) => {
245
- invariant(value.startsWith(MULTIBASE_PREFIX), "Invalid multibase32 encoding", {
246
- F: __dxlog_file,
247
- L: 49,
248
- S: this,
249
- A: [
250
- "value.startsWith(MULTIBASE_PREFIX)",
251
- "'Invalid multibase32 encoding'"
252
- ]
253
- });
254
- return new Uint8Array((0, import_base32_decode.default)(value.slice(1), "RFC4648"));
255
- };
256
- }
257
- static {
258
- this.isValid = isValid;
259
- }
260
- static {
261
- this.random = () => {
262
- return SpaceId.encode(randomBytes(SpaceId.byteLength));
263
- };
264
- }
258
+ static byteLength = 20;
259
+ static encode = (value) => {
260
+ invariant(value instanceof Uint8Array, "Invalid type", {
261
+ F: __dxlog_file,
262
+ L: 43,
263
+ S: this,
264
+ A: [
265
+ "value instanceof Uint8Array",
266
+ "'Invalid type'"
267
+ ]
268
+ });
269
+ invariant(value.length === SpaceId.byteLength, "Invalid length", {
270
+ F: __dxlog_file,
271
+ L: 44,
272
+ S: this,
273
+ A: [
274
+ "value.length === SpaceId.byteLength",
275
+ "'Invalid length'"
276
+ ]
277
+ });
278
+ return MULTIBASE_PREFIX + base32Encode(value, "RFC4648");
279
+ };
280
+ static decode = (value) => {
281
+ invariant(value.startsWith(MULTIBASE_PREFIX), "Invalid multibase32 encoding", {
282
+ F: __dxlog_file,
283
+ L: 49,
284
+ S: this,
285
+ A: [
286
+ "value.startsWith(MULTIBASE_PREFIX)",
287
+ "'Invalid multibase32 encoding'"
288
+ ]
289
+ });
290
+ return new Uint8Array((0, import_base32_decode.default)(value.slice(1), "RFC4648"));
291
+ };
292
+ static isValid = isValid;
293
+ static random = () => {
294
+ return SpaceId.encode(randomBytes(SpaceId.byteLength));
295
+ };
265
296
  };
266
297
 
267
298
  // src/dxn.ts
268
299
  var __dxlog_file2 = "/__w/dxos/dxos/packages/common/keys/src/dxn.ts";
269
300
  var LOCAL_SPACE_TAG = "@";
301
+ var DXN_ECHO_REGEXP = /@(dxn:[a-zA-Z0-p:@]+)/;
270
302
  var QueueSubspaceTags = Object.freeze({
271
303
  DATA: "data",
272
304
  TRACE: "trace"
273
305
  });
274
306
  var DXN = class _DXN {
275
- static {
276
- // TODO(dmaretskyi): Should this be a transformation into the DXN type?
277
- this.Schema = Schema3.NonEmptyString.pipe(
278
- Schema3.pattern(/^dxn:([^:]+):(?:[^:]+:?)+[^:]$/),
279
- // TODO(dmaretskyi): To set the format we need to move the annotation IDs out of the echo-schema package.
280
- // FormatAnnotation.set(FormatEnum.DXN),
281
- Schema3.annotations({
282
- title: "DXN",
283
- description: "DXN URI",
284
- examples: [
285
- "dxn:type:example.com/type/MyType",
286
- "dxn:echo:@:01J00J9B45YHYSGZQTQMSKMGJ6"
287
- ]
288
- })
289
- );
290
- }
307
+ // TODO(burdon): Rename to DXN (i.e., DXN.DXN).
308
+ // TODO(dmaretskyi): Should this be a transformation into the DXN type?
309
+ static Schema = Schema3.NonEmptyString.pipe(
310
+ Schema3.pattern(/^dxn:([^:]+):(?:[^:]+:?)+[^:]$/),
311
+ // TODO(dmaretskyi): To set the format we need to move the annotation IDs out of the echo-schema package.
312
+ // FormatAnnotation.set(FormatEnum.DXN),
313
+ Schema3.annotations({
314
+ title: "DXN",
315
+ description: "DXN URI",
316
+ examples: [
317
+ "dxn:type:example.com/type/MyType",
318
+ "dxn:echo:@:01J00J9B45YHYSGZQTQMSKMGJ6"
319
+ ]
320
+ })
321
+ );
291
322
  static hash(dxn) {
292
323
  return dxn.toString();
293
324
  }
294
- static {
325
+ /**
326
+ * Kind constants.
327
+ */
328
+ static kind = Object.freeze({
295
329
  /**
296
- * Kind constants.
330
+ * dxn:type:<type_name>[:<version>]
297
331
  */
298
- this.kind = Object.freeze({
299
- /**
300
- * dxn:type:<type name>[:<version>]
301
- */
302
- TYPE: "type",
303
- /**
304
- * dxn:echo:<space id>:<echo id>
305
- * dxn:echo:@:<echo id>
306
- */
307
- // TODO(burdon): Rename to OBJECT? (BREAKING CHANGE).
308
- // TODO(burdon): Add separate Kind for space.
309
- ECHO: "echo",
310
- /**
311
- * The subspace tag enables us to partition queues by usage within the context of a space.
312
- * dxn:queue:<subspace_tag>:<space_id>:<queue_id>[:object_id]
313
- * dxn:queue:data:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6
314
- * dxn:queue:trace:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6
315
- */
316
- QUEUE: "queue"
317
- });
318
- }
319
- get kind() {
320
- return this.#kind;
321
- }
332
+ TYPE: "type",
333
+ /**
334
+ * dxn:echo:<space_id>:<echo_id>
335
+ * dxn:echo:@:<echo_id>
336
+ */
337
+ // TODO(burdon): Rename to OBJECT? (BREAKING CHANGE to update "echo").
338
+ // TODO(burdon): Add separate Kind for space?
339
+ ECHO: "echo",
340
+ /**
341
+ * The subspace tag enables us to partition queues by usage within the context of a space.
342
+ * dxn:queue:<subspace_tag>:<space_id>:<queue_id>[:object_id]
343
+ * dxn:queue:data:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6
344
+ * dxn:queue:trace:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6
345
+ */
346
+ QUEUE: "queue"
347
+ });
348
+ /**
349
+ * Exactly equals.
350
+ */
322
351
  static equals(a, b) {
323
352
  return a.kind === b.kind && a.parts.length === b.parts.length && a.parts.every((part, i) => part === b.parts[i]);
324
353
  }
354
+ static equalsEchoId(a, b) {
355
+ const a1 = a.asEchoDXN();
356
+ const b1 = b.asEchoDXN();
357
+ return !!a1 && !!b1 && a1.echoId === b1.echoId;
358
+ }
325
359
  // TODO(burdon): Rename isValid.
326
360
  static isDXNString(dxn) {
327
361
  return dxn.startsWith("dxn:");
@@ -345,12 +379,12 @@ var DXN = class _DXN {
345
379
  static tryParse(dxn) {
346
380
  try {
347
381
  return _DXN.parse(dxn);
348
- } catch (error) {
382
+ } catch {
349
383
  return void 0;
350
384
  }
351
385
  }
352
386
  /**
353
- * @example `dxn:type:example.com/type/Contact`
387
+ * @example `dxn:type:example.com/type/Person`
354
388
  */
355
389
  static fromTypename(typename) {
356
390
  return new _DXN(_DXN.kind.TYPE, [
@@ -358,7 +392,7 @@ var DXN = class _DXN {
358
392
  ]);
359
393
  }
360
394
  /**
361
- * @example `dxn:type:example.com/type/Contact:0.1.0`
395
+ * @example `dxn:type:example.com/type/Person:0.1.0`
362
396
  */
363
397
  // TODO(dmaretskyi): Consider using @ as the version separator.
364
398
  static fromTypenameAndVersion(typename, version) {
@@ -368,42 +402,30 @@ var DXN = class _DXN {
368
402
  ]);
369
403
  }
370
404
  /**
405
+ * @example `dxn:echo:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6`
406
+ */
407
+ static fromSpaceAndObjectId(spaceId, objectId) {
408
+ assertArgument(SpaceId.isValid(spaceId), `Invalid space ID: ${spaceId}`);
409
+ assertArgument(ObjectId.isValid(objectId), "objectId", `Invalid object ID: ${objectId}`);
410
+ return new _DXN(_DXN.kind.ECHO, [
411
+ spaceId,
412
+ objectId
413
+ ]);
414
+ }
415
+ /**
371
416
  * @example `dxn:echo:@:01J00J9B45YHYSGZQTQMSKMGJ6`
372
417
  */
373
418
  static fromLocalObjectId(id) {
419
+ assertArgument(ObjectId.isValid(id), "id", `Invalid object ID: ${id}`);
374
420
  return new _DXN(_DXN.kind.ECHO, [
375
421
  LOCAL_SPACE_TAG,
376
422
  id
377
423
  ]);
378
424
  }
379
425
  static fromQueue(subspaceTag, spaceId, queueId, objectId) {
380
- invariant2(SpaceId.isValid(spaceId), void 0, {
381
- F: __dxlog_file2,
382
- L: 150,
383
- S: this,
384
- A: [
385
- "SpaceId.isValid(spaceId)",
386
- ""
387
- ]
388
- });
389
- invariant2(ObjectId.isValid(queueId), void 0, {
390
- F: __dxlog_file2,
391
- L: 151,
392
- S: this,
393
- A: [
394
- "ObjectId.isValid(queueId)",
395
- ""
396
- ]
397
- });
398
- invariant2(!objectId || ObjectId.isValid(objectId), void 0, {
399
- F: __dxlog_file2,
400
- L: 152,
401
- S: this,
402
- A: [
403
- "!objectId || ObjectId.isValid(objectId)",
404
- ""
405
- ]
406
- });
426
+ assertArgument(SpaceId.isValid(spaceId), `Invalid space ID: ${spaceId}`);
427
+ assertArgument(ObjectId.isValid(queueId), "queueId", `Invalid queue ID: ${queueId}`);
428
+ assertArgument(!objectId || ObjectId.isValid(objectId), "objectId", `Invalid object ID: ${objectId}`);
407
429
  return new _DXN(_DXN.kind.QUEUE, [
408
430
  subspaceTag,
409
431
  spaceId,
@@ -416,33 +438,17 @@ var DXN = class _DXN {
416
438
  #kind;
417
439
  #parts;
418
440
  constructor(kind, parts) {
419
- invariant2(parts.length > 0, void 0, {
420
- F: __dxlog_file2,
421
- L: 161,
422
- S: this,
423
- A: [
424
- "parts.length > 0",
425
- ""
426
- ]
427
- });
428
- invariant2(parts.every((part) => typeof part === "string" && part.length > 0 && part.indexOf(":") === -1), void 0, {
429
- F: __dxlog_file2,
430
- L: 162,
431
- S: this,
432
- A: [
433
- "parts.every((part) => typeof part === 'string' && part.length > 0 && part.indexOf(':') === -1)",
434
- ""
435
- ]
436
- });
441
+ assertArgument(parts.length > 0, "parts", `Invalid DXN: ${parts}`);
442
+ assertArgument(parts.every((part) => typeof part === "string" && part.length > 0 && part.indexOf(":") === -1), "parts", `Invalid DXN: ${parts}`);
437
443
  switch (kind) {
438
444
  case _DXN.kind.TYPE:
439
445
  if (parts.length > 2) {
440
- throw new Error('Invalid "type" DXN');
446
+ throw new Error("Invalid DXN.kind.TYPE");
441
447
  }
442
448
  break;
443
449
  case _DXN.kind.ECHO:
444
450
  if (parts.length !== 2) {
445
- throw new Error('Invalid "echo" DXN');
451
+ throw new Error("Invalid DXN.kind.ECHO");
446
452
  }
447
453
  break;
448
454
  }
@@ -477,6 +483,9 @@ var DXN = class _DXN {
477
483
  }
478
484
  };
479
485
  }
486
+ get kind() {
487
+ return this.#kind;
488
+ }
480
489
  get parts() {
481
490
  return this.#parts;
482
491
  }
@@ -484,7 +493,7 @@ var DXN = class _DXN {
484
493
  get typename() {
485
494
  invariant2(this.#kind === _DXN.kind.TYPE, void 0, {
486
495
  F: __dxlog_file2,
487
- L: 217,
496
+ L: 250,
488
497
  S: this,
489
498
  A: [
490
499
  "this.#kind === DXN.kind.TYPE",
@@ -493,6 +502,9 @@ var DXN = class _DXN {
493
502
  });
494
503
  return this.#parts[0];
495
504
  }
505
+ equals(other) {
506
+ return _DXN.equals(this, other);
507
+ }
496
508
  hasTypenameOf(typename) {
497
509
  return this.#kind === _DXN.kind.TYPE && this.#parts.length === 1 && this.#parts[0] === typename;
498
510
  }
@@ -505,6 +517,7 @@ var DXN = class _DXN {
505
517
  }
506
518
  const [type, version] = this.#parts;
507
519
  return {
520
+ // TODO(wittjosiah): Should be `typename` for consistency.
508
521
  type,
509
522
  version
510
523
  };
@@ -516,6 +529,7 @@ var DXN = class _DXN {
516
529
  const [spaceId, echoId] = this.#parts;
517
530
  return {
518
531
  spaceId: spaceId === LOCAL_SPACE_TAG ? void 0 : spaceId,
532
+ // TODO(burdon): objectId.
519
533
  echoId
520
534
  };
521
535
  }
@@ -534,6 +548,15 @@ var DXN = class _DXN {
534
548
  objectId
535
549
  };
536
550
  }
551
+ /**
552
+ * Produces a new DXN with the given parts appended.
553
+ */
554
+ extend(parts) {
555
+ return new _DXN(this.#kind, [
556
+ ...this.#parts,
557
+ ...parts
558
+ ]);
559
+ }
537
560
  };
538
561
 
539
562
  // src/identity-did.ts
@@ -597,9 +620,8 @@ var PUBLIC_KEY_LENGTH = 32;
597
620
  var SECRET_KEY_LENGTH = 64;
598
621
  var isLikeArrayBuffer = (value) => typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ArrayBuffer";
599
622
  var PublicKey = class _PublicKey {
600
- static {
601
- this.ZERO = _PublicKey.from("00".repeat(PUBLIC_KEY_LENGTH));
602
- }
623
+ _value;
624
+ static ZERO = _PublicKey.from("00".repeat(PUBLIC_KEY_LENGTH));
603
625
  /**
604
626
  * Creates new instance of PublicKey automatically determining the input format.
605
627
  * @param source A Buffer, or Uint8Array, or hex encoded string, or something with an `asUint8Array` method on it
@@ -608,7 +630,7 @@ var PublicKey = class _PublicKey {
608
630
  static from(source) {
609
631
  invariant4(source, void 0, {
610
632
  F: __dxlog_file4,
611
- L: 49,
633
+ L: 50,
612
634
  S: this,
613
635
  A: [
614
636
  "source",
@@ -700,7 +722,7 @@ var PublicKey = class _PublicKey {
700
722
  static bufferize(str) {
701
723
  invariant4(typeof str === "string", "Invalid type", {
702
724
  F: __dxlog_file4,
703
- L: 152,
725
+ L: 153,
704
726
  S: this,
705
727
  A: [
706
728
  "typeof str === 'string'",
@@ -723,7 +745,7 @@ var PublicKey = class _PublicKey {
723
745
  }
724
746
  invariant4(key instanceof Buffer2, "Invalid type", {
725
747
  F: __dxlog_file4,
726
- L: 171,
748
+ L: 172,
727
749
  S: this,
728
750
  A: [
729
751
  "key instanceof Buffer",
@@ -742,7 +764,7 @@ var PublicKey = class _PublicKey {
742
764
  static fromMultibase32(encoded) {
743
765
  invariant4(encoded.startsWith("B"), "Invalid multibase32 encoding", {
744
766
  F: __dxlog_file4,
745
- L: 184,
767
+ L: 185,
746
768
  S: this,
747
769
  A: [
748
770
  "encoded.startsWith('B')",
@@ -881,6 +903,7 @@ var PublicKey = class _PublicKey {
881
903
  };
882
904
  export {
883
905
  DXN,
906
+ DXN_ECHO_REGEXP,
884
907
  IdentityDid,
885
908
  LOCAL_SPACE_TAG,
886
909
  ObjectId,
@@ -888,6 +911,7 @@ export {
888
911
  PublicKey,
889
912
  QueueSubspaceTags,
890
913
  SECRET_KEY_LENGTH,
914
+ SimplePRNG,
891
915
  SpaceId
892
916
  };
893
917
  //# sourceMappingURL=index.mjs.map