@carddb/client 0.3.0 → 0.4.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 +1 -1
- package/dist/index.cjs +337 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +172 -3
- package/dist/index.d.ts +172 -3
- package/dist/index.js +336 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { RestrictedError, RateLimitError, ServerError, ConnectionError, TimeoutE
|
|
|
2
2
|
export * from '@carddb/core';
|
|
3
3
|
|
|
4
4
|
// src/client.ts
|
|
5
|
-
var DEFAULT_ENDPOINT = "https://carddb.
|
|
5
|
+
var DEFAULT_ENDPOINT = "https://carddb.dev/query";
|
|
6
6
|
var DEFAULT_TIMEOUT = 3e4;
|
|
7
7
|
var DEFAULT_OPEN_TIMEOUT = 1e4;
|
|
8
8
|
var DEFAULT_CACHE_TTL = 300;
|
|
@@ -679,6 +679,25 @@ var GamesResource = class extends BaseResource {
|
|
|
679
679
|
const result = await this.connection.execute(query, QueryBuilder.gameUpdateVariables(id, input));
|
|
680
680
|
return result["gameUpdate"];
|
|
681
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* Get publisher-defined game region metadata for scan-capable clients.
|
|
684
|
+
*/
|
|
685
|
+
async getRegions(options = {}) {
|
|
686
|
+
const publisherSlug = this.resolvePublisher(options.publisherSlug);
|
|
687
|
+
const gameKey = this.resolveGame(options.gameKey);
|
|
688
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
689
|
+
const variables = QueryBuilder.gameScanRegionsVariables(
|
|
690
|
+
publisherSlug,
|
|
691
|
+
gameKey,
|
|
692
|
+
options.includeInactive
|
|
693
|
+
);
|
|
694
|
+
const key = this.cacheKey("games", "getRegions", variables);
|
|
695
|
+
return this.withCache(key, "games", options, async () => {
|
|
696
|
+
const { query } = QueryBuilder.gameScanRegions();
|
|
697
|
+
const result = await this.connection.execute(query, variables);
|
|
698
|
+
return result["gameScanRegions"] ?? [];
|
|
699
|
+
});
|
|
700
|
+
}
|
|
682
701
|
/**
|
|
683
702
|
* Search for games
|
|
684
703
|
*
|
|
@@ -2523,6 +2542,27 @@ var FilesResource = class extends BaseResource {
|
|
|
2523
2542
|
const result = await this.connection.execute(query, { id });
|
|
2524
2543
|
return result["fileUploadConfirm"];
|
|
2525
2544
|
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Request a presigned upload URL, PUT bytes directly to storage, then confirm the file.
|
|
2547
|
+
*/
|
|
2548
|
+
async upload(input) {
|
|
2549
|
+
const size = input.size ?? inferUploadSize(input.body);
|
|
2550
|
+
if (!size || size <= 0) {
|
|
2551
|
+
throw new Error("files.upload requires a positive size or a body with an inferable size");
|
|
2552
|
+
}
|
|
2553
|
+
const upload = await this.requestUpload({
|
|
2554
|
+
filename: input.filename,
|
|
2555
|
+
contentType: input.contentType,
|
|
2556
|
+
size,
|
|
2557
|
+
isPublic: input.isPublic ?? false,
|
|
2558
|
+
entityType: input.entityType ?? entityTypeForPurpose(input.purpose),
|
|
2559
|
+
entityId: input.entityId,
|
|
2560
|
+
publisherId: input.publisherId,
|
|
2561
|
+
datasetId: input.datasetId
|
|
2562
|
+
});
|
|
2563
|
+
await putUpload(upload.uploadUrl, input.contentType, input.body);
|
|
2564
|
+
return this.confirmUpload(upload.file.id);
|
|
2565
|
+
}
|
|
2526
2566
|
/**
|
|
2527
2567
|
* Delete a file. Requires a server-side secret credential.
|
|
2528
2568
|
*/
|
|
@@ -2533,6 +2573,294 @@ var FilesResource = class extends BaseResource {
|
|
|
2533
2573
|
return Boolean(result["fileDelete"]);
|
|
2534
2574
|
}
|
|
2535
2575
|
};
|
|
2576
|
+
async function putUpload(uploadUrl, contentType, body) {
|
|
2577
|
+
const uploadFetch = globalThis.fetch;
|
|
2578
|
+
if (!uploadFetch) throw new Error("files.upload requires a runtime with fetch support");
|
|
2579
|
+
const response = await uploadFetch(uploadUrl, {
|
|
2580
|
+
method: "PUT",
|
|
2581
|
+
headers: { "Content-Type": contentType },
|
|
2582
|
+
body
|
|
2583
|
+
});
|
|
2584
|
+
if (!response.ok) {
|
|
2585
|
+
const responseBody = await response.text().catch(() => "");
|
|
2586
|
+
throw new Error(
|
|
2587
|
+
`File upload failed with ${response.status} ${response.statusText}${responseBody ? `: ${responseBody}` : ""}`
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
function inferUploadSize(body) {
|
|
2592
|
+
if (typeof body === "string") return new TextEncoder().encode(body).byteLength;
|
|
2593
|
+
if (body instanceof ArrayBuffer) return body.byteLength;
|
|
2594
|
+
if (ArrayBuffer.isView(body)) return body.byteLength;
|
|
2595
|
+
const sized = body;
|
|
2596
|
+
if (typeof sized?.size === "number") return sized.size;
|
|
2597
|
+
if (typeof sized?.byteLength === "number") return sized.byteLength;
|
|
2598
|
+
if (typeof sized?.length === "number") return sized.length;
|
|
2599
|
+
return void 0;
|
|
2600
|
+
}
|
|
2601
|
+
function entityTypeForPurpose(purpose) {
|
|
2602
|
+
if (!purpose || purpose === "scan_image") return void 0;
|
|
2603
|
+
if (purpose === "import") return "import";
|
|
2604
|
+
if (purpose === "scan_template_example") return "scan_template_example";
|
|
2605
|
+
return purpose;
|
|
2606
|
+
}
|
|
2607
|
+
var ScansResource = class extends BaseResource {
|
|
2608
|
+
constructor(connection, config) {
|
|
2609
|
+
super(connection, config);
|
|
2610
|
+
}
|
|
2611
|
+
/**
|
|
2612
|
+
* Create a scan job for an already uploaded image file.
|
|
2613
|
+
*/
|
|
2614
|
+
async createJob(input) {
|
|
2615
|
+
const scopedInput = this.resolveCreateJobInput(input);
|
|
2616
|
+
const { query } = QueryBuilder.createScanJob();
|
|
2617
|
+
const result = await this.connection.execute(
|
|
2618
|
+
query,
|
|
2619
|
+
QueryBuilder.createScanJobVariables(scopedInput)
|
|
2620
|
+
);
|
|
2621
|
+
return result["createScanJob"];
|
|
2622
|
+
}
|
|
2623
|
+
/**
|
|
2624
|
+
* Get a scan job and its latest processing result.
|
|
2625
|
+
*/
|
|
2626
|
+
async getJob(id, options = {}) {
|
|
2627
|
+
const key = this.cacheKey("scans", "getJob", { id });
|
|
2628
|
+
return this.withCache(key, "scans", options, async () => {
|
|
2629
|
+
const { query } = QueryBuilder.scanJob();
|
|
2630
|
+
const result = await this.connection.execute(query, { id });
|
|
2631
|
+
return result["scanJob"] ?? null;
|
|
2632
|
+
});
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Poll a scan job until it reaches a terminal status.
|
|
2636
|
+
*/
|
|
2637
|
+
async pollJob(id, options = {}) {
|
|
2638
|
+
const timeoutMs = options.timeoutMs ?? 3e5;
|
|
2639
|
+
const backoffFactor = Math.max(options.backoffFactor ?? 1.5, 1);
|
|
2640
|
+
const maxIntervalMs = options.maxIntervalMs ?? 1e4;
|
|
2641
|
+
const startedAt = Date.now();
|
|
2642
|
+
let intervalMs = Math.max(options.intervalMs ?? 1e3, 1);
|
|
2643
|
+
while (true) {
|
|
2644
|
+
throwIfAborted(options.signal);
|
|
2645
|
+
const job = await this.getJob(id, { cache: false });
|
|
2646
|
+
if (!job) throw new Error(`Scan job '${id}' was not found`);
|
|
2647
|
+
if (isTerminalScanStatus(job.status)) return job;
|
|
2648
|
+
const elapsedMs = Date.now() - startedAt;
|
|
2649
|
+
const remainingMs = timeoutMs - elapsedMs;
|
|
2650
|
+
if (remainingMs <= 0) {
|
|
2651
|
+
throw new Error(`Timed out waiting for scan job '${id}'`);
|
|
2652
|
+
}
|
|
2653
|
+
await sleep(Math.min(intervalMs, remainingMs));
|
|
2654
|
+
intervalMs = Math.min(Math.ceil(intervalMs * backoffFactor), maxIntervalMs);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
/**
|
|
2658
|
+
* Submit correctness feedback for a completed scan job.
|
|
2659
|
+
*/
|
|
2660
|
+
async submitFeedback(input) {
|
|
2661
|
+
const { query } = QueryBuilder.submitScanFeedback();
|
|
2662
|
+
const result = await this.connection.execute(
|
|
2663
|
+
query,
|
|
2664
|
+
QueryBuilder.submitScanFeedbackVariables(input)
|
|
2665
|
+
);
|
|
2666
|
+
return result["submitScanFeedback"];
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Aggregate scan metrics for a publisher/game/dataset scope.
|
|
2670
|
+
*/
|
|
2671
|
+
async metrics(input) {
|
|
2672
|
+
const scopedInput = this.resolveMetricsInput(input);
|
|
2673
|
+
const { query } = QueryBuilder.scanMetrics();
|
|
2674
|
+
const result = await this.connection.execute(
|
|
2675
|
+
query,
|
|
2676
|
+
QueryBuilder.scanMetricsVariables(scopedInput)
|
|
2677
|
+
);
|
|
2678
|
+
return result["scanMetrics"];
|
|
2679
|
+
}
|
|
2680
|
+
/**
|
|
2681
|
+
* Verify an `X-CardDB-Signature` value for a webhook body.
|
|
2682
|
+
*/
|
|
2683
|
+
async verifyWebhookSignature(input) {
|
|
2684
|
+
const subtle = getSubtleCrypto();
|
|
2685
|
+
const key = await subtle.importKey(
|
|
2686
|
+
"raw",
|
|
2687
|
+
encodeUtf8(input.secret),
|
|
2688
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
2689
|
+
false,
|
|
2690
|
+
["sign"]
|
|
2691
|
+
);
|
|
2692
|
+
const digest = await subtle.sign("HMAC", key, bodyToBytes(input.body));
|
|
2693
|
+
const expected = `sha256=${toHex(new Uint8Array(digest))}`;
|
|
2694
|
+
return constantTimeEqual(input.signature.trim().toLowerCase(), expected);
|
|
2695
|
+
}
|
|
2696
|
+
resolveCreateJobInput(input) {
|
|
2697
|
+
const publisherSlug = this.resolvePublisher(input.publisherSlug);
|
|
2698
|
+
const gameKey = this.resolveGame(input.gameKey);
|
|
2699
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
2700
|
+
return { ...input, publisherSlug, gameKey };
|
|
2701
|
+
}
|
|
2702
|
+
resolveMetricsInput(input) {
|
|
2703
|
+
const publisherSlug = this.resolvePublisher(input.publisherSlug);
|
|
2704
|
+
const gameKey = this.resolveGame(input.gameKey);
|
|
2705
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
2706
|
+
return { ...input, publisherSlug, gameKey };
|
|
2707
|
+
}
|
|
2708
|
+
};
|
|
2709
|
+
function isTerminalScanStatus(status) {
|
|
2710
|
+
const normalized = status.toLowerCase();
|
|
2711
|
+
return normalized === "completed" || normalized === "failed" || normalized === "cancelled";
|
|
2712
|
+
}
|
|
2713
|
+
async function sleep(ms) {
|
|
2714
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2715
|
+
}
|
|
2716
|
+
function throwIfAborted(signal) {
|
|
2717
|
+
if (!signal) return;
|
|
2718
|
+
if (signal.throwIfAborted) signal.throwIfAborted();
|
|
2719
|
+
if (signal.aborted) throw new Error("Scan job polling aborted");
|
|
2720
|
+
}
|
|
2721
|
+
function getSubtleCrypto() {
|
|
2722
|
+
const cryptoLike = globalThis;
|
|
2723
|
+
const subtle = cryptoLike.crypto?.subtle;
|
|
2724
|
+
if (!subtle) {
|
|
2725
|
+
throw new Error("Web Crypto HMAC support is not available in this runtime");
|
|
2726
|
+
}
|
|
2727
|
+
return subtle;
|
|
2728
|
+
}
|
|
2729
|
+
function bodyToBytes(body) {
|
|
2730
|
+
if (typeof body === "string") return encodeUtf8(body);
|
|
2731
|
+
if (body instanceof ArrayBuffer) return new Uint8Array(body);
|
|
2732
|
+
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
|
|
2733
|
+
}
|
|
2734
|
+
function encodeUtf8(value) {
|
|
2735
|
+
return new TextEncoder().encode(value);
|
|
2736
|
+
}
|
|
2737
|
+
function toHex(bytes) {
|
|
2738
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
2739
|
+
}
|
|
2740
|
+
function constantTimeEqual(left, right) {
|
|
2741
|
+
const maxLength = Math.max(left.length, right.length);
|
|
2742
|
+
let diff = left.length ^ right.length;
|
|
2743
|
+
for (let index = 0; index < maxLength; index++) {
|
|
2744
|
+
diff |= (left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
|
|
2745
|
+
}
|
|
2746
|
+
return diff === 0;
|
|
2747
|
+
}
|
|
2748
|
+
var ScanTemplatesResource = class extends BaseResource {
|
|
2749
|
+
constructor(connection, config) {
|
|
2750
|
+
super(connection, config);
|
|
2751
|
+
}
|
|
2752
|
+
/**
|
|
2753
|
+
* Resolve the active scan template for a game or dataset scope.
|
|
2754
|
+
*/
|
|
2755
|
+
async resolve(input) {
|
|
2756
|
+
const scopedInput = this.resolveTemplateScope(input);
|
|
2757
|
+
const key = this.cacheKey("scanTemplates", "resolve", { ...scopedInput });
|
|
2758
|
+
return this.withCache(key, "scanTemplates", input, async () => {
|
|
2759
|
+
const { query } = QueryBuilder.resolveScanTemplate();
|
|
2760
|
+
const result = await this.connection.execute(
|
|
2761
|
+
query,
|
|
2762
|
+
QueryBuilder.resolveScanTemplateVariables(scopedInput)
|
|
2763
|
+
);
|
|
2764
|
+
return result["resolveScanTemplate"];
|
|
2765
|
+
});
|
|
2766
|
+
}
|
|
2767
|
+
/**
|
|
2768
|
+
* List publisher-managed scan templates for a game or dataset scope.
|
|
2769
|
+
*/
|
|
2770
|
+
async list(input) {
|
|
2771
|
+
const scopedInput = this.resolveListScope(input);
|
|
2772
|
+
const key = this.cacheKey("scanTemplates", "list", { ...scopedInput });
|
|
2773
|
+
return this.withCache(key, "scanTemplates", input, async () => {
|
|
2774
|
+
const { query } = QueryBuilder.scanTemplates();
|
|
2775
|
+
const result = await this.connection.execute(
|
|
2776
|
+
query,
|
|
2777
|
+
QueryBuilder.scanTemplatesVariables(scopedInput)
|
|
2778
|
+
);
|
|
2779
|
+
const payload = result["scanTemplates"];
|
|
2780
|
+
return payload?.templates ?? [];
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
/**
|
|
2784
|
+
* Create a publisher-managed scan template. Requires a server-side secret credential.
|
|
2785
|
+
*/
|
|
2786
|
+
async create(input) {
|
|
2787
|
+
this.config.requireSecretCredential("scanTemplates.create");
|
|
2788
|
+
const scopedInput = this.resolveSaveInput(input);
|
|
2789
|
+
const { query } = QueryBuilder.createScanTemplate();
|
|
2790
|
+
const result = await this.connection.execute(
|
|
2791
|
+
query,
|
|
2792
|
+
QueryBuilder.createScanTemplateVariables(scopedInput)
|
|
2793
|
+
);
|
|
2794
|
+
return result["createScanTemplate"];
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* Replace a publisher-managed scan template. Requires a server-side secret credential.
|
|
2798
|
+
*/
|
|
2799
|
+
async update(idOrInput, input) {
|
|
2800
|
+
this.config.requireSecretCredential("scanTemplates.update");
|
|
2801
|
+
const id = typeof idOrInput === "string" ? idOrInput : idOrInput.id;
|
|
2802
|
+
const templateInput = typeof idOrInput === "string" ? input : withoutId(idOrInput);
|
|
2803
|
+
if (!templateInput) throw new Error("scan template input is required");
|
|
2804
|
+
const scopedInput = this.resolveSaveInput(templateInput);
|
|
2805
|
+
const { query } = QueryBuilder.updateScanTemplate();
|
|
2806
|
+
const result = await this.connection.execute(
|
|
2807
|
+
query,
|
|
2808
|
+
QueryBuilder.updateScanTemplateVariables(id, scopedInput)
|
|
2809
|
+
);
|
|
2810
|
+
return result["updateScanTemplate"];
|
|
2811
|
+
}
|
|
2812
|
+
/**
|
|
2813
|
+
* Validate a draft scan template and normalize provided region OCR hints.
|
|
2814
|
+
*/
|
|
2815
|
+
async preview(input) {
|
|
2816
|
+
const scopedInput = this.resolvePreviewInput(input);
|
|
2817
|
+
const { query } = QueryBuilder.previewScanTemplate();
|
|
2818
|
+
const result = await this.connection.execute(
|
|
2819
|
+
query,
|
|
2820
|
+
QueryBuilder.previewScanTemplateVariables(scopedInput)
|
|
2821
|
+
);
|
|
2822
|
+
return result["previewScanTemplate"];
|
|
2823
|
+
}
|
|
2824
|
+
resolveTemplateScope(input) {
|
|
2825
|
+
const publisherSlug = this.resolvePublisher(input.publisherSlug);
|
|
2826
|
+
const gameKey = this.resolveGame(input.gameKey);
|
|
2827
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
2828
|
+
return {
|
|
2829
|
+
publisherSlug,
|
|
2830
|
+
gameKey,
|
|
2831
|
+
datasetKey: input.datasetKey,
|
|
2832
|
+
templateId: input.templateId
|
|
2833
|
+
};
|
|
2834
|
+
}
|
|
2835
|
+
resolveListScope(input) {
|
|
2836
|
+
const publisherSlug = this.resolvePublisher(input.publisherSlug);
|
|
2837
|
+
const gameKey = this.resolveGame(input.gameKey);
|
|
2838
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
2839
|
+
return {
|
|
2840
|
+
publisherSlug,
|
|
2841
|
+
gameKey,
|
|
2842
|
+
datasetKey: input.datasetKey,
|
|
2843
|
+
includeArchived: input.includeArchived
|
|
2844
|
+
};
|
|
2845
|
+
}
|
|
2846
|
+
resolveSaveInput(input) {
|
|
2847
|
+
const publisherSlug = this.resolvePublisher(input.publisherSlug);
|
|
2848
|
+
const gameKey = this.resolveGame(input.gameKey);
|
|
2849
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
2850
|
+
return { ...input, publisherSlug, gameKey };
|
|
2851
|
+
}
|
|
2852
|
+
resolvePreviewInput(input) {
|
|
2853
|
+
const publisherSlug = this.resolvePublisher(input.publisherSlug);
|
|
2854
|
+
const gameKey = this.resolveGame(input.gameKey);
|
|
2855
|
+
this.validateAccess(publisherSlug, gameKey);
|
|
2856
|
+
return { ...input, publisherSlug, gameKey };
|
|
2857
|
+
}
|
|
2858
|
+
};
|
|
2859
|
+
function withoutId(input) {
|
|
2860
|
+
const templateInput = { ...input };
|
|
2861
|
+
delete templateInput.id;
|
|
2862
|
+
return templateInput;
|
|
2863
|
+
}
|
|
2536
2864
|
|
|
2537
2865
|
// src/client.ts
|
|
2538
2866
|
var CardDBClient = class _CardDBClient {
|
|
@@ -2558,6 +2886,10 @@ var CardDBClient = class _CardDBClient {
|
|
|
2558
2886
|
exports;
|
|
2559
2887
|
/** File upload helper resource */
|
|
2560
2888
|
files;
|
|
2889
|
+
/** Scan job helper resource */
|
|
2890
|
+
scans;
|
|
2891
|
+
/** Scan template helper resource */
|
|
2892
|
+
scanTemplates;
|
|
2561
2893
|
/**
|
|
2562
2894
|
* Create a new CardDB client
|
|
2563
2895
|
*
|
|
@@ -2576,6 +2908,8 @@ var CardDBClient = class _CardDBClient {
|
|
|
2576
2908
|
this.imports = new ImportsResource(this.connection, this.config);
|
|
2577
2909
|
this.exports = new ExportsResource(this.connection, this.config);
|
|
2578
2910
|
this.files = new FilesResource(this.connection, this.config);
|
|
2911
|
+
this.scans = new ScansResource(this.connection, this.config);
|
|
2912
|
+
this.scanTemplates = new ScanTemplatesResource(this.connection, this.config);
|
|
2579
2913
|
}
|
|
2580
2914
|
/**
|
|
2581
2915
|
* Get information about the current API key
|
|
@@ -2649,6 +2983,6 @@ var CardDBClient = class _CardDBClient {
|
|
|
2649
2983
|
}
|
|
2650
2984
|
};
|
|
2651
2985
|
|
|
2652
|
-
export { BaseResource, CardDBClient, Configuration, Connection, DEFAULT_CACHE_TTL, DEFAULT_ENDPOINT, DEFAULT_MAX_NETWORK_RETRIES, DEFAULT_MAX_RETRIES, DEFAULT_OPEN_TIMEOUT, DEFAULT_RETRY_BASE_DELAY, DEFAULT_RETRY_MAX_DELAY, DEFAULT_TIMEOUT, DatasetsResource, DecksResource, ExportsResource, FilesResource, GamesResource, ImportFormatsResource, ImportsResource, PublishersResource, RecordsResource, RulesResource, cacheKey, getRateLimitInfo, getSDKVersion, getUserAgent, readCache, writeCache };
|
|
2986
|
+
export { BaseResource, CardDBClient, Configuration, Connection, DEFAULT_CACHE_TTL, DEFAULT_ENDPOINT, DEFAULT_MAX_NETWORK_RETRIES, DEFAULT_MAX_RETRIES, DEFAULT_OPEN_TIMEOUT, DEFAULT_RETRY_BASE_DELAY, DEFAULT_RETRY_MAX_DELAY, DEFAULT_TIMEOUT, DatasetsResource, DecksResource, ExportsResource, FilesResource, GamesResource, ImportFormatsResource, ImportsResource, PublishersResource, RecordsResource, RulesResource, ScanTemplatesResource, ScansResource, cacheKey, getRateLimitInfo, getSDKVersion, getUserAgent, readCache, writeCache };
|
|
2653
2987
|
//# sourceMappingURL=index.js.map
|
|
2654
2988
|
//# sourceMappingURL=index.js.map
|