@ariestools/aries-datalake-client 0.1.19 → 0.1.21
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/README.md +126 -1
- package/dist/browser/CompositePayloadsClient.d.ts +91 -0
- package/dist/browser/CompositePayloadsClient.d.ts.map +1 -0
- package/dist/browser/PayloadsClient.d.ts.map +1 -1
- package/dist/browser/RestPublicPayloadsReader.d.ts +38 -0
- package/dist/browser/RestPublicPayloadsReader.d.ts.map +1 -0
- package/dist/browser/browser.d.ts +4 -0
- package/dist/browser/browser.d.ts.map +1 -1
- package/dist/browser/browser.mjs +354 -19
- package/dist/browser/browser.mjs.map +4 -4
- package/dist/node/CompositePayloadsClient.d.ts +91 -0
- package/dist/node/CompositePayloadsClient.d.ts.map +1 -0
- package/dist/node/LocalDatalakeClient.d.ts.map +1 -1
- package/dist/node/PayloadsClient.d.ts.map +1 -1
- package/dist/node/RestPublicPayloadsReader.d.ts +38 -0
- package/dist/node/RestPublicPayloadsReader.d.ts.map +1 -0
- package/dist/node/browser.d.ts +4 -0
- package/dist/node/browser.d.ts.map +1 -1
- package/dist/node/defaultDatalake.d.ts.map +1 -1
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.mjs +363 -21
- package/dist/node/index.mjs.map +4 -4
- package/dist/node/payloadRequest.d.ts +11 -0
- package/dist/node/payloadRequest.d.ts.map +1 -0
- package/package.json +17 -14
package/dist/node/index.mjs
CHANGED
|
@@ -1,3 +1,252 @@
|
|
|
1
|
+
// src/CompositePayloadsClient.ts
|
|
2
|
+
var CompositePayloadsWriteError = class extends Error {
|
|
3
|
+
result;
|
|
4
|
+
constructor(result) {
|
|
5
|
+
super("Required datalake writes did not complete");
|
|
6
|
+
this.name = "CompositePayloadsWriteError";
|
|
7
|
+
this.result = result;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var CompositePayloadsReadError = class extends Error {
|
|
11
|
+
result;
|
|
12
|
+
constructor(result) {
|
|
13
|
+
super("Datalake read could not be verified");
|
|
14
|
+
this.name = "CompositePayloadsReadError";
|
|
15
|
+
this.result = result;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var CompositePayloadsClient = class {
|
|
19
|
+
identify;
|
|
20
|
+
targets;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
if (typeof options.identify !== "function") throw new TypeError("Canonical payload identity is required");
|
|
23
|
+
if (options.targets.length === 0) throw new TypeError("At least one datalake target is required");
|
|
24
|
+
const names = /* @__PURE__ */ new Set();
|
|
25
|
+
this.targets = options.targets.map((target) => {
|
|
26
|
+
if (!/^[a-z0-9][a-z0-9._-]{0,63}$/i.test(target.name) || names.has(target.name)) {
|
|
27
|
+
throw new TypeError("Datalake target names must be unique non-secret identifiers");
|
|
28
|
+
}
|
|
29
|
+
names.add(target.name);
|
|
30
|
+
return { ...target, policy: snapshotPolicy(target.policy) };
|
|
31
|
+
});
|
|
32
|
+
this.identify = options.identify;
|
|
33
|
+
}
|
|
34
|
+
/** Missing hashes fall through in target order. Provider errors and corruption fail explicitly. */
|
|
35
|
+
async get(hashes) {
|
|
36
|
+
return (await this.getWithReceipts(hashes)).payloads;
|
|
37
|
+
}
|
|
38
|
+
async getMany(hashes) {
|
|
39
|
+
return await this.get(hashes);
|
|
40
|
+
}
|
|
41
|
+
async getWithReceipts(hashes) {
|
|
42
|
+
const requested = [...new Set(hashes)];
|
|
43
|
+
if (requested.some((hash) => typeof hash !== "string" || hash.length === 0)) throw new TypeError("Hashes must be non-empty strings");
|
|
44
|
+
const found = /* @__PURE__ */ new Map();
|
|
45
|
+
const result = {
|
|
46
|
+
payloads: [],
|
|
47
|
+
receipts: [],
|
|
48
|
+
sources: {}
|
|
49
|
+
};
|
|
50
|
+
for (const target of this.targets) {
|
|
51
|
+
const remaining = requested.filter((hash) => !found.has(hash));
|
|
52
|
+
if (remaining.length === 0) break;
|
|
53
|
+
const receipt = {
|
|
54
|
+
target: target.name,
|
|
55
|
+
requested: remaining,
|
|
56
|
+
found: []
|
|
57
|
+
};
|
|
58
|
+
result.receipts.push(receipt);
|
|
59
|
+
let response;
|
|
60
|
+
try {
|
|
61
|
+
response = await target.client.getMany([...remaining]);
|
|
62
|
+
} catch {
|
|
63
|
+
receipt.error = "provider_error";
|
|
64
|
+
throw new CompositePayloadsReadError(result);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const verified = await this.verify(response, new Set(remaining));
|
|
68
|
+
for (const payload of verified.values()) {
|
|
69
|
+
found.set(payload._hash, payload);
|
|
70
|
+
result.sources[payload._hash] = target.name;
|
|
71
|
+
receipt.found.push(payload._hash);
|
|
72
|
+
}
|
|
73
|
+
result.payloads = requested.flatMap((hash) => found.has(hash) ? [found.get(hash)] : []);
|
|
74
|
+
} catch {
|
|
75
|
+
receipt.error = "invalid_response";
|
|
76
|
+
throw new CompositePayloadsReadError(result);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/** Payload-array acknowledgment suitable for consumers of insert/get method contracts. */
|
|
82
|
+
async insert(payloads) {
|
|
83
|
+
return (await this.insertWithReceipts(payloads)).acknowledged;
|
|
84
|
+
}
|
|
85
|
+
async insertWithReceipts(payloads) {
|
|
86
|
+
const snapshots = payloads.map(snapshotPayload);
|
|
87
|
+
const prepared = [];
|
|
88
|
+
const seen = /* @__PURE__ */ new Set();
|
|
89
|
+
const encoder = new TextEncoder();
|
|
90
|
+
for (const payload of snapshots) {
|
|
91
|
+
const { hash } = await this.identify(payload);
|
|
92
|
+
requireHash(hash);
|
|
93
|
+
if (!seen.has(hash)) {
|
|
94
|
+
prepared.push({
|
|
95
|
+
payload,
|
|
96
|
+
hash,
|
|
97
|
+
bytes: encoder.encode(JSON.stringify(payload)).byteLength
|
|
98
|
+
});
|
|
99
|
+
seen.add(hash);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const writes = this.targets.map((target) => prepareWrite(target, prepared));
|
|
103
|
+
const outcomes = await Promise.all(writes.map((write) => this.writeTarget(write)));
|
|
104
|
+
const acknowledged = /* @__PURE__ */ new Map();
|
|
105
|
+
for (const outcome of outcomes) {
|
|
106
|
+
for (const payload of outcome.acknowledged) acknowledged.set(payload._hash, payload);
|
|
107
|
+
}
|
|
108
|
+
const result = {
|
|
109
|
+
acknowledged: prepared.flatMap(({ hash }) => acknowledged.has(hash) ? [acknowledged.get(hash)] : []),
|
|
110
|
+
receipts: writes.map((write) => write.receipt)
|
|
111
|
+
};
|
|
112
|
+
if (result.receipts.some((receipt) => receipt.status === "failed")) throw new CompositePayloadsWriteError(result);
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
async verify(payloads, expected) {
|
|
116
|
+
if (!Array.isArray(payloads)) throw new TypeError("Expected payload array");
|
|
117
|
+
const snapshots = payloads.map((payload) => {
|
|
118
|
+
if (typeof payload?._sequence !== "string" || payload._sequence.length === 0) throw new TypeError("Missing storage sequence");
|
|
119
|
+
return {
|
|
120
|
+
...snapshotPayload(payload),
|
|
121
|
+
_hash: payload._hash,
|
|
122
|
+
_dataHash: payload._dataHash,
|
|
123
|
+
_sequence: payload._sequence
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
const verified = /* @__PURE__ */ new Map();
|
|
127
|
+
for (const payload of snapshots) {
|
|
128
|
+
const identity = await this.identify(snapshotPayload(payload));
|
|
129
|
+
if (identity.hash !== payload._hash || identity.dataHash !== payload._dataHash || !expected.has(identity.hash)) {
|
|
130
|
+
throw new TypeError("Unexpected payload identity");
|
|
131
|
+
}
|
|
132
|
+
verified.set(identity.hash, payload);
|
|
133
|
+
}
|
|
134
|
+
return verified;
|
|
135
|
+
}
|
|
136
|
+
async writeTarget({
|
|
137
|
+
target,
|
|
138
|
+
payloads,
|
|
139
|
+
receipt
|
|
140
|
+
}) {
|
|
141
|
+
const result = { acknowledged: [], receipts: [receipt] };
|
|
142
|
+
if (payloads.length === 0) return result;
|
|
143
|
+
let response;
|
|
144
|
+
try {
|
|
145
|
+
response = await target.client.insert(payloads.map((item) => snapshotPayload(item.payload)));
|
|
146
|
+
} catch {
|
|
147
|
+
receipt.status = "failed";
|
|
148
|
+
receipt.error = "provider_error";
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
await this.verify(response.inserted, new Set(receipt.eligible));
|
|
153
|
+
if (!Array.isArray(response.summary.rejected) || response.summary.rejected.some((hash) => !receipt.eligible.includes(hash))) {
|
|
154
|
+
throw new TypeError("Unexpected rejected hashes");
|
|
155
|
+
}
|
|
156
|
+
receipt.rejected = [...new Set(response.summary.rejected)];
|
|
157
|
+
} catch {
|
|
158
|
+
receipt.status = "failed";
|
|
159
|
+
receipt.error = "invalid_response";
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
let readback;
|
|
163
|
+
try {
|
|
164
|
+
readback = await target.client.getMany([...receipt.eligible]);
|
|
165
|
+
} catch {
|
|
166
|
+
receipt.status = "failed";
|
|
167
|
+
receipt.error = "provider_error";
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const verified = await this.verify(readback, new Set(receipt.eligible));
|
|
172
|
+
result.acknowledged = receipt.eligible.flatMap((hash) => verified.has(hash) ? [verified.get(hash)] : []);
|
|
173
|
+
receipt.acknowledged = result.acknowledged.map((payload) => payload._hash);
|
|
174
|
+
if (receipt.rejected.length > 0 || verified.size !== receipt.eligible.length) {
|
|
175
|
+
receipt.status = "failed";
|
|
176
|
+
receipt.error = receipt.rejected.length > 0 ? "policy_rejected" : "incomplete_readback";
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
receipt.status = "failed";
|
|
180
|
+
receipt.error = "invalid_response";
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
function snapshotPolicy(policy) {
|
|
186
|
+
if (!policy || policy.mode !== "all" && policy.mode !== "selected") throw new TypeError("Explicit datalake policy is required");
|
|
187
|
+
if (policy.mode === "selected" && (!Array.isArray(policy.allowedSchemas) || policy.maxPayloadBytes === void 0)) {
|
|
188
|
+
throw new TypeError("Selected datalakes require an allowlist and byte limit");
|
|
189
|
+
}
|
|
190
|
+
for (const schemas of [policy.allowedSchemas, policy.disallowedSchemas]) {
|
|
191
|
+
if (schemas !== void 0 && (!Array.isArray(schemas) || schemas.some((schema) => typeof schema !== "string" || schema.length === 0))) {
|
|
192
|
+
throw new TypeError("Schema lists must contain non-empty identifiers");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const limit of [policy.maxPayloadBytes, ...Object.values(policy.schemaMaxPayloadBytes ?? {})]) {
|
|
196
|
+
if (limit !== void 0 && (!Number.isSafeInteger(limit) || limit <= 0)) throw new RangeError("Payload byte limits must be positive safe integers");
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
...policy,
|
|
200
|
+
allowedSchemas: policy.allowedSchemas === void 0 ? void 0 : [...policy.allowedSchemas],
|
|
201
|
+
disallowedSchemas: policy.disallowedSchemas === void 0 ? void 0 : [...policy.disallowedSchemas],
|
|
202
|
+
schemaMaxPayloadBytes: { ...policy.schemaMaxPayloadBytes }
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function prepareWrite(target, payloads) {
|
|
206
|
+
const selected = [];
|
|
207
|
+
const excluded = [];
|
|
208
|
+
for (const item of payloads) {
|
|
209
|
+
const reason = exclusionReason(target.policy, item);
|
|
210
|
+
if (reason) excluded.push({ hash: item.hash, reason });
|
|
211
|
+
else selected.push(item);
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
target,
|
|
215
|
+
payloads: selected,
|
|
216
|
+
receipt: {
|
|
217
|
+
target: target.name,
|
|
218
|
+
policyRevision: target.policy.revision,
|
|
219
|
+
eligible: selected.map((item) => item.hash),
|
|
220
|
+
excluded,
|
|
221
|
+
acknowledged: [],
|
|
222
|
+
rejected: [],
|
|
223
|
+
status: selected.length > 0 ? "complete" : "excluded"
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function exclusionReason(policy, item) {
|
|
228
|
+
const { schema } = item.payload;
|
|
229
|
+
if (policy.allowedSchemas !== void 0 && !policy.allowedSchemas.includes(schema) || policy.disallowedSchemas?.includes(schema)) return "schema";
|
|
230
|
+
const schemaLimit = policy.schemaMaxPayloadBytes && Object.hasOwn(policy.schemaMaxPayloadBytes, schema) ? policy.schemaMaxPayloadBytes[schema] : void 0;
|
|
231
|
+
const limit = Math.min(policy.maxPayloadBytes ?? Infinity, schemaLimit ?? Infinity);
|
|
232
|
+
if (item.bytes > limit) return "size";
|
|
233
|
+
if (policy.isValid && !policy.isValid(snapshotPayload(item.payload))) return "validation";
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
function snapshotPayload(payload) {
|
|
237
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload) || typeof payload.schema !== "string" || payload.schema.length === 0) {
|
|
238
|
+
throw new TypeError("Expected flat schema-bearing payloads");
|
|
239
|
+
}
|
|
240
|
+
const stripped = Object.fromEntries(Object.entries(payload).filter(([key]) => !key.startsWith("_")));
|
|
241
|
+
const serialized = JSON.stringify(stripped);
|
|
242
|
+
const copy = JSON.parse(serialized);
|
|
243
|
+
if (copy.schema !== payload.schema) throw new TypeError("Payload serialization changed its schema");
|
|
244
|
+
return copy;
|
|
245
|
+
}
|
|
246
|
+
function requireHash(hash) {
|
|
247
|
+
if (typeof hash !== "string" || hash.length === 0) throw new TypeError("Canonical payload identity returned an invalid hash");
|
|
248
|
+
}
|
|
249
|
+
|
|
1
250
|
// src/credentials.ts
|
|
2
251
|
import {
|
|
3
252
|
chmodSync,
|
|
@@ -110,7 +359,8 @@ var LocalDatalakeClient = class {
|
|
|
110
359
|
if (store.datalakes.some((dl) => dl.name === request.name)) {
|
|
111
360
|
throw new Error(`Datalake already exists: ${request.name}`);
|
|
112
361
|
}
|
|
113
|
-
const
|
|
362
|
+
const nowDate = /* @__PURE__ */ new Date();
|
|
363
|
+
const now = nowDate.toISOString();
|
|
114
364
|
const tier = request.config.tier;
|
|
115
365
|
const descriptor = {
|
|
116
366
|
id: generateId(),
|
|
@@ -157,10 +407,11 @@ var LocalDatalakeClient = class {
|
|
|
157
407
|
const store = readStore();
|
|
158
408
|
const datalake = requireDatalake(store, request.datalakeId);
|
|
159
409
|
const existing = datalake.acl.findIndex((entry2) => entry2.principal === request.principal);
|
|
410
|
+
const grantedAtDate = /* @__PURE__ */ new Date();
|
|
160
411
|
const entry = {
|
|
161
412
|
principal: request.principal,
|
|
162
413
|
role: request.role,
|
|
163
|
-
grantedAt:
|
|
414
|
+
grantedAt: grantedAtDate.toISOString(),
|
|
164
415
|
grantedBy: LOCAL_OWNER_ID
|
|
165
416
|
};
|
|
166
417
|
if (existing === -1) {
|
|
@@ -186,11 +437,12 @@ var LocalDatalakeClient = class {
|
|
|
186
437
|
exp: Math.floor(Date.now() / 1e3) + ttl
|
|
187
438
|
})
|
|
188
439
|
).toString("base64url");
|
|
440
|
+
const expiresAtDate = new Date(Date.now() + ttl * 1e3);
|
|
189
441
|
return {
|
|
190
442
|
token: `local.${issued}`,
|
|
191
443
|
datalakeId: datalake.id,
|
|
192
444
|
role: request.role,
|
|
193
|
-
expiresAt:
|
|
445
|
+
expiresAt: expiresAtDate.toISOString(),
|
|
194
446
|
url: datalake.url ?? `http://localhost:8080/datalakes/${datalake.name}`
|
|
195
447
|
};
|
|
196
448
|
}
|
|
@@ -198,7 +450,8 @@ var LocalDatalakeClient = class {
|
|
|
198
450
|
const store = readStore();
|
|
199
451
|
const datalake = requireDatalake(store, request.datalakeId);
|
|
200
452
|
datalake.acl = datalake.acl.filter((entry) => entry.principal !== request.principal);
|
|
201
|
-
|
|
453
|
+
const updatedAtDate = /* @__PURE__ */ new Date();
|
|
454
|
+
datalake.updatedAt = updatedAtDate.toISOString();
|
|
202
455
|
writeStore(store);
|
|
203
456
|
return datalake;
|
|
204
457
|
}
|
|
@@ -337,10 +590,11 @@ import {
|
|
|
337
590
|
function setDefaultDatalake(name, id) {
|
|
338
591
|
const home = getAriesHome();
|
|
339
592
|
if (!existsSync3(home)) mkdirSync3(home, { recursive: true });
|
|
593
|
+
const setAtDate = /* @__PURE__ */ new Date();
|
|
340
594
|
const payload = {
|
|
341
595
|
name,
|
|
342
596
|
id,
|
|
343
|
-
setAt:
|
|
597
|
+
setAt: setAtDate.toISOString()
|
|
344
598
|
};
|
|
345
599
|
writeFileSync3(getDefaultDatalakePath(), JSON.stringify(payload, void 0, 2), "utf8");
|
|
346
600
|
}
|
|
@@ -362,11 +616,9 @@ function clearDefaultDatalake() {
|
|
|
362
616
|
|
|
363
617
|
// src/PayloadsClient.ts
|
|
364
618
|
import {
|
|
365
|
-
DATALAKE_API_VERSION,
|
|
366
619
|
DATALAKE_HEADER_DUPLICATES,
|
|
367
620
|
DATALAKE_HEADER_NEXT_CURSOR,
|
|
368
621
|
DATALAKE_HEADER_REJECTED,
|
|
369
|
-
DatalakeApiError as DatalakeApiError2,
|
|
370
622
|
datalakePlaneClearPath,
|
|
371
623
|
datalakePlaneDeletePath,
|
|
372
624
|
datalakePlaneGetManyPath,
|
|
@@ -375,6 +627,9 @@ import {
|
|
|
375
627
|
datalakePlaneNextPath,
|
|
376
628
|
datalakePlaneUsagePath
|
|
377
629
|
} from "@ariestools/aries-datalake-core/browser";
|
|
630
|
+
|
|
631
|
+
// src/payloadRequest.ts
|
|
632
|
+
import { DATALAKE_API_VERSION, DatalakeApiError as DatalakeApiError2 } from "@ariestools/aries-datalake-core/browser";
|
|
378
633
|
function extractRequestBase(urlWithPossiblePath) {
|
|
379
634
|
try {
|
|
380
635
|
const parsed = new URL(urlWithPossiblePath);
|
|
@@ -386,6 +641,24 @@ function extractRequestBase(urlWithPossiblePath) {
|
|
|
386
641
|
return urlWithPossiblePath.replace(/\/$/, "");
|
|
387
642
|
}
|
|
388
643
|
}
|
|
644
|
+
function parsePayloadResponse(response, text, method) {
|
|
645
|
+
const payload = text.length > 0 ? JSON.parse(text) : void 0;
|
|
646
|
+
if (!response.ok) {
|
|
647
|
+
const errorBody = isApiErrorBody2(payload) ? payload : {
|
|
648
|
+
code: "internal",
|
|
649
|
+
message: "Unexpected " + response.status + " response from " + method + " data plane"
|
|
650
|
+
};
|
|
651
|
+
throw new DatalakeApiError2(response.status, errorBody);
|
|
652
|
+
}
|
|
653
|
+
return payload;
|
|
654
|
+
}
|
|
655
|
+
function isApiErrorBody2(value) {
|
|
656
|
+
if (typeof value !== "object" || value === null) return false;
|
|
657
|
+
const maybe = value;
|
|
658
|
+
return typeof maybe.code === "string" && typeof maybe.message === "string";
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// src/PayloadsClient.ts
|
|
389
662
|
var RestPayloadsClient = class {
|
|
390
663
|
authToken;
|
|
391
664
|
datalakeId;
|
|
@@ -469,20 +742,12 @@ var RestPayloadsClient = class {
|
|
|
469
742
|
const response = await this.fetchImpl(`${this.requestBase}${path4}`, init);
|
|
470
743
|
if (response.status === 204) return { data: void 0, headers: response.headers };
|
|
471
744
|
const text = await response.text();
|
|
472
|
-
|
|
473
|
-
if (!response.ok) {
|
|
474
|
-
const errorBody = isApiErrorBody2(payload) ? payload : {
|
|
475
|
-
code: "internal",
|
|
476
|
-
message: `Unexpected ${response.status} response from ${method} data plane`
|
|
477
|
-
};
|
|
478
|
-
throw new DatalakeApiError2(response.status, errorBody);
|
|
479
|
-
}
|
|
480
|
-
return { data: payload, headers: response.headers };
|
|
745
|
+
return { data: parsePayloadResponse(response, text, method), headers: response.headers };
|
|
481
746
|
}
|
|
482
747
|
};
|
|
483
748
|
function readInsertSummary(headers) {
|
|
484
749
|
const duplicatesRaw = headers.get(DATALAKE_HEADER_DUPLICATES);
|
|
485
|
-
const duplicates = duplicatesRaw === null ? 0 :
|
|
750
|
+
const duplicates = duplicatesRaw === null ? 0 : Math.trunc(Number(duplicatesRaw));
|
|
486
751
|
const rejectedRaw = headers.get(DATALAKE_HEADER_REJECTED);
|
|
487
752
|
const rejected = rejectedRaw === null || rejectedRaw.length === 0 ? [] : rejectedRaw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
488
753
|
return {
|
|
@@ -490,15 +755,92 @@ function readInsertSummary(headers) {
|
|
|
490
755
|
rejected
|
|
491
756
|
};
|
|
492
757
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
758
|
+
|
|
759
|
+
// src/RestPublicPayloadsReader.ts
|
|
760
|
+
import { datalakePlaneGetManyPath as datalakePlaneGetManyPath2, datalakePlaneGetPath as datalakePlaneGetPath2 } from "@ariestools/aries-datalake-core/browser";
|
|
761
|
+
import { readResponseText } from "@ariestools/sdk/fetch";
|
|
762
|
+
var RestPublicPayloadsReader = class {
|
|
763
|
+
datalakeId;
|
|
764
|
+
fetchImpl;
|
|
765
|
+
requestBase;
|
|
766
|
+
constructor(options) {
|
|
767
|
+
this.requestBase = publicRequestBase(options.baseUrl);
|
|
768
|
+
this.datalakeId = options.datalakeId;
|
|
769
|
+
this.fetchImpl = options.fetchImpl;
|
|
770
|
+
}
|
|
771
|
+
async get(hash, options = {}) {
|
|
772
|
+
const payload = await this.request(datalakePlaneGetPath2(this.datalakeId, hash), options);
|
|
773
|
+
if (!isStoredPayload(payload)) throw new TypeError("Data plane returned an invalid stored payload");
|
|
774
|
+
return payload;
|
|
775
|
+
}
|
|
776
|
+
async getMany(hashes, options = {}) {
|
|
777
|
+
const policy = pinReadOptions(options);
|
|
778
|
+
const requested = [...hashes];
|
|
779
|
+
if (requested.length === 0) return [];
|
|
780
|
+
const payloads = await this.request(datalakePlaneGetManyPath2(this.datalakeId), policy, requested);
|
|
781
|
+
if (!Array.isArray(payloads) || !payloads.every(isStoredPayload)) {
|
|
782
|
+
throw new TypeError("Data plane returned an invalid stored-payload array");
|
|
783
|
+
}
|
|
784
|
+
return payloads;
|
|
785
|
+
}
|
|
786
|
+
async request(path4, options, hashes) {
|
|
787
|
+
const { maxResponseBytes, signal } = pinReadOptions(options);
|
|
788
|
+
const method = hashes === void 0 ? "GET" : "POST";
|
|
789
|
+
const headers = { accept: "application/json" };
|
|
790
|
+
const init = {
|
|
791
|
+
credentials: "omit",
|
|
792
|
+
headers,
|
|
793
|
+
method,
|
|
794
|
+
redirect: "error",
|
|
795
|
+
signal
|
|
796
|
+
};
|
|
797
|
+
if (hashes !== void 0) {
|
|
798
|
+
headers["content-type"] = "application/json";
|
|
799
|
+
init.body = JSON.stringify(hashes);
|
|
800
|
+
}
|
|
801
|
+
const fetchImpl = this.fetchImpl ?? globalThis.fetch;
|
|
802
|
+
const response = await fetchImpl(this.requestBase + path4, init);
|
|
803
|
+
const text = await readResponseText(response, { maxResponseBytes, signal });
|
|
804
|
+
return parsePayloadResponse(response, text, method);
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
function pinReadOptions(options) {
|
|
808
|
+
const { maxResponseBytes, signal } = options;
|
|
809
|
+
if (maxResponseBytes !== void 0 && (!Number.isSafeInteger(maxResponseBytes) || maxResponseBytes <= 0)) {
|
|
810
|
+
throw new RangeError("maxResponseBytes must be a positive safe integer");
|
|
811
|
+
}
|
|
812
|
+
signal?.throwIfAborted();
|
|
813
|
+
return { maxResponseBytes, signal };
|
|
814
|
+
}
|
|
815
|
+
function publicRequestBase(baseUrl) {
|
|
816
|
+
let parsed;
|
|
817
|
+
try {
|
|
818
|
+
parsed = new URL(baseUrl);
|
|
819
|
+
} catch {
|
|
820
|
+
throw new TypeError("baseUrl must be an absolute HTTP(S) URL");
|
|
821
|
+
}
|
|
822
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
823
|
+
throw new TypeError("baseUrl must be an absolute HTTP(S) URL");
|
|
824
|
+
}
|
|
825
|
+
if (parsed.username !== "" || parsed.password !== "") {
|
|
826
|
+
throw new TypeError("Public data-plane URLs must not contain credentials");
|
|
827
|
+
}
|
|
828
|
+
if (parsed.href.includes("#")) throw new TypeError("Public data-plane URLs must not contain fragments");
|
|
829
|
+
return extractRequestBase(baseUrl);
|
|
830
|
+
}
|
|
831
|
+
function isStoredPayload(value) {
|
|
832
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
833
|
+
const payload = value;
|
|
834
|
+
return ["schema", "_hash", "_dataHash", "_sequence"].every((key) => Object.hasOwn(payload, key) && typeof payload[key] === "string");
|
|
497
835
|
}
|
|
498
836
|
export {
|
|
837
|
+
CompositePayloadsClient,
|
|
838
|
+
CompositePayloadsReadError,
|
|
839
|
+
CompositePayloadsWriteError,
|
|
499
840
|
LocalDatalakeClient,
|
|
500
841
|
RestDatalakeClient,
|
|
501
842
|
RestPayloadsClient,
|
|
843
|
+
RestPublicPayloadsReader,
|
|
502
844
|
clearCredentials,
|
|
503
845
|
clearDefaultDatalake,
|
|
504
846
|
createDatalakeClient,
|