@milaboratories/pl-client 3.16.1 → 3.17.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.
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.js","names":[],"sources":["../../src/core/transaction.ts"],"sourcesContent":["import 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 AuthAPI_Grant,\n ResourceAPI_Tree_Filter,\n ResourceAPI_Tree_SeedResource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport {\n TxAPI_Open_Request_WritableTx,\n AuthAPI_GrantAccess_GrantType,\n AuthAPI_Role,\n} 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\n/** Access level handed to a grant recipient (see {@link PlTransaction.grantAccess}). */\nexport interface GrantPermissions {\n /** Write access = ability to modify the resource subtree + re-share it. */\n writable: boolean;\n}\n\n/**\n * Distinguishes a regular user-to-user grant from a system-level public grant.\n * Re-export of the wire enum so callers need not reach into the generated proto.\n */\nexport const GrantType = AuthAPI_GrantAccess_GrantType;\nexport type GrantType = AuthAPI_GrantAccess_GrantType;\n\n/**\n * Effective role of an authenticated session (controller / workflow / user / admin).\n * Re-export of the wire enum so callers need not reach into the generated proto.\n * Returned by {@link LLPlClient.getSessionInfo} and surfaced as\n * {@link PlClient.currentUserRole}.\n */\nexport const Role = AuthAPI_Role;\nexport type Role = AuthAPI_Role;\n\n/**\n * Recognises the \"all users on the server\" sentinel login. A public\n * ({@link GrantType.ANY_AUTHORISED}) grant is recorded against a reserved login, and\n * recipients of an everyone-grant surface in `ListGrants` with that value — callers\n * detect it here and map it to \"*\".\n *\n * Matched by exact token equality. The long random token guarantees no real user login\n * collides with it.\n */\nconst EveryoneUser = \"everyone-Po9ahwahxai7Aejingaiyiequuecu3ei4moaNge4xahTh0Co7XeeLeiph6ahy3As\";\nexport function isEveryoneUserLogin(login: string): boolean {\n return login === EveryoneUser;\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 showSoftDeletes: false,\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 * Grant another user access to a resource (and its subtree). Used by the\n * project-sharing donor flow to hand a recipient the shared envelope.\n *\n * `grantType` defaults to a regular user-to-user grant\n * ({@link GrantType.SINGLE_USER}); pass {@link GrantType.ANY_AUTHORISED}\n * to make the resource public to everyone (requires backend `publicGrants:v1`\n * and a role allowed to grant to everyone — `target` is ignored / rewritten\n * to the everyone-user by the backend).\n */\n public grantAccess(\n rId: AnyResourceRef,\n target: string,\n permissions: GrantPermissions,\n grantType: GrantType = AuthAPI_GrantAccess_GrantType.SINGLE_USER,\n ): void {\n this.sendVoidAsync({\n oneofKind: \"grantAccess\",\n grantAccess: {\n ...this.toSignedResourceId(rId),\n targetUser: target,\n permissions,\n grantType,\n },\n });\n }\n\n /**\n * Revoke a single user's grant on a resource — the inverse of {@link grantAccess}.\n * Used by the sharing donor flow to pull one recipient out of a multi-recipient\n * envelope without tearing the whole share down. A no-op on the backend if the user\n * has no grant.\n */\n public revokeAccess(rId: AnyResourceRef, target: string): void {\n this.sendVoidAsync({\n oneofKind: \"revokeAccess\",\n revokeAccess: {\n ...this.toSignedResourceId(rId),\n targetUser: target,\n },\n });\n }\n\n /**\n * Enumerate the grants of a resource — the donor-side \"who did I share with\" view.\n * The backend gates this on the signed, writable resource handle, so only the\n * resource's owner can read its grants. Recipients of a public\n * ({@link GrantType.ANY_AUTHORISED}) grant surface with `user` matching the\n * everyone-sentinel — test with {@link isEveryoneUserLogin}.\n *\n * Transactional unary op (single response with all grants), so it rides the tx\n * channel and works on every wire protocol — unlike the standalone server-streaming\n * `ListGrants` RPC, which has no REST binding.\n */\n public listGrants(rId: AnyResourceRef): Promise<AuthAPI_Grant[]> {\n return this.sendSingleAndParse(\n { oneofKind: \"listGrants\", listGrants: this.toSignedResourceId(rId) },\n (r) => r.listGrants.grants,\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 showSoftDeletes: false,\n // Empty token requests the full tree — this call has no continuation to resume.\n changedSinceToken: new Uint8Array(0),\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
+ {"version":3,"file":"transaction.js","names":[],"sources":["../../src/core/transaction.ts"],"sourcesContent":["import 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 AuthAPI_Grant,\n ResourceAPI_Tree_Filter,\n ResourceAPI_Tree_SeedResource,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport {\n TxAPI_Open_Request_WritableTx,\n AuthAPI_GrantAccess_GrantType,\n AuthAPI_Role,\n} 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 * A node the request's `traverseStopRules` matched is emitted as a lightweight marker\n * instead of a full resource payload. Callers must narrow on `frameKind` before accessing\n * type-specific fields.\n * Note: `frameKind` is distinct from `ResourceData.kind` (which is the resource kind).\n *\n * Under `changedSinceToken` there are no markers: stop rules do not apply, and an unchanged\n * resource produces no frame at all.\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\n/** Access level handed to a grant recipient (see {@link PlTransaction.grantAccess}). */\nexport interface GrantPermissions {\n /** Write access = ability to modify the resource subtree + re-share it. */\n writable: boolean;\n}\n\n/**\n * Distinguishes a regular user-to-user grant from a system-level public grant.\n * Re-export of the wire enum so callers need not reach into the generated proto.\n */\nexport const GrantType = AuthAPI_GrantAccess_GrantType;\nexport type GrantType = AuthAPI_GrantAccess_GrantType;\n\n/**\n * Effective role of an authenticated session (controller / workflow / user / admin).\n * Re-export of the wire enum so callers need not reach into the generated proto.\n * Returned by {@link LLPlClient.getSessionInfo} and surfaced as\n * {@link PlClient.currentUserRole}.\n */\nexport const Role = AuthAPI_Role;\nexport type Role = AuthAPI_Role;\n\n/**\n * Recognises the \"all users on the server\" sentinel login. A public\n * ({@link GrantType.ANY_AUTHORISED}) grant is recorded against a reserved login, and\n * recipients of an everyone-grant surface in `ListGrants` with that value — callers\n * detect it here and map it to \"*\".\n *\n * Matched by exact token equality. The long random token guarantees no real user login\n * collides with it.\n */\nconst EveryoneUser = \"everyone-Po9ahwahxai7Aejingaiyiequuecu3ei4moaNge4xahTh0Co7XeeLeiph6ahy3As\";\nexport function isEveryoneUserLogin(login: string): boolean {\n return login === EveryoneUser;\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 txOpen: Promise<{ id: bigint; sinceToken?: Uint8Array }>;\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.txOpen = 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) => ({\n id: notEmpty(r.txOpen.tx?.id),\n // Empty on a server without treeChangedSince:v1, and on a writable transaction,\n // which is served none: its reads see this transaction's own uncommitted writes,\n // so a token earned here could pin state that never commits.\n sinceToken: r.txOpen.nextSinceToken.length > 0 ? r.txOpen.nextSinceToken : undefined,\n }),\n );\n this.globalTxId = this.txOpen.then((r) => r.id);\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 showSoftDeletes: false,\n // Always empty: an on-demand read asks for what the caller does not hold, so a\n // token here could only suppress the one body it came for.\n changedSinceToken: new Uint8Array(0),\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 * Grant another user access to a resource (and its subtree). Used by the\n * project-sharing donor flow to hand a recipient the shared envelope.\n *\n * `grantType` defaults to a regular user-to-user grant\n * ({@link GrantType.SINGLE_USER}); pass {@link GrantType.ANY_AUTHORISED}\n * to make the resource public to everyone (requires backend `publicGrants:v1`\n * and a role allowed to grant to everyone — `target` is ignored / rewritten\n * to the everyone-user by the backend).\n */\n public grantAccess(\n rId: AnyResourceRef,\n target: string,\n permissions: GrantPermissions,\n grantType: GrantType = AuthAPI_GrantAccess_GrantType.SINGLE_USER,\n ): void {\n this.sendVoidAsync({\n oneofKind: \"grantAccess\",\n grantAccess: {\n ...this.toSignedResourceId(rId),\n targetUser: target,\n permissions,\n grantType,\n },\n });\n }\n\n /**\n * Revoke a single user's grant on a resource — the inverse of {@link grantAccess}.\n * Used by the sharing donor flow to pull one recipient out of a multi-recipient\n * envelope without tearing the whole share down. A no-op on the backend if the user\n * has no grant.\n */\n public revokeAccess(rId: AnyResourceRef, target: string): void {\n this.sendVoidAsync({\n oneofKind: \"revokeAccess\",\n revokeAccess: {\n ...this.toSignedResourceId(rId),\n targetUser: target,\n },\n });\n }\n\n /**\n * Enumerate the grants of a resource — the donor-side \"who did I share with\" view.\n * The backend gates this on the signed, writable resource handle, so only the\n * resource's owner can read its grants. Recipients of a public\n * ({@link GrantType.ANY_AUTHORISED}) grant surface with `user` matching the\n * everyone-sentinel — test with {@link isEveryoneUserLogin}.\n *\n * Transactional unary op (single response with all grants), so it rides the tx\n * channel and works on every wire protocol — unlike the standalone server-streaming\n * `ListGrants` RPC, which has no REST binding.\n */\n public listGrants(rId: AnyResourceRef): Promise<AuthAPI_Grant[]> {\n return this.sendSingleAndParse(\n { oneofKind: \"listGrants\", listGrants: this.toSignedResourceId(rId) },\n (r) => r.listGrants.grants,\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 // Always empty, as for the single resource read above.\n changedSinceToken: new Uint8Array(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 /**\n * The change token this transaction was opened at, to hand back as\n * {@link resourceTree}'s `changedSinceToken` on a later poll. `undefined` when the server\n * does not advertise `treeChangedSince:v1`, and on a writable transaction, which is served\n * none.\n *\n * Store it only after a whole response has been applied - kept after a partial apply, the\n * dropped resources are never sent again - and discard it when the traversal shape changes,\n * which the token cannot express itself. Opaque: never parse one, and never compare across\n * instances.\n */\n public async getNextSinceToken(): Promise<Uint8Array | undefined> {\n return (await this.txOpen).sinceToken;\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 * Deprecated, and ignored under `changedSinceToken`: a stop rule prunes on mutable state,\n * so on a delta walk it would hide a changed subtree behind a resource that merely\n * flipped a gate.\n * @param opts.includeKv - When true, each yielded item includes KV entries.\n * @param opts.maxDepth - Optional depth cap.\n * @param opts.changedSinceToken - A token from {@link getNextSinceToken}. Yields only\n * resources newer than it, and the walk ENDS at an unchanged one, so a change beneath one\n * is not reached. A response may reference resources it does not carry; read those back\n * with `unconditionalDepth`. An unusable token is answered with the full tree, not an error.\n * @param opts.unconditionalDepth - Emit every resource at or below this depth whatever its\n * change token says, the seed being depth 0. Ignored without `changedSinceToken`. Absent\n * differs from 0, which takes the seeds alone.\n */\n public resourceTree(\n seeds: (ResourceData | SignedResourceId)[],\n opts?: {\n fieldFilter?: ResourceAPI_Tree_Filter;\n /** @deprecated prune with `changedSinceToken` instead; ignored under one. */\n traverseStopRules?: ResourceAPI_Tree_Filter;\n includeKv?: boolean;\n maxDepth?: number;\n changedSinceToken?: Uint8Array;\n unconditionalDepth?: 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 showSoftDeletes: false,\n // Empty requests the full tree.\n changedSinceToken: opts?.changedSinceToken ?? new Uint8Array(0),\n unconditionalDepth: opts?.unconditionalDepth,\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 // A traverseStopRules match, sent without a body.\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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"}
@@ -147,7 +147,8 @@ const treeFilter = {
147
147
  * exactly the same nodes where the client BFS would stop, eliminating
148
148
  * unnecessary follow-up calls.
149
149
  *
150
- * Valid only inside `traverseStopRules`.
150
+ * Valid only inside `traverseStopRules`, which the backend ignores under a
151
+ * `changedSinceToken` - prune with the token instead where one is available.
151
152
  */
152
153
  readyOrDuplicateOrError() {
153
154
  return treeFilter.or(treeFilter.resourceReadyForCalculation(true), treeFilter.isDuplicate(true), treeFilter.hasErrors(true));
@@ -1 +1 @@
1
- {"version":3,"file":"tree_filter.cjs","names":[],"sources":["../../src/core/tree_filter.ts"],"sourcesContent":["import type { ResourceAPI_Tree_Filter } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport {\n ResourceAPI_Tree_Filter_OperatorType,\n ResourceAPI_Tree_Filter_Property,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\n\nexport type { ResourceAPI_Tree_Filter };\n\n/** Shorthand alias for the filter predicate type. */\nexport type Filter = ResourceAPI_Tree_Filter;\n\n/** Shorthand alias for the Property enum. */\nexport type Property = ResourceAPI_Tree_Filter_Property;\n\n// Re-export enum namespaces under shorter aliases so callers need not import api.ts directly.\nexport { ResourceAPI_Tree_Filter_OperatorType as FilterOperatorType };\nexport { ResourceAPI_Tree_Filter_Property as FilterProperty };\n\n/**\n * Builder helpers for {@link ResourceAPI_Tree_Filter} predicates used in\n * `ResourceAPI_Tree_Request.fieldFilter` and `traverseStopRules`.\n *\n * Property restrictions (not enforced here; the backend rejects invalid combinations):\n * - `FIELD_NAME` is only valid inside `fieldFilter`.\n * - `IS_FINAL`, `ALL_OUTPUTS_FINAL`, and resource-level boolean predicates are only valid inside `traverseStopRules`.\n */\nexport const treeFilter = {\n // ── Group operators ──────────────────────────────────────────────────────\n\n and(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.AND,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n or(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.OR,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n not(child: Filter): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.NOT,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: [child] } },\n };\n },\n\n // ── Generic leaf operators ───────────────────────────────────────────────\n\n /** Exact-match predicate on a string property. */\n eq(prop: Property, value: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"stringValue\", stringValue: value },\n };\n },\n\n /** Regex-match predicate on a string property. */\n match(prop: Property, pattern: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.MATCH,\n value: { oneofKind: \"stringValue\", stringValue: pattern },\n };\n },\n\n /** Boolean-equality predicate. */\n boolEq(prop: Property, value: boolean): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"boolValue\", boolValue: value },\n };\n },\n\n // ── Typed convenience wrappers ───────────────────────────────────────────\n\n /** Match resources whose type string equals `name` exactly. */\n resourceTypeEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, name);\n },\n\n /** Match resources whose type string satisfies the regex `pattern`. */\n resourceTypeMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, pattern);\n },\n\n /**\n * Match field edges whose name equals `name` exactly.\n * Valid only inside `fieldFilter`.\n */\n fieldNameEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.FIELD_NAME, name);\n },\n\n /**\n * Match field edges whose name satisfies the regex `pattern`.\n * Valid only inside `fieldFilter`.\n */\n fieldNameMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.FIELD_NAME, pattern);\n },\n\n /**\n * Match resources where `is_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n isFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_FINAL, value);\n },\n\n /**\n * Match resources where `all_outputs_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n allOutputsFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.ALL_OUTPUTS_FINAL, value);\n },\n\n /**\n * Match resources where `resource_ready_for_calculation == value`.\n * True when the resource is Original, inputs are locked, and all inputs are final.\n * Valid only inside `traverseStopRules`.\n */\n resourceReadyForCalculation(value: boolean): Filter {\n return treeFilter.boolEq(\n ResourceAPI_Tree_Filter_Property.RESOURCE_READY_FOR_CALCULATION,\n value,\n );\n },\n\n /**\n * Match resources where `is_duplicate == value`.\n * True when the resource has a non-zero original_resource_id.\n * Valid only inside `traverseStopRules`.\n */\n isDuplicate(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_DUPLICATE, value);\n },\n\n /**\n * Match resources where `has_errors == value`.\n * True when the resource has at least one field carrying an error (aggregated\n * has-error flag). Can be true even when the resource's own status is not\n * Error (e.g., an Original resource with a failed input field).\n * Valid only inside `traverseStopRules`.\n */\n hasErrors(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.HAS_ERRORS, value);\n },\n\n /**\n * Match resources where `outputs_locked == value`.\n * Valid only inside `traverseStopRules`.\n */\n outputsLocked(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.OUTPUTS_LOCKED, value);\n },\n\n /**\n * Match resources that are ready-or-duplicate-or-error: mirrors the BFS\n * `readyOrDuplicateOrError` predicate used by pl-tree to decide whether a\n * resource subtree needs further polling.\n *\n * Use this as `traverseStopRules` to stop the server-side tree walk at\n * exactly the same nodes where the client BFS would stop, eliminating\n * unnecessary follow-up calls.\n *\n * Valid only inside `traverseStopRules`.\n */\n readyOrDuplicateOrError(): Filter {\n return treeFilter.or(\n treeFilter.resourceReadyForCalculation(true),\n treeFilter.isDuplicate(true),\n treeFilter.hasErrors(true),\n );\n },\n} as const;\n"],"mappings":";;;;;;;;;;AA0BA,MAAa,aAAa;CAGxB,IAAI,GAAG,UAA4B;EACjC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,GAAG,GAAG,UAA4B;EAChC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,IAAI,OAAuB;EACzB,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,CAAC,KAAK,EAAE;GAAE;EACzE;CACF;;CAKA,GAAG,MAAgB,OAAuB;EACxC,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAM;EACxD;CACF;;CAGA,MAAM,MAAgB,SAAyB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAQ;EAC1D;CACF;;CAGA,OAAO,MAAgB,OAAwB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAa,WAAW;GAAM;EACpD;CACF;;CAKA,eAAe,MAAsB;EACnC,OAAO,WAAW,GAAA,GAAmD,IAAI;CAC3E;;CAGA,kBAAkB,SAAyB;EACzC,OAAO,WAAW,MAAA,GAAsD,OAAO;CACjF;;;;;CAMA,YAAY,MAAsB;EAChC,OAAO,WAAW,GAAA,GAAgD,IAAI;CACxE;;;;;CAMA,eAAe,SAAyB;EACtC,OAAO,WAAW,MAAA,GAAmD,OAAO;CAC9E;;;;;CAMA,QAAQ,OAAwB;EAC9B,OAAO,WAAW,OAAA,GAAkD,KAAK;CAC3E;;;;;CAMA,gBAAgB,OAAwB;EACtC,OAAO,WAAW,OAAA,GAA2D,KAAK;CACpF;;;;;;CAOA,4BAA4B,OAAwB;EAClD,OAAO,WAAW,OAAA,GAEhB,KACF;CACF;;;;;;CAOA,YAAY,OAAwB;EAClC,OAAO,WAAW,OAAA,GAAsD,KAAK;CAC/E;;;;;;;;CASA,UAAU,OAAwB;EAChC,OAAO,WAAW,OAAA,GAAoD,KAAK;CAC7E;;;;;CAMA,cAAc,OAAwB;EACpC,OAAO,WAAW,OAAA,GAAwD,KAAK;CACjF;;;;;;;;;;;;CAaA,0BAAkC;EAChC,OAAO,WAAW,GAChB,WAAW,4BAA4B,IAAI,GAC3C,WAAW,YAAY,IAAI,GAC3B,WAAW,UAAU,IAAI,CAC3B;CACF;AACF"}
1
+ {"version":3,"file":"tree_filter.cjs","names":[],"sources":["../../src/core/tree_filter.ts"],"sourcesContent":["import type { ResourceAPI_Tree_Filter } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport {\n ResourceAPI_Tree_Filter_OperatorType,\n ResourceAPI_Tree_Filter_Property,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\n\nexport type { ResourceAPI_Tree_Filter };\n\n/** Shorthand alias for the filter predicate type. */\nexport type Filter = ResourceAPI_Tree_Filter;\n\n/** Shorthand alias for the Property enum. */\nexport type Property = ResourceAPI_Tree_Filter_Property;\n\n// Re-export enum namespaces under shorter aliases so callers need not import api.ts directly.\nexport { ResourceAPI_Tree_Filter_OperatorType as FilterOperatorType };\nexport { ResourceAPI_Tree_Filter_Property as FilterProperty };\n\n/**\n * Builder helpers for {@link ResourceAPI_Tree_Filter} predicates used in\n * `ResourceAPI_Tree_Request.fieldFilter` and `traverseStopRules`.\n *\n * Property restrictions (not enforced here; the backend rejects invalid combinations):\n * - `FIELD_NAME` is only valid inside `fieldFilter`.\n * - `IS_FINAL`, `ALL_OUTPUTS_FINAL`, and resource-level boolean predicates are only valid inside `traverseStopRules`.\n */\nexport const treeFilter = {\n // ── Group operators ──────────────────────────────────────────────────────\n\n and(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.AND,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n or(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.OR,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n not(child: Filter): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.NOT,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: [child] } },\n };\n },\n\n // ── Generic leaf operators ───────────────────────────────────────────────\n\n /** Exact-match predicate on a string property. */\n eq(prop: Property, value: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"stringValue\", stringValue: value },\n };\n },\n\n /** Regex-match predicate on a string property. */\n match(prop: Property, pattern: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.MATCH,\n value: { oneofKind: \"stringValue\", stringValue: pattern },\n };\n },\n\n /** Boolean-equality predicate. */\n boolEq(prop: Property, value: boolean): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"boolValue\", boolValue: value },\n };\n },\n\n // ── Typed convenience wrappers ───────────────────────────────────────────\n\n /** Match resources whose type string equals `name` exactly. */\n resourceTypeEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, name);\n },\n\n /** Match resources whose type string satisfies the regex `pattern`. */\n resourceTypeMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, pattern);\n },\n\n /**\n * Match field edges whose name equals `name` exactly.\n * Valid only inside `fieldFilter`.\n */\n fieldNameEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.FIELD_NAME, name);\n },\n\n /**\n * Match field edges whose name satisfies the regex `pattern`.\n * Valid only inside `fieldFilter`.\n */\n fieldNameMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.FIELD_NAME, pattern);\n },\n\n /**\n * Match resources where `is_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n isFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_FINAL, value);\n },\n\n /**\n * Match resources where `all_outputs_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n allOutputsFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.ALL_OUTPUTS_FINAL, value);\n },\n\n /**\n * Match resources where `resource_ready_for_calculation == value`.\n * True when the resource is Original, inputs are locked, and all inputs are final.\n * Valid only inside `traverseStopRules`.\n */\n resourceReadyForCalculation(value: boolean): Filter {\n return treeFilter.boolEq(\n ResourceAPI_Tree_Filter_Property.RESOURCE_READY_FOR_CALCULATION,\n value,\n );\n },\n\n /**\n * Match resources where `is_duplicate == value`.\n * True when the resource has a non-zero original_resource_id.\n * Valid only inside `traverseStopRules`.\n */\n isDuplicate(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_DUPLICATE, value);\n },\n\n /**\n * Match resources where `has_errors == value`.\n * True when the resource has at least one field carrying an error (aggregated\n * has-error flag). Can be true even when the resource's own status is not\n * Error (e.g., an Original resource with a failed input field).\n * Valid only inside `traverseStopRules`.\n */\n hasErrors(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.HAS_ERRORS, value);\n },\n\n /**\n * Match resources where `outputs_locked == value`.\n * Valid only inside `traverseStopRules`.\n */\n outputsLocked(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.OUTPUTS_LOCKED, value);\n },\n\n /**\n * Match resources that are ready-or-duplicate-or-error: mirrors the BFS\n * `readyOrDuplicateOrError` predicate used by pl-tree to decide whether a\n * resource subtree needs further polling.\n *\n * Use this as `traverseStopRules` to stop the server-side tree walk at\n * exactly the same nodes where the client BFS would stop, eliminating\n * unnecessary follow-up calls.\n *\n * Valid only inside `traverseStopRules`, which the backend ignores under a\n * `changedSinceToken` - prune with the token instead where one is available.\n */\n readyOrDuplicateOrError(): Filter {\n return treeFilter.or(\n treeFilter.resourceReadyForCalculation(true),\n treeFilter.isDuplicate(true),\n treeFilter.hasErrors(true),\n );\n },\n} as const;\n"],"mappings":";;;;;;;;;;AA0BA,MAAa,aAAa;CAGxB,IAAI,GAAG,UAA4B;EACjC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,GAAG,GAAG,UAA4B;EAChC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,IAAI,OAAuB;EACzB,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,CAAC,KAAK,EAAE;GAAE;EACzE;CACF;;CAKA,GAAG,MAAgB,OAAuB;EACxC,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAM;EACxD;CACF;;CAGA,MAAM,MAAgB,SAAyB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAQ;EAC1D;CACF;;CAGA,OAAO,MAAgB,OAAwB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAa,WAAW;GAAM;EACpD;CACF;;CAKA,eAAe,MAAsB;EACnC,OAAO,WAAW,GAAA,GAAmD,IAAI;CAC3E;;CAGA,kBAAkB,SAAyB;EACzC,OAAO,WAAW,MAAA,GAAsD,OAAO;CACjF;;;;;CAMA,YAAY,MAAsB;EAChC,OAAO,WAAW,GAAA,GAAgD,IAAI;CACxE;;;;;CAMA,eAAe,SAAyB;EACtC,OAAO,WAAW,MAAA,GAAmD,OAAO;CAC9E;;;;;CAMA,QAAQ,OAAwB;EAC9B,OAAO,WAAW,OAAA,GAAkD,KAAK;CAC3E;;;;;CAMA,gBAAgB,OAAwB;EACtC,OAAO,WAAW,OAAA,GAA2D,KAAK;CACpF;;;;;;CAOA,4BAA4B,OAAwB;EAClD,OAAO,WAAW,OAAA,GAEhB,KACF;CACF;;;;;;CAOA,YAAY,OAAwB;EAClC,OAAO,WAAW,OAAA,GAAsD,KAAK;CAC/E;;;;;;;;CASA,UAAU,OAAwB;EAChC,OAAO,WAAW,OAAA,GAAoD,KAAK;CAC7E;;;;;CAMA,cAAc,OAAwB;EACpC,OAAO,WAAW,OAAA,GAAwD,KAAK;CACjF;;;;;;;;;;;;;CAcA,0BAAkC;EAChC,OAAO,WAAW,GAChB,WAAW,4BAA4B,IAAI,GAC3C,WAAW,YAAY,IAAI,GAC3B,WAAW,UAAU,IAAI,CAC3B;CACF;AACF"}
@@ -80,7 +80,8 @@ export declare const treeFilter: {
80
80
  * exactly the same nodes where the client BFS would stop, eliminating
81
81
  * unnecessary follow-up calls.
82
82
  *
83
- * Valid only inside `traverseStopRules`.
83
+ * Valid only inside `traverseStopRules`, which the backend ignores under a
84
+ * `changedSinceToken` - prune with the token instead where one is available.
84
85
  */
85
86
  readonly readyOrDuplicateOrError: () => Filter;
86
87
  };
@@ -1 +1 @@
1
- {"version":3,"file":"tree_filter.d.ts","names":[],"sources":["../../src/core/tree_filter.ts"],"mappings":";;;YASY,SAAS;;YAGT,WAAW;;;;;;;;;qBAcV;WAGX,SAAG,UAAc,aAAW;WAO5B,QAAE,UAAc,aAAW;WAO3B,MAAG,OAAQ,WAAS;;WAUpB,KAAE,MAAO,UAAQ,kBAAkB;;WASnC,QAAK,MAAO,UAAQ,oBAAoB;;WASxC,SAAM,MAAO,UAAQ,mBAAmB;;WAWxC,iBAAc,iBAAgB;;WAK9B,oBAAiB,oBAAmB;;;;;WAQpC,cAAW,iBAAgB;;;;;WAQ3B,iBAAc,oBAAmB;;;;;WAQjC,UAAO,mBAAkB;;;;;WAQzB,kBAAe,mBAAkB;;;;;;WASjC,8BAA2B,mBAAkB;;;;;;WAY7C,cAAW,mBAAkB;;;;;;;;WAW7B,YAAS,mBAAkB;;;;;WAQ3B,gBAAa,mBAAkB;;;;;;;;;;;;WAe/B,+BAA2B"}
1
+ {"version":3,"file":"tree_filter.d.ts","names":[],"sources":["../../src/core/tree_filter.ts"],"mappings":";;;YASY,SAAS;;YAGT,WAAW;;;;;;;;;qBAcV;WAGX,SAAG,UAAc,aAAW;WAO5B,QAAE,UAAc,aAAW;WAO3B,MAAG,OAAQ,WAAS;;WAUpB,KAAE,MAAO,UAAQ,kBAAkB;;WASnC,QAAK,MAAO,UAAQ,oBAAoB;;WASxC,SAAM,MAAO,UAAQ,mBAAmB;;WAWxC,iBAAc,iBAAgB;;WAK9B,oBAAiB,oBAAmB;;;;;WAQpC,cAAW,iBAAgB;;;;;WAQ3B,iBAAc,oBAAmB;;;;;WAQjC,UAAO,mBAAkB;;;;;WAQzB,kBAAe,mBAAkB;;;;;;WASjC,8BAA2B,mBAAkB;;;;;;WAY7C,cAAW,mBAAkB;;;;;;;;WAW7B,YAAS,mBAAkB;;;;;WAQ3B,gBAAa,mBAAkB;;;;;;;;;;;;;WAgB/B,+BAA2B"}
@@ -147,7 +147,8 @@ const treeFilter = {
147
147
  * exactly the same nodes where the client BFS would stop, eliminating
148
148
  * unnecessary follow-up calls.
149
149
  *
150
- * Valid only inside `traverseStopRules`.
150
+ * Valid only inside `traverseStopRules`, which the backend ignores under a
151
+ * `changedSinceToken` - prune with the token instead where one is available.
151
152
  */
152
153
  readyOrDuplicateOrError() {
153
154
  return treeFilter.or(treeFilter.resourceReadyForCalculation(true), treeFilter.isDuplicate(true), treeFilter.hasErrors(true));
@@ -1 +1 @@
1
- {"version":3,"file":"tree_filter.js","names":[],"sources":["../../src/core/tree_filter.ts"],"sourcesContent":["import type { ResourceAPI_Tree_Filter } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport {\n ResourceAPI_Tree_Filter_OperatorType,\n ResourceAPI_Tree_Filter_Property,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\n\nexport type { ResourceAPI_Tree_Filter };\n\n/** Shorthand alias for the filter predicate type. */\nexport type Filter = ResourceAPI_Tree_Filter;\n\n/** Shorthand alias for the Property enum. */\nexport type Property = ResourceAPI_Tree_Filter_Property;\n\n// Re-export enum namespaces under shorter aliases so callers need not import api.ts directly.\nexport { ResourceAPI_Tree_Filter_OperatorType as FilterOperatorType };\nexport { ResourceAPI_Tree_Filter_Property as FilterProperty };\n\n/**\n * Builder helpers for {@link ResourceAPI_Tree_Filter} predicates used in\n * `ResourceAPI_Tree_Request.fieldFilter` and `traverseStopRules`.\n *\n * Property restrictions (not enforced here; the backend rejects invalid combinations):\n * - `FIELD_NAME` is only valid inside `fieldFilter`.\n * - `IS_FINAL`, `ALL_OUTPUTS_FINAL`, and resource-level boolean predicates are only valid inside `traverseStopRules`.\n */\nexport const treeFilter = {\n // ── Group operators ──────────────────────────────────────────────────────\n\n and(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.AND,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n or(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.OR,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n not(child: Filter): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.NOT,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: [child] } },\n };\n },\n\n // ── Generic leaf operators ───────────────────────────────────────────────\n\n /** Exact-match predicate on a string property. */\n eq(prop: Property, value: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"stringValue\", stringValue: value },\n };\n },\n\n /** Regex-match predicate on a string property. */\n match(prop: Property, pattern: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.MATCH,\n value: { oneofKind: \"stringValue\", stringValue: pattern },\n };\n },\n\n /** Boolean-equality predicate. */\n boolEq(prop: Property, value: boolean): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"boolValue\", boolValue: value },\n };\n },\n\n // ── Typed convenience wrappers ───────────────────────────────────────────\n\n /** Match resources whose type string equals `name` exactly. */\n resourceTypeEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, name);\n },\n\n /** Match resources whose type string satisfies the regex `pattern`. */\n resourceTypeMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, pattern);\n },\n\n /**\n * Match field edges whose name equals `name` exactly.\n * Valid only inside `fieldFilter`.\n */\n fieldNameEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.FIELD_NAME, name);\n },\n\n /**\n * Match field edges whose name satisfies the regex `pattern`.\n * Valid only inside `fieldFilter`.\n */\n fieldNameMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.FIELD_NAME, pattern);\n },\n\n /**\n * Match resources where `is_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n isFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_FINAL, value);\n },\n\n /**\n * Match resources where `all_outputs_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n allOutputsFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.ALL_OUTPUTS_FINAL, value);\n },\n\n /**\n * Match resources where `resource_ready_for_calculation == value`.\n * True when the resource is Original, inputs are locked, and all inputs are final.\n * Valid only inside `traverseStopRules`.\n */\n resourceReadyForCalculation(value: boolean): Filter {\n return treeFilter.boolEq(\n ResourceAPI_Tree_Filter_Property.RESOURCE_READY_FOR_CALCULATION,\n value,\n );\n },\n\n /**\n * Match resources where `is_duplicate == value`.\n * True when the resource has a non-zero original_resource_id.\n * Valid only inside `traverseStopRules`.\n */\n isDuplicate(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_DUPLICATE, value);\n },\n\n /**\n * Match resources where `has_errors == value`.\n * True when the resource has at least one field carrying an error (aggregated\n * has-error flag). Can be true even when the resource's own status is not\n * Error (e.g., an Original resource with a failed input field).\n * Valid only inside `traverseStopRules`.\n */\n hasErrors(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.HAS_ERRORS, value);\n },\n\n /**\n * Match resources where `outputs_locked == value`.\n * Valid only inside `traverseStopRules`.\n */\n outputsLocked(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.OUTPUTS_LOCKED, value);\n },\n\n /**\n * Match resources that are ready-or-duplicate-or-error: mirrors the BFS\n * `readyOrDuplicateOrError` predicate used by pl-tree to decide whether a\n * resource subtree needs further polling.\n *\n * Use this as `traverseStopRules` to stop the server-side tree walk at\n * exactly the same nodes where the client BFS would stop, eliminating\n * unnecessary follow-up calls.\n *\n * Valid only inside `traverseStopRules`.\n */\n readyOrDuplicateOrError(): Filter {\n return treeFilter.or(\n treeFilter.resourceReadyForCalculation(true),\n treeFilter.isDuplicate(true),\n treeFilter.hasErrors(true),\n );\n },\n} as const;\n"],"mappings":";;;;;;;;;;AA0BA,MAAa,aAAa;CAGxB,IAAI,GAAG,UAA4B;EACjC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,GAAG,GAAG,UAA4B;EAChC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,IAAI,OAAuB;EACzB,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,CAAC,KAAK,EAAE;GAAE;EACzE;CACF;;CAKA,GAAG,MAAgB,OAAuB;EACxC,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAM;EACxD;CACF;;CAGA,MAAM,MAAgB,SAAyB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAQ;EAC1D;CACF;;CAGA,OAAO,MAAgB,OAAwB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAa,WAAW;GAAM;EACpD;CACF;;CAKA,eAAe,MAAsB;EACnC,OAAO,WAAW,GAAA,GAAmD,IAAI;CAC3E;;CAGA,kBAAkB,SAAyB;EACzC,OAAO,WAAW,MAAA,GAAsD,OAAO;CACjF;;;;;CAMA,YAAY,MAAsB;EAChC,OAAO,WAAW,GAAA,GAAgD,IAAI;CACxE;;;;;CAMA,eAAe,SAAyB;EACtC,OAAO,WAAW,MAAA,GAAmD,OAAO;CAC9E;;;;;CAMA,QAAQ,OAAwB;EAC9B,OAAO,WAAW,OAAA,GAAkD,KAAK;CAC3E;;;;;CAMA,gBAAgB,OAAwB;EACtC,OAAO,WAAW,OAAA,GAA2D,KAAK;CACpF;;;;;;CAOA,4BAA4B,OAAwB;EAClD,OAAO,WAAW,OAAA,GAEhB,KACF;CACF;;;;;;CAOA,YAAY,OAAwB;EAClC,OAAO,WAAW,OAAA,GAAsD,KAAK;CAC/E;;;;;;;;CASA,UAAU,OAAwB;EAChC,OAAO,WAAW,OAAA,GAAoD,KAAK;CAC7E;;;;;CAMA,cAAc,OAAwB;EACpC,OAAO,WAAW,OAAA,GAAwD,KAAK;CACjF;;;;;;;;;;;;CAaA,0BAAkC;EAChC,OAAO,WAAW,GAChB,WAAW,4BAA4B,IAAI,GAC3C,WAAW,YAAY,IAAI,GAC3B,WAAW,UAAU,IAAI,CAC3B;CACF;AACF"}
1
+ {"version":3,"file":"tree_filter.js","names":[],"sources":["../../src/core/tree_filter.ts"],"sourcesContent":["import type { ResourceAPI_Tree_Filter } from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\nimport {\n ResourceAPI_Tree_Filter_OperatorType,\n ResourceAPI_Tree_Filter_Property,\n} from \"../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api\";\n\nexport type { ResourceAPI_Tree_Filter };\n\n/** Shorthand alias for the filter predicate type. */\nexport type Filter = ResourceAPI_Tree_Filter;\n\n/** Shorthand alias for the Property enum. */\nexport type Property = ResourceAPI_Tree_Filter_Property;\n\n// Re-export enum namespaces under shorter aliases so callers need not import api.ts directly.\nexport { ResourceAPI_Tree_Filter_OperatorType as FilterOperatorType };\nexport { ResourceAPI_Tree_Filter_Property as FilterProperty };\n\n/**\n * Builder helpers for {@link ResourceAPI_Tree_Filter} predicates used in\n * `ResourceAPI_Tree_Request.fieldFilter` and `traverseStopRules`.\n *\n * Property restrictions (not enforced here; the backend rejects invalid combinations):\n * - `FIELD_NAME` is only valid inside `fieldFilter`.\n * - `IS_FINAL`, `ALL_OUTPUTS_FINAL`, and resource-level boolean predicates are only valid inside `traverseStopRules`.\n */\nexport const treeFilter = {\n // ── Group operators ──────────────────────────────────────────────────────\n\n and(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.AND,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n or(...children: Filter[]): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.OR,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: children } },\n };\n },\n\n not(child: Filter): Filter {\n return {\n operator: ResourceAPI_Tree_Filter_OperatorType.NOT,\n value: { oneofKind: \"filtersValue\", filtersValue: { filters: [child] } },\n };\n },\n\n // ── Generic leaf operators ───────────────────────────────────────────────\n\n /** Exact-match predicate on a string property. */\n eq(prop: Property, value: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"stringValue\", stringValue: value },\n };\n },\n\n /** Regex-match predicate on a string property. */\n match(prop: Property, pattern: string): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.MATCH,\n value: { oneofKind: \"stringValue\", stringValue: pattern },\n };\n },\n\n /** Boolean-equality predicate. */\n boolEq(prop: Property, value: boolean): Filter {\n return {\n key: prop,\n operator: ResourceAPI_Tree_Filter_OperatorType.EQUAL,\n value: { oneofKind: \"boolValue\", boolValue: value },\n };\n },\n\n // ── Typed convenience wrappers ───────────────────────────────────────────\n\n /** Match resources whose type string equals `name` exactly. */\n resourceTypeEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, name);\n },\n\n /** Match resources whose type string satisfies the regex `pattern`. */\n resourceTypeMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.RESOURCE_TYPE, pattern);\n },\n\n /**\n * Match field edges whose name equals `name` exactly.\n * Valid only inside `fieldFilter`.\n */\n fieldNameEq(name: string): Filter {\n return treeFilter.eq(ResourceAPI_Tree_Filter_Property.FIELD_NAME, name);\n },\n\n /**\n * Match field edges whose name satisfies the regex `pattern`.\n * Valid only inside `fieldFilter`.\n */\n fieldNameMatch(pattern: string): Filter {\n return treeFilter.match(ResourceAPI_Tree_Filter_Property.FIELD_NAME, pattern);\n },\n\n /**\n * Match resources where `is_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n isFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_FINAL, value);\n },\n\n /**\n * Match resources where `all_outputs_final == value`.\n * Valid only inside `traverseStopRules`.\n */\n allOutputsFinal(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.ALL_OUTPUTS_FINAL, value);\n },\n\n /**\n * Match resources where `resource_ready_for_calculation == value`.\n * True when the resource is Original, inputs are locked, and all inputs are final.\n * Valid only inside `traverseStopRules`.\n */\n resourceReadyForCalculation(value: boolean): Filter {\n return treeFilter.boolEq(\n ResourceAPI_Tree_Filter_Property.RESOURCE_READY_FOR_CALCULATION,\n value,\n );\n },\n\n /**\n * Match resources where `is_duplicate == value`.\n * True when the resource has a non-zero original_resource_id.\n * Valid only inside `traverseStopRules`.\n */\n isDuplicate(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.IS_DUPLICATE, value);\n },\n\n /**\n * Match resources where `has_errors == value`.\n * True when the resource has at least one field carrying an error (aggregated\n * has-error flag). Can be true even when the resource's own status is not\n * Error (e.g., an Original resource with a failed input field).\n * Valid only inside `traverseStopRules`.\n */\n hasErrors(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.HAS_ERRORS, value);\n },\n\n /**\n * Match resources where `outputs_locked == value`.\n * Valid only inside `traverseStopRules`.\n */\n outputsLocked(value: boolean): Filter {\n return treeFilter.boolEq(ResourceAPI_Tree_Filter_Property.OUTPUTS_LOCKED, value);\n },\n\n /**\n * Match resources that are ready-or-duplicate-or-error: mirrors the BFS\n * `readyOrDuplicateOrError` predicate used by pl-tree to decide whether a\n * resource subtree needs further polling.\n *\n * Use this as `traverseStopRules` to stop the server-side tree walk at\n * exactly the same nodes where the client BFS would stop, eliminating\n * unnecessary follow-up calls.\n *\n * Valid only inside `traverseStopRules`, which the backend ignores under a\n * `changedSinceToken` - prune with the token instead where one is available.\n */\n readyOrDuplicateOrError(): Filter {\n return treeFilter.or(\n treeFilter.resourceReadyForCalculation(true),\n treeFilter.isDuplicate(true),\n treeFilter.hasErrors(true),\n );\n },\n} as const;\n"],"mappings":";;;;;;;;;;AA0BA,MAAa,aAAa;CAGxB,IAAI,GAAG,UAA4B;EACjC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,GAAG,GAAG,UAA4B;EAChC,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,SAAS;GAAE;EAC1E;CACF;CAEA,IAAI,OAAuB;EACzB,OAAO;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAgB,cAAc,EAAE,SAAS,CAAC,KAAK,EAAE;GAAE;EACzE;CACF;;CAKA,GAAG,MAAgB,OAAuB;EACxC,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAM;EACxD;CACF;;CAGA,MAAM,MAAgB,SAAyB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAe,aAAa;GAAQ;EAC1D;CACF;;CAGA,OAAO,MAAgB,OAAwB;EAC7C,OAAO;GACL,KAAK;GACL,UAAA;GACA,OAAO;IAAE,WAAW;IAAa,WAAW;GAAM;EACpD;CACF;;CAKA,eAAe,MAAsB;EACnC,OAAO,WAAW,GAAA,GAAmD,IAAI;CAC3E;;CAGA,kBAAkB,SAAyB;EACzC,OAAO,WAAW,MAAA,GAAsD,OAAO;CACjF;;;;;CAMA,YAAY,MAAsB;EAChC,OAAO,WAAW,GAAA,GAAgD,IAAI;CACxE;;;;;CAMA,eAAe,SAAyB;EACtC,OAAO,WAAW,MAAA,GAAmD,OAAO;CAC9E;;;;;CAMA,QAAQ,OAAwB;EAC9B,OAAO,WAAW,OAAA,GAAkD,KAAK;CAC3E;;;;;CAMA,gBAAgB,OAAwB;EACtC,OAAO,WAAW,OAAA,GAA2D,KAAK;CACpF;;;;;;CAOA,4BAA4B,OAAwB;EAClD,OAAO,WAAW,OAAA,GAEhB,KACF;CACF;;;;;;CAOA,YAAY,OAAwB;EAClC,OAAO,WAAW,OAAA,GAAsD,KAAK;CAC/E;;;;;;;;CASA,UAAU,OAAwB;EAChC,OAAO,WAAW,OAAA,GAAoD,KAAK;CAC7E;;;;;CAMA,cAAc,OAAwB;EACpC,OAAO,WAAW,OAAA,GAAwD,KAAK;CACjF;;;;;;;;;;;;;CAcA,0BAAkC;EAChC,OAAO,WAAW,GAChB,WAAW,4BAA4B,IAAI,GAC3C,WAAW,YAAY,IAAI,GAC3B,WAAW,UAAU,IAAI,CAC3B;CACF;AACF"}
@@ -4472,6 +4472,12 @@ var ResourceAPI_Get_Request$Type = class extends _protobuf_ts_runtime.MessageTyp
4472
4472
  name: "show_soft_deletes",
4473
4473
  kind: "scalar",
4474
4474
  T: 8
4475
+ },
4476
+ {
4477
+ no: 5,
4478
+ name: "changed_since_token",
4479
+ kind: "scalar",
4480
+ T: 12
4475
4481
  }
4476
4482
  ]);
4477
4483
  }
@@ -4481,6 +4487,7 @@ var ResourceAPI_Get_Request$Type = class extends _protobuf_ts_runtime.MessageTyp
4481
4487
  message.resourceSignature = /* @__PURE__ */ new Uint8Array(0);
4482
4488
  message.loadFields = false;
4483
4489
  message.showSoftDeletes = false;
4490
+ message.changedSinceToken = /* @__PURE__ */ new Uint8Array(0);
4484
4491
  if (value !== void 0) (0, _protobuf_ts_runtime.reflectionMergePartial)(this, message, value);
4485
4492
  return message;
4486
4493
  }
@@ -4501,6 +4508,9 @@ var ResourceAPI_Get_Request$Type = class extends _protobuf_ts_runtime.MessageTyp
4501
4508
  case 4:
4502
4509
  message.showSoftDeletes = reader.bool();
4503
4510
  break;
4511
+ case 5:
4512
+ message.changedSinceToken = reader.bytes();
4513
+ break;
4504
4514
  default:
4505
4515
  let u = options.readUnknownField;
4506
4516
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -4515,6 +4525,7 @@ var ResourceAPI_Get_Request$Type = class extends _protobuf_ts_runtime.MessageTyp
4515
4525
  if (message.loadFields !== false) writer.tag(2, _protobuf_ts_runtime.WireType.Varint).bool(message.loadFields);
4516
4526
  if (message.resourceSignature.length) writer.tag(3, _protobuf_ts_runtime.WireType.LengthDelimited).bytes(message.resourceSignature);
4517
4527
  if (message.showSoftDeletes !== false) writer.tag(4, _protobuf_ts_runtime.WireType.Varint).bool(message.showSoftDeletes);
4528
+ if (message.changedSinceToken.length) writer.tag(5, _protobuf_ts_runtime.WireType.LengthDelimited).bytes(message.changedSinceToken);
4518
4529
  let u = options.writeUnknownFields;
4519
4530
  if (u !== false) (u == true ? _protobuf_ts_runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
4520
4531
  return writer;
@@ -5621,6 +5632,13 @@ var ResourceAPI_Tree_Request$Type = class extends _protobuf_ts_runtime.MessageTy
5621
5632
  name: "changed_since_token",
5622
5633
  kind: "scalar",
5623
5634
  T: 12
5635
+ },
5636
+ {
5637
+ no: 11,
5638
+ name: "unconditional_depth",
5639
+ kind: "scalar",
5640
+ opt: true,
5641
+ T: 13
5624
5642
  }
5625
5643
  ]);
5626
5644
  }
@@ -5667,6 +5685,9 @@ var ResourceAPI_Tree_Request$Type = class extends _protobuf_ts_runtime.MessageTy
5667
5685
  case 10:
5668
5686
  message.changedSinceToken = reader.bytes();
5669
5687
  break;
5688
+ case 11:
5689
+ message.unconditionalDepth = reader.uint32();
5690
+ break;
5670
5691
  default:
5671
5692
  let u = options.readUnknownField;
5672
5693
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -5686,6 +5707,7 @@ var ResourceAPI_Tree_Request$Type = class extends _protobuf_ts_runtime.MessageTy
5686
5707
  for (let i = 0; i < message.seeds.length; i++) ResourceAPI_Tree_SeedResource.internalBinaryWrite(message.seeds[i], writer.tag(8, _protobuf_ts_runtime.WireType.LengthDelimited).fork(), options).join();
5687
5708
  if (message.showSoftDeletes !== false) writer.tag(9, _protobuf_ts_runtime.WireType.Varint).bool(message.showSoftDeletes);
5688
5709
  if (message.changedSinceToken.length) writer.tag(10, _protobuf_ts_runtime.WireType.LengthDelimited).bytes(message.changedSinceToken);
5710
+ if (message.unconditionalDepth !== void 0) writer.tag(11, _protobuf_ts_runtime.WireType.Varint).uint32(message.unconditionalDepth);
5689
5711
  let u = options.writeUnknownFields;
5690
5712
  if (u !== false) (u == true ? _protobuf_ts_runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
5691
5713
  return writer;
@@ -5979,12 +6001,6 @@ var ResourceAPI_Tree_Response$Type = class extends _protobuf_ts_runtime.MessageT
5979
6001
  name: "resource_signature",
5980
6002
  kind: "scalar",
5981
6003
  T: 12
5982
- },
5983
- {
5984
- no: 6,
5985
- name: "resource_unchanged",
5986
- kind: "scalar",
5987
- T: 8
5988
6004
  }
5989
6005
  ]);
5990
6006
  }
@@ -5994,7 +6010,6 @@ var ResourceAPI_Tree_Response$Type = class extends _protobuf_ts_runtime.MessageT
5994
6010
  message.traverseWasStopped = false;
5995
6011
  message.resourceId = 0n;
5996
6012
  message.resourceSignature = /* @__PURE__ */ new Uint8Array(0);
5997
- message.resourceUnchanged = false;
5998
6013
  if (value !== void 0) (0, _protobuf_ts_runtime.reflectionMergePartial)(this, message, value);
5999
6014
  return message;
6000
6015
  }
@@ -6018,9 +6033,6 @@ var ResourceAPI_Tree_Response$Type = class extends _protobuf_ts_runtime.MessageT
6018
6033
  case 5:
6019
6034
  message.resourceSignature = reader.bytes();
6020
6035
  break;
6021
- case 6:
6022
- message.resourceUnchanged = reader.bool();
6023
- break;
6024
6036
  default:
6025
6037
  let u = options.readUnknownField;
6026
6038
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -6036,7 +6048,6 @@ var ResourceAPI_Tree_Response$Type = class extends _protobuf_ts_runtime.MessageT
6036
6048
  if (message.traverseWasStopped !== false) writer.tag(3, _protobuf_ts_runtime.WireType.Varint).bool(message.traverseWasStopped);
6037
6049
  if (message.resourceId !== 0n) writer.tag(4, _protobuf_ts_runtime.WireType.Varint).uint64(message.resourceId);
6038
6050
  if (message.resourceSignature.length) writer.tag(5, _protobuf_ts_runtime.WireType.LengthDelimited).bytes(message.resourceSignature);
6039
- if (message.resourceUnchanged !== false) writer.tag(6, _protobuf_ts_runtime.WireType.Varint).bool(message.resourceUnchanged);
6040
6051
  let u = options.writeUnknownFields;
6041
6052
  if (u !== false) (u == true ? _protobuf_ts_runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
6042
6053
  return writer;
@@ -10048,6 +10059,12 @@ var ResourceKVAPI_List_Request$Type = class extends _protobuf_ts_runtime.Message
10048
10059
  name: "limit",
10049
10060
  kind: "scalar",
10050
10061
  T: 13
10062
+ },
10063
+ {
10064
+ no: 5,
10065
+ name: "changed_since_token",
10066
+ kind: "scalar",
10067
+ T: 12
10051
10068
  }
10052
10069
  ]);
10053
10070
  }
@@ -10057,6 +10074,7 @@ var ResourceKVAPI_List_Request$Type = class extends _protobuf_ts_runtime.Message
10057
10074
  message.resourceSignature = /* @__PURE__ */ new Uint8Array(0);
10058
10075
  message.startFrom = "";
10059
10076
  message.limit = 0;
10077
+ message.changedSinceToken = /* @__PURE__ */ new Uint8Array(0);
10060
10078
  if (value !== void 0) (0, _protobuf_ts_runtime.reflectionMergePartial)(this, message, value);
10061
10079
  return message;
10062
10080
  }
@@ -10077,6 +10095,9 @@ var ResourceKVAPI_List_Request$Type = class extends _protobuf_ts_runtime.Message
10077
10095
  case 3:
10078
10096
  message.limit = reader.uint32();
10079
10097
  break;
10098
+ case 5:
10099
+ message.changedSinceToken = reader.bytes();
10100
+ break;
10080
10101
  default:
10081
10102
  let u = options.readUnknownField;
10082
10103
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -10091,6 +10112,7 @@ var ResourceKVAPI_List_Request$Type = class extends _protobuf_ts_runtime.Message
10091
10112
  if (message.startFrom !== "") writer.tag(2, _protobuf_ts_runtime.WireType.LengthDelimited).string(message.startFrom);
10092
10113
  if (message.limit !== 0) writer.tag(3, _protobuf_ts_runtime.WireType.Varint).uint32(message.limit);
10093
10114
  if (message.resourceSignature.length) writer.tag(4, _protobuf_ts_runtime.WireType.LengthDelimited).bytes(message.resourceSignature);
10115
+ if (message.changedSinceToken.length) writer.tag(5, _protobuf_ts_runtime.WireType.LengthDelimited).bytes(message.changedSinceToken);
10094
10116
  let u = options.writeUnknownFields;
10095
10117
  if (u !== false) (u == true ? _protobuf_ts_runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
10096
10118
  return writer;