@milaboratories/pl-client 3.2.5 → 3.3.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.
Files changed (112) hide show
  1. package/dist/core/client.cjs +24 -56
  2. package/dist/core/client.cjs.map +1 -1
  3. package/dist/core/client.d.ts +12 -8
  4. package/dist/core/client.d.ts.map +1 -1
  5. package/dist/core/client.js +26 -58
  6. package/dist/core/client.js.map +1 -1
  7. package/dist/core/errors.cjs +20 -0
  8. package/dist/core/errors.cjs.map +1 -1
  9. package/dist/core/errors.d.ts +6 -1
  10. package/dist/core/errors.d.ts.map +1 -1
  11. package/dist/core/errors.js +19 -1
  12. package/dist/core/errors.js.map +1 -1
  13. package/dist/core/final.cjs +6 -5
  14. package/dist/core/final.cjs.map +1 -1
  15. package/dist/core/final.d.ts.map +1 -1
  16. package/dist/core/final.js +7 -6
  17. package/dist/core/final.js.map +1 -1
  18. package/dist/core/ll_client.cjs +18 -1
  19. package/dist/core/ll_client.cjs.map +1 -1
  20. package/dist/core/ll_client.d.ts +6 -2
  21. package/dist/core/ll_client.d.ts.map +1 -1
  22. package/dist/core/ll_client.js +19 -2
  23. package/dist/core/ll_client.js.map +1 -1
  24. package/dist/core/transaction.cjs +109 -75
  25. package/dist/core/transaction.cjs.map +1 -1
  26. package/dist/core/transaction.d.ts +30 -22
  27. package/dist/core/transaction.d.ts.map +1 -1
  28. package/dist/core/transaction.js +111 -76
  29. package/dist/core/transaction.js.map +1 -1
  30. package/dist/core/type_conversion.cjs +14 -6
  31. package/dist/core/type_conversion.cjs.map +1 -1
  32. package/dist/core/type_conversion.js +14 -6
  33. package/dist/core/type_conversion.js.map +1 -1
  34. package/dist/core/types.cjs +77 -17
  35. package/dist/core/types.cjs.map +1 -1
  36. package/dist/core/types.d.ts +49 -26
  37. package/dist/core/types.d.ts.map +1 -1
  38. package/dist/core/types.js +66 -14
  39. package/dist/core/types.js.map +1 -1
  40. package/dist/core/user_resources.cjs +181 -0
  41. package/dist/core/user_resources.cjs.map +1 -0
  42. package/dist/core/user_resources.d.ts +75 -0
  43. package/dist/core/user_resources.d.ts.map +1 -0
  44. package/dist/core/user_resources.js +180 -0
  45. package/dist/core/user_resources.js.map +1 -0
  46. package/dist/helpers/poll.cjs +4 -4
  47. package/dist/helpers/poll.cjs.map +1 -1
  48. package/dist/helpers/poll.d.ts +3 -3
  49. package/dist/helpers/poll.d.ts.map +1 -1
  50. package/dist/helpers/poll.js +5 -5
  51. package/dist/helpers/poll.js.map +1 -1
  52. package/dist/helpers/tx_helpers.cjs +1 -1
  53. package/dist/helpers/tx_helpers.cjs.map +1 -1
  54. package/dist/helpers/tx_helpers.d.ts +3 -3
  55. package/dist/helpers/tx_helpers.d.ts.map +1 -1
  56. package/dist/helpers/tx_helpers.js +2 -2
  57. package/dist/helpers/tx_helpers.js.map +1 -1
  58. package/dist/index.cjs +16 -5
  59. package/dist/index.d.ts +5 -4
  60. package/dist/index.js +5 -4
  61. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +724 -188
  62. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
  63. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs +34 -9
  64. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs.map +1 -1
  65. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts +37 -5
  66. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts.map +1 -1
  67. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js +34 -9
  68. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js.map +1 -1
  69. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +326 -136
  70. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
  71. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +724 -188
  72. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
  73. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs +18 -7
  74. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs.map +1 -1
  75. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts +11 -7
  76. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts.map +1 -1
  77. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js +18 -7
  78. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js.map +1 -1
  79. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs +57 -2
  80. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs.map +1 -1
  81. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts +26 -3
  82. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts.map +1 -1
  83. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js +57 -3
  84. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js.map +1 -1
  85. package/dist/proto-rest/plapi.d.ts +421 -207
  86. package/dist/proto-rest/plapi.d.ts.map +1 -1
  87. package/dist/test/test_config.cjs +6 -3
  88. package/dist/test/test_config.cjs.map +1 -1
  89. package/dist/test/test_config.d.ts.map +1 -1
  90. package/dist/test/test_config.js +7 -4
  91. package/dist/test/test_config.js.map +1 -1
  92. package/package.json +4 -4
  93. package/src/core/client.ts +58 -103
  94. package/src/core/errors.ts +23 -0
  95. package/src/core/final.ts +16 -6
  96. package/src/core/ll_client.ts +39 -3
  97. package/src/core/ll_transaction.test.ts +41 -6
  98. package/src/core/transaction.ts +176 -86
  99. package/src/core/type_conversion.ts +24 -9
  100. package/src/core/types.ts +147 -41
  101. package/src/core/user_resources.ts +332 -0
  102. package/src/helpers/poll.ts +15 -8
  103. package/src/helpers/state_helpers.ts +2 -2
  104. package/src/helpers/tx_helpers.ts +5 -5
  105. package/src/index.ts +1 -0
  106. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.ts +61 -14
  107. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +1045 -379
  108. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.ts +33 -18
  109. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.ts +75 -6
  110. package/src/proto-grpc/google/protobuf/descriptor.ts +5 -2
  111. package/src/proto-rest/plapi.ts +447 -225
  112. package/src/test/test_config.ts +8 -5
@@ -1,24 +1,28 @@
1
1
  // TODO: fix this
2
2
  /* eslint-disable no-prototype-builtins */
3
3
  import type {
4
- AnyResourceId,
4
+ ColorProof,
5
5
  LocalResourceId,
6
- OptionalResourceId,
6
+ OptionalSignedResourceId,
7
7
  BasicResourceData,
8
8
  FieldData,
9
9
  FieldType,
10
10
  ResourceData,
11
- ResourceId,
11
+ SignedResourceId,
12
+ ResourceSignature,
12
13
  ResourceType,
13
14
  FutureFieldType,
14
15
  } from "./types";
15
16
  import {
17
+ createSignedResourceId,
16
18
  createLocalResourceId,
17
- ensureResourceIdNotNull,
18
- MaxTxId,
19
19
  isLocalResourceId,
20
+ ensureSignedResourceIdNotNull,
21
+ MaxTxId,
20
22
  extractBasicResourceData,
21
- isNullResourceId,
23
+ parseSignedResourceId,
24
+ toResourceSignature,
25
+ isSignedResourceId,
22
26
  } from "./types";
23
27
  import type {
24
28
  ClientMessageRequest,
@@ -51,7 +55,7 @@ import { PromiseTracker } from "./PromiseTracker";
51
55
  export interface ResourceRef {
52
56
  /** Global resource id of newly created resources, become available only
53
57
  * after response for the corresponding creation request is received. */
54
- readonly globalId: Promise<ResourceId>;
58
+ readonly globalId: Promise<SignedResourceId>;
55
59
 
56
60
  /** Transaction-local resource id is assigned right after resource creation
57
61
  * request is sent, and can be used right away */
@@ -77,12 +81,12 @@ interface _FieldId<RId> {
77
81
  fieldName: string;
78
82
  }
79
83
 
80
- export type FieldId = _FieldId<ResourceId>;
84
+ export type FieldId = _FieldId<SignedResourceId>;
81
85
  export type FieldRef = _FieldId<ResourceRef>;
82
86
  export type LocalFieldId = _FieldId<LocalResourceId>;
83
87
  export type AnyFieldId = FieldId | LocalFieldId;
84
88
 
85
- export type AnyResourceRef = ResourceRef | ResourceId;
89
+ export type AnyResourceRef = ResourceRef | LocalResourceId | SignedResourceId;
86
90
  export type AnyFieldRef = _FieldId<AnyResourceRef>; // FieldRef | FieldId
87
91
  export type AnyRef = AnyResourceRef | AnyFieldRef;
88
92
 
@@ -91,21 +95,26 @@ export function isField(ref: AnyRef): ref is AnyFieldRef {
91
95
  }
92
96
 
93
97
  export function isResource(ref: AnyRef): ref is AnyResourceRef {
94
- return (
95
- typeof ref === "bigint" || (ref.hasOwnProperty("globalId") && ref.hasOwnProperty("localId"))
96
- );
98
+ if (typeof ref === "bigint") return true; // LocalResourceId
99
+ if (typeof ref === "string") return true; // SignedResourceId
100
+ return isResourceRef(ref);
97
101
  }
98
102
 
99
- export function isResourceId(ref: AnyRef): ref is ResourceId {
100
- return typeof ref === "bigint" && !isLocalResourceId(ref) && !isNullResourceId(ref);
103
+ export function isResourceId(ref: AnyRef): ref is SignedResourceId {
104
+ return typeof ref === "string" && isSignedResourceId(ref);
101
105
  }
102
106
 
103
107
  export function isFieldRef(ref: AnyFieldRef): ref is FieldRef {
104
108
  return isResourceRef(ref.resourceId);
105
109
  }
106
110
 
107
- export function isResourceRef(ref: AnyResourceRef): ref is ResourceRef {
108
- return ref.hasOwnProperty("globalId") && ref.hasOwnProperty("localId");
111
+ export function isResourceRef(ref: AnyRef): ref is ResourceRef {
112
+ return (
113
+ typeof ref === "object" &&
114
+ ref !== null &&
115
+ ref.hasOwnProperty("globalId") &&
116
+ ref.hasOwnProperty("localId")
117
+ );
109
118
  }
110
119
 
111
120
  export function toFieldId(ref: AnyFieldRef): AnyFieldId {
@@ -113,20 +122,37 @@ export function toFieldId(ref: AnyFieldRef): AnyFieldId {
113
122
  else return ref as FieldId;
114
123
  }
115
124
 
116
- export async function toGlobalFieldId(ref: AnyFieldRef): Promise<FieldId> {
125
+ export async function toGlobalFieldId(ref: FieldRef | FieldId): Promise<FieldId> {
117
126
  if (isFieldRef(ref))
118
127
  return { resourceId: await ref.resourceId.globalId, fieldName: ref.fieldName };
119
- else return ref as FieldId;
128
+ return ref;
120
129
  }
121
130
 
122
- export function toResourceId(ref: AnyResourceRef): AnyResourceId {
123
- if (isResourceRef(ref)) return ref.localId;
124
- else return ref;
131
+ export interface ResourceIdWithSignature {
132
+ resourceId: bigint;
133
+ resourceSignature: ResourceSignature;
125
134
  }
126
135
 
127
- export async function toGlobalResourceId(ref: AnyResourceRef): Promise<ResourceId> {
136
+ const emptySignature = toResourceSignature(new Uint8Array(0));
137
+
138
+ function toResourceIdAndSignature(ref: AnyResourceRef): ResourceIdWithSignature {
139
+ if (isResourceRef(ref)) {
140
+ // Local ID — no signature yet
141
+ return { resourceId: ref.localId, resourceSignature: emptySignature };
142
+ }
143
+ if (isResourceId(ref)) {
144
+ // SignedResourceId — decompose
145
+ const { globalId, signature } = parseSignedResourceId(ref);
146
+ return { resourceId: globalId as bigint, resourceSignature: signature };
147
+ }
148
+ // Raw bigint (LocalResourceId)
149
+ return { resourceId: ref as bigint, resourceSignature: emptySignature };
150
+ }
151
+
152
+ export async function toGlobalResourceId(ref: AnyResourceRef): Promise<SignedResourceId> {
128
153
  if (isResourceRef(ref)) return await ref.globalId;
129
- else return ref;
154
+ if (isLocalResourceId(ref)) return createSignedResourceId(ref); // legacy path: loose security mode in backend
155
+ return ref;
130
156
  }
131
157
 
132
158
  export function field(resourceId: AnyResourceRef, fieldName: string): AnyFieldRef {
@@ -186,9 +212,9 @@ export class PlTransaction {
186
212
  private readonly ll: LLPlTransaction,
187
213
  public readonly name: string,
188
214
  public readonly writable: boolean,
189
- private readonly _clientRoot: OptionalResourceId,
215
+ private readonly _clientRoot: OptionalSignedResourceId,
190
216
  private readonly finalPredicate: FinalResourceDataPredicate,
191
- private readonly sharedResourceDataCache: LRUCache<ResourceId, ResourceDataCacheRecord>,
217
+ private readonly sharedResourceDataCache: LRUCache<SignedResourceId, ResourceDataCacheRecord>,
192
218
  private readonly enableFormattedErrors: boolean = false,
193
219
  ) {
194
220
  // initiating transaction
@@ -276,6 +302,40 @@ export class PlTransaction {
276
302
  void this.track(this.sendVoidSync(r));
277
303
  }
278
304
 
305
+ /** Set default color proof for subsequent resource creation requests */
306
+ public setDefaultColor(colorProof: ColorProof): void {
307
+ this.sendVoidAsync({
308
+ oneofKind: "setDefaultColor",
309
+ setDefaultColor: { colorProof },
310
+ });
311
+ }
312
+
313
+ private toSignedResourceId(rId: AnyResourceRef): ResourceIdWithSignature {
314
+ return toResourceIdAndSignature(rId);
315
+ }
316
+
317
+ private toSignedFieldId(fId: AnyFieldRef): {
318
+ resourceId: bigint;
319
+ resourceSignature: ResourceSignature;
320
+ fieldName: string;
321
+ } {
322
+ const base = toFieldId(fId);
323
+ const signed = toResourceIdAndSignature(base.resourceId);
324
+ return {
325
+ resourceId: signed.resourceId,
326
+ fieldName: base.fieldName,
327
+ resourceSignature: signed.resourceSignature,
328
+ };
329
+ }
330
+
331
+ private toSignedErrorRef(rId: AnyResourceRef): {
332
+ errorResourceId: bigint;
333
+ errorResourceSignature: ResourceSignature;
334
+ } {
335
+ const { resourceId, resourceSignature } = this.toSignedResourceId(rId);
336
+ return { errorResourceId: resourceId, errorResourceSignature: resourceSignature };
337
+ }
338
+
279
339
  private checkTxOpen() {
280
340
  if (this._completed) throw new Error("Transaction already closed");
281
341
  }
@@ -343,8 +403,8 @@ export class PlTransaction {
343
403
  // Main tx methods
344
404
  //
345
405
 
346
- public get clientRoot(): ResourceId {
347
- return ensureResourceIdNotNull(this._clientRoot);
406
+ public get clientRoot(): SignedResourceId {
407
+ return ensureSignedResourceIdNotNull(this._clientRoot);
348
408
  }
349
409
 
350
410
  //
@@ -355,26 +415,23 @@ export class PlTransaction {
355
415
  name: string,
356
416
  type: ResourceType,
357
417
  errorIfExists: boolean = false,
418
+ color?: ColorProof,
358
419
  ): ResourceRef {
359
- const localId = this.nextLocalResourceId(false);
360
-
361
- const globalId = this.sendSingleAndParse(
362
- {
420
+ return this.createResource(
421
+ false,
422
+ (localId) => ({
363
423
  oneofKind: "resourceCreateSingleton",
364
424
  resourceCreateSingleton: {
365
425
  type,
366
426
  id: localId,
367
427
  data: Buffer.from(name),
368
428
  errorIfExists,
369
- colorProof: new Uint8Array(0),
429
+ colorProof: color ?? emptySignature,
370
430
  },
371
- },
372
- (r) => r.resourceCreateSingleton.resourceId as ResourceId,
431
+ }),
432
+ (r) => r.resourceCreateSingleton.resourceId,
433
+ (r) => r.resourceCreateSingleton.resourceSignature,
373
434
  );
374
-
375
- void this.track(globalId);
376
-
377
- return { globalId, localId };
378
435
  }
379
436
 
380
437
  public getSingleton(name: string, loadFields: true): Promise<ResourceData>;
@@ -399,10 +456,15 @@ export class PlTransaction {
399
456
  root: boolean,
400
457
  req: (localId: LocalResourceId) => OneOfKind<ClientMessageRequest, Kind>,
401
458
  parser: (resp: OneOfKind<ServerMessageResponse, Kind>) => bigint,
459
+ sigExtractor: (resp: OneOfKind<ServerMessageResponse, Kind>) => Uint8Array | undefined,
402
460
  ): ResourceRef {
403
461
  const localId = this.nextLocalResourceId(root);
404
462
 
405
- const globalId = this.sendSingleAndParse(req(localId), (r) => parser(r) as ResourceId);
463
+ const globalId = this.sendSingleAndParse(req(localId), (r) => {
464
+ const rawId = parser(r);
465
+ const sig = sigExtractor ? toResourceSignature(sigExtractor(r)) : undefined;
466
+ return createSignedResourceId(rawId, sig);
467
+ });
406
468
 
407
469
  void this.track(globalId);
408
470
 
@@ -415,10 +477,15 @@ export class PlTransaction {
415
477
  true,
416
478
  (localId) => ({ oneofKind: "resourceCreateRoot", resourceCreateRoot: { type, id: localId } }),
417
479
  (r) => r.resourceCreateRoot.resourceId,
480
+ (r) => r.resourceCreateRoot.resourceSignature,
418
481
  );
419
482
  }
420
483
 
421
- public createStruct(type: ResourceType, data?: Uint8Array | string): ResourceRef {
484
+ public createStruct(
485
+ type: ResourceType,
486
+ data?: Uint8Array | string,
487
+ color?: ColorProof,
488
+ ): ResourceRef {
422
489
  this._stat.structsCreated++;
423
490
  this._stat.structsCreatedDataBytes += data?.length ?? 0;
424
491
  return this.createResource(
@@ -430,14 +497,19 @@ export class PlTransaction {
430
497
  id: localId,
431
498
  data:
432
499
  data === undefined ? undefined : typeof data === "string" ? Buffer.from(data) : data,
433
- colorProof: new Uint8Array(0),
500
+ colorProof: color ?? emptySignature,
434
501
  },
435
502
  }),
436
503
  (r) => r.resourceCreateStruct.resourceId,
504
+ (r) => r.resourceCreateStruct.resourceSignature,
437
505
  );
438
506
  }
439
507
 
440
- public createEphemeral(type: ResourceType, data?: Uint8Array | string): ResourceRef {
508
+ public createEphemeral(
509
+ type: ResourceType,
510
+ data?: Uint8Array | string,
511
+ color?: ColorProof,
512
+ ): ResourceRef {
441
513
  this._stat.ephemeralsCreated++;
442
514
  this._stat.ephemeralsCreatedDataBytes += data?.length ?? 0;
443
515
  return this.createResource(
@@ -449,10 +521,11 @@ export class PlTransaction {
449
521
  id: localId,
450
522
  data:
451
523
  data === undefined ? undefined : typeof data === "string" ? Buffer.from(data) : data,
452
- colorProof: new Uint8Array(0),
524
+ colorProof: color ?? emptySignature,
453
525
  },
454
526
  }),
455
527
  (r) => r.resourceCreateEphemeral.resourceId,
528
+ (r) => r.resourceCreateEphemeral.resourceSignature,
456
529
  );
457
530
  }
458
531
 
@@ -460,6 +533,7 @@ export class PlTransaction {
460
533
  type: ResourceType,
461
534
  data: Uint8Array | string,
462
535
  errorIfExists: boolean = false,
536
+ color?: ColorProof,
463
537
  ): ResourceRef {
464
538
  this._stat.valuesCreated++;
465
539
  this._stat.valuesCreatedDataBytes += data?.length ?? 0;
@@ -472,34 +546,41 @@ export class PlTransaction {
472
546
  id: localId,
473
547
  data: typeof data === "string" ? Buffer.from(data) : data,
474
548
  errorIfExists,
475
- colorProof: new Uint8Array(0),
549
+ colorProof: color ?? emptySignature,
476
550
  },
477
551
  }),
478
552
  (r) => r.resourceCreateValue.resourceId,
553
+ (r) => r.resourceCreateValue.resourceSignature,
479
554
  );
480
555
  }
481
556
 
482
- public createJsonValue(data: unknown): ResourceRef {
557
+ public createJsonValue(data: unknown, color?: ColorProof): ResourceRef {
483
558
  const jsonData = canonicalJsonBytes(data);
484
- return this.createValue(JsonObject, jsonData, false);
559
+ return this.createValue(JsonObject, jsonData, false, color);
485
560
  }
486
561
 
487
- public createJsonGzValue(data: unknown, minSizeToGzip: number | undefined = 16_384): ResourceRef {
562
+ public createJsonGzValue(
563
+ data: unknown,
564
+ minSizeToGzip: number | undefined = 16_384,
565
+ color?: ColorProof,
566
+ ): ResourceRef {
488
567
  const { data: jsonData, isGzipped } = canonicalJsonGzBytes(data, minSizeToGzip);
489
- return this.createValue(isGzipped ? JsonGzObject : JsonObject, jsonData, false);
568
+ return this.createValue(isGzipped ? JsonGzObject : JsonObject, jsonData, false, color);
490
569
  }
491
570
 
492
- public createError(message: string): ResourceRef {
571
+ public createError(message: string, color?: ColorProof): ResourceRef {
493
572
  return this.createValue(
494
573
  ErrorResourceType,
495
574
  JSON.stringify({ message } satisfies ErrorResourceData),
575
+ false,
576
+ color,
496
577
  );
497
578
  }
498
579
 
499
580
  public setResourceName(name: string, rId: AnyResourceRef): void {
500
581
  this.sendVoidAsync({
501
582
  oneofKind: "resourceNameSet",
502
- resourceNameSet: { resourceId: toResourceId(rId), name },
583
+ resourceNameSet: { ...this.toSignedResourceId(rId), name },
503
584
  });
504
585
  }
505
586
 
@@ -507,10 +588,15 @@ export class PlTransaction {
507
588
  this.sendVoidAsync({ oneofKind: "resourceNameDelete", resourceNameDelete: { name } });
508
589
  }
509
590
 
510
- public getResourceByName(name: string): Promise<ResourceId> {
591
+ public getResourceByName(name: string): Promise<SignedResourceId> {
511
592
  return this.sendSingleAndParse(
512
593
  { oneofKind: "resourceNameGet", resourceNameGet: { name } },
513
- (r) => ensureResourceIdNotNull(r.resourceNameGet.resourceId as OptionalResourceId),
594
+ (r) => {
595
+ const rawId = r.resourceNameGet.resourceId;
596
+ if (rawId === 0n) throw new Error("null resource id from getResourceByName");
597
+ const sig = toResourceSignature(r.resourceNameGet.resourceSignature);
598
+ return createSignedResourceId(rawId, sig);
599
+ },
514
600
  );
515
601
  }
516
602
 
@@ -521,18 +607,18 @@ export class PlTransaction {
521
607
  );
522
608
  }
523
609
 
524
- public removeResource(rId: ResourceId): void {
610
+ public removeResource(rId: SignedResourceId): void {
525
611
  this.sendVoidAsync({
526
612
  oneofKind: "resourceRemove",
527
- resourceRemove: { resourceId: rId },
613
+ resourceRemove: this.toSignedResourceId(rId),
528
614
  });
529
615
  }
530
616
 
531
- public resourceExists(rId: ResourceId): Promise<boolean> {
617
+ public resourceExists(rId: SignedResourceId): Promise<boolean> {
532
618
  return this.sendSingleAndParse(
533
619
  {
534
620
  oneofKind: "resourceExists",
535
- resourceExists: { resourceId: rId },
621
+ resourceExists: this.toSignedResourceId(rId),
536
622
  },
537
623
  (r) => r.resourceExists.exists,
538
624
  );
@@ -571,7 +657,7 @@ export class PlTransaction {
571
657
  ignoreCache: boolean = false,
572
658
  ): Promise<BasicResourceData | ResourceData> {
573
659
  return this.track(async () => {
574
- if (!ignoreCache && !isResourceRef(rId) && !isLocalResourceId(rId)) {
660
+ if (!ignoreCache && isResourceId(rId)) {
575
661
  // checking if we can return result from cache
576
662
  const fromCache = this.sharedResourceDataCache.get(rId);
577
663
  if (fromCache && fromCache.cacheTxOpenTimestamp < this.txOpenTimestamp) {
@@ -592,7 +678,7 @@ export class PlTransaction {
592
678
  {
593
679
  oneofKind: "resourceGet",
594
680
  resourceGet: {
595
- resourceId: toResourceId(rId),
681
+ ...this.toSignedResourceId(rId),
596
682
  loadFields: loadFields,
597
683
  },
598
684
  },
@@ -605,7 +691,7 @@ export class PlTransaction {
605
691
 
606
692
  // we will cache only final resource data states
607
693
  // caching result even if we were ignore the cache
608
- if (!isResourceRef(rId) && !isLocalResourceId(rId) && this.finalPredicate(result)) {
694
+ if (isResourceId(rId) && this.finalPredicate(result)) {
609
695
  deepFreeze(result);
610
696
  const fromCache = this.sharedResourceDataCache.get(rId);
611
697
  if (fromCache) {
@@ -660,8 +746,7 @@ export class PlTransaction {
660
746
  );
661
747
 
662
748
  // cleaning cache record if resource was removed from the db
663
- if (result === undefined && !isResourceRef(rId) && !isLocalResourceId(rId))
664
- this.sharedResourceDataCache.delete(rId);
749
+ if (result === undefined && isResourceId(rId)) this.sharedResourceDataCache.delete(rId);
665
750
 
666
751
  return result;
667
752
  });
@@ -678,7 +763,7 @@ export class PlTransaction {
678
763
  this._stat.inputsLocked++;
679
764
  this.sendVoidAsync({
680
765
  oneofKind: "resourceLockInputs",
681
- resourceLockInputs: { resourceId: toResourceId(rId), resourceSignature: new Uint8Array(0) },
766
+ resourceLockInputs: this.toSignedResourceId(rId),
682
767
  });
683
768
  }
684
769
 
@@ -690,7 +775,7 @@ export class PlTransaction {
690
775
  this._stat.outputsLocked++;
691
776
  this.sendVoidAsync({
692
777
  oneofKind: "resourceLockOutputs",
693
- resourceLockOutputs: { resourceId: toResourceId(rId), resourceSignature: new Uint8Array(0) },
778
+ resourceLockOutputs: this.toSignedResourceId(rId),
694
779
  });
695
780
  }
696
781
 
@@ -703,8 +788,8 @@ export class PlTransaction {
703
788
  this.sendVoidAsync({
704
789
  oneofKind: "resourceSetError",
705
790
  resourceSetError: {
706
- resourceId: toResourceId(rId),
707
- errorResourceId: toResourceId(ref),
791
+ ...this.toSignedResourceId(rId),
792
+ ...this.toSignedErrorRef(ref),
708
793
  },
709
794
  });
710
795
  }
@@ -717,7 +802,7 @@ export class PlTransaction {
717
802
  this._stat.fieldsCreated++;
718
803
  this.sendVoidAsync({
719
804
  oneofKind: "fieldCreate",
720
- fieldCreate: { type: fieldTypeToProto(fieldType), id: toFieldId(fId) },
805
+ fieldCreate: { type: fieldTypeToProto(fieldType), id: this.toSignedFieldId(fId) },
721
806
  });
722
807
  if (value !== undefined) this.setField(fId, value);
723
808
  }
@@ -726,7 +811,7 @@ export class PlTransaction {
726
811
  return this.sendSingleAndParse(
727
812
  {
728
813
  oneofKind: "fieldExists",
729
- fieldExists: { field: toFieldId(fId) },
814
+ fieldExists: { field: this.toSignedFieldId(fId) },
730
815
  },
731
816
  (r) => r.fieldExists.exists,
732
817
  );
@@ -734,25 +819,26 @@ export class PlTransaction {
734
819
 
735
820
  public setField(fId: AnyFieldRef, ref: AnyRef): void {
736
821
  this._stat.fieldsSet++;
737
- if (isResource(ref))
822
+ if (isResource(ref)) {
738
823
  this.sendVoidAsync({
739
824
  oneofKind: "fieldSet",
740
825
  fieldSet: {
741
- field: toFieldId(fId),
826
+ field: this.toSignedFieldId(fId),
742
827
  value: {
743
- resourceId: toResourceId(ref),
828
+ ...this.toSignedResourceId(ref),
744
829
  fieldName: "", // default value, read as undefined
745
830
  },
746
831
  },
747
832
  });
748
- else
833
+ } else {
749
834
  this.sendVoidAsync({
750
835
  oneofKind: "fieldSet",
751
836
  fieldSet: {
752
- field: toFieldId(fId),
753
- value: toFieldId(ref),
837
+ field: this.toSignedFieldId(fId),
838
+ value: this.toSignedFieldId(ref),
754
839
  },
755
840
  });
841
+ }
756
842
  }
757
843
 
758
844
  public setFieldError(fId: AnyFieldRef, ref: AnyResourceRef): void {
@@ -760,8 +846,8 @@ export class PlTransaction {
760
846
  this.sendVoidAsync({
761
847
  oneofKind: "fieldSetError",
762
848
  fieldSetError: {
763
- field: toFieldId(fId),
764
- errorResourceId: toResourceId(ref),
849
+ field: this.toSignedFieldId(fId),
850
+ ...this.toSignedErrorRef(ref),
765
851
  },
766
852
  });
767
853
  }
@@ -769,7 +855,7 @@ export class PlTransaction {
769
855
  public getField(fId: AnyFieldRef): Promise<FieldData> {
770
856
  this._stat.fieldsGet++;
771
857
  return this.sendSingleAndParse(
772
- { oneofKind: "fieldGet", fieldGet: { field: toFieldId(fId) } },
858
+ { oneofKind: "fieldGet", fieldGet: { field: this.toSignedFieldId(fId) } },
773
859
  (r) => protoToField(notEmpty(r.fieldGet.field)),
774
860
  );
775
861
  }
@@ -779,11 +865,17 @@ export class PlTransaction {
779
865
  }
780
866
 
781
867
  public resetField(fId: AnyFieldRef): void {
782
- this.sendVoidAsync({ oneofKind: "fieldReset", fieldReset: { field: toFieldId(fId) } });
868
+ this.sendVoidAsync({
869
+ oneofKind: "fieldReset",
870
+ fieldReset: { field: this.toSignedFieldId(fId) },
871
+ });
783
872
  }
784
873
 
785
874
  public removeField(fId: AnyFieldRef): void {
786
- this.sendVoidAsync({ oneofKind: "fieldRemove", fieldRemove: { field: toFieldId(fId) } });
875
+ this.sendVoidAsync({
876
+ oneofKind: "fieldRemove",
877
+ fieldRemove: { field: this.toSignedFieldId(fId) },
878
+ });
787
879
  }
788
880
 
789
881
  //
@@ -796,7 +888,7 @@ export class PlTransaction {
796
888
  {
797
889
  oneofKind: "resourceKeyValueList",
798
890
  resourceKeyValueList: {
799
- resourceId: toResourceId(rId),
891
+ ...this.toSignedResourceId(rId),
800
892
  startFrom: "",
801
893
  limit: 0,
802
894
  },
@@ -837,8 +929,7 @@ export class PlTransaction {
837
929
  this.sendVoidAsync({
838
930
  oneofKind: "resourceKeyValueSet",
839
931
  resourceKeyValueSet: {
840
- resourceId: toResourceId(rId),
841
- resourceSignature: new Uint8Array(0),
932
+ ...this.toSignedResourceId(rId),
842
933
  key,
843
934
  value: toBytes(value),
844
935
  },
@@ -849,8 +940,7 @@ export class PlTransaction {
849
940
  this.sendVoidAsync({
850
941
  oneofKind: "resourceKeyValueDelete",
851
942
  resourceKeyValueDelete: {
852
- resourceId: toResourceId(rId),
853
- resourceSignature: new Uint8Array(0),
943
+ ...this.toSignedResourceId(rId),
854
944
  key,
855
945
  },
856
946
  });
@@ -862,7 +952,7 @@ export class PlTransaction {
862
952
  {
863
953
  oneofKind: "resourceKeyValueGet",
864
954
  resourceKeyValueGet: {
865
- resourceId: toResourceId(rId),
955
+ ...this.toSignedResourceId(rId),
866
956
  key,
867
957
  },
868
958
  },
@@ -893,7 +983,7 @@ export class PlTransaction {
893
983
  {
894
984
  oneofKind: "resourceKeyValueGetIfExists",
895
985
  resourceKeyValueGetIfExists: {
896
- resourceId: toResourceId(rId),
986
+ ...this.toSignedResourceId(rId),
897
987
  key,
898
988
  },
899
989
  },
@@ -920,7 +1010,7 @@ export class PlTransaction {
920
1010
 
921
1011
  public async getKValueJsonIfExists<T>(rId: AnyResourceRef, key: string): Promise<T | undefined> {
922
1012
  return this.track(async () => {
923
- const str = await this.getKValueString(rId, key);
1013
+ const str = await this.getKValueStringIfExists(rId, key);
924
1014
  if (str === undefined) return undefined;
925
1015
  return JSON.parse(str) as T;
926
1016
  });
@@ -10,13 +10,17 @@ import { FieldType as GrpcFieldType } from "../proto-grpc/github.com/milaborator
10
10
  import type {
11
11
  FieldData,
12
12
  FieldStatus,
13
- OptionalResourceId,
13
+ OptionalSignedResourceId,
14
14
  FieldType,
15
15
  ResourceData,
16
- ResourceId,
17
16
  ResourceKind,
18
17
  } from "./types";
19
- import { NullResourceId } from "./types";
18
+ import {
19
+ createSignedResourceId,
20
+ NullSignedResourceId,
21
+ toResourceSignature,
22
+ NullResourceId,
23
+ } from "./types";
20
24
  import { assertNever, notEmpty } from "@milaboratories/ts-helpers";
21
25
  import { throwPlNotFoundError } from "./errors";
22
26
 
@@ -26,12 +30,20 @@ function resourceIsDeleted(proto: Resource): boolean {
26
30
  return proto.deletedTime !== undefined && proto.deletedTime.seconds !== 0n;
27
31
  }
28
32
 
33
+ function protoIdToOptionalResourceId(id: bigint, signature?: Uint8Array): OptionalSignedResourceId {
34
+ if (id === NullResourceId) return NullSignedResourceId;
35
+ return createSignedResourceId(id, toResourceSignature(signature));
36
+ }
37
+
29
38
  /** Throws "native" pl not found error, if resource is marked as deleted. */
30
39
  export function protoToResource(proto: Resource): ResourceData {
31
40
  if (resourceIsDeleted(proto)) throwPlNotFoundError("resource deleted");
32
41
  return {
33
- id: proto.resourceId as ResourceId,
34
- originalResourceId: proto.originalResourceId as OptionalResourceId,
42
+ id: createSignedResourceId(proto.resourceId, toResourceSignature(proto.resourceSignature)),
43
+ originalResourceId: protoIdToOptionalResourceId(
44
+ proto.originalResourceId,
45
+ proto.originalResourceSignature,
46
+ ),
35
47
  type: notEmpty(proto.type),
36
48
  data: proto.data,
37
49
  inputsLocked: proto.inputsLocked,
@@ -55,9 +67,12 @@ function protoToResourceKind(proto: Resource_Kind): ResourceKind {
55
67
  throw new Error("invalid ResourceKind: " + proto);
56
68
  }
57
69
 
58
- function protoToError(proto: Resource): OptionalResourceId {
70
+ function protoToError(proto: Resource): OptionalSignedResourceId {
59
71
  const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);
60
- return (f?.error ?? NullResourceId) as OptionalResourceId;
72
+ if (!f) return NullSignedResourceId;
73
+ const errId = f.error ?? 0n;
74
+ if (errId === 0n) return NullSignedResourceId;
75
+ return createSignedResourceId(errId, toResourceSignature(f.errorSignature));
61
76
  }
62
77
 
63
78
  export function protoToField(proto: Field): FieldData {
@@ -65,8 +80,8 @@ export function protoToField(proto: Field): FieldData {
65
80
  name: notEmpty(proto.id?.fieldName),
66
81
  type: protoToFieldType(proto.type),
67
82
  status: protoToFieldStatus(proto.valueStatus),
68
- value: proto.value as OptionalResourceId,
69
- error: proto.error as OptionalResourceId,
83
+ value: protoIdToOptionalResourceId(proto.value, proto.valueSignature),
84
+ error: protoIdToOptionalResourceId(proto.error, proto.errorSignature),
70
85
  valueIsFinal: proto.valueIsFinal,
71
86
  };
72
87
  }