@milaboratories/pl-client 3.2.4 → 3.3.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.
- package/dist/core/client.cjs +24 -56
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +12 -8
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +26 -58
- package/dist/core/client.js.map +1 -1
- package/dist/core/errors.cjs +20 -0
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts +6 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +19 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/final.cjs +6 -5
- package/dist/core/final.cjs.map +1 -1
- package/dist/core/final.d.ts.map +1 -1
- package/dist/core/final.js +7 -6
- package/dist/core/final.js.map +1 -1
- package/dist/core/ll_client.cjs +18 -1
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +6 -2
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +19 -2
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/transaction.cjs +109 -75
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts +30 -22
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +111 -76
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/type_conversion.cjs +14 -6
- package/dist/core/type_conversion.cjs.map +1 -1
- package/dist/core/type_conversion.js +14 -6
- package/dist/core/type_conversion.js.map +1 -1
- package/dist/core/types.cjs +77 -17
- package/dist/core/types.cjs.map +1 -1
- package/dist/core/types.d.ts +49 -26
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +66 -14
- package/dist/core/types.js.map +1 -1
- package/dist/core/user_resources.cjs +181 -0
- package/dist/core/user_resources.cjs.map +1 -0
- package/dist/core/user_resources.d.ts +75 -0
- package/dist/core/user_resources.d.ts.map +1 -0
- package/dist/core/user_resources.js +180 -0
- package/dist/core/user_resources.js.map +1 -0
- package/dist/helpers/poll.cjs +4 -4
- package/dist/helpers/poll.cjs.map +1 -1
- package/dist/helpers/poll.d.ts +3 -3
- package/dist/helpers/poll.d.ts.map +1 -1
- package/dist/helpers/poll.js +5 -5
- package/dist/helpers/poll.js.map +1 -1
- package/dist/helpers/tx_helpers.cjs +1 -1
- package/dist/helpers/tx_helpers.cjs.map +1 -1
- package/dist/helpers/tx_helpers.d.ts +3 -3
- package/dist/helpers/tx_helpers.d.ts.map +1 -1
- package/dist/helpers/tx_helpers.js +2 -2
- package/dist/helpers/tx_helpers.js.map +1 -1
- package/dist/index.cjs +16 -5
- package/dist/index.d.ts +5 -4
- package/dist/index.js +5 -4
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +724 -188
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs +34 -9
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts +37 -5
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js +34 -9
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +326 -136
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +724 -188
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs +18 -7
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts +11 -7
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js +18 -7
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs +57 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts +26 -3
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js +57 -3
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.js.map +1 -1
- package/dist/proto-rest/plapi.d.ts +421 -207
- package/dist/proto-rest/plapi.d.ts.map +1 -1
- package/dist/test/test_config.cjs +6 -3
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +7 -4
- package/dist/test/test_config.js.map +1 -1
- package/package.json +5 -5
- package/src/core/client.ts +58 -103
- package/src/core/errors.ts +23 -0
- package/src/core/final.ts +16 -6
- package/src/core/ll_client.ts +39 -3
- package/src/core/ll_transaction.test.ts +41 -6
- package/src/core/transaction.ts +176 -86
- package/src/core/type_conversion.ts +24 -9
- package/src/core/types.ts +147 -41
- package/src/core/user_resources.ts +332 -0
- package/src/helpers/poll.ts +15 -8
- package/src/helpers/state_helpers.ts +2 -2
- package/src/helpers/tx_helpers.ts +5 -5
- package/src/index.ts +1 -0
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client.ts +61 -14
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +1045 -379
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api_types.ts +33 -18
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/base_types.ts +75 -6
- package/src/proto-grpc/google/protobuf/descriptor.ts +5 -2
- package/src/proto-rest/plapi.ts +447 -225
- package/src/test/test_config.ts +8 -5
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { createSignedResourceId, isNotNullSignedResourceId, toResourceSignature } from "./types.js";
|
|
2
|
+
import { isUnimplementedError } from "./errors.js";
|
|
3
|
+
import { toGlobalResourceId } from "./transaction.js";
|
|
4
|
+
import { ClientRoot } from "../helpers/pl.js";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
//#region src/core/user_resources.ts
|
|
7
|
+
const AnonymousClientRoot = "AnonymousRoot";
|
|
8
|
+
const LsStorageTypePrefix = "LS/";
|
|
9
|
+
const LsProviderFieldPrefix = "storage/";
|
|
10
|
+
/**
|
|
11
|
+
* Abstracts user resource discovery with backward compatibility.
|
|
12
|
+
*
|
|
13
|
+
* Detects backend capability on the first getUserRoot() call and remembers
|
|
14
|
+
* the result. Three-tier fallback:
|
|
15
|
+
* 1. getUserRoot RPC (newest, supports doNotCreate)
|
|
16
|
+
* 2. listUserResources RPC (streams all resources, picks userRoot)
|
|
17
|
+
* 3. Named resource lookup/creation via transaction (legacy)
|
|
18
|
+
*/
|
|
19
|
+
var UserResources = class {
|
|
20
|
+
backendCapability;
|
|
21
|
+
constructor(ll, runTx, authUser) {
|
|
22
|
+
this.ll = ll;
|
|
23
|
+
this.runTx = runTx;
|
|
24
|
+
this.authUser = authUser;
|
|
25
|
+
}
|
|
26
|
+
async getUserRoot(opts = {}) {
|
|
27
|
+
if (this.backendCapability === void 0) return await this.detectAndGetUserRoot(opts);
|
|
28
|
+
return await this.getUserRootWith(this.backendCapability, opts);
|
|
29
|
+
}
|
|
30
|
+
async detectAndGetUserRoot(opts = {}) {
|
|
31
|
+
try {
|
|
32
|
+
const root = await this.getUserRootViaRpc(opts);
|
|
33
|
+
this.backendCapability = "getUserRoot";
|
|
34
|
+
return root;
|
|
35
|
+
} catch (err) {
|
|
36
|
+
if (!isUnimplementedError(err)) throw err;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const root = await this.getUserRootViaList(opts);
|
|
40
|
+
this.backendCapability = "listUserResources";
|
|
41
|
+
return root;
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (!isUnimplementedError(err)) throw err;
|
|
44
|
+
}
|
|
45
|
+
this.backendCapability = "legacy";
|
|
46
|
+
return await this.getUserRootViaLegacy(opts);
|
|
47
|
+
}
|
|
48
|
+
async getUserRootWith(capability, opts = {}) {
|
|
49
|
+
switch (capability) {
|
|
50
|
+
case "getUserRoot": return await this.getUserRootViaRpc(opts);
|
|
51
|
+
case "listUserResources": return await this.getUserRootViaList(opts);
|
|
52
|
+
case "legacy": return await this.getUserRootViaLegacy(opts);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns all data libraries the user has access to.
|
|
57
|
+
* Always fetches fresh from the server (no caching).
|
|
58
|
+
*/
|
|
59
|
+
async getDataLibraries(opts = {}) {
|
|
60
|
+
if (this.backendCapability === void 0) try {
|
|
61
|
+
const libs = await this.getDataLibrariesViaList(opts);
|
|
62
|
+
this.backendCapability = "listUserResources";
|
|
63
|
+
return libs;
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (!isUnimplementedError(err)) throw err;
|
|
66
|
+
this.backendCapability = "legacy";
|
|
67
|
+
return await this.getDataLibrariesViaLegacy();
|
|
68
|
+
}
|
|
69
|
+
if (this.backendCapability !== "legacy") return await this.getDataLibrariesViaList(opts);
|
|
70
|
+
return await this.getDataLibrariesViaLegacy();
|
|
71
|
+
}
|
|
72
|
+
async getUserRootViaRpc(opts = {}) {
|
|
73
|
+
const resp = await this.ll.getUserRoot({
|
|
74
|
+
login: opts.login,
|
|
75
|
+
doNotCreate: opts.doNotCreate
|
|
76
|
+
});
|
|
77
|
+
if (resp.userRoot === void 0) {
|
|
78
|
+
if (opts.doNotCreate) return void 0;
|
|
79
|
+
throw new Error("getUserRoot returned no userRoot entry");
|
|
80
|
+
}
|
|
81
|
+
return createSignedResourceId(resp.userRoot.resourceId, toResourceSignature(resp.userRoot.resourceSignature));
|
|
82
|
+
}
|
|
83
|
+
async getUserRootViaList(opts = {}) {
|
|
84
|
+
const responses = await this.ll.listUserResources({
|
|
85
|
+
login: opts.login,
|
|
86
|
+
limit: 1
|
|
87
|
+
});
|
|
88
|
+
for (const msg of responses) if (msg.entry.oneofKind === "userRoot") return createSignedResourceId(msg.entry.userRoot.resourceId, toResourceSignature(msg.entry.userRoot.resourceSignature));
|
|
89
|
+
throw new Error("listUserResources returned no userRoot entry");
|
|
90
|
+
}
|
|
91
|
+
async getDataLibrariesViaList(opts = {}) {
|
|
92
|
+
const responses = await this.ll.listUserResources({ login: opts.login });
|
|
93
|
+
const v1Entries = [];
|
|
94
|
+
const v2ResourceIds = [];
|
|
95
|
+
for (const msg of responses) {
|
|
96
|
+
if (msg.entry.oneofKind !== "sharedResource") continue;
|
|
97
|
+
const sr = msg.entry.sharedResource;
|
|
98
|
+
if (!sr.resourceType) continue;
|
|
99
|
+
const typeName = sr.resourceType.name;
|
|
100
|
+
const typeVersion = sr.resourceType.version;
|
|
101
|
+
if (!typeName.startsWith(LsStorageTypePrefix)) continue;
|
|
102
|
+
const rId = createSignedResourceId(sr.resourceId, toResourceSignature(sr.resourceSignature));
|
|
103
|
+
const rType = {
|
|
104
|
+
name: typeName,
|
|
105
|
+
version: typeVersion
|
|
106
|
+
};
|
|
107
|
+
if (typeVersion === "2") v2ResourceIds.push({
|
|
108
|
+
resourceId: rId,
|
|
109
|
+
resourceType: rType
|
|
110
|
+
});
|
|
111
|
+
else {
|
|
112
|
+
const storageId = typeName.substring(3);
|
|
113
|
+
v1Entries.push({
|
|
114
|
+
storageId,
|
|
115
|
+
storageName: storageId,
|
|
116
|
+
resourceId: rId,
|
|
117
|
+
resourceType: rType
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
let v2Entries = [];
|
|
122
|
+
if (v2ResourceIds.length > 0) v2Entries = await this.runTx("ReadLsStorageV2Data", false, "", async (tx) => {
|
|
123
|
+
const entries = [];
|
|
124
|
+
for (const { resourceId, resourceType } of v2ResourceIds) {
|
|
125
|
+
const rd = await tx.getResourceData(resourceId, false);
|
|
126
|
+
if (rd.data) {
|
|
127
|
+
const v2Data = JSON.parse(Buffer.from(rd.data).toString("utf-8"));
|
|
128
|
+
entries.push({
|
|
129
|
+
storageId: v2Data.storageID,
|
|
130
|
+
storageName: v2Data.storageName,
|
|
131
|
+
resourceId,
|
|
132
|
+
resourceType
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return entries;
|
|
137
|
+
});
|
|
138
|
+
const result = /* @__PURE__ */ new Map();
|
|
139
|
+
for (const entry of [...v1Entries, ...v2Entries]) result.set(entry.storageId, entry);
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
async getUserRootViaLegacy(opts = {}) {
|
|
143
|
+
const login = opts.login ?? this.authUser;
|
|
144
|
+
const mainRootName = login === null ? AnonymousClientRoot : createHash("sha256").update(login).digest("hex");
|
|
145
|
+
return await this.runTx("initialization", true, "", async (tx) => {
|
|
146
|
+
if (await tx.checkResourceNameExists(mainRootName)) return await tx.getResourceByName(mainRootName);
|
|
147
|
+
if (opts.doNotCreateUserRoot) return;
|
|
148
|
+
const mainRoot = tx.createRoot(ClientRoot);
|
|
149
|
+
tx.setResourceName(mainRootName, mainRoot);
|
|
150
|
+
await tx.commit();
|
|
151
|
+
return await toGlobalResourceId(mainRoot);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
async getDataLibrariesViaLegacy() {
|
|
155
|
+
return await this.runTx("GetAvailableStorageIds", false, "", async (tx) => {
|
|
156
|
+
const lsProviderId = await tx.getResourceByName("LSProvider");
|
|
157
|
+
const provider = await tx.getResourceData(lsProviderId, true);
|
|
158
|
+
const result = /* @__PURE__ */ new Map();
|
|
159
|
+
for (const field of provider.fields) {
|
|
160
|
+
if (field.type !== "Dynamic" || !isNotNullSignedResourceId(field.value)) continue;
|
|
161
|
+
if (!field.name.startsWith(LsProviderFieldPrefix)) continue;
|
|
162
|
+
const storageId = field.name.substring(8);
|
|
163
|
+
result.set(storageId, {
|
|
164
|
+
storageId,
|
|
165
|
+
storageName: storageId,
|
|
166
|
+
resourceId: field.value,
|
|
167
|
+
resourceType: {
|
|
168
|
+
name: `${LsStorageTypePrefix}${storageId}`,
|
|
169
|
+
version: "1"
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
//#endregion
|
|
178
|
+
export { UserResources };
|
|
179
|
+
|
|
180
|
+
//# sourceMappingURL=user_resources.js.map
|
|
@@ -0,0 +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/** 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 doNotCreate)\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(): Promise<SignedResourceId>;\n async getUserRoot(opts: { login?: string }): Promise<SignedResourceId>;\n async getUserRoot(opts: { login?: string; doNotCreate: false }): Promise<SignedResourceId>;\n async getUserRoot(opts: {\n login?: string;\n doNotCreate: true;\n }): Promise<SignedResourceId | undefined>;\n async getUserRoot(\n opts: { login?: string; doNotCreate?: 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(\n opts: { login?: string; doNotCreate?: 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; doNotCreate?: 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; doNotCreateUserRoot?: 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 private async getUserRootViaRpc(opts: { login?: string }): Promise<SignedResourceId>;\n private async getUserRootViaRpc(opts: {\n login?: string;\n doNotCreate: false;\n }): Promise<SignedResourceId>;\n private async getUserRootViaRpc(opts: {\n login?: string;\n doNotCreate: true;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaRpc(\n opts: { login?: string; doNotCreate?: boolean } = {},\n ): Promise<SignedResourceId | undefined> {\n const resp = await this.ll.getUserRoot({\n login: opts.login,\n doNotCreate: opts.doNotCreate,\n });\n if (resp.userRoot === undefined) {\n if (opts.doNotCreate) 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: { login?: string }): Promise<SignedResourceId>;\n private async getUserRootViaList(opts: {\n login?: string;\n doNotCreate: false;\n }): Promise<SignedResourceId>;\n private async getUserRootViaList(opts: {\n login?: string;\n doNotCreate: true;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaList(\n opts: { login?: string; doNotCreate?: 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 throw new Error(\"listUserResources returned no userRoot entry\");\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: { login?: string }): Promise<SignedResourceId>;\n private async getUserRootViaLegacy(opts: {\n login?: string;\n doNotCreateUserRoot: false;\n }): Promise<SignedResourceId>;\n private async getUserRootViaLegacy(opts: {\n login?: string;\n doNotCreateUserRoot: true;\n }): Promise<SignedResourceId | undefined>;\n private async getUserRootViaLegacy(\n opts: { login?: string; doNotCreateUserRoot?: 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.doNotCreateUserRoot) {\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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"}
|
package/dist/helpers/poll.cjs
CHANGED
|
@@ -23,7 +23,7 @@ var PollResourceAccessor = class {
|
|
|
23
23
|
return this;
|
|
24
24
|
}
|
|
25
25
|
async requireNoError() {
|
|
26
|
-
if (require_types.
|
|
26
|
+
if (require_types.isNullSignedResourceId(this.data.error)) return this;
|
|
27
27
|
await this.tx.throwError(this.data.error, this.path);
|
|
28
28
|
return this;
|
|
29
29
|
}
|
|
@@ -43,8 +43,8 @@ var PollResourceAccessor = class {
|
|
|
43
43
|
};
|
|
44
44
|
const path = [...this.path, name];
|
|
45
45
|
const fieldData = this.getFieldData(name, expectedType);
|
|
46
|
-
if (require_types.
|
|
47
|
-
if (require_types.
|
|
46
|
+
if (require_types.isNotNullSignedResourceId(fieldData.error) && (failOnError || require_types.isNullSignedResourceId(fieldData.value))) await this.tx.throwError(fieldData.error, path);
|
|
47
|
+
if (require_types.isNullSignedResourceId(fieldData.value)) throw new ContinuePolling();
|
|
48
48
|
return await this.tx.get(fieldData.value, failOnError, path);
|
|
49
49
|
}
|
|
50
50
|
async getMulti(ops, ...names) {
|
|
@@ -54,7 +54,7 @@ var PollResourceAccessor = class {
|
|
|
54
54
|
return Object.fromEntries(await Promise.all(names.map(async (name) => [name, await this.get(name, ops)])));
|
|
55
55
|
}
|
|
56
56
|
async getAllFinal(ops = {}) {
|
|
57
|
-
return await this.getMultiObj(ops, ...this.data.fields.filter((f) => f.valueIsFinal || require_types.
|
|
57
|
+
return await this.getMultiObj(ops, ...this.data.fields.filter((f) => f.valueIsFinal || require_types.isNotNullSignedResourceId(f.error)).map((f) => f.name));
|
|
58
58
|
}
|
|
59
59
|
async getKValue(key) {
|
|
60
60
|
const value = await this.tx.tx.getKValueStringIfExists(this.data.id, key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll.cjs","names":["
|
|
1
|
+
{"version":3,"file":"poll.cjs","names":["isNullSignedResourceId","isNotNullSignedResourceId","resourceIdToString","tp"],"sources":["../../src/helpers/poll.ts"],"sourcesContent":["import type { PlClient } from \"../core/client\";\nimport type { RetryOptions } from \"@milaboratories/ts-helpers\";\nimport { createRetryState, nextRetryStateOrError, notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { FieldData, FieldType, ResourceData, SignedResourceId } from \"../core/types\";\nimport {\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n resourceIdToString,\n} from \"../core/types\";\nimport type { PlTransaction } from \"../core/transaction\";\nimport * as tp from \"node:timers/promises\";\n\n/** This error tells state assertion mechanism that required state is not yet ready */\nexport class ContinuePolling extends Error {\n name = \"ContinuePolling\";\n}\n\nexport type PollFieldTraverseOps = {\n expectedType?: FieldType;\n /** Fail if error present along with the value, if value not present,\n * but error do, exception will be thrown anyway. */\n failOnError: boolean;\n /** Traverse only if field report its value as final. */\n onlyFinal: boolean;\n};\n\nconst DefaultPollFieldTraverseOps: PollFieldTraverseOps = {\n failOnError: true,\n onlyFinal: false,\n};\n\nexport class PollResourceAccessor {\n constructor(\n public readonly tx: PollTxAccessor,\n public readonly data: ResourceData,\n public readonly path: string[],\n ) {}\n\n public final(): PollResourceAccessor {\n if (!this.data.final) throw new ContinuePolling();\n return this;\n }\n\n public async requireNoError(): Promise<PollResourceAccessor> {\n if (isNullSignedResourceId(this.data.error)) return this;\n await this.tx.throwError(this.data.error, this.path);\n // hmm... https://github.com/microsoft/TypeScript/issues/34955\n return this;\n }\n\n public getFieldData(name: string, expectedType?: FieldType): FieldData {\n const fieldData = this.data.fields.find((f) => f.name === name);\n\n if (fieldData !== undefined) {\n if (expectedType !== undefined && fieldData.type !== expectedType)\n throw new Error(`Unexpected field type. Expected ${expectedType}, found ${fieldData.type}`);\n return fieldData;\n }\n\n if (\n ((expectedType === \"Input\" || expectedType === \"Service\") && this.data.inputsLocked) ||\n (expectedType === \"Output\" && this.data.outputsLocked)\n )\n throw new Error(\n // eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions\n `Field \"${name}\" not found. Expected type: ${expectedType}, state: ${this.data}`,\n );\n\n throw new ContinuePolling();\n }\n\n public async get(\n name: string,\n ops: Partial<PollFieldTraverseOps> = {},\n ): Promise<PollResourceAccessor> {\n const { expectedType, failOnError } = { ...DefaultPollFieldTraverseOps, ...ops };\n const path = [...this.path, name];\n\n const fieldData = this.getFieldData(name, expectedType);\n if (\n isNotNullSignedResourceId(fieldData.error) &&\n (failOnError || isNullSignedResourceId(fieldData.value))\n )\n await this.tx.throwError(fieldData.error, path);\n\n if (isNullSignedResourceId(fieldData.value)) throw new ContinuePolling();\n\n return await this.tx.get(fieldData.value, failOnError, path);\n }\n\n public async getMulti(\n ops: Partial<PollFieldTraverseOps>,\n ...names: string[]\n ): Promise<PollResourceAccessor[]> {\n return await Promise.all(names.map((name) => this.get(name, ops)));\n }\n\n public async getMultiObj<Key extends string>(\n ops: Partial<PollFieldTraverseOps>,\n ...names: Key[]\n ): Promise<Record<Key, PollResourceAccessor>> {\n return Object.fromEntries(\n await Promise.all(names.map(async (name) => [name, await this.get(name, ops)])),\n );\n }\n\n public async getAllFinal(\n ops: Partial<PollFieldTraverseOps> = {},\n ): Promise<Record<string, PollResourceAccessor>> {\n return await this.getMultiObj(\n ops,\n ...this.data.fields\n .filter((f) => f.valueIsFinal || isNotNullSignedResourceId(f.error))\n .map((f) => f.name),\n );\n }\n\n public async getKValue(key: string): Promise<string> {\n const value = await this.tx.tx.getKValueStringIfExists(this.data.id, key);\n if (value === undefined) throw new ContinuePolling();\n return value;\n }\n\n public async getKValueObj<T>(key: string): Promise<T> {\n return JSON.parse(await this.getKValue(key)) as T;\n }\n}\n\nexport class PollTxAccessor {\n constructor(public readonly tx: PlTransaction) {}\n\n public async get(\n rid: SignedResourceId,\n failOnError: boolean = true,\n path: string[] = [],\n ): Promise<PollResourceAccessor> {\n const data = await this.tx.getResourceData(rid, true);\n const accessor = new PollResourceAccessor(this, data, [...path, resourceIdToString(rid)]);\n if (failOnError) await accessor.requireNoError();\n return accessor;\n }\n\n async throwError(error: SignedResourceId, path: string[] = []): Promise<never> {\n const errorRes = await this.get(error);\n const errorText = Buffer.from(notEmpty(errorRes.data.data)).toString();\n throw new Error(`${path.join(\" -> \")} = ${errorText}`);\n }\n}\n\nexport const DefaultPollingRetryOptions: RetryOptions = {\n type: \"linearBackoff\",\n jitter: 0,\n maxAttempts: 100,\n backoffStep: 10,\n initialDelay: 10,\n};\n\nexport async function poll<T>(\n cl: PlClient,\n cb: (tx: PollTxAccessor) => Promise<T>,\n retryOptions: RetryOptions = DefaultPollingRetryOptions,\n txName: string = \"polling\",\n): Promise<T> {\n let retryState = createRetryState(retryOptions);\n while (true) {\n try {\n return await cl.withReadTx(txName, async (tx) => {\n return await cb(new PollTxAccessor(tx));\n });\n } catch (e: any) {\n // Rethrowing any error except the \"not ready yet\"\n if (!(e instanceof ContinuePolling)) throw e;\n }\n await tp.setTimeout(retryState.nextDelay);\n retryState = nextRetryStateOrError(retryState);\n }\n}\n"],"mappings":"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"}
|
package/dist/helpers/poll.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FieldData, FieldType, ResourceData,
|
|
1
|
+
import { FieldData, FieldType, ResourceData, SignedResourceId } from "../core/types.js";
|
|
2
2
|
import { PlTransaction } from "../core/transaction.js";
|
|
3
3
|
import { PlClient } from "../core/client.js";
|
|
4
4
|
import { RetryOptions } from "@milaboratories/ts-helpers";
|
|
@@ -33,8 +33,8 @@ declare class PollResourceAccessor {
|
|
|
33
33
|
declare class PollTxAccessor {
|
|
34
34
|
readonly tx: PlTransaction;
|
|
35
35
|
constructor(tx: PlTransaction);
|
|
36
|
-
get(rid:
|
|
37
|
-
throwError(error:
|
|
36
|
+
get(rid: SignedResourceId, failOnError?: boolean, path?: string[]): Promise<PollResourceAccessor>;
|
|
37
|
+
throwError(error: SignedResourceId, path?: string[]): Promise<never>;
|
|
38
38
|
}
|
|
39
39
|
declare const DefaultPollingRetryOptions: RetryOptions;
|
|
40
40
|
declare function poll<T>(cl: PlClient, cb: (tx: PollTxAccessor) => Promise<T>, retryOptions?: RetryOptions, txName?: string): Promise<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll.d.ts","names":[],"sources":["../../src/helpers/poll.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"poll.d.ts","names":[],"sources":["../../src/helpers/poll.ts"],"mappings":";;;;;;;cAaa,eAAA,SAAwB,KAAA;EACnC,IAAA;AAAA;AAAA,KAGU,oBAAA;EACV,YAAA,GAAe,SAAA;EAJX;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,CAAA,GAAS,oBAAA;EAKH,cAAA,CAAA,GAAkB,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,oBAAA,CACX,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,GAAA,CAAgB,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,YAAA;AAAA,iBAQnB,IAAA,GAAA,CACpB,EAAA,EAAI,QAAA,EACJ,EAAA,GAAK,EAAA,EAAI,cAAA,KAAmB,OAAA,CAAQ,CAAA,GACpC,YAAA,GAAc,YAAA,EACd,MAAA,YACC,OAAA,CAAQ,CAAA"}
|
package/dist/helpers/poll.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNotNullSignedResourceId, isNullSignedResourceId, resourceIdToString } from "../core/types.js";
|
|
2
2
|
import { createRetryState, nextRetryStateOrError, notEmpty } from "@milaboratories/ts-helpers";
|
|
3
3
|
import * as tp from "node:timers/promises";
|
|
4
4
|
//#region src/helpers/poll.ts
|
|
@@ -21,7 +21,7 @@ var PollResourceAccessor = class {
|
|
|
21
21
|
return this;
|
|
22
22
|
}
|
|
23
23
|
async requireNoError() {
|
|
24
|
-
if (
|
|
24
|
+
if (isNullSignedResourceId(this.data.error)) return this;
|
|
25
25
|
await this.tx.throwError(this.data.error, this.path);
|
|
26
26
|
return this;
|
|
27
27
|
}
|
|
@@ -41,8 +41,8 @@ var PollResourceAccessor = class {
|
|
|
41
41
|
};
|
|
42
42
|
const path = [...this.path, name];
|
|
43
43
|
const fieldData = this.getFieldData(name, expectedType);
|
|
44
|
-
if (
|
|
45
|
-
if (
|
|
44
|
+
if (isNotNullSignedResourceId(fieldData.error) && (failOnError || isNullSignedResourceId(fieldData.value))) await this.tx.throwError(fieldData.error, path);
|
|
45
|
+
if (isNullSignedResourceId(fieldData.value)) throw new ContinuePolling();
|
|
46
46
|
return await this.tx.get(fieldData.value, failOnError, path);
|
|
47
47
|
}
|
|
48
48
|
async getMulti(ops, ...names) {
|
|
@@ -52,7 +52,7 @@ var PollResourceAccessor = class {
|
|
|
52
52
|
return Object.fromEntries(await Promise.all(names.map(async (name) => [name, await this.get(name, ops)])));
|
|
53
53
|
}
|
|
54
54
|
async getAllFinal(ops = {}) {
|
|
55
|
-
return await this.getMultiObj(ops, ...this.data.fields.filter((f) => f.valueIsFinal ||
|
|
55
|
+
return await this.getMultiObj(ops, ...this.data.fields.filter((f) => f.valueIsFinal || isNotNullSignedResourceId(f.error)).map((f) => f.name));
|
|
56
56
|
}
|
|
57
57
|
async getKValue(key) {
|
|
58
58
|
const value = await this.tx.tx.getKValueStringIfExists(this.data.id, key);
|
package/dist/helpers/poll.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll.js","names":[],"sources":["../../src/helpers/poll.ts"],"sourcesContent":["import type { PlClient } from \"../core/client\";\nimport type { RetryOptions } from \"@milaboratories/ts-helpers\";\nimport { createRetryState, nextRetryStateOrError, notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { FieldData, FieldType, ResourceData,
|
|
1
|
+
{"version":3,"file":"poll.js","names":[],"sources":["../../src/helpers/poll.ts"],"sourcesContent":["import type { PlClient } from \"../core/client\";\nimport type { RetryOptions } from \"@milaboratories/ts-helpers\";\nimport { createRetryState, nextRetryStateOrError, notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { FieldData, FieldType, ResourceData, SignedResourceId } from \"../core/types\";\nimport {\n isNotNullSignedResourceId,\n isNullSignedResourceId,\n resourceIdToString,\n} from \"../core/types\";\nimport type { PlTransaction } from \"../core/transaction\";\nimport * as tp from \"node:timers/promises\";\n\n/** This error tells state assertion mechanism that required state is not yet ready */\nexport class ContinuePolling extends Error {\n name = \"ContinuePolling\";\n}\n\nexport type PollFieldTraverseOps = {\n expectedType?: FieldType;\n /** Fail if error present along with the value, if value not present,\n * but error do, exception will be thrown anyway. */\n failOnError: boolean;\n /** Traverse only if field report its value as final. */\n onlyFinal: boolean;\n};\n\nconst DefaultPollFieldTraverseOps: PollFieldTraverseOps = {\n failOnError: true,\n onlyFinal: false,\n};\n\nexport class PollResourceAccessor {\n constructor(\n public readonly tx: PollTxAccessor,\n public readonly data: ResourceData,\n public readonly path: string[],\n ) {}\n\n public final(): PollResourceAccessor {\n if (!this.data.final) throw new ContinuePolling();\n return this;\n }\n\n public async requireNoError(): Promise<PollResourceAccessor> {\n if (isNullSignedResourceId(this.data.error)) return this;\n await this.tx.throwError(this.data.error, this.path);\n // hmm... https://github.com/microsoft/TypeScript/issues/34955\n return this;\n }\n\n public getFieldData(name: string, expectedType?: FieldType): FieldData {\n const fieldData = this.data.fields.find((f) => f.name === name);\n\n if (fieldData !== undefined) {\n if (expectedType !== undefined && fieldData.type !== expectedType)\n throw new Error(`Unexpected field type. Expected ${expectedType}, found ${fieldData.type}`);\n return fieldData;\n }\n\n if (\n ((expectedType === \"Input\" || expectedType === \"Service\") && this.data.inputsLocked) ||\n (expectedType === \"Output\" && this.data.outputsLocked)\n )\n throw new Error(\n // eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions\n `Field \"${name}\" not found. Expected type: ${expectedType}, state: ${this.data}`,\n );\n\n throw new ContinuePolling();\n }\n\n public async get(\n name: string,\n ops: Partial<PollFieldTraverseOps> = {},\n ): Promise<PollResourceAccessor> {\n const { expectedType, failOnError } = { ...DefaultPollFieldTraverseOps, ...ops };\n const path = [...this.path, name];\n\n const fieldData = this.getFieldData(name, expectedType);\n if (\n isNotNullSignedResourceId(fieldData.error) &&\n (failOnError || isNullSignedResourceId(fieldData.value))\n )\n await this.tx.throwError(fieldData.error, path);\n\n if (isNullSignedResourceId(fieldData.value)) throw new ContinuePolling();\n\n return await this.tx.get(fieldData.value, failOnError, path);\n }\n\n public async getMulti(\n ops: Partial<PollFieldTraverseOps>,\n ...names: string[]\n ): Promise<PollResourceAccessor[]> {\n return await Promise.all(names.map((name) => this.get(name, ops)));\n }\n\n public async getMultiObj<Key extends string>(\n ops: Partial<PollFieldTraverseOps>,\n ...names: Key[]\n ): Promise<Record<Key, PollResourceAccessor>> {\n return Object.fromEntries(\n await Promise.all(names.map(async (name) => [name, await this.get(name, ops)])),\n );\n }\n\n public async getAllFinal(\n ops: Partial<PollFieldTraverseOps> = {},\n ): Promise<Record<string, PollResourceAccessor>> {\n return await this.getMultiObj(\n ops,\n ...this.data.fields\n .filter((f) => f.valueIsFinal || isNotNullSignedResourceId(f.error))\n .map((f) => f.name),\n );\n }\n\n public async getKValue(key: string): Promise<string> {\n const value = await this.tx.tx.getKValueStringIfExists(this.data.id, key);\n if (value === undefined) throw new ContinuePolling();\n return value;\n }\n\n public async getKValueObj<T>(key: string): Promise<T> {\n return JSON.parse(await this.getKValue(key)) as T;\n }\n}\n\nexport class PollTxAccessor {\n constructor(public readonly tx: PlTransaction) {}\n\n public async get(\n rid: SignedResourceId,\n failOnError: boolean = true,\n path: string[] = [],\n ): Promise<PollResourceAccessor> {\n const data = await this.tx.getResourceData(rid, true);\n const accessor = new PollResourceAccessor(this, data, [...path, resourceIdToString(rid)]);\n if (failOnError) await accessor.requireNoError();\n return accessor;\n }\n\n async throwError(error: SignedResourceId, path: string[] = []): Promise<never> {\n const errorRes = await this.get(error);\n const errorText = Buffer.from(notEmpty(errorRes.data.data)).toString();\n throw new Error(`${path.join(\" -> \")} = ${errorText}`);\n }\n}\n\nexport const DefaultPollingRetryOptions: RetryOptions = {\n type: \"linearBackoff\",\n jitter: 0,\n maxAttempts: 100,\n backoffStep: 10,\n initialDelay: 10,\n};\n\nexport async function poll<T>(\n cl: PlClient,\n cb: (tx: PollTxAccessor) => Promise<T>,\n retryOptions: RetryOptions = DefaultPollingRetryOptions,\n txName: string = \"polling\",\n): Promise<T> {\n let retryState = createRetryState(retryOptions);\n while (true) {\n try {\n return await cl.withReadTx(txName, async (tx) => {\n return await cb(new PollTxAccessor(tx));\n });\n } catch (e: any) {\n // Rethrowing any error except the \"not ready yet\"\n if (!(e instanceof ContinuePolling)) throw e;\n }\n await tp.setTimeout(retryState.nextDelay);\n retryState = nextRetryStateOrError(retryState);\n }\n}\n"],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ async function valErr(tx, f) {
|
|
|
8
8
|
errorId: f.error,
|
|
9
9
|
error: ""
|
|
10
10
|
};
|
|
11
|
-
if (require_types.
|
|
11
|
+
if (require_types.isNotNullSignedResourceId(f.error)) {
|
|
12
12
|
const e = await tx.getResourceData(f.error, true);
|
|
13
13
|
const deserializationResult = (0, _milaboratories_ts_helpers.cachedDeserialize)((0, _milaboratories_ts_helpers.notEmpty)(e.data));
|
|
14
14
|
if (typeof deserializationResult !== "string") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx_helpers.cjs","names":["
|
|
1
|
+
{"version":3,"file":"tx_helpers.cjs","names":["isNotNullSignedResourceId"],"sources":["../../src/helpers/tx_helpers.ts"],"sourcesContent":["import type { PlTransaction } from \"../core/transaction\";\nimport type { FieldData, OptionalSignedResourceId } from \"../core/types\";\nimport { isNotNullSignedResourceId } from \"../core/types\";\nimport { cachedDeserialize, notEmpty } from \"@milaboratories/ts-helpers\";\n\nexport interface ValErr {\n valueId: OptionalSignedResourceId;\n errorId: OptionalSignedResourceId;\n error?: string;\n}\n\nexport async function valErr(tx: PlTransaction, f: FieldData): Promise<ValErr> {\n const result = {\n valueId: f.value,\n errorId: f.error,\n error: \"\",\n };\n\n if (isNotNullSignedResourceId(f.error)) {\n const e = await tx.getResourceData(f.error, true);\n const deserializationResult = cachedDeserialize(notEmpty(e.data));\n if (typeof deserializationResult !== \"string\") {\n const dataStr = notEmpty(e.data).toString();\n throw new Error(\n `Unexpected error structure: ${dataStr.substring(0, Math.min(dataStr.length, 100))}...`,\n );\n }\n result.error = deserializationResult;\n }\n\n return result;\n}\n"],"mappings":";;;;AAWA,eAAsB,OAAO,IAAmB,GAA+B;CAC7E,MAAM,SAAS;EACb,SAAS,EAAE;EACX,SAAS,EAAE;EACX,OAAO;EACR;AAED,KAAIA,cAAAA,0BAA0B,EAAE,MAAM,EAAE;EACtC,MAAM,IAAI,MAAM,GAAG,gBAAgB,EAAE,OAAO,KAAK;EACjD,MAAM,yBAAA,GAAA,2BAAA,oBAAA,GAAA,2BAAA,UAAmD,EAAE,KAAK,CAAC;AACjE,MAAI,OAAO,0BAA0B,UAAU;GAC7C,MAAM,WAAA,GAAA,2BAAA,UAAmB,EAAE,KAAK,CAAC,UAAU;AAC3C,SAAM,IAAI,MACR,+BAA+B,QAAQ,UAAU,GAAG,KAAK,IAAI,QAAQ,QAAQ,IAAI,CAAC,CAAC,KACpF;;AAEH,SAAO,QAAQ;;AAGjB,QAAO"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { FieldData,
|
|
1
|
+
import { FieldData, OptionalSignedResourceId } from "../core/types.js";
|
|
2
2
|
import { PlTransaction } from "../core/transaction.js";
|
|
3
3
|
|
|
4
4
|
//#region src/helpers/tx_helpers.d.ts
|
|
5
5
|
interface ValErr {
|
|
6
|
-
valueId:
|
|
7
|
-
errorId:
|
|
6
|
+
valueId: OptionalSignedResourceId;
|
|
7
|
+
errorId: OptionalSignedResourceId;
|
|
8
8
|
error?: string;
|
|
9
9
|
}
|
|
10
10
|
declare function valErr(tx: PlTransaction, f: FieldData): Promise<ValErr>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx_helpers.d.ts","names":[],"sources":["../../src/helpers/tx_helpers.ts"],"mappings":";;;;UAKiB,MAAA;EACf,OAAA,EAAS,
|
|
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,wBAAA;EACT,KAAA;AAAA;AAAA,iBAGoB,MAAA,CAAO,EAAA,EAAI,aAAA,EAAe,CAAA,EAAG,SAAA,GAAY,OAAA,CAAQ,MAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNotNullSignedResourceId } from "../core/types.js";
|
|
2
2
|
import { cachedDeserialize, notEmpty } from "@milaboratories/ts-helpers";
|
|
3
3
|
//#region src/helpers/tx_helpers.ts
|
|
4
4
|
async function valErr(tx, f) {
|
|
@@ -7,7 +7,7 @@ async function valErr(tx, f) {
|
|
|
7
7
|
errorId: f.error,
|
|
8
8
|
error: ""
|
|
9
9
|
};
|
|
10
|
-
if (
|
|
10
|
+
if (isNotNullSignedResourceId(f.error)) {
|
|
11
11
|
const e = await tx.getResourceData(f.error, true);
|
|
12
12
|
const deserializationResult = cachedDeserialize(notEmpty(e.data));
|
|
13
13
|
if (typeof deserializationResult !== "string") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx_helpers.js","names":[],"sources":["../../src/helpers/tx_helpers.ts"],"sourcesContent":["import type { PlTransaction } from \"../core/transaction\";\nimport type { FieldData,
|
|
1
|
+
{"version":3,"file":"tx_helpers.js","names":[],"sources":["../../src/helpers/tx_helpers.ts"],"sourcesContent":["import type { PlTransaction } from \"../core/transaction\";\nimport type { FieldData, OptionalSignedResourceId } from \"../core/types\";\nimport { isNotNullSignedResourceId } from \"../core/types\";\nimport { cachedDeserialize, notEmpty } from \"@milaboratories/ts-helpers\";\n\nexport interface ValErr {\n valueId: OptionalSignedResourceId;\n errorId: OptionalSignedResourceId;\n error?: string;\n}\n\nexport async function valErr(tx: PlTransaction, f: FieldData): Promise<ValErr> {\n const result = {\n valueId: f.value,\n errorId: f.error,\n error: \"\",\n };\n\n if (isNotNullSignedResourceId(f.error)) {\n const e = await tx.getResourceData(f.error, true);\n const deserializationResult = cachedDeserialize(notEmpty(e.data));\n if (typeof deserializationResult !== \"string\") {\n const dataStr = notEmpty(e.data).toString();\n throw new Error(\n `Unexpected error structure: ${dataStr.substring(0, Math.min(dataStr.length, 100))}...`,\n );\n }\n result.error = deserializationResult;\n }\n\n return result;\n}\n"],"mappings":";;;AAWA,eAAsB,OAAO,IAAmB,GAA+B;CAC7E,MAAM,SAAS;EACb,SAAS,EAAE;EACX,SAAS,EAAE;EACX,OAAO;EACR;AAED,KAAI,0BAA0B,EAAE,MAAM,EAAE;EACtC,MAAM,IAAI,MAAM,GAAG,gBAAgB,EAAE,OAAO,KAAK;EACjD,MAAM,wBAAwB,kBAAkB,SAAS,EAAE,KAAK,CAAC;AACjE,MAAI,OAAO,0BAA0B,UAAU;GAC7C,MAAM,UAAU,SAAS,EAAE,KAAK,CAAC,UAAU;AAC3C,SAAM,IAAI,MACR,+BAA+B,QAAQ,UAAU,GAAG,KAAK,IAAI,QAAQ,QAAQ,IAAI,CAAC,CAAC,KACpF;;AAEH,SAAO,QAAQ;;AAGjB,QAAO"}
|
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,7 @@ const require_config = require("./core/config.cjs");
|
|
|
8
8
|
const require_auth = require("./core/auth.cjs");
|
|
9
9
|
const require_index = require("./proto-rest/index.cjs");
|
|
10
10
|
const require_final = require("./core/final.cjs");
|
|
11
|
+
const require_user_resources = require("./core/user_resources.cjs");
|
|
11
12
|
const require_client = require("./core/client.cjs");
|
|
12
13
|
const require_driver = require("./core/driver.cjs");
|
|
13
14
|
const require_unauth_client = require("./core/unauth_client.cjs");
|
|
@@ -37,6 +38,8 @@ exports.DisconnectedError = require_errors.DisconnectedError;
|
|
|
37
38
|
exports.MaxLocalId = require_types.MaxLocalId;
|
|
38
39
|
exports.MaxTxId = require_types.MaxTxId;
|
|
39
40
|
exports.NullResourceId = require_types.NullResourceId;
|
|
41
|
+
exports.NullSignedResourceId = require_types.NullSignedResourceId;
|
|
42
|
+
exports.PermissionDeniedError = require_errors.PermissionDeniedError;
|
|
40
43
|
Object.defineProperty(exports, "Pl", {
|
|
41
44
|
enumerable: true,
|
|
42
45
|
get: function() {
|
|
@@ -70,14 +73,17 @@ exports.TxCommitConflict = require_transaction.TxCommitConflict;
|
|
|
70
73
|
exports.UnauthenticatedError = require_errors.UnauthenticatedError;
|
|
71
74
|
exports.UnauthenticatedPlClient = require_unauth_client.UnauthenticatedPlClient;
|
|
72
75
|
exports.UnrecoverablePlError = require_errors.UnrecoverablePlError;
|
|
76
|
+
exports.UserResources = require_user_resources.UserResources;
|
|
73
77
|
exports.addRTypeToMetadata = require_driver.addRTypeToMetadata;
|
|
74
|
-
exports.
|
|
78
|
+
exports.anyResourceIdToBigint = require_types.anyResourceIdToBigint;
|
|
79
|
+
exports.base64UrlToSignature = require_types.base64UrlToSignature;
|
|
75
80
|
exports.checkLocalityOfResourceId = require_types.checkLocalityOfResourceId;
|
|
76
81
|
exports.createGlobalResourceId = require_types.createGlobalResourceId;
|
|
77
82
|
exports.createLocalResourceId = require_types.createLocalResourceId;
|
|
78
83
|
exports.createRTypeRoutingHeader = require_driver.createRTypeRoutingHeader;
|
|
84
|
+
exports.createSignedResourceId = require_types.createSignedResourceId;
|
|
79
85
|
exports.defaultPlClient = require_default_client.defaultPlClient;
|
|
80
|
-
exports.
|
|
86
|
+
exports.ensureSignedResourceIdNotNull = require_types.ensureSignedResourceIdNotNull;
|
|
81
87
|
exports.expirationFromAuthInformation = require_auth.expirationFromAuthInformation;
|
|
82
88
|
exports.extractBasicResourceData = require_types.extractBasicResourceData;
|
|
83
89
|
exports.extractTxId = require_types.extractTxId;
|
|
@@ -92,17 +98,21 @@ exports.isField = require_transaction.isField;
|
|
|
92
98
|
exports.isFieldRef = require_transaction.isFieldRef;
|
|
93
99
|
exports.isLocalResourceId = require_types.isLocalResourceId;
|
|
94
100
|
exports.isNotFoundError = require_errors.isNotFoundError;
|
|
95
|
-
exports.
|
|
96
|
-
exports.
|
|
101
|
+
exports.isNotNullSignedResourceId = require_types.isNotNullSignedResourceId;
|
|
102
|
+
exports.isNullSignedResourceId = require_types.isNullSignedResourceId;
|
|
103
|
+
exports.isPermissionDenied = require_errors.isPermissionDenied;
|
|
97
104
|
exports.isResource = require_transaction.isResource;
|
|
98
105
|
exports.isResourceId = require_transaction.isResourceId;
|
|
99
106
|
exports.isResourceRef = require_transaction.isResourceRef;
|
|
100
107
|
exports.isRootResourceId = require_types.isRootResourceId;
|
|
108
|
+
exports.isSignedResourceId = require_types.isSignedResourceId;
|
|
101
109
|
exports.isTimeoutError = require_errors.isTimeoutError;
|
|
102
110
|
exports.isTimeoutOrCancelError = require_errors.isTimeoutOrCancelError;
|
|
103
111
|
exports.isUnauthenticated = require_errors.isUnauthenticated;
|
|
104
112
|
exports.isUnimplementedError = require_errors.isUnimplementedError;
|
|
105
113
|
exports.jsonToData = require_types.jsonToData;
|
|
114
|
+
exports.parseResourceType = require_types.parseResourceType;
|
|
115
|
+
exports.parseSignedResourceId = require_types.parseSignedResourceId;
|
|
106
116
|
exports.plAddressToConfig = require_config.plAddressToConfig;
|
|
107
117
|
exports.poll = require_poll.poll;
|
|
108
118
|
exports.resDataToJson = require_types.resDataToJson;
|
|
@@ -112,11 +122,12 @@ exports.resourceType = require_types.resourceType;
|
|
|
112
122
|
exports.resourceTypeToString = require_types.resourceTypeToString;
|
|
113
123
|
exports.resourceTypesEqual = require_types.resourceTypesEqual;
|
|
114
124
|
exports.rethrowMeaningfulError = require_errors.rethrowMeaningfulError;
|
|
125
|
+
exports.signatureToBase64Url = require_types.signatureToBase64Url;
|
|
115
126
|
exports.stringifyWithResourceId = require_types.stringifyWithResourceId;
|
|
116
127
|
exports.throwPlNotFoundError = require_errors.throwPlNotFoundError;
|
|
117
128
|
exports.toFieldId = require_transaction.toFieldId;
|
|
118
129
|
exports.toGlobalFieldId = require_transaction.toGlobalFieldId;
|
|
119
130
|
exports.toGlobalResourceId = require_transaction.toGlobalResourceId;
|
|
120
|
-
exports.
|
|
131
|
+
exports.toResourceSignature = require_types.toResourceSignature;
|
|
121
132
|
exports.tryGetFileConfig = require_default_client.tryGetFileConfig;
|
|
122
133
|
exports.valErr = require_tx_helpers.valErr;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { AnyResourceId, BasicResourceData, FieldData, FieldStatus, FieldType, FutureFieldType, LocalResourceId, MaxLocalId, MaxTxId, NullResourceId, OptionalAnyResourceId,
|
|
1
|
+
import { AnyResourceId, BasicResourceData, ColorProof, FieldData, FieldStatus, FieldType, FutureFieldType, GlobalResourceId, LocalResourceId, MaxLocalId, MaxTxId, NullResourceId, NullSignedResourceId, OptionalAnyResourceId, OptionalSignedResourceId, ResourceData, ResourceKind, ResourceSignature, ResourceType, SignedResourceId, anyResourceIdToBigint, base64UrlToSignature, checkLocalityOfResourceId, createGlobalResourceId, createLocalResourceId, createSignedResourceId, ensureSignedResourceIdNotNull, extractBasicResourceData, extractTxId, getField, isAnyResourceId, isLocalResourceId, isNotNullSignedResourceId, isNullSignedResourceId, isRootResourceId, isSignedResourceId, jsonToData, parseResourceType, parseSignedResourceId, resDataToJson, resourceIdFromString, resourceIdToString, resourceType, resourceTypeToString, resourceTypesEqual, signatureToBase64Url, stringifyWithResourceId, toResourceSignature } from "./core/types.js";
|
|
2
2
|
import { DefaultFinalResourceDataPredicate, FinalResourceDataPredicate, ResourceTypeName, ResourceTypePrefix } from "./core/final.js";
|
|
3
|
-
import { AnyFieldId, AnyFieldRef, AnyRef, AnyResourceRef, FieldId, FieldRef, KeyValue, KeyValueString, LocalFieldId, PlTransaction, ResourceRef, TxCommitConflict, field, isField, isFieldRef, isResource, isResourceId, isResourceRef, toFieldId, toGlobalFieldId, toGlobalResourceId
|
|
3
|
+
import { AnyFieldId, AnyFieldRef, AnyRef, AnyResourceRef, FieldId, FieldRef, KeyValue, KeyValueString, LocalFieldId, PlTransaction, ResourceIdWithSignature, ResourceRef, TxCommitConflict, field, isField, isFieldRef, isResource, isResourceId, isResourceRef, toFieldId, toGlobalFieldId, toGlobalResourceId } from "./core/transaction.js";
|
|
4
4
|
import { pl_d_exports } from "./helpers/pl.js";
|
|
5
5
|
import { AnonymousAuthInformation, AuthInformation, AuthOps, DEFAULT_AUTH_MAX_REFRESH, 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_RO_TX_TIMEOUT, DEFAULT_RW_TX_TIMEOUT, DEFAULT_TOKEN_TTL_SECONDS, DefaultRetryOptions, PlClientConfig, PlConnectionStatus, PlConnectionStatusListener, SUPPORTED_WIRE_PROTOCOLS, plAddressToConfig, wireProtocol } from "./core/config.js";
|
|
6
6
|
import { GrpcConnection, RestConnection, WireClientProvider, WireClientProviderFactory, WireConnection } from "./core/wire.js";
|
|
7
7
|
import { index_d_exports } from "./proto-rest/index.js";
|
|
8
8
|
import { PlDriver, PlDriverDefinition, addRTypeToMetadata, createRTypeRoutingHeader } from "./core/driver.js";
|
|
9
|
+
import { StorageInfo, TxRunner, UserResources } from "./core/user_resources.js";
|
|
9
10
|
import { PlClient, TxOps } from "./core/client.js";
|
|
10
|
-
import { DisconnectedError, PlError, PlErrorCodeNotFound, RESTError, RecoverablePlError, UnauthenticatedError, UnrecoverablePlError, isAbortedError, isCancelError, isConnectionProblem, isNotFoundError, isTimeoutError, isTimeoutOrCancelError, isUnauthenticated, isUnimplementedError, rethrowMeaningfulError, throwPlNotFoundError } from "./core/errors.js";
|
|
11
|
+
import { DisconnectedError, PermissionDeniedError, PlError, PlErrorCodeNotFound, RESTError, RecoverablePlError, UnauthenticatedError, UnrecoverablePlError, isAbortedError, isCancelError, isConnectionProblem, isNotFoundError, isPermissionDenied, isTimeoutError, isTimeoutOrCancelError, isUnauthenticated, isUnimplementedError, rethrowMeaningfulError, throwPlNotFoundError } from "./core/errors.js";
|
|
11
12
|
import { defaultPlClient, tryGetFileConfig } from "./core/default_client.js";
|
|
12
13
|
import { UnauthenticatedPlClient } from "./core/unauth_client.js";
|
|
13
14
|
import { expirationFromAuthInformation, inferAuthRefreshTime } from "./core/auth.js";
|
|
14
15
|
import { ValErr, valErr } from "./helpers/tx_helpers.js";
|
|
15
16
|
import { ContinuePolling, DefaultPollingRetryOptions, PollFieldTraverseOps, PollResourceAccessor, PollTxAccessor, poll } from "./helpers/poll.js";
|
|
16
17
|
import { test_config_d_exports } from "./test/test_config.js";
|
|
17
|
-
export { AnonymousAuthInformation, AnyFieldId, AnyFieldRef, AnyRef, AnyResourceId, AnyResourceRef, AuthInformation, AuthOps, BasicResourceData, ContinuePolling, DEFAULT_AUTH_MAX_REFRESH, 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_RO_TX_TIMEOUT, DEFAULT_RW_TX_TIMEOUT, DEFAULT_TOKEN_TTL_SECONDS, DefaultFinalResourceDataPredicate, DefaultPollingRetryOptions, DefaultRetryOptions, DisconnectedError, FieldData, FieldId, FieldRef, FieldStatus, FieldType, FinalResourceDataPredicate, FutureFieldType, GrpcConnection, KeyValue, KeyValueString, LocalFieldId, LocalResourceId, MaxLocalId, MaxTxId, NullResourceId, OptionalAnyResourceId,
|
|
18
|
+
export { AnonymousAuthInformation, AnyFieldId, AnyFieldRef, AnyRef, AnyResourceId, AnyResourceRef, AuthInformation, AuthOps, BasicResourceData, ColorProof, ContinuePolling, DEFAULT_AUTH_MAX_REFRESH, 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_RO_TX_TIMEOUT, DEFAULT_RW_TX_TIMEOUT, DEFAULT_TOKEN_TTL_SECONDS, DefaultFinalResourceDataPredicate, DefaultPollingRetryOptions, DefaultRetryOptions, DisconnectedError, FieldData, FieldId, FieldRef, FieldStatus, FieldType, FinalResourceDataPredicate, FutureFieldType, GlobalResourceId, GrpcConnection, KeyValue, KeyValueString, LocalFieldId, LocalResourceId, MaxLocalId, MaxTxId, NullResourceId, NullSignedResourceId, OptionalAnyResourceId, OptionalSignedResourceId, PermissionDeniedError, pl_d_exports as Pl, PlClient, PlClientConfig, PlConnectionStatus, PlConnectionStatusListener, PlDriver, PlDriverDefinition, PlError, PlErrorCodeNotFound, PlTransaction, PollFieldTraverseOps, PollResourceAccessor, PollTxAccessor, RESTError, RecoverablePlError, ResourceData, ResourceIdWithSignature, ResourceKind, ResourceRef, ResourceSignature, ResourceType, ResourceTypeName, ResourceTypePrefix, index_d_exports as RestAPI, RestConnection, SUPPORTED_WIRE_PROTOCOLS, SignedResourceId, StorageInfo, test_config_d_exports as TestHelpers, TxCommitConflict, TxOps, TxRunner, UnauthenticatedError, UnauthenticatedPlClient, UnrecoverablePlError, UserResources, ValErr, WireClientProvider, WireClientProviderFactory, WireConnection, addRTypeToMetadata, anyResourceIdToBigint, base64UrlToSignature, checkLocalityOfResourceId, createGlobalResourceId, createLocalResourceId, createRTypeRoutingHeader, createSignedResourceId, defaultPlClient, ensureSignedResourceIdNotNull, expirationFromAuthInformation, extractBasicResourceData, extractTxId, field, getField, inferAuthRefreshTime, isAbortedError, isAnyResourceId, isCancelError, isConnectionProblem, isField, isFieldRef, isLocalResourceId, isNotFoundError, isNotNullSignedResourceId, isNullSignedResourceId, isPermissionDenied, isResource, isResourceId, isResourceRef, isRootResourceId, isSignedResourceId, isTimeoutError, isTimeoutOrCancelError, isUnauthenticated, isUnimplementedError, jsonToData, parseResourceType, parseSignedResourceId, plAddressToConfig, poll, resDataToJson, resourceIdFromString, resourceIdToString, resourceType, resourceTypeToString, resourceTypesEqual, rethrowMeaningfulError, signatureToBase64Url, stringifyWithResourceId, throwPlNotFoundError, toFieldId, toGlobalFieldId, toGlobalResourceId, toResourceSignature, tryGetFileConfig, valErr, wireProtocol };
|