@form-engine-ts/storage-azure-table 2.7.0 → 2.8.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/README.md +5 -0
- package/dist/index.cjs +146 -0
- package/dist/index.js +146 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,3 +35,8 @@ unsupported expressions remain client-filtered with identical semantics.
|
|
|
35
35
|
to fill the requested logical page after client-side filtering. `buildSubmissionFilter` can replace filter generation.
|
|
36
36
|
The deprecated `client`, `submissionCodec`, and `toODataFilter` options remain available for compatibility. The caller
|
|
37
37
|
owns table creation, credentials, retries, and client lifecycle.
|
|
38
|
+
|
|
39
|
+
`listTextAnswerPage` accepts either the legacy single field ID or `TextAnswerPageQueryOptions.fieldIds`. Page size counts
|
|
40
|
+
emitted text items rather than entities. Its opaque Base64 JSON cursor retains the Azure continuation token plus entity
|
|
41
|
+
and field indexes, so a page can resume inside a multi-answer entity without gaps or duplicates. Empty answers do not
|
|
42
|
+
consume the item limit, and scanning remains bounded by `maxScanPages`.
|
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,70 @@ __export(index_exports, {
|
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
29
|
var import_core = require("@form-engine-ts/core");
|
|
30
|
+
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
31
|
+
function encodeBase64(bytes) {
|
|
32
|
+
let result = "";
|
|
33
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
34
|
+
const first = bytes[index] ?? 0;
|
|
35
|
+
const second = bytes[index + 1] ?? 0;
|
|
36
|
+
const third = bytes[index + 2] ?? 0;
|
|
37
|
+
const combined = first << 16 | second << 8 | third;
|
|
38
|
+
result += BASE64_ALPHABET[combined >> 18 & 63] ?? "";
|
|
39
|
+
result += BASE64_ALPHABET[combined >> 12 & 63] ?? "";
|
|
40
|
+
result += index + 1 < bytes.length ? BASE64_ALPHABET[combined >> 6 & 63] ?? "" : "=";
|
|
41
|
+
result += index + 2 < bytes.length ? BASE64_ALPHABET[combined & 63] ?? "" : "=";
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
function decodeBase64(value) {
|
|
46
|
+
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
|
|
47
|
+
throw new TypeError("cursor must be a valid Base64 token.");
|
|
48
|
+
}
|
|
49
|
+
const bytes = [];
|
|
50
|
+
for (let index = 0; index < value.length; index += 4) {
|
|
51
|
+
const characters = value.slice(index, index + 4);
|
|
52
|
+
const sextets = [...characters].map((character) => character === "=" ? 0 : BASE64_ALPHABET.indexOf(character));
|
|
53
|
+
const combined = (sextets[0] ?? 0) << 18 | (sextets[1] ?? 0) << 12 | (sextets[2] ?? 0) << 6 | (sextets[3] ?? 0);
|
|
54
|
+
bytes.push(combined >> 16 & 255);
|
|
55
|
+
if (characters[2] !== "=") bytes.push(combined >> 8 & 255);
|
|
56
|
+
if (characters[3] !== "=") bytes.push(combined & 255);
|
|
57
|
+
}
|
|
58
|
+
return new Uint8Array(bytes);
|
|
59
|
+
}
|
|
60
|
+
function encodeAzureTextAnswerCursor(value) {
|
|
61
|
+
return encodeBase64(new TextEncoder().encode(JSON.stringify(value)));
|
|
62
|
+
}
|
|
63
|
+
function decodeAzureTextAnswerCursor(cursor) {
|
|
64
|
+
try {
|
|
65
|
+
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(decodeBase64(cursor)));
|
|
66
|
+
if (!isRecord(value) || value.tableContinuationToken !== null && typeof value.tableContinuationToken !== "string" || !Number.isSafeInteger(value.entityIndex) || value.entityIndex < 0 || !Number.isSafeInteger(value.fieldIndex) || value.fieldIndex < 0) {
|
|
67
|
+
throw new TypeError("Azure text answer cursor payload is invalid.");
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
tableContinuationToken: value.tableContinuationToken,
|
|
71
|
+
entityIndex: value.entityIndex,
|
|
72
|
+
fieldIndex: value.fieldIndex
|
|
73
|
+
};
|
|
74
|
+
} catch (cause) {
|
|
75
|
+
if (cause instanceof TypeError && cause.message === "Azure text answer cursor payload is invalid.") throw cause;
|
|
76
|
+
throw new TypeError("cursor must be a valid Azure text answer cursor.", { cause });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function textAnswerQuery(fieldIdOrOptions, options) {
|
|
80
|
+
const query = typeof fieldIdOrOptions === "string" ? options ?? {} : fieldIdOrOptions ?? {};
|
|
81
|
+
const requested = typeof fieldIdOrOptions === "string" ? [fieldIdOrOptions] : query.fieldIds;
|
|
82
|
+
if (requested?.some((fieldId) => fieldId.trim().length === 0)) {
|
|
83
|
+
throw new TypeError("fieldIds must not contain empty values.");
|
|
84
|
+
}
|
|
85
|
+
const fieldIds = requested === void 0 ? void 0 : [...new Set(requested)];
|
|
86
|
+
return { query, ...fieldIds === void 0 ? {} : { fieldIds } };
|
|
87
|
+
}
|
|
88
|
+
function submissionTextAnswers(submission, fieldIds) {
|
|
89
|
+
const entries = fieldIds === void 0 ? Object.entries(submission.values) : fieldIds.map((id) => [id, submission.values[id]]);
|
|
90
|
+
return entries.flatMap(
|
|
91
|
+
([fieldId, value]) => typeof value === "string" && value.length > 0 ? [{ fieldId, text: value }] : []
|
|
92
|
+
);
|
|
93
|
+
}
|
|
30
94
|
function cloneJson(value) {
|
|
31
95
|
return JSON.parse(JSON.stringify(value));
|
|
32
96
|
}
|
|
@@ -300,6 +364,88 @@ function createAzureTableStorage(options = {}) {
|
|
|
300
364
|
...continuationToken === void 0 || continuationToken.length === 0 ? {} : { nextCursor: continuationToken }
|
|
301
365
|
};
|
|
302
366
|
},
|
|
367
|
+
async listTextAnswerPage(formId, fieldIdOrOptions, providedOptions) {
|
|
368
|
+
const { query, fieldIds } = textAnswerQuery(fieldIdOrOptions, providedOptions);
|
|
369
|
+
const pageSize = (0, import_core.normalizeSubmissionPageSize)(query.pageSize);
|
|
370
|
+
const cursor = query.cursor === void 0 ? void 0 : decodeAzureTextAnswerCursor(query.cursor);
|
|
371
|
+
const client = await submissionClient(formId, query);
|
|
372
|
+
const items = [];
|
|
373
|
+
let tableContinuationToken = cursor?.tableContinuationToken ?? void 0;
|
|
374
|
+
let entityStartIndex = cursor?.entityIndex ?? 0;
|
|
375
|
+
let fieldStartIndex = cursor?.fieldIndex ?? 0;
|
|
376
|
+
let scannedPages = 0;
|
|
377
|
+
while (scannedPages < maxScanPages) {
|
|
378
|
+
const requestToken = tableContinuationToken;
|
|
379
|
+
const iterator = client.listEntities({ queryOptions: { filter: queryFilter(formId, query) } }).byPage({
|
|
380
|
+
maxPageSize: pageSize,
|
|
381
|
+
...requestToken === void 0 ? {} : { continuationToken: requestToken }
|
|
382
|
+
});
|
|
383
|
+
const result = await iterator.next();
|
|
384
|
+
if (result.done === true) break;
|
|
385
|
+
scannedPages += 1;
|
|
386
|
+
const page = result.value;
|
|
387
|
+
for (let entityIndex = entityStartIndex; entityIndex < page.length; entityIndex += 1) {
|
|
388
|
+
const raw = page[entityIndex];
|
|
389
|
+
if (raw === void 0) continue;
|
|
390
|
+
const submission = deserializeIfMatching(raw);
|
|
391
|
+
if (submission === void 0 || !matchesBuiltInFilters(submission, formId, query) || !(0, import_core.matchesSubmissionPageFilters)(submission, query)) {
|
|
392
|
+
fieldStartIndex = 0;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
const answers = submissionTextAnswers(submission, fieldIds);
|
|
396
|
+
for (let fieldIndex = entityIndex === entityStartIndex ? fieldStartIndex : 0; fieldIndex < answers.length; fieldIndex += 1) {
|
|
397
|
+
const answer = answers[fieldIndex];
|
|
398
|
+
if (answer === void 0) continue;
|
|
399
|
+
items.push({
|
|
400
|
+
responseId: submission.id,
|
|
401
|
+
formId: submission.formId,
|
|
402
|
+
formVersion: submission.formVersion,
|
|
403
|
+
fieldId: answer.fieldId,
|
|
404
|
+
text: answer.text,
|
|
405
|
+
locale: submission.locale,
|
|
406
|
+
submittedAt: submission.submittedAt,
|
|
407
|
+
...submission.metadata === void 0 ? {} : { metadata: submission.metadata }
|
|
408
|
+
});
|
|
409
|
+
if (items.length < pageSize) continue;
|
|
410
|
+
const nextFieldIndex = fieldIndex + 1;
|
|
411
|
+
const hasFieldsInEntity = nextFieldIndex < answers.length;
|
|
412
|
+
const hasEntitiesInPage = entityIndex + 1 < page.length;
|
|
413
|
+
const nextPageToken = page.continuationToken;
|
|
414
|
+
const hasMore = hasFieldsInEntity || hasEntitiesInPage || nextPageToken !== void 0;
|
|
415
|
+
if (!hasMore) return { items, hasMore: false };
|
|
416
|
+
const nextCursor = hasFieldsInEntity ? {
|
|
417
|
+
tableContinuationToken: requestToken ?? null,
|
|
418
|
+
entityIndex,
|
|
419
|
+
fieldIndex: nextFieldIndex
|
|
420
|
+
} : hasEntitiesInPage ? {
|
|
421
|
+
tableContinuationToken: requestToken ?? null,
|
|
422
|
+
entityIndex: entityIndex + 1,
|
|
423
|
+
fieldIndex: 0
|
|
424
|
+
} : {
|
|
425
|
+
tableContinuationToken: nextPageToken ?? null,
|
|
426
|
+
entityIndex: 0,
|
|
427
|
+
fieldIndex: 0
|
|
428
|
+
};
|
|
429
|
+
return { items, hasMore: true, nextCursor: encodeAzureTextAnswerCursor(nextCursor) };
|
|
430
|
+
}
|
|
431
|
+
fieldStartIndex = 0;
|
|
432
|
+
}
|
|
433
|
+
tableContinuationToken = page.continuationToken;
|
|
434
|
+
entityStartIndex = 0;
|
|
435
|
+
fieldStartIndex = 0;
|
|
436
|
+
if (tableContinuationToken === void 0) break;
|
|
437
|
+
}
|
|
438
|
+
if (tableContinuationToken === void 0) return { items, hasMore: false };
|
|
439
|
+
return {
|
|
440
|
+
items,
|
|
441
|
+
hasMore: true,
|
|
442
|
+
nextCursor: encodeAzureTextAnswerCursor({
|
|
443
|
+
tableContinuationToken,
|
|
444
|
+
entityIndex: 0,
|
|
445
|
+
fieldIndex: 0
|
|
446
|
+
})
|
|
447
|
+
};
|
|
448
|
+
},
|
|
303
449
|
async deleteSubmission(submissionId) {
|
|
304
450
|
const client = await submissionClient("");
|
|
305
451
|
for await (const raw of client.listEntities()) {
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { assertValidFormSchema, matchesSubmissionPageFilters, normalizeSubmissionPageSize } from "@form-engine-ts/core";
|
|
3
|
+
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4
|
+
function encodeBase64(bytes) {
|
|
5
|
+
let result = "";
|
|
6
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
7
|
+
const first = bytes[index] ?? 0;
|
|
8
|
+
const second = bytes[index + 1] ?? 0;
|
|
9
|
+
const third = bytes[index + 2] ?? 0;
|
|
10
|
+
const combined = first << 16 | second << 8 | third;
|
|
11
|
+
result += BASE64_ALPHABET[combined >> 18 & 63] ?? "";
|
|
12
|
+
result += BASE64_ALPHABET[combined >> 12 & 63] ?? "";
|
|
13
|
+
result += index + 1 < bytes.length ? BASE64_ALPHABET[combined >> 6 & 63] ?? "" : "=";
|
|
14
|
+
result += index + 2 < bytes.length ? BASE64_ALPHABET[combined & 63] ?? "" : "=";
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
function decodeBase64(value) {
|
|
19
|
+
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
|
|
20
|
+
throw new TypeError("cursor must be a valid Base64 token.");
|
|
21
|
+
}
|
|
22
|
+
const bytes = [];
|
|
23
|
+
for (let index = 0; index < value.length; index += 4) {
|
|
24
|
+
const characters = value.slice(index, index + 4);
|
|
25
|
+
const sextets = [...characters].map((character) => character === "=" ? 0 : BASE64_ALPHABET.indexOf(character));
|
|
26
|
+
const combined = (sextets[0] ?? 0) << 18 | (sextets[1] ?? 0) << 12 | (sextets[2] ?? 0) << 6 | (sextets[3] ?? 0);
|
|
27
|
+
bytes.push(combined >> 16 & 255);
|
|
28
|
+
if (characters[2] !== "=") bytes.push(combined >> 8 & 255);
|
|
29
|
+
if (characters[3] !== "=") bytes.push(combined & 255);
|
|
30
|
+
}
|
|
31
|
+
return new Uint8Array(bytes);
|
|
32
|
+
}
|
|
33
|
+
function encodeAzureTextAnswerCursor(value) {
|
|
34
|
+
return encodeBase64(new TextEncoder().encode(JSON.stringify(value)));
|
|
35
|
+
}
|
|
36
|
+
function decodeAzureTextAnswerCursor(cursor) {
|
|
37
|
+
try {
|
|
38
|
+
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(decodeBase64(cursor)));
|
|
39
|
+
if (!isRecord(value) || value.tableContinuationToken !== null && typeof value.tableContinuationToken !== "string" || !Number.isSafeInteger(value.entityIndex) || value.entityIndex < 0 || !Number.isSafeInteger(value.fieldIndex) || value.fieldIndex < 0) {
|
|
40
|
+
throw new TypeError("Azure text answer cursor payload is invalid.");
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
tableContinuationToken: value.tableContinuationToken,
|
|
44
|
+
entityIndex: value.entityIndex,
|
|
45
|
+
fieldIndex: value.fieldIndex
|
|
46
|
+
};
|
|
47
|
+
} catch (cause) {
|
|
48
|
+
if (cause instanceof TypeError && cause.message === "Azure text answer cursor payload is invalid.") throw cause;
|
|
49
|
+
throw new TypeError("cursor must be a valid Azure text answer cursor.", { cause });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function textAnswerQuery(fieldIdOrOptions, options) {
|
|
53
|
+
const query = typeof fieldIdOrOptions === "string" ? options ?? {} : fieldIdOrOptions ?? {};
|
|
54
|
+
const requested = typeof fieldIdOrOptions === "string" ? [fieldIdOrOptions] : query.fieldIds;
|
|
55
|
+
if (requested?.some((fieldId) => fieldId.trim().length === 0)) {
|
|
56
|
+
throw new TypeError("fieldIds must not contain empty values.");
|
|
57
|
+
}
|
|
58
|
+
const fieldIds = requested === void 0 ? void 0 : [...new Set(requested)];
|
|
59
|
+
return { query, ...fieldIds === void 0 ? {} : { fieldIds } };
|
|
60
|
+
}
|
|
61
|
+
function submissionTextAnswers(submission, fieldIds) {
|
|
62
|
+
const entries = fieldIds === void 0 ? Object.entries(submission.values) : fieldIds.map((id) => [id, submission.values[id]]);
|
|
63
|
+
return entries.flatMap(
|
|
64
|
+
([fieldId, value]) => typeof value === "string" && value.length > 0 ? [{ fieldId, text: value }] : []
|
|
65
|
+
);
|
|
66
|
+
}
|
|
3
67
|
function cloneJson(value) {
|
|
4
68
|
return JSON.parse(JSON.stringify(value));
|
|
5
69
|
}
|
|
@@ -273,6 +337,88 @@ function createAzureTableStorage(options = {}) {
|
|
|
273
337
|
...continuationToken === void 0 || continuationToken.length === 0 ? {} : { nextCursor: continuationToken }
|
|
274
338
|
};
|
|
275
339
|
},
|
|
340
|
+
async listTextAnswerPage(formId, fieldIdOrOptions, providedOptions) {
|
|
341
|
+
const { query, fieldIds } = textAnswerQuery(fieldIdOrOptions, providedOptions);
|
|
342
|
+
const pageSize = normalizeSubmissionPageSize(query.pageSize);
|
|
343
|
+
const cursor = query.cursor === void 0 ? void 0 : decodeAzureTextAnswerCursor(query.cursor);
|
|
344
|
+
const client = await submissionClient(formId, query);
|
|
345
|
+
const items = [];
|
|
346
|
+
let tableContinuationToken = cursor?.tableContinuationToken ?? void 0;
|
|
347
|
+
let entityStartIndex = cursor?.entityIndex ?? 0;
|
|
348
|
+
let fieldStartIndex = cursor?.fieldIndex ?? 0;
|
|
349
|
+
let scannedPages = 0;
|
|
350
|
+
while (scannedPages < maxScanPages) {
|
|
351
|
+
const requestToken = tableContinuationToken;
|
|
352
|
+
const iterator = client.listEntities({ queryOptions: { filter: queryFilter(formId, query) } }).byPage({
|
|
353
|
+
maxPageSize: pageSize,
|
|
354
|
+
...requestToken === void 0 ? {} : { continuationToken: requestToken }
|
|
355
|
+
});
|
|
356
|
+
const result = await iterator.next();
|
|
357
|
+
if (result.done === true) break;
|
|
358
|
+
scannedPages += 1;
|
|
359
|
+
const page = result.value;
|
|
360
|
+
for (let entityIndex = entityStartIndex; entityIndex < page.length; entityIndex += 1) {
|
|
361
|
+
const raw = page[entityIndex];
|
|
362
|
+
if (raw === void 0) continue;
|
|
363
|
+
const submission = deserializeIfMatching(raw);
|
|
364
|
+
if (submission === void 0 || !matchesBuiltInFilters(submission, formId, query) || !matchesSubmissionPageFilters(submission, query)) {
|
|
365
|
+
fieldStartIndex = 0;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
const answers = submissionTextAnswers(submission, fieldIds);
|
|
369
|
+
for (let fieldIndex = entityIndex === entityStartIndex ? fieldStartIndex : 0; fieldIndex < answers.length; fieldIndex += 1) {
|
|
370
|
+
const answer = answers[fieldIndex];
|
|
371
|
+
if (answer === void 0) continue;
|
|
372
|
+
items.push({
|
|
373
|
+
responseId: submission.id,
|
|
374
|
+
formId: submission.formId,
|
|
375
|
+
formVersion: submission.formVersion,
|
|
376
|
+
fieldId: answer.fieldId,
|
|
377
|
+
text: answer.text,
|
|
378
|
+
locale: submission.locale,
|
|
379
|
+
submittedAt: submission.submittedAt,
|
|
380
|
+
...submission.metadata === void 0 ? {} : { metadata: submission.metadata }
|
|
381
|
+
});
|
|
382
|
+
if (items.length < pageSize) continue;
|
|
383
|
+
const nextFieldIndex = fieldIndex + 1;
|
|
384
|
+
const hasFieldsInEntity = nextFieldIndex < answers.length;
|
|
385
|
+
const hasEntitiesInPage = entityIndex + 1 < page.length;
|
|
386
|
+
const nextPageToken = page.continuationToken;
|
|
387
|
+
const hasMore = hasFieldsInEntity || hasEntitiesInPage || nextPageToken !== void 0;
|
|
388
|
+
if (!hasMore) return { items, hasMore: false };
|
|
389
|
+
const nextCursor = hasFieldsInEntity ? {
|
|
390
|
+
tableContinuationToken: requestToken ?? null,
|
|
391
|
+
entityIndex,
|
|
392
|
+
fieldIndex: nextFieldIndex
|
|
393
|
+
} : hasEntitiesInPage ? {
|
|
394
|
+
tableContinuationToken: requestToken ?? null,
|
|
395
|
+
entityIndex: entityIndex + 1,
|
|
396
|
+
fieldIndex: 0
|
|
397
|
+
} : {
|
|
398
|
+
tableContinuationToken: nextPageToken ?? null,
|
|
399
|
+
entityIndex: 0,
|
|
400
|
+
fieldIndex: 0
|
|
401
|
+
};
|
|
402
|
+
return { items, hasMore: true, nextCursor: encodeAzureTextAnswerCursor(nextCursor) };
|
|
403
|
+
}
|
|
404
|
+
fieldStartIndex = 0;
|
|
405
|
+
}
|
|
406
|
+
tableContinuationToken = page.continuationToken;
|
|
407
|
+
entityStartIndex = 0;
|
|
408
|
+
fieldStartIndex = 0;
|
|
409
|
+
if (tableContinuationToken === void 0) break;
|
|
410
|
+
}
|
|
411
|
+
if (tableContinuationToken === void 0) return { items, hasMore: false };
|
|
412
|
+
return {
|
|
413
|
+
items,
|
|
414
|
+
hasMore: true,
|
|
415
|
+
nextCursor: encodeAzureTextAnswerCursor({
|
|
416
|
+
tableContinuationToken,
|
|
417
|
+
entityIndex: 0,
|
|
418
|
+
fieldIndex: 0
|
|
419
|
+
})
|
|
420
|
+
};
|
|
421
|
+
},
|
|
276
422
|
async deleteSubmission(submissionId) {
|
|
277
423
|
const client = await submissionClient("");
|
|
278
424
|
for await (const raw of client.listEntities()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/storage-azure-table",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"typescript"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@form-engine-ts/core": "2.
|
|
42
|
+
"@form-engine-ts/core": "2.8.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@azure/data-tables": "^13.3.2"
|