@neetru/sdk 3.4.0 → 3.4.2
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/CHANGELOG.md +31 -0
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/auth.cjs +230 -38
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +230 -38
- package/dist/auth.mjs.map +1 -1
- package/dist/build-guard.cjs +41 -6
- package/dist/build-guard.cjs.map +1 -1
- package/dist/build-guard.d.cts +24 -1
- package/dist/build-guard.d.ts +24 -1
- package/dist/build-guard.mjs +40 -7
- package/dist/build-guard.mjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +230 -38
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +230 -38
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/index.cjs +231 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +231 -39
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/react.cjs +593 -31
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +97 -2
- package/dist/react.d.ts +97 -2
- package/dist/react.mjs +590 -31
- package/dist/react.mjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/{types-DdJyqBy-.d.ts → types-BlOLDMR0.d.ts} +79 -6
- package/dist/{types-BoFSCHF_.d.cts → types-D-QdG502.d.cts} +79 -6
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createNeetruClient } from './auth.cjs';
|
|
2
2
|
export { NeetruError, NeetruErrorCode } from './errors.cjs';
|
|
3
|
-
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket,
|
|
3
|
+
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-D-QdG502.cjs';
|
|
4
4
|
export { DEV_FIXTURE_USER, MockAi, MockAuth, MockAuthOptions, MockDb, MockEntitlements, MockSupport, MockUsage } from './mocks.cjs';
|
|
5
5
|
import 'drizzle-orm/node-postgres';
|
|
6
6
|
|
|
@@ -42,6 +42,6 @@ declare function checkCoreVersionCompat(coreVersion: string): void;
|
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
44
|
/** Versão do SDK — exportada explicitamente pra detecção em runtime. */
|
|
45
|
-
declare const VERSION: "3.4.
|
|
45
|
+
declare const VERSION: "3.4.1";
|
|
46
46
|
|
|
47
47
|
export { VERSION, checkCoreVersionCompat };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createNeetruClient } from './auth.js';
|
|
2
2
|
export { NeetruError, NeetruErrorCode } from './errors.js';
|
|
3
|
-
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket,
|
|
3
|
+
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-BlOLDMR0.js';
|
|
4
4
|
export { DEV_FIXTURE_USER, MockAi, MockAuth, MockAuthOptions, MockDb, MockEntitlements, MockSupport, MockUsage } from './mocks.js';
|
|
5
5
|
import 'drizzle-orm/node-postgres';
|
|
6
6
|
|
|
@@ -42,6 +42,6 @@ declare function checkCoreVersionCompat(coreVersion: string): void;
|
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
44
|
/** Versão do SDK — exportada explicitamente pra detecção em runtime. */
|
|
45
|
-
declare const VERSION: "3.4.
|
|
45
|
+
declare const VERSION: "3.4.1";
|
|
46
46
|
|
|
47
47
|
export { VERSION, checkCoreVersionCompat };
|
package/dist/index.mjs
CHANGED
|
@@ -682,13 +682,17 @@ var init_lease = __esm({
|
|
|
682
682
|
// src/db/sql/sql-client.ts
|
|
683
683
|
var sql_client_exports = {};
|
|
684
684
|
__export(sql_client_exports, {
|
|
685
|
+
DEFAULT_POOL_CONNECT_TIMEOUT_MS: () => DEFAULT_POOL_CONNECT_TIMEOUT_MS,
|
|
686
|
+
DEFAULT_POOL_IDLE_MS: () => DEFAULT_POOL_IDLE_MS,
|
|
687
|
+
DEFAULT_POOL_MAX: () => DEFAULT_POOL_MAX,
|
|
685
688
|
LEASE_ENDPOINT: () => LEASE_ENDPOINT,
|
|
686
689
|
LEASE_RENEW_ENDPOINT: () => LEASE_RENEW_ENDPOINT,
|
|
687
690
|
createDrizzleHandle: () => createDrizzleHandle,
|
|
688
691
|
createHttpLeaseFetcher: () => createHttpLeaseFetcher,
|
|
689
692
|
createPgPool: () => createPgPool,
|
|
690
693
|
createSqlClientFromConfig: () => createSqlClientFromConfig,
|
|
691
|
-
createSqlClientWithDeps: () => createSqlClientWithDeps
|
|
694
|
+
createSqlClientWithDeps: () => createSqlClientWithDeps,
|
|
695
|
+
resolvePoolTuning: () => resolvePoolTuning
|
|
692
696
|
});
|
|
693
697
|
function mapEnvToCore(sdkEnv) {
|
|
694
698
|
if (sdkEnv === "workspace") return "staging";
|
|
@@ -777,6 +781,30 @@ function parseLease(raw) {
|
|
|
777
781
|
expiresAt: req("expiresAt", "string")
|
|
778
782
|
};
|
|
779
783
|
}
|
|
784
|
+
function readEnvInt(name, def, min, max) {
|
|
785
|
+
const raw = typeof process !== "undefined" ? process.env?.[name] : void 0;
|
|
786
|
+
if (raw === void 0 || raw.trim() === "") return def;
|
|
787
|
+
const n = Number.parseInt(raw.trim(), 10);
|
|
788
|
+
if (!Number.isFinite(n) || n < min || n > max) return def;
|
|
789
|
+
return n;
|
|
790
|
+
}
|
|
791
|
+
function resolvePoolTuning() {
|
|
792
|
+
return {
|
|
793
|
+
// Teto 100: bem abaixo do `max_client_conn = 500` do PgBouncer, com folga
|
|
794
|
+
// para múltiplas instâncias do app dividirem o mesmo front-door.
|
|
795
|
+
max: readEnvInt("NEETRU_DB_POOL_MAX", DEFAULT_POOL_MAX, 1, 100),
|
|
796
|
+
// Teto 15min = janela do cert; piso 1s.
|
|
797
|
+
idleTimeoutMillis: readEnvInt("NEETRU_DB_POOL_IDLE_MS", DEFAULT_POOL_IDLE_MS, 1e3, 9e5),
|
|
798
|
+
connectionTimeoutMillis: readEnvInt(
|
|
799
|
+
"NEETRU_DB_POOL_CONNECT_TIMEOUT_MS",
|
|
800
|
+
DEFAULT_POOL_CONNECT_TIMEOUT_MS,
|
|
801
|
+
1e3,
|
|
802
|
+
12e4
|
|
803
|
+
),
|
|
804
|
+
keepAlive: true,
|
|
805
|
+
keepAliveInitialDelayMillis: 1e4
|
|
806
|
+
};
|
|
807
|
+
}
|
|
780
808
|
async function createPgPool(lease) {
|
|
781
809
|
const { Pool } = await import(
|
|
782
810
|
/* webpackIgnore: true */
|
|
@@ -795,9 +823,7 @@ async function createPgPool(lease) {
|
|
|
795
823
|
user: lease.user,
|
|
796
824
|
password: lease.password,
|
|
797
825
|
ssl,
|
|
798
|
-
|
|
799
|
-
idleTimeoutMillis: 3e4,
|
|
800
|
-
connectionTimeoutMillis: 1e4
|
|
826
|
+
...resolvePoolTuning()
|
|
801
827
|
});
|
|
802
828
|
}
|
|
803
829
|
async function createDrizzleHandle(pool, schema) {
|
|
@@ -932,9 +958,9 @@ async function createSqlClientFromConfig(config, schema, options) {
|
|
|
932
958
|
user: lease.user,
|
|
933
959
|
password: lease.password,
|
|
934
960
|
ssl,
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
961
|
+
// Tuning centralizado (env-tunável) — ver resolvePoolTuning + auditoria
|
|
962
|
+
// docs/_review/AUDITORIA_DB_CONN_PERF_2026-09-06.md no Core.
|
|
963
|
+
...resolvePoolTuning()
|
|
938
964
|
});
|
|
939
965
|
};
|
|
940
966
|
const createDrizzle = (pool, s) => {
|
|
@@ -957,7 +983,7 @@ async function createSqlClientFromConfig(config, schema, options) {
|
|
|
957
983
|
options
|
|
958
984
|
);
|
|
959
985
|
}
|
|
960
|
-
var LEASE_ENDPOINT, LEASE_RENEW_ENDPOINT;
|
|
986
|
+
var LEASE_ENDPOINT, LEASE_RENEW_ENDPOINT, DEFAULT_POOL_MAX, DEFAULT_POOL_IDLE_MS, DEFAULT_POOL_CONNECT_TIMEOUT_MS;
|
|
961
987
|
var init_sql_client = __esm({
|
|
962
988
|
"src/db/sql/sql-client.ts"() {
|
|
963
989
|
init_db_errors();
|
|
@@ -966,6 +992,9 @@ var init_sql_client = __esm({
|
|
|
966
992
|
init_resilient_pool();
|
|
967
993
|
LEASE_ENDPOINT = "/api/sdk/v1/db/lease";
|
|
968
994
|
LEASE_RENEW_ENDPOINT = "/api/sdk/v1/db/lease/renew";
|
|
995
|
+
DEFAULT_POOL_MAX = 10;
|
|
996
|
+
DEFAULT_POOL_IDLE_MS = 6e4;
|
|
997
|
+
DEFAULT_POOL_CONNECT_TIMEOUT_MS = 1e4;
|
|
969
998
|
}
|
|
970
999
|
});
|
|
971
1000
|
|
|
@@ -2541,8 +2570,10 @@ var MutationQueue = class {
|
|
|
2541
2570
|
await this.store.deleteMutation(mutationId);
|
|
2542
2571
|
}
|
|
2543
2572
|
/**
|
|
2544
|
-
* Marca uma mutação como `failed` e registra o erro.
|
|
2545
|
-
* Incrementa `attempts`. Chamado pelo SyncEngine
|
|
2573
|
+
* Marca uma mutação como `failed` (dead-letter) e registra o erro.
|
|
2574
|
+
* Incrementa `attempts` e carimba `lastAttemptAt`. Chamado pelo SyncEngine
|
|
2575
|
+
* quando a mutação esgota o teto de tentativas (mutação-veneno): sai do
|
|
2576
|
+
* conjunto `queued`, então `drain()` para de devolvê-la e a fila DESTRAVA.
|
|
2546
2577
|
*/
|
|
2547
2578
|
async markFailed(mutationId, error) {
|
|
2548
2579
|
const mut = await this.store.getMutation(mutationId);
|
|
@@ -2551,12 +2582,14 @@ var MutationQueue = class {
|
|
|
2551
2582
|
...mut,
|
|
2552
2583
|
status: "failed",
|
|
2553
2584
|
lastError: error,
|
|
2554
|
-
attempts: mut.attempts + 1
|
|
2585
|
+
attempts: mut.attempts + 1,
|
|
2586
|
+
lastAttemptAt: Date.now()
|
|
2555
2587
|
});
|
|
2556
2588
|
}
|
|
2557
2589
|
/**
|
|
2558
|
-
* Incrementa `attempts` e volta para `queued`
|
|
2559
|
-
* Chamado pelo SyncEngine em falha
|
|
2590
|
+
* Incrementa `attempts`, carimba `lastAttemptAt` e volta para `queued`
|
|
2591
|
+
* (falha transiente com backoff). Chamado pelo SyncEngine em falha
|
|
2592
|
+
* transiente (5xx, timeout) da mutação que REALMENTE foi tentada.
|
|
2560
2593
|
*/
|
|
2561
2594
|
async markRetry(mutationId, error) {
|
|
2562
2595
|
const mut = await this.store.getMutation(mutationId);
|
|
@@ -2565,9 +2598,24 @@ var MutationQueue = class {
|
|
|
2565
2598
|
...mut,
|
|
2566
2599
|
status: "queued",
|
|
2567
2600
|
lastError: error,
|
|
2568
|
-
attempts: mut.attempts + 1
|
|
2601
|
+
attempts: mut.attempts + 1,
|
|
2602
|
+
lastAttemptAt: Date.now()
|
|
2569
2603
|
});
|
|
2570
2604
|
}
|
|
2605
|
+
/**
|
|
2606
|
+
* Reverte uma mutação `inflight` de volta a `queued` SEM tocar em `attempts`
|
|
2607
|
+
* nem `lastAttemptAt`. Usado para mutações que foram marcadas inflight mas
|
|
2608
|
+
* NUNCA chegaram a ser enviadas (estavam atrás da head no FIFO e o push
|
|
2609
|
+
* parou antes delas): contá-las como tentativa as empurraria pro dead-letter
|
|
2610
|
+
* por engano, e adiaria seu envio via backoff sem que tenham falhado.
|
|
2611
|
+
* No-op se a mutação não está mais `inflight`.
|
|
2612
|
+
*/
|
|
2613
|
+
async requeueInflight(mutationId) {
|
|
2614
|
+
const mut = await this.store.getMutation(mutationId);
|
|
2615
|
+
if (!mut) return;
|
|
2616
|
+
if (mut.status !== "inflight") return;
|
|
2617
|
+
await this.store.putMutation({ ...mut, status: "queued" });
|
|
2618
|
+
}
|
|
2571
2619
|
};
|
|
2572
2620
|
|
|
2573
2621
|
// src/db/field-value.ts
|
|
@@ -2623,6 +2671,10 @@ function hasFieldSentinel(data) {
|
|
|
2623
2671
|
}
|
|
2624
2672
|
|
|
2625
2673
|
// src/db/offline/sync-engine.ts
|
|
2674
|
+
var MAX_MUTATION_ATTEMPTS = 8;
|
|
2675
|
+
var BACKOFF_BASE_MS = 1e3;
|
|
2676
|
+
var BACKOFF_CAP_MS = 5 * 60 * 1e3;
|
|
2677
|
+
var TRUNCATED_COLLECTIONS_META_KEY = "truncatedCollections";
|
|
2626
2678
|
function hasSentinels(payload) {
|
|
2627
2679
|
return payload !== null && hasFieldSentinel(payload);
|
|
2628
2680
|
}
|
|
@@ -2657,6 +2709,8 @@ var SyncEngine = class {
|
|
|
2657
2709
|
_state;
|
|
2658
2710
|
/** Listeners de mudança de SyncState. */
|
|
2659
2711
|
_stateListeners = /* @__PURE__ */ new Set();
|
|
2712
|
+
/** Listeners de erro de ciclo de sync (P2-C — não mais engolido em silêncio). */
|
|
2713
|
+
_errorListeners = /* @__PURE__ */ new Set();
|
|
2660
2714
|
/** Cleanup functions dos listeners externos. */
|
|
2661
2715
|
_cleanups = [];
|
|
2662
2716
|
/** Timer de resync periódico. */
|
|
@@ -2715,6 +2769,19 @@ var SyncEngine = class {
|
|
|
2715
2769
|
this._stateListeners.delete(cb);
|
|
2716
2770
|
};
|
|
2717
2771
|
}
|
|
2772
|
+
/**
|
|
2773
|
+
* Registra um hook de erro de sync (P2-C). Disparado quando um ciclo falha
|
|
2774
|
+
* (exceção inesperada nas fases, falha de pull/resync ou dead-letter de uma
|
|
2775
|
+
* mutação-veneno) — o que antes era engolido com "log silencioso".
|
|
2776
|
+
* O mesmo diagnóstico também aparece em `SyncState.lastError`.
|
|
2777
|
+
* Retorna uma função de unsubscribe.
|
|
2778
|
+
*/
|
|
2779
|
+
onError(cb) {
|
|
2780
|
+
this._errorListeners.add(cb);
|
|
2781
|
+
return () => {
|
|
2782
|
+
this._errorListeners.delete(cb);
|
|
2783
|
+
};
|
|
2784
|
+
}
|
|
2718
2785
|
/**
|
|
2719
2786
|
* Força um sync imediato (I3 §10.3 `flush()`).
|
|
2720
2787
|
* Resolve quando a fila esvazia OU rejeita se o engine estiver destruído.
|
|
@@ -2747,8 +2814,10 @@ var SyncEngine = class {
|
|
|
2747
2814
|
}
|
|
2748
2815
|
await this._phase2Pull();
|
|
2749
2816
|
this._phase3Realtime();
|
|
2750
|
-
this._updateState({ status: "idle", lastSyncedAt: Date.now() });
|
|
2817
|
+
this._updateState({ status: "idle", lastSyncedAt: Date.now(), lastError: null });
|
|
2751
2818
|
} catch (err) {
|
|
2819
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2820
|
+
this._recordSyncError("cycle", `ciclo de sync falhou: ${msg}`);
|
|
2752
2821
|
this._updateState({ status: "idle" });
|
|
2753
2822
|
} finally {
|
|
2754
2823
|
this._syncing = false;
|
|
@@ -2783,6 +2852,9 @@ var SyncEngine = class {
|
|
|
2783
2852
|
async _phase1Push() {
|
|
2784
2853
|
const mutations = await this._queue.drain();
|
|
2785
2854
|
if (mutations.length === 0) return true;
|
|
2855
|
+
if (this._isInBackoff(mutations[0])) {
|
|
2856
|
+
return true;
|
|
2857
|
+
}
|
|
2786
2858
|
for (const mut of mutations) {
|
|
2787
2859
|
await this._queue.markInflight(mut.mutationId);
|
|
2788
2860
|
}
|
|
@@ -2790,10 +2862,16 @@ var SyncEngine = class {
|
|
|
2790
2862
|
try {
|
|
2791
2863
|
result = await this._transport.pushMutations(mutations);
|
|
2792
2864
|
} catch (err) {
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2865
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2866
|
+
const busChangesOnThrow = [];
|
|
2867
|
+
const [head, ...behind] = mutations;
|
|
2868
|
+
await this._retryOrDeadLetter(head, errMsg, busChangesOnThrow);
|
|
2869
|
+
for (const mut of behind) {
|
|
2870
|
+
await this._queue.requeueInflight(mut.mutationId);
|
|
2871
|
+
}
|
|
2872
|
+
if (busChangesOnThrow.length > 0) this._bus.emit(busChangesOnThrow);
|
|
2873
|
+
this._refreshPendingWrites().catch(() => {
|
|
2874
|
+
});
|
|
2797
2875
|
return false;
|
|
2798
2876
|
}
|
|
2799
2877
|
const busChanges = [];
|
|
@@ -2820,8 +2898,16 @@ var SyncEngine = class {
|
|
|
2820
2898
|
}
|
|
2821
2899
|
const processedIds = new Set(result.results.map((r) => r.mutationId));
|
|
2822
2900
|
const unprocessed = mutations.filter((m) => !processedIds.has(m.mutationId));
|
|
2823
|
-
|
|
2824
|
-
|
|
2901
|
+
if (unprocessed.length > 0) {
|
|
2902
|
+
const [boundary, ...behind] = unprocessed;
|
|
2903
|
+
await this._retryOrDeadLetter(
|
|
2904
|
+
boundary,
|
|
2905
|
+
"partial_push: muta\xE7\xE3o n\xE3o processada no lote",
|
|
2906
|
+
busChanges
|
|
2907
|
+
);
|
|
2908
|
+
for (const mut of behind) {
|
|
2909
|
+
await this._queue.requeueInflight(mut.mutationId);
|
|
2910
|
+
}
|
|
2825
2911
|
}
|
|
2826
2912
|
if (busChanges.length > 0) {
|
|
2827
2913
|
this._bus.emit(busChanges);
|
|
@@ -3013,6 +3099,67 @@ var SyncEngine = class {
|
|
|
3013
3099
|
});
|
|
3014
3100
|
}
|
|
3015
3101
|
}
|
|
3102
|
+
// ─── Dead-letter + backoff (P1-C) ────────────────────────────────────────────
|
|
3103
|
+
/**
|
|
3104
|
+
* Trata a falha transiente de UMA mutação que foi realmente tentada.
|
|
3105
|
+
*
|
|
3106
|
+
* - Se ainda há orçamento de tentativas → `markRetry` (volta pra fila com
|
|
3107
|
+
* backoff, `attempts++`).
|
|
3108
|
+
* - Se esgotou (`attempts+1 >= MAX_MUTATION_ATTEMPTS`) → DEAD-LETTER:
|
|
3109
|
+
* `markFailed` (sai do conjunto `queued`, então `drain()` para de devolvê-la
|
|
3110
|
+
* e a fila FIFO DESTRAVA para as demais coleções) + grava um ConflictRecord
|
|
3111
|
+
* `failed_max_attempts` (o produto vê via `getConflicts()`) + limpa o estado
|
|
3112
|
+
* pending do doc no cache + registra `lastError`/dispara `onError`.
|
|
3113
|
+
*/
|
|
3114
|
+
async _retryOrDeadLetter(mut, errMsg, busChanges) {
|
|
3115
|
+
if (mut.attempts + 1 < MAX_MUTATION_ATTEMPTS) {
|
|
3116
|
+
await this._queue.markRetry(mut.mutationId, errMsg);
|
|
3117
|
+
return;
|
|
3118
|
+
}
|
|
3119
|
+
await this._queue.markFailed(mut.mutationId, errMsg);
|
|
3120
|
+
const conflictRecord = {
|
|
3121
|
+
collection: mut.collection,
|
|
3122
|
+
docId: mut.docId,
|
|
3123
|
+
mutationId: mut.mutationId,
|
|
3124
|
+
losingData: mut.payload ?? {},
|
|
3125
|
+
winningData: {},
|
|
3126
|
+
reason: "failed_max_attempts",
|
|
3127
|
+
detectedAt: Date.now(),
|
|
3128
|
+
delivered: false
|
|
3129
|
+
};
|
|
3130
|
+
await this._store.appendConflict(conflictRecord);
|
|
3131
|
+
const existing = await this._store.getDoc(mut.collection, mut.docId);
|
|
3132
|
+
if (existing) {
|
|
3133
|
+
await this._store.putDoc({
|
|
3134
|
+
...existing,
|
|
3135
|
+
meta: { ...existing.meta, state: "synced", pendingMutationIds: [] }
|
|
3136
|
+
});
|
|
3137
|
+
busChanges.push({
|
|
3138
|
+
type: "modified",
|
|
3139
|
+
collection: mut.collection,
|
|
3140
|
+
doc: { id: mut.docId, data: existing.data }
|
|
3141
|
+
});
|
|
3142
|
+
}
|
|
3143
|
+
this._recordSyncError(
|
|
3144
|
+
"push",
|
|
3145
|
+
`muta\xE7\xE3o ${mut.mutationId} (${mut.collection}/${mut.docId}) descartada ap\xF3s ${mut.attempts + 1} tentativas: ${errMsg}`
|
|
3146
|
+
);
|
|
3147
|
+
}
|
|
3148
|
+
/**
|
|
3149
|
+
* `true` se a mutação (head do FIFO) ainda está dentro da janela de backoff
|
|
3150
|
+
* desde a última tentativa falha. Só se aplica a mutações já tentadas
|
|
3151
|
+
* (`attempts > 0` e `lastAttemptAt` carimbado).
|
|
3152
|
+
*/
|
|
3153
|
+
_isInBackoff(mut) {
|
|
3154
|
+
if (mut.attempts <= 0) return false;
|
|
3155
|
+
const last = mut.lastAttemptAt;
|
|
3156
|
+
if (typeof last !== "number") return false;
|
|
3157
|
+
return Date.now() < last + this._backoffDelayMs(mut.attempts);
|
|
3158
|
+
}
|
|
3159
|
+
/** Backoff exponencial keyed em `attempts`, com teto `BACKOFF_CAP_MS`. */
|
|
3160
|
+
_backoffDelayMs(attempts) {
|
|
3161
|
+
return Math.min(BACKOFF_BASE_MS * 2 ** (attempts - 1), BACKOFF_CAP_MS);
|
|
3162
|
+
}
|
|
3016
3163
|
// ─── FASE 2 — pull (reconciliar o cache) ─────────────────────────────────────
|
|
3017
3164
|
/**
|
|
3018
3165
|
* Busca mudanças do servidor e aplica ao cache via ConflictResolver.
|
|
@@ -3052,10 +3199,14 @@ var SyncEngine = class {
|
|
|
3052
3199
|
}
|
|
3053
3200
|
const busChanges = [];
|
|
3054
3201
|
await this._applyServerDocs(resyncResult.docs, busChanges, true);
|
|
3202
|
+
const truncatedCollections = resyncResult.truncatedCollections ?? [];
|
|
3203
|
+
const truncatedSet = new Set(truncatedCollections);
|
|
3204
|
+
await this._store.setMeta(TRUNCATED_COLLECTIONS_META_KEY, truncatedCollections);
|
|
3055
3205
|
const returnedKeys = new Set(
|
|
3056
3206
|
resyncResult.docs.map((d) => `${d.collection}::${d.id}`)
|
|
3057
3207
|
);
|
|
3058
3208
|
for (const col of collections) {
|
|
3209
|
+
if (truncatedSet.has(col)) continue;
|
|
3059
3210
|
const queryResult = await this._store.listDocs(col, {});
|
|
3060
3211
|
for (const { id } of queryResult.docs) {
|
|
3061
3212
|
const key = `${col}::${id}`;
|
|
@@ -3215,7 +3366,8 @@ var SyncEngine = class {
|
|
|
3215
3366
|
status: isOnline ? "idle" : "offline",
|
|
3216
3367
|
pendingWrites: 0,
|
|
3217
3368
|
lastSyncedAt: null,
|
|
3218
|
-
isLeaderTab: this._tabCoordinator.isLeader()
|
|
3369
|
+
isLeaderTab: this._tabCoordinator.isLeader(),
|
|
3370
|
+
lastError: null
|
|
3219
3371
|
};
|
|
3220
3372
|
}
|
|
3221
3373
|
/**
|
|
@@ -3225,7 +3377,7 @@ var SyncEngine = class {
|
|
|
3225
3377
|
_updateState(partial) {
|
|
3226
3378
|
const prev = this._state;
|
|
3227
3379
|
const next = { ...prev, ...partial };
|
|
3228
|
-
const changed = prev.status !== next.status || prev.pendingWrites !== next.pendingWrites || prev.lastSyncedAt !== next.lastSyncedAt || prev.isLeaderTab !== next.isLeaderTab;
|
|
3380
|
+
const changed = prev.status !== next.status || prev.pendingWrites !== next.pendingWrites || prev.lastSyncedAt !== next.lastSyncedAt || prev.isLeaderTab !== next.isLeaderTab || (prev.lastError ?? null) !== (next.lastError ?? null);
|
|
3229
3381
|
this._state = next;
|
|
3230
3382
|
if (changed) {
|
|
3231
3383
|
this._emitState(next);
|
|
@@ -3239,6 +3391,21 @@ var SyncEngine = class {
|
|
|
3239
3391
|
}
|
|
3240
3392
|
}
|
|
3241
3393
|
}
|
|
3394
|
+
/**
|
|
3395
|
+
* P2-C: registra a falha de um ciclo de sync — antes engolida em silêncio.
|
|
3396
|
+
* Publica em `SyncState.lastError` (visível via `onSyncStateChanged`) e
|
|
3397
|
+
* dispara o hook `onError`. Nunca lança (diagnóstico é best-effort).
|
|
3398
|
+
*/
|
|
3399
|
+
_recordSyncError(phase, message) {
|
|
3400
|
+
this._updateState({ lastError: message });
|
|
3401
|
+
const event = { phase, message, at: Date.now() };
|
|
3402
|
+
for (const listener of this._errorListeners) {
|
|
3403
|
+
try {
|
|
3404
|
+
listener({ ...event });
|
|
3405
|
+
} catch {
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3242
3409
|
/**
|
|
3243
3410
|
* Atualiza `pendingWrites` no estado.
|
|
3244
3411
|
* Chamado de forma assíncrona quando necessário.
|
|
@@ -4048,7 +4215,9 @@ var DbCollectionRefImpl = class {
|
|
|
4048
4215
|
const isOnline = this._isOnline();
|
|
4049
4216
|
const syncState = this._engine.getSyncState();
|
|
4050
4217
|
const nextCursor = buildNextCursor(result.docs, effectiveLimit);
|
|
4051
|
-
const
|
|
4218
|
+
const truncatedRaw = await this._store.getMeta(TRUNCATED_COLLECTIONS_META_KEY);
|
|
4219
|
+
const truncated = Array.isArray(truncatedRaw) && truncatedRaw.includes(this._collection);
|
|
4220
|
+
const stale = !isOnline || syncState.status === "offline" || truncated;
|
|
4052
4221
|
const fromCache = hasPending || syncState.lastSyncedAt === null || stale;
|
|
4053
4222
|
return {
|
|
4054
4223
|
docs: result.docs.map((d) => ({ id: d.id, data: d.data })),
|
|
@@ -4056,7 +4225,8 @@ var DbCollectionRefImpl = class {
|
|
|
4056
4225
|
fromCache,
|
|
4057
4226
|
stale,
|
|
4058
4227
|
hasPendingWrites: hasPending,
|
|
4059
|
-
changes: []
|
|
4228
|
+
changes: [],
|
|
4229
|
+
truncated
|
|
4060
4230
|
};
|
|
4061
4231
|
}
|
|
4062
4232
|
// ── CRUD ────────────────────────────────────────────────────────────────────
|
|
@@ -4502,6 +4672,9 @@ var NeetruDbDocumentsImpl = class {
|
|
|
4502
4672
|
async getConflicts() {
|
|
4503
4673
|
return this._store.listConflicts();
|
|
4504
4674
|
}
|
|
4675
|
+
onError(cb) {
|
|
4676
|
+
return this._engine.onError(cb);
|
|
4677
|
+
}
|
|
4505
4678
|
};
|
|
4506
4679
|
async function createOfflineDocumentsNamespace(opts) {
|
|
4507
4680
|
const store = isIndexedDBUnavailable() ? new MemoryStore() : new LocalStore(opts.dbName);
|
|
@@ -4977,6 +5150,7 @@ var defaultWebSocketFactory = (url) => {
|
|
|
4977
5150
|
// src/db/client-db.ts
|
|
4978
5151
|
var DATASTORE_COLLECTION_ENDPOINT = (collection) => `/api/sdk/v1/datastore/${encodeURIComponent(collection)}`;
|
|
4979
5152
|
var DATASTORE_DOC_ENDPOINT = (collection, docId) => `/api/sdk/v1/datastore/${encodeURIComponent(collection)}/${encodeURIComponent(docId)}`;
|
|
5153
|
+
var DOCUMENTS_RESYNC_PAGE_CAP = 200;
|
|
4980
5154
|
function resolveTransport(transport, opts, config) {
|
|
4981
5155
|
if (opts._transport) {
|
|
4982
5156
|
return opts._transport;
|
|
@@ -5089,6 +5263,7 @@ function createRestSyncTransport(config) {
|
|
|
5089
5263
|
const tenantHeaders = tenantScopeId ? { "x-neetru-tenant": tenantScopeId } : void 0;
|
|
5090
5264
|
const now = Date.now();
|
|
5091
5265
|
const docs = [];
|
|
5266
|
+
const truncatedCollections = [];
|
|
5092
5267
|
for (const collection of collections) {
|
|
5093
5268
|
let raw;
|
|
5094
5269
|
try {
|
|
@@ -5098,11 +5273,11 @@ function createRestSyncTransport(config) {
|
|
|
5098
5273
|
requireAuth: true,
|
|
5099
5274
|
retries: 2,
|
|
5100
5275
|
headers: tenantHeaders,
|
|
5101
|
-
// Teto do Core
|
|
5102
|
-
//
|
|
5103
|
-
// deleção-por-ausência
|
|
5104
|
-
//
|
|
5105
|
-
query: { limit:
|
|
5276
|
+
// Teto do Core (DOCUMENTS_RESYNC_PAGE_CAP). Coleções acima dele vêm
|
|
5277
|
+
// TRUNCADAS — reportadas em `truncatedCollections` p/ o SyncEngine
|
|
5278
|
+
// (a) NÃO rodar deleção-por-ausência e (b) sinalizar
|
|
5279
|
+
// `DbListResult.truncated`. Paginação por cursor é tarefa Core (gated).
|
|
5280
|
+
query: { limit: DOCUMENTS_RESYNC_PAGE_CAP }
|
|
5106
5281
|
});
|
|
5107
5282
|
} catch (err) {
|
|
5108
5283
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -5113,6 +5288,9 @@ function createRestSyncTransport(config) {
|
|
|
5113
5288
|
}
|
|
5114
5289
|
const resp = raw;
|
|
5115
5290
|
const items = Array.isArray(resp?.items) ? resp.items : [];
|
|
5291
|
+
if (items.length >= DOCUMENTS_RESYNC_PAGE_CAP) {
|
|
5292
|
+
truncatedCollections.push(collection);
|
|
5293
|
+
}
|
|
5116
5294
|
for (const item of items) {
|
|
5117
5295
|
if (!item || typeof item !== "object") continue;
|
|
5118
5296
|
const record = item;
|
|
@@ -5140,7 +5318,7 @@ function createRestSyncTransport(config) {
|
|
|
5140
5318
|
});
|
|
5141
5319
|
}
|
|
5142
5320
|
}
|
|
5143
|
-
return { docs, newWatermark: now };
|
|
5321
|
+
return { docs, newWatermark: now, truncatedCollections };
|
|
5144
5322
|
}
|
|
5145
5323
|
};
|
|
5146
5324
|
}
|
|
@@ -5202,20 +5380,20 @@ function buildTicketProvider(config, opts) {
|
|
|
5202
5380
|
return ticket;
|
|
5203
5381
|
};
|
|
5204
5382
|
}
|
|
5205
|
-
var
|
|
5206
|
-
function
|
|
5207
|
-
if (
|
|
5208
|
-
if (dbOpts.dbId) return;
|
|
5383
|
+
var _hasWarnedDbIdIgnored = false;
|
|
5384
|
+
function warnDbIdIgnoredOnce(config, dbOpts) {
|
|
5385
|
+
if (_hasWarnedDbIdIgnored) return;
|
|
5386
|
+
if (!dbOpts.dbId) return;
|
|
5209
5387
|
if (config.env === "prod") return;
|
|
5210
5388
|
if (typeof window === "undefined") return;
|
|
5211
5389
|
if (typeof console === "undefined" || typeof console.warn !== "function") return;
|
|
5212
|
-
|
|
5390
|
+
_hasWarnedDbIdIgnored = true;
|
|
5213
5391
|
console.warn(
|
|
5214
|
-
|
|
5392
|
+
'[neetru/sdk] client.db recebeu `dbId` ("' + dbOpts.dbId + '") mas ele N\xC3O roteia nem escopa nada no servidor: as escritas do mundo Documentos (add/set/update/remove/list) SEMPRE caem no datastore gen\xE9rico do Core, escopado s\xF3 por tenant/produto (header x-neetru-tenant). `dbId` apenas nomeia o cache offline LOCAL (IndexedDB). ATEN\xC7\xC3O: usar dbIds distintos no MESMO tenant/produto N\xC3O isola os dados no servidor \u2014 eles se misturam (co-mingling). Veja o JSDoc de NeetruDbOptions.dbId.'
|
|
5215
5393
|
);
|
|
5216
5394
|
}
|
|
5217
5395
|
function createNeetruDb(config, dbOpts = {}) {
|
|
5218
|
-
|
|
5396
|
+
warnDbIdIgnoredOnce(config, dbOpts);
|
|
5219
5397
|
let resolvedTransport;
|
|
5220
5398
|
if (dbOpts.transport !== void 0) {
|
|
5221
5399
|
resolvedTransport = dbOpts.transport;
|
|
@@ -5293,6 +5471,20 @@ function createNeetruDb(config, dbOpts = {}) {
|
|
|
5293
5471
|
async getConflicts() {
|
|
5294
5472
|
const docs = await getDocsPromise();
|
|
5295
5473
|
return docs.getConflicts();
|
|
5474
|
+
},
|
|
5475
|
+
onError(cb) {
|
|
5476
|
+
if (_docsResolved) return _docsResolved.onError(cb);
|
|
5477
|
+
let unsub = null;
|
|
5478
|
+
let cancelled = false;
|
|
5479
|
+
getDocsPromise().then((docs) => {
|
|
5480
|
+
if (!cancelled) {
|
|
5481
|
+
unsub = docs.onError(cb);
|
|
5482
|
+
}
|
|
5483
|
+
});
|
|
5484
|
+
return () => {
|
|
5485
|
+
cancelled = true;
|
|
5486
|
+
unsub?.();
|
|
5487
|
+
};
|
|
5296
5488
|
}
|
|
5297
5489
|
};
|
|
5298
5490
|
}
|
|
@@ -7839,7 +8031,7 @@ function createNeetruClient(config = {}) {
|
|
|
7839
8031
|
init_errors();
|
|
7840
8032
|
init_db_errors();
|
|
7841
8033
|
init_http();
|
|
7842
|
-
var VERSION = "3.4.
|
|
8034
|
+
var VERSION = "3.4.1";
|
|
7843
8035
|
|
|
7844
8036
|
export { DEFAULT_BASE_URL, DEV_FIXTURE_USER, MockAi, MockAuth, MockCheckout, MockDb, MockEntitlements, MockNotifications, MockSupport, MockUsage, MockWebhooks, NEETRU_SENTINEL_KEY, NeetruDbError, NeetruError, VERSION, checkCoreVersionCompat, createAiNamespace, createCheckoutNamespace, createNeetruClient, createNeetruDb, createNotificationsNamespace, createWebhooksNamespace, increment, isFieldSentinel, isIncrementSentinel, isServerTimestampSentinel, serverTimestamp, verifyWebhookRequest, verifyWebhookSignature };
|
|
7845
8037
|
//# sourceMappingURL=index.mjs.map
|