@milaboratories/pl-client 3.4.2 → 3.5.0

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 (67) hide show
  1. package/dist/core/final.cjs.map +1 -1
  2. package/dist/core/final.js.map +1 -1
  3. package/dist/core/ll_client.cjs +7 -1
  4. package/dist/core/ll_client.cjs.map +1 -1
  5. package/dist/core/ll_client.d.ts.map +1 -1
  6. package/dist/core/ll_client.js +7 -1
  7. package/dist/core/ll_client.js.map +1 -1
  8. package/dist/core/ll_transaction.cjs +151 -26
  9. package/dist/core/ll_transaction.cjs.map +1 -1
  10. package/dist/core/ll_transaction.d.ts +1 -0
  11. package/dist/core/ll_transaction.d.ts.map +1 -1
  12. package/dist/core/ll_transaction.js +151 -26
  13. package/dist/core/ll_transaction.js.map +1 -1
  14. package/dist/core/transaction.cjs +89 -0
  15. package/dist/core/transaction.cjs.map +1 -1
  16. package/dist/core/transaction.d.ts +47 -1
  17. package/dist/core/transaction.d.ts.map +1 -1
  18. package/dist/core/transaction.js +90 -1
  19. package/dist/core/transaction.js.map +1 -1
  20. package/dist/core/tree_filter.cjs +106 -0
  21. package/dist/core/tree_filter.cjs.map +1 -0
  22. package/dist/core/tree_filter.d.ts +85 -0
  23. package/dist/core/tree_filter.d.ts.map +1 -0
  24. package/dist/core/tree_filter.js +106 -0
  25. package/dist/core/tree_filter.js.map +1 -0
  26. package/dist/core/type_conversion.cjs +1 -0
  27. package/dist/core/type_conversion.cjs.map +1 -1
  28. package/dist/core/type_conversion.js +1 -1
  29. package/dist/core/type_conversion.js.map +1 -1
  30. package/dist/index.cjs +5 -0
  31. package/dist/index.d.ts +4 -2
  32. package/dist/index.js +3 -1
  33. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.cjs.map +1 -1
  34. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.js.map +1 -1
  35. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +450 -4
  36. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
  37. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +328 -2
  38. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
  39. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +449 -5
  40. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
  41. package/dist/proto-grpc/google/protobuf/timestamp.cjs.map +1 -1
  42. package/dist/proto-grpc/google/protobuf/timestamp.d.ts +9 -8
  43. package/dist/proto-grpc/google/protobuf/timestamp.d.ts.map +1 -1
  44. package/dist/proto-grpc/google/protobuf/timestamp.js.map +1 -1
  45. package/dist/proto-grpc/google/rpc/code.cjs.map +1 -1
  46. package/dist/proto-grpc/google/rpc/code.js.map +1 -1
  47. package/package.json +4 -4
  48. package/src/core/final.ts +1 -1
  49. package/src/core/ll_client.ts +11 -1
  50. package/src/core/ll_transaction.test.ts +13 -18
  51. package/src/core/ll_transaction.ts +237 -60
  52. package/src/core/transaction.test.ts +38 -0
  53. package/src/core/transaction.ts +136 -1
  54. package/src/core/tree_filter.test.ts +217 -0
  55. package/src/core/tree_filter.ts +182 -0
  56. package/src/core/type_conversion.ts +1 -1
  57. package/src/index.ts +1 -0
  58. package/src/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.ts +1 -1
  59. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +604 -6
  60. package/src/proto-grpc/google/api/http.ts +1 -1
  61. package/src/proto-grpc/google/protobuf/descriptor.ts +242 -12
  62. package/src/proto-grpc/google/protobuf/timestamp.ts +9 -8
  63. package/src/proto-grpc/google/protobuf/wrappers.ts +38 -4
  64. package/src/proto-grpc/google/rpc/code.ts +1 -1
  65. package/src/proto-grpc/google/rpc/error_details.ts +5 -5
  66. package/src/proto-grpc/google/rpc/http.ts +1 -1
  67. package/src/proto-grpc/google/rpc/status.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ll_transaction.js","names":[],"sources":["../../src/core/ll_transaction.ts"],"sourcesContent":["import type {\n TxAPI_ClientMessage,\n TxAPI_ServerMessage,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport type { BiDiStream } from \"./abstract_stream\";\nimport Denque from \"denque\";\nimport type { Status } from \"../proto-grpc/github.com/googleapis/googleapis/google/rpc/status\";\nimport {\n PlErrorCodeNotFound,\n RecoverablePlError,\n rethrowMeaningfulError,\n UnrecoverablePlError,\n} from \"./errors\";\nimport { StatefulPromise } from \"./StatefulPromise\";\n\nexport type ClientMessageRequest = TxAPI_ClientMessage[\"request\"];\n\nexport type ServerMessageResponse = TxAPI_ServerMessage[\"response\"];\n\ntype TxStream = BiDiStream<TxAPI_ClientMessage, TxAPI_ServerMessage>;\n\nexport type OneOfKind<T extends { oneofKind: unknown }, Kind extends T[\"oneofKind\"]> = Extract<\n T,\n { oneofKind: Kind }\n>;\n\ninterface SingleResponseHandler<Kind extends ServerMessageResponse[\"oneofKind\"]> {\n kind: Kind;\n expectMultiResponse: false;\n resolve: (v: OneOfKind<ServerMessageResponse, Kind>) => void;\n reject: (e: Error) => void;\n}\n\ninterface MultiResponseHandler<Kind extends ServerMessageResponse[\"oneofKind\"]> {\n kind: Kind;\n expectMultiResponse: true;\n resolve: (v: OneOfKind<ServerMessageResponse, Kind>[]) => void;\n reject: (e: Error) => void;\n}\n\ntype AnySingleResponseHandler = SingleResponseHandler<ServerMessageResponse[\"oneofKind\"]>;\n\ntype AnyMultiResponseHandler = MultiResponseHandler<ServerMessageResponse[\"oneofKind\"]>;\n\ntype AnyResponseHandler =\n | SingleResponseHandler<ServerMessageResponse[\"oneofKind\"]>\n | MultiResponseHandler<ServerMessageResponse[\"oneofKind\"]>;\n\nfunction createResponseHandler<Kind extends ServerMessageResponse[\"oneofKind\"]>(\n kind: Kind,\n expectMultiResponse: boolean,\n resolve:\n | ((v: OneOfKind<ServerMessageResponse, Kind>) => void)\n | ((v: OneOfKind<ServerMessageResponse, Kind>[]) => void),\n reject: (e: Error) => void,\n): AnyResponseHandler {\n return { kind, expectMultiResponse, resolve, reject } as AnyResponseHandler;\n}\n\nfunction isRecoverable(status: Status): boolean {\n return status.code === PlErrorCodeNotFound;\n}\n\nexport class RethrowError extends Error {\n name = \"RethrowError\";\n constructor(public readonly rethrowLambda: () => never) {\n super(\"Rethrow error, you should never see this one.\");\n }\n}\n\nexport class LLPlTransaction {\n /** Bidirectional channel through which transaction communicates with the server */\n private readonly stream: TxStream;\n\n /** Used to abort ongoing transaction stream */\n private readonly abortController = new AbortController();\n\n /** Counter of sent requests, used to calculate which future response will correspond to this request.\n * Incremented on each sent request. */\n private requestIdxCounter = 0;\n\n /** Queue from which incoming message processor takes handlers to which pass incoming messages */\n private readonly responseHandlerQueue = new Denque<AnyResponseHandler>();\n\n /** Each new resource, created by the transaction, is assigned with virtual (local) resource id, to make it possible\n * to populate its fields without awaiting actual resource id. This counter tracks those ids on client side, the\n * same way it is tracked on the server, so client can synchronously return such ids to the user. */\n private localResourceIdCounter = 0n;\n\n /** Switches to true, when this transaction closes due to normal or exceptional conditions. Prevents any new messages\n * to be sent to the stream. */\n private closed = false;\n /** Whether the outgoing stream was already closed. */\n private completed = false;\n\n /** If this transaction was terminated due to error, this is a generator to create new errors if corresponding response is required. */\n private errorFactory?: () => never;\n\n /** Timestamp when transaction was opened */\n private readonly openTimestamp = Date.now();\n\n private readonly incomingProcessorResult: Promise<(() => never) | null>;\n\n constructor(streamFactory: (abortSignal: AbortSignal) => TxStream) {\n this.stream = streamFactory(this.abortController.signal);\n\n // Starting incoming event processor\n this.incomingProcessorResult = this.incomingEventProcessor();\n }\n\n private assignErrorFactoryIfNotSet(\n errorFactory: () => never,\n reject?: (e: Error) => void,\n ): () => never {\n if (reject !== undefined) reject(new RethrowError(errorFactory));\n if (this.errorFactory) return errorFactory;\n this.errorFactory = errorFactory;\n return errorFactory;\n }\n\n private async incomingEventProcessor(): Promise<(() => never) | null> {\n /** Counter of received responses, used to check consistency of responses.\n * Increments on each received message. */\n let expectedId = -1;\n\n // defined externally to make possible to communicate any processing errors\n // to the specific request on which it happened\n let currentHandler: AnyResponseHandler | undefined = undefined;\n let responseAggregator: ServerMessageResponse[] | undefined = undefined;\n try {\n for await (const message of this.stream.responses) {\n if (currentHandler === undefined) {\n currentHandler = this.responseHandlerQueue.shift();\n\n if (currentHandler === undefined) {\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(`orphan incoming message`);\n });\n break;\n }\n\n // allocating response aggregator array\n if (currentHandler.expectMultiResponse) responseAggregator = [];\n\n expectedId++;\n }\n\n if (message.requestId !== expectedId) {\n const errorMessage = `out of order messages, ${message.requestId} !== ${expectedId}`;\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(errorMessage);\n });\n break;\n }\n\n if (message.error !== undefined) {\n const status = message.error;\n\n if (isRecoverable(status)) {\n currentHandler.reject(\n new RethrowError(() => {\n throw new RecoverablePlError(status);\n }),\n );\n currentHandler = undefined;\n\n if (message.multiMessage !== undefined && !message.multiMessage.isLast) {\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(\"Unexpected message sequence.\");\n });\n break;\n }\n\n // We can continue to work after recoverable errors\n continue;\n } else {\n this.assignErrorFactoryIfNotSet(() => {\n throw new UnrecoverablePlError(status);\n }, currentHandler.reject);\n currentHandler = undefined;\n\n // In case of unrecoverable errors we close the transaction\n break;\n }\n }\n\n if (\n currentHandler.kind !== message.response.oneofKind &&\n message?.multiMessage?.isEmpty !== true\n ) {\n const errorMessage = `inconsistent request response types: ${currentHandler.kind} !== ${message.response.oneofKind}`;\n\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(errorMessage);\n }, currentHandler.reject);\n currentHandler = undefined;\n\n break;\n }\n\n if (currentHandler.expectMultiResponse !== (message.multiMessage !== undefined)) {\n const errorMessage = `inconsistent multi state: ${currentHandler.expectMultiResponse} !== ${message.multiMessage !== undefined}`;\n\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(errorMessage);\n }, currentHandler.reject);\n currentHandler = undefined;\n\n break;\n }\n\n // <- at this point we validated everything we can at this level\n\n if (message.multiMessage !== undefined) {\n if (!message.multiMessage.isEmpty) {\n if (message.multiMessage.id !== responseAggregator!.length + 1) {\n const errorMessage = `inconsistent multi id: ${message.multiMessage.id} !== ${responseAggregator!.length + 1}`;\n\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(errorMessage);\n }, currentHandler.reject);\n currentHandler = undefined;\n\n break;\n }\n\n responseAggregator!.push(message.response);\n }\n\n if (message.multiMessage.isLast) {\n (currentHandler as AnyMultiResponseHandler).resolve(responseAggregator!);\n responseAggregator = undefined;\n currentHandler = undefined;\n }\n } else {\n (currentHandler as AnySingleResponseHandler).resolve(message.response);\n currentHandler = undefined;\n }\n\n // After receiving a terminal response (txCommit or txDiscard), we proactively close the client stream.\n // This ensures consistent behavior between the gRPC and WebSocket transports,\n // since the server closes the connection automatically upon transaction completion in both cases.\n if (this.isTerminalResponse(message) && this.responseHandlerQueue.length === 0) {\n await this.stream.requests.complete();\n }\n }\n } catch (e: any) {\n return this.assignErrorFactoryIfNotSet(() => {\n rethrowMeaningfulError(e, true);\n }, currentHandler?.reject);\n } finally {\n await this.close();\n }\n return null;\n }\n\n /** Executed after termination of incoming message processor */\n private async close(): Promise<void> {\n if (this.closed) return;\n\n this.closed = true;\n\n // Rejecting all messages\n\n while (true) {\n const handler = this.responseHandlerQueue.shift();\n if (!handler) break;\n if (this.errorFactory) handler.reject(new RethrowError(this.errorFactory));\n else handler.reject(new Error(\"no reply\"));\n }\n\n // closing outgoing stream\n await this.stream.requests.complete();\n }\n\n /** Forcefully close the transaction, terminate all connections and reject all pending requests */\n public abort(cause?: Error) {\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(`transaction aborted`, { cause });\n });\n this.abortController.abort(cause);\n }\n\n /** Await incoming message loop termination and throw any leftover errors if it was unsuccessful */\n public async await(): Promise<void> {\n // for those who want to understand \"why?\":\n // this way there is no hanging promise that will complete with rejection\n // until await is implicitly requested, the this.incomingProcessorResult\n // always resolves with success\n\n const processingResult = await this.incomingProcessorResult;\n if (processingResult !== null) processingResult();\n }\n\n public async send<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n expectMultiResponse: false,\n ): Promise<OneOfKind<ServerMessageResponse, Kind>>;\n public async send<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n expectMultiResponse: true,\n ): Promise<OneOfKind<ServerMessageResponse, Kind>[]>;\n /** Generate proper client message and send it to the server, and returns a promise of future response. */\n public async send<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n expectMultiResponse: boolean,\n ): Promise<OneOfKind<ServerMessageResponse, Kind> | OneOfKind<ServerMessageResponse, Kind>[]> {\n if (this.errorFactory) return Promise.reject(new RethrowError(this.errorFactory));\n\n if (this.closed) return Promise.reject(new Error(\"Transaction already closed\"));\n\n // Note: Promise synchronously executes a callback passed to a constructor\n const result = StatefulPromise.fromDeferredReject(\n new Promise<OneOfKind<ServerMessageResponse, Kind>>((resolve, reject) => {\n this.responseHandlerQueue.push(\n createResponseHandler(r.oneofKind, expectMultiResponse, resolve, reject),\n );\n }),\n );\n\n // Awaiting message dispatch to catch any associated errors.\n // There is no hurry, we are not going to receive a response until message is sent.\n await this.stream.requests.send({\n requestId: this.requestIdxCounter++,\n request: r,\n });\n\n try {\n return await result;\n } catch (e: any) {\n if (e instanceof RethrowError) e.rethrowLambda();\n throw new Error(\"Error while waiting for response\", { cause: e });\n }\n }\n\n private _completed = false;\n\n /** Safe to call multiple times */\n public async complete() {\n if (this._completed) return;\n this._completed = true;\n await this.stream.requests.complete();\n }\n\n private isTerminalResponse(message: TxAPI_ServerMessage): boolean {\n const kind = message.response.oneofKind;\n return kind === \"txCommit\" || kind === \"txDiscard\";\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ll_transaction.js","names":[],"sources":["../../src/core/ll_transaction.ts"],"sourcesContent":["import type {\n TxAPI_ClientMessage,\n TxAPI_ServerMessage,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport type { BiDiStream } from \"./abstract_stream\";\nimport Denque from \"denque\";\nimport type { Status } from \"../proto-grpc/github.com/googleapis/googleapis/google/rpc/status\";\nimport {\n PlErrorCodeNotFound,\n RecoverablePlError,\n rethrowMeaningfulError,\n UnrecoverablePlError,\n} from \"./errors\";\nimport { StatefulPromise } from \"./StatefulPromise\";\n\nexport type ClientMessageRequest = TxAPI_ClientMessage[\"request\"];\n\nexport type ServerMessageResponse = TxAPI_ServerMessage[\"response\"];\n\ntype TxStream = BiDiStream<TxAPI_ClientMessage, TxAPI_ServerMessage>;\n\nexport type OneOfKind<T extends { oneofKind: unknown }, Kind extends T[\"oneofKind\"]> = Extract<\n T,\n { oneofKind: Kind }\n>;\n\ninterface SingleResponseHandler {\n mode: \"single\";\n kind: ServerMessageResponse[\"oneofKind\"];\n resolve: (v: ServerMessageResponse) => void;\n reject: (e: Error) => void;\n}\n\ninterface MultiResponseHandler {\n mode: \"multiBuffered\";\n kind: ServerMessageResponse[\"oneofKind\"];\n resolve: (v: ServerMessageResponse[]) => void;\n reject: (e: Error) => void;\n}\n\ninterface MultiStreamResponseHandler {\n mode: \"multiStream\";\n kind: ServerMessageResponse[\"oneofKind\"];\n stream: AsyncMessageStream<ServerMessageResponse>;\n}\n\ntype AnySingleResponseHandler = SingleResponseHandler;\ntype AnyMultiStreamResponseHandler = MultiStreamResponseHandler;\n\ntype AnyResponseHandler =\n | AnySingleResponseHandler\n | MultiResponseHandler\n | AnyMultiStreamResponseHandler;\n\n// Implements both AsyncIterable and AsyncIterator: `[Symbol.asyncIterator]()` returns\n// `this`, so multiple `for await` loops over the same stream share state instead of\n// creating independent iterators that would race on `waitingResolve`/`waitingReject`.\n// Only one active consumer is supported; concurrent `next()` calls are not safe.\nclass AsyncMessageStream<T> implements AsyncIterable<T>, AsyncIterator<T> {\n private readonly queue = new Denque<T>();\n private done = false;\n private cancelled = false;\n private failure?: Error;\n private waitingResolve?: (value: IteratorResult<T>) => void;\n private waitingReject?: (reason?: unknown) => void;\n\n public push(value: T): void {\n if (this.done || this.cancelled) return;\n if (this.waitingResolve) {\n const resolve = this.waitingResolve;\n this.waitingResolve = undefined;\n this.waitingReject = undefined;\n resolve({ value, done: false });\n return;\n }\n this.queue.push(value);\n }\n\n public end(): void {\n if (this.done) return;\n this.done = true;\n if (this.waitingResolve) {\n const resolve = this.waitingResolve;\n this.waitingResolve = undefined;\n this.waitingReject = undefined;\n resolve({ value: undefined, done: true });\n }\n }\n\n // Fail-fast: any frames still buffered in `this.queue` are intentionally dropped.\n // `next()` checks `this.failure` before draining the queue, so consumers see the\n // error immediately. This differs from `end()`, which drains buffered frames first.\n // Rationale: when the upstream stream errors, the in-flight response is treated as\n // corrupt and partial frames must not be surfaced.\n public fail(error: Error): void {\n if (this.done) return;\n this.failure = error;\n this.done = true;\n if (this.waitingReject) {\n const reject = this.waitingReject;\n this.waitingResolve = undefined;\n this.waitingReject = undefined;\n reject(error);\n }\n }\n\n public cancel(): void {\n this.cancelled = true;\n this.done = true;\n this.queue.clear();\n if (this.waitingResolve) {\n const resolve = this.waitingResolve;\n this.waitingResolve = undefined;\n this.waitingReject = undefined;\n resolve({ value: undefined, done: true });\n }\n }\n\n public async next(): Promise<IteratorResult<T>> {\n if (this.failure) throw this.failure;\n\n const value = this.queue.shift();\n if (value !== undefined) return { value, done: false };\n\n if (this.done) return { value: undefined, done: true };\n\n return await new Promise<IteratorResult<T>>((resolve, reject) => {\n this.waitingResolve = resolve;\n this.waitingReject = reject;\n });\n }\n\n public async return(): Promise<IteratorResult<T>> {\n this.cancel();\n return { value: undefined, done: true };\n }\n\n public async throw(error?: unknown): Promise<IteratorResult<T>> {\n this.cancel();\n throw error;\n }\n\n [Symbol.asyncIterator](): this {\n return this;\n }\n}\n\nfunction isRecoverable(status: Status): boolean {\n return status.code === PlErrorCodeNotFound;\n}\n\nexport class RethrowError extends Error {\n name = \"RethrowError\";\n constructor(public readonly rethrowLambda: () => never) {\n super(\"Rethrow error, you should never see this one.\");\n }\n}\n\nexport class LLPlTransaction {\n /** Bidirectional channel through which transaction communicates with the server */\n private readonly stream: TxStream;\n\n /** Used to abort ongoing transaction stream */\n private readonly abortController = new AbortController();\n\n /** Counter of sent requests, used to calculate which future response will correspond to this request.\n * Incremented on each sent request. */\n private requestIdxCounter = 0;\n\n /** Queue from which incoming message processor takes handlers to which pass incoming messages */\n private readonly responseHandlerQueue = new Denque<AnyResponseHandler>();\n\n /** Each new resource, created by the transaction, is assigned with virtual (local) resource id, to make it possible\n * to populate its fields without awaiting actual resource id. This counter tracks those ids on client side, the\n * same way it is tracked on the server, so client can synchronously return such ids to the user. */\n private localResourceIdCounter = 0n;\n\n /** Switches to true, when this transaction closes due to normal or exceptional conditions. Prevents any new messages\n * to be sent to the stream. */\n private closed = false;\n /** Whether the outgoing stream was already closed. */\n private completed = false;\n\n /** If this transaction was terminated due to error, this is a generator to create new errors if corresponding response is required. */\n private errorFactory?: () => never;\n\n /** Timestamp when transaction was opened */\n private readonly openTimestamp = Date.now();\n\n private readonly incomingProcessorResult: Promise<(() => never) | null>;\n\n constructor(streamFactory: (abortSignal: AbortSignal) => TxStream) {\n this.stream = streamFactory(this.abortController.signal);\n\n // Starting incoming event processor\n this.incomingProcessorResult = this.incomingEventProcessor();\n }\n\n private assignErrorFactoryIfNotSet(\n errorFactory: () => never,\n reject?: (e: Error) => void,\n ): () => never {\n if (reject !== undefined) reject(new RethrowError(errorFactory));\n if (this.errorFactory) return errorFactory;\n this.errorFactory = errorFactory;\n return errorFactory;\n }\n\n private async incomingEventProcessor(): Promise<(() => never) | null> {\n /** Counter of received responses, used to check consistency of responses.\n * Increments on each received message. */\n let expectedId = -1;\n\n // defined externally to make possible to communicate any processing errors\n // to the specific request on which it happened\n let currentHandler: AnyResponseHandler | undefined = undefined;\n let responseAggregator: ServerMessageResponse[] | undefined = undefined;\n let currentMultiIdx = 0;\n try {\n for await (const message of this.stream.responses) {\n if (currentHandler === undefined) {\n currentHandler = this.responseHandlerQueue.shift();\n\n if (currentHandler === undefined) {\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(`orphan incoming message`);\n });\n break;\n }\n\n if (currentHandler.mode === \"multiBuffered\") responseAggregator = [];\n currentMultiIdx = 0;\n expectedId++;\n }\n\n if (message.requestId !== expectedId) {\n const errorMessage = `out of order messages, ${message.requestId} !== ${expectedId}`;\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(errorMessage);\n });\n break;\n }\n\n if (message.error !== undefined) {\n const status = message.error;\n\n if (isRecoverable(status)) {\n const recoverableError = new RethrowError(() => {\n throw new RecoverablePlError(status);\n });\n if (currentHandler.mode === \"single\" || currentHandler.mode === \"multiBuffered\") {\n currentHandler.reject(recoverableError);\n } else {\n currentHandler.stream.fail(recoverableError);\n }\n currentHandler = undefined;\n\n if (message.multiMessage !== undefined && !message.multiMessage.isLast) {\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(\"Unexpected message sequence.\");\n });\n break;\n }\n\n // We can continue to work after recoverable errors\n continue;\n } else {\n this.assignErrorFactoryIfNotSet(\n () => {\n throw new UnrecoverablePlError(status);\n },\n currentHandler.mode === \"single\" || currentHandler.mode === \"multiBuffered\"\n ? currentHandler.reject\n : undefined,\n );\n if (currentHandler.mode === \"multiStream\") {\n currentHandler.stream.fail(new UnrecoverablePlError(status));\n }\n currentHandler = undefined;\n\n // In case of unrecoverable errors we close the transaction\n break;\n }\n }\n\n if (\n currentHandler.kind !== message.response.oneofKind &&\n message?.multiMessage?.isEmpty !== true\n ) {\n const errorMessage = `inconsistent request response types: ${currentHandler.kind} !== ${message.response.oneofKind}`;\n\n this.assignErrorFactoryIfNotSet(\n () => {\n throw new Error(errorMessage);\n },\n currentHandler.mode === \"single\" || currentHandler.mode === \"multiBuffered\"\n ? currentHandler.reject\n : undefined,\n );\n if (currentHandler.mode === \"multiStream\") {\n currentHandler.stream.fail(new Error(errorMessage));\n }\n currentHandler = undefined;\n\n break;\n }\n\n const expectMultiResponse =\n currentHandler.mode === \"multiBuffered\" || currentHandler.mode === \"multiStream\";\n if (expectMultiResponse !== (message.multiMessage !== undefined)) {\n const errorMessage = `inconsistent multi state: ${expectMultiResponse} !== ${message.multiMessage !== undefined}`;\n\n this.assignErrorFactoryIfNotSet(\n () => {\n throw new Error(errorMessage);\n },\n currentHandler.mode === \"single\" || currentHandler.mode === \"multiBuffered\"\n ? currentHandler.reject\n : undefined,\n );\n if (currentHandler.mode === \"multiStream\") {\n currentHandler.stream.fail(new Error(errorMessage));\n }\n currentHandler = undefined;\n\n break;\n }\n\n // <- at this point we validated everything we can at this level\n\n if (message.multiMessage !== undefined) {\n if (!message.multiMessage.isEmpty) {\n if (message.multiMessage.id !== currentMultiIdx + 1) {\n const errorMessage = `inconsistent multi id: ${message.multiMessage.id} !== ${currentMultiIdx + 1}`;\n\n this.assignErrorFactoryIfNotSet(\n () => {\n throw new Error(errorMessage);\n },\n currentHandler.mode === \"multiBuffered\" ? currentHandler.reject : undefined,\n );\n if (currentHandler.mode === \"multiStream\") {\n currentHandler.stream.fail(new Error(errorMessage));\n }\n currentHandler = undefined;\n\n break;\n }\n\n currentMultiIdx++;\n if (currentHandler.mode === \"multiBuffered\") {\n responseAggregator!.push(message.response);\n } else if (currentHandler.mode === \"multiStream\") {\n currentHandler.stream.push(message.response);\n }\n }\n\n if (message.multiMessage.isLast) {\n if (currentHandler.mode === \"multiBuffered\") {\n currentHandler.resolve(responseAggregator!);\n responseAggregator = undefined;\n } else if (currentHandler.mode === \"multiStream\") {\n currentHandler.stream.end();\n }\n currentHandler = undefined;\n }\n } else {\n (currentHandler as AnySingleResponseHandler).resolve(message.response);\n currentHandler = undefined;\n }\n\n // After receiving a terminal response (txCommit or txDiscard), we proactively close the client stream.\n // This ensures consistent behavior between the gRPC and WebSocket transports,\n // since the server closes the connection automatically upon transaction completion in both cases.\n if (this.isTerminalResponse(message) && this.responseHandlerQueue.length === 0) {\n await this.stream.requests.complete();\n }\n }\n } catch (e: any) {\n return this.assignErrorFactoryIfNotSet(\n () => {\n rethrowMeaningfulError(e, true);\n },\n currentHandler &&\n (currentHandler.mode === \"single\" || currentHandler.mode === \"multiBuffered\")\n ? currentHandler.reject\n : undefined,\n );\n } finally {\n await this.close();\n }\n return null;\n }\n\n /** Executed after termination of incoming message processor */\n private async close(): Promise<void> {\n if (this.closed) return;\n\n this.closed = true;\n\n // Rejecting all messages\n\n while (true) {\n const handler = this.responseHandlerQueue.shift();\n if (!handler) break;\n const noReplyError = this.errorFactory\n ? new RethrowError(this.errorFactory)\n : new Error(\"no reply\");\n if (handler.mode === \"single\" || handler.mode === \"multiBuffered\") {\n handler.reject(noReplyError);\n } else {\n handler.stream.fail(noReplyError);\n }\n }\n\n // closing outgoing stream\n await this.stream.requests.complete();\n }\n\n /** Forcefully close the transaction, terminate all connections and reject all pending requests */\n public abort(cause?: Error) {\n this.assignErrorFactoryIfNotSet(() => {\n throw new Error(`transaction aborted`, { cause });\n });\n this.abortController.abort(cause);\n }\n\n /** Await incoming message loop termination and throw any leftover errors if it was unsuccessful */\n public async await(): Promise<void> {\n // for those who want to understand \"why?\":\n // this way there is no hanging promise that will complete with rejection\n // until await is implicitly requested, the this.incomingProcessorResult\n // always resolves with success\n\n const processingResult = await this.incomingProcessorResult;\n if (processingResult !== null) processingResult();\n }\n\n public async send<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n expectMultiResponse: false,\n ): Promise<OneOfKind<ServerMessageResponse, Kind>>;\n public async send<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n expectMultiResponse: true,\n ): Promise<OneOfKind<ServerMessageResponse, Kind>[]>;\n /** Generate proper client message and send it to the server, and returns a promise of future response. */\n public async send<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n expectMultiResponse: boolean,\n ): Promise<OneOfKind<ServerMessageResponse, Kind> | OneOfKind<ServerMessageResponse, Kind>[]> {\n if (this.errorFactory) return Promise.reject(new RethrowError(this.errorFactory));\n\n if (this.closed) return Promise.reject(new Error(\"Transaction already closed\"));\n\n // Note: Promise synchronously executes a callback passed to a constructor\n const result = StatefulPromise.fromDeferredReject(\n new Promise<\n OneOfKind<ServerMessageResponse, Kind> | OneOfKind<ServerMessageResponse, Kind>[]\n >((resolve, reject) => {\n if (expectMultiResponse) {\n this.responseHandlerQueue.push({\n mode: \"multiBuffered\",\n kind: r.oneofKind,\n resolve: resolve as (v: ServerMessageResponse[]) => void,\n reject,\n });\n } else {\n this.responseHandlerQueue.push({\n mode: \"single\",\n kind: r.oneofKind,\n resolve: resolve as (v: ServerMessageResponse) => void,\n reject,\n });\n }\n }),\n );\n\n // Awaiting message dispatch to catch any associated errors.\n // There is no hurry, we are not going to receive a response until message is sent.\n await this.stream.requests.send({\n requestId: this.requestIdxCounter++,\n request: r,\n });\n\n try {\n return await result;\n } catch (e: any) {\n if (e instanceof RethrowError) e.rethrowLambda();\n throw new Error(\"Error while waiting for response\", { cause: e });\n }\n }\n\n public sendStream<Kind extends ClientMessageRequest[\"oneofKind\"]>(\n r: OneOfKind<ClientMessageRequest, Kind>,\n ): AsyncIterable<OneOfKind<ServerMessageResponse, Kind>> {\n if (this.errorFactory) throw new RethrowError(this.errorFactory);\n if (this.closed) throw new Error(\"Transaction already closed\");\n\n const stream = new AsyncMessageStream<ServerMessageResponse>();\n this.responseHandlerQueue.push({ mode: \"multiStream\", kind: r.oneofKind, stream });\n\n void this.stream.requests\n .send({ requestId: this.requestIdxCounter++, request: r })\n .catch((e: unknown) => {\n if (e instanceof Error) stream.fail(e);\n else stream.fail(new Error(\"Error while sending request\", { cause: e }));\n });\n\n return stream as AsyncIterable<OneOfKind<ServerMessageResponse, Kind>>;\n }\n\n private _completed = false;\n\n /** Safe to call multiple times */\n public async complete() {\n if (this._completed) return;\n this._completed = true;\n await this.stream.requests.complete();\n }\n\n private isTerminalResponse(message: TxAPI_ServerMessage): boolean {\n const kind = message.response.oneofKind;\n return kind === \"txCommit\" || kind === \"txDiscard\";\n }\n}\n"],"mappings":"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"}
@@ -670,6 +670,95 @@ var PlTransaction = class PlTransaction {
670
670
  async await() {
671
671
  await this.ll.await();
672
672
  }
673
+ /**
674
+ * Perform a single `ResourceTree` walk and yield each visited resource.
675
+ *
676
+ * Items are yielded incrementally as stream frames arrive from server.
677
+ *
678
+ * The low-level transaction stream is still ordered, so each active request
679
+ * must be consumed to completion (or closed via iterator `return()`/`throw()`)
680
+ * before later responses can be dispatched.
681
+ *
682
+ * @param seeds - Roots for the traversal. May include both {@link ResourceData}
683
+ * and {@link SignedResourceId} values in the same array.
684
+ * @param opts.fieldFilter - Per-field predicate; matching field edges are not descended.
685
+ * This wire field accepts only one filter. Compose multiple rules via
686
+ * `treeFilter.and(...)` / `treeFilter.or(...)`.
687
+ * @param opts.traverseStopRules - Per-resource predicate; matching resources are returned
688
+ * with `traverseWasStopped = true` and their children are not visited.
689
+ * This wire field accepts only one filter. Compose multiple rules via
690
+ * `treeFilter.and(...)` / `treeFilter.or(...)`.
691
+ * @param opts.includeKv - When true, each yielded item includes KV entries.
692
+ * @param opts.maxDepth - Optional depth cap.
693
+ */
694
+ resourceTree(seeds, opts) {
695
+ if (seeds.length === 0) throw new Error("resourceTree: at least one seed must be provided");
696
+ const seedProtos = seeds.map((seed) => {
697
+ const { globalId, signature } = require_types.parseSignedResourceId(typeof seed === "string" ? seed : seed.id);
698
+ return {
699
+ resourceId: globalId,
700
+ resourceSignature: signature
701
+ };
702
+ });
703
+ const firstSeed = seedProtos[0];
704
+ const responseStream = this.ll.sendStream({
705
+ oneofKind: "resourceTree",
706
+ resourceTree: {
707
+ resourceId: firstSeed?.resourceId ?? 0n,
708
+ resourceSignature: firstSeed?.resourceSignature ?? new Uint8Array(0),
709
+ seeds: seedProtos,
710
+ fieldFilter: opts?.fieldFilter,
711
+ traverseStopRules: opts?.traverseStopRules,
712
+ includeKv: opts?.includeKv ?? false,
713
+ maxDepth: opts?.maxDepth
714
+ }
715
+ });
716
+ return { [Symbol.asyncIterator]() {
717
+ const iterator = responseStream[Symbol.asyncIterator]();
718
+ return {
719
+ async next() {
720
+ while (true) {
721
+ const item = await iterator.next();
722
+ if (item.done) return {
723
+ value: void 0,
724
+ done: true
725
+ };
726
+ const frame = item.value.resourceTree;
727
+ if (frame === void 0) continue;
728
+ if (frame.resource && require_type_conversion.resourceIsDeleted(frame.resource)) continue;
729
+ if (!frame.resource) return {
730
+ value: {
731
+ frameKind: "stopMarker",
732
+ id: require_types.createSignedResourceId(frame.resourceId, require_types.toResourceSignature(frame.resourceSignature)),
733
+ traverseWasStopped: true
734
+ },
735
+ done: false
736
+ };
737
+ return {
738
+ value: {
739
+ frameKind: "resource",
740
+ ...require_type_conversion.protoToResource(frame.resource),
741
+ kv: frame.kv,
742
+ traverseWasStopped: frame.traverseWasStopped
743
+ },
744
+ done: false
745
+ };
746
+ }
747
+ },
748
+ async return() {
749
+ if (iterator.return) await iterator.return();
750
+ return {
751
+ value: void 0,
752
+ done: true
753
+ };
754
+ },
755
+ async throw(error) {
756
+ if (iterator.throw) await iterator.throw(error);
757
+ throw error;
758
+ }
759
+ };
760
+ } };
761
+ }
673
762
  nextLocalResourceId(root) {
674
763
  return require_types.createLocalResourceId(root, ++this.localResourceIdCounter, this.localTxId);
675
764
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.cjs","names":["isSignedResourceId","toResourceSignature","parseSignedResourceId","isLocalResourceId","createSignedResourceId","isNotFoundError","PromiseTracker","initialTxStatWithoutTime","TxAPI_Open_Request_WritableTx","ensureSignedResourceIdNotNull","protoToResource","JsonObject","JsonGzObject","ErrorResourceType","extractBasicResourceData","fieldTypeToProto","protoToField","toBytes","createLocalResourceId"],"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":";;;;;;;;;;;;AA4FA,SAAgB,QAAQ,KAAiC;AACvD,QAAO,IAAI,eAAe,aAAa,IAAI,IAAI,eAAe,YAAY;;AAG5E,SAAgB,WAAW,KAAoC;AAC7D,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAO,cAAc,IAAI;;AAG3B,SAAgB,aAAa,KAAsC;AACjE,QAAO,OAAO,QAAQ,YAAYA,cAAAA,mBAAmB,IAAI;;AAG3D,SAAgB,WAAW,KAAmC;AAC5D,QAAO,cAAc,IAAI,WAAW;;AAGtC,SAAgB,cAAc,KAAiC;AAC7D,QACE,OAAO,QAAQ,YACf,QAAQ,QACR,IAAI,eAAe,WAAW,IAC9B,IAAI,eAAe,UAAU;;AAIjC,SAAgB,UAAU,KAA8B;AACtD,KAAI,WAAW,IAAI,CAAE,QAAO;EAAE,YAAY,IAAI,WAAW;EAAS,WAAW,IAAI;EAAW;KACvF,QAAO;;AAGd,eAAsB,gBAAgB,KAA2C;AAC/E,KAAI,WAAW,IAAI,CACjB,QAAO;EAAE,YAAY,MAAM,IAAI,WAAW;EAAU,WAAW,IAAI;EAAW;AAChF,QAAO;;AAQT,MAAM,iBAAiBC,cAAAA,oBAAoB,IAAI,WAAW,EAAE,CAAC;AAE7D,SAAS,yBAAyB,KAA8C;AAC9E,KAAI,cAAc,IAAI,CAEpB,QAAO;EAAE,YAAY,IAAI;EAAS,mBAAmB;EAAgB;AAEvE,KAAI,aAAa,IAAI,EAAE;EAErB,MAAM,EAAE,UAAU,cAAcC,cAAAA,sBAAsB,IAAI;AAC1D,SAAO;GAAE,YAAY;GAAoB,mBAAmB;GAAW;;AAGzE,QAAO;EAAE,YAAY;EAAe,mBAAmB;EAAgB;;AAGzE,eAAsB,mBAAmB,KAAgD;AACvF,KAAI,cAAc,IAAI,CAAE,QAAO,MAAM,IAAI;AACzC,KAAIC,cAAAA,kBAAkB,IAAI,CAAE,QAAOC,cAAAA,uBAAuB,IAAI;AAC9D,QAAO;;AAGT,SAAgB,MAAM,YAA4B,WAAgC;AAChF,QAAO;EAAE;EAAY;EAAW;;;AAIlC,IAAa,mBAAb,cAAsC,MAAM;CAC1C,OAAO;;AAGT,eAAe,oBAAuB,IAA8C;AAClF,KAAI;AACF,SAAO,MAAM,IAAI;UACV,GAAG;AACV,MAAIC,eAAAA,gBAAgB,EAAE,CAAE,QAAO,KAAA;AAC/B,QAAM;;;;;;;;;;;AAYV,IAAa,gBAAb,MAAa,cAAc;CACzB;CACA,YAAqC,cAAc,eAAe;;CAGlE,kBAAmC,KAAK,KAAK;CAE7C,yBAAiC;;;;CAKjC,aAAqB;CAErB,uBAAwC;CAExC,UAA0B,IAAIC,uBAAAA,gBAAgB;CAE9C,aAA8B,KAAK,KAAK;CACxC,QAAyBC,aAAAA,0BAA0B;CACnD,IAAW,OAAe;AACxB,SAAO;GACL,GAAG,KAAK;GACR,QAAQ,KAAK,KAAK,GAAG,KAAK;GAC3B;;CAGH,YACE,IACA,MACA,UACA,aACA,gBACA,yBACA,wBAAkD,OAClD;AAPiB,OAAA,KAAA;AACD,OAAA,OAAA;AACA,OAAA,WAAA;AACC,OAAA,cAAA;AACA,OAAA,iBAAA;AACA,OAAA,0BAAA;AACA,OAAA,wBAAA;AAGjB,OAAK,aAAa,KAAK,mBACrB;GACE,WAAW;GACX,QAAQ;IACN;IACA;IACA,UAAU,WACNC,YAAAA,8BAA8B,WAC9BA,YAAAA,8BAA8B;IACnC;GACF,GACA,OAAA,GAAA,2BAAA,UAAe,EAAE,OAAO,IAAI,GAAG,CACjC;AAEI,OAAK,MAAM,KAAK,WAAW;AAGhC,OAAK,WAAW,OAAO,QAAQ;AAC7B,OAAI,CAAC,KAAK,qBACR,SAAQ,KAAK,IAAI;IAEnB;AAGF,OAAK,MAAM;;;;;CAMb,MAAgB,mBAAgE;AAC9E,SAAO,KAAK,QAAQ,MAAM,kBAAkB;;CAG9C,MAAc,0BAAyC;AAErD,QAAM,KAAK,QAAQ,UAAU;;CAG/B,mBACE,GACA,QACY;AACZ,SAAO,KAAK,QAAQ,MAAM,YAAY;GACpC,MAAM,qBAAqB,KAAK,GAAG,KAAK,GAAG,MAAM;AAE5C,QAAK,QAAQ,MAAM,mBAAmB;AAE3C,SAAM,KAAK,yBAAyB;AAGpC,UAAO,OAAO,MAAM,mBAAmB;IACvC;;CAGJ,kBACE,GACA,QACY;AACZ,SAAO,KAAK,QAAQ,MAAM,YAAY;GACpC,MAAM,qBAAqB,KAAK,GAAG,KAAK,GAAG,KAAK;AAE3C,QAAK,QAAQ,MAAM,mBAAmB;AAE3C,SAAM,KAAK,yBAAyB;AAGpC,UAAO,OAAO,MAAM,mBAAmB;IACvC;;CAGJ,MAAc,aACZ,GACe;AACf,QAAM,KAAK,GAAG,KAAK,GAAG,MAAM;;;CAI9B,cACE,GACM;AACD,OAAK,MAAM,KAAK,aAAa,EAAE,CAAC;;;CAIvC,gBAAuB,YAA8B;AACnD,OAAK,cAAc;GACjB,WAAW;GACX,iBAAiB,EAAE,YAAY;GAChC,CAAC;;CAGJ,mBAA2B,KAA8C;AACvE,SAAO,yBAAyB,IAAI;;CAGtC,gBAAwB,KAItB;EACA,MAAM,OAAO,UAAU,IAAI;EAC3B,MAAM,SAAS,yBAAyB,KAAK,WAAW;AACxD,SAAO;GACL,YAAY,OAAO;GACnB,WAAW,KAAK;GAChB,mBAAmB,OAAO;GAC3B;;CAGH,iBAAyB,KAGvB;EACA,MAAM,EAAE,YAAY,sBAAsB,KAAK,mBAAmB,IAAI;AACtE,SAAO;GAAE,iBAAiB;GAAY,wBAAwB;GAAmB;;CAGnF,cAAsB;AACpB,MAAI,KAAK,WAAY,OAAM,IAAI,MAAM,6BAA6B;;CAGpE,IAAW,YAAY;AACrB,SAAO,KAAK;;;;CAKd,MAAa,SAAS;AACpB,OAAK,aAAa;AAGlB,OAAK,aAAa;AAElB,MAAI,CAAC,KAAK,UAAU;GAElB,MAAM,iBAAiB,KAAK,MAAM,KAAK,GAAG,UAAU,CAAC;AACrD,SAAM,KAAK,yBAAyB;AACpC,SAAM;AACN,SAAM,KAAK,GAAG,OAAO;SAChB;GACL,MAAM,iBAAiB,KAAK,MAC1B,KAAK,mBAAmB;IAAE,WAAW;IAAY,UAAU,EAAE;IAAE,GAAG,MAAM,EAAE,SAAS,QAAQ,CAC5F;GAGD,MAAM,iBAAiB,KAAK,MAAM,KAAK,GAAG,UAAU,CAAC;AAIrD,SAAM,KAAK,yBAAyB;AAEpC,OAAI,CAAE,MAAM,eAAiB,OAAM,IAAI,kBAAkB;AAEzD,SAAM;AAGN,SAAM,KAAK,GAAG,OAAO;;;CAIzB,MAAa,UAAU;AACrB,OAAK,aAAa;AAGlB,OAAK,aAAa;EAElB,MAAM,kBAAkB,KAAK,aAAa;GAAE,WAAW;GAAa,WAAW,EAAE;GAAE,CAAC;AAC/E,OAAK,MAAM,gBAAgB;EAEhC,MAAM,iBAAiB,KAAK,MAAM,KAAK,GAAG,UAAU,CAAC;AAIrD,QAAM,KAAK,yBAAyB;AAEpC,QAAM;AACN,QAAM;AACN,QAAM,KAAK,GAAG,OAAO;;CAOvB,IAAW,aAA+B;AACxC,SAAOC,cAAAA,8BAA8B,KAAK,YAAY;;CAOxD,gBACE,MACA,MACA,gBAAyB,OACzB,OACa;AACb,SAAO,KAAK,eACV,QACC,aAAa;GACZ,WAAW;GACX,yBAAyB;IACvB;IACA,IAAI;IACJ,MAAM,OAAO,KAAK,KAAK;IACvB;IACA,YAAY,SAAS;IACtB;GACF,IACA,MAAM,EAAE,wBAAwB,aAChC,MAAM,EAAE,wBAAwB,kBAClC;;CAKH,aACE,MACA,aAAsB,MACqB;AAC3C,SAAO,KAAK,mBACV;GACE,WAAW;GACX,sBAAsB;IACpB,MAAM,OAAO,KAAK,KAAK;IACvB;IACD;GACF,GACA,MAAMC,wBAAAA,iBAAAA,GAAAA,2BAAAA,UAAyB,EAAE,qBAAqB,SAAS,CAAC,CAClE;;CAGH,eACE,MACA,KACA,QACA,cACa;EACb,MAAM,UAAU,KAAK,oBAAoB,KAAK;EAE9C,MAAM,WAAW,KAAK,mBAAmB,IAAI,QAAQ,GAAG,MAAM;AAG5D,UAAON,cAAAA,uBAFO,OAAO,EAAE,EACX,eAAeH,cAAAA,oBAAoB,aAAa,EAAE,CAAC,GAAG,KAAA,EACzB;IACzC;AAEG,OAAK,MAAM,SAAS;AAEzB,SAAO;GAAE;GAAU;GAAS;;CAG9B,WAAkB,MAAiC;AACjD,OAAK,MAAM;AACX,SAAO,KAAK,eACV,OACC,aAAa;GAAE,WAAW;GAAsB,oBAAoB;IAAE;IAAM,IAAI;IAAS;GAAE,IAC3F,MAAM,EAAE,mBAAmB,aAC3B,MAAM,EAAE,mBAAmB,kBAC7B;;CAGH,aACE,MACA,MACA,OACa;AACb,OAAK,MAAM;AACX,OAAK,MAAM,2BAA2B,MAAM,UAAU;AACtD,SAAO,KAAK,eACV,QACC,aAAa;GACZ,WAAW;GACX,sBAAsB;IACpB;IACA,IAAI;IACJ,MACE,SAAS,KAAA,IAAY,KAAA,IAAY,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,GAAG;IAClF,YAAY,SAAS;IACtB;GACF,IACA,MAAM,EAAE,qBAAqB,aAC7B,MAAM,EAAE,qBAAqB,kBAC/B;;CAGH,gBACE,MACA,MACA,OACa;AACb,OAAK,MAAM;AACX,OAAK,MAAM,8BAA8B,MAAM,UAAU;AACzD,SAAO,KAAK,eACV,QACC,aAAa;GACZ,WAAW;GACX,yBAAyB;IACvB;IACA,IAAI;IACJ,MACE,SAAS,KAAA,IAAY,KAAA,IAAY,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,GAAG;IAClF,YAAY,SAAS;IACtB;GACF,IACA,MAAM,EAAE,wBAAwB,aAChC,MAAM,EAAE,wBAAwB,kBAClC;;CAGH,YACE,MACA,MACA,gBAAyB,OACzB,OACa;AACb,OAAK,MAAM;AACX,OAAK,MAAM,0BAA0B,MAAM,UAAU;AACrD,SAAO,KAAK,eACV,QACC,aAAa;GACZ,WAAW;GACX,qBAAqB;IACnB;IACA,IAAI;IACJ,MAAM,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,GAAG;IACrD;IACA,YAAY,SAAS;IACtB;GACF,IACA,MAAM,EAAE,oBAAoB,aAC5B,MAAM,EAAE,oBAAoB,kBAC9B;;CAGH,gBAAuB,MAAe,OAAiC;EACrE,MAAM,YAAA,GAAA,2BAAA,oBAA8B,KAAK;AACzC,SAAO,KAAK,YAAYU,WAAAA,YAAY,UAAU,OAAO,MAAM;;CAG7D,kBACE,MACA,gBAAoC,OACpC,OACa;EACb,MAAM,EAAE,MAAM,UAAU,eAAA,GAAA,2BAAA,sBAAmC,MAAM,cAAc;AAC/E,SAAO,KAAK,YAAY,YAAYC,WAAAA,eAAeD,WAAAA,YAAY,UAAU,OAAO,MAAM;;CAGxF,YAAmB,SAAiB,OAAiC;AACnE,SAAO,KAAK,YACVE,uBAAAA,mBACA,KAAK,UAAU,EAAE,SAAS,CAA6B,EACvD,OACA,MACD;;CAGH,gBAAuB,MAAc,KAA2B;AAC9D,OAAK,cAAc;GACjB,WAAW;GACX,iBAAiB;IAAE,GAAG,KAAK,mBAAmB,IAAI;IAAE;IAAM;GAC3D,CAAC;;CAGJ,mBAA0B,MAAoB;AAC5C,OAAK,cAAc;GAAE,WAAW;GAAsB,oBAAoB,EAAE,MAAM;GAAE,CAAC;;CAGvF,kBAAyB,MAAyC;AAChE,SAAO,KAAK,mBACV;GAAE,WAAW;GAAmB,iBAAiB,EAAE,MAAM;GAAE,GAC1D,MAAM;GACL,MAAM,QAAQ,EAAE,gBAAgB;AAChC,OAAI,UAAU,GAAI,OAAM,IAAI,MAAM,0CAA0C;AAE5E,UAAOT,cAAAA,uBAAuB,OADlBH,cAAAA,oBAAoB,EAAE,gBAAgB,kBAAkB,CAC3B;IAE5C;;CAGH,wBAA+B,MAAgC;AAC7D,SAAO,KAAK,mBACV;GAAE,WAAW;GAAsB,oBAAoB,EAAE,MAAM;GAAE,GAChE,MAAM,EAAE,mBAAmB,OAC7B;;CAGH,eAAsB,KAA6B;AACjD,OAAK,cAAc;GACjB,WAAW;GACX,gBAAgB,KAAK,mBAAmB,IAAI;GAC7C,CAAC;;CAGJ,eAAsB,KAAyC;AAC7D,SAAO,KAAK,mBACV;GACE,WAAW;GACX,gBAAgB,KAAK,mBAAmB,IAAI;GAC7C,GACA,MAAM,EAAE,eAAe,OACzB;;CA8BH,MAAa,gBACX,KACA,aAAsB,MACtB,cAAuB,OACoB;AAC3C,SAAO,KAAK,MAAM,YAAY;AAC5B,OAAI,CAAC,eAAe,aAAa,IAAI,EAAE;IAErC,MAAM,YAAY,KAAK,wBAAwB,IAAI,IAAI;AACvD,QAAI,aAAa,UAAU,uBAAuB,KAAK;SACjD,CAAC,YAAY;AACf,WAAK,MAAM;AACX,WAAK,MAAM,sBAAsB,UAAU,UAAU,MAAM,UAAU;AACrE,aAAO,UAAU;gBACR,UAAU,MAAM;AACzB,WAAK,MAAM;AACX,WAAK,MAAM,sBAAsB,UAAU,UAAU,MAAM,UAAU;AACrE,WAAK,MAAM,uBAAuB,UAAU,KAAK,OAAO;AACxD,aAAO,UAAU;;;;GAKvB,MAAM,SAAS,MAAM,KAAK,mBACxB;IACE,WAAW;IACX,aAAa;KACX,GAAG,KAAK,mBAAmB,IAAI;KACnB;KACb;IACF,GACA,MAAMS,wBAAAA,iBAAAA,GAAAA,2BAAAA,UAAyB,EAAE,YAAY,SAAS,CAAC,CACzD;AAED,QAAK,MAAM;AACX,QAAK,MAAM,oBAAoB,OAAO,MAAM,UAAU;AACtD,QAAK,MAAM,qBAAqB,OAAO,OAAO;AAI9C,OAAI,aAAa,IAAI,IAAI,KAAK,eAAe,OAAO,EAAE;AACpD,KAAA,GAAA,2BAAA,YAAW,OAAO;IAClB,MAAM,YAAY,KAAK,wBAAwB,IAAI,IAAI;AACvD,QAAI;SACE,cAAc,CAAC,UAAU,MAAM;AACjC,gBAAU,OAAO;AAEjB,gBAAU,uBAAuB,KAAK;;WAEnC;KACL,MAAM,YAAYI,cAAAA,yBAAyB,OAAO;AAClD,MAAA,GAAA,2BAAA,YAAW,UAAU;AACrB,SAAI,WACF,MAAK,wBAAwB,IAAI,KAAK;MACpC;MACA,MAAM;MACN,sBAAsB,KAAK;MAC5B,CAAC;SAEF,MAAK,wBAAwB,IAAI,KAAK;MACpC;MACA,MAAM,KAAA;MACN,sBAAsB,KAAK;MAC5B,CAAC;;;AAIR,UAAO;IACP;;CAeJ,MAAa,wBACX,KACA,aAAsB,MACiC;AACvD,SAAO,KAAK,MAAM,YAAY;GAG5B,MAAM,SAAS,MAAM,oBACnB,YAAY,MAAM,KAAK,gBAAgB,KAAK,YAAY,KAAK,CAC9D;AAGD,OAAI,WAAW,KAAA,KAAa,aAAa,IAAI,CAAE,MAAK,wBAAwB,OAAO,IAAI;AAEvF,UAAO;IACP;;;;;;;;;CAUJ,WAAkB,KAA2B;AAC3C,OAAK,MAAM;AACX,OAAK,cAAc;GACjB,WAAW;GACX,oBAAoB,KAAK,mBAAmB,IAAI;GACjD,CAAC;;;;;;CAOJ,YAAmB,KAA2B;AAC5C,OAAK,MAAM;AACX,OAAK,cAAc;GACjB,WAAW;GACX,qBAAqB,KAAK,mBAAmB,IAAI;GAClD,CAAC;;CAGJ,KAAY,KAA2B;AACrC,OAAK,WAAW,IAAI;AACpB,OAAK,YAAY,IAAI;;CAGvB,iBAAwB,KAAqB,KAA2B;AACtE,OAAK,cAAc;GACjB,WAAW;GACX,kBAAkB;IAChB,GAAG,KAAK,mBAAmB,IAAI;IAC/B,GAAG,KAAK,iBAAiB,IAAI;IAC9B;GACF,CAAC;;CAOJ,YAAmB,KAAkB,WAAsB,OAAsB;AAC/E,OAAK,MAAM;AACX,OAAK,cAAc;GACjB,WAAW;GACX,aAAa;IAAE,MAAMC,wBAAAA,iBAAiB,UAAU;IAAE,IAAI,KAAK,gBAAgB,IAAI;IAAE;GAClF,CAAC;AACF,MAAI,UAAU,KAAA,EAAW,MAAK,SAAS,KAAK,MAAM;;CAGpD,YAAmB,KAAoC;AACrD,SAAO,KAAK,mBACV;GACE,WAAW;GACX,aAAa,EAAE,OAAO,KAAK,gBAAgB,IAAI,EAAE;GAClD,GACA,MAAM,EAAE,YAAY,OACtB;;CAGH,SAAgB,KAAkB,KAAmB;AACnD,OAAK,MAAM;AACX,MAAI,WAAW,IAAI,CACjB,MAAK,cAAc;GACjB,WAAW;GACX,UAAU;IACR,OAAO,KAAK,gBAAgB,IAAI;IAChC,OAAO;KACL,GAAG,KAAK,mBAAmB,IAAI;KAC/B,WAAW;KACZ;IACF;GACF,CAAC;MAEF,MAAK,cAAc;GACjB,WAAW;GACX,UAAU;IACR,OAAO,KAAK,gBAAgB,IAAI;IAChC,OAAO,KAAK,gBAAgB,IAAI;IACjC;GACF,CAAC;;CAIN,cAAqB,KAAkB,KAA2B;AAChE,OAAK,MAAM;AACX,OAAK,cAAc;GACjB,WAAW;GACX,eAAe;IACb,OAAO,KAAK,gBAAgB,IAAI;IAChC,GAAG,KAAK,iBAAiB,IAAI;IAC9B;GACF,CAAC;;CAGJ,SAAgB,KAAsC;AACpD,OAAK,MAAM;AACX,SAAO,KAAK,mBACV;GAAE,WAAW;GAAY,UAAU,EAAE,OAAO,KAAK,gBAAgB,IAAI,EAAE;GAAE,GACxE,MAAMC,wBAAAA,cAAAA,GAAAA,2BAAAA,UAAsB,EAAE,SAAS,MAAM,CAAC,CAChD;;CAGH,MAAa,iBAAiB,KAAkD;AAC9E,SAAO,KAAK,MAAM,oBAAoB,YAAY,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC;;CAG9E,WAAkB,KAAwB;AACxC,OAAK,cAAc;GACjB,WAAW;GACX,YAAY,EAAE,OAAO,KAAK,gBAAgB,IAAI,EAAE;GACjD,CAAC;;CAGJ,YAAmB,KAAwB;AACzC,OAAK,cAAc;GACjB,WAAW;GACX,aAAa,EAAE,OAAO,KAAK,gBAAgB,IAAI,EAAE;GAClD,CAAC;;CAOJ,MAAa,cAAc,KAA0C;AACnE,SAAO,KAAK,MAAM,YAAY;GAC5B,MAAM,SAAS,MAAM,KAAK,kBACxB;IACE,WAAW;IACX,sBAAsB;KACpB,GAAG,KAAK,mBAAmB,IAAI;KAC/B,WAAW;KACX,OAAO;KACR;IACF,GACA,MAAM,EAAE,KAAK,MAAM,EAAE,qBAAqB,OAAQ,CACpD;AAED,QAAK,MAAM;AACX,QAAK,MAAM,iBAAiB,OAAO;AACnC,QAAK,MAAM,MAAM,OAAQ,MAAK,MAAM,eAAe,GAAG,IAAI,SAAS,GAAG,MAAM;AAE5E,UAAO;IACP;;CAGJ,MAAa,oBAAoB,KAAgD;AAC/E,SAAO,KAAK,MAAM,aACf,MAAM,KAAK,cAAc,IAAI,EAAE,KAAK,EAAE,KAAK,aAAa;GACvD;GACA,OAAO,OAAO,KAAK,MAAM,CAAC,UAAU;GACrC,EAAE,CACJ;;CAGH,MAAa,8BAA8B,KAAsD;AAC/F,SAAO,KAAK,MAAM,oBAAoB,YAAY,MAAM,KAAK,cAAc,IAAI,CAAC,CAAC;;CAGnF,MAAa,oCACX,KACuC;AACvC,SAAO,KAAK,MAAM,oBAAoB,YAAY,MAAM,KAAK,oBAAoB,IAAI,CAAC,CAAC;;CAGzF,UAAiB,KAAqB,KAAa,OAAkC;AACnF,OAAK,MAAM;AACX,OAAK,MAAM;AACX,OAAK,cAAc;GACjB,WAAW;GACX,qBAAqB;IACnB,GAAG,KAAK,mBAAmB,IAAI;IAC/B;IACA,OAAOC,aAAAA,QAAQ,MAAM;IACtB;GACF,CAAC;;CAGJ,aAAoB,KAAqB,KAAmB;AAC1D,OAAK,cAAc;GACjB,WAAW;GACX,wBAAwB;IACtB,GAAG,KAAK,mBAAmB,IAAI;IAC/B;IACD;GACF,CAAC;;CAGJ,MAAa,UAAU,KAAqB,KAAkC;AAC5E,SAAO,KAAK,MAAM,YAAY;GAC5B,MAAM,SAAS,MAAM,KAAK,mBACxB;IACE,WAAW;IACX,qBAAqB;KACnB,GAAG,KAAK,mBAAmB,IAAI;KAC/B;KACD;IACF,GACA,MAAM,EAAE,oBAAoB,MAC9B;AAED,QAAK,MAAM;AACX,QAAK,MAAM,cAAc,OAAO;AAEhC,UAAO;IACP;;CAGJ,MAAa,gBAAgB,KAAqB,KAA8B;AAC9E,SAAO,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,IAAI,CAAC,CAAC,UAAU,CAAC;;CAGvF,MAAa,cAAiB,KAAqB,KAAyB;AAC1E,SAAO,KAAK,MAAM,YAAY,KAAK,MAAM,MAAM,KAAK,gBAAgB,KAAK,IAAI,CAAC,CAAM;;CAGtF,MAAa,kBACX,KACA,KACiC;AACjC,SAAO,KAAK,MAAM,YAAY;GAC5B,MAAM,SAAS,MAAM,KAAK,mBACxB;IACE,WAAW;IACX,6BAA6B;KAC3B,GAAG,KAAK,mBAAmB,IAAI;KAC/B;KACD;IACF,GACA,MACC,EAAE,4BAA4B,SAAS,EAAE,4BAA4B,QAAQ,KAAA,EAChF;AAED,QAAK,MAAM;AACX,QAAK,MAAM,cAAc,QAAQ,UAAU;AAE3C,UAAO;IACP;;CAGJ,MAAa,wBACX,KACA,KAC6B;AAC7B,SAAO,KAAK,MAAM,YAAY;GAC5B,MAAM,OAAO,MAAM,KAAK,kBAAkB,KAAK,IAAI;AACnD,UAAO,SAAS,KAAA,IAAY,KAAA,IAAY,OAAO,KAAK,KAAK,CAAC,UAAU;IACpE;;CAGJ,MAAa,sBAAyB,KAAqB,KAAqC;AAC9F,SAAO,KAAK,MAAM,YAAY;GAC5B,MAAM,MAAM,MAAM,KAAK,wBAAwB,KAAK,IAAI;AACxD,OAAI,QAAQ,KAAA,EAAW,QAAO,KAAA;AAC9B,UAAO,KAAK,MAAM,IAAI;IACtB;;;CAaJ,oBAA2B,KAAa,WAAmB,WAAsC;EAC/F,MAAM,OAAO,OAAO,KAAK,KAAK,UAAU;GAAE;GAAW;GAAW,CAAC,CAAC;EAClE,MAAM,mBAAmB,KAAK,gBAAgB;GAAE,MAAM;GAAiB,SAAS;GAAK,EAAE,KAAK;AAC5F,OAAK,SAAS;GAAE,YAAY;GAAkB,WAAW;GAAY,EAAE,IAAI;AAC3E,SAAO;GAAE,YAAY;GAAkB,WAAW;GAAU;;CAO9D,MAAa,gBAAgB;AAC3B,OAAK,uBAAuB;AAC5B,SAAO,MAAM,KAAK;;;CAIpB,MAAa,WAAW;AACtB,MAAI,KAAK,WAAY;AACrB,OAAK,aAAa;EAClB,MAAM,iBAAiB,KAAK,MAAM,KAAK,GAAG,UAAU,CAAC;AACrD,QAAM,KAAK,yBAAyB;AACpC,QAAM;;;;CAKR,MAAa,QAAQ;AACnB,QAAM,KAAK,GAAG,OAAO;;CAOvB,oBAA4B,MAAgC;AAC1D,SAAOC,cAAAA,sBAAsB,MAAM,EAAE,KAAK,wBAAwB,KAAK,UAAU;;CAGnF,OAAe,mBAAmB;CAElC,OAAe,gBAAgB;AAC7B,gBAAc;AACd,MAAI,cAAc,qBAAA,WAA8B,eAAc,mBAAmB;AACjF,SAAO,cAAc"}
1
+ {"version":3,"file":"transaction.cjs","names":["isSignedResourceId","toResourceSignature","parseSignedResourceId","isLocalResourceId","createSignedResourceId","isNotFoundError","PromiseTracker","initialTxStatWithoutTime","TxAPI_Open_Request_WritableTx","ensureSignedResourceIdNotNull","protoToResource","JsonObject","JsonGzObject","ErrorResourceType","extractBasicResourceData","fieldTypeToProto","protoToField","toBytes","resourceIsDeleted","createLocalResourceId"],"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 type {\n ResourceAPI_Tree_Filter,\n ResourceAPI_Tree_SeedResource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\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 {\n fieldTypeToProto,\n protoToField,\n protoToResource,\n resourceIsDeleted,\n} 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\nexport type ResourceTreeItem = ResourceData & { kv: KeyValue[]; traverseWasStopped: boolean };\n\n/** A single frame from the resourceTree() stream.\n *\n * When the server advertises `treeStopMarker:v1`, a stop-matched node is emitted\n * as a lightweight marker instead of a full resource payload. Callers must\n * narrow on `frameKind` before accessing type-specific fields.\n * Note: `frameKind` is distinct from `ResourceData.kind` (which is the resource kind).\n */\nexport type ResourceTreeFrame =\n | (ResourceTreeItem & { frameKind: \"resource\" })\n | { frameKind: \"stopMarker\"; id: SignedResourceId; traverseWasStopped: true };\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 // Tree streaming\n //\n\n /**\n * Perform a single `ResourceTree` walk and yield each visited resource.\n *\n * Items are yielded incrementally as stream frames arrive from server.\n *\n * The low-level transaction stream is still ordered, so each active request\n * must be consumed to completion (or closed via iterator `return()`/`throw()`)\n * before later responses can be dispatched.\n *\n * @param seeds - Roots for the traversal. May include both {@link ResourceData}\n * and {@link SignedResourceId} values in the same array.\n * @param opts.fieldFilter - Per-field predicate; matching field edges are not descended.\n * This wire field accepts only one filter. Compose multiple rules via\n * `treeFilter.and(...)` / `treeFilter.or(...)`.\n * @param opts.traverseStopRules - Per-resource predicate; matching resources are returned\n * with `traverseWasStopped = true` and their children are not visited.\n * This wire field accepts only one filter. Compose multiple rules via\n * `treeFilter.and(...)` / `treeFilter.or(...)`.\n * @param opts.includeKv - When true, each yielded item includes KV entries.\n * @param opts.maxDepth - Optional depth cap.\n */\n public resourceTree(\n seeds: (ResourceData | SignedResourceId)[],\n opts?: {\n fieldFilter?: ResourceAPI_Tree_Filter;\n traverseStopRules?: ResourceAPI_Tree_Filter;\n includeKv?: boolean;\n maxDepth?: number;\n },\n ): AsyncIterable<ResourceTreeFrame> {\n if (seeds.length === 0) {\n throw new Error(\"resourceTree: at least one seed must be provided\");\n }\n\n const seedProtos = seeds.map((seed): ResourceAPI_Tree_SeedResource => {\n const signedId = typeof seed === \"string\" ? seed : seed.id;\n const { globalId, signature } = parseSignedResourceId(signedId);\n return { resourceId: globalId, resourceSignature: signature };\n });\n\n const firstSeed = seedProtos[0];\n\n const responseStream = this.ll.sendStream({\n oneofKind: \"resourceTree\",\n resourceTree: {\n // Keep compatibility with request shape that requires non-optional fields.\n resourceId: firstSeed?.resourceId ?? 0n,\n resourceSignature: firstSeed?.resourceSignature ?? new Uint8Array(0),\n seeds: seedProtos,\n fieldFilter: opts?.fieldFilter,\n traverseStopRules: opts?.traverseStopRules,\n includeKv: opts?.includeKv ?? false,\n maxDepth: opts?.maxDepth,\n },\n });\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<ResourceTreeFrame> {\n const iterator = responseStream[Symbol.asyncIterator]();\n\n return {\n async next(): Promise<IteratorResult<ResourceTreeFrame>> {\n while (true) {\n const item = await iterator.next();\n if (item.done) return { value: undefined, done: true };\n\n const frame = item.value.resourceTree;\n if (frame === undefined) continue;\n\n if (frame.resource && resourceIsDeleted(frame.resource)) {\n continue;\n }\n\n if (!frame.resource) {\n // Stop-marker frame: no resource body; server advertised treeStopMarker:v1.\n const id = createSignedResourceId(\n frame.resourceId,\n toResourceSignature(frame.resourceSignature),\n );\n return {\n value: { frameKind: \"stopMarker\", id, traverseWasStopped: true },\n done: false,\n };\n }\n\n return {\n value: {\n frameKind: \"resource\",\n ...protoToResource(frame.resource),\n kv: frame.kv,\n traverseWasStopped: frame.traverseWasStopped,\n },\n done: false,\n };\n }\n },\n async return(): Promise<IteratorResult<ResourceTreeFrame>> {\n if (iterator.return) await iterator.return();\n return { value: undefined, done: true };\n },\n async throw(error?: unknown): Promise<IteratorResult<ResourceTreeFrame>> {\n if (iterator.throw) await iterator.throw(error);\n throw error;\n },\n };\n },\n };\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,4 +1,5 @@
1
1
  import { BasicResourceData, ColorProof, FieldData, FieldType, FutureFieldType, LocalResourceId, OptionalSignedResourceId, ResourceData, ResourceSignature, ResourceType, SignedResourceId } from "./types.js";
2
+ import { ResourceAPI_Tree_Filter } from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js";
2
3
  import { LLPlTransaction } from "./ll_transaction.js";
3
4
  import { FinalResourceDataPredicate } from "./final.js";
4
5
  import { ResourceDataCacheRecord } from "./cache.js";
@@ -26,6 +27,24 @@ interface KeyValueString {
26
27
  key: string;
27
28
  value: string;
28
29
  }
30
+ type ResourceTreeItem = ResourceData & {
31
+ kv: KeyValue[];
32
+ traverseWasStopped: boolean;
33
+ };
34
+ /** A single frame from the resourceTree() stream.
35
+ *
36
+ * When the server advertises `treeStopMarker:v1`, a stop-matched node is emitted
37
+ * as a lightweight marker instead of a full resource payload. Callers must
38
+ * narrow on `frameKind` before accessing type-specific fields.
39
+ * Note: `frameKind` is distinct from `ResourceData.kind` (which is the resource kind).
40
+ */
41
+ type ResourceTreeFrame = (ResourceTreeItem & {
42
+ frameKind: "resource";
43
+ }) | {
44
+ frameKind: "stopMarker";
45
+ id: SignedResourceId;
46
+ traverseWasStopped: true;
47
+ };
29
48
  interface _FieldId<RId> {
30
49
  /** Parent resource id */
31
50
  resourceId: RId;
@@ -184,10 +203,37 @@ declare class PlTransaction {
184
203
  /** Await incoming message loop termination and throw
185
204
  * any leftover errors if it was unsuccessful */
186
205
  await(): Promise<void>;
206
+ /**
207
+ * Perform a single `ResourceTree` walk and yield each visited resource.
208
+ *
209
+ * Items are yielded incrementally as stream frames arrive from server.
210
+ *
211
+ * The low-level transaction stream is still ordered, so each active request
212
+ * must be consumed to completion (or closed via iterator `return()`/`throw()`)
213
+ * before later responses can be dispatched.
214
+ *
215
+ * @param seeds - Roots for the traversal. May include both {@link ResourceData}
216
+ * and {@link SignedResourceId} values in the same array.
217
+ * @param opts.fieldFilter - Per-field predicate; matching field edges are not descended.
218
+ * This wire field accepts only one filter. Compose multiple rules via
219
+ * `treeFilter.and(...)` / `treeFilter.or(...)`.
220
+ * @param opts.traverseStopRules - Per-resource predicate; matching resources are returned
221
+ * with `traverseWasStopped = true` and their children are not visited.
222
+ * This wire field accepts only one filter. Compose multiple rules via
223
+ * `treeFilter.and(...)` / `treeFilter.or(...)`.
224
+ * @param opts.includeKv - When true, each yielded item includes KV entries.
225
+ * @param opts.maxDepth - Optional depth cap.
226
+ */
227
+ resourceTree(seeds: (ResourceData | SignedResourceId)[], opts?: {
228
+ fieldFilter?: ResourceAPI_Tree_Filter;
229
+ traverseStopRules?: ResourceAPI_Tree_Filter;
230
+ includeKv?: boolean;
231
+ maxDepth?: number;
232
+ }): AsyncIterable<ResourceTreeFrame>;
187
233
  private nextLocalResourceId;
188
234
  private static localTxIdCounter;
189
235
  private static nextLocalTxId;
190
236
  }
191
237
  //#endregion
192
- export { AnyFieldId, AnyFieldRef, AnyRef, AnyResourceRef, FieldId, FieldRef, KeyValue, KeyValueString, LocalFieldId, PlTransaction, ResourceIdWithSignature, ResourceRef, TxCommitConflict, field, isField, isFieldRef, isResource, isResourceId, isResourceRef, toFieldId, toGlobalFieldId, toGlobalResourceId };
238
+ export { AnyFieldId, AnyFieldRef, AnyRef, AnyResourceRef, FieldId, FieldRef, KeyValue, KeyValueString, LocalFieldId, PlTransaction, ResourceIdWithSignature, ResourceRef, ResourceTreeFrame, ResourceTreeItem, TxCommitConflict, field, isField, isFieldRef, isResource, isResourceId, isResourceRef, toFieldId, toGlobalFieldId, toGlobalResourceId };
193
239
  //# sourceMappingURL=transaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.d.ts","names":[],"sources":["../../src/core/transaction.ts"],"mappings":"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"}
1
+ {"version":3,"file":"transaction.d.ts","names":[],"sources":["../../src/core/transaction.ts"],"mappings":"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"}