@dudousxd/nestjs-durable-store-mikro-orm 0.31.0 → 0.33.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/index.cjs +134 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +84 -49
- package/dist/index.d.ts +84 -49
- package/dist/index.js +132 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _mikro_orm_core from '@mikro-orm/core';
|
|
2
2
|
import { EntityRepository, EntityRepositoryType, EntitySchema, MikroORM } from '@mikro-orm/core';
|
|
3
|
-
import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, CheckpointStat, CheckpointQuery, SignalWaiter, ChildWait } from '@dudousxd/nestjs-durable-core';
|
|
3
|
+
import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, OwnedLeaseReclaim, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, CheckpointStat, CheckpointQuery, SignalWaiter, ChildWait } from '@dudousxd/nestjs-durable-core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Custom repositories for the durable entities, so a host app can `@InjectRepository`/inject a
|
|
@@ -145,6 +145,79 @@ declare function durableEntities(options?: {
|
|
|
145
145
|
/** Durable entity schemas with the canonical `'snake_case'` column names. */
|
|
146
146
|
declare const ENTITIES: EntitySchema<any, never, _mikro_orm_core.EntityCtor<any>>[];
|
|
147
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Tables this store creates and manages at boot (autoSchema). Feed to your ORM's migration differ
|
|
150
|
+
* exclude/skipTables so it never tries to drop them.
|
|
151
|
+
*
|
|
152
|
+
* ```ts
|
|
153
|
+
* await MikroORM.init({
|
|
154
|
+
* // ...your entities/driver config
|
|
155
|
+
* schemaGenerator: { skipTables: durableManagedTables() },
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* Derived from the same {@link DURABLE_TABLE_NAMES} set `ensureMikroOrmDurableSchema` scopes its own
|
|
160
|
+
* heal to — one list, so a consumer's denylist can never drift from what this store actually owns.
|
|
161
|
+
*/
|
|
162
|
+
declare function durableManagedTables(): string[];
|
|
163
|
+
/**
|
|
164
|
+
* Where {@link ensureMikroOrmDurableSchema} reports a schema repair it actually applied. `console`
|
|
165
|
+
* (the default) satisfies it, and so does NestJS's `Logger`, so an app can route the warning into
|
|
166
|
+
* its own log stream.
|
|
167
|
+
*/
|
|
168
|
+
interface DurableSchemaLogger {
|
|
169
|
+
warn(message: string): void;
|
|
170
|
+
}
|
|
171
|
+
interface EnsureMikroOrmDurableSchemaOptions {
|
|
172
|
+
/** Sink for the schema-repair warning. Defaults to `console`. */
|
|
173
|
+
logger?: DurableSchemaLogger | undefined;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The warning logged when the boot-time heal changed an EXISTING durable schema: created a table
|
|
177
|
+
* that was missing next to ones that exist, added a column or index, changed a column type, or
|
|
178
|
+
* converted a table's collation. Never logged when the schema was already current, and never on a
|
|
179
|
+
* fresh install (no durable table existed, so creating them all is the expected first boot).
|
|
180
|
+
*
|
|
181
|
+
* The discriminator matters more than the wording: a warning on every boot would be filtered as
|
|
182
|
+
* noise, and a silent repair hides a migration-managed schema that has drifted from the library.
|
|
183
|
+
*/
|
|
184
|
+
declare function mikroOrmSchemaRepairWarning(repairs: readonly string[]): string;
|
|
185
|
+
/**
|
|
186
|
+
* Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every
|
|
187
|
+
* boot (auto-schema) and from a MikroORM migration when you disable auto-schema:
|
|
188
|
+
*
|
|
189
|
+
* ```ts
|
|
190
|
+
* export class AddDurableTables extends Migration {
|
|
191
|
+
* async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the
|
|
196
|
+
* recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),
|
|
197
|
+
* a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a
|
|
198
|
+
* migration-managed schema that means recreating the migrations table and dropping app foreign keys.
|
|
199
|
+
* Instead we compute the safe additive diff and execute only the statements that target our own
|
|
200
|
+
* `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table
|
|
201
|
+
* and `alter table ... add` only for missing columns, so existing tables — and the entire rest of
|
|
202
|
+
* the host schema — are left untouched.
|
|
203
|
+
*
|
|
204
|
+
* This runs on every boot of every pod, and `getUpdateSchemaSQL({ safe: true })` introspects the
|
|
205
|
+
* WHOLE database's `information_schema` (the store shares the app ORM) before string-filtering down
|
|
206
|
+
* to our tables — wasted round-trips when nothing changed. So a fingerprint GATE fronts it: a marker
|
|
207
|
+
* table records the fingerprint of the metadata last applied; if the in-memory expected fingerprint
|
|
208
|
+
* matches the stored one we return after two cheap round-trips (a `CREATE TABLE IF NOT EXISTS` for
|
|
209
|
+
* the marker + one PK read), skipping BOTH the introspection AND the collation probes. Only a fresh
|
|
210
|
+
* DB (no marker), an entity change, or a {@link SCHEMA_REVISION} bump runs the full heal — under a
|
|
211
|
+
* best-effort advisory lock, with a re-check in case a sibling pod healed while we waited.
|
|
212
|
+
*
|
|
213
|
+
* When the heal changes an existing durable schema (a missing table, column or index, a column type,
|
|
214
|
+
* a MySQL collation), it logs ONE warning listing each change to `options.logger` (default
|
|
215
|
+
* `console`); see {@link mikroOrmSchemaRepairWarning}. A current schema and a fresh install log
|
|
216
|
+
* nothing. Because of the fingerprint gate, a column dropped by hand AFTER the marker was written is
|
|
217
|
+
* not noticed until the fingerprint changes (an upgrade) or the marker row is deleted.
|
|
218
|
+
*/
|
|
219
|
+
declare function ensureMikroOrmDurableSchema(orm: MikroORM, options?: EnsureMikroOrmDurableSchemaOptions): Promise<void>;
|
|
220
|
+
|
|
148
221
|
/** Options for scoping a `MikroOrmStateStore` to a single tenant namespace. */
|
|
149
222
|
interface MikroOrmStateStoreOptions {
|
|
150
223
|
/**
|
|
@@ -155,6 +228,12 @@ interface MikroOrmStateStoreOptions {
|
|
|
155
228
|
scope?: {
|
|
156
229
|
namespace?: string;
|
|
157
230
|
};
|
|
231
|
+
/**
|
|
232
|
+
* Where `ensureSchema()` (the boot-time auto-schema) reports a schema repair it actually applied
|
|
233
|
+
* — a missing table, column or index it had to add. Defaults to `console`. NestJS's `Logger`
|
|
234
|
+
* satisfies it.
|
|
235
|
+
*/
|
|
236
|
+
schemaLogger?: DurableSchemaLogger | undefined;
|
|
158
237
|
}
|
|
159
238
|
/**
|
|
160
239
|
* MikroORM-backed `StateStore`. Works on any MikroORM driver — Postgres, MySQL, SQLite (tested);
|
|
@@ -166,6 +245,7 @@ interface MikroOrmStateStoreOptions {
|
|
|
166
245
|
*/
|
|
167
246
|
declare class MikroOrmStateStore implements StateStore {
|
|
168
247
|
private readonly orm;
|
|
248
|
+
private readonly opts;
|
|
169
249
|
private readonly scopeNamespace;
|
|
170
250
|
constructor(orm: MikroORM, opts?: MikroOrmStateStoreOptions);
|
|
171
251
|
/**
|
|
@@ -205,11 +285,11 @@ declare class MikroOrmStateStore implements StateStore {
|
|
|
205
285
|
saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;
|
|
206
286
|
}) => Promise<T>): Promise<T>;
|
|
207
287
|
listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
|
|
208
|
-
listOrphanedRuns(nowMs: number, limit: number, namespace?: string): Promise<WorkflowRun[]>;
|
|
288
|
+
listOrphanedRuns(nowMs: number, limit: number, namespace?: string, ownedBy?: OwnedLeaseReclaim): Promise<WorkflowRun[]>;
|
|
209
289
|
listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
|
|
210
290
|
listDueTimers(nowMs: number, namespace?: string, limit?: number): Promise<WorkflowRun[]>;
|
|
211
291
|
tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
|
|
212
|
-
releaseRunLock(runId: string): Promise<void>;
|
|
292
|
+
releaseRunLock(runId: string, owner?: string): Promise<void>;
|
|
213
293
|
renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
|
|
214
294
|
/** The `where` every run query shares — {@link listRuns} pages it, {@link runFacets} groups it.
|
|
215
295
|
* Only the predicates MikroORM can express declaratively; `tag`/`attributes` need raw SQL and are
|
|
@@ -332,49 +412,4 @@ declare class MikroOrmStateStore implements StateStore {
|
|
|
332
412
|
removeBufferedEvent(id: string): Promise<boolean>;
|
|
333
413
|
}
|
|
334
414
|
|
|
335
|
-
|
|
336
|
-
* Tables this store creates and manages at boot (autoSchema). Feed to your ORM's migration differ
|
|
337
|
-
* exclude/skipTables so it never tries to drop them.
|
|
338
|
-
*
|
|
339
|
-
* ```ts
|
|
340
|
-
* await MikroORM.init({
|
|
341
|
-
* // ...your entities/driver config
|
|
342
|
-
* schemaGenerator: { skipTables: durableManagedTables() },
|
|
343
|
-
* });
|
|
344
|
-
* ```
|
|
345
|
-
*
|
|
346
|
-
* Derived from the same {@link DURABLE_TABLE_NAMES} set `ensureMikroOrmDurableSchema` scopes its own
|
|
347
|
-
* heal to — one list, so a consumer's denylist can never drift from what this store actually owns.
|
|
348
|
-
*/
|
|
349
|
-
declare function durableManagedTables(): string[];
|
|
350
|
-
/**
|
|
351
|
-
* Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every
|
|
352
|
-
* boot (auto-schema) and from a MikroORM migration when you disable auto-schema:
|
|
353
|
-
*
|
|
354
|
-
* ```ts
|
|
355
|
-
* export class AddDurableTables extends Migration {
|
|
356
|
-
* async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }
|
|
357
|
-
* }
|
|
358
|
-
* ```
|
|
359
|
-
*
|
|
360
|
-
* It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the
|
|
361
|
-
* recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),
|
|
362
|
-
* a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a
|
|
363
|
-
* migration-managed schema that means recreating the migrations table and dropping app foreign keys.
|
|
364
|
-
* Instead we compute the safe additive diff and execute only the statements that target our own
|
|
365
|
-
* `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table
|
|
366
|
-
* and `alter table ... add` only for missing columns, so existing tables — and the entire rest of
|
|
367
|
-
* the host schema — are left untouched.
|
|
368
|
-
*
|
|
369
|
-
* This runs on every boot of every pod, and `getUpdateSchemaSQL({ safe: true })` introspects the
|
|
370
|
-
* WHOLE database's `information_schema` (the store shares the app ORM) before string-filtering down
|
|
371
|
-
* to our tables — wasted round-trips when nothing changed. So a fingerprint GATE fronts it: a marker
|
|
372
|
-
* table records the fingerprint of the metadata last applied; if the in-memory expected fingerprint
|
|
373
|
-
* matches the stored one we return after two cheap round-trips (a `CREATE TABLE IF NOT EXISTS` for
|
|
374
|
-
* the marker + one PK read), skipping BOTH the introspection AND the collation probes. Only a fresh
|
|
375
|
-
* DB (no marker), an entity change, or a {@link SCHEMA_REVISION} bump runs the full heal — under a
|
|
376
|
-
* best-effort advisory lock, with a re-check in case a sibling pod healed while we waited.
|
|
377
|
-
*/
|
|
378
|
-
declare function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void>;
|
|
379
|
-
|
|
380
|
-
export { BufferedEventEntity, BufferedEventRepository, BufferedSignalEntity, BufferedSignalRepository, type DurableColumnNaming, ENTITIES, MikroOrmStateStore, type MikroOrmStateStoreOptions, RunAttributeEntity, RunAttributeRepository, ScheduleEntity, ScheduleRepository, SignalWaiterEntity, SignalWaiterRepository, StepCheckpointEntity, StepCheckpointRepository, WorkflowRunEntity, WorkflowRunRepository, durableEntities, durableManagedTables, ensureMikroOrmDurableSchema };
|
|
415
|
+
export { BufferedEventEntity, BufferedEventRepository, BufferedSignalEntity, BufferedSignalRepository, type DurableColumnNaming, type DurableSchemaLogger, ENTITIES, type EnsureMikroOrmDurableSchemaOptions, MikroOrmStateStore, type MikroOrmStateStoreOptions, RunAttributeEntity, RunAttributeRepository, ScheduleEntity, ScheduleRepository, SignalWaiterEntity, SignalWaiterRepository, StepCheckpointEntity, StepCheckpointRepository, WorkflowRunEntity, WorkflowRunRepository, durableEntities, durableManagedTables, ensureMikroOrmDurableSchema, mikroOrmSchemaRepairWarning };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _mikro_orm_core from '@mikro-orm/core';
|
|
2
2
|
import { EntityRepository, EntityRepositoryType, EntitySchema, MikroORM } from '@mikro-orm/core';
|
|
3
|
-
import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, CheckpointStat, CheckpointQuery, SignalWaiter, ChildWait } from '@dudousxd/nestjs-durable-core';
|
|
3
|
+
import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, OwnedLeaseReclaim, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, CheckpointStat, CheckpointQuery, SignalWaiter, ChildWait } from '@dudousxd/nestjs-durable-core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Custom repositories for the durable entities, so a host app can `@InjectRepository`/inject a
|
|
@@ -145,6 +145,79 @@ declare function durableEntities(options?: {
|
|
|
145
145
|
/** Durable entity schemas with the canonical `'snake_case'` column names. */
|
|
146
146
|
declare const ENTITIES: EntitySchema<any, never, _mikro_orm_core.EntityCtor<any>>[];
|
|
147
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Tables this store creates and manages at boot (autoSchema). Feed to your ORM's migration differ
|
|
150
|
+
* exclude/skipTables so it never tries to drop them.
|
|
151
|
+
*
|
|
152
|
+
* ```ts
|
|
153
|
+
* await MikroORM.init({
|
|
154
|
+
* // ...your entities/driver config
|
|
155
|
+
* schemaGenerator: { skipTables: durableManagedTables() },
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* Derived from the same {@link DURABLE_TABLE_NAMES} set `ensureMikroOrmDurableSchema` scopes its own
|
|
160
|
+
* heal to — one list, so a consumer's denylist can never drift from what this store actually owns.
|
|
161
|
+
*/
|
|
162
|
+
declare function durableManagedTables(): string[];
|
|
163
|
+
/**
|
|
164
|
+
* Where {@link ensureMikroOrmDurableSchema} reports a schema repair it actually applied. `console`
|
|
165
|
+
* (the default) satisfies it, and so does NestJS's `Logger`, so an app can route the warning into
|
|
166
|
+
* its own log stream.
|
|
167
|
+
*/
|
|
168
|
+
interface DurableSchemaLogger {
|
|
169
|
+
warn(message: string): void;
|
|
170
|
+
}
|
|
171
|
+
interface EnsureMikroOrmDurableSchemaOptions {
|
|
172
|
+
/** Sink for the schema-repair warning. Defaults to `console`. */
|
|
173
|
+
logger?: DurableSchemaLogger | undefined;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The warning logged when the boot-time heal changed an EXISTING durable schema: created a table
|
|
177
|
+
* that was missing next to ones that exist, added a column or index, changed a column type, or
|
|
178
|
+
* converted a table's collation. Never logged when the schema was already current, and never on a
|
|
179
|
+
* fresh install (no durable table existed, so creating them all is the expected first boot).
|
|
180
|
+
*
|
|
181
|
+
* The discriminator matters more than the wording: a warning on every boot would be filtered as
|
|
182
|
+
* noise, and a silent repair hides a migration-managed schema that has drifted from the library.
|
|
183
|
+
*/
|
|
184
|
+
declare function mikroOrmSchemaRepairWarning(repairs: readonly string[]): string;
|
|
185
|
+
/**
|
|
186
|
+
* Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every
|
|
187
|
+
* boot (auto-schema) and from a MikroORM migration when you disable auto-schema:
|
|
188
|
+
*
|
|
189
|
+
* ```ts
|
|
190
|
+
* export class AddDurableTables extends Migration {
|
|
191
|
+
* async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the
|
|
196
|
+
* recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),
|
|
197
|
+
* a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a
|
|
198
|
+
* migration-managed schema that means recreating the migrations table and dropping app foreign keys.
|
|
199
|
+
* Instead we compute the safe additive diff and execute only the statements that target our own
|
|
200
|
+
* `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table
|
|
201
|
+
* and `alter table ... add` only for missing columns, so existing tables — and the entire rest of
|
|
202
|
+
* the host schema — are left untouched.
|
|
203
|
+
*
|
|
204
|
+
* This runs on every boot of every pod, and `getUpdateSchemaSQL({ safe: true })` introspects the
|
|
205
|
+
* WHOLE database's `information_schema` (the store shares the app ORM) before string-filtering down
|
|
206
|
+
* to our tables — wasted round-trips when nothing changed. So a fingerprint GATE fronts it: a marker
|
|
207
|
+
* table records the fingerprint of the metadata last applied; if the in-memory expected fingerprint
|
|
208
|
+
* matches the stored one we return after two cheap round-trips (a `CREATE TABLE IF NOT EXISTS` for
|
|
209
|
+
* the marker + one PK read), skipping BOTH the introspection AND the collation probes. Only a fresh
|
|
210
|
+
* DB (no marker), an entity change, or a {@link SCHEMA_REVISION} bump runs the full heal — under a
|
|
211
|
+
* best-effort advisory lock, with a re-check in case a sibling pod healed while we waited.
|
|
212
|
+
*
|
|
213
|
+
* When the heal changes an existing durable schema (a missing table, column or index, a column type,
|
|
214
|
+
* a MySQL collation), it logs ONE warning listing each change to `options.logger` (default
|
|
215
|
+
* `console`); see {@link mikroOrmSchemaRepairWarning}. A current schema and a fresh install log
|
|
216
|
+
* nothing. Because of the fingerprint gate, a column dropped by hand AFTER the marker was written is
|
|
217
|
+
* not noticed until the fingerprint changes (an upgrade) or the marker row is deleted.
|
|
218
|
+
*/
|
|
219
|
+
declare function ensureMikroOrmDurableSchema(orm: MikroORM, options?: EnsureMikroOrmDurableSchemaOptions): Promise<void>;
|
|
220
|
+
|
|
148
221
|
/** Options for scoping a `MikroOrmStateStore` to a single tenant namespace. */
|
|
149
222
|
interface MikroOrmStateStoreOptions {
|
|
150
223
|
/**
|
|
@@ -155,6 +228,12 @@ interface MikroOrmStateStoreOptions {
|
|
|
155
228
|
scope?: {
|
|
156
229
|
namespace?: string;
|
|
157
230
|
};
|
|
231
|
+
/**
|
|
232
|
+
* Where `ensureSchema()` (the boot-time auto-schema) reports a schema repair it actually applied
|
|
233
|
+
* — a missing table, column or index it had to add. Defaults to `console`. NestJS's `Logger`
|
|
234
|
+
* satisfies it.
|
|
235
|
+
*/
|
|
236
|
+
schemaLogger?: DurableSchemaLogger | undefined;
|
|
158
237
|
}
|
|
159
238
|
/**
|
|
160
239
|
* MikroORM-backed `StateStore`. Works on any MikroORM driver — Postgres, MySQL, SQLite (tested);
|
|
@@ -166,6 +245,7 @@ interface MikroOrmStateStoreOptions {
|
|
|
166
245
|
*/
|
|
167
246
|
declare class MikroOrmStateStore implements StateStore {
|
|
168
247
|
private readonly orm;
|
|
248
|
+
private readonly opts;
|
|
169
249
|
private readonly scopeNamespace;
|
|
170
250
|
constructor(orm: MikroORM, opts?: MikroOrmStateStoreOptions);
|
|
171
251
|
/**
|
|
@@ -205,11 +285,11 @@ declare class MikroOrmStateStore implements StateStore {
|
|
|
205
285
|
saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;
|
|
206
286
|
}) => Promise<T>): Promise<T>;
|
|
207
287
|
listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
|
|
208
|
-
listOrphanedRuns(nowMs: number, limit: number, namespace?: string): Promise<WorkflowRun[]>;
|
|
288
|
+
listOrphanedRuns(nowMs: number, limit: number, namespace?: string, ownedBy?: OwnedLeaseReclaim): Promise<WorkflowRun[]>;
|
|
209
289
|
listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
|
|
210
290
|
listDueTimers(nowMs: number, namespace?: string, limit?: number): Promise<WorkflowRun[]>;
|
|
211
291
|
tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
|
|
212
|
-
releaseRunLock(runId: string): Promise<void>;
|
|
292
|
+
releaseRunLock(runId: string, owner?: string): Promise<void>;
|
|
213
293
|
renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
|
|
214
294
|
/** The `where` every run query shares — {@link listRuns} pages it, {@link runFacets} groups it.
|
|
215
295
|
* Only the predicates MikroORM can express declaratively; `tag`/`attributes` need raw SQL and are
|
|
@@ -332,49 +412,4 @@ declare class MikroOrmStateStore implements StateStore {
|
|
|
332
412
|
removeBufferedEvent(id: string): Promise<boolean>;
|
|
333
413
|
}
|
|
334
414
|
|
|
335
|
-
|
|
336
|
-
* Tables this store creates and manages at boot (autoSchema). Feed to your ORM's migration differ
|
|
337
|
-
* exclude/skipTables so it never tries to drop them.
|
|
338
|
-
*
|
|
339
|
-
* ```ts
|
|
340
|
-
* await MikroORM.init({
|
|
341
|
-
* // ...your entities/driver config
|
|
342
|
-
* schemaGenerator: { skipTables: durableManagedTables() },
|
|
343
|
-
* });
|
|
344
|
-
* ```
|
|
345
|
-
*
|
|
346
|
-
* Derived from the same {@link DURABLE_TABLE_NAMES} set `ensureMikroOrmDurableSchema` scopes its own
|
|
347
|
-
* heal to — one list, so a consumer's denylist can never drift from what this store actually owns.
|
|
348
|
-
*/
|
|
349
|
-
declare function durableManagedTables(): string[];
|
|
350
|
-
/**
|
|
351
|
-
* Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every
|
|
352
|
-
* boot (auto-schema) and from a MikroORM migration when you disable auto-schema:
|
|
353
|
-
*
|
|
354
|
-
* ```ts
|
|
355
|
-
* export class AddDurableTables extends Migration {
|
|
356
|
-
* async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }
|
|
357
|
-
* }
|
|
358
|
-
* ```
|
|
359
|
-
*
|
|
360
|
-
* It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the
|
|
361
|
-
* recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),
|
|
362
|
-
* a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a
|
|
363
|
-
* migration-managed schema that means recreating the migrations table and dropping app foreign keys.
|
|
364
|
-
* Instead we compute the safe additive diff and execute only the statements that target our own
|
|
365
|
-
* `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table
|
|
366
|
-
* and `alter table ... add` only for missing columns, so existing tables — and the entire rest of
|
|
367
|
-
* the host schema — are left untouched.
|
|
368
|
-
*
|
|
369
|
-
* This runs on every boot of every pod, and `getUpdateSchemaSQL({ safe: true })` introspects the
|
|
370
|
-
* WHOLE database's `information_schema` (the store shares the app ORM) before string-filtering down
|
|
371
|
-
* to our tables — wasted round-trips when nothing changed. So a fingerprint GATE fronts it: a marker
|
|
372
|
-
* table records the fingerprint of the metadata last applied; if the in-memory expected fingerprint
|
|
373
|
-
* matches the stored one we return after two cheap round-trips (a `CREATE TABLE IF NOT EXISTS` for
|
|
374
|
-
* the marker + one PK read), skipping BOTH the introspection AND the collation probes. Only a fresh
|
|
375
|
-
* DB (no marker), an entity change, or a {@link SCHEMA_REVISION} bump runs the full heal — under a
|
|
376
|
-
* best-effort advisory lock, with a re-check in case a sibling pod healed while we waited.
|
|
377
|
-
*/
|
|
378
|
-
declare function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void>;
|
|
379
|
-
|
|
380
|
-
export { BufferedEventEntity, BufferedEventRepository, BufferedSignalEntity, BufferedSignalRepository, type DurableColumnNaming, ENTITIES, MikroOrmStateStore, type MikroOrmStateStoreOptions, RunAttributeEntity, RunAttributeRepository, ScheduleEntity, ScheduleRepository, SignalWaiterEntity, SignalWaiterRepository, StepCheckpointEntity, StepCheckpointRepository, WorkflowRunEntity, WorkflowRunRepository, durableEntities, durableManagedTables, ensureMikroOrmDurableSchema };
|
|
415
|
+
export { BufferedEventEntity, BufferedEventRepository, BufferedSignalEntity, BufferedSignalRepository, type DurableColumnNaming, type DurableSchemaLogger, ENTITIES, type EnsureMikroOrmDurableSchemaOptions, MikroOrmStateStore, type MikroOrmStateStoreOptions, RunAttributeEntity, RunAttributeRepository, ScheduleEntity, ScheduleRepository, SignalWaiterEntity, SignalWaiterRepository, StepCheckpointEntity, StepCheckpointRepository, WorkflowRunEntity, WorkflowRunRepository, durableEntities, durableManagedTables, ensureMikroOrmDurableSchema, mikroOrmSchemaRepairWarning };
|
package/dist/index.js
CHANGED
|
@@ -679,6 +679,78 @@ var MARKER_TABLE = "durable_schema_meta";
|
|
|
679
679
|
var MARKER_ROW_ID = "durable";
|
|
680
680
|
var SCHEMA_LOCK_NAME = "durable_schema";
|
|
681
681
|
var SCHEMA_REVISION = 1;
|
|
682
|
+
function mikroOrmSchemaRepairWarning(repairs) {
|
|
683
|
+
return [
|
|
684
|
+
`[nestjs-durable] store-mikro-orm repaired the durable schema at boot: ${repairs.join("; ")}.`,
|
|
685
|
+
"The database had drifted from the schema this library version expects (it was created by an",
|
|
686
|
+
"older version, or a migration left these out), so they were applied at runtime and nothing",
|
|
687
|
+
"recorded them in your migration history. To make them permanent, add a migration that calls",
|
|
688
|
+
"`ensureMikroOrmDurableSchema(orm)`. This warning appears only when a repair was applied; a",
|
|
689
|
+
"schema that is already current logs nothing."
|
|
690
|
+
].join(" ");
|
|
691
|
+
}
|
|
692
|
+
__name(mikroOrmSchemaRepairWarning, "mikroOrmSchemaRepairWarning");
|
|
693
|
+
function unquote(identifier) {
|
|
694
|
+
return identifier.replace(/^[`"']|[`"']$/g, "");
|
|
695
|
+
}
|
|
696
|
+
__name(unquote, "unquote");
|
|
697
|
+
function describeDurableStatement(statement) {
|
|
698
|
+
const table = targetTable(statement) ?? "?";
|
|
699
|
+
if (/^create\s+table\b/i.test(statement)) return [
|
|
700
|
+
`created table ${table}`
|
|
701
|
+
];
|
|
702
|
+
const createIndex = statement.match(/^create\s+(?:unique\s+)?index\s+(?:if\s+not\s+exists\s+)?([`"']?[\w$]+[`"']?)/i);
|
|
703
|
+
if (createIndex?.[1]) return [
|
|
704
|
+
`created index ${unquote(createIndex[1])} on ${table}`
|
|
705
|
+
];
|
|
706
|
+
if (/^alter\s+table\b/i.test(statement)) {
|
|
707
|
+
const out = [];
|
|
708
|
+
let other = false;
|
|
709
|
+
for (const action of splitTopLevel(statement.replace(/^alter\s+table\s+[`"']?[\w$]+[`"']?\s*/i, ""))) {
|
|
710
|
+
const index = action.match(/^add\s+(?:unique\s+|fulltext\s+)?(?:index|key)\s+([`"']?[\w$]+[`"']?)/i);
|
|
711
|
+
const constraint = action.match(/^add\s+constraint\s+([`"']?[\w$]+[`"']?)/i);
|
|
712
|
+
const column = action.match(/^add\s+(?:column\s+)?([`"']?[\w$]+[`"']?)/i);
|
|
713
|
+
if (index?.[1]) out.push(`created index ${unquote(index[1])} on ${table}`);
|
|
714
|
+
else if (constraint?.[1]) out.push(`added constraint ${unquote(constraint[1])} on ${table}`);
|
|
715
|
+
else if (column?.[1] && !/^add\s+(?:primary|unique|fulltext|foreign)\b/i.test(action)) out.push(`added column ${table}.${unquote(column[1])}`);
|
|
716
|
+
else other = true;
|
|
717
|
+
}
|
|
718
|
+
if (other || out.length === 0) {
|
|
719
|
+
const flat = statement.replace(/\s+/g, " ");
|
|
720
|
+
out.push(`altered ${table} (${flat.length > 160 ? `${flat.slice(0, 157)}...` : flat})`);
|
|
721
|
+
}
|
|
722
|
+
return out;
|
|
723
|
+
}
|
|
724
|
+
return [
|
|
725
|
+
`ran ${statement.replace(/\s+/g, " ").slice(0, 160)}`
|
|
726
|
+
];
|
|
727
|
+
}
|
|
728
|
+
__name(describeDurableStatement, "describeDurableStatement");
|
|
729
|
+
function splitTopLevel(text) {
|
|
730
|
+
const parts = [];
|
|
731
|
+
let depth = 0;
|
|
732
|
+
let quote;
|
|
733
|
+
let current = "";
|
|
734
|
+
for (const ch of text) {
|
|
735
|
+
if (quote) {
|
|
736
|
+
if (ch === quote) quote = void 0;
|
|
737
|
+
} else if (ch === "'" || ch === '"' || ch === "`") {
|
|
738
|
+
quote = ch;
|
|
739
|
+
} else if (ch === "(") {
|
|
740
|
+
depth++;
|
|
741
|
+
} else if (ch === ")") {
|
|
742
|
+
depth--;
|
|
743
|
+
} else if (ch === "," && depth === 0) {
|
|
744
|
+
parts.push(current.trim());
|
|
745
|
+
current = "";
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
current += ch;
|
|
749
|
+
}
|
|
750
|
+
if (current.trim()) parts.push(current.trim());
|
|
751
|
+
return parts;
|
|
752
|
+
}
|
|
753
|
+
__name(splitTopLevel, "splitTopLevel");
|
|
682
754
|
function compareStrings(a, b) {
|
|
683
755
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
684
756
|
}
|
|
@@ -797,7 +869,8 @@ async function releaseSchemaLock(orm, dialect) {
|
|
|
797
869
|
}
|
|
798
870
|
}
|
|
799
871
|
__name(releaseSchemaLock, "releaseSchemaLock");
|
|
800
|
-
async function ensureMikroOrmDurableSchema(orm) {
|
|
872
|
+
async function ensureMikroOrmDurableSchema(orm, options = {}) {
|
|
873
|
+
const logger = options.logger ?? console;
|
|
801
874
|
const dialect = detectSqlDialect(orm);
|
|
802
875
|
await orm.em.getConnection().execute(createMarkerTableSql());
|
|
803
876
|
const expected = computeExpectedFingerprint(orm, DURABLE_TABLE_NAMES);
|
|
@@ -810,8 +883,9 @@ async function ensureMikroOrmDurableSchema(orm) {
|
|
|
810
883
|
if (await readStoredFingerprint(orm) === expected) {
|
|
811
884
|
return;
|
|
812
885
|
}
|
|
813
|
-
await healDurableSchema(orm);
|
|
886
|
+
const { repairs, freshInstall } = await healDurableSchema(orm);
|
|
814
887
|
await writeFingerprint(orm, dialect, expected);
|
|
888
|
+
if (repairs.length > 0 && !freshInstall) logger.warn(mikroOrmSchemaRepairWarning(repairs));
|
|
815
889
|
} finally {
|
|
816
890
|
await releaseSchemaLock(orm, dialect);
|
|
817
891
|
}
|
|
@@ -826,9 +900,14 @@ async function healDurableSchema(orm) {
|
|
|
826
900
|
return table !== void 0 && DURABLE_TABLE_NAMES.has(table);
|
|
827
901
|
});
|
|
828
902
|
const connection = orm.em.getConnection();
|
|
903
|
+
const created = new Set(ours.filter((statement) => /^create\s+table\b/i.test(statement)).map((statement) => targetTable(statement)));
|
|
904
|
+
const repairs = [];
|
|
829
905
|
for (const statement of ours) {
|
|
830
906
|
try {
|
|
831
907
|
await connection.execute(statement);
|
|
908
|
+
const table = targetTable(statement);
|
|
909
|
+
const isCreateTable = /^create\s+table\b/i.test(statement);
|
|
910
|
+
if (isCreateTable || !created.has(table)) repairs.push(...describeDurableStatement(statement));
|
|
832
911
|
} catch (err) {
|
|
833
912
|
if (isRequiredStructure(statement)) {
|
|
834
913
|
throw err;
|
|
@@ -837,7 +916,17 @@ async function healDurableSchema(orm) {
|
|
|
837
916
|
console.warn(`[nestjs-durable-store-mikro-orm] skipped a non-structural durable-schema statement that failed; the column is left as-is (functional) \u2014 repair the data out of band to converge its type. Statement: ${statement} \u2014 ${message}`);
|
|
838
917
|
}
|
|
839
918
|
}
|
|
840
|
-
await alignDurableCollation(orm);
|
|
919
|
+
const converted = await alignDurableCollation(orm);
|
|
920
|
+
for (const { table, from, to } of converted) {
|
|
921
|
+
if (!created.has(table)) repairs.push(`converted ${table} collation from ${from} to ${to}`);
|
|
922
|
+
}
|
|
923
|
+
const freshInstall = [
|
|
924
|
+
...DURABLE_TABLE_NAMES
|
|
925
|
+
].every((table) => created.has(table));
|
|
926
|
+
return {
|
|
927
|
+
repairs,
|
|
928
|
+
freshInstall
|
|
929
|
+
};
|
|
841
930
|
}
|
|
842
931
|
__name(healDurableSchema, "healDurableSchema");
|
|
843
932
|
function isSafeSqlIdentifier(value) {
|
|
@@ -845,17 +934,18 @@ function isSafeSqlIdentifier(value) {
|
|
|
845
934
|
}
|
|
846
935
|
__name(isSafeSqlIdentifier, "isSafeSqlIdentifier");
|
|
847
936
|
async function alignDurableCollation(orm) {
|
|
937
|
+
const converted = [];
|
|
848
938
|
const platform = String(orm.em.getPlatform().constructor.name).toLowerCase();
|
|
849
939
|
if (!platform.includes("mysql") && !platform.includes("maria")) {
|
|
850
|
-
return;
|
|
940
|
+
return converted;
|
|
851
941
|
}
|
|
852
942
|
const collate = orm.config.get("collate");
|
|
853
943
|
if (typeof collate !== "string" || !isSafeSqlIdentifier(collate)) {
|
|
854
|
-
return;
|
|
944
|
+
return converted;
|
|
855
945
|
}
|
|
856
946
|
const charset = collate.split("_")[0];
|
|
857
947
|
if (!charset || !isSafeSqlIdentifier(charset)) {
|
|
858
|
-
return;
|
|
948
|
+
return converted;
|
|
859
949
|
}
|
|
860
950
|
const connection = orm.em.getConnection();
|
|
861
951
|
for (const table of DURABLE_TABLE_NAMES) {
|
|
@@ -868,11 +958,17 @@ async function alignDurableCollation(orm) {
|
|
|
868
958
|
continue;
|
|
869
959
|
}
|
|
870
960
|
await connection.execute(`alter table \`${table}\` convert to character set ${charset} collate ${collate}`);
|
|
961
|
+
converted.push({
|
|
962
|
+
table,
|
|
963
|
+
from: current,
|
|
964
|
+
to: collate
|
|
965
|
+
});
|
|
871
966
|
} catch (err) {
|
|
872
967
|
const message = err instanceof Error ? err.message : String(err);
|
|
873
968
|
console.warn(`[nestjs-durable-store-mikro-orm] could not align collation for \`${table}\` to ${collate} (left as-is): ${message}`);
|
|
874
969
|
}
|
|
875
970
|
}
|
|
971
|
+
return converted;
|
|
876
972
|
}
|
|
877
973
|
__name(alignDurableCollation, "alignDurableCollation");
|
|
878
974
|
|
|
@@ -882,10 +978,12 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
882
978
|
__name(this, "MikroOrmStateStore");
|
|
883
979
|
}
|
|
884
980
|
orm;
|
|
981
|
+
opts;
|
|
885
982
|
scopeNamespace;
|
|
886
|
-
constructor(orm, opts) {
|
|
983
|
+
constructor(orm, opts = {}) {
|
|
887
984
|
this.orm = orm;
|
|
888
|
-
this.
|
|
985
|
+
this.opts = opts;
|
|
986
|
+
this.scopeNamespace = opts.scope?.namespace;
|
|
889
987
|
}
|
|
890
988
|
/**
|
|
891
989
|
* Derive a store confined to a single tenant `scope.namespace`, sharing this store's ORM (no new
|
|
@@ -895,6 +993,7 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
895
993
|
*/
|
|
896
994
|
withScope(scope) {
|
|
897
995
|
return new _MikroOrmStateStore(this.orm, {
|
|
996
|
+
...this.opts,
|
|
898
997
|
scope
|
|
899
998
|
});
|
|
900
999
|
}
|
|
@@ -912,7 +1011,9 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
912
1011
|
return em;
|
|
913
1012
|
}
|
|
914
1013
|
async ensureSchema() {
|
|
915
|
-
await ensureMikroOrmDurableSchema(this.orm
|
|
1014
|
+
await ensureMikroOrmDurableSchema(this.orm, {
|
|
1015
|
+
logger: this.opts.schemaLogger
|
|
1016
|
+
});
|
|
916
1017
|
}
|
|
917
1018
|
async tryAdmitSingleton(runId, tag, workflow, limit, retryWakeAt) {
|
|
918
1019
|
return this.fork().transactional(async (em) => {
|
|
@@ -938,6 +1039,7 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
938
1039
|
}, {
|
|
939
1040
|
status: "suspended",
|
|
940
1041
|
wakeAt: new Date(patch.wakeAt),
|
|
1042
|
+
tags: patch.tags,
|
|
941
1043
|
updatedAt: patch.updatedAt
|
|
942
1044
|
});
|
|
943
1045
|
return false;
|
|
@@ -1157,7 +1259,7 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1157
1259
|
});
|
|
1158
1260
|
return rows.map(fromRunEntity);
|
|
1159
1261
|
}
|
|
1160
|
-
async listOrphanedRuns(nowMs, limit, namespace) {
|
|
1262
|
+
async listOrphanedRuns(nowMs, limit, namespace, ownedBy) {
|
|
1161
1263
|
if (limit <= 0) return [];
|
|
1162
1264
|
const em = this.fork();
|
|
1163
1265
|
const rows = await em.find(WorkflowRunEntity, {
|
|
@@ -1175,7 +1277,16 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1175
1277
|
lockedUntil: {
|
|
1176
1278
|
$lte: new Date(nowMs)
|
|
1177
1279
|
}
|
|
1178
|
-
}
|
|
1280
|
+
},
|
|
1281
|
+
// A live lease left by a previous process with the caller's own instance id.
|
|
1282
|
+
...ownedBy ? [
|
|
1283
|
+
{
|
|
1284
|
+
lockedBy: ownedBy.owner,
|
|
1285
|
+
lockedUntil: {
|
|
1286
|
+
$lt: new Date(ownedBy.lockedBefore)
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
] : []
|
|
1179
1290
|
],
|
|
1180
1291
|
...namespace !== void 0 ? {
|
|
1181
1292
|
namespace
|
|
@@ -1244,10 +1355,13 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1244
1355
|
});
|
|
1245
1356
|
return affected === 1;
|
|
1246
1357
|
}
|
|
1247
|
-
async releaseRunLock(runId) {
|
|
1358
|
+
async releaseRunLock(runId, owner) {
|
|
1248
1359
|
const em = this.fork();
|
|
1249
|
-
await em.nativeUpdate(WorkflowRunEntity, {
|
|
1360
|
+
await em.nativeUpdate(WorkflowRunEntity, owner === void 0 ? {
|
|
1250
1361
|
id: runId
|
|
1362
|
+
} : {
|
|
1363
|
+
id: runId,
|
|
1364
|
+
lockedBy: owner
|
|
1251
1365
|
}, {
|
|
1252
1366
|
lockedBy: null,
|
|
1253
1367
|
lockedUntil: null
|
|
@@ -1579,7 +1693,7 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
|
1579
1693
|
* single statement. */
|
|
1580
1694
|
async updateSchedule(id, patch, expectedNextFireAt) {
|
|
1581
1695
|
const data = {};
|
|
1582
|
-
if (patch.namespace !== void 0) data.namespace = patch.namespace;
|
|
1696
|
+
if (patch.namespace !== void 0) data.namespace = patch.namespace || "default";
|
|
1583
1697
|
if (patch.workflow !== void 0) data.workflow = patch.workflow;
|
|
1584
1698
|
if (patch.paused !== void 0) data.paused = patch.paused;
|
|
1585
1699
|
if ("nextFireAt" in patch) data.nextFireAt = patch.nextFireAt ?? null;
|
|
@@ -1965,7 +2079,7 @@ function runUpdateData(patch) {
|
|
|
1965
2079
|
if ("tags" in patch) data.tags = patch.tags ?? null;
|
|
1966
2080
|
if ("searchAttributes" in patch) data.searchAttributes = patch.searchAttributes ?? null;
|
|
1967
2081
|
if ("priority" in patch) data.priority = patch.priority ?? null;
|
|
1968
|
-
if ("namespace" in patch) data.namespace = patch.namespace
|
|
2082
|
+
if ("namespace" in patch) data.namespace = patch.namespace || "default";
|
|
1969
2083
|
if ("origin" in patch) data.origin = patch.origin ?? null;
|
|
1970
2084
|
if (patch.createdAt != null) data.createdAt = patch.createdAt;
|
|
1971
2085
|
if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;
|
|
@@ -1989,7 +2103,7 @@ function toRunEntity(run) {
|
|
|
1989
2103
|
e.tags = run.tags ?? null;
|
|
1990
2104
|
e.searchAttributes = run.searchAttributes ?? null;
|
|
1991
2105
|
e.priority = run.priority ?? null;
|
|
1992
|
-
e.namespace = run.namespace
|
|
2106
|
+
e.namespace = run.namespace || "default";
|
|
1993
2107
|
e.origin = run.origin ?? null;
|
|
1994
2108
|
e.createdAt = run.createdAt;
|
|
1995
2109
|
e.updatedAt = run.updatedAt;
|
|
@@ -2131,6 +2245,7 @@ export {
|
|
|
2131
2245
|
WorkflowRunRepository,
|
|
2132
2246
|
durableEntities,
|
|
2133
2247
|
durableManagedTables,
|
|
2134
|
-
ensureMikroOrmDurableSchema
|
|
2248
|
+
ensureMikroOrmDurableSchema,
|
|
2249
|
+
mikroOrmSchemaRepairWarning
|
|
2135
2250
|
};
|
|
2136
2251
|
//# sourceMappingURL=index.js.map
|