@dxos/keys 0.8.3-main.672df60 → 0.8.3-staging.0fa589b

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.
@@ -98,7 +98,35 @@ var require_base32_decode = __commonJS({
98
98
  // packages/common/keys/src/index.ts
99
99
  init_inject_globals();
100
100
 
101
- // packages/common/keys/src/identity-did.ts
101
+ // packages/common/keys/src/dxn.ts
102
+ init_inject_globals();
103
+ import { Schema as Schema3 } from "effect";
104
+ import { devtoolsFormatter, inspectCustom } from "@dxos/debug";
105
+ import { invariant as invariant2 } from "@dxos/invariant";
106
+
107
+ // packages/common/keys/src/object-id.ts
108
+ init_inject_globals();
109
+ import { Schema } from "effect";
110
+ import { ulid } from "ulidx";
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",
113
+ pattern: "^[0-7][0-9A-HJKMNP-TV-Z]{25}$"
114
+ });
115
+ var ObjectId = class extends ObjectIdSchema {
116
+ static isValid(id) {
117
+ try {
118
+ Schema.decodeSync(ObjectId)(id);
119
+ return true;
120
+ } catch (err) {
121
+ return false;
122
+ }
123
+ }
124
+ static random() {
125
+ return ulid();
126
+ }
127
+ };
128
+
129
+ // packages/common/keys/src/space-id.ts
102
130
  init_inject_globals();
103
131
  var import_base32_decode = __toESM(require_base32_decode(), 1);
104
132
 
@@ -165,7 +193,8 @@ function base32Encode(data, variant, options) {
165
193
  return output;
166
194
  }
167
195
 
168
- // packages/common/keys/src/identity-did.ts
196
+ // packages/common/keys/src/space-id.ts
197
+ import { Schema as Schema2 } from "effect";
169
198
  import { invariant } from "@dxos/invariant";
170
199
 
171
200
  // packages/common/keys/src/random-bytes.ts
@@ -177,701 +206,675 @@ var randomBytes = (length) => {
177
206
  return bytes;
178
207
  };
179
208
 
180
- // packages/common/keys/src/identity-did.ts
181
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/keys/src/identity-did.ts";
182
- var IdentityDid = Object.freeze({
183
- byteLength: 20,
184
- encode: (value) => {
185
- invariant(value instanceof Uint8Array, "Invalid type", {
186
- F: __dxlog_file,
187
- L: 22,
188
- S: void 0,
189
- A: [
190
- "value instanceof Uint8Array",
191
- "'Invalid type'"
192
- ]
193
- });
194
- invariant(value.length === IdentityDid.byteLength, "Invalid length", {
195
- F: __dxlog_file,
196
- L: 23,
197
- S: void 0,
198
- A: [
199
- "value.length === IdentityDid.byteLength",
200
- "'Invalid length'"
201
- ]
202
- });
203
- return DID_PREFIX + MULTIBASE_PREFIX + base32Encode(value, "RFC4648");
204
- },
205
- decode: (value) => {
206
- invariant(value.startsWith(DID_PREFIX + MULTIBASE_PREFIX), "Invalid multibase32 encoding", {
207
- F: __dxlog_file,
208
- L: 28,
209
- S: void 0,
210
- A: [
211
- "value.startsWith(DID_PREFIX + MULTIBASE_PREFIX)",
212
- "'Invalid multibase32 encoding'"
213
- ]
214
- });
215
- return new Uint8Array((0, import_base32_decode.default)(value.slice(10), "RFC4648"));
216
- },
217
- isValid: (value) => {
218
- return typeof value === "string" && value.startsWith(DID_PREFIX + MULTIBASE_PREFIX) && value.length === ENCODED_LENGTH;
219
- },
220
- random: () => {
221
- return IdentityDid.encode(randomBytes(IdentityDid.byteLength));
222
- }
223
- });
209
+ // packages/common/keys/src/space-id.ts
210
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/keys/src/space-id.ts";
224
211
  var MULTIBASE_PREFIX = "B";
225
- var DID_PREFIX = "did:halo:";
226
- var ENCODED_LENGTH = 42;
212
+ var ENCODED_LENGTH = 33;
213
+ var isValid = (value) => {
214
+ return typeof value === "string" && value.startsWith(MULTIBASE_PREFIX) && value.length === ENCODED_LENGTH;
215
+ };
216
+ 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
+ }
265
+ };
227
266
 
228
- // packages/common/keys/src/public-key.ts
229
- init_inject_globals();
230
- var import_base32_decode2 = __toESM(require_base32_decode(), 1);
231
- import { devtoolsFormatter, equalsSymbol, inspectCustom, truncateKey } from "@dxos/debug";
232
- import { invariant as invariant2 } from "@dxos/invariant";
233
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/common/keys/src/public-key.ts";
234
- var PUBLIC_KEY_LENGTH = 32;
235
- var SECRET_KEY_LENGTH = 64;
236
- var isLikeArrayBuffer = (value) => typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ArrayBuffer";
237
- var PublicKey = class _PublicKey {
267
+ // packages/common/keys/src/dxn.ts
268
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/common/keys/src/dxn.ts";
269
+ var LOCAL_SPACE_TAG = "@";
270
+ var QueueSubspaceTags = Object.freeze({
271
+ DATA: "data",
272
+ TRACE: "trace"
273
+ });
274
+ var DXN = class _DXN {
238
275
  static {
239
- this.ZERO = _PublicKey.from("00".repeat(PUBLIC_KEY_LENGTH));
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
+ );
240
290
  }
241
- /**
242
- * Creates new instance of PublicKey automatically determining the input format.
243
- * @param source A Buffer, or Uint8Array, or hex encoded string, or something with an `asUint8Array` method on it
244
- * @returns PublicKey
245
- */
246
- static from(source) {
247
- invariant2(source, void 0, {
248
- F: __dxlog_file2,
249
- L: 49,
250
- S: this,
251
- A: [
252
- "source",
253
- ""
254
- ]
291
+ static hash(dxn) {
292
+ return dxn.toString();
293
+ }
294
+ static {
295
+ /**
296
+ * Kind constants.
297
+ */
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"
255
317
  });
256
- if (source instanceof _PublicKey) {
257
- return source;
258
- } else if (source instanceof Buffer2) {
259
- return new _PublicKey(new Uint8Array(source.buffer, source.byteOffset, source.byteLength));
260
- } else if (source instanceof Uint8Array) {
261
- return new _PublicKey(source);
262
- } else if (source instanceof ArrayBuffer || isLikeArrayBuffer(source)) {
263
- return new _PublicKey(new Uint8Array(source));
264
- } else if (typeof source === "string") {
265
- return _PublicKey.fromHex(source);
266
- } else if (source.asUint8Array) {
267
- return new _PublicKey(source.asUint8Array());
268
- } else {
269
- throw new TypeError(`Unable to create PublicKey from ${source}`);
270
- }
271
318
  }
272
- /**
273
- * Same as `PublicKey.from` but does not throw and instead returns a `{ key: PublicKey }` or `{ error: Error }`
274
- * @param source Same PublicKeyLike argument as for `PublicKey.from`
275
- * @returns PublicKey
276
- */
277
- static safeFrom(source) {
278
- if (!source) {
279
- return void 0;
319
+ get kind() {
320
+ return this.#kind;
321
+ }
322
+ static equals(a, b) {
323
+ return a.kind === b.kind && a.parts.length === b.parts.length && a.parts.every((part, i) => part === b.parts[i]);
324
+ }
325
+ // TODO(burdon): Rename isValid.
326
+ static isDXNString(dxn) {
327
+ return dxn.startsWith("dxn:");
328
+ }
329
+ static parse(dxn) {
330
+ if (typeof dxn !== "string") {
331
+ throw new Error(`Invalid DXN: ${dxn}`);
332
+ }
333
+ const [prefix, kind, ...parts] = dxn.split(":");
334
+ if (!(prefix === "dxn")) {
335
+ throw new Error(`Invalid DXN: ${dxn}`);
280
336
  }
337
+ if (!(typeof kind === "string" && kind.length > 0)) {
338
+ throw new Error(`Invalid DXN: ${dxn}`);
339
+ }
340
+ if (!(parts.length > 0)) {
341
+ throw new Error(`Invalid DXN: ${dxn}`);
342
+ }
343
+ return new _DXN(kind, parts);
344
+ }
345
+ static tryParse(dxn) {
281
346
  try {
282
- const key = _PublicKey.from(source);
283
- return key;
284
- } catch (err) {
347
+ return _DXN.parse(dxn);
348
+ } catch (error) {
285
349
  return void 0;
286
350
  }
287
351
  }
288
352
  /**
289
- * Creates new instance of PublicKey from hex string.
353
+ * @example `dxn:type:example.com/type/Contact`
290
354
  */
291
- static fromHex(hex) {
292
- if (hex.startsWith("0x")) {
293
- hex = hex.slice(2);
294
- }
295
- const buf = Buffer2.from(hex, "hex");
296
- return new _PublicKey(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
355
+ static fromTypename(typename) {
356
+ return new _DXN(_DXN.kind.TYPE, [
357
+ typename
358
+ ]);
297
359
  }
298
360
  /**
299
- * Creates a new key.
361
+ * @example `dxn:type:example.com/type/Contact:0.1.0`
300
362
  */
301
- static random() {
302
- return _PublicKey.from(randomBytes(PUBLIC_KEY_LENGTH));
303
- }
304
- static randomOfLength(length) {
305
- return _PublicKey.from(randomBytes(length));
306
- }
307
- static *randomSequence() {
308
- for (let i = 0; i < 1e4; i++) {
309
- yield _PublicKey.random();
310
- }
311
- throw new Error("Too many keys requested");
312
- }
313
- /**
314
- * Tests if provided values is an instance of PublicKey.
315
- */
316
- static isPublicKey(value) {
317
- return value instanceof _PublicKey;
318
- }
319
- /**
320
- * Asserts that provided values is an instance of PublicKey.
321
- */
322
- static assertValidPublicKey(value) {
323
- if (!this.isPublicKey(value)) {
324
- throw new TypeError("Invalid PublicKey");
325
- }
363
+ // TODO(dmaretskyi): Consider using @ as the version separator.
364
+ static fromTypenameAndVersion(typename, version) {
365
+ return new _DXN(_DXN.kind.TYPE, [
366
+ typename,
367
+ version
368
+ ]);
326
369
  }
327
370
  /**
328
- * Tests two keys for equality.
371
+ * @example `dxn:echo:@:01J00J9B45YHYSGZQTQMSKMGJ6`
329
372
  */
330
- static equals(left, right) {
331
- return _PublicKey.from(left).equals(right);
373
+ static fromLocalObjectId(id) {
374
+ return new _DXN(_DXN.kind.ECHO, [
375
+ LOCAL_SPACE_TAG,
376
+ id
377
+ ]);
332
378
  }
333
- /**
334
- * @param str string representation of key.
335
- * @return Key buffer.
336
- * @deprecated All keys should be represented as instances of PublicKey.
337
- */
338
- static bufferize(str) {
339
- invariant2(typeof str === "string", "Invalid type", {
379
+ 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, {
340
399
  F: __dxlog_file2,
341
400
  L: 152,
342
401
  S: this,
343
402
  A: [
344
- "typeof str === 'string'",
345
- "'Invalid type'"
403
+ "!objectId || ObjectId.isValid(objectId)",
404
+ ""
346
405
  ]
347
406
  });
348
- const buffer = Buffer2.from(str, "hex");
349
- return buffer;
407
+ return new _DXN(_DXN.kind.QUEUE, [
408
+ subspaceTag,
409
+ spaceId,
410
+ queueId,
411
+ ...objectId ? [
412
+ objectId
413
+ ] : []
414
+ ]);
350
415
  }
351
- /**
352
- * @param key key like data structure (but not PublicKey which should use toString).
353
- * @return Hex string representation of key.
354
- * @deprecated All keys should be represented as instances of PublicKey.
355
- */
356
- static stringify(key) {
357
- if (key instanceof _PublicKey) {
358
- key = key.asBuffer();
359
- } else if (key instanceof Uint8Array) {
360
- key = Buffer2.from(key.buffer, key.byteOffset, key.byteLength);
361
- }
362
- invariant2(key instanceof Buffer2, "Invalid type", {
416
+ #kind;
417
+ #parts;
418
+ constructor(kind, parts) {
419
+ invariant2(parts.length > 0, void 0, {
363
420
  F: __dxlog_file2,
364
- L: 171,
421
+ L: 161,
365
422
  S: this,
366
423
  A: [
367
- "key instanceof Buffer",
368
- "'Invalid type'"
424
+ "parts.length > 0",
425
+ ""
369
426
  ]
370
427
  });
371
- return key.toString("hex");
372
- }
373
- /**
374
- * To be used with ComplexMap and ComplexSet.
375
- * Returns a scalar representation for this key.
376
- */
377
- static hash(key) {
378
- return key.toHex();
379
- }
380
- static fromMultibase32(encoded) {
381
- invariant2(encoded.startsWith("B"), "Invalid multibase32 encoding", {
428
+ invariant2(parts.every((part) => typeof part === "string" && part.length > 0 && part.indexOf(":") === -1), void 0, {
382
429
  F: __dxlog_file2,
383
- L: 184,
430
+ L: 162,
384
431
  S: this,
385
432
  A: [
386
- "encoded.startsWith('B')",
387
- "'Invalid multibase32 encoding'"
433
+ "parts.every((part) => typeof part === 'string' && part.length > 0 && part.indexOf(':') === -1)",
434
+ ""
388
435
  ]
389
436
  });
390
- return new _PublicKey(new Uint8Array((0, import_base32_decode2.default)(encoded.slice(1), "RFC4648")));
391
- }
392
- constructor(_value) {
393
- this._value = _value;
394
- if (!(_value instanceof Uint8Array)) {
395
- throw new TypeError(`Expected Uint8Array, got: ${_value}`);
437
+ switch (kind) {
438
+ case _DXN.kind.TYPE:
439
+ if (parts.length > 2) {
440
+ throw new Error('Invalid "type" DXN');
441
+ }
442
+ break;
443
+ case _DXN.kind.ECHO:
444
+ if (parts.length !== 2) {
445
+ throw new Error('Invalid "echo" DXN');
446
+ }
447
+ break;
396
448
  }
449
+ this.#kind = kind;
450
+ this.#parts = parts;
397
451
  }
398
- toString() {
399
- return this.toHex();
400
- }
401
- toJSON() {
402
- return this.toHex();
403
- }
404
- toJSONL() {
405
- return this.truncate();
452
+ get parts() {
453
+ return this.#parts;
406
454
  }
407
- get length() {
408
- return this._value.length;
455
+ // TODO(burdon): Should getters fail?
456
+ get typename() {
457
+ invariant2(this.#kind === _DXN.kind.TYPE, void 0, {
458
+ F: __dxlog_file2,
459
+ L: 188,
460
+ S: this,
461
+ A: [
462
+ "this.#kind === DXN.kind.TYPE",
463
+ ""
464
+ ]
465
+ });
466
+ return this.#parts[0];
409
467
  }
410
- toHex() {
411
- return this.asBuffer().toString("hex");
468
+ hasTypenameOf(typename) {
469
+ return this.#kind === _DXN.kind.TYPE && this.#parts.length === 1 && this.#parts[0] === typename;
412
470
  }
413
- toMultibase32() {
414
- return "B" + base32Encode(this._value, "RFC4648");
471
+ isLocalObjectId() {
472
+ return this.#kind === _DXN.kind.ECHO && this.#parts[0] === LOCAL_SPACE_TAG && this.#parts.length === 2;
415
473
  }
416
- truncate(length = void 0) {
417
- return truncateKey(this, length);
474
+ asTypeDXN() {
475
+ if (this.kind !== _DXN.kind.TYPE) {
476
+ return void 0;
477
+ }
478
+ const [type, version] = this.#parts;
479
+ return {
480
+ type,
481
+ version
482
+ };
418
483
  }
419
- asBuffer() {
420
- return Buffer2.from(this._value.buffer, this._value.byteOffset, this._value.byteLength);
484
+ asEchoDXN() {
485
+ if (this.kind !== _DXN.kind.ECHO) {
486
+ return void 0;
487
+ }
488
+ const [spaceId, echoId] = this.#parts;
489
+ return {
490
+ spaceId: spaceId === LOCAL_SPACE_TAG ? void 0 : spaceId,
491
+ echoId
492
+ };
421
493
  }
422
- asUint8Array() {
423
- return this._value;
494
+ asQueueDXN() {
495
+ if (this.kind !== _DXN.kind.QUEUE) {
496
+ return void 0;
497
+ }
498
+ const [subspaceTag, spaceId, queueId, objectId] = this.#parts;
499
+ if (typeof queueId !== "string") {
500
+ return void 0;
501
+ }
502
+ return {
503
+ subspaceTag,
504
+ spaceId,
505
+ queueId,
506
+ objectId
507
+ };
424
508
  }
425
- getInsecureHash(modulo) {
426
- return Math.abs(this._value.reduce((acc, val) => acc ^ val | 0, 0)) % modulo;
509
+ toString() {
510
+ return `dxn:${this.#kind}:${this.#parts.join(":")}`;
427
511
  }
428
512
  /**
429
513
  * Used by Node.js to get textual representation of this object when it's printed with a `console.log` statement.
430
514
  */
431
515
  [inspectCustom](depth, options, inspectFn) {
432
- if (!options.colors || typeof process.stdout.hasColors !== "function" || !process.stdout.hasColors()) {
433
- return `<PublicKey ${this.truncate()}>`;
434
- }
435
516
  const printControlCode = (code) => {
436
517
  return `\x1B[${code}m`;
437
518
  };
438
- const colors = [
439
- "red",
440
- "green",
441
- "yellow",
442
- "blue",
443
- "magenta",
444
- "cyan",
445
- "redBright",
446
- "greenBright",
447
- "yellowBright",
448
- "blueBright",
449
- "magentaBright",
450
- "cyanBright",
451
- "whiteBright"
452
- ];
453
- const color = colors[this.getInsecureHash(colors.length)];
454
- return `PublicKey(${printControlCode(inspectFn.colors[color][0])}${this.truncate()}${printControlCode(inspectFn.colors.reset[0])})`;
519
+ return printControlCode(inspectFn.colors.blueBright[0]) + this.toString() + printControlCode(inspectFn.colors.reset[0]);
455
520
  }
456
521
  get [devtoolsFormatter]() {
457
522
  return {
458
523
  header: () => {
459
- const colors = [
460
- "darkred",
461
- "green",
462
- "orange",
463
- "blue",
464
- "darkmagenta",
465
- "darkcyan",
466
- "red",
467
- "green",
468
- "orange",
469
- "blue",
470
- "magenta",
471
- "darkcyan",
472
- "black"
473
- ];
474
- const color = colors[this.getInsecureHash(colors.length)];
475
524
  return [
476
525
  "span",
477
- {},
478
- [
479
- "span",
480
- {},
481
- "PublicKey("
482
- ],
483
- [
484
- "span",
485
- {
486
- style: `color: ${color};`
487
- },
488
- this.truncate()
489
- ],
490
- [
491
- "span",
492
- {},
493
- ")"
494
- ]
526
+ {
527
+ style: "font-weight: bold;"
528
+ },
529
+ this.toString()
495
530
  ];
496
531
  }
497
532
  };
498
533
  }
499
- /**
500
- * Test this key for equality with some other key.
501
- */
502
- equals(other) {
503
- const otherConverted = _PublicKey.from(other);
504
- if (this._value.length !== otherConverted._value.length) {
505
- return false;
506
- }
507
- let equal = true;
508
- for (let i = 0; i < this._value.length; i++) {
509
- equal &&= this._value[i] === otherConverted._value[i];
510
- }
511
- return equal;
512
- }
513
- [equalsSymbol](other) {
514
- if (!_PublicKey.isPublicKey(other)) {
515
- return false;
516
- }
517
- return this.equals(other);
518
- }
519
534
  };
520
535
 
521
- // packages/common/keys/src/space-id.ts
536
+ // packages/common/keys/src/identity-did.ts
522
537
  init_inject_globals();
523
- var import_base32_decode3 = __toESM(require_base32_decode(), 1);
524
- import { Schema } from "effect";
538
+ var import_base32_decode2 = __toESM(require_base32_decode(), 1);
525
539
  import { invariant as invariant3 } from "@dxos/invariant";
526
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/common/keys/src/space-id.ts";
527
- var MULTIBASE_PREFIX2 = "B";
528
- var ENCODED_LENGTH2 = 33;
529
- var isValid = (value) => {
530
- return typeof value === "string" && value.startsWith(MULTIBASE_PREFIX2) && value.length === ENCODED_LENGTH2;
531
- };
532
- var SpaceId = class extends Schema.String.pipe(Schema.filter(isValid)) {
533
- static {
534
- this.byteLength = 20;
535
- }
536
- static {
537
- this.encode = (value) => {
538
- invariant3(value instanceof Uint8Array, "Invalid type", {
539
- F: __dxlog_file3,
540
- L: 43,
541
- S: this,
542
- A: [
543
- "value instanceof Uint8Array",
544
- "'Invalid type'"
545
- ]
546
- });
547
- invariant3(value.length === SpaceId.byteLength, "Invalid length", {
548
- F: __dxlog_file3,
549
- L: 44,
550
- S: this,
551
- A: [
552
- "value.length === SpaceId.byteLength",
553
- "'Invalid length'"
554
- ]
555
- });
556
- return MULTIBASE_PREFIX2 + base32Encode(value, "RFC4648");
557
- };
558
- }
559
- static {
560
- this.decode = (value) => {
561
- invariant3(value.startsWith(MULTIBASE_PREFIX2), "Invalid multibase32 encoding", {
562
- F: __dxlog_file3,
563
- L: 49,
564
- S: this,
565
- A: [
566
- "value.startsWith(MULTIBASE_PREFIX)",
567
- "'Invalid multibase32 encoding'"
568
- ]
569
- });
570
- return new Uint8Array((0, import_base32_decode3.default)(value.slice(1), "RFC4648"));
571
- };
572
- }
573
- static {
574
- this.isValid = isValid;
575
- }
576
- static {
577
- this.random = () => {
578
- return SpaceId.encode(randomBytes(SpaceId.byteLength));
579
- };
540
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/common/keys/src/identity-did.ts";
541
+ var IdentityDid = Object.freeze({
542
+ byteLength: 20,
543
+ encode: (value) => {
544
+ invariant3(value instanceof Uint8Array, "Invalid type", {
545
+ F: __dxlog_file3,
546
+ L: 22,
547
+ S: void 0,
548
+ A: [
549
+ "value instanceof Uint8Array",
550
+ "'Invalid type'"
551
+ ]
552
+ });
553
+ invariant3(value.length === IdentityDid.byteLength, "Invalid length", {
554
+ F: __dxlog_file3,
555
+ L: 23,
556
+ S: void 0,
557
+ A: [
558
+ "value.length === IdentityDid.byteLength",
559
+ "'Invalid length'"
560
+ ]
561
+ });
562
+ return DID_PREFIX + MULTIBASE_PREFIX2 + base32Encode(value, "RFC4648");
563
+ },
564
+ decode: (value) => {
565
+ invariant3(value.startsWith(DID_PREFIX + MULTIBASE_PREFIX2), "Invalid multibase32 encoding", {
566
+ F: __dxlog_file3,
567
+ L: 28,
568
+ S: void 0,
569
+ A: [
570
+ "value.startsWith(DID_PREFIX + MULTIBASE_PREFIX)",
571
+ "'Invalid multibase32 encoding'"
572
+ ]
573
+ });
574
+ return new Uint8Array((0, import_base32_decode2.default)(value.slice(10), "RFC4648"));
575
+ },
576
+ isValid: (value) => {
577
+ return typeof value === "string" && value.startsWith(DID_PREFIX + MULTIBASE_PREFIX2) && value.length === ENCODED_LENGTH2;
578
+ },
579
+ random: () => {
580
+ return IdentityDid.encode(randomBytes(IdentityDid.byteLength));
580
581
  }
581
- };
582
+ });
583
+ var MULTIBASE_PREFIX2 = "B";
584
+ var DID_PREFIX = "did:halo:";
585
+ var ENCODED_LENGTH2 = 42;
582
586
 
583
- // packages/common/keys/src/dxn.ts
587
+ // packages/common/keys/src/public-key.ts
584
588
  init_inject_globals();
585
- import { Schema as Schema3 } from "effect";
586
- import { devtoolsFormatter as devtoolsFormatter2, inspectCustom as inspectCustom2 } from "@dxos/debug";
589
+ var import_base32_decode3 = __toESM(require_base32_decode(), 1);
590
+ import { devtoolsFormatter as devtoolsFormatter2, equalsSymbol, inspectCustom as inspectCustom2, truncateKey } from "@dxos/debug";
587
591
  import { invariant as invariant4 } from "@dxos/invariant";
588
-
589
- // packages/common/keys/src/object-id.ts
590
- init_inject_globals();
591
- import { Schema as Schema2 } from "effect";
592
- import { ulid } from "ulidx";
593
- var ObjectIdSchema = Schema2.String.pipe(Schema2.pattern(/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i)).annotations({
594
- description: "a Universally Unique Lexicographically Sortable Identifier",
595
- pattern: "^[0-7][0-9A-HJKMNP-TV-Z]{25}$"
596
- });
597
- var ObjectId = class extends ObjectIdSchema {
598
- static isValid(id) {
599
- try {
600
- Schema2.decodeSync(ObjectId)(id);
601
- return true;
602
- } catch (err) {
603
- return false;
604
- }
605
- }
606
- static random() {
607
- return ulid();
608
- }
609
- };
610
-
611
- // packages/common/keys/src/dxn.ts
612
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/common/keys/src/dxn.ts";
613
- var LOCAL_SPACE_TAG = "@";
614
- var QueueSubspaceTags = Object.freeze({
615
- DATA: "data",
616
- TRACE: "trace"
617
- });
618
- var DXN = class _DXN {
592
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/common/keys/src/public-key.ts";
593
+ var PUBLIC_KEY_LENGTH = 32;
594
+ var SECRET_KEY_LENGTH = 64;
595
+ var isLikeArrayBuffer = (value) => typeof value === "object" && value !== null && Object.getPrototypeOf(value).constructor.name === "ArrayBuffer";
596
+ var PublicKey = class _PublicKey {
619
597
  static {
620
- // TODO(dmaretskyi): Should this be a transformation into the DXN type?
621
- this.Schema = Schema3.NonEmptyString.pipe(
622
- Schema3.pattern(/^dxn:([^:]+):(?:[^:]+:?)+[^:]$/),
623
- // TODO(dmaretskyi): To set the format we need to move the annotation IDs out of the echo-schema package.
624
- // FormatAnnotation.set(FormatEnum.DXN),
625
- Schema3.annotations({
626
- title: "DXN",
627
- description: "DXN URI",
628
- examples: [
629
- "dxn:type:example.com/type/MyType",
630
- "dxn:echo:@:01J00J9B45YHYSGZQTQMSKMGJ6"
631
- ]
632
- })
633
- );
598
+ this.ZERO = _PublicKey.from("00".repeat(PUBLIC_KEY_LENGTH));
634
599
  }
635
- static {
636
- /**
637
- * Kind constants.
638
- */
639
- this.kind = Object.freeze({
640
- /**
641
- * dxn:type:<type name>[:<version>]
642
- */
643
- TYPE: "type",
644
- /**
645
- * dxn:echo:<space id>:<echo id>
646
- * dxn:echo:@:<echo id>
647
- */
648
- // TODO(burdon): Rename to OBJECT? (BREAKING CHANGE).
649
- // TODO(burdon): Add separate Kind for space.
650
- ECHO: "echo",
651
- /**
652
- * The subspace tag enables us to partition queues by usage within the context of a space.
653
- * dxn:queue:<subspace_tag>:<space_id>:<queue_id>[:object_id]
654
- * dxn:queue:data:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6
655
- * dxn:queue:trace:BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE:01J00J9B45YHYSGZQTQMSKMGJ6
656
- */
657
- QUEUE: "queue"
600
+ /**
601
+ * Creates new instance of PublicKey automatically determining the input format.
602
+ * @param source A Buffer, or Uint8Array, or hex encoded string, or something with an `asUint8Array` method on it
603
+ * @returns PublicKey
604
+ */
605
+ static from(source) {
606
+ invariant4(source, void 0, {
607
+ F: __dxlog_file4,
608
+ L: 49,
609
+ S: this,
610
+ A: [
611
+ "source",
612
+ ""
613
+ ]
658
614
  });
659
- }
660
- get kind() {
661
- return this.#kind;
662
- }
663
- static equals(a, b) {
664
- return a.kind === b.kind && a.parts.length === b.parts.length && a.parts.every((part, i) => part === b.parts[i]);
665
- }
666
- // TODO(burdon): Rename isValid.
667
- static isDXNString(dxn) {
668
- return dxn.startsWith("dxn:");
669
- }
670
- static parse(dxn) {
671
- if (typeof dxn !== "string") {
672
- throw new Error(`Invalid DXN: ${dxn}`);
615
+ if (source instanceof _PublicKey) {
616
+ return source;
617
+ } else if (source instanceof Buffer2) {
618
+ return new _PublicKey(new Uint8Array(source.buffer, source.byteOffset, source.byteLength));
619
+ } else if (source instanceof Uint8Array) {
620
+ return new _PublicKey(source);
621
+ } else if (source instanceof ArrayBuffer || isLikeArrayBuffer(source)) {
622
+ return new _PublicKey(new Uint8Array(source));
623
+ } else if (typeof source === "string") {
624
+ return _PublicKey.fromHex(source);
625
+ } else if (source.asUint8Array) {
626
+ return new _PublicKey(source.asUint8Array());
627
+ } else {
628
+ throw new TypeError(`Unable to create PublicKey from ${source}`);
673
629
  }
674
- const [prefix, kind, ...parts] = dxn.split(":");
675
- if (!(prefix === "dxn")) {
676
- throw new Error(`Invalid DXN: ${dxn}`);
630
+ }
631
+ /**
632
+ * Same as `PublicKey.from` but does not throw and instead returns a `{ key: PublicKey }` or `{ error: Error }`
633
+ * @param source Same PublicKeyLike argument as for `PublicKey.from`
634
+ * @returns PublicKey
635
+ */
636
+ static safeFrom(source) {
637
+ if (!source) {
638
+ return void 0;
677
639
  }
678
- if (!(typeof kind === "string" && kind.length > 0)) {
679
- throw new Error(`Invalid DXN: ${dxn}`);
640
+ try {
641
+ const key = _PublicKey.from(source);
642
+ return key;
643
+ } catch (err) {
644
+ return void 0;
680
645
  }
681
- if (!(parts.length > 0)) {
682
- throw new Error(`Invalid DXN: ${dxn}`);
646
+ }
647
+ /**
648
+ * Creates new instance of PublicKey from hex string.
649
+ */
650
+ static fromHex(hex) {
651
+ if (hex.startsWith("0x")) {
652
+ hex = hex.slice(2);
683
653
  }
684
- return new _DXN(kind, parts);
654
+ const buf = Buffer2.from(hex, "hex");
655
+ return new _PublicKey(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
685
656
  }
686
- static tryParse(dxn) {
687
- try {
688
- return _DXN.parse(dxn);
689
- } catch (error) {
690
- return void 0;
657
+ /**
658
+ * Creates a new key.
659
+ */
660
+ static random() {
661
+ return _PublicKey.from(randomBytes(PUBLIC_KEY_LENGTH));
662
+ }
663
+ static randomOfLength(length) {
664
+ return _PublicKey.from(randomBytes(length));
665
+ }
666
+ static *randomSequence() {
667
+ for (let i = 0; i < 1e4; i++) {
668
+ yield _PublicKey.random();
691
669
  }
670
+ throw new Error("Too many keys requested");
692
671
  }
693
672
  /**
694
- * @example `dxn:type:example.com/type/Contact`
673
+ * Tests if provided values is an instance of PublicKey.
695
674
  */
696
- static fromTypename(typename) {
697
- return new _DXN(_DXN.kind.TYPE, [
698
- typename
699
- ]);
675
+ static isPublicKey(value) {
676
+ return value instanceof _PublicKey;
677
+ }
678
+ /**
679
+ * Asserts that provided values is an instance of PublicKey.
680
+ */
681
+ static assertValidPublicKey(value) {
682
+ if (!this.isPublicKey(value)) {
683
+ throw new TypeError("Invalid PublicKey");
684
+ }
700
685
  }
701
686
  /**
702
- * @example `dxn:type:example.com/type/Contact:0.1.0`
687
+ * Tests two keys for equality.
703
688
  */
704
- // TODO(dmaretskyi): Consider using @ as the version separator.
705
- static fromTypenameAndVersion(typename, version) {
706
- return new _DXN(_DXN.kind.TYPE, [
707
- typename,
708
- version
709
- ]);
689
+ static equals(left, right) {
690
+ return _PublicKey.from(left).equals(right);
710
691
  }
711
692
  /**
712
- * @example `dxn:echo:@:01J00J9B45YHYSGZQTQMSKMGJ6`
693
+ * @param str string representation of key.
694
+ * @return Key buffer.
695
+ * @deprecated All keys should be represented as instances of PublicKey.
713
696
  */
714
- static fromLocalObjectId(id) {
715
- return new _DXN(_DXN.kind.ECHO, [
716
- LOCAL_SPACE_TAG,
717
- id
718
- ]);
719
- }
720
- static fromQueue(subspaceTag, spaceId, queueId, objectId) {
721
- invariant4(SpaceId.isValid(spaceId), void 0, {
722
- F: __dxlog_file4,
723
- L: 146,
724
- S: this,
725
- A: [
726
- "SpaceId.isValid(spaceId)",
727
- ""
728
- ]
729
- });
730
- invariant4(ObjectId.isValid(queueId), void 0, {
731
- F: __dxlog_file4,
732
- L: 147,
733
- S: this,
734
- A: [
735
- "ObjectId.isValid(queueId)",
736
- ""
737
- ]
738
- });
739
- invariant4(!objectId || ObjectId.isValid(objectId), void 0, {
697
+ static bufferize(str) {
698
+ invariant4(typeof str === "string", "Invalid type", {
740
699
  F: __dxlog_file4,
741
- L: 148,
700
+ L: 152,
742
701
  S: this,
743
702
  A: [
744
- "!objectId || ObjectId.isValid(objectId)",
745
- ""
703
+ "typeof str === 'string'",
704
+ "'Invalid type'"
746
705
  ]
747
706
  });
748
- return new _DXN(_DXN.kind.QUEUE, [
749
- subspaceTag,
750
- spaceId,
751
- queueId,
752
- ...objectId ? [
753
- objectId
754
- ] : []
755
- ]);
707
+ const buffer = Buffer2.from(str, "hex");
708
+ return buffer;
756
709
  }
757
- #kind;
758
- #parts;
759
- constructor(kind, parts) {
760
- invariant4(parts.length > 0, void 0, {
761
- F: __dxlog_file4,
762
- L: 157,
763
- S: this,
764
- A: [
765
- "parts.length > 0",
766
- ""
767
- ]
768
- });
769
- invariant4(parts.every((part) => typeof part === "string" && part.length > 0 && part.indexOf(":") === -1), void 0, {
710
+ /**
711
+ * @param key key like data structure (but not PublicKey which should use toString).
712
+ * @return Hex string representation of key.
713
+ * @deprecated All keys should be represented as instances of PublicKey.
714
+ */
715
+ static stringify(key) {
716
+ if (key instanceof _PublicKey) {
717
+ key = key.asBuffer();
718
+ } else if (key instanceof Uint8Array) {
719
+ key = Buffer2.from(key.buffer, key.byteOffset, key.byteLength);
720
+ }
721
+ invariant4(key instanceof Buffer2, "Invalid type", {
770
722
  F: __dxlog_file4,
771
- L: 158,
723
+ L: 171,
772
724
  S: this,
773
725
  A: [
774
- "parts.every((part) => typeof part === 'string' && part.length > 0 && part.indexOf(':') === -1)",
775
- ""
726
+ "key instanceof Buffer",
727
+ "'Invalid type'"
776
728
  ]
777
729
  });
778
- switch (kind) {
779
- case _DXN.kind.TYPE:
780
- if (parts.length > 2) {
781
- throw new Error('Invalid "type" DXN');
782
- }
783
- break;
784
- case _DXN.kind.ECHO:
785
- if (parts.length !== 2) {
786
- throw new Error('Invalid "echo" DXN');
787
- }
788
- break;
789
- }
790
- this.#kind = kind;
791
- this.#parts = parts;
730
+ return key.toString("hex");
792
731
  }
793
- get parts() {
794
- return this.#parts;
732
+ /**
733
+ * To be used with ComplexMap and ComplexSet.
734
+ * Returns a scalar representation for this key.
735
+ */
736
+ static hash(key) {
737
+ return key.toHex();
795
738
  }
796
- // TODO(burdon): Should getters fail?
797
- get typename() {
798
- invariant4(this.#kind === _DXN.kind.TYPE, void 0, {
739
+ static fromMultibase32(encoded) {
740
+ invariant4(encoded.startsWith("B"), "Invalid multibase32 encoding", {
799
741
  F: __dxlog_file4,
800
742
  L: 184,
801
743
  S: this,
802
744
  A: [
803
- "this.#kind === DXN.kind.TYPE",
804
- ""
745
+ "encoded.startsWith('B')",
746
+ "'Invalid multibase32 encoding'"
805
747
  ]
806
748
  });
807
- return this.#parts[0];
749
+ return new _PublicKey(new Uint8Array((0, import_base32_decode3.default)(encoded.slice(1), "RFC4648")));
808
750
  }
809
- hasTypenameOf(typename) {
810
- return this.#kind === _DXN.kind.TYPE && this.#parts.length === 1 && this.#parts[0] === typename;
751
+ constructor(_value) {
752
+ this._value = _value;
753
+ if (!(_value instanceof Uint8Array)) {
754
+ throw new TypeError(`Expected Uint8Array, got: ${_value}`);
755
+ }
811
756
  }
812
- isLocalObjectId() {
813
- return this.#kind === _DXN.kind.ECHO && this.#parts[0] === LOCAL_SPACE_TAG && this.#parts.length === 2;
757
+ toString() {
758
+ return this.toHex();
814
759
  }
815
- asTypeDXN() {
816
- if (this.kind !== _DXN.kind.TYPE) {
817
- return void 0;
818
- }
819
- const [type, version] = this.#parts;
820
- return {
821
- type,
822
- version
823
- };
760
+ toJSON() {
761
+ return this.toHex();
824
762
  }
825
- asEchoDXN() {
826
- if (this.kind !== _DXN.kind.ECHO) {
827
- return void 0;
828
- }
829
- const [spaceId, echoId] = this.#parts;
830
- return {
831
- spaceId: spaceId === LOCAL_SPACE_TAG ? void 0 : spaceId,
832
- echoId
833
- };
763
+ toJSONL() {
764
+ return this.truncate();
834
765
  }
835
- asQueueDXN() {
836
- if (this.kind !== _DXN.kind.QUEUE) {
837
- return void 0;
838
- }
839
- const [subspaceTag, spaceId, queueId, objectId] = this.#parts;
840
- if (typeof queueId !== "string") {
841
- return void 0;
842
- }
843
- return {
844
- subspaceTag,
845
- spaceId,
846
- queueId,
847
- objectId
848
- };
766
+ get length() {
767
+ return this._value.length;
849
768
  }
850
- toString() {
851
- return `dxn:${this.#kind}:${this.#parts.join(":")}`;
769
+ toHex() {
770
+ return this.asBuffer().toString("hex");
771
+ }
772
+ toMultibase32() {
773
+ return "B" + base32Encode(this._value, "RFC4648");
774
+ }
775
+ truncate(length = void 0) {
776
+ return truncateKey(this, length);
777
+ }
778
+ asBuffer() {
779
+ return Buffer2.from(this._value.buffer, this._value.byteOffset, this._value.byteLength);
780
+ }
781
+ asUint8Array() {
782
+ return this._value;
783
+ }
784
+ getInsecureHash(modulo) {
785
+ return Math.abs(this._value.reduce((acc, val) => acc ^ val | 0, 0)) % modulo;
852
786
  }
853
787
  /**
854
788
  * Used by Node.js to get textual representation of this object when it's printed with a `console.log` statement.
855
789
  */
856
790
  [inspectCustom2](depth, options, inspectFn) {
791
+ if (!options.colors || typeof process.stdout.hasColors !== "function" || !process.stdout.hasColors()) {
792
+ return `<PublicKey ${this.truncate()}>`;
793
+ }
857
794
  const printControlCode = (code) => {
858
795
  return `\x1B[${code}m`;
859
796
  };
860
- return printControlCode(inspectFn.colors.blueBright[0]) + this.toString() + printControlCode(inspectFn.colors.reset[0]);
797
+ const colors = [
798
+ "red",
799
+ "green",
800
+ "yellow",
801
+ "blue",
802
+ "magenta",
803
+ "cyan",
804
+ "redBright",
805
+ "greenBright",
806
+ "yellowBright",
807
+ "blueBright",
808
+ "magentaBright",
809
+ "cyanBright",
810
+ "whiteBright"
811
+ ];
812
+ const color = colors[this.getInsecureHash(colors.length)];
813
+ return `PublicKey(${printControlCode(inspectFn.colors[color][0])}${this.truncate()}${printControlCode(inspectFn.colors.reset[0])})`;
861
814
  }
862
815
  get [devtoolsFormatter2]() {
863
816
  return {
864
817
  header: () => {
818
+ const colors = [
819
+ "darkred",
820
+ "green",
821
+ "orange",
822
+ "blue",
823
+ "darkmagenta",
824
+ "darkcyan",
825
+ "red",
826
+ "green",
827
+ "orange",
828
+ "blue",
829
+ "magenta",
830
+ "darkcyan",
831
+ "black"
832
+ ];
833
+ const color = colors[this.getInsecureHash(colors.length)];
865
834
  return [
866
835
  "span",
867
- {
868
- style: "font-weight: bold;"
869
- },
870
- this.toString()
836
+ {},
837
+ [
838
+ "span",
839
+ {},
840
+ "PublicKey("
841
+ ],
842
+ [
843
+ "span",
844
+ {
845
+ style: `color: ${color};`
846
+ },
847
+ this.truncate()
848
+ ],
849
+ [
850
+ "span",
851
+ {},
852
+ ")"
853
+ ]
871
854
  ];
872
855
  }
873
856
  };
874
857
  }
858
+ /**
859
+ * Test this key for equality with some other key.
860
+ */
861
+ equals(other) {
862
+ const otherConverted = _PublicKey.from(other);
863
+ if (this._value.length !== otherConverted._value.length) {
864
+ return false;
865
+ }
866
+ let equal = true;
867
+ for (let i = 0; i < this._value.length; i++) {
868
+ equal &&= this._value[i] === otherConverted._value[i];
869
+ }
870
+ return equal;
871
+ }
872
+ [equalsSymbol](other) {
873
+ if (!_PublicKey.isPublicKey(other)) {
874
+ return false;
875
+ }
876
+ return this.equals(other);
877
+ }
875
878
  };
876
879
  export {
877
880
  DXN,