@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 +1 @@
1
- {"version":3,"file":"transaction.js","names":[],"sources":["../../src/core/transaction.ts"],"sourcesContent":["// TODO: fix this\n/* eslint-disable no-prototype-builtins */\nimport type {\n AnyResourceId,\n LocalResourceId,\n OptionalResourceId,\n BasicResourceData,\n FieldData,\n FieldType,\n ResourceData,\n ResourceId,\n ResourceType,\n FutureFieldType,\n} from \"./types\";\nimport {\n createLocalResourceId,\n ensureResourceIdNotNull,\n MaxTxId,\n isLocalResourceId,\n extractBasicResourceData,\n isNullResourceId,\n} from \"./types\";\nimport type {\n ClientMessageRequest,\n LLPlTransaction,\n OneOfKind,\n ServerMessageResponse,\n} from \"./ll_transaction\";\nimport { TxAPI_Open_Request_WritableTx } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport type { NonUndefined } from \"utility-types\";\nimport { toBytes } from \"../util/util\";\nimport { fieldTypeToProto, protoToField, protoToResource } from \"./type_conversion\";\nimport {\n canonicalJsonBytes,\n canonicalJsonGzBytes,\n deepFreeze,\n notEmpty,\n} from \"@milaboratories/ts-helpers\";\nimport { isNotFoundError } from \"./errors\";\nimport type { FinalResourceDataPredicate } from \"./final\";\nimport type { LRUCache } from \"lru-cache\";\nimport type { ResourceDataCacheRecord } from \"./cache\";\nimport type { TxStat } from \"./stat\";\nimport { initialTxStatWithoutTime } from \"./stat\";\nimport type { ErrorResourceData } from \"./error_resource\";\nimport { ErrorResourceType } from \"./error_resource\";\nimport { JsonGzObject, JsonObject } from \"../helpers/pl\";\nimport { PromiseTracker } from \"./PromiseTracker\";\n\n/** Reference to resource, used only within transaction */\nexport interface ResourceRef {\n /** Global resource id of newly created resources, become available only\n * after response for the corresponding creation request is received. */\n readonly globalId: Promise<ResourceId>;\n\n /** Transaction-local resource id is assigned right after resource creation\n * request is sent, and can be used right away */\n readonly localId: LocalResourceId;\n}\n\n/** Key-Value pair from resource-attached KV storage */\nexport interface KeyValue {\n key: string;\n value: Uint8Array;\n}\n\n/** Key-Value pair from resource-attached KV storage */\nexport interface KeyValueString {\n key: string;\n value: string;\n}\n\ninterface _FieldId<RId> {\n /** Parent resource id */\n resourceId: RId;\n /** Field name */\n fieldName: string;\n}\n\nexport type FieldId = _FieldId<ResourceId>;\nexport type FieldRef = _FieldId<ResourceRef>;\nexport type LocalFieldId = _FieldId<LocalResourceId>;\nexport type AnyFieldId = FieldId | LocalFieldId;\n\nexport type AnyResourceRef = ResourceRef | ResourceId;\nexport type AnyFieldRef = _FieldId<AnyResourceRef>; // FieldRef | FieldId\nexport type AnyRef = AnyResourceRef | AnyFieldRef;\n\nexport function isField(ref: AnyRef): ref is AnyFieldRef {\n return ref.hasOwnProperty(\"resourceId\") && ref.hasOwnProperty(\"fieldName\");\n}\n\nexport function isResource(ref: AnyRef): ref is AnyResourceRef {\n return (\n typeof ref === \"bigint\" || (ref.hasOwnProperty(\"globalId\") && ref.hasOwnProperty(\"localId\"))\n );\n}\n\nexport function isResourceId(ref: AnyRef): ref is ResourceId {\n return typeof ref === \"bigint\" && !isLocalResourceId(ref) && !isNullResourceId(ref);\n}\n\nexport function isFieldRef(ref: AnyFieldRef): ref is FieldRef {\n return isResourceRef(ref.resourceId);\n}\n\nexport function isResourceRef(ref: AnyResourceRef): ref is ResourceRef {\n return ref.hasOwnProperty(\"globalId\") && ref.hasOwnProperty(\"localId\");\n}\n\nexport function toFieldId(ref: AnyFieldRef): AnyFieldId {\n if (isFieldRef(ref)) return { resourceId: ref.resourceId.localId, fieldName: ref.fieldName };\n else return ref as FieldId;\n}\n\nexport async function toGlobalFieldId(ref: AnyFieldRef): Promise<FieldId> {\n if (isFieldRef(ref))\n return { resourceId: await ref.resourceId.globalId, fieldName: ref.fieldName };\n else return ref as FieldId;\n}\n\nexport function toResourceId(ref: AnyResourceRef): AnyResourceId {\n if (isResourceRef(ref)) return ref.localId;\n else return ref;\n}\n\nexport async function toGlobalResourceId(ref: AnyResourceRef): Promise<ResourceId> {\n if (isResourceRef(ref)) return await ref.globalId;\n else return ref;\n}\n\nexport function field(resourceId: AnyResourceRef, fieldName: string): AnyFieldRef {\n return { resourceId, fieldName };\n}\n\n/** If transaction commit failed due to write conflicts */\nexport class TxCommitConflict extends Error {\n name = \"TxCommitConflict\";\n}\n\nasync function notFoundToUndefined<T>(cb: () => Promise<T>): Promise<T | undefined> {\n try {\n return await cb();\n } catch (e) {\n if (isNotFoundError(e)) return undefined;\n throw e;\n }\n}\n\n/**\n * Each platform transaction has 3 stages:\n * - initialization (txOpen message -> txInfo response)\n * - communication (create resources, fields, references and so on)\n * - finalization (txCommit or txDiscard message)\n *\n * This class encapsulates finalization stage and provides ready-to-communication transaction object.\n * */\nexport class PlTransaction {\n private readonly globalTxId: Promise<bigint>;\n private readonly localTxId: number = PlTransaction.nextLocalTxId();\n\n /** Used in caching */\n private readonly txOpenTimestamp = Date.now();\n\n private localResourceIdCounter = 0;\n\n /** Store logical tx open / closed state to prevent invalid sequence of requests.\n * True means output stream was completed.\n * Contract: there must be no async operations between setting this field to true and sending complete signal to stream. */\n private _completed = false;\n\n private globalTxIdWasAwaited: boolean = false;\n\n public readonly pending = new PromiseTracker();\n\n private readonly _startTime = Date.now();\n private readonly _stat = initialTxStatWithoutTime();\n public get stat(): TxStat {\n return {\n ...this._stat,\n timeMs: Date.now() - this._startTime,\n };\n }\n\n constructor(\n private readonly ll: LLPlTransaction,\n public readonly name: string,\n public readonly writable: boolean,\n private readonly _clientRoot: OptionalResourceId,\n private readonly finalPredicate: FinalResourceDataPredicate,\n private readonly sharedResourceDataCache: LRUCache<ResourceId, ResourceDataCacheRecord>,\n private readonly enableFormattedErrors: boolean = false,\n ) {\n // initiating transaction\n this.globalTxId = this.sendSingleAndParse(\n {\n oneofKind: \"txOpen\",\n txOpen: {\n name,\n enableFormattedErrors,\n writable: writable\n ? TxAPI_Open_Request_WritableTx.WRITABLE\n : TxAPI_Open_Request_WritableTx.NOT_WRITABLE,\n },\n },\n (r) => notEmpty(r.txOpen.tx?.id),\n );\n\n void this.track(this.globalTxId);\n\n // To avoid floating promise\n this.globalTxId.catch((err) => {\n if (!this.globalTxIdWasAwaited) {\n console.warn(err);\n }\n });\n\n // Adding stats\n this._stat.txCount++;\n }\n\n /**\n * Collect all pending promises for the transaction finalization.\n */\n public track<T>(promiseOrCallback: Promise<T> | (() => Promise<T>)): Promise<T> {\n return this.pending.track(promiseOrCallback);\n }\n\n private async drainAndAwaitPendingOps(): Promise<void> {\n // awaiting these pending operations first, to catch any errors\n await this.pending.awaitAll();\n }\n\n private sendSingleAndParse<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>, T>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n parser: (resp: OneOfKind<ServerMessageResponse, Kind>) => T,\n ): Promise<T> {\n return this.pending.track(async () => {\n const rawResponsePromise = this.ll.send(r, false);\n\n void this.pending.track(rawResponsePromise);\n\n await this.drainAndAwaitPendingOps();\n\n // awaiting our result, and parsing the response\n return parser(await rawResponsePromise);\n });\n }\n\n private sendMultiAndParse<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>, T>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n parser: (resp: OneOfKind<ServerMessageResponse, Kind>[]) => T,\n ): Promise<T> {\n return this.pending.track(async () => {\n const rawResponsePromise = this.ll.send(r, true);\n\n void this.pending.track(rawResponsePromise);\n\n await this.drainAndAwaitPendingOps();\n\n // awaiting our result, and parsing the response\n return parser(await rawResponsePromise);\n });\n }\n\n private async sendVoidSync<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n ): Promise<void> {\n await this.ll.send(r, false);\n }\n\n /** Requests sent with this method should never produce recoverable errors */\n private sendVoidAsync<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n ): void {\n void this.track(this.sendVoidSync(r));\n }\n\n private checkTxOpen() {\n if (this._completed) throw new Error(\"Transaction already closed\");\n }\n\n public get completed() {\n return this._completed;\n }\n\n /** Commit & closes transaction. {@link TxCommitConflict} is thrown on\n * commit conflicts. */\n public async commit() {\n this.checkTxOpen();\n\n // tx will accept no requests after this one\n this._completed = true;\n\n if (!this.writable) {\n // no need to explicitly commit or reject read-only tx\n const completeResult = this.track(this.ll.complete());\n await this.drainAndAwaitPendingOps();\n await completeResult;\n await this.ll.await();\n } else {\n const commitResponse = this.track(\n this.sendSingleAndParse({ oneofKind: \"txCommit\", txCommit: {} }, (r) => r.txCommit.success),\n );\n\n // send closing frame right after commit to save some time on round-trips\n const completeResult = this.track(this.ll.complete());\n\n // now when we pushed all packets into the stream, we should wait for any\n // pending void operations from before, to catch any errors\n await this.drainAndAwaitPendingOps();\n\n if (!(await commitResponse)) throw new TxCommitConflict();\n\n await completeResult;\n\n // await event-loop completion\n await this.ll.await();\n }\n }\n\n public async discard() {\n this.checkTxOpen();\n\n // tx will accept no requests after this one\n this._completed = true;\n\n const discardResponse = this.sendVoidSync({ oneofKind: \"txDiscard\", txDiscard: {} });\n void this.track(discardResponse);\n // send closing frame right after commit to save some time on round-trips\n const completeResult = this.track(this.ll.complete());\n\n // now when we pushed all packets into the stream, we should wait for any\n // pending void operations from before, to catch any errors\n await this.drainAndAwaitPendingOps();\n\n await discardResponse;\n await completeResult;\n await this.ll.await();\n }\n\n //\n // Main tx methods\n //\n\n public get clientRoot(): ResourceId {\n return ensureResourceIdNotNull(this._clientRoot);\n }\n\n //\n // Resources\n //\n\n public createSingleton(\n name: string,\n type: ResourceType,\n errorIfExists: boolean = false,\n ): ResourceRef {\n const localId = this.nextLocalResourceId(false);\n\n const globalId = this.sendSingleAndParse(\n {\n oneofKind: \"resourceCreateSingleton\",\n resourceCreateSingleton: {\n type,\n id: localId,\n data: Buffer.from(name),\n errorIfExists,\n colorProof: new Uint8Array(0),\n },\n },\n (r) => r.resourceCreateSingleton.resourceId as ResourceId,\n );\n\n void this.track(globalId);\n\n return { globalId, localId };\n }\n\n public getSingleton(name: string, loadFields: true): Promise<ResourceData>;\n public getSingleton(name: string, loadFields: false): Promise<BasicResourceData>;\n public getSingleton(\n name: string,\n loadFields: boolean = true,\n ): Promise<BasicResourceData | ResourceData> {\n return this.sendSingleAndParse(\n {\n oneofKind: \"resourceGetSingleton\",\n resourceGetSingleton: {\n data: Buffer.from(name),\n loadFields,\n },\n },\n (r) => protoToResource(notEmpty(r.resourceGetSingleton.resource)),\n );\n }\n\n private createResource<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>>(\n root: boolean,\n req: (localId: LocalResourceId) => OneOfKind<ClientMessageRequest, Kind>,\n parser: (resp: OneOfKind<ServerMessageResponse, Kind>) => bigint,\n ): ResourceRef {\n const localId = this.nextLocalResourceId(root);\n\n const globalId = this.sendSingleAndParse(req(localId), (r) => parser(r) as ResourceId);\n\n void this.track(globalId);\n\n return { globalId, localId };\n }\n\n public createRoot(type: ResourceType): ResourceRef {\n this._stat.rootsCreated++;\n return this.createResource(\n true,\n (localId) => ({ oneofKind: \"resourceCreateRoot\", resourceCreateRoot: { type, id: localId } }),\n (r) => r.resourceCreateRoot.resourceId,\n );\n }\n\n public createStruct(type: ResourceType, data?: Uint8Array | string): ResourceRef {\n this._stat.structsCreated++;\n this._stat.structsCreatedDataBytes += data?.length ?? 0;\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateStruct\",\n resourceCreateStruct: {\n type,\n id: localId,\n data:\n data === undefined ? undefined : typeof data === \"string\" ? Buffer.from(data) : data,\n colorProof: new Uint8Array(0),\n },\n }),\n (r) => r.resourceCreateStruct.resourceId,\n );\n }\n\n public createEphemeral(type: ResourceType, data?: Uint8Array | string): ResourceRef {\n this._stat.ephemeralsCreated++;\n this._stat.ephemeralsCreatedDataBytes += data?.length ?? 0;\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateEphemeral\",\n resourceCreateEphemeral: {\n type,\n id: localId,\n data:\n data === undefined ? undefined : typeof data === \"string\" ? Buffer.from(data) : data,\n colorProof: new Uint8Array(0),\n },\n }),\n (r) => r.resourceCreateEphemeral.resourceId,\n );\n }\n\n public createValue(\n type: ResourceType,\n data: Uint8Array | string,\n errorIfExists: boolean = false,\n ): ResourceRef {\n this._stat.valuesCreated++;\n this._stat.valuesCreatedDataBytes += data?.length ?? 0;\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateValue\",\n resourceCreateValue: {\n type,\n id: localId,\n data: typeof data === \"string\" ? Buffer.from(data) : data,\n errorIfExists,\n colorProof: new Uint8Array(0),\n },\n }),\n (r) => r.resourceCreateValue.resourceId,\n );\n }\n\n public createJsonValue(data: unknown): ResourceRef {\n const jsonData = canonicalJsonBytes(data);\n return this.createValue(JsonObject, jsonData, false);\n }\n\n public createJsonGzValue(data: unknown, minSizeToGzip: number | undefined = 16_384): ResourceRef {\n const { data: jsonData, isGzipped } = canonicalJsonGzBytes(data, minSizeToGzip);\n return this.createValue(isGzipped ? JsonGzObject : JsonObject, jsonData, false);\n }\n\n public createError(message: string): ResourceRef {\n return this.createValue(\n ErrorResourceType,\n JSON.stringify({ message } satisfies ErrorResourceData),\n );\n }\n\n public setResourceName(name: string, rId: AnyResourceRef): void {\n this.sendVoidAsync({\n oneofKind: \"resourceNameSet\",\n resourceNameSet: { resourceId: toResourceId(rId), name },\n });\n }\n\n public deleteResourceName(name: string): void {\n this.sendVoidAsync({ oneofKind: \"resourceNameDelete\", resourceNameDelete: { name } });\n }\n\n public getResourceByName(name: string): Promise<ResourceId> {\n return this.sendSingleAndParse(\n { oneofKind: \"resourceNameGet\", resourceNameGet: { name } },\n (r) => ensureResourceIdNotNull(r.resourceNameGet.resourceId as OptionalResourceId),\n );\n }\n\n public checkResourceNameExists(name: string): Promise<boolean> {\n return this.sendSingleAndParse(\n { oneofKind: \"resourceNameExists\", resourceNameExists: { name } },\n (r) => r.resourceNameExists.exists,\n );\n }\n\n public removeResource(rId: ResourceId): void {\n this.sendVoidAsync({\n oneofKind: \"resourceRemove\",\n resourceRemove: { resourceId: rId },\n });\n }\n\n public resourceExists(rId: ResourceId): Promise<boolean> {\n return this.sendSingleAndParse(\n {\n oneofKind: \"resourceExists\",\n resourceExists: { resourceId: rId },\n },\n (r) => r.resourceExists.exists,\n );\n }\n\n /** This method may return stale resource state from cache if resource was removed */\n public async getResourceData(rId: AnyResourceRef, loadFields: true): Promise<ResourceData>;\n /** This method may return stale resource state from cache if resource was removed */\n public async getResourceData(rId: AnyResourceRef, loadFields: false): Promise<BasicResourceData>;\n /** This method may return stale resource state from cache if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: boolean,\n ): Promise<BasicResourceData | ResourceData>;\n /** This method may return stale resource state from cache if ignoreCache == false if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: true,\n ignoreCache: boolean,\n ): Promise<ResourceData>;\n /** This method may return stale resource state from cache if ignoreCache == false if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: false,\n ignoreCache: boolean,\n ): Promise<BasicResourceData>;\n /** This method may return stale resource state from cache if ignoreCache == false if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: boolean,\n ignoreCache: boolean,\n ): Promise<BasicResourceData | ResourceData>;\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: boolean = true,\n ignoreCache: boolean = false,\n ): Promise<BasicResourceData | ResourceData> {\n return this.track(async () => {\n if (!ignoreCache && !isResourceRef(rId) && !isLocalResourceId(rId)) {\n // checking if we can return result from cache\n const fromCache = this.sharedResourceDataCache.get(rId);\n if (fromCache && fromCache.cacheTxOpenTimestamp < this.txOpenTimestamp) {\n if (!loadFields) {\n this._stat.rGetDataCacheHits++;\n this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;\n return fromCache.basicData;\n } else if (fromCache.data) {\n this._stat.rGetDataCacheHits++;\n this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;\n this._stat.rGetDataCacheFields += fromCache.data.fields.length;\n return fromCache.data;\n }\n }\n }\n\n const result = await this.sendSingleAndParse(\n {\n oneofKind: \"resourceGet\",\n resourceGet: {\n resourceId: toResourceId(rId),\n loadFields: loadFields,\n },\n },\n (r) => protoToResource(notEmpty(r.resourceGet.resource)),\n );\n\n this._stat.rGetDataNetRequests++;\n this._stat.rGetDataNetBytes += result.data?.length ?? 0;\n this._stat.rGetDataNetFields += result.fields.length;\n\n // we will cache only final resource data states\n // caching result even if we were ignore the cache\n if (!isResourceRef(rId) && !isLocalResourceId(rId) && this.finalPredicate(result)) {\n deepFreeze(result);\n const fromCache = this.sharedResourceDataCache.get(rId);\n if (fromCache) {\n if (loadFields && !fromCache.data) {\n fromCache.data = result;\n // updating timestamp because we updated the record\n fromCache.cacheTxOpenTimestamp = this.txOpenTimestamp;\n }\n } else {\n const basicData = extractBasicResourceData(result);\n deepFreeze(basicData);\n if (loadFields)\n this.sharedResourceDataCache.set(rId, {\n basicData,\n data: result,\n cacheTxOpenTimestamp: this.txOpenTimestamp,\n });\n else\n this.sharedResourceDataCache.set(rId, {\n basicData,\n data: undefined,\n cacheTxOpenTimestamp: this.txOpenTimestamp,\n });\n }\n }\n\n return result;\n });\n }\n\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: true,\n ): Promise<ResourceData | undefined>;\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: false,\n ): Promise<BasicResourceData | undefined>;\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: boolean,\n ): Promise<BasicResourceData | ResourceData | undefined>;\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: boolean = true,\n ): Promise<BasicResourceData | ResourceData | undefined> {\n return this.track(async () => {\n // calling this method will ignore cache, because user intention is to detect resource absence\n // which cache will prevent\n const result = await notFoundToUndefined(\n async () => await this.getResourceData(rId, loadFields, true),\n );\n\n // cleaning cache record if resource was removed from the db\n if (result === undefined && !isResourceRef(rId) && !isLocalResourceId(rId))\n this.sharedResourceDataCache.delete(rId);\n\n return result;\n });\n }\n\n /**\n * Inform platform that resource will not get any new input fields.\n * This is required, when client creates resource without schema and wants\n * controller to start calculations.\n * Most controllers will not start calculations even when all inputs\n * have their values, if inputs list is not locked.\n */\n public lockInputs(rId: AnyResourceRef): void {\n this._stat.inputsLocked++;\n this.sendVoidAsync({\n oneofKind: \"resourceLockInputs\",\n resourceLockInputs: { resourceId: toResourceId(rId), resourceSignature: new Uint8Array(0) },\n });\n }\n\n /**\n * Inform platform that resource will not get any new output fields.\n * This is required for resource to pass deduplication.\n */\n public lockOutputs(rId: AnyResourceRef): void {\n this._stat.outputsLocked++;\n this.sendVoidAsync({\n oneofKind: \"resourceLockOutputs\",\n resourceLockOutputs: { resourceId: toResourceId(rId), resourceSignature: new Uint8Array(0) },\n });\n }\n\n public lock(rID: AnyResourceRef): void {\n this.lockInputs(rID);\n this.lockOutputs(rID);\n }\n\n public setResourceError(rId: AnyResourceRef, ref: AnyResourceRef): void {\n this.sendVoidAsync({\n oneofKind: \"resourceSetError\",\n resourceSetError: {\n resourceId: toResourceId(rId),\n errorResourceId: toResourceId(ref),\n },\n });\n }\n\n //\n // Fields\n //\n\n public createField(fId: AnyFieldRef, fieldType: FieldType, value?: AnyRef): void {\n this._stat.fieldsCreated++;\n this.sendVoidAsync({\n oneofKind: \"fieldCreate\",\n fieldCreate: { type: fieldTypeToProto(fieldType), id: toFieldId(fId) },\n });\n if (value !== undefined) this.setField(fId, value);\n }\n\n public fieldExists(fId: AnyFieldRef): Promise<boolean> {\n return this.sendSingleAndParse(\n {\n oneofKind: \"fieldExists\",\n fieldExists: { field: toFieldId(fId) },\n },\n (r) => r.fieldExists.exists,\n );\n }\n\n public setField(fId: AnyFieldRef, ref: AnyRef): void {\n this._stat.fieldsSet++;\n if (isResource(ref))\n this.sendVoidAsync({\n oneofKind: \"fieldSet\",\n fieldSet: {\n field: toFieldId(fId),\n value: {\n resourceId: toResourceId(ref),\n fieldName: \"\", // default value, read as undefined\n },\n },\n });\n else\n this.sendVoidAsync({\n oneofKind: \"fieldSet\",\n fieldSet: {\n field: toFieldId(fId),\n value: toFieldId(ref),\n },\n });\n }\n\n public setFieldError(fId: AnyFieldRef, ref: AnyResourceRef): void {\n this._stat.fieldsSet++;\n this.sendVoidAsync({\n oneofKind: \"fieldSetError\",\n fieldSetError: {\n field: toFieldId(fId),\n errorResourceId: toResourceId(ref),\n },\n });\n }\n\n public getField(fId: AnyFieldRef): Promise<FieldData> {\n this._stat.fieldsGet++;\n return this.sendSingleAndParse(\n { oneofKind: \"fieldGet\", fieldGet: { field: toFieldId(fId) } },\n (r) => protoToField(notEmpty(r.fieldGet.field)),\n );\n }\n\n public async getFieldIfExists(fId: AnyFieldRef): Promise<FieldData | undefined> {\n return this.track(notFoundToUndefined(async () => await this.getField(fId)));\n }\n\n public resetField(fId: AnyFieldRef): void {\n this.sendVoidAsync({ oneofKind: \"fieldReset\", fieldReset: { field: toFieldId(fId) } });\n }\n\n public removeField(fId: AnyFieldRef): void {\n this.sendVoidAsync({ oneofKind: \"fieldRemove\", fieldRemove: { field: toFieldId(fId) } });\n }\n\n //\n // KV\n //\n\n public async listKeyValues(rId: AnyResourceRef): Promise<KeyValue[]> {\n return this.track(async () => {\n const result = await this.sendMultiAndParse(\n {\n oneofKind: \"resourceKeyValueList\",\n resourceKeyValueList: {\n resourceId: toResourceId(rId),\n startFrom: \"\",\n limit: 0,\n },\n },\n (r) => r.map((e) => e.resourceKeyValueList.record!),\n );\n\n this._stat.kvListRequests++;\n this._stat.kvListEntries += result.length;\n for (const kv of result) this._stat.kvListBytes += kv.key.length + kv.value.length;\n\n return result;\n });\n }\n\n public async listKeyValuesString(rId: AnyResourceRef): Promise<KeyValueString[]> {\n return this.track(async () =>\n (await this.listKeyValues(rId)).map(({ key, value }) => ({\n key,\n value: Buffer.from(value).toString(),\n })),\n );\n }\n\n public async listKeyValuesIfResourceExists(rId: AnyResourceRef): Promise<KeyValue[] | undefined> {\n return this.track(notFoundToUndefined(async () => await this.listKeyValues(rId)));\n }\n\n public async listKeyValuesStringIfResourceExists(\n rId: AnyResourceRef,\n ): Promise<KeyValueString[] | undefined> {\n return this.track(notFoundToUndefined(async () => await this.listKeyValuesString(rId)));\n }\n\n public setKValue(rId: AnyResourceRef, key: string, value: Uint8Array | string): void {\n this._stat.kvSetRequests++;\n this._stat.kvSetBytes++;\n this.sendVoidAsync({\n oneofKind: \"resourceKeyValueSet\",\n resourceKeyValueSet: {\n resourceId: toResourceId(rId),\n resourceSignature: new Uint8Array(0),\n key,\n value: toBytes(value),\n },\n });\n }\n\n public deleteKValue(rId: AnyResourceRef, key: string): void {\n this.sendVoidAsync({\n oneofKind: \"resourceKeyValueDelete\",\n resourceKeyValueDelete: {\n resourceId: toResourceId(rId),\n resourceSignature: new Uint8Array(0),\n key,\n },\n });\n }\n\n public async getKValue(rId: AnyResourceRef, key: string): Promise<Uint8Array> {\n return this.track(async () => {\n const result = await this.sendSingleAndParse(\n {\n oneofKind: \"resourceKeyValueGet\",\n resourceKeyValueGet: {\n resourceId: toResourceId(rId),\n key,\n },\n },\n (r) => r.resourceKeyValueGet.value,\n );\n\n this._stat.kvGetRequests++;\n this._stat.kvGetBytes += result.length;\n\n return result;\n });\n }\n\n public async getKValueString(rId: AnyResourceRef, key: string): Promise<string> {\n return this.track(async () => Buffer.from(await this.getKValue(rId, key)).toString());\n }\n\n public async getKValueJson<T>(rId: AnyResourceRef, key: string): Promise<T> {\n return this.track(async () => JSON.parse(await this.getKValueString(rId, key)) as T);\n }\n\n public async getKValueIfExists(\n rId: AnyResourceRef,\n key: string,\n ): Promise<Uint8Array | undefined> {\n return this.track(async () => {\n const result = await this.sendSingleAndParse(\n {\n oneofKind: \"resourceKeyValueGetIfExists\",\n resourceKeyValueGetIfExists: {\n resourceId: toResourceId(rId),\n key,\n },\n },\n (r) =>\n r.resourceKeyValueGetIfExists.exists ? r.resourceKeyValueGetIfExists.value : undefined,\n );\n\n this._stat.kvGetRequests++;\n this._stat.kvGetBytes += result?.length ?? 0;\n\n return result;\n });\n }\n\n public async getKValueStringIfExists(\n rId: AnyResourceRef,\n key: string,\n ): Promise<string | undefined> {\n return this.track(async () => {\n const data = await this.getKValueIfExists(rId, key);\n return data === undefined ? undefined : Buffer.from(data).toString();\n });\n }\n\n public async getKValueJsonIfExists<T>(rId: AnyResourceRef, key: string): Promise<T | undefined> {\n return this.track(async () => {\n const str = await this.getKValueString(rId, key);\n if (str === undefined) return undefined;\n return JSON.parse(str) as T;\n });\n }\n\n //\n // Cache\n //\n // TODO\n\n //\n // High level ops\n //\n\n /** Resolves existing or create first level resource from */\n public getFutureFieldValue(rId: AnyRef, fieldName: string, fieldType: FutureFieldType): FieldRef {\n const data = Buffer.from(JSON.stringify({ fieldName, fieldType }));\n const getFieldResource = this.createEphemeral({ name: \"json/getField\", version: \"1\" }, data);\n this.setField({ resourceId: getFieldResource, fieldName: \"resource\" }, rId);\n return { resourceId: getFieldResource, fieldName: \"result\" };\n }\n\n //\n // Technical\n //\n\n public async getGlobalTxId() {\n this.globalTxIdWasAwaited = true;\n return await this.globalTxId;\n }\n\n /** Closes output event stream */\n public async complete() {\n if (this._completed) return;\n this._completed = true;\n const completeResult = this.track(this.ll.complete());\n await this.drainAndAwaitPendingOps();\n await completeResult;\n }\n\n /** Await incoming message loop termination and throw\n * any leftover errors if it was unsuccessful */\n public async await() {\n await this.ll.await();\n }\n\n //\n // Helpers\n //\n\n private nextLocalResourceId(root: boolean): LocalResourceId {\n return createLocalResourceId(root, ++this.localResourceIdCounter, this.localTxId);\n }\n\n private static localTxIdCounter = 0;\n\n private static nextLocalTxId() {\n PlTransaction.localTxIdCounter++;\n if (PlTransaction.localTxIdCounter === MaxTxId) PlTransaction.localTxIdCounter = 1;\n return PlTransaction.localTxIdCounter;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"transaction.js","names":[],"sources":["../../src/core/transaction.ts"],"sourcesContent":["// TODO: fix this\n/* eslint-disable no-prototype-builtins */\nimport type {\n ColorProof,\n LocalResourceId,\n OptionalSignedResourceId,\n BasicResourceData,\n FieldData,\n FieldType,\n ResourceData,\n SignedResourceId,\n ResourceSignature,\n ResourceType,\n FutureFieldType,\n} from \"./types\";\nimport {\n createSignedResourceId,\n createLocalResourceId,\n isLocalResourceId,\n ensureSignedResourceIdNotNull,\n MaxTxId,\n extractBasicResourceData,\n parseSignedResourceId,\n toResourceSignature,\n isSignedResourceId,\n} from \"./types\";\nimport type {\n ClientMessageRequest,\n LLPlTransaction,\n OneOfKind,\n ServerMessageResponse,\n} from \"./ll_transaction\";\nimport { TxAPI_Open_Request_WritableTx } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport type { NonUndefined } from \"utility-types\";\nimport { toBytes } from \"../util/util\";\nimport { fieldTypeToProto, protoToField, protoToResource } from \"./type_conversion\";\nimport {\n canonicalJsonBytes,\n canonicalJsonGzBytes,\n deepFreeze,\n notEmpty,\n} from \"@milaboratories/ts-helpers\";\nimport { isNotFoundError } from \"./errors\";\nimport type { FinalResourceDataPredicate } from \"./final\";\nimport type { LRUCache } from \"lru-cache\";\nimport type { ResourceDataCacheRecord } from \"./cache\";\nimport type { TxStat } from \"./stat\";\nimport { initialTxStatWithoutTime } from \"./stat\";\nimport type { ErrorResourceData } from \"./error_resource\";\nimport { ErrorResourceType } from \"./error_resource\";\nimport { JsonGzObject, JsonObject } from \"../helpers/pl\";\nimport { PromiseTracker } from \"./PromiseTracker\";\n\n/** Reference to resource, used only within transaction */\nexport interface ResourceRef {\n /** Global resource id of newly created resources, become available only\n * after response for the corresponding creation request is received. */\n readonly globalId: Promise<SignedResourceId>;\n\n /** Transaction-local resource id is assigned right after resource creation\n * request is sent, and can be used right away */\n readonly localId: LocalResourceId;\n}\n\n/** Key-Value pair from resource-attached KV storage */\nexport interface KeyValue {\n key: string;\n value: Uint8Array;\n}\n\n/** Key-Value pair from resource-attached KV storage */\nexport interface KeyValueString {\n key: string;\n value: string;\n}\n\ninterface _FieldId<RId> {\n /** Parent resource id */\n resourceId: RId;\n /** Field name */\n fieldName: string;\n}\n\nexport type FieldId = _FieldId<SignedResourceId>;\nexport type FieldRef = _FieldId<ResourceRef>;\nexport type LocalFieldId = _FieldId<LocalResourceId>;\nexport type AnyFieldId = FieldId | LocalFieldId;\n\nexport type AnyResourceRef = ResourceRef | LocalResourceId | SignedResourceId;\nexport type AnyFieldRef = _FieldId<AnyResourceRef>; // FieldRef | FieldId\nexport type AnyRef = AnyResourceRef | AnyFieldRef;\n\nexport function isField(ref: AnyRef): ref is AnyFieldRef {\n return ref.hasOwnProperty(\"resourceId\") && ref.hasOwnProperty(\"fieldName\");\n}\n\nexport function isResource(ref: AnyRef): ref is AnyResourceRef {\n if (typeof ref === \"bigint\") return true; // LocalResourceId\n if (typeof ref === \"string\") return true; // SignedResourceId\n return isResourceRef(ref);\n}\n\nexport function isResourceId(ref: AnyRef): ref is SignedResourceId {\n return typeof ref === \"string\" && isSignedResourceId(ref);\n}\n\nexport function isFieldRef(ref: AnyFieldRef): ref is FieldRef {\n return isResourceRef(ref.resourceId);\n}\n\nexport function isResourceRef(ref: AnyRef): ref is ResourceRef {\n return (\n typeof ref === \"object\" &&\n ref !== null &&\n ref.hasOwnProperty(\"globalId\") &&\n ref.hasOwnProperty(\"localId\")\n );\n}\n\nexport function toFieldId(ref: AnyFieldRef): AnyFieldId {\n if (isFieldRef(ref)) return { resourceId: ref.resourceId.localId, fieldName: ref.fieldName };\n else return ref as FieldId;\n}\n\nexport async function toGlobalFieldId(ref: FieldRef | FieldId): Promise<FieldId> {\n if (isFieldRef(ref))\n return { resourceId: await ref.resourceId.globalId, fieldName: ref.fieldName };\n return ref;\n}\n\nexport interface ResourceIdWithSignature {\n resourceId: bigint;\n resourceSignature: ResourceSignature;\n}\n\nconst emptySignature = toResourceSignature(new Uint8Array(0));\n\nfunction toResourceIdAndSignature(ref: AnyResourceRef): ResourceIdWithSignature {\n if (isResourceRef(ref)) {\n // Local ID — no signature yet\n return { resourceId: ref.localId, resourceSignature: emptySignature };\n }\n if (isResourceId(ref)) {\n // SignedResourceId — decompose\n const { globalId, signature } = parseSignedResourceId(ref);\n return { resourceId: globalId as bigint, resourceSignature: signature };\n }\n // Raw bigint (LocalResourceId)\n return { resourceId: ref as bigint, resourceSignature: emptySignature };\n}\n\nexport async function toGlobalResourceId(ref: AnyResourceRef): Promise<SignedResourceId> {\n if (isResourceRef(ref)) return await ref.globalId;\n if (isLocalResourceId(ref)) return createSignedResourceId(ref); // legacy path: loose security mode in backend\n return ref;\n}\n\nexport function field(resourceId: AnyResourceRef, fieldName: string): AnyFieldRef {\n return { resourceId, fieldName };\n}\n\n/** If transaction commit failed due to write conflicts */\nexport class TxCommitConflict extends Error {\n name = \"TxCommitConflict\";\n}\n\nasync function notFoundToUndefined<T>(cb: () => Promise<T>): Promise<T | undefined> {\n try {\n return await cb();\n } catch (e) {\n if (isNotFoundError(e)) return undefined;\n throw e;\n }\n}\n\n/**\n * Each platform transaction has 3 stages:\n * - initialization (txOpen message -> txInfo response)\n * - communication (create resources, fields, references and so on)\n * - finalization (txCommit or txDiscard message)\n *\n * This class encapsulates finalization stage and provides ready-to-communication transaction object.\n * */\nexport class PlTransaction {\n private readonly globalTxId: Promise<bigint>;\n private readonly localTxId: number = PlTransaction.nextLocalTxId();\n\n /** Used in caching */\n private readonly txOpenTimestamp = Date.now();\n\n private localResourceIdCounter = 0;\n\n /** Store logical tx open / closed state to prevent invalid sequence of requests.\n * True means output stream was completed.\n * Contract: there must be no async operations between setting this field to true and sending complete signal to stream. */\n private _completed = false;\n\n private globalTxIdWasAwaited: boolean = false;\n\n public readonly pending = new PromiseTracker();\n\n private readonly _startTime = Date.now();\n private readonly _stat = initialTxStatWithoutTime();\n public get stat(): TxStat {\n return {\n ...this._stat,\n timeMs: Date.now() - this._startTime,\n };\n }\n\n constructor(\n private readonly ll: LLPlTransaction,\n public readonly name: string,\n public readonly writable: boolean,\n private readonly _clientRoot: OptionalSignedResourceId,\n private readonly finalPredicate: FinalResourceDataPredicate,\n private readonly sharedResourceDataCache: LRUCache<SignedResourceId, ResourceDataCacheRecord>,\n private readonly enableFormattedErrors: boolean = false,\n ) {\n // initiating transaction\n this.globalTxId = this.sendSingleAndParse(\n {\n oneofKind: \"txOpen\",\n txOpen: {\n name,\n enableFormattedErrors,\n writable: writable\n ? TxAPI_Open_Request_WritableTx.WRITABLE\n : TxAPI_Open_Request_WritableTx.NOT_WRITABLE,\n },\n },\n (r) => notEmpty(r.txOpen.tx?.id),\n );\n\n void this.track(this.globalTxId);\n\n // To avoid floating promise\n this.globalTxId.catch((err) => {\n if (!this.globalTxIdWasAwaited) {\n console.warn(err);\n }\n });\n\n // Adding stats\n this._stat.txCount++;\n }\n\n /**\n * Collect all pending promises for the transaction finalization.\n */\n public track<T>(promiseOrCallback: Promise<T> | (() => Promise<T>)): Promise<T> {\n return this.pending.track(promiseOrCallback);\n }\n\n private async drainAndAwaitPendingOps(): Promise<void> {\n // awaiting these pending operations first, to catch any errors\n await this.pending.awaitAll();\n }\n\n private sendSingleAndParse<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>, T>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n parser: (resp: OneOfKind<ServerMessageResponse, Kind>) => T,\n ): Promise<T> {\n return this.pending.track(async () => {\n const rawResponsePromise = this.ll.send(r, false);\n\n void this.pending.track(rawResponsePromise);\n\n await this.drainAndAwaitPendingOps();\n\n // awaiting our result, and parsing the response\n return parser(await rawResponsePromise);\n });\n }\n\n private sendMultiAndParse<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>, T>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n parser: (resp: OneOfKind<ServerMessageResponse, Kind>[]) => T,\n ): Promise<T> {\n return this.pending.track(async () => {\n const rawResponsePromise = this.ll.send(r, true);\n\n void this.pending.track(rawResponsePromise);\n\n await this.drainAndAwaitPendingOps();\n\n // awaiting our result, and parsing the response\n return parser(await rawResponsePromise);\n });\n }\n\n private async sendVoidSync<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n ): Promise<void> {\n await this.ll.send(r, false);\n }\n\n /** Requests sent with this method should never produce recoverable errors */\n private sendVoidAsync<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n ): void {\n void this.track(this.sendVoidSync(r));\n }\n\n /** Set default color proof for subsequent resource creation requests */\n public setDefaultColor(colorProof: ColorProof): void {\n this.sendVoidAsync({\n oneofKind: \"setDefaultColor\",\n setDefaultColor: { colorProof },\n });\n }\n\n private toSignedResourceId(rId: AnyResourceRef): ResourceIdWithSignature {\n return toResourceIdAndSignature(rId);\n }\n\n private toSignedFieldId(fId: AnyFieldRef): {\n resourceId: bigint;\n resourceSignature: ResourceSignature;\n fieldName: string;\n } {\n const base = toFieldId(fId);\n const signed = toResourceIdAndSignature(base.resourceId);\n return {\n resourceId: signed.resourceId,\n fieldName: base.fieldName,\n resourceSignature: signed.resourceSignature,\n };\n }\n\n private toSignedErrorRef(rId: AnyResourceRef): {\n errorResourceId: bigint;\n errorResourceSignature: ResourceSignature;\n } {\n const { resourceId, resourceSignature } = this.toSignedResourceId(rId);\n return { errorResourceId: resourceId, errorResourceSignature: resourceSignature };\n }\n\n private checkTxOpen() {\n if (this._completed) throw new Error(\"Transaction already closed\");\n }\n\n public get completed() {\n return this._completed;\n }\n\n /** Commit & closes transaction. {@link TxCommitConflict} is thrown on\n * commit conflicts. */\n public async commit() {\n this.checkTxOpen();\n\n // tx will accept no requests after this one\n this._completed = true;\n\n if (!this.writable) {\n // no need to explicitly commit or reject read-only tx\n const completeResult = this.track(this.ll.complete());\n await this.drainAndAwaitPendingOps();\n await completeResult;\n await this.ll.await();\n } else {\n const commitResponse = this.track(\n this.sendSingleAndParse({ oneofKind: \"txCommit\", txCommit: {} }, (r) => r.txCommit.success),\n );\n\n // send closing frame right after commit to save some time on round-trips\n const completeResult = this.track(this.ll.complete());\n\n // now when we pushed all packets into the stream, we should wait for any\n // pending void operations from before, to catch any errors\n await this.drainAndAwaitPendingOps();\n\n if (!(await commitResponse)) throw new TxCommitConflict();\n\n await completeResult;\n\n // await event-loop completion\n await this.ll.await();\n }\n }\n\n public async discard() {\n this.checkTxOpen();\n\n // tx will accept no requests after this one\n this._completed = true;\n\n const discardResponse = this.sendVoidSync({ oneofKind: \"txDiscard\", txDiscard: {} });\n void this.track(discardResponse);\n // send closing frame right after commit to save some time on round-trips\n const completeResult = this.track(this.ll.complete());\n\n // now when we pushed all packets into the stream, we should wait for any\n // pending void operations from before, to catch any errors\n await this.drainAndAwaitPendingOps();\n\n await discardResponse;\n await completeResult;\n await this.ll.await();\n }\n\n //\n // Main tx methods\n //\n\n public get clientRoot(): SignedResourceId {\n return ensureSignedResourceIdNotNull(this._clientRoot);\n }\n\n //\n // Resources\n //\n\n public createSingleton(\n name: string,\n type: ResourceType,\n errorIfExists: boolean = false,\n color?: ColorProof,\n ): ResourceRef {\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateSingleton\",\n resourceCreateSingleton: {\n type,\n id: localId,\n data: Buffer.from(name),\n errorIfExists,\n colorProof: color ?? emptySignature,\n },\n }),\n (r) => r.resourceCreateSingleton.resourceId,\n (r) => r.resourceCreateSingleton.resourceSignature,\n );\n }\n\n public getSingleton(name: string, loadFields: true): Promise<ResourceData>;\n public getSingleton(name: string, loadFields: false): Promise<BasicResourceData>;\n public getSingleton(\n name: string,\n loadFields: boolean = true,\n ): Promise<BasicResourceData | ResourceData> {\n return this.sendSingleAndParse(\n {\n oneofKind: \"resourceGetSingleton\",\n resourceGetSingleton: {\n data: Buffer.from(name),\n loadFields,\n },\n },\n (r) => protoToResource(notEmpty(r.resourceGetSingleton.resource)),\n );\n }\n\n private createResource<Kind extends NonUndefined<ClientMessageRequest[\"oneofKind\"]>>(\n root: boolean,\n req: (localId: LocalResourceId) => OneOfKind<ClientMessageRequest, Kind>,\n parser: (resp: OneOfKind<ServerMessageResponse, Kind>) => bigint,\n sigExtractor: (resp: OneOfKind<ServerMessageResponse, Kind>) => Uint8Array | undefined,\n ): ResourceRef {\n const localId = this.nextLocalResourceId(root);\n\n const globalId = this.sendSingleAndParse(req(localId), (r) => {\n const rawId = parser(r);\n const sig = sigExtractor ? toResourceSignature(sigExtractor(r)) : undefined;\n return createSignedResourceId(rawId, sig);\n });\n\n void this.track(globalId);\n\n return { globalId, localId };\n }\n\n public createRoot(type: ResourceType): ResourceRef {\n this._stat.rootsCreated++;\n return this.createResource(\n true,\n (localId) => ({ oneofKind: \"resourceCreateRoot\", resourceCreateRoot: { type, id: localId } }),\n (r) => r.resourceCreateRoot.resourceId,\n (r) => r.resourceCreateRoot.resourceSignature,\n );\n }\n\n public createStruct(\n type: ResourceType,\n data?: Uint8Array | string,\n color?: ColorProof,\n ): ResourceRef {\n this._stat.structsCreated++;\n this._stat.structsCreatedDataBytes += data?.length ?? 0;\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateStruct\",\n resourceCreateStruct: {\n type,\n id: localId,\n data:\n data === undefined ? undefined : typeof data === \"string\" ? Buffer.from(data) : data,\n colorProof: color ?? emptySignature,\n },\n }),\n (r) => r.resourceCreateStruct.resourceId,\n (r) => r.resourceCreateStruct.resourceSignature,\n );\n }\n\n public createEphemeral(\n type: ResourceType,\n data?: Uint8Array | string,\n color?: ColorProof,\n ): ResourceRef {\n this._stat.ephemeralsCreated++;\n this._stat.ephemeralsCreatedDataBytes += data?.length ?? 0;\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateEphemeral\",\n resourceCreateEphemeral: {\n type,\n id: localId,\n data:\n data === undefined ? undefined : typeof data === \"string\" ? Buffer.from(data) : data,\n colorProof: color ?? emptySignature,\n },\n }),\n (r) => r.resourceCreateEphemeral.resourceId,\n (r) => r.resourceCreateEphemeral.resourceSignature,\n );\n }\n\n public createValue(\n type: ResourceType,\n data: Uint8Array | string,\n errorIfExists: boolean = false,\n color?: ColorProof,\n ): ResourceRef {\n this._stat.valuesCreated++;\n this._stat.valuesCreatedDataBytes += data?.length ?? 0;\n return this.createResource(\n false,\n (localId) => ({\n oneofKind: \"resourceCreateValue\",\n resourceCreateValue: {\n type,\n id: localId,\n data: typeof data === \"string\" ? Buffer.from(data) : data,\n errorIfExists,\n colorProof: color ?? emptySignature,\n },\n }),\n (r) => r.resourceCreateValue.resourceId,\n (r) => r.resourceCreateValue.resourceSignature,\n );\n }\n\n public createJsonValue(data: unknown, color?: ColorProof): ResourceRef {\n const jsonData = canonicalJsonBytes(data);\n return this.createValue(JsonObject, jsonData, false, color);\n }\n\n public createJsonGzValue(\n data: unknown,\n minSizeToGzip: number | undefined = 16_384,\n color?: ColorProof,\n ): ResourceRef {\n const { data: jsonData, isGzipped } = canonicalJsonGzBytes(data, minSizeToGzip);\n return this.createValue(isGzipped ? JsonGzObject : JsonObject, jsonData, false, color);\n }\n\n public createError(message: string, color?: ColorProof): ResourceRef {\n return this.createValue(\n ErrorResourceType,\n JSON.stringify({ message } satisfies ErrorResourceData),\n false,\n color,\n );\n }\n\n public setResourceName(name: string, rId: AnyResourceRef): void {\n this.sendVoidAsync({\n oneofKind: \"resourceNameSet\",\n resourceNameSet: { ...this.toSignedResourceId(rId), name },\n });\n }\n\n public deleteResourceName(name: string): void {\n this.sendVoidAsync({ oneofKind: \"resourceNameDelete\", resourceNameDelete: { name } });\n }\n\n public getResourceByName(name: string): Promise<SignedResourceId> {\n return this.sendSingleAndParse(\n { oneofKind: \"resourceNameGet\", resourceNameGet: { name } },\n (r) => {\n const rawId = r.resourceNameGet.resourceId;\n if (rawId === 0n) throw new Error(\"null resource id from getResourceByName\");\n const sig = toResourceSignature(r.resourceNameGet.resourceSignature);\n return createSignedResourceId(rawId, sig);\n },\n );\n }\n\n public checkResourceNameExists(name: string): Promise<boolean> {\n return this.sendSingleAndParse(\n { oneofKind: \"resourceNameExists\", resourceNameExists: { name } },\n (r) => r.resourceNameExists.exists,\n );\n }\n\n public removeResource(rId: SignedResourceId): void {\n this.sendVoidAsync({\n oneofKind: \"resourceRemove\",\n resourceRemove: this.toSignedResourceId(rId),\n });\n }\n\n public resourceExists(rId: SignedResourceId): Promise<boolean> {\n return this.sendSingleAndParse(\n {\n oneofKind: \"resourceExists\",\n resourceExists: this.toSignedResourceId(rId),\n },\n (r) => r.resourceExists.exists,\n );\n }\n\n /** This method may return stale resource state from cache if resource was removed */\n public async getResourceData(rId: AnyResourceRef, loadFields: true): Promise<ResourceData>;\n /** This method may return stale resource state from cache if resource was removed */\n public async getResourceData(rId: AnyResourceRef, loadFields: false): Promise<BasicResourceData>;\n /** This method may return stale resource state from cache if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: boolean,\n ): Promise<BasicResourceData | ResourceData>;\n /** This method may return stale resource state from cache if ignoreCache == false if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: true,\n ignoreCache: boolean,\n ): Promise<ResourceData>;\n /** This method may return stale resource state from cache if ignoreCache == false if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: false,\n ignoreCache: boolean,\n ): Promise<BasicResourceData>;\n /** This method may return stale resource state from cache if ignoreCache == false if resource was removed */\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: boolean,\n ignoreCache: boolean,\n ): Promise<BasicResourceData | ResourceData>;\n public async getResourceData(\n rId: AnyResourceRef,\n loadFields: boolean = true,\n ignoreCache: boolean = false,\n ): Promise<BasicResourceData | ResourceData> {\n return this.track(async () => {\n if (!ignoreCache && isResourceId(rId)) {\n // checking if we can return result from cache\n const fromCache = this.sharedResourceDataCache.get(rId);\n if (fromCache && fromCache.cacheTxOpenTimestamp < this.txOpenTimestamp) {\n if (!loadFields) {\n this._stat.rGetDataCacheHits++;\n this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;\n return fromCache.basicData;\n } else if (fromCache.data) {\n this._stat.rGetDataCacheHits++;\n this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;\n this._stat.rGetDataCacheFields += fromCache.data.fields.length;\n return fromCache.data;\n }\n }\n }\n\n const result = await this.sendSingleAndParse(\n {\n oneofKind: \"resourceGet\",\n resourceGet: {\n ...this.toSignedResourceId(rId),\n loadFields: loadFields,\n },\n },\n (r) => protoToResource(notEmpty(r.resourceGet.resource)),\n );\n\n this._stat.rGetDataNetRequests++;\n this._stat.rGetDataNetBytes += result.data?.length ?? 0;\n this._stat.rGetDataNetFields += result.fields.length;\n\n // we will cache only final resource data states\n // caching result even if we were ignore the cache\n if (isResourceId(rId) && this.finalPredicate(result)) {\n deepFreeze(result);\n const fromCache = this.sharedResourceDataCache.get(rId);\n if (fromCache) {\n if (loadFields && !fromCache.data) {\n fromCache.data = result;\n // updating timestamp because we updated the record\n fromCache.cacheTxOpenTimestamp = this.txOpenTimestamp;\n }\n } else {\n const basicData = extractBasicResourceData(result);\n deepFreeze(basicData);\n if (loadFields)\n this.sharedResourceDataCache.set(rId, {\n basicData,\n data: result,\n cacheTxOpenTimestamp: this.txOpenTimestamp,\n });\n else\n this.sharedResourceDataCache.set(rId, {\n basicData,\n data: undefined,\n cacheTxOpenTimestamp: this.txOpenTimestamp,\n });\n }\n }\n\n return result;\n });\n }\n\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: true,\n ): Promise<ResourceData | undefined>;\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: false,\n ): Promise<BasicResourceData | undefined>;\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: boolean,\n ): Promise<BasicResourceData | ResourceData | undefined>;\n public async getResourceDataIfExists(\n rId: AnyResourceRef,\n loadFields: boolean = true,\n ): Promise<BasicResourceData | ResourceData | undefined> {\n return this.track(async () => {\n // calling this method will ignore cache, because user intention is to detect resource absence\n // which cache will prevent\n const result = await notFoundToUndefined(\n async () => await this.getResourceData(rId, loadFields, true),\n );\n\n // cleaning cache record if resource was removed from the db\n if (result === undefined && isResourceId(rId)) this.sharedResourceDataCache.delete(rId);\n\n return result;\n });\n }\n\n /**\n * Inform platform that resource will not get any new input fields.\n * This is required, when client creates resource without schema and wants\n * controller to start calculations.\n * Most controllers will not start calculations even when all inputs\n * have their values, if inputs list is not locked.\n */\n public lockInputs(rId: AnyResourceRef): void {\n this._stat.inputsLocked++;\n this.sendVoidAsync({\n oneofKind: \"resourceLockInputs\",\n resourceLockInputs: this.toSignedResourceId(rId),\n });\n }\n\n /**\n * Inform platform that resource will not get any new output fields.\n * This is required for resource to pass deduplication.\n */\n public lockOutputs(rId: AnyResourceRef): void {\n this._stat.outputsLocked++;\n this.sendVoidAsync({\n oneofKind: \"resourceLockOutputs\",\n resourceLockOutputs: this.toSignedResourceId(rId),\n });\n }\n\n public lock(rID: AnyResourceRef): void {\n this.lockInputs(rID);\n this.lockOutputs(rID);\n }\n\n public setResourceError(rId: AnyResourceRef, ref: AnyResourceRef): void {\n this.sendVoidAsync({\n oneofKind: \"resourceSetError\",\n resourceSetError: {\n ...this.toSignedResourceId(rId),\n ...this.toSignedErrorRef(ref),\n },\n });\n }\n\n //\n // Fields\n //\n\n public createField(fId: AnyFieldRef, fieldType: FieldType, value?: AnyRef): void {\n this._stat.fieldsCreated++;\n this.sendVoidAsync({\n oneofKind: \"fieldCreate\",\n fieldCreate: { type: fieldTypeToProto(fieldType), id: this.toSignedFieldId(fId) },\n });\n if (value !== undefined) this.setField(fId, value);\n }\n\n public fieldExists(fId: AnyFieldRef): Promise<boolean> {\n return this.sendSingleAndParse(\n {\n oneofKind: \"fieldExists\",\n fieldExists: { field: this.toSignedFieldId(fId) },\n },\n (r) => r.fieldExists.exists,\n );\n }\n\n public setField(fId: AnyFieldRef, ref: AnyRef): void {\n this._stat.fieldsSet++;\n if (isResource(ref)) {\n this.sendVoidAsync({\n oneofKind: \"fieldSet\",\n fieldSet: {\n field: this.toSignedFieldId(fId),\n value: {\n ...this.toSignedResourceId(ref),\n fieldName: \"\", // default value, read as undefined\n },\n },\n });\n } else {\n this.sendVoidAsync({\n oneofKind: \"fieldSet\",\n fieldSet: {\n field: this.toSignedFieldId(fId),\n value: this.toSignedFieldId(ref),\n },\n });\n }\n }\n\n public setFieldError(fId: AnyFieldRef, ref: AnyResourceRef): void {\n this._stat.fieldsSet++;\n this.sendVoidAsync({\n oneofKind: \"fieldSetError\",\n fieldSetError: {\n field: this.toSignedFieldId(fId),\n ...this.toSignedErrorRef(ref),\n },\n });\n }\n\n public getField(fId: AnyFieldRef): Promise<FieldData> {\n this._stat.fieldsGet++;\n return this.sendSingleAndParse(\n { oneofKind: \"fieldGet\", fieldGet: { field: this.toSignedFieldId(fId) } },\n (r) => protoToField(notEmpty(r.fieldGet.field)),\n );\n }\n\n public async getFieldIfExists(fId: AnyFieldRef): Promise<FieldData | undefined> {\n return this.track(notFoundToUndefined(async () => await this.getField(fId)));\n }\n\n public resetField(fId: AnyFieldRef): void {\n this.sendVoidAsync({\n oneofKind: \"fieldReset\",\n fieldReset: { field: this.toSignedFieldId(fId) },\n });\n }\n\n public removeField(fId: AnyFieldRef): void {\n this.sendVoidAsync({\n oneofKind: \"fieldRemove\",\n fieldRemove: { field: this.toSignedFieldId(fId) },\n });\n }\n\n //\n // KV\n //\n\n public async listKeyValues(rId: AnyResourceRef): Promise<KeyValue[]> {\n return this.track(async () => {\n const result = await this.sendMultiAndParse(\n {\n oneofKind: \"resourceKeyValueList\",\n resourceKeyValueList: {\n ...this.toSignedResourceId(rId),\n startFrom: \"\",\n limit: 0,\n },\n },\n (r) => r.map((e) => e.resourceKeyValueList.record!),\n );\n\n this._stat.kvListRequests++;\n this._stat.kvListEntries += result.length;\n for (const kv of result) this._stat.kvListBytes += kv.key.length + kv.value.length;\n\n return result;\n });\n }\n\n public async listKeyValuesString(rId: AnyResourceRef): Promise<KeyValueString[]> {\n return this.track(async () =>\n (await this.listKeyValues(rId)).map(({ key, value }) => ({\n key,\n value: Buffer.from(value).toString(),\n })),\n );\n }\n\n public async listKeyValuesIfResourceExists(rId: AnyResourceRef): Promise<KeyValue[] | undefined> {\n return this.track(notFoundToUndefined(async () => await this.listKeyValues(rId)));\n }\n\n public async listKeyValuesStringIfResourceExists(\n rId: AnyResourceRef,\n ): Promise<KeyValueString[] | undefined> {\n return this.track(notFoundToUndefined(async () => await this.listKeyValuesString(rId)));\n }\n\n public setKValue(rId: AnyResourceRef, key: string, value: Uint8Array | string): void {\n this._stat.kvSetRequests++;\n this._stat.kvSetBytes++;\n this.sendVoidAsync({\n oneofKind: \"resourceKeyValueSet\",\n resourceKeyValueSet: {\n ...this.toSignedResourceId(rId),\n key,\n value: toBytes(value),\n },\n });\n }\n\n public deleteKValue(rId: AnyResourceRef, key: string): void {\n this.sendVoidAsync({\n oneofKind: \"resourceKeyValueDelete\",\n resourceKeyValueDelete: {\n ...this.toSignedResourceId(rId),\n key,\n },\n });\n }\n\n public async getKValue(rId: AnyResourceRef, key: string): Promise<Uint8Array> {\n return this.track(async () => {\n const result = await this.sendSingleAndParse(\n {\n oneofKind: \"resourceKeyValueGet\",\n resourceKeyValueGet: {\n ...this.toSignedResourceId(rId),\n key,\n },\n },\n (r) => r.resourceKeyValueGet.value,\n );\n\n this._stat.kvGetRequests++;\n this._stat.kvGetBytes += result.length;\n\n return result;\n });\n }\n\n public async getKValueString(rId: AnyResourceRef, key: string): Promise<string> {\n return this.track(async () => Buffer.from(await this.getKValue(rId, key)).toString());\n }\n\n public async getKValueJson<T>(rId: AnyResourceRef, key: string): Promise<T> {\n return this.track(async () => JSON.parse(await this.getKValueString(rId, key)) as T);\n }\n\n public async getKValueIfExists(\n rId: AnyResourceRef,\n key: string,\n ): Promise<Uint8Array | undefined> {\n return this.track(async () => {\n const result = await this.sendSingleAndParse(\n {\n oneofKind: \"resourceKeyValueGetIfExists\",\n resourceKeyValueGetIfExists: {\n ...this.toSignedResourceId(rId),\n key,\n },\n },\n (r) =>\n r.resourceKeyValueGetIfExists.exists ? r.resourceKeyValueGetIfExists.value : undefined,\n );\n\n this._stat.kvGetRequests++;\n this._stat.kvGetBytes += result?.length ?? 0;\n\n return result;\n });\n }\n\n public async getKValueStringIfExists(\n rId: AnyResourceRef,\n key: string,\n ): Promise<string | undefined> {\n return this.track(async () => {\n const data = await this.getKValueIfExists(rId, key);\n return data === undefined ? undefined : Buffer.from(data).toString();\n });\n }\n\n public async getKValueJsonIfExists<T>(rId: AnyResourceRef, key: string): Promise<T | undefined> {\n return this.track(async () => {\n const str = await this.getKValueStringIfExists(rId, key);\n if (str === undefined) return undefined;\n return JSON.parse(str) as T;\n });\n }\n\n //\n // Cache\n //\n // TODO\n\n //\n // High level ops\n //\n\n /** Resolves existing or create first level resource from */\n public getFutureFieldValue(rId: AnyRef, fieldName: string, fieldType: FutureFieldType): FieldRef {\n const data = Buffer.from(JSON.stringify({ fieldName, fieldType }));\n const getFieldResource = this.createEphemeral({ name: \"json/getField\", version: \"1\" }, data);\n this.setField({ resourceId: getFieldResource, fieldName: \"resource\" }, rId);\n return { resourceId: getFieldResource, fieldName: \"result\" };\n }\n\n //\n // Technical\n //\n\n public async getGlobalTxId() {\n this.globalTxIdWasAwaited = true;\n return await this.globalTxId;\n }\n\n /** Closes output event stream */\n public async complete() {\n if (this._completed) return;\n this._completed = true;\n const completeResult = this.track(this.ll.complete());\n await this.drainAndAwaitPendingOps();\n await completeResult;\n }\n\n /** Await incoming message loop termination and throw\n * any leftover errors if it was unsuccessful */\n public async await() {\n await this.ll.await();\n }\n\n //\n // Helpers\n //\n\n private nextLocalResourceId(root: boolean): LocalResourceId {\n return createLocalResourceId(root, ++this.localResourceIdCounter, this.localTxId);\n }\n\n private static localTxIdCounter = 0;\n\n private static nextLocalTxId() {\n PlTransaction.localTxIdCounter++;\n if (PlTransaction.localTxIdCounter === MaxTxId) PlTransaction.localTxIdCounter = 1;\n return PlTransaction.localTxIdCounter;\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  require("../_virtual/_rolldown/runtime.cjs");
2
- require("./types.cjs");
2
+ const require_types = require("./types.cjs");
3
3
  const require_base_types = require("../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs");
4
4
  const require_api_types = require("../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs");
5
5
  const require_errors = require("./errors.cjs");
@@ -9,12 +9,16 @@ const ResourceErrorField = "resourceError";
9
9
  function resourceIsDeleted(proto) {
10
10
  return proto.deletedTime !== void 0 && proto.deletedTime.seconds !== 0n;
11
11
  }
12
+ function protoIdToOptionalResourceId(id, signature) {
13
+ if (id === 0n) return "";
14
+ return require_types.createSignedResourceId(id, require_types.toResourceSignature(signature));
15
+ }
12
16
  /** Throws "native" pl not found error, if resource is marked as deleted. */
13
17
  function protoToResource(proto) {
14
18
  if (resourceIsDeleted(proto)) require_errors.throwPlNotFoundError("resource deleted");
15
19
  return {
16
- id: proto.resourceId,
17
- originalResourceId: proto.originalResourceId,
20
+ id: require_types.createSignedResourceId(proto.resourceId, require_types.toResourceSignature(proto.resourceSignature)),
21
+ originalResourceId: protoIdToOptionalResourceId(proto.originalResourceId, proto.originalResourceSignature),
18
22
  type: (0, _milaboratories_ts_helpers.notEmpty)(proto.type),
19
23
  data: proto.data,
20
24
  inputsLocked: proto.inputsLocked,
@@ -34,15 +38,19 @@ function protoToResourceKind(proto) {
34
38
  throw new Error("invalid ResourceKind: " + proto);
35
39
  }
36
40
  function protoToError(proto) {
37
- return proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField)?.error ?? 0n;
41
+ const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);
42
+ if (!f) return "";
43
+ const errId = f.error ?? 0n;
44
+ if (errId === 0n) return "";
45
+ return require_types.createSignedResourceId(errId, require_types.toResourceSignature(f.errorSignature));
38
46
  }
39
47
  function protoToField(proto) {
40
48
  return {
41
49
  name: (0, _milaboratories_ts_helpers.notEmpty)(proto.id?.fieldName),
42
50
  type: protoToFieldType(proto.type),
43
51
  status: protoToFieldStatus(proto.valueStatus),
44
- value: proto.value,
45
- error: proto.error,
52
+ value: protoIdToOptionalResourceId(proto.value, proto.valueSignature),
53
+ error: protoIdToOptionalResourceId(proto.error, proto.errorSignature),
46
54
  valueIsFinal: proto.valueIsFinal
47
55
  };
48
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"type_conversion.cjs","names":["Resource_Kind","GrpcFieldType","Field_ValueStatus"],"sources":["../../src/core/type_conversion.ts"],"sourcesContent":["import type {\n Field,\n Resource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport {\n Field_ValueStatus,\n Resource_Kind,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport { FieldType as GrpcFieldType } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types\";\nimport type {\n FieldData,\n FieldStatus,\n OptionalResourceId,\n FieldType,\n ResourceData,\n ResourceId,\n ResourceKind,\n} from \"./types\";\nimport { NullResourceId } from \"./types\";\nimport { assertNever, notEmpty } from \"@milaboratories/ts-helpers\";\nimport { throwPlNotFoundError } from \"./errors\";\n\nconst ResourceErrorField = \"resourceError\";\n\nfunction resourceIsDeleted(proto: Resource): boolean {\n return proto.deletedTime !== undefined && proto.deletedTime.seconds !== 0n;\n}\n\n/** Throws \"native\" pl not found error, if resource is marked as deleted. */\nexport function protoToResource(proto: Resource): ResourceData {\n if (resourceIsDeleted(proto)) throwPlNotFoundError(\"resource deleted\");\n return {\n id: proto.resourceId as ResourceId,\n originalResourceId: proto.originalResourceId as OptionalResourceId,\n type: notEmpty(proto.type),\n data: proto.data,\n inputsLocked: proto.inputsLocked,\n outputsLocked: proto.outputsLocked,\n resourceReady: proto.resourceReady,\n kind: protoToResourceKind(proto.kind),\n error: protoToError(proto),\n final: proto.isFinal,\n fields: proto.fields?.filter((f) => f.id!.fieldName !== ResourceErrorField).map(protoToField),\n };\n}\n\nfunction protoToResourceKind(proto: Resource_Kind): ResourceKind {\n switch (proto) {\n case Resource_Kind.STRUCTURAL:\n return \"Structural\";\n case Resource_Kind.VALUE:\n return \"Value\";\n }\n\n throw new Error(\"invalid ResourceKind: \" + proto);\n}\n\nfunction protoToError(proto: Resource): OptionalResourceId {\n const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);\n return (f?.error ?? NullResourceId) as OptionalResourceId;\n}\n\nexport function protoToField(proto: Field): FieldData {\n return {\n name: notEmpty(proto.id?.fieldName),\n type: protoToFieldType(proto.type),\n status: protoToFieldStatus(proto.valueStatus),\n value: proto.value as OptionalResourceId,\n error: proto.error as OptionalResourceId,\n valueIsFinal: proto.valueIsFinal,\n };\n}\n\nfunction protoToFieldType(proto: GrpcFieldType): FieldType {\n switch (proto) {\n case GrpcFieldType.INPUT:\n return \"Input\";\n case GrpcFieldType.OUTPUT:\n return \"Output\";\n case GrpcFieldType.SERVICE:\n return \"Service\";\n case GrpcFieldType.ONE_TIME_WRITABLE:\n return \"OTW\";\n case GrpcFieldType.DYNAMIC:\n return \"Dynamic\";\n case GrpcFieldType.MULTIPLE_TIMES_WRITABLE:\n return \"MTW\";\n default:\n throw new Error(\"invalid FieldType: \" + proto);\n }\n}\n\nfunction protoToFieldStatus(proto: Field_ValueStatus): FieldStatus {\n switch (proto) {\n case Field_ValueStatus.EMPTY:\n return \"Empty\";\n case Field_ValueStatus.ASSIGNED:\n return \"Assigned\";\n case Field_ValueStatus.RESOLVED:\n return \"Resolved\";\n default:\n throw new Error(\"invalid FieldStatus: \" + proto);\n }\n}\n\nexport function fieldTypeToProto(type: FieldType): GrpcFieldType {\n switch (type) {\n case \"Input\":\n return GrpcFieldType.INPUT;\n case \"Output\":\n return GrpcFieldType.OUTPUT;\n case \"Dynamic\":\n return GrpcFieldType.DYNAMIC;\n case \"Service\":\n return GrpcFieldType.SERVICE;\n case \"MTW\":\n return GrpcFieldType.MULTIPLE_TIMES_WRITABLE;\n case \"OTW\":\n return GrpcFieldType.ONE_TIME_WRITABLE;\n default:\n return assertNever(type);\n }\n}\n"],"mappings":";;;;;;;AAsBA,MAAM,qBAAqB;AAE3B,SAAS,kBAAkB,OAA0B;AACnD,QAAO,MAAM,gBAAgB,KAAA,KAAa,MAAM,YAAY,YAAY;;;AAI1E,SAAgB,gBAAgB,OAA+B;AAC7D,KAAI,kBAAkB,MAAM,CAAE,gBAAA,qBAAqB,mBAAmB;AACtE,QAAO;EACL,IAAI,MAAM;EACV,oBAAoB,MAAM;EAC1B,OAAA,GAAA,2BAAA,UAAe,MAAM,KAAK;EAC1B,MAAM,MAAM;EACZ,cAAc,MAAM;EACpB,eAAe,MAAM;EACrB,eAAe,MAAM;EACrB,MAAM,oBAAoB,MAAM,KAAK;EACrC,OAAO,aAAa,MAAM;EAC1B,OAAO,MAAM;EACb,QAAQ,MAAM,QAAQ,QAAQ,MAAM,EAAE,GAAI,cAAc,mBAAmB,CAAC,IAAI,aAAa;EAC9F;;AAGH,SAAS,oBAAoB,OAAoC;AAC/D,SAAQ,OAAR;EACE,KAAKA,kBAAAA,cAAc,WACjB,QAAO;EACT,KAAKA,kBAAAA,cAAc,MACjB,QAAO;;AAGX,OAAM,IAAI,MAAM,2BAA2B,MAAM;;AAGnD,SAAS,aAAa,OAAqC;AAEzD,QADU,MAAM,OAAO,MAAM,MAAM,GAAG,IAAI,cAAc,mBAAmB,EAChE,SAAA;;AAGb,SAAgB,aAAa,OAAyB;AACpD,QAAO;EACL,OAAA,GAAA,2BAAA,UAAe,MAAM,IAAI,UAAU;EACnC,MAAM,iBAAiB,MAAM,KAAK;EAClC,QAAQ,mBAAmB,MAAM,YAAY;EAC7C,OAAO,MAAM;EACb,OAAO,MAAM;EACb,cAAc,MAAM;EACrB;;AAGH,SAAS,iBAAiB,OAAiC;AACzD,SAAQ,OAAR;EACE,KAAKC,mBAAAA,UAAc,MACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,OACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,QACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,kBACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,QACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,wBACjB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,wBAAwB,MAAM;;;AAIpD,SAAS,mBAAmB,OAAuC;AACjE,SAAQ,OAAR;EACE,KAAKC,kBAAAA,kBAAkB,MACrB,QAAO;EACT,KAAKA,kBAAAA,kBAAkB,SACrB,QAAO;EACT,KAAKA,kBAAAA,kBAAkB,SACrB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,0BAA0B,MAAM;;;AAItD,SAAgB,iBAAiB,MAAgC;AAC/D,SAAQ,MAAR;EACE,KAAK,QACH,QAAOD,mBAAAA,UAAc;EACvB,KAAK,SACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,UACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,UACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,MACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,MACH,QAAOA,mBAAAA,UAAc;EACvB,QACE,SAAA,GAAA,2BAAA,aAAmB,KAAK"}
1
+ {"version":3,"file":"type_conversion.cjs","names":["createSignedResourceId","toResourceSignature","Resource_Kind","GrpcFieldType","Field_ValueStatus"],"sources":["../../src/core/type_conversion.ts"],"sourcesContent":["import type {\n Field,\n Resource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport {\n Field_ValueStatus,\n Resource_Kind,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport { FieldType as GrpcFieldType } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types\";\nimport type {\n FieldData,\n FieldStatus,\n OptionalSignedResourceId,\n FieldType,\n ResourceData,\n ResourceKind,\n} from \"./types\";\nimport {\n createSignedResourceId,\n NullSignedResourceId,\n toResourceSignature,\n NullResourceId,\n} from \"./types\";\nimport { assertNever, notEmpty } from \"@milaboratories/ts-helpers\";\nimport { throwPlNotFoundError } from \"./errors\";\n\nconst ResourceErrorField = \"resourceError\";\n\nfunction resourceIsDeleted(proto: Resource): boolean {\n return proto.deletedTime !== undefined && proto.deletedTime.seconds !== 0n;\n}\n\nfunction protoIdToOptionalResourceId(id: bigint, signature?: Uint8Array): OptionalSignedResourceId {\n if (id === NullResourceId) return NullSignedResourceId;\n return createSignedResourceId(id, toResourceSignature(signature));\n}\n\n/** Throws \"native\" pl not found error, if resource is marked as deleted. */\nexport function protoToResource(proto: Resource): ResourceData {\n if (resourceIsDeleted(proto)) throwPlNotFoundError(\"resource deleted\");\n return {\n id: createSignedResourceId(proto.resourceId, toResourceSignature(proto.resourceSignature)),\n originalResourceId: protoIdToOptionalResourceId(\n proto.originalResourceId,\n proto.originalResourceSignature,\n ),\n type: notEmpty(proto.type),\n data: proto.data,\n inputsLocked: proto.inputsLocked,\n outputsLocked: proto.outputsLocked,\n resourceReady: proto.resourceReady,\n kind: protoToResourceKind(proto.kind),\n error: protoToError(proto),\n final: proto.isFinal,\n fields: proto.fields?.filter((f) => f.id!.fieldName !== ResourceErrorField).map(protoToField),\n };\n}\n\nfunction protoToResourceKind(proto: Resource_Kind): ResourceKind {\n switch (proto) {\n case Resource_Kind.STRUCTURAL:\n return \"Structural\";\n case Resource_Kind.VALUE:\n return \"Value\";\n }\n\n throw new Error(\"invalid ResourceKind: \" + proto);\n}\n\nfunction protoToError(proto: Resource): OptionalSignedResourceId {\n const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);\n if (!f) return NullSignedResourceId;\n const errId = f.error ?? 0n;\n if (errId === 0n) return NullSignedResourceId;\n return createSignedResourceId(errId, toResourceSignature(f.errorSignature));\n}\n\nexport function protoToField(proto: Field): FieldData {\n return {\n name: notEmpty(proto.id?.fieldName),\n type: protoToFieldType(proto.type),\n status: protoToFieldStatus(proto.valueStatus),\n value: protoIdToOptionalResourceId(proto.value, proto.valueSignature),\n error: protoIdToOptionalResourceId(proto.error, proto.errorSignature),\n valueIsFinal: proto.valueIsFinal,\n };\n}\n\nfunction protoToFieldType(proto: GrpcFieldType): FieldType {\n switch (proto) {\n case GrpcFieldType.INPUT:\n return \"Input\";\n case GrpcFieldType.OUTPUT:\n return \"Output\";\n case GrpcFieldType.SERVICE:\n return \"Service\";\n case GrpcFieldType.ONE_TIME_WRITABLE:\n return \"OTW\";\n case GrpcFieldType.DYNAMIC:\n return \"Dynamic\";\n case GrpcFieldType.MULTIPLE_TIMES_WRITABLE:\n return \"MTW\";\n default:\n throw new Error(\"invalid FieldType: \" + proto);\n }\n}\n\nfunction protoToFieldStatus(proto: Field_ValueStatus): FieldStatus {\n switch (proto) {\n case Field_ValueStatus.EMPTY:\n return \"Empty\";\n case Field_ValueStatus.ASSIGNED:\n return \"Assigned\";\n case Field_ValueStatus.RESOLVED:\n return \"Resolved\";\n default:\n throw new Error(\"invalid FieldStatus: \" + proto);\n }\n}\n\nexport function fieldTypeToProto(type: FieldType): GrpcFieldType {\n switch (type) {\n case \"Input\":\n return GrpcFieldType.INPUT;\n case \"Output\":\n return GrpcFieldType.OUTPUT;\n case \"Dynamic\":\n return GrpcFieldType.DYNAMIC;\n case \"Service\":\n return GrpcFieldType.SERVICE;\n case \"MTW\":\n return GrpcFieldType.MULTIPLE_TIMES_WRITABLE;\n case \"OTW\":\n return GrpcFieldType.ONE_TIME_WRITABLE;\n default:\n return assertNever(type);\n }\n}\n"],"mappings":";;;;;;;AA0BA,MAAM,qBAAqB;AAE3B,SAAS,kBAAkB,OAA0B;AACnD,QAAO,MAAM,gBAAgB,KAAA,KAAa,MAAM,YAAY,YAAY;;AAG1E,SAAS,4BAA4B,IAAY,WAAkD;AACjG,KAAI,OAAA,GAAuB,QAAA;AAC3B,QAAOA,cAAAA,uBAAuB,IAAIC,cAAAA,oBAAoB,UAAU,CAAC;;;AAInE,SAAgB,gBAAgB,OAA+B;AAC7D,KAAI,kBAAkB,MAAM,CAAE,gBAAA,qBAAqB,mBAAmB;AACtE,QAAO;EACL,IAAID,cAAAA,uBAAuB,MAAM,YAAYC,cAAAA,oBAAoB,MAAM,kBAAkB,CAAC;EAC1F,oBAAoB,4BAClB,MAAM,oBACN,MAAM,0BACP;EACD,OAAA,GAAA,2BAAA,UAAe,MAAM,KAAK;EAC1B,MAAM,MAAM;EACZ,cAAc,MAAM;EACpB,eAAe,MAAM;EACrB,eAAe,MAAM;EACrB,MAAM,oBAAoB,MAAM,KAAK;EACrC,OAAO,aAAa,MAAM;EAC1B,OAAO,MAAM;EACb,QAAQ,MAAM,QAAQ,QAAQ,MAAM,EAAE,GAAI,cAAc,mBAAmB,CAAC,IAAI,aAAa;EAC9F;;AAGH,SAAS,oBAAoB,OAAoC;AAC/D,SAAQ,OAAR;EACE,KAAKC,kBAAAA,cAAc,WACjB,QAAO;EACT,KAAKA,kBAAAA,cAAc,MACjB,QAAO;;AAGX,OAAM,IAAI,MAAM,2BAA2B,MAAM;;AAGnD,SAAS,aAAa,OAA2C;CAC/D,MAAM,IAAI,MAAM,OAAO,MAAM,MAAM,GAAG,IAAI,cAAc,mBAAmB;AAC3E,KAAI,CAAC,EAAG,QAAA;CACR,MAAM,QAAQ,EAAE,SAAS;AACzB,KAAI,UAAU,GAAI,QAAA;AAClB,QAAOF,cAAAA,uBAAuB,OAAOC,cAAAA,oBAAoB,EAAE,eAAe,CAAC;;AAG7E,SAAgB,aAAa,OAAyB;AACpD,QAAO;EACL,OAAA,GAAA,2BAAA,UAAe,MAAM,IAAI,UAAU;EACnC,MAAM,iBAAiB,MAAM,KAAK;EAClC,QAAQ,mBAAmB,MAAM,YAAY;EAC7C,OAAO,4BAA4B,MAAM,OAAO,MAAM,eAAe;EACrE,OAAO,4BAA4B,MAAM,OAAO,MAAM,eAAe;EACrE,cAAc,MAAM;EACrB;;AAGH,SAAS,iBAAiB,OAAiC;AACzD,SAAQ,OAAR;EACE,KAAKE,mBAAAA,UAAc,MACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,OACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,QACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,kBACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,QACjB,QAAO;EACT,KAAKA,mBAAAA,UAAc,wBACjB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,wBAAwB,MAAM;;;AAIpD,SAAS,mBAAmB,OAAuC;AACjE,SAAQ,OAAR;EACE,KAAKC,kBAAAA,kBAAkB,MACrB,QAAO;EACT,KAAKA,kBAAAA,kBAAkB,SACrB,QAAO;EACT,KAAKA,kBAAAA,kBAAkB,SACrB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,0BAA0B,MAAM;;;AAItD,SAAgB,iBAAiB,MAAgC;AAC/D,SAAQ,MAAR;EACE,KAAK,QACH,QAAOD,mBAAAA,UAAc;EACvB,KAAK,SACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,UACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,UACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,MACH,QAAOA,mBAAAA,UAAc;EACvB,KAAK,MACH,QAAOA,mBAAAA,UAAc;EACvB,QACE,SAAA,GAAA,2BAAA,aAAmB,KAAK"}
@@ -1,4 +1,4 @@
1
- import "./types.js";
1
+ import { createSignedResourceId, toResourceSignature } from "./types.js";
2
2
  import { FieldType } from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js";
3
3
  import { Field_ValueStatus, Resource_Kind } from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js";
4
4
  import { throwPlNotFoundError } from "./errors.js";
@@ -8,12 +8,16 @@ const ResourceErrorField = "resourceError";
8
8
  function resourceIsDeleted(proto) {
9
9
  return proto.deletedTime !== void 0 && proto.deletedTime.seconds !== 0n;
10
10
  }
11
+ function protoIdToOptionalResourceId(id, signature) {
12
+ if (id === 0n) return "";
13
+ return createSignedResourceId(id, toResourceSignature(signature));
14
+ }
11
15
  /** Throws "native" pl not found error, if resource is marked as deleted. */
12
16
  function protoToResource(proto) {
13
17
  if (resourceIsDeleted(proto)) throwPlNotFoundError("resource deleted");
14
18
  return {
15
- id: proto.resourceId,
16
- originalResourceId: proto.originalResourceId,
19
+ id: createSignedResourceId(proto.resourceId, toResourceSignature(proto.resourceSignature)),
20
+ originalResourceId: protoIdToOptionalResourceId(proto.originalResourceId, proto.originalResourceSignature),
17
21
  type: notEmpty(proto.type),
18
22
  data: proto.data,
19
23
  inputsLocked: proto.inputsLocked,
@@ -33,15 +37,19 @@ function protoToResourceKind(proto) {
33
37
  throw new Error("invalid ResourceKind: " + proto);
34
38
  }
35
39
  function protoToError(proto) {
36
- return proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField)?.error ?? 0n;
40
+ const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);
41
+ if (!f) return "";
42
+ const errId = f.error ?? 0n;
43
+ if (errId === 0n) return "";
44
+ return createSignedResourceId(errId, toResourceSignature(f.errorSignature));
37
45
  }
38
46
  function protoToField(proto) {
39
47
  return {
40
48
  name: notEmpty(proto.id?.fieldName),
41
49
  type: protoToFieldType(proto.type),
42
50
  status: protoToFieldStatus(proto.valueStatus),
43
- value: proto.value,
44
- error: proto.error,
51
+ value: protoIdToOptionalResourceId(proto.value, proto.valueSignature),
52
+ error: protoIdToOptionalResourceId(proto.error, proto.errorSignature),
45
53
  valueIsFinal: proto.valueIsFinal
46
54
  };
47
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"type_conversion.js","names":["GrpcFieldType"],"sources":["../../src/core/type_conversion.ts"],"sourcesContent":["import type {\n Field,\n Resource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport {\n Field_ValueStatus,\n Resource_Kind,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport { FieldType as GrpcFieldType } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types\";\nimport type {\n FieldData,\n FieldStatus,\n OptionalResourceId,\n FieldType,\n ResourceData,\n ResourceId,\n ResourceKind,\n} from \"./types\";\nimport { NullResourceId } from \"./types\";\nimport { assertNever, notEmpty } from \"@milaboratories/ts-helpers\";\nimport { throwPlNotFoundError } from \"./errors\";\n\nconst ResourceErrorField = \"resourceError\";\n\nfunction resourceIsDeleted(proto: Resource): boolean {\n return proto.deletedTime !== undefined && proto.deletedTime.seconds !== 0n;\n}\n\n/** Throws \"native\" pl not found error, if resource is marked as deleted. */\nexport function protoToResource(proto: Resource): ResourceData {\n if (resourceIsDeleted(proto)) throwPlNotFoundError(\"resource deleted\");\n return {\n id: proto.resourceId as ResourceId,\n originalResourceId: proto.originalResourceId as OptionalResourceId,\n type: notEmpty(proto.type),\n data: proto.data,\n inputsLocked: proto.inputsLocked,\n outputsLocked: proto.outputsLocked,\n resourceReady: proto.resourceReady,\n kind: protoToResourceKind(proto.kind),\n error: protoToError(proto),\n final: proto.isFinal,\n fields: proto.fields?.filter((f) => f.id!.fieldName !== ResourceErrorField).map(protoToField),\n };\n}\n\nfunction protoToResourceKind(proto: Resource_Kind): ResourceKind {\n switch (proto) {\n case Resource_Kind.STRUCTURAL:\n return \"Structural\";\n case Resource_Kind.VALUE:\n return \"Value\";\n }\n\n throw new Error(\"invalid ResourceKind: \" + proto);\n}\n\nfunction protoToError(proto: Resource): OptionalResourceId {\n const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);\n return (f?.error ?? NullResourceId) as OptionalResourceId;\n}\n\nexport function protoToField(proto: Field): FieldData {\n return {\n name: notEmpty(proto.id?.fieldName),\n type: protoToFieldType(proto.type),\n status: protoToFieldStatus(proto.valueStatus),\n value: proto.value as OptionalResourceId,\n error: proto.error as OptionalResourceId,\n valueIsFinal: proto.valueIsFinal,\n };\n}\n\nfunction protoToFieldType(proto: GrpcFieldType): FieldType {\n switch (proto) {\n case GrpcFieldType.INPUT:\n return \"Input\";\n case GrpcFieldType.OUTPUT:\n return \"Output\";\n case GrpcFieldType.SERVICE:\n return \"Service\";\n case GrpcFieldType.ONE_TIME_WRITABLE:\n return \"OTW\";\n case GrpcFieldType.DYNAMIC:\n return \"Dynamic\";\n case GrpcFieldType.MULTIPLE_TIMES_WRITABLE:\n return \"MTW\";\n default:\n throw new Error(\"invalid FieldType: \" + proto);\n }\n}\n\nfunction protoToFieldStatus(proto: Field_ValueStatus): FieldStatus {\n switch (proto) {\n case Field_ValueStatus.EMPTY:\n return \"Empty\";\n case Field_ValueStatus.ASSIGNED:\n return \"Assigned\";\n case Field_ValueStatus.RESOLVED:\n return \"Resolved\";\n default:\n throw new Error(\"invalid FieldStatus: \" + proto);\n }\n}\n\nexport function fieldTypeToProto(type: FieldType): GrpcFieldType {\n switch (type) {\n case \"Input\":\n return GrpcFieldType.INPUT;\n case \"Output\":\n return GrpcFieldType.OUTPUT;\n case \"Dynamic\":\n return GrpcFieldType.DYNAMIC;\n case \"Service\":\n return GrpcFieldType.SERVICE;\n case \"MTW\":\n return GrpcFieldType.MULTIPLE_TIMES_WRITABLE;\n case \"OTW\":\n return GrpcFieldType.ONE_TIME_WRITABLE;\n default:\n return assertNever(type);\n }\n}\n"],"mappings":";;;;;;AAsBA,MAAM,qBAAqB;AAE3B,SAAS,kBAAkB,OAA0B;AACnD,QAAO,MAAM,gBAAgB,KAAA,KAAa,MAAM,YAAY,YAAY;;;AAI1E,SAAgB,gBAAgB,OAA+B;AAC7D,KAAI,kBAAkB,MAAM,CAAE,sBAAqB,mBAAmB;AACtE,QAAO;EACL,IAAI,MAAM;EACV,oBAAoB,MAAM;EAC1B,MAAM,SAAS,MAAM,KAAK;EAC1B,MAAM,MAAM;EACZ,cAAc,MAAM;EACpB,eAAe,MAAM;EACrB,eAAe,MAAM;EACrB,MAAM,oBAAoB,MAAM,KAAK;EACrC,OAAO,aAAa,MAAM;EAC1B,OAAO,MAAM;EACb,QAAQ,MAAM,QAAQ,QAAQ,MAAM,EAAE,GAAI,cAAc,mBAAmB,CAAC,IAAI,aAAa;EAC9F;;AAGH,SAAS,oBAAoB,OAAoC;AAC/D,SAAQ,OAAR;EACE,KAAK,cAAc,WACjB,QAAO;EACT,KAAK,cAAc,MACjB,QAAO;;AAGX,OAAM,IAAI,MAAM,2BAA2B,MAAM;;AAGnD,SAAS,aAAa,OAAqC;AAEzD,QADU,MAAM,OAAO,MAAM,MAAM,GAAG,IAAI,cAAc,mBAAmB,EAChE,SAAA;;AAGb,SAAgB,aAAa,OAAyB;AACpD,QAAO;EACL,MAAM,SAAS,MAAM,IAAI,UAAU;EACnC,MAAM,iBAAiB,MAAM,KAAK;EAClC,QAAQ,mBAAmB,MAAM,YAAY;EAC7C,OAAO,MAAM;EACb,OAAO,MAAM;EACb,cAAc,MAAM;EACrB;;AAGH,SAAS,iBAAiB,OAAiC;AACzD,SAAQ,OAAR;EACE,KAAKA,UAAc,MACjB,QAAO;EACT,KAAKA,UAAc,OACjB,QAAO;EACT,KAAKA,UAAc,QACjB,QAAO;EACT,KAAKA,UAAc,kBACjB,QAAO;EACT,KAAKA,UAAc,QACjB,QAAO;EACT,KAAKA,UAAc,wBACjB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,wBAAwB,MAAM;;;AAIpD,SAAS,mBAAmB,OAAuC;AACjE,SAAQ,OAAR;EACE,KAAK,kBAAkB,MACrB,QAAO;EACT,KAAK,kBAAkB,SACrB,QAAO;EACT,KAAK,kBAAkB,SACrB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,0BAA0B,MAAM;;;AAItD,SAAgB,iBAAiB,MAAgC;AAC/D,SAAQ,MAAR;EACE,KAAK,QACH,QAAOA,UAAc;EACvB,KAAK,SACH,QAAOA,UAAc;EACvB,KAAK,UACH,QAAOA,UAAc;EACvB,KAAK,UACH,QAAOA,UAAc;EACvB,KAAK,MACH,QAAOA,UAAc;EACvB,KAAK,MACH,QAAOA,UAAc;EACvB,QACE,QAAO,YAAY,KAAK"}
1
+ {"version":3,"file":"type_conversion.js","names":["GrpcFieldType"],"sources":["../../src/core/type_conversion.ts"],"sourcesContent":["import type {\n Field,\n Resource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport {\n Field_ValueStatus,\n Resource_Kind,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types\";\nimport { FieldType as GrpcFieldType } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types\";\nimport type {\n FieldData,\n FieldStatus,\n OptionalSignedResourceId,\n FieldType,\n ResourceData,\n ResourceKind,\n} from \"./types\";\nimport {\n createSignedResourceId,\n NullSignedResourceId,\n toResourceSignature,\n NullResourceId,\n} from \"./types\";\nimport { assertNever, notEmpty } from \"@milaboratories/ts-helpers\";\nimport { throwPlNotFoundError } from \"./errors\";\n\nconst ResourceErrorField = \"resourceError\";\n\nfunction resourceIsDeleted(proto: Resource): boolean {\n return proto.deletedTime !== undefined && proto.deletedTime.seconds !== 0n;\n}\n\nfunction protoIdToOptionalResourceId(id: bigint, signature?: Uint8Array): OptionalSignedResourceId {\n if (id === NullResourceId) return NullSignedResourceId;\n return createSignedResourceId(id, toResourceSignature(signature));\n}\n\n/** Throws \"native\" pl not found error, if resource is marked as deleted. */\nexport function protoToResource(proto: Resource): ResourceData {\n if (resourceIsDeleted(proto)) throwPlNotFoundError(\"resource deleted\");\n return {\n id: createSignedResourceId(proto.resourceId, toResourceSignature(proto.resourceSignature)),\n originalResourceId: protoIdToOptionalResourceId(\n proto.originalResourceId,\n proto.originalResourceSignature,\n ),\n type: notEmpty(proto.type),\n data: proto.data,\n inputsLocked: proto.inputsLocked,\n outputsLocked: proto.outputsLocked,\n resourceReady: proto.resourceReady,\n kind: protoToResourceKind(proto.kind),\n error: protoToError(proto),\n final: proto.isFinal,\n fields: proto.fields?.filter((f) => f.id!.fieldName !== ResourceErrorField).map(protoToField),\n };\n}\n\nfunction protoToResourceKind(proto: Resource_Kind): ResourceKind {\n switch (proto) {\n case Resource_Kind.STRUCTURAL:\n return \"Structural\";\n case Resource_Kind.VALUE:\n return \"Value\";\n }\n\n throw new Error(\"invalid ResourceKind: \" + proto);\n}\n\nfunction protoToError(proto: Resource): OptionalSignedResourceId {\n const f = proto.fields.find((f) => f?.id?.fieldName === ResourceErrorField);\n if (!f) return NullSignedResourceId;\n const errId = f.error ?? 0n;\n if (errId === 0n) return NullSignedResourceId;\n return createSignedResourceId(errId, toResourceSignature(f.errorSignature));\n}\n\nexport function protoToField(proto: Field): FieldData {\n return {\n name: notEmpty(proto.id?.fieldName),\n type: protoToFieldType(proto.type),\n status: protoToFieldStatus(proto.valueStatus),\n value: protoIdToOptionalResourceId(proto.value, proto.valueSignature),\n error: protoIdToOptionalResourceId(proto.error, proto.errorSignature),\n valueIsFinal: proto.valueIsFinal,\n };\n}\n\nfunction protoToFieldType(proto: GrpcFieldType): FieldType {\n switch (proto) {\n case GrpcFieldType.INPUT:\n return \"Input\";\n case GrpcFieldType.OUTPUT:\n return \"Output\";\n case GrpcFieldType.SERVICE:\n return \"Service\";\n case GrpcFieldType.ONE_TIME_WRITABLE:\n return \"OTW\";\n case GrpcFieldType.DYNAMIC:\n return \"Dynamic\";\n case GrpcFieldType.MULTIPLE_TIMES_WRITABLE:\n return \"MTW\";\n default:\n throw new Error(\"invalid FieldType: \" + proto);\n }\n}\n\nfunction protoToFieldStatus(proto: Field_ValueStatus): FieldStatus {\n switch (proto) {\n case Field_ValueStatus.EMPTY:\n return \"Empty\";\n case Field_ValueStatus.ASSIGNED:\n return \"Assigned\";\n case Field_ValueStatus.RESOLVED:\n return \"Resolved\";\n default:\n throw new Error(\"invalid FieldStatus: \" + proto);\n }\n}\n\nexport function fieldTypeToProto(type: FieldType): GrpcFieldType {\n switch (type) {\n case \"Input\":\n return GrpcFieldType.INPUT;\n case \"Output\":\n return GrpcFieldType.OUTPUT;\n case \"Dynamic\":\n return GrpcFieldType.DYNAMIC;\n case \"Service\":\n return GrpcFieldType.SERVICE;\n case \"MTW\":\n return GrpcFieldType.MULTIPLE_TIMES_WRITABLE;\n case \"OTW\":\n return GrpcFieldType.ONE_TIME_WRITABLE;\n default:\n return assertNever(type);\n }\n}\n"],"mappings":";;;;;;AA0BA,MAAM,qBAAqB;AAE3B,SAAS,kBAAkB,OAA0B;AACnD,QAAO,MAAM,gBAAgB,KAAA,KAAa,MAAM,YAAY,YAAY;;AAG1E,SAAS,4BAA4B,IAAY,WAAkD;AACjG,KAAI,OAAA,GAAuB,QAAA;AAC3B,QAAO,uBAAuB,IAAI,oBAAoB,UAAU,CAAC;;;AAInE,SAAgB,gBAAgB,OAA+B;AAC7D,KAAI,kBAAkB,MAAM,CAAE,sBAAqB,mBAAmB;AACtE,QAAO;EACL,IAAI,uBAAuB,MAAM,YAAY,oBAAoB,MAAM,kBAAkB,CAAC;EAC1F,oBAAoB,4BAClB,MAAM,oBACN,MAAM,0BACP;EACD,MAAM,SAAS,MAAM,KAAK;EAC1B,MAAM,MAAM;EACZ,cAAc,MAAM;EACpB,eAAe,MAAM;EACrB,eAAe,MAAM;EACrB,MAAM,oBAAoB,MAAM,KAAK;EACrC,OAAO,aAAa,MAAM;EAC1B,OAAO,MAAM;EACb,QAAQ,MAAM,QAAQ,QAAQ,MAAM,EAAE,GAAI,cAAc,mBAAmB,CAAC,IAAI,aAAa;EAC9F;;AAGH,SAAS,oBAAoB,OAAoC;AAC/D,SAAQ,OAAR;EACE,KAAK,cAAc,WACjB,QAAO;EACT,KAAK,cAAc,MACjB,QAAO;;AAGX,OAAM,IAAI,MAAM,2BAA2B,MAAM;;AAGnD,SAAS,aAAa,OAA2C;CAC/D,MAAM,IAAI,MAAM,OAAO,MAAM,MAAM,GAAG,IAAI,cAAc,mBAAmB;AAC3E,KAAI,CAAC,EAAG,QAAA;CACR,MAAM,QAAQ,EAAE,SAAS;AACzB,KAAI,UAAU,GAAI,QAAA;AAClB,QAAO,uBAAuB,OAAO,oBAAoB,EAAE,eAAe,CAAC;;AAG7E,SAAgB,aAAa,OAAyB;AACpD,QAAO;EACL,MAAM,SAAS,MAAM,IAAI,UAAU;EACnC,MAAM,iBAAiB,MAAM,KAAK;EAClC,QAAQ,mBAAmB,MAAM,YAAY;EAC7C,OAAO,4BAA4B,MAAM,OAAO,MAAM,eAAe;EACrE,OAAO,4BAA4B,MAAM,OAAO,MAAM,eAAe;EACrE,cAAc,MAAM;EACrB;;AAGH,SAAS,iBAAiB,OAAiC;AACzD,SAAQ,OAAR;EACE,KAAKA,UAAc,MACjB,QAAO;EACT,KAAKA,UAAc,OACjB,QAAO;EACT,KAAKA,UAAc,QACjB,QAAO;EACT,KAAKA,UAAc,kBACjB,QAAO;EACT,KAAKA,UAAc,QACjB,QAAO;EACT,KAAKA,UAAc,wBACjB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,wBAAwB,MAAM;;;AAIpD,SAAS,mBAAmB,OAAuC;AACjE,SAAQ,OAAR;EACE,KAAK,kBAAkB,MACrB,QAAO;EACT,KAAK,kBAAkB,SACrB,QAAO;EACT,KAAK,kBAAkB,SACrB,QAAO;EACT,QACE,OAAM,IAAI,MAAM,0BAA0B,MAAM;;;AAItD,SAAgB,iBAAiB,MAAgC;AAC/D,SAAQ,MAAR;EACE,KAAK,QACH,QAAOA,UAAc;EACvB,KAAK,SACH,QAAOA,UAAc;EACvB,KAAK,UACH,QAAOA,UAAc;EACvB,KAAK,UACH,QAAOA,UAAc;EACvB,KAAK,MACH,QAAOA,UAAc;EACvB,KAAK,MACH,QAAOA,UAAc;EACvB,QACE,QAAO,YAAY,KAAK"}
@@ -5,13 +5,6 @@ const NullResourceId = 0n;
5
5
  function isNullResourceId(resourceId) {
6
6
  return resourceId === NullResourceId;
7
7
  }
8
- function isNotNullResourceId(resourceId) {
9
- return resourceId !== NullResourceId;
10
- }
11
- function ensureResourceIdNotNull(resourceId) {
12
- if (!isNotNullResourceId(resourceId)) throw new Error("null resource id");
13
- return resourceId;
14
- }
15
8
  function isAnyResourceId(resourceId) {
16
9
  return resourceId !== 0n;
17
10
  }
@@ -24,6 +17,13 @@ function resourceType(name, version) {
24
17
  function resourceTypeToString(rt) {
25
18
  return `${rt.name}:${rt.version}`;
26
19
  }
20
+ function parseResourceType(str) {
21
+ const [name, version] = str.split(":");
22
+ return {
23
+ name,
24
+ version
25
+ };
26
+ }
27
27
  function resourceTypesEqual(type1, type2) {
28
28
  return type1.name === type2.name && type1.version === type2.version;
29
29
  }
@@ -60,6 +60,7 @@ function isRootResourceId(id) {
60
60
  return (id & ResourceIdRootMask) !== 0n;
61
61
  }
62
62
  function isLocalResourceId(id) {
63
+ if (typeof id === "string") return false;
63
64
  return (id & ResourceIdLocalMask) !== 0n;
64
65
  }
65
66
  function createLocalResourceId(isRoot, localCounterValue, localTxId) {
@@ -77,6 +78,8 @@ function checkLocalityOfResourceId(resourceId, expectedTxId) {
77
78
  if (extractTxId(resourceId) !== expectedTxId) throw Error("local id from another transaction, globalize id before leaking it from the transaction");
78
79
  }
79
80
  function resourceIdToString(resourceId) {
81
+ if (isSignedResourceId(resourceId)) resourceId = anyResourceIdToBigint(resourceId);
82
+ if (isNullSignedResourceId(resourceId)) return "XX:0x0";
80
83
  if (isNullResourceId(resourceId)) return "XX:0x0";
81
84
  if (isLocalResourceId(resourceId)) return (isRootResourceId(resourceId) ? "R" : "N") + "L:0x" + (LocalIdMask & resourceId).toString(16) + "[0x" + extractTxId(resourceId).toString(16) + "]";
82
85
  else return (isRootResourceId(resourceId) ? "R" : "N") + "G:0x" + (NoFlagsIdMask & resourceId).toString(16);
@@ -90,39 +93,96 @@ function resourceIdFromString(str) {
90
93
  if (lg === "L") return createLocalResourceId(rn === "R", Number.parseInt(rid, 16), Number.parseInt(txid, 16));
91
94
  else return createGlobalResourceId(rn === "R", BigInt("0x" + rid));
92
95
  }
93
- /** Converts bigint to global resource id */
94
- function bigintToResourceId(resourceId) {
95
- if (isLocalResourceId(resourceId)) throw new Error(`Local resource id: ${resourceIdToString(resourceId)}`);
96
- if (isNullResourceId(resourceId)) throw new Error(`Null resource id.`);
97
- return resourceId;
96
+ function anyResourceIdToBigint(resourceId) {
97
+ if (typeof resourceId !== "string") return resourceId;
98
+ return parseSignedResourceId(resourceId).globalId;
98
99
  }
99
100
  function stringifyWithResourceId(object) {
100
- return JSON.stringify(object, (key, value) => typeof value === "bigint" ? resourceIdToString(value) : value);
101
+ return JSON.stringify(object, (key, value) => {
102
+ if (typeof value === "bigint") return resourceIdToString(value);
103
+ if (isSignedResourceId(value)) return resourceIdToString(value);
104
+ return value;
105
+ });
106
+ }
107
+ const NullSignedResourceId = "";
108
+ function isNullSignedResourceId(resourceId) {
109
+ return resourceId === "";
110
+ }
111
+ function isNotNullSignedResourceId(resourceId) {
112
+ return resourceId !== "";
113
+ }
114
+ function ensureSignedResourceIdNotNull(resourceId) {
115
+ if (!isNotNullSignedResourceId(resourceId)) throw new Error("null resource id");
116
+ return resourceId;
117
+ }
118
+ function isSignedResourceId(resourceId) {
119
+ return typeof resourceId === "string" && resourceId.includes("|");
120
+ }
121
+ /** Encode resource signature to base64url for embedding in URL-based handles. */
122
+ function signatureToBase64Url(sig) {
123
+ return sig && sig.length > 0 ? Buffer.from(sig).toString("base64url") : "";
124
+ }
125
+ /** Cast raw bytes to a branded ResourceSignature, returning undefined for empty/missing input. */
126
+ function toResourceSignature(raw) {
127
+ return raw && raw.length > 0 ? raw : new Uint8Array(0);
128
+ }
129
+ /** Decode base64url-encoded string back to a branded ResourceSignature. */
130
+ function base64UrlToSignature(str) {
131
+ return toResourceSignature(Buffer.from(str, "base64url"));
132
+ }
133
+ /** Converts bigint global resource id and signature to a SignedResourceId string.
134
+ * Format: "<globalIdString>|<signatureHex>" */
135
+ function createSignedResourceId(globalId, signature) {
136
+ if (isLocalResourceId(globalId)) throw new Error(`Local resource id: ${resourceIdToString(globalId)}`);
137
+ if (isNullResourceId(globalId)) throw new Error(`Null resource id.`);
138
+ const sigHex = signature ? Buffer.from(signature).toString("hex") : "";
139
+ return `${String(globalId)}|${sigHex}`;
140
+ }
141
+ function parseSignedResourceId(resourceId) {
142
+ if (typeof resourceId !== "string") throw new Error(`Not a signed resource id: ${resourceId}`);
143
+ const pipeIdx = resourceId.indexOf("|");
144
+ if (pipeIdx < 0) throw new Error(`Malformed signed resource id (no '|'): ${resourceId}`);
145
+ const globalIdStr = resourceId.substring(0, pipeIdx);
146
+ const signatureHex = resourceId.substring(pipeIdx + 1);
147
+ const globalId = BigInt(globalIdStr);
148
+ if (isNullSignedResourceId(globalId) || isLocalResourceId(globalId)) throw new Error(`Invalid global id portion in signed resource id: ${globalIdStr}`);
149
+ return {
150
+ globalId,
151
+ signature: signatureHex.length > 0 ? Buffer.from(signatureHex, "hex") : new Uint8Array(0)
152
+ };
101
153
  }
102
154
  //#endregion
103
155
  exports.MaxLocalId = MaxLocalId;
104
156
  exports.MaxTxId = MaxTxId;
105
157
  exports.NullResourceId = NullResourceId;
106
- exports.bigintToResourceId = bigintToResourceId;
158
+ exports.NullSignedResourceId = NullSignedResourceId;
159
+ exports.anyResourceIdToBigint = anyResourceIdToBigint;
160
+ exports.base64UrlToSignature = base64UrlToSignature;
107
161
  exports.checkLocalityOfResourceId = checkLocalityOfResourceId;
108
162
  exports.createGlobalResourceId = createGlobalResourceId;
109
163
  exports.createLocalResourceId = createLocalResourceId;
110
- exports.ensureResourceIdNotNull = ensureResourceIdNotNull;
164
+ exports.createSignedResourceId = createSignedResourceId;
165
+ exports.ensureSignedResourceIdNotNull = ensureSignedResourceIdNotNull;
111
166
  exports.extractBasicResourceData = extractBasicResourceData;
112
167
  exports.extractTxId = extractTxId;
113
168
  exports.getField = getField;
114
169
  exports.isAnyResourceId = isAnyResourceId;
115
170
  exports.isLocalResourceId = isLocalResourceId;
116
- exports.isNotNullResourceId = isNotNullResourceId;
117
- exports.isNullResourceId = isNullResourceId;
171
+ exports.isNotNullSignedResourceId = isNotNullSignedResourceId;
172
+ exports.isNullSignedResourceId = isNullSignedResourceId;
118
173
  exports.isRootResourceId = isRootResourceId;
174
+ exports.isSignedResourceId = isSignedResourceId;
119
175
  exports.jsonToData = jsonToData;
176
+ exports.parseResourceType = parseResourceType;
177
+ exports.parseSignedResourceId = parseSignedResourceId;
120
178
  exports.resDataToJson = resDataToJson;
121
179
  exports.resourceIdFromString = resourceIdFromString;
122
180
  exports.resourceIdToString = resourceIdToString;
123
181
  exports.resourceType = resourceType;
124
182
  exports.resourceTypeToString = resourceTypeToString;
125
183
  exports.resourceTypesEqual = resourceTypesEqual;
184
+ exports.signatureToBase64Url = signatureToBase64Url;
126
185
  exports.stringifyWithResourceId = stringifyWithResourceId;
186
+ exports.toResourceSignature = toResourceSignature;
127
187
 
128
188
  //# sourceMappingURL=types.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs","names":[],"sources":["../../src/core/types.ts"],"sourcesContent":["import { cachedDeserialize, notEmpty } from \"@milaboratories/ts-helpers\";\n\n// more details here: https://egghead.io/blog/using-branded-types-in-typescript\ndeclare const __resource_id_type__: unique symbol;\ntype BrandResourceId<B> = bigint & { [__resource_id_type__]: B };\n\n/** Global resource id */\nexport type ResourceId = BrandResourceId<\"global\">;\n\n/** Null resource id */\nexport type NullResourceId = BrandResourceId<\"null\">;\n\n/** Local resource id */\nexport type LocalResourceId = BrandResourceId<\"local\">;\n\n/** Any non-null resource id */\nexport type AnyResourceId = ResourceId | LocalResourceId;\n\n/** Any resource id */\nexport type OptionalResourceId = NullResourceId | ResourceId;\n\n/** All possible resource flavours */\nexport type OptionalAnyResourceId = NullResourceId | ResourceId | LocalResourceId;\n\nexport const NullResourceId = 0n as NullResourceId;\n\nexport function isNullResourceId(resourceId: bigint): resourceId is NullResourceId {\n return resourceId === NullResourceId;\n}\n\nexport function isNotNullResourceId(resourceId: OptionalResourceId): resourceId is ResourceId {\n return resourceId !== NullResourceId;\n}\n\nexport function ensureResourceIdNotNull(resourceId: OptionalResourceId): ResourceId {\n if (!isNotNullResourceId(resourceId)) throw new Error(\"null resource id\");\n return resourceId;\n}\n\nexport function isAnyResourceId(resourceId: bigint): resourceId is AnyResourceId {\n return resourceId !== 0n;\n}\n\n// see local / global resource logic below...\n\nexport type ResourceKind = \"Structural\" | \"Value\";\n\nexport type FieldType = \"Input\" | \"Output\" | \"Service\" | \"OTW\" | \"Dynamic\" | \"MTW\";\n\nexport type FutureFieldType = \"Output\" | \"Input\" | \"Service\";\n\nexport type FieldStatus = \"Empty\" | \"Assigned\" | \"Resolved\";\n\nexport interface ResourceType {\n readonly name: string;\n readonly version: string;\n}\n\nexport function resourceType(name: string, version: string): ResourceType {\n return { name, version };\n}\n\nexport function resourceTypeToString(rt: ResourceType): string {\n return `${rt.name}:${rt.version}`;\n}\n\nexport function resourceTypesEqual(type1: ResourceType, type2: ResourceType): boolean {\n return type1.name === type2.name && type1.version === type2.version;\n}\n\n/** Readonly fields here marks properties of resource that can't change according to pl's state machine. */\nexport type BasicResourceData = {\n readonly id: ResourceId;\n readonly originalResourceId: OptionalResourceId;\n\n readonly kind: ResourceKind;\n readonly type: ResourceType;\n\n readonly data?: Uint8Array;\n\n readonly error: OptionalResourceId;\n\n readonly inputsLocked: boolean;\n readonly outputsLocked: boolean;\n readonly resourceReady: boolean;\n\n /** This value is derived from resource state by the server and can be used as\n * a robust criteria to determine resource is in final state. */\n readonly final: boolean;\n};\n\nexport function extractBasicResourceData(rd: ResourceData): BasicResourceData {\n const {\n id,\n originalResourceId,\n kind,\n type,\n data,\n error,\n inputsLocked,\n outputsLocked,\n resourceReady,\n final,\n } = rd;\n return {\n id,\n originalResourceId,\n kind,\n type,\n data,\n error,\n inputsLocked,\n outputsLocked,\n resourceReady,\n final,\n };\n}\n\nexport const jsonToData = (data: unknown) => Buffer.from(JSON.stringify(data));\n\nexport const resDataToJson = (res: ResourceData) => cachedDeserialize(notEmpty(res.data));\n\nexport type ResourceData = BasicResourceData & {\n readonly fields: FieldData[];\n};\n\nexport function getField(r: ResourceData, name: string): FieldData {\n return notEmpty(r.fields.find((f) => f.name === name));\n}\n\nexport type FieldData = {\n readonly name: string;\n readonly type: FieldType;\n readonly status: FieldStatus;\n readonly value: OptionalResourceId;\n readonly error: OptionalResourceId;\n\n /** True if value the fields points to is in final state. */\n readonly valueIsFinal: boolean;\n};\n\n//\n// Local / Global ResourceId arithmetics\n//\n\n// Note: txId and other numerical values are made numbers but not bigint intentionally,\n// after implementing security model based on signed resource ids this will make\n// much more sense\n\nconst ResourceIdRootMask = 1n << 63n;\nconst ResourceIdLocalMask = 1n << 62n;\nconst NoFlagsIdMask = 0x3fffffffffffffffn;\nconst LocalResourceIdTxIdOffset = 24n;\nexport const MaxLocalId = 0xffffff;\nexport const MaxTxId = 0xffffffff;\n/** Mask valid after applying shift */\nconst TxIdMask = BigInt(MaxTxId);\nconst LocalIdMask = BigInt(MaxLocalId);\n\n// /** Basically removes embedded tx id */\n// const LocalIdCleanMask = 0xFF00000000FFFFFFn;\n\nexport function isRootResourceId(id: bigint) {\n return (id & ResourceIdRootMask) !== 0n;\n}\n\nexport function isLocalResourceId(id: bigint): id is LocalResourceId {\n return (id & ResourceIdLocalMask) !== 0n;\n}\n\nexport function createLocalResourceId(\n isRoot: boolean,\n localCounterValue: number,\n localTxId: number,\n): LocalResourceId {\n if (\n localCounterValue > MaxLocalId ||\n localTxId > MaxTxId ||\n localCounterValue < 0 ||\n localTxId <= 0\n )\n throw Error(\"wrong local id or tx id\");\n return ((isRoot ? ResourceIdRootMask : 0n) |\n ResourceIdLocalMask |\n BigInt(localCounterValue) |\n (BigInt(localTxId) << LocalResourceIdTxIdOffset)) as LocalResourceId;\n}\n\nexport function createGlobalResourceId(isRoot: boolean, unmaskedId: bigint): ResourceId {\n return ((isRoot ? ResourceIdRootMask : 0n) | unmaskedId) as ResourceId;\n}\n\nexport function extractTxId(localResourceId: LocalResourceId): number {\n return Number((localResourceId >> LocalResourceIdTxIdOffset) & TxIdMask);\n}\n\nexport function checkLocalityOfResourceId(resourceId: AnyResourceId, expectedTxId: number): void {\n if (!isLocalResourceId(resourceId)) return;\n if (extractTxId(resourceId) !== expectedTxId)\n throw Error(\n \"local id from another transaction, globalize id before leaking it from the transaction\",\n );\n}\n\nexport function resourceIdToString(resourceId: OptionalAnyResourceId): string {\n if (isNullResourceId(resourceId)) return \"XX:0x0\";\n if (isLocalResourceId(resourceId))\n return (\n (isRootResourceId(resourceId) ? \"R\" : \"N\") +\n \"L:0x\" +\n (LocalIdMask & resourceId).toString(16) +\n \"[0x\" +\n extractTxId(resourceId).toString(16) +\n \"]\"\n );\n else\n return (\n (isRootResourceId(resourceId) ? \"R\" : \"N\") +\n \"G:0x\" +\n (NoFlagsIdMask & resourceId).toString(16)\n );\n}\n\nconst resourceIdRegexp =\n /^(?:(?<xx>XX)|(?<rn>[XRN])(?<lg>[XLG])):0x(?<rid>[0-9a-fA-F]+)(?:\\[0x(?<txid>[0-9a-fA-F]+)])?$/;\n\nexport function resourceIdFromString(str: string): OptionalAnyResourceId | undefined {\n const match = str.match(resourceIdRegexp);\n if (match === null) return undefined;\n const { xx, rn, lg, rid, txid } = match.groups!;\n if (xx) return NullResourceId;\n if (lg === \"L\")\n return createLocalResourceId(rn === \"R\", Number.parseInt(rid, 16), Number.parseInt(txid, 16));\n else return createGlobalResourceId(rn === \"R\", BigInt(\"0x\" + rid));\n}\n\n/** Converts bigint to global resource id */\nexport function bigintToResourceId(resourceId: bigint): ResourceId {\n if (isLocalResourceId(resourceId))\n throw new Error(`Local resource id: ${resourceIdToString(resourceId)}`);\n if (isNullResourceId(resourceId)) throw new Error(`Null resource id.`);\n return resourceId as ResourceId;\n}\n\nexport function stringifyWithResourceId(object: unknown): string {\n return JSON.stringify(object, (key, value) =>\n typeof value === \"bigint\" ? resourceIdToString(value as OptionalAnyResourceId) : value,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"types.cjs","names":[],"sources":["../../src/core/types.ts"],"sourcesContent":["import type { Branded } from \"@milaboratories/pl-model-common\";\nimport { cachedDeserialize, notEmpty } from \"@milaboratories/ts-helpers\";\n\n/** Null resource id */\nexport type NullResourceId = Branded<bigint, \"null\", \"__resource_id__\">;\n\n/** Global resource id */\nexport type GlobalResourceId = Branded<bigint, \"global\", \"__resource_id__\">;\n\n/** Local resource id */\nexport type LocalResourceId = Branded<bigint, \"local\", \"__resource_id__\">;\n\n/** Any non-null resource id */\nexport type AnyResourceId = GlobalResourceId | LocalResourceId;\n\n/** All possible resource flavours */\nexport type OptionalAnyResourceId = NullResourceId | GlobalResourceId | LocalResourceId;\n\nexport const NullResourceId = 0n as NullResourceId;\n\nfunction isNullResourceId(resourceId: bigint | string): resourceId is NullResourceId {\n return resourceId === NullResourceId;\n}\n\nexport function isAnyResourceId(resourceId: bigint): resourceId is AnyResourceId {\n return resourceId !== 0n;\n}\n\n// see local / global resource logic below...\n\nexport type ResourceKind = \"Structural\" | \"Value\";\n\nexport type FieldType = \"Input\" | \"Output\" | \"Service\" | \"OTW\" | \"Dynamic\" | \"MTW\";\n\nexport type FutureFieldType = \"Output\" | \"Input\" | \"Service\";\n\nexport type FieldStatus = \"Empty\" | \"Assigned\" | \"Resolved\";\n\nexport interface ResourceType {\n readonly name: string;\n readonly version: string;\n}\n\nexport function resourceType(name: string, version: string): ResourceType {\n return { name, version };\n}\n\nexport function resourceTypeToString(rt: ResourceType): string {\n return `${rt.name}:${rt.version}`;\n}\n\nexport function parseResourceType(str: string): ResourceType {\n const [name, version] = str.split(\":\");\n return { name, version };\n}\n\nexport function resourceTypesEqual(type1: ResourceType, type2: ResourceType): boolean {\n return type1.name === type2.name && type1.version === type2.version;\n}\n\n/** Color proof used for resource creation requests (alias for ResourceSignature). */\nexport type ColorProof = ResourceSignature;\n\n/** Readonly fields here marks properties of resource that can't change according to pl's state machine. */\nexport type BasicResourceData = {\n readonly id: SignedResourceId;\n readonly originalResourceId: OptionalSignedResourceId;\n\n readonly kind: ResourceKind;\n readonly type: ResourceType;\n\n readonly data?: Uint8Array;\n\n readonly error: OptionalSignedResourceId;\n\n readonly inputsLocked: boolean;\n readonly outputsLocked: boolean;\n readonly resourceReady: boolean;\n\n /** This value is derived from resource state by the server and can be used as\n * a robust criteria to determine resource is in final state. */\n readonly final: boolean;\n};\n\nexport function extractBasicResourceData(rd: ResourceData): BasicResourceData {\n const {\n id,\n originalResourceId,\n kind,\n type,\n data,\n error,\n inputsLocked,\n outputsLocked,\n resourceReady,\n final,\n } = rd;\n return {\n id,\n originalResourceId,\n kind,\n type,\n data,\n error,\n inputsLocked,\n outputsLocked,\n resourceReady,\n final,\n };\n}\n\nexport const jsonToData = (data: unknown) => Buffer.from(JSON.stringify(data));\n\nexport const resDataToJson = (res: ResourceData) => cachedDeserialize(notEmpty(res.data));\n\nexport type ResourceData = BasicResourceData & {\n readonly fields: FieldData[];\n};\n\nexport function getField(r: ResourceData, name: string): FieldData {\n return notEmpty(r.fields.find((f) => f.name === name));\n}\n\nexport type FieldData = {\n readonly name: string;\n readonly type: FieldType;\n readonly status: FieldStatus;\n readonly value: OptionalSignedResourceId;\n readonly error: OptionalSignedResourceId;\n\n /** True if value the fields points to is in final state. */\n readonly valueIsFinal: boolean;\n};\n\n//\n// Local / Global ResourceId arithmetics\n//\n\n// Note: txId and other numerical values are made numbers but not bigint intentionally,\n// after implementing security model based on signed resource ids this will make\n// much more sense\n\nconst ResourceIdRootMask = 1n << 63n;\nconst ResourceIdLocalMask = 1n << 62n;\nconst NoFlagsIdMask = 0x3fffffffffffffffn;\nconst LocalResourceIdTxIdOffset = 24n;\nexport const MaxLocalId = 0xffffff;\nexport const MaxTxId = 0xffffffff;\n/** Mask valid after applying shift */\nconst TxIdMask = BigInt(MaxTxId);\nconst LocalIdMask = BigInt(MaxLocalId);\n\n// /** Basically removes embedded tx id */\n// const LocalIdCleanMask = 0xFF00000000FFFFFFn;\n\nexport function isRootResourceId(id: bigint) {\n return (id & ResourceIdRootMask) !== 0n;\n}\n\nexport function isLocalResourceId(id: bigint | string): id is LocalResourceId {\n if (typeof id === \"string\") {\n return false;\n }\n\n return (id & ResourceIdLocalMask) !== 0n;\n}\n\nexport function createLocalResourceId(\n isRoot: boolean,\n localCounterValue: number,\n localTxId: number,\n): LocalResourceId {\n if (\n localCounterValue > MaxLocalId ||\n localTxId > MaxTxId ||\n localCounterValue < 0 ||\n localTxId <= 0\n )\n throw Error(\"wrong local id or tx id\");\n return ((isRoot ? ResourceIdRootMask : 0n) |\n ResourceIdLocalMask |\n BigInt(localCounterValue) |\n (BigInt(localTxId) << LocalResourceIdTxIdOffset)) as LocalResourceId;\n}\n\nexport function createGlobalResourceId(isRoot: boolean, unmaskedId: bigint): GlobalResourceId {\n return ((isRoot ? ResourceIdRootMask : 0n) | unmaskedId) as GlobalResourceId;\n}\n\nexport function extractTxId(localResourceId: LocalResourceId): number {\n return Number((localResourceId >> LocalResourceIdTxIdOffset) & TxIdMask);\n}\n\nexport function checkLocalityOfResourceId(resourceId: AnyResourceId, expectedTxId: number): void {\n if (!isLocalResourceId(resourceId)) return;\n if (extractTxId(resourceId) !== expectedTxId)\n throw Error(\n \"local id from another transaction, globalize id before leaking it from the transaction\",\n );\n}\n\nexport function resourceIdToString(\n resourceId: OptionalAnyResourceId | OptionalSignedResourceId,\n): string {\n if (isSignedResourceId(resourceId)) {\n // Strip signature\n resourceId = anyResourceIdToBigint(resourceId) as GlobalResourceId;\n }\n\n if (isNullSignedResourceId(resourceId)) return \"XX:0x0\";\n if (isNullResourceId(resourceId)) return \"XX:0x0\";\n\n if (isLocalResourceId(resourceId))\n return (\n (isRootResourceId(resourceId) ? \"R\" : \"N\") +\n \"L:0x\" +\n (LocalIdMask & resourceId).toString(16) +\n \"[0x\" +\n extractTxId(resourceId).toString(16) +\n \"]\"\n );\n else\n return (\n (isRootResourceId(resourceId) ? \"R\" : \"N\") +\n \"G:0x\" +\n (NoFlagsIdMask & resourceId).toString(16)\n );\n}\n\nconst resourceIdRegexp =\n /^(?:(?<xx>XX)|(?<rn>[XRN])(?<lg>[XLG])):0x(?<rid>[0-9a-fA-F]+)(?:\\[0x(?<txid>[0-9a-fA-F]+)])?$/;\n\nexport function resourceIdFromString(str: string): OptionalAnyResourceId | undefined {\n const match = str.match(resourceIdRegexp);\n if (match === null) return undefined;\n const { xx, rn, lg, rid, txid } = match.groups!;\n if (xx) return NullResourceId;\n if (lg === \"L\")\n return createLocalResourceId(rn === \"R\", Number.parseInt(rid, 16), Number.parseInt(txid, 16));\n else return createGlobalResourceId(rn === \"R\", BigInt(\"0x\" + rid));\n}\n\nexport function anyResourceIdToBigint(resourceId: bigint | SignedResourceId): bigint {\n if (typeof resourceId !== \"string\") {\n return resourceId;\n }\n\n const parsed = parseSignedResourceId(resourceId);\n return parsed.globalId as bigint;\n}\n\nexport function stringifyWithResourceId(object: unknown): string {\n return JSON.stringify(object, (key, value) => {\n if (typeof value === \"bigint\") return resourceIdToString(value as OptionalAnyResourceId);\n if (isSignedResourceId(value)) return resourceIdToString(value);\n return value;\n });\n}\n\n/** Opaque authorization signature attached to a resource. */\nexport type ResourceSignature = Branded<Uint8Array, \"ResourceSignature\">;\n\n/**\n * Signed resource id is \"<global ID>|<resource signature hex>\", encoded as string\n * (e.g. \"NG:0x123EC|1234567890abcdef\")\n */\nexport type SignedResourceId = Branded<string, \"signed\", \"__signed_resource_id__\">;\n\nexport type NullSignedResourceId = Branded<string, \"null\", \"__signed_resource_id__\">;\n\nexport const NullSignedResourceId = \"\" as NullSignedResourceId;\n\n/** Nullable signed resource ID */\nexport type OptionalSignedResourceId = NullSignedResourceId | SignedResourceId;\n\nexport function isNullSignedResourceId(\n resourceId: bigint | string,\n): resourceId is NullSignedResourceId {\n return resourceId === NullSignedResourceId;\n}\n\nexport function isNotNullSignedResourceId(\n resourceId: OptionalSignedResourceId,\n): resourceId is SignedResourceId {\n // lint-allow-cast\n return resourceId !== NullSignedResourceId;\n}\n\nexport function ensureSignedResourceIdNotNull(\n resourceId: OptionalSignedResourceId,\n): SignedResourceId {\n if (!isNotNullSignedResourceId(resourceId)) throw new Error(\"null resource id\");\n return resourceId;\n}\n\nexport function isSignedResourceId(resourceId: bigint | string): resourceId is SignedResourceId {\n // lint-allow-cast\n return typeof resourceId === \"string\" && resourceId.includes(\"|\");\n}\n\n/** Encode resource signature to base64url for embedding in URL-based handles. */\nexport function signatureToBase64Url(sig?: ResourceSignature): string {\n return sig && sig.length > 0 ? Buffer.from(sig).toString(\"base64url\") : \"\";\n}\n\n/** Cast raw bytes to a branded ResourceSignature, returning undefined for empty/missing input. */\nexport function toResourceSignature(raw?: Uint8Array): ResourceSignature {\n return raw && raw.length > 0\n ? (raw as ResourceSignature)\n : (new Uint8Array(0) as ResourceSignature);\n}\n\n/** Decode base64url-encoded string back to a branded ResourceSignature. */\nexport function base64UrlToSignature(str: string): ResourceSignature {\n return toResourceSignature(Buffer.from(str, \"base64url\"))!;\n}\n\n/** Converts bigint global resource id and signature to a SignedResourceId string.\n * Format: \"<globalIdString>|<signatureHex>\" */\nexport function createSignedResourceId(\n globalId: bigint,\n signature?: ResourceSignature,\n): SignedResourceId {\n if (isLocalResourceId(globalId))\n throw new Error(`Local resource id: ${resourceIdToString(globalId)}`);\n if (isNullResourceId(globalId)) throw new Error(`Null resource id.`);\n\n const sigHex = signature ? Buffer.from(signature).toString(\"hex\") : \"\";\n return `${String(globalId)}|${sigHex}` as SignedResourceId; // lint-allow-cast\n}\n\nexport function parseSignedResourceId(resourceId: SignedResourceId): {\n globalId: GlobalResourceId;\n signature: ResourceSignature;\n} {\n if (typeof resourceId !== \"string\") {\n throw new Error(`Not a signed resource id: ${resourceId}`);\n }\n\n const pipeIdx = resourceId.indexOf(\"|\");\n if (pipeIdx < 0) throw new Error(`Malformed signed resource id (no '|'): ${resourceId}`);\n\n const globalIdStr = resourceId.substring(0, pipeIdx);\n const signatureHex = resourceId.substring(pipeIdx + 1);\n\n const globalId = BigInt(globalIdStr);\n if (isNullSignedResourceId(globalId) || isLocalResourceId(globalId))\n throw new Error(`Invalid global id portion in signed resource id: ${globalIdStr}`);\n\n const signature: ResourceSignature = (\n signatureHex.length > 0 ? Buffer.from(signatureHex, \"hex\") : new Uint8Array(0)\n ) as ResourceSignature;\n\n return { globalId: globalId as GlobalResourceId, signature };\n}\n"],"mappings":"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"}