@absolutejs/sync 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine/devtools.d.ts +27 -0
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.js +166 -6
- package/dist/engine/index.js.map +7 -6
- package/dist/engine/pack.d.ts +138 -0
- package/dist/engine/schedule.d.ts +14 -0
- package/dist/engine/syncEngine.d.ts +13 -0
- package/dist/index.js +164 -6
- package/dist/index.js.map +6 -5
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync packs — Convex Components without the lock-in. A pack bundles
|
|
3
|
+
* schemas + collections + mutations + scheduled + permissions + readers/
|
|
4
|
+
* writers + CRDT field declarations into one npm-distributable module
|
|
5
|
+
* registered with a single {@link SyncEngine.registerPack} call.
|
|
6
|
+
*
|
|
7
|
+
* See `syncPacks.design.md` for the rationale and the worked examples.
|
|
8
|
+
*
|
|
9
|
+
* Pack design rules (enforced at register time):
|
|
10
|
+
*
|
|
11
|
+
* - A pack declares which tables it `ownsTables`. Two registered packs
|
|
12
|
+
* cannot claim the same table; the host app's directly-registered
|
|
13
|
+
* tables are NOT counted (host registrations always win).
|
|
14
|
+
* - Name construction (namespacing) is the pack's job — each published
|
|
15
|
+
* pack ships as a factory `create<Name>Pack(config)` that builds names
|
|
16
|
+
* from a `tablePrefix` and the host's user/auth context.
|
|
17
|
+
* - Packs compose via the subscription layer (read each other's
|
|
18
|
+
* collections), never via cross-pack `runMutation` calls.
|
|
19
|
+
*/
|
|
20
|
+
import type { CollectionDefinition, JoinCollectionDefinition } from './collection';
|
|
21
|
+
import type { GraphCollectionDefinition } from './graph';
|
|
22
|
+
import type { MutationDefinition, TableWriter } from './mutation';
|
|
23
|
+
import type { PermissionsDefinition } from './permissions';
|
|
24
|
+
import type { ReactiveQueryDefinition, TableReader } from './reactive';
|
|
25
|
+
import type { ScheduleDefinition } from './schedule';
|
|
26
|
+
import type { SchemaDefinition } from './schema';
|
|
27
|
+
import type { SearchCollectionDefinition } from './search';
|
|
28
|
+
import type { CrdtMergeable } from '../crdt';
|
|
29
|
+
/**
|
|
30
|
+
* Same shape as the engine's per-table CRDT field map (see
|
|
31
|
+
* {@link SyncEngine.registerCrdt}). A pack declares CRDT field types
|
|
32
|
+
* here; the engine wires them on registration.
|
|
33
|
+
*/
|
|
34
|
+
export type CrdtFieldsMap = Record<string, Record<string, CrdtMergeable<unknown>>>;
|
|
35
|
+
/**
|
|
36
|
+
* A pack — a self-contained bundle of every registration the engine
|
|
37
|
+
* already accepts. The engine's `registerPack(pack)` dispatches each
|
|
38
|
+
* field to the matching `engine.register*` method. There is no new
|
|
39
|
+
* persistence path; packs are pure composition.
|
|
40
|
+
*/
|
|
41
|
+
export type SyncPack = {
|
|
42
|
+
/**
|
|
43
|
+
* Pack identifier. Used for devtools labelling and conflict
|
|
44
|
+
* diagnostics. Should match the npm package name (e.g.
|
|
45
|
+
* "@absolutejs/sync-pack-presence").
|
|
46
|
+
*/
|
|
47
|
+
name: string;
|
|
48
|
+
/**
|
|
49
|
+
* Pack semver. Surfaced in {@link EngineInspection.packs} and in
|
|
50
|
+
* conflict diagnostics (e.g. "table 'comments' is owned by
|
|
51
|
+
* sync-pack-comments@2.1.0").
|
|
52
|
+
*/
|
|
53
|
+
version: string;
|
|
54
|
+
/**
|
|
55
|
+
* Tables this pack OWNS. The engine rejects another pack that also
|
|
56
|
+
* claims one of these. Direct host registrations (e.g.
|
|
57
|
+
* `engine.registerSchema("foo", ...)`) are NOT tracked as ownership,
|
|
58
|
+
* so the host can still extend a pack's table or override its
|
|
59
|
+
* schema/permissions.
|
|
60
|
+
*/
|
|
61
|
+
ownsTables: string[];
|
|
62
|
+
/**
|
|
63
|
+
* Tables this pack reads but does NOT own (e.g. a comments pack
|
|
64
|
+
* reads the host's `users` table for author info). Reported in
|
|
65
|
+
* {@link EngineInspection.packs}; not enforced unless
|
|
66
|
+
* {@link requireDependencies} is `true`.
|
|
67
|
+
*/
|
|
68
|
+
readsTables?: string[];
|
|
69
|
+
/**
|
|
70
|
+
* When `true`, the engine throws {@link PackMissingDependencyError}
|
|
71
|
+
* at register time if any table in `readsTables` has no registered
|
|
72
|
+
* reader. Default `false` — host-app reads can be wired lazily.
|
|
73
|
+
*/
|
|
74
|
+
requireDependencies?: boolean;
|
|
75
|
+
schemas?: SchemaDefinition;
|
|
76
|
+
permissions?: PermissionsDefinition<any>;
|
|
77
|
+
readers?: Record<string, TableReader<any>>;
|
|
78
|
+
writers?: Record<string, TableWriter<any, any, any>>;
|
|
79
|
+
crdt?: CrdtFieldsMap;
|
|
80
|
+
collections?: CollectionDefinition<any, any, any>[];
|
|
81
|
+
joinCollections?: JoinCollectionDefinition<any, any, any, any, any>[];
|
|
82
|
+
graphCollections?: GraphCollectionDefinition<any, any, any>[];
|
|
83
|
+
searchCollections?: SearchCollectionDefinition<any, any, any>[];
|
|
84
|
+
reactiveQueries?: ReactiveQueryDefinition<any, any, any>[];
|
|
85
|
+
mutations?: MutationDefinition<any, any, any>[];
|
|
86
|
+
schedules?: ScheduleDefinition[];
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Pack metadata stored on the engine and surfaced via
|
|
90
|
+
* {@link EngineInspection.packs}.
|
|
91
|
+
*/
|
|
92
|
+
export type RegisteredPack = {
|
|
93
|
+
name: string;
|
|
94
|
+
version: string;
|
|
95
|
+
ownsTables: string[];
|
|
96
|
+
readsTables: string[];
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Thrown by {@link SyncEngine.registerPack} when a pack claims a table
|
|
100
|
+
* that another registered pack already owns. The message names both
|
|
101
|
+
* packs and the colliding table so the operator can pick a
|
|
102
|
+
* `tablePrefix`.
|
|
103
|
+
*/
|
|
104
|
+
export declare class PackTableConflictError extends Error {
|
|
105
|
+
readonly table: string;
|
|
106
|
+
readonly existingPack: string;
|
|
107
|
+
readonly newPack: string;
|
|
108
|
+
constructor(table: string, existingPack: string, newPack: string);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Thrown by {@link SyncEngine.registerPack} when a pack has
|
|
112
|
+
* `requireDependencies: true` and at least one table in
|
|
113
|
+
* {@link SyncPack.readsTables} has no registered reader at register
|
|
114
|
+
* time. Pack authors opt into this when their pack cannot function
|
|
115
|
+
* without the host having wired the dependency up front.
|
|
116
|
+
*/
|
|
117
|
+
export declare class PackMissingDependencyError extends Error {
|
|
118
|
+
readonly pack: string;
|
|
119
|
+
readonly missingTable: string;
|
|
120
|
+
constructor(pack: string, missingTable: string);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Identity helper. A pack is plain data — the helper exists for type
|
|
124
|
+
* inference, not for runtime behavior.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* export const createPresencePack = (config: PresencePackConfig) =>
|
|
128
|
+
* defineSyncPack({
|
|
129
|
+
* name: '@absolutejs/sync-pack-presence',
|
|
130
|
+
* version: '0.1.0',
|
|
131
|
+
* ownsTables: [resolveTableName('presence', config.tablePrefix)],
|
|
132
|
+
* schemas: { ... },
|
|
133
|
+
* collections: [ ... ],
|
|
134
|
+
* mutations: [ ... ],
|
|
135
|
+
* schedules: [ ... ],
|
|
136
|
+
* });
|
|
137
|
+
*/
|
|
138
|
+
export declare const defineSyncPack: (pack: SyncPack) => SyncPack;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MutationActions } from './mutation';
|
|
2
2
|
import type { ReadHandle } from './reactive';
|
|
3
|
+
import type { RetryPolicy } from './retry';
|
|
3
4
|
/**
|
|
4
5
|
* Scheduled functions — server-triggered work whose effects flow through the
|
|
5
6
|
* change feed, so what a schedule writes goes live to subscribers with no extra
|
|
@@ -30,6 +31,19 @@ export type ScheduleDefinition = {
|
|
|
30
31
|
pattern: string;
|
|
31
32
|
/** The work to run on each fire. Writes via `ctx.actions` go live. */
|
|
32
33
|
run: (ctx: ScheduleContext) => Promise<void> | void;
|
|
34
|
+
/**
|
|
35
|
+
* Opt-in retry of the whole handler on classified-as-retryable errors —
|
|
36
|
+
* same shape and defaults as {@link MutationDefinition.retry}. When set
|
|
37
|
+
* and `run` throws a retryable error, the engine discards the buffered
|
|
38
|
+
* changes, awaits a backoff, and re-runs the handler with a fresh
|
|
39
|
+
* transaction. The handler MUST be idempotent under retry (external
|
|
40
|
+
* side effects fire more than once).
|
|
41
|
+
*
|
|
42
|
+
* For per-item retry (e.g. one of many emails failing), write that
|
|
43
|
+
* loop inside the handler — this outer retry covers transient
|
|
44
|
+
* infrastructure failures of the whole fire, not per-item logic.
|
|
45
|
+
*/
|
|
46
|
+
retry?: RetryPolicy;
|
|
33
47
|
};
|
|
34
48
|
/**
|
|
35
49
|
* Define a scheduled function. Identity at runtime (for type inference). Register
|
|
@@ -4,6 +4,7 @@ import type { MutationDefinition, TableWriter, TransactionRunner } from './mutat
|
|
|
4
4
|
import type { ReactiveQueryDefinition, TableReader } from './reactive';
|
|
5
5
|
import { type BridgeFetchConfig, type HandlerMetricsHook } from './sandbox';
|
|
6
6
|
import type { PermissionsDefinition, TablePermissions } from './permissions';
|
|
7
|
+
import type { SyncPack } from './pack';
|
|
7
8
|
import type { SearchCollectionDefinition } from './search';
|
|
8
9
|
import type { ScheduleDefinition } from './schedule';
|
|
9
10
|
import type { EngineActivity, EngineInspection } from './devtools';
|
|
@@ -213,6 +214,18 @@ export type SyncEngine = {
|
|
|
213
214
|
* }
|
|
214
215
|
*/
|
|
215
216
|
streamChanges: (options?: StreamChangesOptions) => AsyncIterable<LoggedChange>;
|
|
217
|
+
/**
|
|
218
|
+
* Register a {@link SyncPack} — a self-contained bundle of schemas,
|
|
219
|
+
* permissions, readers/writers, collections, mutations, and schedules.
|
|
220
|
+
* Dispatches each field to the matching `register*` method. Rejects
|
|
221
|
+
* with {@link PackTableConflictError} if the pack claims a table
|
|
222
|
+
* another registered pack already owns; with
|
|
223
|
+
* {@link PackMissingDependencyError} if `requireDependencies` is set
|
|
224
|
+
* and a `readsTables` entry has no registered reader.
|
|
225
|
+
*
|
|
226
|
+
* See `syncPacks.design.md` for the rationale.
|
|
227
|
+
*/
|
|
228
|
+
registerPack: (pack: SyncPack) => void;
|
|
216
229
|
};
|
|
217
230
|
/**
|
|
218
231
|
* A single committed change as it appears in the engine's change log and on
|
package/dist/index.js
CHANGED
|
@@ -935,6 +935,32 @@ var fireMetrics = (hook, record) => {
|
|
|
935
935
|
}
|
|
936
936
|
};
|
|
937
937
|
|
|
938
|
+
// src/engine/pack.ts
|
|
939
|
+
class PackTableConflictError extends Error {
|
|
940
|
+
table;
|
|
941
|
+
existingPack;
|
|
942
|
+
newPack;
|
|
943
|
+
constructor(table, existingPack, newPack) {
|
|
944
|
+
super(`Pack "${newPack}" claims table "${table}", but "${existingPack}" already owns it. Use a tablePrefix on one of them.`);
|
|
945
|
+
this.name = "PackTableConflictError";
|
|
946
|
+
this.table = table;
|
|
947
|
+
this.existingPack = existingPack;
|
|
948
|
+
this.newPack = newPack;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
class PackMissingDependencyError extends Error {
|
|
953
|
+
pack;
|
|
954
|
+
missingTable;
|
|
955
|
+
constructor(pack, missingTable) {
|
|
956
|
+
super(`Pack "${pack}" requires a reader for table "${missingTable}" but none is registered. Call engine.registerReader("${missingTable}", ...) before engine.registerPack.`);
|
|
957
|
+
this.name = "PackMissingDependencyError";
|
|
958
|
+
this.pack = pack;
|
|
959
|
+
this.missingTable = missingTable;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
var defineSyncPack = (pack) => pack;
|
|
963
|
+
|
|
938
964
|
// src/engine/search.ts
|
|
939
965
|
var SEARCH_SCORE_FIELD = "_score";
|
|
940
966
|
var defineSearchCollection = (definition) => ({
|
|
@@ -1044,6 +1070,8 @@ var createSyncEngine = (options = {}) => {
|
|
|
1044
1070
|
const writers = new Map;
|
|
1045
1071
|
const readers = new Map;
|
|
1046
1072
|
const schedules = new Map;
|
|
1073
|
+
const packTableOwners = new Map;
|
|
1074
|
+
const registeredPacks = [];
|
|
1047
1075
|
const permissions = new Map;
|
|
1048
1076
|
for (const [table, rules] of Object.entries(options.permissions ?? {})) {
|
|
1049
1077
|
permissions.set(table, rules);
|
|
@@ -1775,7 +1803,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
1775
1803
|
}
|
|
1776
1804
|
};
|
|
1777
1805
|
};
|
|
1778
|
-
|
|
1806
|
+
const engine = {
|
|
1779
1807
|
register: (collection) => {
|
|
1780
1808
|
registry.set(collection.name, collection);
|
|
1781
1809
|
for (const table of collection.tables ?? [collection.name]) {
|
|
@@ -2050,13 +2078,136 @@ var createSyncEngine = (options = {}) => {
|
|
|
2050
2078
|
throw new Error(`Unknown schedule "${name}"`);
|
|
2051
2079
|
}
|
|
2052
2080
|
const runHandler = async (tx) => {
|
|
2053
|
-
const { actions, buffered
|
|
2081
|
+
const { actions, buffered } = makeActions(tx, {}, false);
|
|
2054
2082
|
const db = makeReadHandle({}, new Set, new Set, [], false);
|
|
2055
2083
|
await schedule.run({ actions, db });
|
|
2056
|
-
return
|
|
2084
|
+
return buffered;
|
|
2057
2085
|
};
|
|
2058
|
-
const
|
|
2059
|
-
|
|
2086
|
+
const retry = schedule.retry;
|
|
2087
|
+
const maxAttempts = retry === undefined ? 1 : retry.maxAttempts ?? 5;
|
|
2088
|
+
const isRetryable = retry?.isRetryable ?? isSerializationFailure;
|
|
2089
|
+
const computeDelay = retry?.backoff ?? exponentialBackoff();
|
|
2090
|
+
const maxElapsedMs = retry?.maxElapsedMs ?? 30000;
|
|
2091
|
+
const startedAt = Date.now();
|
|
2092
|
+
let lastError;
|
|
2093
|
+
let attemptsMade = 0;
|
|
2094
|
+
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
2095
|
+
attemptsMade = attempt;
|
|
2096
|
+
try {
|
|
2097
|
+
const buffered = runInTransaction !== undefined ? await runInTransaction((tx) => runHandler(tx)) : await runHandler(undefined);
|
|
2098
|
+
await applyChangeBatch(buffered);
|
|
2099
|
+
emitActivity({
|
|
2100
|
+
type: "schedule",
|
|
2101
|
+
at: Date.now(),
|
|
2102
|
+
name,
|
|
2103
|
+
status: "ok"
|
|
2104
|
+
});
|
|
2105
|
+
return;
|
|
2106
|
+
} catch (error) {
|
|
2107
|
+
lastError = error;
|
|
2108
|
+
const elapsedMs = Date.now() - startedAt;
|
|
2109
|
+
const canRetry = attempt < maxAttempts && isRetryable(error) && elapsedMs < maxElapsedMs;
|
|
2110
|
+
if (!canRetry)
|
|
2111
|
+
break;
|
|
2112
|
+
const rawDelay = computeDelay(attempt);
|
|
2113
|
+
const remaining = maxElapsedMs - elapsedMs;
|
|
2114
|
+
if (remaining <= 0)
|
|
2115
|
+
break;
|
|
2116
|
+
const delayMs = Math.max(0, Math.min(rawDelay, remaining));
|
|
2117
|
+
emitActivity({
|
|
2118
|
+
type: "scheduleRetry",
|
|
2119
|
+
at: Date.now(),
|
|
2120
|
+
name,
|
|
2121
|
+
attempt,
|
|
2122
|
+
delayMs,
|
|
2123
|
+
errorName: error instanceof Error ? error.name : "Error",
|
|
2124
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
2125
|
+
});
|
|
2126
|
+
if (delayMs > 0) {
|
|
2127
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
emitActivity({
|
|
2132
|
+
type: "schedule",
|
|
2133
|
+
at: Date.now(),
|
|
2134
|
+
name,
|
|
2135
|
+
status: "error"
|
|
2136
|
+
});
|
|
2137
|
+
if (attemptsMade > 1) {
|
|
2138
|
+
throw new RetriesExhaustedError(attemptsMade, Date.now() - startedAt, lastError);
|
|
2139
|
+
}
|
|
2140
|
+
throw lastError;
|
|
2141
|
+
},
|
|
2142
|
+
registerPack: (pack) => {
|
|
2143
|
+
for (const table of pack.ownsTables) {
|
|
2144
|
+
const existing = packTableOwners.get(table);
|
|
2145
|
+
if (existing !== undefined) {
|
|
2146
|
+
throw new PackTableConflictError(table, existing, pack.name);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
if (pack.requireDependencies === true) {
|
|
2150
|
+
for (const table of pack.readsTables ?? []) {
|
|
2151
|
+
if (!readers.has(table)) {
|
|
2152
|
+
throw new PackMissingDependencyError(pack.name, table);
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
if (pack.schemas !== undefined) {
|
|
2157
|
+
for (const [table, schema] of Object.entries(pack.schemas)) {
|
|
2158
|
+
engine.registerSchema(table, schema);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
if (pack.permissions !== undefined) {
|
|
2162
|
+
for (const [table, rules] of Object.entries(pack.permissions)) {
|
|
2163
|
+
engine.registerPermissions(table, rules);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
if (pack.readers !== undefined) {
|
|
2167
|
+
for (const [table, reader] of Object.entries(pack.readers)) {
|
|
2168
|
+
engine.registerReader(table, reader);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
if (pack.writers !== undefined) {
|
|
2172
|
+
for (const [table, writer] of Object.entries(pack.writers)) {
|
|
2173
|
+
engine.registerWriter(table, writer);
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
if (pack.crdt !== undefined) {
|
|
2177
|
+
for (const [table, fields] of Object.entries(pack.crdt)) {
|
|
2178
|
+
engine.registerCrdt(table, fields);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
for (const collection of pack.collections ?? []) {
|
|
2182
|
+
engine.register(collection);
|
|
2183
|
+
}
|
|
2184
|
+
for (const collection of pack.joinCollections ?? []) {
|
|
2185
|
+
engine.registerJoin(collection);
|
|
2186
|
+
}
|
|
2187
|
+
for (const collection of pack.graphCollections ?? []) {
|
|
2188
|
+
engine.registerGraph(collection);
|
|
2189
|
+
}
|
|
2190
|
+
for (const collection of pack.searchCollections ?? []) {
|
|
2191
|
+
engine.registerSearch(collection);
|
|
2192
|
+
}
|
|
2193
|
+
for (const query of pack.reactiveQueries ?? []) {
|
|
2194
|
+
engine.registerReactive(query);
|
|
2195
|
+
}
|
|
2196
|
+
for (const mutation of pack.mutations ?? []) {
|
|
2197
|
+
engine.registerMutation(mutation);
|
|
2198
|
+
}
|
|
2199
|
+
for (const schedule of pack.schedules ?? []) {
|
|
2200
|
+
engine.registerSchedule(schedule);
|
|
2201
|
+
}
|
|
2202
|
+
for (const table of pack.ownsTables) {
|
|
2203
|
+
packTableOwners.set(table, pack.name);
|
|
2204
|
+
}
|
|
2205
|
+
registeredPacks.push({
|
|
2206
|
+
name: pack.name,
|
|
2207
|
+
version: pack.version,
|
|
2208
|
+
ownsTables: [...pack.ownsTables],
|
|
2209
|
+
readsTables: [...pack.readsTables ?? []]
|
|
2210
|
+
});
|
|
2060
2211
|
},
|
|
2061
2212
|
inspect: () => {
|
|
2062
2213
|
const collections = [...registry.entries()].map(([name, def]) => {
|
|
@@ -2096,6 +2247,12 @@ var createSyncEngine = (options = {}) => {
|
|
|
2096
2247
|
version: entry.version,
|
|
2097
2248
|
table: entry.table,
|
|
2098
2249
|
op: entry.change.op
|
|
2250
|
+
})),
|
|
2251
|
+
packs: registeredPacks.map((pack) => ({
|
|
2252
|
+
name: pack.name,
|
|
2253
|
+
version: pack.version,
|
|
2254
|
+
ownsTables: [...pack.ownsTables],
|
|
2255
|
+
readsTables: [...pack.readsTables]
|
|
2099
2256
|
}))
|
|
2100
2257
|
};
|
|
2101
2258
|
},
|
|
@@ -2182,6 +2339,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2182
2339
|
};
|
|
2183
2340
|
}
|
|
2184
2341
|
};
|
|
2342
|
+
return engine;
|
|
2185
2343
|
};
|
|
2186
2344
|
|
|
2187
2345
|
// src/engine/cdc.ts
|
|
@@ -2460,5 +2618,5 @@ export {
|
|
|
2460
2618
|
createPresenceHub
|
|
2461
2619
|
};
|
|
2462
2620
|
|
|
2463
|
-
//# debugId=
|
|
2621
|
+
//# debugId=483AEB81CDF95A5764756E2164756E21
|
|
2464
2622
|
//# sourceMappingURL=index.js.map
|