@milaboratories/pl-client 3.14.7 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/core/PromiseTracker.d.ts +1 -2
  2. package/dist/core/PromiseTracker.d.ts.map +1 -1
  3. package/dist/core/abstract_stream.d.ts +2 -3
  4. package/dist/core/abstract_stream.d.ts.map +1 -1
  5. package/dist/core/auth.d.ts +2 -4
  6. package/dist/core/auth.d.ts.map +1 -1
  7. package/dist/core/cache.d.ts +1 -3
  8. package/dist/core/cache.d.ts.map +1 -1
  9. package/dist/core/capabilities.d.ts +2 -3
  10. package/dist/core/capabilities.d.ts.map +1 -1
  11. package/dist/core/client.cjs +7 -0
  12. package/dist/core/client.cjs.map +1 -1
  13. package/dist/core/client.d.ts +8 -5
  14. package/dist/core/client.d.ts.map +1 -1
  15. package/dist/core/client.js +7 -0
  16. package/dist/core/client.js.map +1 -1
  17. package/dist/core/config.d.ts +29 -31
  18. package/dist/core/config.d.ts.map +1 -1
  19. package/dist/core/default_client.d.ts +2 -4
  20. package/dist/core/default_client.d.ts.map +1 -1
  21. package/dist/core/driver.d.ts +4 -6
  22. package/dist/core/driver.d.ts.map +1 -1
  23. package/dist/core/errors.d.ts +20 -22
  24. package/dist/core/errors.d.ts.map +1 -1
  25. package/dist/core/final.d.ts +4 -5
  26. package/dist/core/final.d.ts.map +1 -1
  27. package/dist/core/ll_client.cjs +45 -18
  28. package/dist/core/ll_client.cjs.map +1 -1
  29. package/dist/core/ll_client.d.ts +21 -10
  30. package/dist/core/ll_client.d.ts.map +1 -1
  31. package/dist/core/ll_client.js +45 -18
  32. package/dist/core/ll_client.js.map +1 -1
  33. package/dist/core/ll_transaction.d.ts +4 -6
  34. package/dist/core/ll_transaction.d.ts.map +1 -1
  35. package/dist/core/stat.d.ts +2 -3
  36. package/dist/core/stat.d.ts.map +1 -1
  37. package/dist/core/transaction.cjs +2 -1
  38. package/dist/core/transaction.cjs.map +1 -1
  39. package/dist/core/transaction.d.ts +30 -32
  40. package/dist/core/transaction.d.ts.map +1 -1
  41. package/dist/core/transaction.js +2 -1
  42. package/dist/core/transaction.js.map +1 -1
  43. package/dist/core/tree_filter.d.ts +14 -10
  44. package/dist/core/tree_filter.d.ts.map +1 -1
  45. package/dist/core/types.d.ts +54 -55
  46. package/dist/core/types.d.ts.map +1 -1
  47. package/dist/core/unauth_client.cjs +79 -32
  48. package/dist/core/unauth_client.cjs.map +1 -1
  49. package/dist/core/unauth_client.d.ts +53 -20
  50. package/dist/core/unauth_client.d.ts.map +1 -1
  51. package/dist/core/unauth_client.js +79 -32
  52. package/dist/core/unauth_client.js.map +1 -1
  53. package/dist/core/user_resources.cjs +23 -0
  54. package/dist/core/user_resources.cjs.map +1 -1
  55. package/dist/core/user_resources.d.ts +33 -7
  56. package/dist/core/user_resources.d.ts.map +1 -1
  57. package/dist/core/user_resources.js +23 -0
  58. package/dist/core/user_resources.js.map +1 -1
  59. package/dist/core/wire.d.ts +5 -7
  60. package/dist/core/wire.d.ts.map +1 -1
  61. package/dist/helpers/pl.d.ts +32 -34
  62. package/dist/helpers/pl.d.ts.map +1 -1
  63. package/dist/helpers/poll.d.ts +8 -9
  64. package/dist/helpers/poll.d.ts.map +1 -1
  65. package/dist/helpers/tx_helpers.d.ts +2 -4
  66. package/dist/helpers/tx_helpers.d.ts.map +1 -1
  67. package/dist/index.d.ts +3 -3
  68. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.d.ts +2 -4
  69. package/dist/proto-grpc/github.com/googleapis/googleapis/google/rpc/status.d.ts.map +1 -1
  70. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +310 -15
  71. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
  72. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs +19 -3
  73. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs.map +1 -1
  74. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts +29 -5
  75. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts.map +1 -1
  76. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js +19 -3
  77. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js.map +1 -1
  78. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +2336 -429
  79. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
  80. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +309 -16
  81. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
  82. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts +51 -30
  83. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts.map +1 -1
  84. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts +7 -9
  85. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts.map +1 -1
  86. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts +6 -8
  87. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts.map +1 -1
  88. package/dist/proto-grpc/google/protobuf/any.d.ts +2 -4
  89. package/dist/proto-grpc/google/protobuf/any.d.ts.map +1 -1
  90. package/dist/proto-grpc/google/protobuf/duration.d.ts +2 -4
  91. package/dist/proto-grpc/google/protobuf/duration.d.ts.map +1 -1
  92. package/dist/proto-grpc/google/protobuf/timestamp.d.ts +2 -4
  93. package/dist/proto-grpc/google/protobuf/timestamp.d.ts.map +1 -1
  94. package/dist/proto-grpc/google/rpc/code.d.ts +1 -2
  95. package/dist/proto-grpc/google/rpc/code.d.ts.map +1 -1
  96. package/dist/proto-rest/index.d.ts +6 -8
  97. package/dist/proto-rest/index.d.ts.map +1 -1
  98. package/dist/proto-rest/plapi.d.ts +248 -123
  99. package/dist/proto-rest/plapi.d.ts.map +1 -1
  100. package/dist/test/tcp-proxy.d.ts +3 -5
  101. package/dist/test/tcp-proxy.d.ts.map +1 -1
  102. package/dist/test/test_config.d.ts +13 -14
  103. package/dist/test/test_config.d.ts.map +1 -1
  104. package/package.json +6 -6
  105. package/src/core/client.ts +9 -0
  106. package/src/core/ll_client.ts +40 -13
  107. package/src/core/transaction.ts +2 -0
  108. package/src/core/unauth_client.test.ts +69 -1
  109. package/src/core/unauth_client.ts +108 -34
  110. package/src/core/unauth_client_branch.test.ts +416 -5
  111. package/src/core/user_resources.ts +39 -0
  112. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.ts +34 -3
  113. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +431 -15
  114. package/src/proto-rest/plapi.ts +8 -2
@@ -1 +1 @@
1
- {"version":3,"file":"user_resources.cjs","names":["isUnimplementedError","createSignedResourceId","toResourceSignature","ClientRoot","toGlobalResourceId","isNotNullSignedResourceId"],"sources":["../../src/core/user_resources.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { LLPlClient } from \"./ll_client\";\nimport type { PlTransaction } from \"./transaction\";\nimport { toGlobalResourceId } from \"./transaction\";\nimport type { OptionalSignedResourceId, SignedResourceId, ResourceType } from \"./types\";\nimport {\n createSignedResourceId,\n isNotNullSignedResourceId,\n NullSignedResourceId,\n toResourceSignature,\n} from \"./types\";\nimport { isUnimplementedError } from \"./errors\";\nimport { ClientRoot } from \"../helpers/pl\";\n\nconst AnonymousClientRoot = \"AnonymousRoot\";\nconst LsStorageTypePrefix = \"LS/\"; // implements ls API in particular storage\nconst LsProviderFieldPrefix = \"storage/\"; // provides access to storages list\n\n/** One recipient of a resource, as returned by {@link UserResources.listGrants}. */\nexport interface GrantEntry {\n /** Login the grant targets. An everyone-grant surfaces here as the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\"); callers\n * map it to \"*\". */\n readonly user: string;\n /** True for a writable grant (copy / collaboration), false for read-only. */\n readonly writable: boolean;\n /** Login of the user who created the grant. */\n readonly grantedBy: string;\n /** When the grant was created (ms epoch). */\n readonly grantedAt: number;\n}\n\n/** One user known to the server, as returned by {@link UserResources.listUsers}. */\nexport interface UserEntry {\n /** Stable identifier of the user; the grant target and `GetUserRoot` key. */\n readonly login: string;\n}\n\n/** Information about a single data library (LS storage). */\nexport interface StorageInfo {\n /** Machine-stable identifier, e.g. \"library\". Used for filtering and map keys. */\n readonly storageId: string;\n /** Human-readable display name. For V1/legacy equals storageId; for V2 from resource JSON data. */\n readonly storageName: string;\n /** Signed resource ID for this storage resource. */\n readonly resourceId: SignedResourceId;\n /** Full resource type including correct version (\"1\" or \"2\"). */\n readonly resourceType: ResourceType;\n}\n\n/** V2 LsStorage resource JSON data shape (contract with backend). */\ninterface LsStorageV2Data {\n storageName: string;\n storageID: string;\n}\n\n/**\n * Callback type for running transactions. Matches PlClient._withTx signature\n * so the index can run transactions before PlClient is fully initialized.\n */\nexport type TxRunner = <T>(\n name: string,\n writable: boolean,\n clientRoot: OptionalSignedResourceId,\n body: (tx: PlTransaction) => Promise<T>,\n) => Promise<T>;\n\ntype BackendCapability = \"getUserRoot\" | \"listUserResources\" | \"legacy\";\n\n/**\n * Abstracts user resource discovery with backward compatibility.\n *\n * Detects backend capability on the first getUserRoot() call and remembers\n * the result. Three-tier fallback:\n * 1. getUserRoot RPC (newest, supports createIfNotExists)\n * 2. listUserResources RPC (streams all resources, picks userRoot)\n * 3. Named resource lookup/creation via transaction (legacy)\n */\nexport class UserResources {\n private backendCapability: BackendCapability | undefined;\n\n constructor(\n private readonly ll: LLPlClient,\n private readonly runTx: TxRunner,\n public readonly authUser: string | null,\n ) {}\n\n /**\n * Returns the user's root resource ID.\n *\n * On first call, detects backend capability by trying methods in order:\n * 1. getUserRoot RPC (newest)\n * 2. listUserResources RPC\n * 3. Named resource lookup/creation via transaction (legacy)\n */\n async getUserRoot(opts: { login?: string; createIfNotExists: true }): Promise<SignedResourceId>;\n async getUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n async getUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n if (this.backendCapability === undefined) {\n return await this.detectAndGetUserRoot(opts);\n }\n return await this.getUserRootWith(this.backendCapability, opts);\n }\n\n private async detectAndGetUserRoot(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async detectAndGetUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async detectAndGetUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n // 1. Try getUserRoot RPC\n try {\n const root = await this.getUserRootViaRpc(opts);\n this.backendCapability = \"getUserRoot\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 2. Try listUserResources\n try {\n const root = await this.getUserRootViaList(opts);\n this.backendCapability = \"listUserResources\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 3. Legacy fallback\n this.backendCapability = \"legacy\";\n return await this.getUserRootViaLegacy(opts);\n }\n\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists: true },\n ): Promise<SignedResourceId>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts?: { login?: string; createIfNotExists?: boolean },\n ): Promise<SignedResourceId | undefined>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n switch (capability) {\n case \"getUserRoot\":\n return await this.getUserRootViaRpc(opts);\n case \"listUserResources\":\n return await this.getUserRootViaList(opts);\n case \"legacy\":\n return await this.getUserRootViaLegacy(opts);\n }\n }\n\n /**\n * Returns all data libraries the user has access to.\n * Always fetches fresh from the server (no caching).\n */\n async getDataLibraries(\n opts: { login?: string; createUserRootIfNotExists?: boolean } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n if (this.backendCapability === undefined) {\n // First call — detect backend capability\n try {\n const libs = await this.getDataLibrariesViaList(opts);\n // getUserRoot RPC doesn't return libraries, but listUserResources does;\n // record at least \"listUserResources\" so future getUserRoot calls don't re-detect.\n this.backendCapability = \"listUserResources\";\n return libs;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n this.backendCapability = \"legacy\";\n return await this.getDataLibrariesViaLegacy();\n }\n }\n\n // A server that supports getUserRoot definitely supports listUserResources.\n if (this.backendCapability !== \"legacy\") {\n return await this.getDataLibrariesViaList(opts);\n }\n return await this.getDataLibrariesViaLegacy();\n }\n\n /**\n * Discovers shared resources of a given type granted to the user, as signed resource ids.\n *\n * The public, type-filtered form of {@link getDataLibrariesViaList}: it polls the\n * `ListUserResources` gRPC stream and returns every `sharedResource` entry whose\n * `resourceType.name` matches `resourceTypeName`. Matching is by name only — the\n * version is ignored (permissive, survives schema bumps).\n *\n * gRPC-only: `ListUserResources` throws on a REST-connected client\n * ({@link LLPlClient.listUserResources}), so callers on REST get a thrown error.\n */\n async listSharedResourcesByType(\n resourceTypeName: string,\n opts: { login?: string } = {},\n ): Promise<SignedResourceId[]> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n const result: SignedResourceId[] = [];\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n if (!sr.resourceType) continue;\n if (sr.resourceType.name !== resourceTypeName) continue;\n result.push(createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature)));\n }\n return result;\n }\n\n /**\n * Enumerates the recipients of a single resource — the donor-side \"who did I\n * share with\" view.\n *\n * Takes a signed, writable resource handle: the backend gates grant listing on a\n * signed resource id with writable permission, so only the resource's owner can\n * call it. An everyone-grant surfaces with `user` matching the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\");\n * the caller maps that to \"*\".\n *\n * Runs over a read transaction ({@link PlTransaction.listGrants}), so it works on\n * every wire protocol — including REST, where the standalone server-streaming\n * `ListGrants` RPC has no binding.\n */\n async listGrants(resourceId: SignedResourceId): Promise<GrantEntry[]> {\n const grants = await this.runTx(\"ListGrants\", false, NullSignedResourceId, (tx) =>\n tx.listGrants(resourceId),\n );\n return grants.map((grant) => ({\n user: grant.user,\n writable: grant.permissions?.writable ?? false,\n grantedBy: grant.grantedBy,\n grantedAt: Number(grant.grantedAt),\n }));\n }\n\n /**\n * Lists the logins of users known to the server, for the recipient picker. A user becomes\n * known on first login; provisioned users who have never logged in do not appear. gRPC-only\n * (the underlying {@link LLPlClient.listUsers} has no REST binding) — throws on a\n * REST-connected client, so callers gate on the `userListing:v1` capability.\n */\n async listUsers(): Promise<UserEntry[]> {\n const users = await this.ll.listUsers();\n return users.map((user) => ({ login: user.login }));\n }\n\n private async getUserRootViaRpc(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaRpc(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaRpc(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const resp = await this.ll.getUserRoot({\n login: opts.login,\n createIfNotExists: opts.createIfNotExists,\n });\n if (resp.userRoot === undefined) {\n if (!opts.createIfNotExists) return undefined;\n throw new Error(\"getUserRoot returned no userRoot entry\");\n }\n return createSignedResourceId(\n resp.userRoot.resourceId,\n toResourceSignature(resp.userRoot.resourceSignature),\n );\n }\n\n private async getUserRootViaList(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaList(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaList(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const responses = await this.ll.listUserResources({ login: opts.login, limit: 1 });\n for (const msg of responses) {\n if (msg.entry.oneofKind === \"userRoot\") {\n return createSignedResourceId(\n msg.entry.userRoot.resourceId,\n toResourceSignature(msg.entry.userRoot.resourceSignature),\n );\n }\n }\n\n if (opts.createIfNotExists) {\n throw new Error(\"listUserResources returned no userRoot entry\");\n }\n\n return undefined;\n }\n\n private async getDataLibrariesViaList(\n opts: { login?: string } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n // Collect all LS/* shared resources, separating V1 and V2\n const v1Entries: StorageInfo[] = [];\n const v2ResourceIds: { resourceId: SignedResourceId; resourceType: ResourceType }[] = [];\n\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n\n if (!sr.resourceType) continue;\n const typeName = sr.resourceType.name;\n const typeVersion = sr.resourceType.version;\n if (!typeName.startsWith(LsStorageTypePrefix)) continue;\n\n const rId = createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature));\n const rType: ResourceType = { name: typeName, version: typeVersion };\n\n if (typeVersion === \"2\") {\n v2ResourceIds.push({ resourceId: rId, resourceType: rType });\n } else {\n // V1 or unknown version: derive storageId from type name\n const storageId = typeName.substring(LsStorageTypePrefix.length);\n v1Entries.push({\n storageId,\n storageName: storageId,\n resourceId: rId,\n resourceType: rType,\n });\n }\n }\n\n // Read V2 resource data in a single transaction\n let v2Entries: StorageInfo[] = [];\n if (v2ResourceIds.length > 0) {\n v2Entries = await this.runTx(\n \"ReadLsStorageV2Data\",\n false,\n NullSignedResourceId,\n async (tx) => {\n const entries: StorageInfo[] = [];\n for (const { resourceId, resourceType } of v2ResourceIds) {\n const rd = await tx.getResourceData(resourceId, false);\n if (rd.data) {\n const v2Data = JSON.parse(Buffer.from(rd.data).toString(\"utf-8\")) as LsStorageV2Data;\n entries.push({\n storageId: v2Data.storageID,\n storageName: v2Data.storageName,\n resourceId,\n resourceType,\n });\n }\n }\n return entries;\n },\n );\n }\n\n const result = new Map<string, StorageInfo>();\n for (const entry of [...v1Entries, ...v2Entries]) {\n result.set(entry.storageId, entry);\n }\n return result;\n }\n\n private async getUserRootViaLegacy(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaLegacy(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaLegacy(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const login = opts.login ?? this.authUser;\n const mainRootName =\n login === null ? AnonymousClientRoot : createHash(\"sha256\").update(login).digest(\"hex\");\n\n return await this.runTx(\"initialization\", true, NullSignedResourceId, async (tx) => {\n if (await tx.checkResourceNameExists(mainRootName)) {\n return await tx.getResourceByName(mainRootName);\n }\n\n if (!opts.createIfNotExists) {\n return undefined;\n }\n\n const mainRoot = tx.createRoot(ClientRoot);\n tx.setResourceName(mainRootName, mainRoot);\n await tx.commit();\n return await toGlobalResourceId(mainRoot);\n });\n }\n\n private async getDataLibrariesViaLegacy(): Promise<ReadonlyMap<string, StorageInfo>> {\n return await this.runTx(\"GetAvailableStorageIds\", false, NullSignedResourceId, async (tx) => {\n const lsProviderId = await tx.getResourceByName(\"LSProvider\");\n const provider = await tx.getResourceData(lsProviderId, true);\n\n const result = new Map<string, StorageInfo>();\n for (const field of provider.fields) {\n if (field.type !== \"Dynamic\" || !isNotNullSignedResourceId(field.value)) continue;\n if (!field.name.startsWith(LsProviderFieldPrefix)) continue;\n\n const storageId = field.name.substring(LsProviderFieldPrefix.length);\n result.set(storageId, {\n storageId,\n storageName: storageId,\n resourceId: field.value,\n resourceType: { name: `${LsStorageTypePrefix}${storageId}`, version: \"1\" },\n });\n }\n return result;\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"user_resources.cjs","names":["isUnimplementedError","createSignedResourceId","toResourceSignature","ClientRoot","toGlobalResourceId","isNotNullSignedResourceId"],"sources":["../../src/core/user_resources.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { LLPlClient } from \"./ll_client\";\nimport type { PlTransaction } from \"./transaction\";\nimport { toGlobalResourceId } from \"./transaction\";\nimport type { OptionalSignedResourceId, SignedResourceId, ResourceType } from \"./types\";\nimport {\n createSignedResourceId,\n isNotNullSignedResourceId,\n NullSignedResourceId,\n toResourceSignature,\n} from \"./types\";\nimport { isUnimplementedError } from \"./errors\";\nimport { ClientRoot } from \"../helpers/pl\";\n\nconst AnonymousClientRoot = \"AnonymousRoot\";\nconst LsStorageTypePrefix = \"LS/\"; // implements ls API in particular storage\nconst LsProviderFieldPrefix = \"storage/\"; // provides access to storages list\n\n/** One recipient of a resource, as returned by {@link UserResources.listGrants}. */\nexport interface GrantEntry {\n /** Login the grant targets. An everyone-grant surfaces here as the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\"); callers\n * map it to \"*\". */\n readonly user: string;\n /** True for a writable grant (copy / collaboration), false for read-only. */\n readonly writable: boolean;\n /** Login of the user who created the grant. */\n readonly grantedBy: string;\n /** When the grant was created (ms epoch). */\n readonly grantedAt: number;\n}\n\n/** One user known to the server, as returned by {@link UserResources.listUsers}. */\nexport interface UserEntry {\n /** Stable identifier of the user; the grant target and `GetUserRoot` key. */\n readonly login: string;\n}\n\n/** What {@link UserResources.deleteUser} removed, so a caller can report it. */\nexport interface UserDeletionReport {\n /** Raw id of the root resource the user owned, or undefined when they had none. Unsigned —\n * the resource is gone, so this is for the audit line, not for further calls. */\n readonly userRootId: bigint | undefined;\n /** Whether that root resource was deleted. */\n readonly userRootDeleted: boolean;\n /** Grants revoked, the user-root self-grant included. */\n readonly revokedGrants: number;\n /** Identity-index entries removed — one per value that resolved to the account: its login,\n * its email, and any alternative of either. */\n readonly removedIdentityIndexEntries: number;\n}\n\n/** Information about a single data library (LS storage). */\nexport interface StorageInfo {\n /** Machine-stable identifier, e.g. \"library\". Used for filtering and map keys. */\n readonly storageId: string;\n /** Human-readable display name. For V1/legacy equals storageId; for V2 from resource JSON data. */\n readonly storageName: string;\n /** Signed resource ID for this storage resource. */\n readonly resourceId: SignedResourceId;\n /** Full resource type including correct version (\"1\" or \"2\"). */\n readonly resourceType: ResourceType;\n}\n\n/** V2 LsStorage resource JSON data shape (contract with backend). */\ninterface LsStorageV2Data {\n storageName: string;\n storageID: string;\n}\n\n/**\n * Callback type for running transactions. Matches PlClient._withTx signature\n * so the index can run transactions before PlClient is fully initialized.\n */\nexport type TxRunner = <T>(\n name: string,\n writable: boolean,\n clientRoot: OptionalSignedResourceId,\n body: (tx: PlTransaction) => Promise<T>,\n) => Promise<T>;\n\ntype BackendCapability = \"getUserRoot\" | \"listUserResources\" | \"legacy\";\n\n/**\n * Abstracts user resource discovery with backward compatibility.\n *\n * Detects backend capability on the first getUserRoot() call and remembers\n * the result. Three-tier fallback:\n * 1. getUserRoot RPC (newest, supports createIfNotExists)\n * 2. listUserResources RPC (streams all resources, picks userRoot)\n * 3. Named resource lookup/creation via transaction (legacy)\n */\nexport class UserResources {\n private backendCapability: BackendCapability | undefined;\n\n constructor(\n private readonly ll: LLPlClient,\n private readonly runTx: TxRunner,\n public readonly authUser: string | null,\n ) {}\n\n /**\n * Returns the user's root resource ID.\n *\n * On first call, detects backend capability by trying methods in order:\n * 1. getUserRoot RPC (newest)\n * 2. listUserResources RPC\n * 3. Named resource lookup/creation via transaction (legacy)\n */\n async getUserRoot(opts: { login?: string; createIfNotExists: true }): Promise<SignedResourceId>;\n async getUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n async getUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n if (this.backendCapability === undefined) {\n return await this.detectAndGetUserRoot(opts);\n }\n return await this.getUserRootWith(this.backendCapability, opts);\n }\n\n private async detectAndGetUserRoot(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async detectAndGetUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async detectAndGetUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n // 1. Try getUserRoot RPC\n try {\n const root = await this.getUserRootViaRpc(opts);\n this.backendCapability = \"getUserRoot\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 2. Try listUserResources\n try {\n const root = await this.getUserRootViaList(opts);\n this.backendCapability = \"listUserResources\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 3. Legacy fallback\n this.backendCapability = \"legacy\";\n return await this.getUserRootViaLegacy(opts);\n }\n\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists: true },\n ): Promise<SignedResourceId>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts?: { login?: string; createIfNotExists?: boolean },\n ): Promise<SignedResourceId | undefined>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n switch (capability) {\n case \"getUserRoot\":\n return await this.getUserRootViaRpc(opts);\n case \"listUserResources\":\n return await this.getUserRootViaList(opts);\n case \"legacy\":\n return await this.getUserRootViaLegacy(opts);\n }\n }\n\n /**\n * Returns all data libraries the user has access to.\n * Always fetches fresh from the server (no caching).\n */\n async getDataLibraries(\n opts: { login?: string; createUserRootIfNotExists?: boolean } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n if (this.backendCapability === undefined) {\n // First call — detect backend capability\n try {\n const libs = await this.getDataLibrariesViaList(opts);\n // getUserRoot RPC doesn't return libraries, but listUserResources does;\n // record at least \"listUserResources\" so future getUserRoot calls don't re-detect.\n this.backendCapability = \"listUserResources\";\n return libs;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n this.backendCapability = \"legacy\";\n return await this.getDataLibrariesViaLegacy();\n }\n }\n\n // A server that supports getUserRoot definitely supports listUserResources.\n if (this.backendCapability !== \"legacy\") {\n return await this.getDataLibrariesViaList(opts);\n }\n return await this.getDataLibrariesViaLegacy();\n }\n\n /**\n * Discovers shared resources of a given type granted to the user, as signed resource ids.\n *\n * The public, type-filtered form of {@link getDataLibrariesViaList}: it polls the\n * `ListUserResources` gRPC stream and returns every `sharedResource` entry whose\n * `resourceType.name` matches `resourceTypeName`. Matching is by name only — the\n * version is ignored (permissive, survives schema bumps).\n *\n * gRPC-only: `ListUserResources` throws on a REST-connected client\n * ({@link LLPlClient.listUserResources}), so callers on REST get a thrown error.\n */\n async listSharedResourcesByType(\n resourceTypeName: string,\n opts: { login?: string } = {},\n ): Promise<SignedResourceId[]> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n const result: SignedResourceId[] = [];\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n if (!sr.resourceType) continue;\n if (sr.resourceType.name !== resourceTypeName) continue;\n result.push(createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature)));\n }\n return result;\n }\n\n /**\n * Enumerates the recipients of a single resource — the donor-side \"who did I\n * share with\" view.\n *\n * Takes a signed, writable resource handle: the backend gates grant listing on a\n * signed resource id with writable permission, so only the resource's owner can\n * call it. An everyone-grant surfaces with `user` matching the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\");\n * the caller maps that to \"*\".\n *\n * Runs over a read transaction ({@link PlTransaction.listGrants}), so it works on\n * every wire protocol — including REST, where the standalone server-streaming\n * `ListGrants` RPC has no binding.\n */\n async listGrants(resourceId: SignedResourceId): Promise<GrantEntry[]> {\n const grants = await this.runTx(\"ListGrants\", false, NullSignedResourceId, (tx) =>\n tx.listGrants(resourceId),\n );\n return grants.map((grant) => ({\n user: grant.user,\n writable: grant.permissions?.writable ?? false,\n grantedBy: grant.grantedBy,\n grantedAt: Number(grant.grantedAt),\n }));\n }\n\n /**\n * Lists the logins of users known to the server, for the recipient picker. A user becomes\n * known on first login; provisioned users who have never logged in do not appear. gRPC-only\n * (the underlying {@link LLPlClient.listUsers} has no REST binding) — throws on a\n * REST-connected client, so callers gate on the `userListing:v1` capability.\n */\n async listUsers(): Promise<UserEntry[]> {\n const users = await this.ll.listUsers();\n return users.map((user) => ({ login: user.login }));\n }\n\n /**\n * Deletes a user account: the record, every identity-index entry that resolves to it (its login,\n * its email, and any alternative of either), every grant it holds, and its root resource — and\n * with the root, everything still attached under it.\n *\n * Exists for the duplicate account one person can end up with — an identity that could not be\n * matched across a provider cutover, or one minted before the backend started refusing two\n * records for one identity. The spare record shows up wherever users are listed and its projects\n * keep taking part in deduplication.\n *\n * Destructive and irreversible. Re-attach anything worth keeping to another user's root before\n * calling — `pl-cli admin delete-user` does both steps in order. Requires admin/controller\n * credentials; gRPC-only, like {@link listUsers}.\n */\n async deleteUser(login: string): Promise<UserDeletionReport> {\n const resp = await this.ll.deleteUser(login);\n\n return {\n userRootId: resp.userRootId === 0n ? undefined : resp.userRootId,\n userRootDeleted: resp.userRootDeleted,\n revokedGrants: resp.revokedGrants,\n removedIdentityIndexEntries: resp.removedIdentityIndexEntries,\n };\n }\n\n private async getUserRootViaRpc(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaRpc(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaRpc(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const resp = await this.ll.getUserRoot({\n login: opts.login,\n createIfNotExists: opts.createIfNotExists,\n });\n if (resp.userRoot === undefined) {\n if (!opts.createIfNotExists) return undefined;\n throw new Error(\"getUserRoot returned no userRoot entry\");\n }\n return createSignedResourceId(\n resp.userRoot.resourceId,\n toResourceSignature(resp.userRoot.resourceSignature),\n );\n }\n\n private async getUserRootViaList(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaList(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaList(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const responses = await this.ll.listUserResources({ login: opts.login, limit: 1 });\n for (const msg of responses) {\n if (msg.entry.oneofKind === \"userRoot\") {\n return createSignedResourceId(\n msg.entry.userRoot.resourceId,\n toResourceSignature(msg.entry.userRoot.resourceSignature),\n );\n }\n }\n\n if (opts.createIfNotExists) {\n throw new Error(\"listUserResources returned no userRoot entry\");\n }\n\n return undefined;\n }\n\n private async getDataLibrariesViaList(\n opts: { login?: string } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n // Collect all LS/* shared resources, separating V1 and V2\n const v1Entries: StorageInfo[] = [];\n const v2ResourceIds: { resourceId: SignedResourceId; resourceType: ResourceType }[] = [];\n\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n\n if (!sr.resourceType) continue;\n const typeName = sr.resourceType.name;\n const typeVersion = sr.resourceType.version;\n if (!typeName.startsWith(LsStorageTypePrefix)) continue;\n\n const rId = createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature));\n const rType: ResourceType = { name: typeName, version: typeVersion };\n\n if (typeVersion === \"2\") {\n v2ResourceIds.push({ resourceId: rId, resourceType: rType });\n } else {\n // V1 or unknown version: derive storageId from type name\n const storageId = typeName.substring(LsStorageTypePrefix.length);\n v1Entries.push({\n storageId,\n storageName: storageId,\n resourceId: rId,\n resourceType: rType,\n });\n }\n }\n\n // Read V2 resource data in a single transaction\n let v2Entries: StorageInfo[] = [];\n if (v2ResourceIds.length > 0) {\n v2Entries = await this.runTx(\n \"ReadLsStorageV2Data\",\n false,\n NullSignedResourceId,\n async (tx) => {\n const entries: StorageInfo[] = [];\n for (const { resourceId, resourceType } of v2ResourceIds) {\n const rd = await tx.getResourceData(resourceId, false);\n if (rd.data) {\n const v2Data = JSON.parse(Buffer.from(rd.data).toString(\"utf-8\")) as LsStorageV2Data;\n entries.push({\n storageId: v2Data.storageID,\n storageName: v2Data.storageName,\n resourceId,\n resourceType,\n });\n }\n }\n return entries;\n },\n );\n }\n\n const result = new Map<string, StorageInfo>();\n for (const entry of [...v1Entries, ...v2Entries]) {\n result.set(entry.storageId, entry);\n }\n return result;\n }\n\n private async getUserRootViaLegacy(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaLegacy(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaLegacy(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const login = opts.login ?? this.authUser;\n const mainRootName =\n login === null ? AnonymousClientRoot : createHash(\"sha256\").update(login).digest(\"hex\");\n\n return await this.runTx(\"initialization\", true, NullSignedResourceId, async (tx) => {\n if (await tx.checkResourceNameExists(mainRootName)) {\n return await tx.getResourceByName(mainRootName);\n }\n\n if (!opts.createIfNotExists) {\n return undefined;\n }\n\n const mainRoot = tx.createRoot(ClientRoot);\n tx.setResourceName(mainRootName, mainRoot);\n await tx.commit();\n return await toGlobalResourceId(mainRoot);\n });\n }\n\n private async getDataLibrariesViaLegacy(): Promise<ReadonlyMap<string, StorageInfo>> {\n return await this.runTx(\"GetAvailableStorageIds\", false, NullSignedResourceId, async (tx) => {\n const lsProviderId = await tx.getResourceByName(\"LSProvider\");\n const provider = await tx.getResourceData(lsProviderId, true);\n\n const result = new Map<string, StorageInfo>();\n for (const field of provider.fields) {\n if (field.type !== \"Dynamic\" || !isNotNullSignedResourceId(field.value)) continue;\n if (!field.name.startsWith(LsProviderFieldPrefix)) continue;\n\n const storageId = field.name.substring(LsProviderFieldPrefix.length);\n result.set(storageId, {\n storageId,\n storageName: storageId,\n resourceId: field.value,\n resourceType: { name: `${LsStorageTypePrefix}${storageId}`, version: \"1\" },\n });\n }\n return result;\n });\n }\n}\n"],"mappings":"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"}
@@ -1,10 +1,9 @@
1
1
  import { OptionalSignedResourceId, ResourceType, SignedResourceId } from "./types.js";
2
2
  import { PlTransaction } from "./transaction.js";
3
3
  import { LLPlClient } from "./ll_client.js";
4
-
5
4
  //#region src/core/user_resources.d.ts
6
5
  /** One recipient of a resource, as returned by {@link UserResources.listGrants}. */
7
- interface GrantEntry {
6
+ export interface GrantEntry {
8
7
  /** Login the grant targets. An everyone-grant surfaces here as the backend's
9
8
  * everyone-sentinel — test with {@link isEveryoneUserLogin} (from "./transaction"); callers
10
9
  * map it to "*". */
@@ -17,12 +16,25 @@ interface GrantEntry {
17
16
  readonly grantedAt: number;
18
17
  }
19
18
  /** One user known to the server, as returned by {@link UserResources.listUsers}. */
20
- interface UserEntry {
19
+ export interface UserEntry {
21
20
  /** Stable identifier of the user; the grant target and `GetUserRoot` key. */
22
21
  readonly login: string;
23
22
  }
23
+ /** What {@link UserResources.deleteUser} removed, so a caller can report it. */
24
+ export interface UserDeletionReport {
25
+ /** Raw id of the root resource the user owned, or undefined when they had none. Unsigned —
26
+ * the resource is gone, so this is for the audit line, not for further calls. */
27
+ readonly userRootId: bigint | undefined;
28
+ /** Whether that root resource was deleted. */
29
+ readonly userRootDeleted: boolean;
30
+ /** Grants revoked, the user-root self-grant included. */
31
+ readonly revokedGrants: number;
32
+ /** Identity-index entries removed — one per value that resolved to the account: its login,
33
+ * its email, and any alternative of either. */
34
+ readonly removedIdentityIndexEntries: number;
35
+ }
24
36
  /** Information about a single data library (LS storage). */
25
- interface StorageInfo {
37
+ export interface StorageInfo {
26
38
  /** Machine-stable identifier, e.g. "library". Used for filtering and map keys. */
27
39
  readonly storageId: string;
28
40
  /** Human-readable display name. For V1/legacy equals storageId; for V2 from resource JSON data. */
@@ -36,7 +48,7 @@ interface StorageInfo {
36
48
  * Callback type for running transactions. Matches PlClient._withTx signature
37
49
  * so the index can run transactions before PlClient is fully initialized.
38
50
  */
39
- type TxRunner = <T>(name: string, writable: boolean, clientRoot: OptionalSignedResourceId, body: (tx: PlTransaction) => Promise<T>) => Promise<T>;
51
+ export type TxRunner = <T>(name: string, writable: boolean, clientRoot: OptionalSignedResourceId, body: (tx: PlTransaction) => Promise<T>) => Promise<T>;
40
52
  /**
41
53
  * Abstracts user resource discovery with backward compatibility.
42
54
  *
@@ -46,7 +58,7 @@ type TxRunner = <T>(name: string, writable: boolean, clientRoot: OptionalSignedR
46
58
  * 2. listUserResources RPC (streams all resources, picks userRoot)
47
59
  * 3. Named resource lookup/creation via transaction (legacy)
48
60
  */
49
- declare class UserResources {
61
+ export declare class UserResources {
50
62
  private readonly ll;
51
63
  private readonly runTx;
52
64
  readonly authUser: string | null;
@@ -114,6 +126,21 @@ declare class UserResources {
114
126
  * REST-connected client, so callers gate on the `userListing:v1` capability.
115
127
  */
116
128
  listUsers(): Promise<UserEntry[]>;
129
+ /**
130
+ * Deletes a user account: the record, every identity-index entry that resolves to it (its login,
131
+ * its email, and any alternative of either), every grant it holds, and its root resource — and
132
+ * with the root, everything still attached under it.
133
+ *
134
+ * Exists for the duplicate account one person can end up with — an identity that could not be
135
+ * matched across a provider cutover, or one minted before the backend started refusing two
136
+ * records for one identity. The spare record shows up wherever users are listed and its projects
137
+ * keep taking part in deduplication.
138
+ *
139
+ * Destructive and irreversible. Re-attach anything worth keeping to another user's root before
140
+ * calling — `pl-cli admin delete-user` does both steps in order. Requires admin/controller
141
+ * credentials; gRPC-only, like {@link listUsers}.
142
+ */
143
+ deleteUser(login: string): Promise<UserDeletionReport>;
117
144
  private getUserRootViaRpc;
118
145
  private getUserRootViaList;
119
146
  private getDataLibrariesViaList;
@@ -121,5 +148,4 @@ declare class UserResources {
121
148
  private getDataLibrariesViaLegacy;
122
149
  }
123
150
  //#endregion
124
- export { GrantEntry, StorageInfo, TxRunner, UserEntry, UserResources };
125
151
  //# sourceMappingURL=user_resources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user_resources.d.ts","names":[],"sources":["../../src/core/user_resources.ts"],"mappings":";;;;;;UAmBiB,UAAA;EAAA;;;EAAA,SAIN,IAAA;EAAA;EAAA,SAEA,QAAA;EAEA;EAAA,SAAA,SAAA;EAES;EAAA,SAAT,SAAA;AAAA;;UAIM,SAAA;EAED;EAAA,SAAL,KAAK;AAAA;;UAIC,WAAA;EAQoB;EAAA,SAN1B,SAAA;EAEA;EAAA,SAAA,WAAA;EAEY;EAAA,SAAZ,UAAA,EAAY,gBAAA;EAEE;EAAA,SAAd,YAAA,EAAc,YAAY;AAAA;AAarC;;;;AAAA,KAAY,QAAA,OACV,IAAA,UACA,QAAA,WACA,UAAA,EAAY,wBAAA,EACZ,IAAA,GAAO,EAAA,EAAI,aAAA,KAAkB,OAAA,CAAQ,CAAA,MAClC,OAAA,CAAQ,CAAA;;;;;;;;;;cAaA,aAAA;EAAA,iBAIQ,EAAA;EAAA,iBACA,KAAA;EAAA,SACD,QAAA;EAAA,QALV,iBAAA;cAGW,EAAA,EAAI,UAAA,EACJ,KAAA,EAAO,QAAA,EACR,QAAA;EApBlB;;;;AACY;AAad;;;EAiBQ,WAAA,CAAY,IAAA;IAAQ,KAAA;IAAgB,iBAAA;EAAA,IAA4B,OAAA,CAAQ,gBAAA;EACxE,WAAA,CAAY,IAAA;IAChB,KAAA;IACA,iBAAA;EAAA,IACE,OAAA,CAAQ,gBAAA;EAAA,QAUE,oBAAA;EAAA,QAkCA,eAAA;EAiEX;;;;EAvCG,gBAAA,CACJ,IAAA;IAAQ,KAAA;IAAgB,yBAAA;EAAA,IACvB,OAAA,CAAQ,WAAA,SAAoB,WAAA;EAzFZ;;;;;;;;;;;EA2Hb,yBAAA,CACJ,gBAAA,UACA,IAAA;IAAQ,KAAA;EAAA,IACP,OAAA,CAAQ,gBAAA;EAjH2D;;;;;;;;;;;;;;EA6IhE,UAAA,CAAW,UAAA,EAAY,gBAAA,GAAmB,OAAA,CAAQ,UAAA;EAjE7C;;;;;;EAmFL,SAAA,IAAa,OAAA,CAAQ,SAAA;EAAA,QAKb,iBAAA;EAAA,QAyBA,kBAAA;EAAA,QA4BA,uBAAA;EAAA,QAoEA,oBAAA;EAAA,QA+BA,yBAAA;AAAA"}
1
+ {"version":3,"file":"user_resources.d.ts","names":[],"sources":["../../src/core/user_resources.ts"],"mappings":";;;;;iBAmBiB;;;;WAIN;;WAEA;;WAEA;;WAEA;;;iBAIM;;WAEN;;;iBAIM;;;WAGN;;WAEA;;WAEA;;;WAGA;;;iBAIM;;WAEN;;WAEA;;WAEA,YAAY;;WAEZ,cAAc;;;;;;YAab,YAAY,GACtB,cACA,mBACA,YAAY,0BACZ,OAAO,IAAI,kBAAkB,QAAQ,OAClC,QAAQ;;;;;;;;;;qBAaA;mBAIQ;mBACA;WACD;UALV;EAER,YACmB,IAAI,YACJ,OAAO,UACR;;;;;;;;;EAWZ,YAAY;IAAQ;IAAgB;MAA4B,QAAQ;EACxE,YAAY;IAChB;IACA;MACE,QAAQ;UAUE;UAkCA;;;;;EA0BR,iBACJ;IAAQ;IAAgB;MACvB,QAAQ,oBAAoB;;;;;;;;;;;;EAkCzB,0BACJ,0BACA;IAAQ;MACP,QAAQ;;;;;;;;;;;;;;;EA4BL,WAAW,YAAY,mBAAmB,QAAQ;;;;;;;EAkBlD,aAAa,QAAQ;;;;;;;;;;;;;;;EAmBrB,WAAW,gBAAgB,QAAQ;UAW3B;UAyBA;UA4BA;UAoEA;UA+BA"}
@@ -126,6 +126,29 @@ var UserResources = class {
126
126
  async listUsers() {
127
127
  return (await this.ll.listUsers()).map((user) => ({ login: user.login }));
128
128
  }
129
+ /**
130
+ * Deletes a user account: the record, every identity-index entry that resolves to it (its login,
131
+ * its email, and any alternative of either), every grant it holds, and its root resource — and
132
+ * with the root, everything still attached under it.
133
+ *
134
+ * Exists for the duplicate account one person can end up with — an identity that could not be
135
+ * matched across a provider cutover, or one minted before the backend started refusing two
136
+ * records for one identity. The spare record shows up wherever users are listed and its projects
137
+ * keep taking part in deduplication.
138
+ *
139
+ * Destructive and irreversible. Re-attach anything worth keeping to another user's root before
140
+ * calling — `pl-cli admin delete-user` does both steps in order. Requires admin/controller
141
+ * credentials; gRPC-only, like {@link listUsers}.
142
+ */
143
+ async deleteUser(login) {
144
+ const resp = await this.ll.deleteUser(login);
145
+ return {
146
+ userRootId: resp.userRootId === 0n ? void 0 : resp.userRootId,
147
+ userRootDeleted: resp.userRootDeleted,
148
+ revokedGrants: resp.revokedGrants,
149
+ removedIdentityIndexEntries: resp.removedIdentityIndexEntries
150
+ };
151
+ }
129
152
  async getUserRootViaRpc(opts = {}) {
130
153
  const resp = await this.ll.getUserRoot({
131
154
  login: opts.login,
@@ -1 +1 @@
1
- {"version":3,"file":"user_resources.js","names":[],"sources":["../../src/core/user_resources.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { LLPlClient } from \"./ll_client\";\nimport type { PlTransaction } from \"./transaction\";\nimport { toGlobalResourceId } from \"./transaction\";\nimport type { OptionalSignedResourceId, SignedResourceId, ResourceType } from \"./types\";\nimport {\n createSignedResourceId,\n isNotNullSignedResourceId,\n NullSignedResourceId,\n toResourceSignature,\n} from \"./types\";\nimport { isUnimplementedError } from \"./errors\";\nimport { ClientRoot } from \"../helpers/pl\";\n\nconst AnonymousClientRoot = \"AnonymousRoot\";\nconst LsStorageTypePrefix = \"LS/\"; // implements ls API in particular storage\nconst LsProviderFieldPrefix = \"storage/\"; // provides access to storages list\n\n/** One recipient of a resource, as returned by {@link UserResources.listGrants}. */\nexport interface GrantEntry {\n /** Login the grant targets. An everyone-grant surfaces here as the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\"); callers\n * map it to \"*\". */\n readonly user: string;\n /** True for a writable grant (copy / collaboration), false for read-only. */\n readonly writable: boolean;\n /** Login of the user who created the grant. */\n readonly grantedBy: string;\n /** When the grant was created (ms epoch). */\n readonly grantedAt: number;\n}\n\n/** One user known to the server, as returned by {@link UserResources.listUsers}. */\nexport interface UserEntry {\n /** Stable identifier of the user; the grant target and `GetUserRoot` key. */\n readonly login: string;\n}\n\n/** Information about a single data library (LS storage). */\nexport interface StorageInfo {\n /** Machine-stable identifier, e.g. \"library\". Used for filtering and map keys. */\n readonly storageId: string;\n /** Human-readable display name. For V1/legacy equals storageId; for V2 from resource JSON data. */\n readonly storageName: string;\n /** Signed resource ID for this storage resource. */\n readonly resourceId: SignedResourceId;\n /** Full resource type including correct version (\"1\" or \"2\"). */\n readonly resourceType: ResourceType;\n}\n\n/** V2 LsStorage resource JSON data shape (contract with backend). */\ninterface LsStorageV2Data {\n storageName: string;\n storageID: string;\n}\n\n/**\n * Callback type for running transactions. Matches PlClient._withTx signature\n * so the index can run transactions before PlClient is fully initialized.\n */\nexport type TxRunner = <T>(\n name: string,\n writable: boolean,\n clientRoot: OptionalSignedResourceId,\n body: (tx: PlTransaction) => Promise<T>,\n) => Promise<T>;\n\ntype BackendCapability = \"getUserRoot\" | \"listUserResources\" | \"legacy\";\n\n/**\n * Abstracts user resource discovery with backward compatibility.\n *\n * Detects backend capability on the first getUserRoot() call and remembers\n * the result. Three-tier fallback:\n * 1. getUserRoot RPC (newest, supports createIfNotExists)\n * 2. listUserResources RPC (streams all resources, picks userRoot)\n * 3. Named resource lookup/creation via transaction (legacy)\n */\nexport class UserResources {\n private backendCapability: BackendCapability | undefined;\n\n constructor(\n private readonly ll: LLPlClient,\n private readonly runTx: TxRunner,\n public readonly authUser: string | null,\n ) {}\n\n /**\n * Returns the user's root resource ID.\n *\n * On first call, detects backend capability by trying methods in order:\n * 1. getUserRoot RPC (newest)\n * 2. listUserResources RPC\n * 3. Named resource lookup/creation via transaction (legacy)\n */\n async getUserRoot(opts: { login?: string; createIfNotExists: true }): Promise<SignedResourceId>;\n async getUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n async getUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n if (this.backendCapability === undefined) {\n return await this.detectAndGetUserRoot(opts);\n }\n return await this.getUserRootWith(this.backendCapability, opts);\n }\n\n private async detectAndGetUserRoot(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async detectAndGetUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async detectAndGetUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n // 1. Try getUserRoot RPC\n try {\n const root = await this.getUserRootViaRpc(opts);\n this.backendCapability = \"getUserRoot\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 2. Try listUserResources\n try {\n const root = await this.getUserRootViaList(opts);\n this.backendCapability = \"listUserResources\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 3. Legacy fallback\n this.backendCapability = \"legacy\";\n return await this.getUserRootViaLegacy(opts);\n }\n\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists: true },\n ): Promise<SignedResourceId>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts?: { login?: string; createIfNotExists?: boolean },\n ): Promise<SignedResourceId | undefined>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n switch (capability) {\n case \"getUserRoot\":\n return await this.getUserRootViaRpc(opts);\n case \"listUserResources\":\n return await this.getUserRootViaList(opts);\n case \"legacy\":\n return await this.getUserRootViaLegacy(opts);\n }\n }\n\n /**\n * Returns all data libraries the user has access to.\n * Always fetches fresh from the server (no caching).\n */\n async getDataLibraries(\n opts: { login?: string; createUserRootIfNotExists?: boolean } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n if (this.backendCapability === undefined) {\n // First call — detect backend capability\n try {\n const libs = await this.getDataLibrariesViaList(opts);\n // getUserRoot RPC doesn't return libraries, but listUserResources does;\n // record at least \"listUserResources\" so future getUserRoot calls don't re-detect.\n this.backendCapability = \"listUserResources\";\n return libs;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n this.backendCapability = \"legacy\";\n return await this.getDataLibrariesViaLegacy();\n }\n }\n\n // A server that supports getUserRoot definitely supports listUserResources.\n if (this.backendCapability !== \"legacy\") {\n return await this.getDataLibrariesViaList(opts);\n }\n return await this.getDataLibrariesViaLegacy();\n }\n\n /**\n * Discovers shared resources of a given type granted to the user, as signed resource ids.\n *\n * The public, type-filtered form of {@link getDataLibrariesViaList}: it polls the\n * `ListUserResources` gRPC stream and returns every `sharedResource` entry whose\n * `resourceType.name` matches `resourceTypeName`. Matching is by name only — the\n * version is ignored (permissive, survives schema bumps).\n *\n * gRPC-only: `ListUserResources` throws on a REST-connected client\n * ({@link LLPlClient.listUserResources}), so callers on REST get a thrown error.\n */\n async listSharedResourcesByType(\n resourceTypeName: string,\n opts: { login?: string } = {},\n ): Promise<SignedResourceId[]> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n const result: SignedResourceId[] = [];\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n if (!sr.resourceType) continue;\n if (sr.resourceType.name !== resourceTypeName) continue;\n result.push(createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature)));\n }\n return result;\n }\n\n /**\n * Enumerates the recipients of a single resource — the donor-side \"who did I\n * share with\" view.\n *\n * Takes a signed, writable resource handle: the backend gates grant listing on a\n * signed resource id with writable permission, so only the resource's owner can\n * call it. An everyone-grant surfaces with `user` matching the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\");\n * the caller maps that to \"*\".\n *\n * Runs over a read transaction ({@link PlTransaction.listGrants}), so it works on\n * every wire protocol — including REST, where the standalone server-streaming\n * `ListGrants` RPC has no binding.\n */\n async listGrants(resourceId: SignedResourceId): Promise<GrantEntry[]> {\n const grants = await this.runTx(\"ListGrants\", false, NullSignedResourceId, (tx) =>\n tx.listGrants(resourceId),\n );\n return grants.map((grant) => ({\n user: grant.user,\n writable: grant.permissions?.writable ?? false,\n grantedBy: grant.grantedBy,\n grantedAt: Number(grant.grantedAt),\n }));\n }\n\n /**\n * Lists the logins of users known to the server, for the recipient picker. A user becomes\n * known on first login; provisioned users who have never logged in do not appear. gRPC-only\n * (the underlying {@link LLPlClient.listUsers} has no REST binding) — throws on a\n * REST-connected client, so callers gate on the `userListing:v1` capability.\n */\n async listUsers(): Promise<UserEntry[]> {\n const users = await this.ll.listUsers();\n return users.map((user) => ({ login: user.login }));\n }\n\n private async getUserRootViaRpc(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaRpc(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaRpc(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const resp = await this.ll.getUserRoot({\n login: opts.login,\n createIfNotExists: opts.createIfNotExists,\n });\n if (resp.userRoot === undefined) {\n if (!opts.createIfNotExists) return undefined;\n throw new Error(\"getUserRoot returned no userRoot entry\");\n }\n return createSignedResourceId(\n resp.userRoot.resourceId,\n toResourceSignature(resp.userRoot.resourceSignature),\n );\n }\n\n private async getUserRootViaList(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaList(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaList(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const responses = await this.ll.listUserResources({ login: opts.login, limit: 1 });\n for (const msg of responses) {\n if (msg.entry.oneofKind === \"userRoot\") {\n return createSignedResourceId(\n msg.entry.userRoot.resourceId,\n toResourceSignature(msg.entry.userRoot.resourceSignature),\n );\n }\n }\n\n if (opts.createIfNotExists) {\n throw new Error(\"listUserResources returned no userRoot entry\");\n }\n\n return undefined;\n }\n\n private async getDataLibrariesViaList(\n opts: { login?: string } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n // Collect all LS/* shared resources, separating V1 and V2\n const v1Entries: StorageInfo[] = [];\n const v2ResourceIds: { resourceId: SignedResourceId; resourceType: ResourceType }[] = [];\n\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n\n if (!sr.resourceType) continue;\n const typeName = sr.resourceType.name;\n const typeVersion = sr.resourceType.version;\n if (!typeName.startsWith(LsStorageTypePrefix)) continue;\n\n const rId = createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature));\n const rType: ResourceType = { name: typeName, version: typeVersion };\n\n if (typeVersion === \"2\") {\n v2ResourceIds.push({ resourceId: rId, resourceType: rType });\n } else {\n // V1 or unknown version: derive storageId from type name\n const storageId = typeName.substring(LsStorageTypePrefix.length);\n v1Entries.push({\n storageId,\n storageName: storageId,\n resourceId: rId,\n resourceType: rType,\n });\n }\n }\n\n // Read V2 resource data in a single transaction\n let v2Entries: StorageInfo[] = [];\n if (v2ResourceIds.length > 0) {\n v2Entries = await this.runTx(\n \"ReadLsStorageV2Data\",\n false,\n NullSignedResourceId,\n async (tx) => {\n const entries: StorageInfo[] = [];\n for (const { resourceId, resourceType } of v2ResourceIds) {\n const rd = await tx.getResourceData(resourceId, false);\n if (rd.data) {\n const v2Data = JSON.parse(Buffer.from(rd.data).toString(\"utf-8\")) as LsStorageV2Data;\n entries.push({\n storageId: v2Data.storageID,\n storageName: v2Data.storageName,\n resourceId,\n resourceType,\n });\n }\n }\n return entries;\n },\n );\n }\n\n const result = new Map<string, StorageInfo>();\n for (const entry of [...v1Entries, ...v2Entries]) {\n result.set(entry.storageId, entry);\n }\n return result;\n }\n\n private async getUserRootViaLegacy(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaLegacy(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaLegacy(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const login = opts.login ?? this.authUser;\n const mainRootName =\n login === null ? AnonymousClientRoot : createHash(\"sha256\").update(login).digest(\"hex\");\n\n return await this.runTx(\"initialization\", true, NullSignedResourceId, async (tx) => {\n if (await tx.checkResourceNameExists(mainRootName)) {\n return await tx.getResourceByName(mainRootName);\n }\n\n if (!opts.createIfNotExists) {\n return undefined;\n }\n\n const mainRoot = tx.createRoot(ClientRoot);\n tx.setResourceName(mainRootName, mainRoot);\n await tx.commit();\n return await toGlobalResourceId(mainRoot);\n });\n }\n\n private async getDataLibrariesViaLegacy(): Promise<ReadonlyMap<string, StorageInfo>> {\n return await this.runTx(\"GetAvailableStorageIds\", false, NullSignedResourceId, async (tx) => {\n const lsProviderId = await tx.getResourceByName(\"LSProvider\");\n const provider = await tx.getResourceData(lsProviderId, true);\n\n const result = new Map<string, StorageInfo>();\n for (const field of provider.fields) {\n if (field.type !== \"Dynamic\" || !isNotNullSignedResourceId(field.value)) continue;\n if (!field.name.startsWith(LsProviderFieldPrefix)) continue;\n\n const storageId = field.name.substring(LsProviderFieldPrefix.length);\n result.set(storageId, {\n storageId,\n storageName: storageId,\n resourceId: field.value,\n resourceType: { name: `${LsStorageTypePrefix}${storageId}`, version: \"1\" },\n });\n }\n return result;\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"user_resources.js","names":[],"sources":["../../src/core/user_resources.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { LLPlClient } from \"./ll_client\";\nimport type { PlTransaction } from \"./transaction\";\nimport { toGlobalResourceId } from \"./transaction\";\nimport type { OptionalSignedResourceId, SignedResourceId, ResourceType } from \"./types\";\nimport {\n createSignedResourceId,\n isNotNullSignedResourceId,\n NullSignedResourceId,\n toResourceSignature,\n} from \"./types\";\nimport { isUnimplementedError } from \"./errors\";\nimport { ClientRoot } from \"../helpers/pl\";\n\nconst AnonymousClientRoot = \"AnonymousRoot\";\nconst LsStorageTypePrefix = \"LS/\"; // implements ls API in particular storage\nconst LsProviderFieldPrefix = \"storage/\"; // provides access to storages list\n\n/** One recipient of a resource, as returned by {@link UserResources.listGrants}. */\nexport interface GrantEntry {\n /** Login the grant targets. An everyone-grant surfaces here as the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\"); callers\n * map it to \"*\". */\n readonly user: string;\n /** True for a writable grant (copy / collaboration), false for read-only. */\n readonly writable: boolean;\n /** Login of the user who created the grant. */\n readonly grantedBy: string;\n /** When the grant was created (ms epoch). */\n readonly grantedAt: number;\n}\n\n/** One user known to the server, as returned by {@link UserResources.listUsers}. */\nexport interface UserEntry {\n /** Stable identifier of the user; the grant target and `GetUserRoot` key. */\n readonly login: string;\n}\n\n/** What {@link UserResources.deleteUser} removed, so a caller can report it. */\nexport interface UserDeletionReport {\n /** Raw id of the root resource the user owned, or undefined when they had none. Unsigned —\n * the resource is gone, so this is for the audit line, not for further calls. */\n readonly userRootId: bigint | undefined;\n /** Whether that root resource was deleted. */\n readonly userRootDeleted: boolean;\n /** Grants revoked, the user-root self-grant included. */\n readonly revokedGrants: number;\n /** Identity-index entries removed — one per value that resolved to the account: its login,\n * its email, and any alternative of either. */\n readonly removedIdentityIndexEntries: number;\n}\n\n/** Information about a single data library (LS storage). */\nexport interface StorageInfo {\n /** Machine-stable identifier, e.g. \"library\". Used for filtering and map keys. */\n readonly storageId: string;\n /** Human-readable display name. For V1/legacy equals storageId; for V2 from resource JSON data. */\n readonly storageName: string;\n /** Signed resource ID for this storage resource. */\n readonly resourceId: SignedResourceId;\n /** Full resource type including correct version (\"1\" or \"2\"). */\n readonly resourceType: ResourceType;\n}\n\n/** V2 LsStorage resource JSON data shape (contract with backend). */\ninterface LsStorageV2Data {\n storageName: string;\n storageID: string;\n}\n\n/**\n * Callback type for running transactions. Matches PlClient._withTx signature\n * so the index can run transactions before PlClient is fully initialized.\n */\nexport type TxRunner = <T>(\n name: string,\n writable: boolean,\n clientRoot: OptionalSignedResourceId,\n body: (tx: PlTransaction) => Promise<T>,\n) => Promise<T>;\n\ntype BackendCapability = \"getUserRoot\" | \"listUserResources\" | \"legacy\";\n\n/**\n * Abstracts user resource discovery with backward compatibility.\n *\n * Detects backend capability on the first getUserRoot() call and remembers\n * the result. Three-tier fallback:\n * 1. getUserRoot RPC (newest, supports createIfNotExists)\n * 2. listUserResources RPC (streams all resources, picks userRoot)\n * 3. Named resource lookup/creation via transaction (legacy)\n */\nexport class UserResources {\n private backendCapability: BackendCapability | undefined;\n\n constructor(\n private readonly ll: LLPlClient,\n private readonly runTx: TxRunner,\n public readonly authUser: string | null,\n ) {}\n\n /**\n * Returns the user's root resource ID.\n *\n * On first call, detects backend capability by trying methods in order:\n * 1. getUserRoot RPC (newest)\n * 2. listUserResources RPC\n * 3. Named resource lookup/creation via transaction (legacy)\n */\n async getUserRoot(opts: { login?: string; createIfNotExists: true }): Promise<SignedResourceId>;\n async getUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n async getUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n if (this.backendCapability === undefined) {\n return await this.detectAndGetUserRoot(opts);\n }\n return await this.getUserRootWith(this.backendCapability, opts);\n }\n\n private async detectAndGetUserRoot(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async detectAndGetUserRoot(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async detectAndGetUserRoot(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n // 1. Try getUserRoot RPC\n try {\n const root = await this.getUserRootViaRpc(opts);\n this.backendCapability = \"getUserRoot\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 2. Try listUserResources\n try {\n const root = await this.getUserRootViaList(opts);\n this.backendCapability = \"listUserResources\";\n return root;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n }\n\n // 3. Legacy fallback\n this.backendCapability = \"legacy\";\n return await this.getUserRootViaLegacy(opts);\n }\n\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists: true },\n ): Promise<SignedResourceId>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts?: { login?: string; createIfNotExists?: boolean },\n ): Promise<SignedResourceId | undefined>;\n private async getUserRootWith(\n capability: BackendCapability,\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n switch (capability) {\n case \"getUserRoot\":\n return await this.getUserRootViaRpc(opts);\n case \"listUserResources\":\n return await this.getUserRootViaList(opts);\n case \"legacy\":\n return await this.getUserRootViaLegacy(opts);\n }\n }\n\n /**\n * Returns all data libraries the user has access to.\n * Always fetches fresh from the server (no caching).\n */\n async getDataLibraries(\n opts: { login?: string; createUserRootIfNotExists?: boolean } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n if (this.backendCapability === undefined) {\n // First call — detect backend capability\n try {\n const libs = await this.getDataLibrariesViaList(opts);\n // getUserRoot RPC doesn't return libraries, but listUserResources does;\n // record at least \"listUserResources\" so future getUserRoot calls don't re-detect.\n this.backendCapability = \"listUserResources\";\n return libs;\n } catch (err) {\n if (!isUnimplementedError(err)) throw err;\n this.backendCapability = \"legacy\";\n return await this.getDataLibrariesViaLegacy();\n }\n }\n\n // A server that supports getUserRoot definitely supports listUserResources.\n if (this.backendCapability !== \"legacy\") {\n return await this.getDataLibrariesViaList(opts);\n }\n return await this.getDataLibrariesViaLegacy();\n }\n\n /**\n * Discovers shared resources of a given type granted to the user, as signed resource ids.\n *\n * The public, type-filtered form of {@link getDataLibrariesViaList}: it polls the\n * `ListUserResources` gRPC stream and returns every `sharedResource` entry whose\n * `resourceType.name` matches `resourceTypeName`. Matching is by name only — the\n * version is ignored (permissive, survives schema bumps).\n *\n * gRPC-only: `ListUserResources` throws on a REST-connected client\n * ({@link LLPlClient.listUserResources}), so callers on REST get a thrown error.\n */\n async listSharedResourcesByType(\n resourceTypeName: string,\n opts: { login?: string } = {},\n ): Promise<SignedResourceId[]> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n const result: SignedResourceId[] = [];\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n if (!sr.resourceType) continue;\n if (sr.resourceType.name !== resourceTypeName) continue;\n result.push(createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature)));\n }\n return result;\n }\n\n /**\n * Enumerates the recipients of a single resource — the donor-side \"who did I\n * share with\" view.\n *\n * Takes a signed, writable resource handle: the backend gates grant listing on a\n * signed resource id with writable permission, so only the resource's owner can\n * call it. An everyone-grant surfaces with `user` matching the backend's\n * everyone-sentinel — test with {@link isEveryoneUserLogin} (from \"./transaction\");\n * the caller maps that to \"*\".\n *\n * Runs over a read transaction ({@link PlTransaction.listGrants}), so it works on\n * every wire protocol — including REST, where the standalone server-streaming\n * `ListGrants` RPC has no binding.\n */\n async listGrants(resourceId: SignedResourceId): Promise<GrantEntry[]> {\n const grants = await this.runTx(\"ListGrants\", false, NullSignedResourceId, (tx) =>\n tx.listGrants(resourceId),\n );\n return grants.map((grant) => ({\n user: grant.user,\n writable: grant.permissions?.writable ?? false,\n grantedBy: grant.grantedBy,\n grantedAt: Number(grant.grantedAt),\n }));\n }\n\n /**\n * Lists the logins of users known to the server, for the recipient picker. A user becomes\n * known on first login; provisioned users who have never logged in do not appear. gRPC-only\n * (the underlying {@link LLPlClient.listUsers} has no REST binding) — throws on a\n * REST-connected client, so callers gate on the `userListing:v1` capability.\n */\n async listUsers(): Promise<UserEntry[]> {\n const users = await this.ll.listUsers();\n return users.map((user) => ({ login: user.login }));\n }\n\n /**\n * Deletes a user account: the record, every identity-index entry that resolves to it (its login,\n * its email, and any alternative of either), every grant it holds, and its root resource — and\n * with the root, everything still attached under it.\n *\n * Exists for the duplicate account one person can end up with — an identity that could not be\n * matched across a provider cutover, or one minted before the backend started refusing two\n * records for one identity. The spare record shows up wherever users are listed and its projects\n * keep taking part in deduplication.\n *\n * Destructive and irreversible. Re-attach anything worth keeping to another user's root before\n * calling — `pl-cli admin delete-user` does both steps in order. Requires admin/controller\n * credentials; gRPC-only, like {@link listUsers}.\n */\n async deleteUser(login: string): Promise<UserDeletionReport> {\n const resp = await this.ll.deleteUser(login);\n\n return {\n userRootId: resp.userRootId === 0n ? undefined : resp.userRootId,\n userRootDeleted: resp.userRootDeleted,\n revokedGrants: resp.revokedGrants,\n removedIdentityIndexEntries: resp.removedIdentityIndexEntries,\n };\n }\n\n private async getUserRootViaRpc(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaRpc(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaRpc(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const resp = await this.ll.getUserRoot({\n login: opts.login,\n createIfNotExists: opts.createIfNotExists,\n });\n if (resp.userRoot === undefined) {\n if (!opts.createIfNotExists) return undefined;\n throw new Error(\"getUserRoot returned no userRoot entry\");\n }\n return createSignedResourceId(\n resp.userRoot.resourceId,\n toResourceSignature(resp.userRoot.resourceSignature),\n );\n }\n\n private async getUserRootViaList(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaList(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaList(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const responses = await this.ll.listUserResources({ login: opts.login, limit: 1 });\n for (const msg of responses) {\n if (msg.entry.oneofKind === \"userRoot\") {\n return createSignedResourceId(\n msg.entry.userRoot.resourceId,\n toResourceSignature(msg.entry.userRoot.resourceSignature),\n );\n }\n }\n\n if (opts.createIfNotExists) {\n throw new Error(\"listUserResources returned no userRoot entry\");\n }\n\n return undefined;\n }\n\n private async getDataLibrariesViaList(\n opts: { login?: string } = {},\n ): Promise<ReadonlyMap<string, StorageInfo>> {\n const responses = await this.ll.listUserResources({ login: opts.login });\n\n // Collect all LS/* shared resources, separating V1 and V2\n const v1Entries: StorageInfo[] = [];\n const v2ResourceIds: { resourceId: SignedResourceId; resourceType: ResourceType }[] = [];\n\n for (const msg of responses) {\n if (msg.entry.oneofKind !== \"sharedResource\") continue;\n const sr = msg.entry.sharedResource;\n\n if (!sr.resourceType) continue;\n const typeName = sr.resourceType.name;\n const typeVersion = sr.resourceType.version;\n if (!typeName.startsWith(LsStorageTypePrefix)) continue;\n\n const rId = createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature));\n const rType: ResourceType = { name: typeName, version: typeVersion };\n\n if (typeVersion === \"2\") {\n v2ResourceIds.push({ resourceId: rId, resourceType: rType });\n } else {\n // V1 or unknown version: derive storageId from type name\n const storageId = typeName.substring(LsStorageTypePrefix.length);\n v1Entries.push({\n storageId,\n storageName: storageId,\n resourceId: rId,\n resourceType: rType,\n });\n }\n }\n\n // Read V2 resource data in a single transaction\n let v2Entries: StorageInfo[] = [];\n if (v2ResourceIds.length > 0) {\n v2Entries = await this.runTx(\n \"ReadLsStorageV2Data\",\n false,\n NullSignedResourceId,\n async (tx) => {\n const entries: StorageInfo[] = [];\n for (const { resourceId, resourceType } of v2ResourceIds) {\n const rd = await tx.getResourceData(resourceId, false);\n if (rd.data) {\n const v2Data = JSON.parse(Buffer.from(rd.data).toString(\"utf-8\")) as LsStorageV2Data;\n entries.push({\n storageId: v2Data.storageID,\n storageName: v2Data.storageName,\n resourceId,\n resourceType,\n });\n }\n }\n return entries;\n },\n );\n }\n\n const result = new Map<string, StorageInfo>();\n for (const entry of [...v1Entries, ...v2Entries]) {\n result.set(entry.storageId, entry);\n }\n return result;\n }\n\n private async getUserRootViaLegacy(opts: {\n login?: string;\n createIfNotExists: true;\n }): Promise<SignedResourceId>;\n private async getUserRootViaLegacy(opts?: {\n login?: string;\n createIfNotExists?: boolean;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaLegacy(\n opts: { login?: string; createIfNotExists?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const login = opts.login ?? this.authUser;\n const mainRootName =\n login === null ? AnonymousClientRoot : createHash(\"sha256\").update(login).digest(\"hex\");\n\n return await this.runTx(\"initialization\", true, NullSignedResourceId, async (tx) => {\n if (await tx.checkResourceNameExists(mainRootName)) {\n return await tx.getResourceByName(mainRootName);\n }\n\n if (!opts.createIfNotExists) {\n return undefined;\n }\n\n const mainRoot = tx.createRoot(ClientRoot);\n tx.setResourceName(mainRootName, mainRoot);\n await tx.commit();\n return await toGlobalResourceId(mainRoot);\n });\n }\n\n private async getDataLibrariesViaLegacy(): Promise<ReadonlyMap<string, StorageInfo>> {\n return await this.runTx(\"GetAvailableStorageIds\", false, NullSignedResourceId, async (tx) => {\n const lsProviderId = await tx.getResourceByName(\"LSProvider\");\n const provider = await tx.getResourceData(lsProviderId, true);\n\n const result = new Map<string, StorageInfo>();\n for (const field of provider.fields) {\n if (field.type !== \"Dynamic\" || !isNotNullSignedResourceId(field.value)) continue;\n if (!field.name.startsWith(LsProviderFieldPrefix)) continue;\n\n const storageId = field.name.substring(LsProviderFieldPrefix.length);\n result.set(storageId, {\n storageId,\n storageName: storageId,\n resourceId: field.value,\n resourceType: { name: `${LsStorageTypePrefix}${storageId}`, version: \"1\" },\n });\n }\n return result;\n });\n }\n}\n"],"mappings":"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"}
@@ -2,37 +2,35 @@ import { PlClientConfig } from "./config.js";
2
2
  import { GrpcTransport } from "@protobuf-ts/grpc-transport";
3
3
  import { Dispatcher } from "undici";
4
4
  import { Middleware } from "openapi-fetch";
5
-
6
5
  //#region src/core/wire.d.ts
7
6
  /**
8
7
  * Options for the HTTP client to properly reach the PL server API when
9
8
  * it works in WebSocket + REST mode.
10
9
  */
11
- type RestConnection = {
10
+ export type RestConnection = {
12
11
  type: "rest";
13
12
  Config: PlClientConfig;
14
13
  Dispatcher: Dispatcher;
15
14
  Middlewares: Middleware[];
16
15
  };
17
- type GrpcConnection = {
16
+ export type GrpcConnection = {
18
17
  type: "grpc";
19
18
  Transport: GrpcTransport;
20
19
  };
21
- type WireConnection = RestConnection | GrpcConnection;
20
+ export type WireConnection = RestConnection | GrpcConnection;
22
21
  /**
23
22
  * A provider for a wire (gRPC, HTTP, etc.) client.
24
23
  * The client is created on demand, and is reset when the transport is reset.
25
24
  * This is useful for cases where the client is used in a loop, and the transport is reset after each iteration.
26
25
  */
27
- interface WireClientProvider<Client> {
26
+ export interface WireClientProvider<Client> {
28
27
  get(): Client;
29
28
  }
30
29
  /**
31
30
  * A factory for wire client providers.
32
31
  */
33
- interface WireClientProviderFactory {
32
+ export interface WireClientProviderFactory {
34
33
  createWireClientProvider<Client>(clientConstructor: (transport: WireConnection) => Client): WireClientProvider<Client>;
35
34
  }
36
35
  //#endregion
37
- export { GrpcConnection, RestConnection, WireClientProvider, WireClientProviderFactory, WireConnection };
38
36
  //# sourceMappingURL=wire.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wire.d.ts","names":[],"sources":["../../src/core/wire.ts"],"mappings":";;;;;;;;AASA;;KAAY,cAAA;EACV,IAAA;EACA,MAAA,EAAQ,cAAA;EACR,UAAA,EAAY,UAAA;EACZ,WAAA,EAAa,UAAA;AAAA;AAAA,KAGH,cAAA;EACV,IAAA;EACA,SAAA,EAAW,aAAa;AAAA;AAAA,KAGd,cAAA,GAAiB,cAAA,GAAiB,cAAc;;;;AARnC;AAGzB;UAciB,kBAAA;EACf,GAAA,IAAO,MAAM;AAAA;;;;UAME,yBAAA;EACf,wBAAA,SACE,iBAAA,GAAoB,SAAA,EAAW,cAAA,KAAmB,MAAA,GACjD,kBAAA,CAAmB,MAAA;AAAA"}
1
+ {"version":3,"file":"wire.d.ts","names":[],"sources":["../../src/core/wire.ts"],"mappings":";;;;;;;;;YASY;EACV;EACA,QAAQ;EACR,YAAY;EACZ,aAAa;;YAGH;EACV;EACA,WAAW;;YAGD,iBAAiB,iBAAiB;;;;;;iBAS7B,mBAAmB;EAClC,OAAO;;;;;iBAMQ;EACf,yBAAyB,QACvB,oBAAoB,WAAW,mBAAmB,SACjD,mBAAmB"}
@@ -1,43 +1,41 @@
1
1
  import { FutureFieldType, ResourceType } from "../core/types.js";
2
2
  import { AnyRef, FieldRef, PlTransaction, ResourceRef } from "../core/transaction.js";
3
-
4
- //#region src/helpers/pl.d.ts
5
3
  declare namespace pl_d_exports {
6
4
  export { ClientRoot, EphHolder, EphStdMap, Holder, HolderRefField, JsonArray, JsonBool, JsonGzObject, JsonNull, JsonNumber, JsonObject, JsonString, PlRecord, PlRecordEntry, RNull, StdMap, StructTestResource, ValueTestResource, createPlArray, createPlBool, createPlMap, createPlNull, createPlNumber, createPlObject, createPlString, futureRecord, plEntries, plEntry, unwrapHolder, wrapInEphHolder, wrapInHolder };
7
5
  }
8
- declare const ClientRoot: ResourceType;
9
- declare const StructTestResource: ResourceType;
10
- declare const ValueTestResource: ResourceType;
11
- declare const JsonString: ResourceType;
12
- declare const JsonBool: ResourceType;
13
- declare const JsonObject: ResourceType;
14
- declare const JsonGzObject: ResourceType;
15
- declare const JsonArray: ResourceType;
16
- declare const JsonNumber: ResourceType;
17
- declare const JsonNull: ResourceType;
18
- declare const RNull: ResourceType;
19
- declare const EphStdMap: ResourceType;
20
- declare const StdMap: ResourceType;
21
- declare function createPlNull(tx: PlTransaction): ResourceRef;
22
- declare function createPlBool(tx: PlTransaction, val: boolean): ResourceRef;
23
- declare function createPlNumber(tx: PlTransaction, val: number): ResourceRef;
24
- declare function createPlString(tx: PlTransaction, val: string): ResourceRef;
25
- declare function createPlArray(tx: PlTransaction, val: any[]): ResourceRef;
26
- declare function createPlObject(tx: PlTransaction, val: object): ResourceRef;
27
- type PlRecordEntry<Key extends string = string, Ref extends AnyRef = AnyRef> = [Key, Ref];
28
- type PlRecord<Key extends string = string, Ref extends AnyRef = AnyRef> = Record<Key, Ref>;
29
- declare function plEntry<Key extends string = string, Ref extends AnyRef = AnyRef>(key: Key, ref: Ref): PlRecordEntry<Key, Ref>;
30
- declare function plEntries<Key extends string = string, Ref extends AnyRef = AnyRef>(record: PlRecord<Key, Ref>, fields?: Key[]): PlRecordEntry<Key, Ref>[];
6
+ export declare const ClientRoot: ResourceType;
7
+ export declare const StructTestResource: ResourceType;
8
+ export declare const ValueTestResource: ResourceType;
9
+ export declare const JsonString: ResourceType;
10
+ export declare const JsonBool: ResourceType;
11
+ export declare const JsonObject: ResourceType;
12
+ export declare const JsonGzObject: ResourceType;
13
+ export declare const JsonArray: ResourceType;
14
+ export declare const JsonNumber: ResourceType;
15
+ export declare const JsonNull: ResourceType;
16
+ export declare const RNull: ResourceType;
17
+ export declare const EphStdMap: ResourceType;
18
+ export declare const StdMap: ResourceType;
19
+ export declare function createPlNull(tx: PlTransaction): ResourceRef;
20
+ export declare function createPlBool(tx: PlTransaction, val: boolean): ResourceRef;
21
+ export declare function createPlNumber(tx: PlTransaction, val: number): ResourceRef;
22
+ export declare function createPlString(tx: PlTransaction, val: string): ResourceRef;
23
+ export declare function createPlArray(tx: PlTransaction, val: any[]): ResourceRef;
24
+ export declare function createPlObject(tx: PlTransaction, val: object): ResourceRef;
25
+ export type PlRecordEntry<Key extends string = string, Ref extends AnyRef = AnyRef> = [Key, Ref];
26
+ export type PlRecord<Key extends string = string, Ref extends AnyRef = AnyRef> = Record<Key, Ref>;
27
+ export declare function plEntry<Key extends string = string, Ref extends AnyRef = AnyRef>(key: Key, ref: Ref): PlRecordEntry<Key, Ref>;
28
+ export declare function plEntries<Key extends string = string, Ref extends AnyRef = AnyRef>(record: PlRecord<Key, Ref>, fields?: Key[]): PlRecordEntry<Key, Ref>[];
31
29
  /** Helper method to build standard pl map from a set of entries */
32
- declare function createPlMap(tx: PlTransaction, entries: PlRecordEntry[] | PlRecord, ephemeral: boolean, type?: ResourceType): ResourceRef;
33
- declare function futureRecord<Key extends string>(tx: PlTransaction, rId: AnyRef, keys: Key[], fieldType: FutureFieldType, prefix?: string): PlRecord<Key, FieldRef>;
30
+ export declare function createPlMap(tx: PlTransaction, entries: PlRecordEntry[] | PlRecord, ephemeral: boolean, type?: ResourceType): ResourceRef;
31
+ export declare function futureRecord<Key extends string>(tx: PlTransaction, rId: AnyRef, keys: Key[], fieldType: FutureFieldType, prefix?: string): PlRecord<Key, FieldRef>;
34
32
  /** Name of the field in block holder, that references the actual block-pack. */
35
- declare const Holder: ResourceType;
36
- declare const EphHolder: ResourceType;
37
- declare const HolderRefField = "ref";
38
- declare function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef;
39
- declare function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef;
40
- declare function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef;
33
+ export declare const Holder: ResourceType;
34
+ export declare const EphHolder: ResourceType;
35
+ export declare const HolderRefField = "ref";
36
+ export declare function wrapInHolder(tx: PlTransaction, ref: AnyRef): ResourceRef;
37
+ export declare function wrapInEphHolder(tx: PlTransaction, ref: AnyRef): ResourceRef;
38
+ export declare function unwrapHolder(tx: PlTransaction, ref: AnyRef): FieldRef;
41
39
  //#endregion
42
- export { ClientRoot, EphHolder, EphStdMap, Holder, HolderRefField, JsonArray, JsonBool, JsonGzObject, JsonNull, JsonNumber, JsonObject, JsonString, PlRecord, PlRecordEntry, RNull, StdMap, StructTestResource, ValueTestResource, createPlArray, createPlBool, createPlMap, createPlNull, createPlNumber, createPlObject, createPlString, futureRecord, plEntries, plEntry, pl_d_exports, unwrapHolder, wrapInEphHolder, wrapInHolder };
40
+ export { pl_d_exports };
43
41
  //# sourceMappingURL=pl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pl.d.ts","names":[],"sources":["../../src/helpers/pl.ts"],"mappings":";;;;;;;cAiBa,UAAA,EAAU,YAAwB;AAAA,cAElC,kBAAA,EAAkB,YAAwB;AAAA,cAC1C,iBAAA,EAAiB,YAAuB;AAAA,cAExC,UAAA,EAAU,YAAyB;AAAA,cACnC,QAAA,EAAQ,YAAuB;AAAA,cAC/B,UAAA,EAAU,YAAyB;AAAA,cACnC,YAAA,EAAY,YAA4B;AAAA,cACxC,SAAA,EAAS,YAAwB;AAAA,cACjC,UAAA,EAAU,YAAyB;AAAA,cACnC,QAAA,EAAQ,YAAuB;AAAA,cAE/B,KAAA,EAAK,YAAkB;AAAA,cAEvB,SAAA,EAAW,YAAmC;AAAA,cAC9C,MAAA,EAAQ,YAAgC;AAAA,iBAMrC,YAAA,CAAa,EAAA,EAAI,aAAA,GAAgB,WAAW;AAAA,iBAI5C,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,YAAe,WAAW;AAAA,iBAI1D,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAW;AAAA,iBAI3D,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAW;AAAA,iBAI3D,aAAA,CAAc,EAAA,EAAI,aAAA,EAAe,GAAA,UAAa,WAAW;AAAA,iBAIzD,cAAA,CAAe,EAAA,EAAI,aAAA,EAAe,GAAA,WAAc,WAAW;AAAA,KAQ/D,aAAA,0CAAuD,MAAA,GAAS,MAAA,KAAW,GAAA,EAAK,GAAA;AAAA,KAEhF,QAAA,0CAAkD,MAAA,GAAS,MAAA,IAAU,MAAA,CAAO,GAAA,EAAK,GAAA;AAAA,iBAE7E,OAAA,0CAAiD,MAAA,GAAS,MAAA,EACxE,GAAA,EAAK,GAAA,EACL,GAAA,EAAK,GAAA,GACJ,aAAA,CAAc,GAAA,EAAK,GAAA;AAAA,iBAIN,SAAA,0CAAmD,MAAA,GAAS,MAAA,EAC1E,MAAA,EAAQ,QAAA,CAAS,GAAA,EAAK,GAAA,GACtB,MAAA,GAAS,GAAA,KACR,aAAA,CAAc,GAAA,EAAK,GAAA;;iBAON,WAAA,CACd,EAAA,EAAI,aAAA,EACJ,OAAA,EAAS,aAAA,KAAkB,QAAA,EAC3B,SAAA,WACA,IAAA,GAAO,YAAA,GACN,WAAA;AAAA,iBAYa,YAAA,qBACd,EAAA,EAAI,aAAA,EACJ,GAAA,EAAK,MAAA,EACL,IAAA,EAAM,GAAA,IACN,SAAA,EAAW,eAAA,EACX,MAAA,YACC,QAAA,CAAS,GAAA,EAAK,QAAA;;cAWJ,MAAA,EAAM,YAAS;AAAA,cACf,SAAA,EAAS,YAAY;AAAA,cACrB,cAAA;AAAA,iBAEG,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,WAAA;AAAA,iBAQ9C,eAAA,CAAgB,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,WAAA;AAAA,iBAQjD,YAAA,CAAa,EAAA,EAAI,aAAA,EAAe,GAAA,EAAK,MAAA,GAAS,QAAA"}
1
+ {"version":3,"file":"pl.d.ts","names":[],"sources":["../../src/helpers/pl.ts"],"mappings":";;;;;qBAiBa,YAAU;qBAEV,oBAAkB;qBAClB,mBAAiB;qBAEjB,YAAU;qBACV,UAAQ;qBACR,YAAU;qBACV,cAAY;qBACZ,WAAS;qBACT,YAAU;qBACV,UAAQ;qBAER,OAAK;qBAEL,WAAW;qBACX,QAAQ;wBAML,aAAa,IAAI,gBAAgB;wBAIjC,aAAa,IAAI,eAAe,eAAe;wBAI/C,eAAe,IAAI,eAAe,cAAc;wBAIhD,eAAe,IAAI,eAAe,cAAc;wBAIhD,cAAc,IAAI,eAAe,aAAa;wBAI9C,eAAe,IAAI,eAAe,cAAc;YAQpD,cAAc,6BAA6B,YAAY,SAAS,WAAW,KAAK;YAEhF,SAAS,6BAA6B,YAAY,SAAS,UAAU,OAAO,KAAK;wBAE7E,QAAQ,6BAA6B,YAAY,SAAS,QACxE,KAAK,KACL,KAAK,MACJ,cAAc,KAAK;wBAIN,UAAU,6BAA6B,YAAY,SAAS,QAC1E,QAAQ,SAAS,KAAK,MACtB,SAAS,QACR,cAAc,KAAK;;wBAON,YACd,IAAI,eACJ,SAAS,kBAAkB,UAC3B,oBACA,OAAO,eACN;wBAYa,aAAa,oBAC3B,IAAI,eACJ,KAAK,QACL,MAAM,OACN,WAAW,iBACX,kBACC,SAAS,KAAK;;qBAWJ,QAAM;qBACN,WAAS;qBACT;wBAEG,aAAa,IAAI,eAAe,KAAK,SAAS;wBAQ9C,gBAAgB,IAAI,eAAe,KAAK,SAAS;wBAQjD,aAAa,IAAI,eAAe,KAAK,SAAS"}
@@ -2,20 +2,20 @@ import { FieldData, FieldType, ResourceData, SignedResourceId } from "../core/ty
2
2
  import { PlTransaction } from "../core/transaction.js";
3
3
  import { PlClient } from "../core/client.js";
4
4
  import { RetryOptions } from "@milaboratories/ts-helpers";
5
-
6
5
  //#region src/helpers/poll.d.ts
7
6
  /** This error tells state assertion mechanism that required state is not yet ready */
8
- declare class ContinuePolling extends Error {
7
+ export declare class ContinuePolling extends Error {
9
8
  name: string;
10
9
  }
11
- type PollFieldTraverseOps = {
10
+ export type PollFieldTraverseOps = {
12
11
  expectedType?: FieldType;
13
12
  /** Fail if error present along with the value, if value not present,
14
13
  * but error do, exception will be thrown anyway. */
15
- failOnError: boolean; /** Traverse only if field report its value as final. */
14
+ failOnError: boolean;
15
+ /** Traverse only if field report its value as final. */
16
16
  onlyFinal: boolean;
17
17
  };
18
- declare class PollResourceAccessor {
18
+ export declare class PollResourceAccessor {
19
19
  readonly tx: PollTxAccessor;
20
20
  readonly data: ResourceData;
21
21
  readonly path: string[];
@@ -30,14 +30,13 @@ declare class PollResourceAccessor {
30
30
  getKValue(key: string): Promise<string>;
31
31
  getKValueObj<T>(key: string): Promise<T>;
32
32
  }
33
- declare class PollTxAccessor {
33
+ export declare class PollTxAccessor {
34
34
  readonly tx: PlTransaction;
35
35
  constructor(tx: PlTransaction);
36
36
  get(rid: SignedResourceId, failOnError?: boolean, path?: string[]): Promise<PollResourceAccessor>;
37
37
  throwError(error: SignedResourceId, path?: string[]): Promise<never>;
38
38
  }
39
- declare const DefaultPollingRetryOptions: RetryOptions;
40
- declare function poll<T>(cl: PlClient, cb: (tx: PollTxAccessor) => Promise<T>, retryOptions?: RetryOptions, txName?: string): Promise<T>;
39
+ export declare const DefaultPollingRetryOptions: RetryOptions;
40
+ export declare function poll<T>(cl: PlClient, cb: (tx: PollTxAccessor) => Promise<T>, retryOptions?: RetryOptions, txName?: string): Promise<T>;
41
41
  //#endregion
42
- export { ContinuePolling, DefaultPollingRetryOptions, PollFieldTraverseOps, PollResourceAccessor, PollTxAccessor, poll };
43
42
  //# sourceMappingURL=poll.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"poll.d.ts","names":[],"sources":["../../src/helpers/poll.ts"],"mappings":";;;;;;;cAaa,eAAA,SAAwB,KAAK;EACxC,IAAI;AAAA;AAAA,KAGM,oBAAA;EACV,YAAA,GAAe,SAAS;EAJpB;AAGN;EAIE,WAAA;EAEA,SAAA;AAAA;AAAA,cAQW,oBAAA;EAAA,SAEO,EAAA,EAAI,cAAA;EAAA,SACJ,IAAA,EAAM,YAAA;EAAA,SACN,IAAA;cAFA,EAAA,EAAI,cAAA,EACJ,IAAA,EAAM,YAAA,EACN,IAAA;EAGX,KAAA,IAAS,oBAAA;EAKH,cAAA,IAAkB,OAAA,CAAQ,oBAAA;EAOhC,YAAA,CAAa,IAAA,UAAc,YAAA,GAAe,SAAA,GAAY,SAAA;EAqBhD,GAAA,CACX,IAAA,UACA,GAAA,GAAK,OAAA,CAAQ,oBAAA,IACZ,OAAA,CAAQ,oBAAA;EAgBE,QAAA,CACX,GAAA,EAAK,OAAA,CAAQ,oBAAA,MACV,KAAA,aACF,OAAA,CAAQ,oBAAA;EAIE,WAAA,qBACX,GAAA,EAAK,OAAA,CAAQ,oBAAA,MACV,KAAA,EAAO,GAAA,KACT,OAAA,CAAQ,MAAA,CAAO,GAAA,EAAK,oBAAA;EAMV,WAAA,CACX,GAAA,GAAK,OAAA,CAAQ,oBAAA,IACZ,OAAA,CAAQ,MAAA,SAAe,oBAAA;EASb,SAAA,CAAU,GAAA,WAAc,OAAA;EAMxB,YAAA,IAAgB,GAAA,WAAc,OAAA,CAAQ,CAAA;AAAA;AAAA,cAKxC,cAAA;EAAA,SACiB,EAAA,EAAI,aAAA;cAAJ,EAAA,EAAI,aAAA;EAEnB,GAAA,CACX,GAAA,EAAK,gBAAA,EACL,WAAA,YACA,IAAA,cACC,OAAA,CAAQ,oBAAA;EAOL,UAAA,CAAW,KAAA,EAAO,gBAAA,EAAkB,IAAA,cAAsB,OAAA;AAAA;AAAA,cAOrD,0BAAA,EAA4B,YAMxC;AAAA,iBAEqB,IAAA,IACpB,EAAA,EAAI,QAAA,EACJ,EAAA,GAAK,EAAA,EAAI,cAAA,KAAmB,OAAA,CAAQ,CAAA,GACpC,YAAA,GAAc,YAAA,EACd,MAAA,YACC,OAAA,CAAQ,CAAA"}
1
+ {"version":3,"file":"poll.d.ts","names":[],"sources":["../../src/helpers/poll.ts"],"mappings":";;;;;;qBAaa,wBAAwB;EACnC;;YAGU;EACV,eAAe;;;EAGf;;EAEA;;qBAQW;WAEO,IAAI;WACJ,MAAM;WACN;EAHlB,YACkB,IAAI,gBACJ,MAAM,cACN;EAGX,SAAS;EAKH,kBAAkB,QAAQ;EAOhC,aAAa,cAAc,eAAe,YAAY;EAqBhD,IACX,cACA,MAAK,QAAQ,wBACZ,QAAQ;EAgBE,SACX,KAAK,QAAQ,0BACV,kBACF,QAAQ;EAIE,YAAY,oBACvB,KAAK,QAAQ,0BACV,OAAO,QACT,QAAQ,OAAO,KAAK;EAMV,YACX,MAAK,QAAQ,wBACZ,QAAQ,eAAe;EASb,UAAU,cAAc;EAMxB,aAAa,GAAG,cAAc,QAAQ;;qBAKxC;WACiB,IAAI;EAAhC,YAA4B,IAAI;EAEnB,IACX,KAAK,kBACL,uBACA,kBACC,QAAQ;EAOL,WAAW,OAAO,kBAAkB,kBAAsB;;qBAOrD,4BAA4B;wBAQnB,KAAK,GACzB,IAAI,UACJ,KAAK,IAAI,mBAAmB,QAAQ,IACpC,eAAc,cACd,kBACC,QAAQ"}
@@ -1,13 +1,11 @@
1
1
  import { FieldData, OptionalSignedResourceId } from "../core/types.js";
2
2
  import { PlTransaction } from "../core/transaction.js";
3
-
4
3
  //#region src/helpers/tx_helpers.d.ts
5
- interface ValErr {
4
+ export interface ValErr {
6
5
  valueId: OptionalSignedResourceId;
7
6
  errorId: OptionalSignedResourceId;
8
7
  error?: string;
9
8
  }
10
- declare function valErr(tx: PlTransaction, f: FieldData): Promise<ValErr>;
9
+ export declare function valErr(tx: PlTransaction, f: FieldData): Promise<ValErr>;
11
10
  //#endregion
12
- export { ValErr, valErr };
13
11
  //# sourceMappingURL=tx_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tx_helpers.d.ts","names":[],"sources":["../../src/helpers/tx_helpers.ts"],"mappings":";;;;UAKiB,MAAA;EACf,OAAA,EAAS,wBAAA;EACT,OAAA,EAAS,wBAAwB;EACjC,KAAA;AAAA;AAAA,iBAGoB,MAAA,CAAO,EAAA,EAAI,aAAA,EAAe,CAAA,EAAG,SAAA,GAAY,OAAA,CAAQ,MAAA"}
1
+ {"version":3,"file":"tx_helpers.d.ts","names":[],"sources":["../../src/helpers/tx_helpers.ts"],"mappings":";;;iBAKiB;EACf,SAAS;EACT,SAAS;EACT;;wBAGoB,OAAO,IAAI,eAAe,GAAG,YAAY,QAAQ"}
package/dist/index.d.ts CHANGED
@@ -8,14 +8,14 @@ import { BackendCapability, hasCapability } from "./core/capabilities.js";
8
8
  import { GrpcConnection, RestConnection, WireClientProvider, WireClientProviderFactory, WireConnection } from "./core/wire.js";
9
9
  import { index_d_exports } from "./proto-rest/index.js";
10
10
  import { PlDriver, PlDriverDefinition, addRTypeToMetadata, createRTypeRoutingHeader } from "./core/driver.js";
11
- import { GrantEntry, StorageInfo, TxRunner, UserEntry, UserResources } from "./core/user_resources.js";
11
+ import { GrantEntry, StorageInfo, TxRunner, UserDeletionReport, UserEntry, UserResources } from "./core/user_resources.js";
12
12
  import { PlClient, TxOps } from "./core/client.js";
13
13
  import { DisconnectedError, PermissionDeniedError, PlError, PlErrorCodeNotFound, RESTError, RecoverablePlError, UnauthenticatedError, UnrecoverablePlError, isAbortedError, isCancelError, isConnectionProblem, isNotFoundError, isPermissionDenied, isTimeoutError, isTimeoutOrCancelError, isTransientCallFailure, isUnauthenticated, isUnimplementedError, rethrowMeaningfulError, throwPlNotFoundError } from "./core/errors.js";
14
14
  import { defaultPlClient, tryGetFileConfig } from "./core/default_client.js";
15
- import { SSOAuthMethod, SSOFlowType, SSOLoginAttempt, UnauthenticatedPlClient } from "./core/unauth_client.js";
15
+ import { LoginMethod, SSOAuthMethod, SSOFlowType, SSOLoginAttempt, UnauthenticatedPlClient } from "./core/unauth_client.js";
16
16
  import { expirationFromAuthInformation, inferAuthRefreshTime } from "./core/auth.js";
17
17
  import { Filter, Property, treeFilter } from "./core/tree_filter.js";
18
18
  import { ValErr, valErr } from "./helpers/tx_helpers.js";
19
19
  import { ContinuePolling, DefaultPollingRetryOptions, PollFieldTraverseOps, PollResourceAccessor, PollTxAccessor, poll } from "./helpers/poll.js";
20
20
  import { test_config_d_exports } from "./test/test_config.js";
21
- export { AnonymousAuthInformation, AnyFieldId, AnyFieldRef, AnyRef, AnyResourceId, AnyResourceRef, AuthInformation, AuthOps, BackendCapability, BasicResourceData, ColorProof, ContinuePolling, DEFAULT_AUTH_MAX_REFRESH, DEFAULT_LOGIN_TIMEOUT, DEFAULT_MAX_CACHE_BYTES, DEFAULT_REQUEST_TIMEOUT, DEFAULT_RETRY_BACKOFF_ALGORITHM, DEFAULT_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER, DEFAULT_RETRY_INITIAL_DELAY, DEFAULT_RETRY_JITTER, DEFAULT_RETRY_LINEAR_BACKOFF_STEP, DEFAULT_RETRY_MAX_ATTEMPTS, DEFAULT_RETRY_MAX_DELAY, DEFAULT_RO_TX_TIMEOUT, DEFAULT_RW_TX_TIMEOUT, DEFAULT_TOKEN_TTL_SECONDS, DefaultFinalResourceDataPredicate, DefaultPollingRetryOptions, DefaultRetryOptions, DisconnectedError, FieldData, FieldId, FieldRef, FieldStatus, FieldType, Filter, ResourceAPI_Tree_Filter_OperatorType as FilterOperatorType, ResourceAPI_Tree_Filter_Property as FilterProperty, FinalResourceDataPredicate, FutureFieldType, GlobalResourceId, GrantEntry, GrantPermissions, GrantType, GrpcConnection, KeyValue, KeyValueString, LocalFieldId, LocalResourceId, MAX_ADAPTIVE_REQUEST_TIMEOUT, MaxLocalId, MaxTxId, NullResourceId, NullSignedResourceId, OptionalAnyResourceId, OptionalSignedResourceId, PermissionDeniedError, pl_d_exports as Pl, PlClient, PlClientConfig, PlConnectionStatus, PlConnectionStatusListener, PlDriver, PlDriverDefinition, PlError, PlErrorCodeNotFound, PlTransaction, PollFieldTraverseOps, PollResourceAccessor, PollTxAccessor, Property, RESTError, RTT_DEADLINE_MULTIPLIER, RTT_SMOOTHING_ALPHA, RecoverablePlError, type ResourceAPI_Tree_Filter, ResourceData, ResourceIdWithSignature, ResourceKind, ResourceRef, ResourceSignature, ResourceTreeFrame, ResourceTreeItem, ResourceType, ResourceTypeName, ResourceTypePrefix, index_d_exports as RestAPI, RestConnection, Role, SSOAuthMethod, SSOFlowType, SSOLoginAttempt, SUPPORTED_WIRE_PROTOCOLS, SignedResourceId, StorageInfo, test_config_d_exports as TestHelpers, TxCommitConflict, TxOps, TxRunner, UnauthenticatedError, UnauthenticatedPlClient, UnrecoverablePlError, UserEntry, UserResources, ValErr, WireClientProvider, WireClientProviderFactory, WireConnection, addRTypeToMetadata, anyResourceIdToBigint, asSignedResourceId, base64UrlToSignature, checkLocalityOfResourceId, createGlobalResourceId, createLocalResourceId, createRTypeRoutingHeader, createSignedResourceId, defaultPlClient, deriveUnaryDeadline, ensureSignedResourceIdNotNull, expirationFromAuthInformation, extractBasicResourceData, extractTxId, field, getField, hasCapability, inferAuthRefreshTime, isAbortedError, isAnyResourceId, isCancelError, isConnectionProblem, isEveryoneUserLogin, isField, isFieldRef, isLocalResourceId, isNotFoundError, isNotNullSignedResourceId, isNullSignedResourceId, isPermissionDenied, isResource, isResourceId, isResourceRef, isRootResourceId, isSignedResourceId, isTimeoutError, isTimeoutOrCancelError, isTransientCallFailure, isUnauthenticated, isUnimplementedError, jsonToData, parseResourceType, parseSignedResourceId, plAddressToConfig, poll, readyOrDuplicateOrError, resDataToJson, resourceIdFromString, resourceIdToString, resourceType, resourceTypeToString, resourceTypesEqual, rethrowMeaningfulError, setResourceSignaturesRequired, signatureToBase64Url, smoothRtt, stringifyWithResourceId, throwPlNotFoundError, toFieldId, toGlobalFieldId, toGlobalResourceId, toResourceSignature, treeFilter, tryGetFileConfig, valErr, wireProtocol };
21
+ export { AnonymousAuthInformation, AnyFieldId, AnyFieldRef, AnyRef, AnyResourceId, AnyResourceRef, AuthInformation, AuthOps, BackendCapability, BasicResourceData, ColorProof, ContinuePolling, DEFAULT_AUTH_MAX_REFRESH, DEFAULT_LOGIN_TIMEOUT, DEFAULT_MAX_CACHE_BYTES, DEFAULT_REQUEST_TIMEOUT, DEFAULT_RETRY_BACKOFF_ALGORITHM, DEFAULT_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER, DEFAULT_RETRY_INITIAL_DELAY, DEFAULT_RETRY_JITTER, DEFAULT_RETRY_LINEAR_BACKOFF_STEP, DEFAULT_RETRY_MAX_ATTEMPTS, DEFAULT_RETRY_MAX_DELAY, DEFAULT_RO_TX_TIMEOUT, DEFAULT_RW_TX_TIMEOUT, DEFAULT_TOKEN_TTL_SECONDS, DefaultFinalResourceDataPredicate, DefaultPollingRetryOptions, DefaultRetryOptions, DisconnectedError, FieldData, FieldId, FieldRef, FieldStatus, FieldType, Filter, ResourceAPI_Tree_Filter_OperatorType as FilterOperatorType, ResourceAPI_Tree_Filter_Property as FilterProperty, FinalResourceDataPredicate, FutureFieldType, GlobalResourceId, GrantEntry, GrantPermissions, GrantType, GrpcConnection, KeyValue, KeyValueString, LocalFieldId, LocalResourceId, LoginMethod, MAX_ADAPTIVE_REQUEST_TIMEOUT, MaxLocalId, MaxTxId, NullResourceId, NullSignedResourceId, OptionalAnyResourceId, OptionalSignedResourceId, PermissionDeniedError, pl_d_exports as Pl, PlClient, PlClientConfig, PlConnectionStatus, PlConnectionStatusListener, PlDriver, PlDriverDefinition, PlError, PlErrorCodeNotFound, PlTransaction, PollFieldTraverseOps, PollResourceAccessor, PollTxAccessor, Property, RESTError, RTT_DEADLINE_MULTIPLIER, RTT_SMOOTHING_ALPHA, RecoverablePlError, type ResourceAPI_Tree_Filter, ResourceData, ResourceIdWithSignature, ResourceKind, ResourceRef, ResourceSignature, ResourceTreeFrame, ResourceTreeItem, ResourceType, ResourceTypeName, ResourceTypePrefix, index_d_exports as RestAPI, RestConnection, Role, SSOAuthMethod, SSOFlowType, SSOLoginAttempt, SUPPORTED_WIRE_PROTOCOLS, SignedResourceId, StorageInfo, test_config_d_exports as TestHelpers, TxCommitConflict, TxOps, TxRunner, UnauthenticatedError, UnauthenticatedPlClient, UnrecoverablePlError, UserDeletionReport, UserEntry, UserResources, ValErr, WireClientProvider, WireClientProviderFactory, WireConnection, addRTypeToMetadata, anyResourceIdToBigint, asSignedResourceId, base64UrlToSignature, checkLocalityOfResourceId, createGlobalResourceId, createLocalResourceId, createRTypeRoutingHeader, createSignedResourceId, defaultPlClient, deriveUnaryDeadline, ensureSignedResourceIdNotNull, expirationFromAuthInformation, extractBasicResourceData, extractTxId, field, getField, hasCapability, inferAuthRefreshTime, isAbortedError, isAnyResourceId, isCancelError, isConnectionProblem, isEveryoneUserLogin, isField, isFieldRef, isLocalResourceId, isNotFoundError, isNotNullSignedResourceId, isNullSignedResourceId, isPermissionDenied, isResource, isResourceId, isResourceRef, isRootResourceId, isSignedResourceId, isTimeoutError, isTimeoutOrCancelError, isTransientCallFailure, isUnauthenticated, isUnimplementedError, jsonToData, parseResourceType, parseSignedResourceId, plAddressToConfig, poll, readyOrDuplicateOrError, resDataToJson, resourceIdFromString, resourceIdToString, resourceType, resourceTypeToString, resourceTypesEqual, rethrowMeaningfulError, setResourceSignaturesRequired, signatureToBase64Url, smoothRtt, stringifyWithResourceId, throwPlNotFoundError, toFieldId, toGlobalFieldId, toGlobalResourceId, toResourceSignature, treeFilter, tryGetFileConfig, valErr, wireProtocol };