@secondlayer/subgraphs 3.21.0 → 3.23.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/src/index.d.ts +238 -17
- package/dist/src/index.js +389 -52
- package/dist/src/index.js.map +12 -11
- package/dist/src/runtime/block-processor.d.ts +111 -10
- package/dist/src/runtime/block-processor.js +263 -31
- package/dist/src/runtime/block-processor.js.map +9 -8
- package/dist/src/runtime/catchup.d.ts +111 -10
- package/dist/src/runtime/catchup.js +263 -31
- package/dist/src/runtime/catchup.js.map +9 -8
- package/dist/src/runtime/context.d.ts +111 -11
- package/dist/src/runtime/context.js +166 -12
- package/dist/src/runtime/context.js.map +7 -6
- package/dist/src/runtime/processor.js +272 -35
- package/dist/src/runtime/processor.js.map +10 -9
- package/dist/src/runtime/reindex.d.ts +111 -10
- package/dist/src/runtime/reindex.js +263 -31
- package/dist/src/runtime/reindex.js.map +9 -8
- package/dist/src/runtime/reorg.d.ts +111 -10
- package/dist/src/runtime/reorg.js +268 -31
- package/dist/src/runtime/reorg.js.map +10 -9
- package/dist/src/runtime/replay.d.ts +3 -3
- package/dist/src/runtime/replay.js +30 -6
- package/dist/src/runtime/replay.js.map +4 -4
- package/dist/src/runtime/runner.d.ts +191 -17
- package/dist/src/runtime/source-matcher.d.ts +68 -8
- package/dist/src/runtime/source-matcher.js +30 -6
- package/dist/src/runtime/source-matcher.js.map +3 -3
- package/dist/src/runtime/stats.d.ts +3 -3
- package/dist/src/schema/index.d.ts +114 -13
- package/dist/src/schema/index.js +133 -20
- package/dist/src/schema/index.js.map +5 -5
- package/dist/src/service.js +272 -35
- package/dist/src/service.js.map +10 -9
- package/dist/src/testing/index.d.ts +667 -0
- package/dist/src/testing/index.js +1463 -0
- package/dist/src/testing/index.js.map +17 -0
- package/dist/src/triggers/index.d.ts +57 -6
- package/dist/src/types.d.ts +112 -11
- package/dist/src/validate.d.ts +129 -11
- package/dist/src/validate.js +117 -18
- package/dist/src/validate.js.map +3 -3
- package/package.json +9 -3
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
import { AbiContract } from "@secondlayer/stacks/clarity";
|
|
1
|
+
import { AbiContract as AbiContract2 } from "@secondlayer/stacks/clarity";
|
|
2
|
+
/**
|
|
3
|
+
* How long a read stays valid.
|
|
4
|
+
*
|
|
5
|
+
* - `per-block` (default): pinned to the block being processed, cached under
|
|
6
|
+
* its `index_block_hash`. Sound for any read-only function — reindexing the
|
|
7
|
+
* same block always returns the same value, and a reorg-replaced block has a
|
|
8
|
+
* different id so it can't inherit the orphaned answer.
|
|
9
|
+
* - `contract-constant`: the caller asserts the value cannot change for this
|
|
10
|
+
* contract and these args (SIP-010 `get-decimals`/`get-symbol`), so it is
|
|
11
|
+
* resolved ONCE instead of once per block. This is the mode that makes a
|
|
12
|
+
* backfill affordable — under `per-block` every block is a distinct key and
|
|
13
|
+
* therefore a distinct RPC. Declaring it on a value that does change pins the
|
|
14
|
+
* first answer forever, so it is opt-in and never inferred.
|
|
15
|
+
*/
|
|
16
|
+
type ChainReadCacheMode = "per-block" | "contract-constant";
|
|
17
|
+
type ChainReadOptions = {
|
|
18
|
+
cache?: ChainReadCacheMode
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* `ChainReadClient` with the ABI generic erased. Structurally cheap, so the
|
|
22
|
+
* base `SubgraphContext` can carry it; `TypedSubgraphContext` uses the real
|
|
23
|
+
* one and handlers get full inference.
|
|
24
|
+
*/
|
|
25
|
+
interface ErasedChainReadClient {
|
|
26
|
+
contract(contractId: string, abi: unknown, options?: ChainReadOptions): {
|
|
27
|
+
read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>
|
|
28
|
+
};
|
|
29
|
+
}
|
|
2
30
|
/** Supported column types for subgraph schemas */
|
|
3
31
|
type ColumnType = "text" | "uint" | "int" | "principal" | "boolean" | "timestamp" | "jsonb";
|
|
4
32
|
/** Column definition in a subgraph table */
|
|
@@ -25,15 +53,24 @@ interface SubgraphRelation {
|
|
|
25
53
|
/** Target column(s) the fields point at (a uniqueKeys entry on the target). */
|
|
26
54
|
referencedColumns: string[];
|
|
27
55
|
}
|
|
28
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Table definition within a subgraph schema.
|
|
58
|
+
*
|
|
59
|
+
* The array fields are `readonly` so a schema literal can be hoisted out of
|
|
60
|
+
* the `defineSubgraph()` call with `as const` (or {@link defineSchema}) and
|
|
61
|
+
* still typecheck — `as const` produces `readonly [readonly ["holder"]]`,
|
|
62
|
+
* which a mutable `string[][]` rejects. Without that, extracting a helper
|
|
63
|
+
* that takes `ctx` meant losing the entire typed surface, which is why the
|
|
64
|
+
* shipped starter reached for `ctx: any`.
|
|
65
|
+
*/
|
|
29
66
|
interface SubgraphTable {
|
|
30
67
|
columns: Record<string, SubgraphColumn>;
|
|
31
68
|
/** Composite indexes (each entry is an array of column names) */
|
|
32
|
-
indexes?: string[][];
|
|
69
|
+
indexes?: readonly (readonly string[])[];
|
|
33
70
|
/** Unique key constraints (each entry is an array of column names). Required for upsert. */
|
|
34
|
-
uniqueKeys?: string[][];
|
|
71
|
+
uniqueKeys?: readonly (readonly string[])[];
|
|
35
72
|
/** Foreign-key relations to other tables (for typed ORM joins). */
|
|
36
|
-
relations?: SubgraphRelation[];
|
|
73
|
+
relations?: readonly SubgraphRelation[];
|
|
37
74
|
}
|
|
38
75
|
/** Subgraph schema — maps table names to table definitions */
|
|
39
76
|
type SubgraphSchema = Record<string, SubgraphTable>;
|
|
@@ -68,6 +105,45 @@ interface StxLockFilter {
|
|
|
68
105
|
type TraitScope = {
|
|
69
106
|
trait?: string
|
|
70
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* Scope a source to a DYNAMIC address set discovered from another source's
|
|
110
|
+
* events, instead of a fixed contract list.
|
|
111
|
+
*
|
|
112
|
+
* The standard shape it unlocks: a router plus pools created after you
|
|
113
|
+
* deploy. `contractId` arrays cover a set you know at authoring time; a
|
|
114
|
+
* factory covers the set that grows. It is deliberately NOT tied to contract
|
|
115
|
+
* deployment — the address can come from any field of any event, so it also
|
|
116
|
+
* covers launchpad-minted tokens, DAO extension allowlists, and registry
|
|
117
|
+
* entries.
|
|
118
|
+
*
|
|
119
|
+
* ```ts
|
|
120
|
+
* sources: {
|
|
121
|
+
* registry: { type: "print_event", contractId: REGISTRY, topic: "pool-created" },
|
|
122
|
+
* swaps: {
|
|
123
|
+
* type: "print_event",
|
|
124
|
+
* topic: "swap",
|
|
125
|
+
* // every pool the registry has ever announced, including new ones
|
|
126
|
+
* factory: { from: "registry", field: "data.pool" },
|
|
127
|
+
* },
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* Two guarantees the runtime provides:
|
|
132
|
+
* - **Same-block ordering** — a contract discovered in block N receives its
|
|
133
|
+
* own block-N events. Discovery runs before matching, within the block.
|
|
134
|
+
* - **Reorg-scoped** — the discovered set is stamped with the block that
|
|
135
|
+
* revealed it and rolled back with everything else on a fork, so an address
|
|
136
|
+
* announced on an orphaned chain does not linger forever.
|
|
137
|
+
*/
|
|
138
|
+
interface FactoryScope {
|
|
139
|
+
factory?: {
|
|
140
|
+
/** Source name whose events reveal the addresses. */
|
|
141
|
+
from: string
|
|
142
|
+
/** Dotted path to the address on that source's payload
|
|
143
|
+
* (e.g. `"data.pool"`, `"contractId"`, `"data.token.id"`). */
|
|
144
|
+
field: string
|
|
145
|
+
};
|
|
146
|
+
}
|
|
71
147
|
/** FT event filters */
|
|
72
148
|
interface FtTransferFilter extends TraitScope {
|
|
73
149
|
type: "ft_transfer";
|
|
@@ -106,9 +182,19 @@ interface NftBurnFilter extends TraitScope {
|
|
|
106
182
|
sender?: string;
|
|
107
183
|
}
|
|
108
184
|
/** Contract event filters */
|
|
109
|
-
interface ContractCallFilter extends TraitScope {
|
|
185
|
+
interface ContractCallFilter extends TraitScope, FactoryScope {
|
|
110
186
|
type: "contract_call";
|
|
111
|
-
|
|
187
|
+
/**
|
|
188
|
+
* One contract id, or a SET of them (max 20) — the standard DeFi shape is
|
|
189
|
+
* a router plus N pools, which used to cost N near-identical sources and
|
|
190
|
+
* handlers, or the `"*"` catch-all that erases per-source typing. Payload
|
|
191
|
+
* types are identical per `type`, so one handler serves the set and
|
|
192
|
+
* `event.contractId` disambiguates.
|
|
193
|
+
*
|
|
194
|
+
* Supports `*` wildcards (e.g. `"SP1ABC….pool-*"`). Mutually exclusive
|
|
195
|
+
* with `trait`, which resolves its own set per block.
|
|
196
|
+
*/
|
|
197
|
+
contractId?: string | readonly string[];
|
|
112
198
|
functionName?: string;
|
|
113
199
|
caller?: string;
|
|
114
200
|
/**
|
|
@@ -117,7 +203,7 @@ interface ContractCallFilter extends TraitScope {
|
|
|
117
203
|
* definition and used at runtime to decode args by name. Omit to keep
|
|
118
204
|
* `event.args` as a positional `unknown[]`.
|
|
119
205
|
*/
|
|
120
|
-
abi?:
|
|
206
|
+
abi?: AbiContract2;
|
|
121
207
|
}
|
|
122
208
|
interface ContractDeployFilter {
|
|
123
209
|
type: "contract_deploy";
|
|
@@ -146,9 +232,11 @@ type PrintField = ColumnType | {
|
|
|
146
232
|
} | {
|
|
147
233
|
list: PrintField
|
|
148
234
|
};
|
|
149
|
-
interface PrintEventFilter extends TraitScope {
|
|
235
|
+
interface PrintEventFilter extends TraitScope, FactoryScope {
|
|
150
236
|
type: "print_event";
|
|
151
|
-
|
|
237
|
+
/** One contract id, or a set of them (max 20). Supports `*` wildcards.
|
|
238
|
+
* Mutually exclusive with `trait`. */
|
|
239
|
+
contractId?: string | readonly string[];
|
|
152
240
|
topic?: string;
|
|
153
241
|
/**
|
|
154
242
|
* Per-topic field schema. When declared, the handler's `event` is a
|
|
@@ -186,8 +274,21 @@ interface SubgraphContext {
|
|
|
186
274
|
hash: string
|
|
187
275
|
timestamp: number
|
|
188
276
|
burnBlockHeight: number
|
|
277
|
+
/** Nakamoto StacksBlockId, when the block row carries one. */
|
|
278
|
+
indexBlockHash?: string | null
|
|
189
279
|
};
|
|
190
280
|
tx: TxMeta;
|
|
281
|
+
/**
|
|
282
|
+
* Read-only contract calls pinned to this block. Cached, so the same
|
|
283
|
+
* (contract, function, args) is fetched once per block rather than once
|
|
284
|
+
* per event.
|
|
285
|
+
*
|
|
286
|
+
* Erased here on purpose: this interface is compared structurally wherever
|
|
287
|
+
* a subgraph definition is passed around, and carrying an ABI-generic
|
|
288
|
+
* method pushes those comparisons past TS's instantiation depth. Handlers
|
|
289
|
+
* receive `TypedSubgraphContext`, which exposes the fully typed version.
|
|
290
|
+
*/
|
|
291
|
+
client: ErasedChainReadClient;
|
|
191
292
|
insert(table: string, row: Record<string, unknown>): void;
|
|
192
293
|
update(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
|
|
193
294
|
upsert(table: string, key: Record<string, unknown>, row: Record<string, unknown>): void;
|
|
@@ -251,9 +352,9 @@ interface GeneratedSQL {
|
|
|
251
352
|
* each with auto-columns and indexes.
|
|
252
353
|
*/
|
|
253
354
|
declare function generateSubgraphSQL(def: SubgraphDefinition, schemaNameOverride?: string): GeneratedSQL;
|
|
254
|
-
import { Database } from "@secondlayer/shared/db";
|
|
255
|
-
import { Kysely } from "kysely";
|
|
256
|
-
type AnyDb =
|
|
355
|
+
import { Database as Database2 } from "@secondlayer/shared/db";
|
|
356
|
+
import { Kysely as Kysely2 } from "kysely";
|
|
357
|
+
type AnyDb = Kysely2<Database2>;
|
|
257
358
|
interface TableDiff {
|
|
258
359
|
/** Tables added to the schema */
|
|
259
360
|
addedTables: string[];
|
package/dist/src/schema/index.js
CHANGED
|
@@ -86,24 +86,105 @@ var VALID_FILTER_TYPES = [
|
|
|
86
86
|
"contract_deploy",
|
|
87
87
|
"print_event"
|
|
88
88
|
];
|
|
89
|
-
var
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
var contractIdField = z.union([
|
|
90
|
+
z.string(),
|
|
91
|
+
z.array(z.string()).min(1).max(20)
|
|
92
|
+
]);
|
|
93
|
+
var traitScope = { trait: z.string().optional() };
|
|
94
|
+
var factoryScope = {
|
|
95
|
+
factory: z.object({ from: z.string().min(1), field: z.string().min(1) }).strict().optional()
|
|
96
|
+
};
|
|
97
|
+
var amountRange = {
|
|
93
98
|
minAmount: z.bigint().optional(),
|
|
94
|
-
maxAmount: z.bigint().optional()
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
maxAmount: z.bigint().optional()
|
|
100
|
+
};
|
|
101
|
+
var SubgraphFilterUnion = z.discriminatedUnion("type", [
|
|
102
|
+
z.object({
|
|
103
|
+
type: z.literal("stx_transfer"),
|
|
104
|
+
sender: z.string().optional(),
|
|
105
|
+
recipient: z.string().optional(),
|
|
106
|
+
...amountRange
|
|
107
|
+
}).strict(),
|
|
108
|
+
z.object({
|
|
109
|
+
type: z.literal("stx_mint"),
|
|
110
|
+
recipient: z.string().optional(),
|
|
111
|
+
minAmount: z.bigint().optional()
|
|
112
|
+
}).strict(),
|
|
113
|
+
z.object({
|
|
114
|
+
type: z.literal("stx_burn"),
|
|
115
|
+
sender: z.string().optional(),
|
|
116
|
+
minAmount: z.bigint().optional()
|
|
117
|
+
}).strict(),
|
|
118
|
+
z.object({
|
|
119
|
+
type: z.literal("stx_lock"),
|
|
120
|
+
lockedAddress: z.string().optional(),
|
|
121
|
+
minAmount: z.bigint().optional()
|
|
122
|
+
}).strict(),
|
|
123
|
+
z.object({
|
|
124
|
+
type: z.literal("ft_transfer"),
|
|
125
|
+
assetIdentifier: z.string().optional(),
|
|
126
|
+
sender: z.string().optional(),
|
|
127
|
+
recipient: z.string().optional(),
|
|
128
|
+
minAmount: z.bigint().optional(),
|
|
129
|
+
...traitScope
|
|
130
|
+
}).strict(),
|
|
131
|
+
z.object({
|
|
132
|
+
type: z.literal("ft_mint"),
|
|
133
|
+
assetIdentifier: z.string().optional(),
|
|
134
|
+
recipient: z.string().optional(),
|
|
135
|
+
minAmount: z.bigint().optional(),
|
|
136
|
+
...traitScope
|
|
137
|
+
}).strict(),
|
|
138
|
+
z.object({
|
|
139
|
+
type: z.literal("ft_burn"),
|
|
140
|
+
assetIdentifier: z.string().optional(),
|
|
141
|
+
sender: z.string().optional(),
|
|
142
|
+
minAmount: z.bigint().optional(),
|
|
143
|
+
...traitScope
|
|
144
|
+
}).strict(),
|
|
145
|
+
z.object({
|
|
146
|
+
type: z.literal("nft_transfer"),
|
|
147
|
+
assetIdentifier: z.string().optional(),
|
|
148
|
+
sender: z.string().optional(),
|
|
149
|
+
recipient: z.string().optional(),
|
|
150
|
+
...traitScope
|
|
151
|
+
}).strict(),
|
|
152
|
+
z.object({
|
|
153
|
+
type: z.literal("nft_mint"),
|
|
154
|
+
assetIdentifier: z.string().optional(),
|
|
155
|
+
recipient: z.string().optional(),
|
|
156
|
+
...traitScope
|
|
157
|
+
}).strict(),
|
|
158
|
+
z.object({
|
|
159
|
+
type: z.literal("nft_burn"),
|
|
160
|
+
assetIdentifier: z.string().optional(),
|
|
161
|
+
sender: z.string().optional(),
|
|
162
|
+
...traitScope
|
|
163
|
+
}).strict(),
|
|
164
|
+
z.object({
|
|
165
|
+
type: z.literal("contract_call"),
|
|
166
|
+
contractId: contractIdField.optional(),
|
|
167
|
+
functionName: z.string().optional(),
|
|
168
|
+
caller: z.string().optional(),
|
|
169
|
+
abi: AbiContractSchema.optional(),
|
|
170
|
+
...traitScope,
|
|
171
|
+
...factoryScope
|
|
172
|
+
}).strict(),
|
|
173
|
+
z.object({
|
|
174
|
+
type: z.literal("contract_deploy"),
|
|
175
|
+
deployer: z.string().optional(),
|
|
176
|
+
contractName: z.string().optional()
|
|
177
|
+
}).strict(),
|
|
178
|
+
z.object({
|
|
179
|
+
type: z.literal("print_event"),
|
|
180
|
+
contractId: contractIdField.optional(),
|
|
181
|
+
topic: z.string().optional(),
|
|
182
|
+
prints: z.record(z.string(), z.record(z.string(), PrintFieldSchema)).optional(),
|
|
183
|
+
...traitScope,
|
|
184
|
+
...factoryScope
|
|
185
|
+
}).strict()
|
|
186
|
+
]);
|
|
187
|
+
var SubgraphFilterSchema = SubgraphFilterUnion;
|
|
107
188
|
var SubgraphDefinitionSchema = z.object({
|
|
108
189
|
name: SubgraphNameSchema,
|
|
109
190
|
version: z.string().optional(),
|
|
@@ -117,6 +198,23 @@ var SubgraphDefinitionSchema = z.object({
|
|
|
117
198
|
function validateSubgraphDefinition(def) {
|
|
118
199
|
return SubgraphDefinitionSchema.parse(def);
|
|
119
200
|
}
|
|
201
|
+
function filterFieldsByType() {
|
|
202
|
+
const options = SubgraphFilterUnion?._def?.options ?? [];
|
|
203
|
+
const out = [];
|
|
204
|
+
for (const option of options) {
|
|
205
|
+
const shape = option?.shape ?? option?._def?.shape;
|
|
206
|
+
if (!shape)
|
|
207
|
+
continue;
|
|
208
|
+
const literal = shape.type?._def?.values?.[0] ?? shape.type?._def?.value ?? undefined;
|
|
209
|
+
if (typeof literal !== "string")
|
|
210
|
+
continue;
|
|
211
|
+
out.push({
|
|
212
|
+
type: literal,
|
|
213
|
+
fields: Object.keys(shape).filter((k) => k !== "type")
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
120
218
|
|
|
121
219
|
// src/schema/generator.ts
|
|
122
220
|
import { createHash } from "node:crypto";
|
|
@@ -212,6 +310,18 @@ function emitJournalDDL(schemaName) {
|
|
|
212
310
|
`CREATE INDEX IF NOT EXISTS idx_${schemaName}_journal_height ON ${schemaName}._journal (block_height)`
|
|
213
311
|
];
|
|
214
312
|
}
|
|
313
|
+
function emitFactoryDDL(schemaName) {
|
|
314
|
+
return [
|
|
315
|
+
`CREATE TABLE IF NOT EXISTS ${schemaName}._factory_addresses (
|
|
316
|
+
source_name TEXT NOT NULL,
|
|
317
|
+
address TEXT NOT NULL,
|
|
318
|
+
block_height BIGINT NOT NULL,
|
|
319
|
+
_created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
320
|
+
PRIMARY KEY (source_name, address)
|
|
321
|
+
)`,
|
|
322
|
+
`CREATE INDEX IF NOT EXISTS idx_${schemaName}_factory_height ON ${schemaName}._factory_addresses (block_height)`
|
|
323
|
+
];
|
|
324
|
+
}
|
|
215
325
|
function emitForeignKeyDDL(schemaName, tableName, tableDef) {
|
|
216
326
|
return (tableDef.relations ?? []).map((rel) => {
|
|
217
327
|
const constraintName = `fk_${schemaName}_${tableName}_${rel.name}`;
|
|
@@ -230,6 +340,9 @@ function generateSubgraphSQL(def, schemaNameOverride) {
|
|
|
230
340
|
statements.push(...emitTableDDL(schemaName, tableName, tableDef));
|
|
231
341
|
}
|
|
232
342
|
statements.push(...emitJournalDDL(schemaName));
|
|
343
|
+
if (Object.values(def.sources ?? {}).some((src) => src.factory !== undefined)) {
|
|
344
|
+
statements.push(...emitFactoryDDL(schemaName));
|
|
345
|
+
}
|
|
233
346
|
for (const [tableName, tableDef] of Object.entries(def.schema)) {
|
|
234
347
|
statements.push(...emitForeignKeyDDL(schemaName, tableName, tableDef));
|
|
235
348
|
}
|
|
@@ -255,8 +368,8 @@ function diffKeyLists(existing, incoming) {
|
|
|
255
368
|
const existingSet = new Set((existing ?? []).map(key));
|
|
256
369
|
const incomingSet = new Set((incoming ?? []).map(key));
|
|
257
370
|
return {
|
|
258
|
-
added: (incoming ?? []).filter((cols) => !existingSet.has(key(cols))),
|
|
259
|
-
removed: (existing ?? []).filter((cols) => !incomingSet.has(key(cols)))
|
|
371
|
+
added: (incoming ?? []).filter((cols) => !existingSet.has(key(cols))).map((cols) => [...cols]),
|
|
372
|
+
removed: (existing ?? []).filter((cols) => !incomingSet.has(key(cols))).map((cols) => [...cols])
|
|
260
373
|
};
|
|
261
374
|
}
|
|
262
375
|
function diffSchema(existing, incoming) {
|
|
@@ -605,5 +718,5 @@ export {
|
|
|
605
718
|
TYPE_MAP
|
|
606
719
|
};
|
|
607
720
|
|
|
608
|
-
//# debugId=
|
|
721
|
+
//# debugId=A19E9CF28F38E66064756E2164756E21
|
|
609
722
|
//# sourceMappingURL=index.js.map
|