@classytic/arc 1.1.0 → 2.1.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/README.md +247 -794
- package/bin/arc.js +91 -52
- package/dist/EventTransport-BD2U0BTc.d.mts +100 -0
- package/dist/EventTransport-BD2U0BTc.d.mts.map +1 -0
- package/dist/HookSystem-BsGV-j2l.mjs +405 -0
- package/dist/HookSystem-BsGV-j2l.mjs.map +1 -0
- package/dist/ResourceRegistry-DsN4KJjV.mjs +250 -0
- package/dist/ResourceRegistry-DsN4KJjV.mjs.map +1 -0
- package/dist/adapters/index.d.mts +5 -0
- package/dist/adapters/index.mjs +3 -0
- package/dist/audit/index.d.mts +82 -0
- package/dist/audit/index.d.mts.map +1 -0
- package/dist/audit/index.mjs +276 -0
- package/dist/audit/index.mjs.map +1 -0
- package/dist/audit/mongodb.d.mts +5 -0
- package/dist/audit/mongodb.mjs +3 -0
- package/dist/audited-C3T5DTUx.mjs +141 -0
- package/dist/audited-C3T5DTUx.mjs.map +1 -0
- package/dist/auth/index.d.mts +189 -0
- package/dist/auth/index.d.mts.map +1 -0
- package/dist/auth/index.mjs +1102 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth/redis-session.d.mts +44 -0
- package/dist/auth/redis-session.d.mts.map +1 -0
- package/dist/auth/redis-session.mjs +76 -0
- package/dist/auth/redis-session.mjs.map +1 -0
- package/dist/betterAuthOpenApi-BrHKeSAx.mjs +250 -0
- package/dist/betterAuthOpenApi-BrHKeSAx.mjs.map +1 -0
- package/dist/cache/index.d.mts +146 -0
- package/dist/cache/index.d.mts.map +1 -0
- package/dist/cache/index.mjs +92 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/caching-Bl28lYsR.mjs +94 -0
- package/dist/caching-Bl28lYsR.mjs.map +1 -0
- package/dist/chunk-C7Uep-_p.mjs +20 -0
- package/dist/circuitBreaker-DeY4FCjs.mjs +1097 -0
- package/dist/circuitBreaker-DeY4FCjs.mjs.map +1 -0
- package/dist/cli/commands/describe.d.mts +19 -0
- package/dist/cli/commands/describe.d.mts.map +1 -0
- package/dist/cli/commands/describe.mjs +239 -0
- package/dist/cli/commands/describe.mjs.map +1 -0
- package/dist/cli/commands/docs.d.mts +14 -0
- package/dist/cli/commands/docs.d.mts.map +1 -0
- package/dist/cli/commands/docs.mjs +53 -0
- package/dist/cli/commands/docs.mjs.map +1 -0
- package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -1
- package/dist/cli/commands/generate.d.mts.map +1 -0
- package/dist/cli/commands/generate.mjs +358 -0
- package/dist/cli/commands/generate.mjs.map +1 -0
- package/dist/cli/commands/{init.d.ts → init.d.mts} +12 -8
- package/dist/cli/commands/init.d.mts.map +1 -0
- package/dist/cli/commands/{init.js → init.mjs} +807 -616
- package/dist/cli/commands/init.mjs.map +1 -0
- package/dist/cli/commands/introspect.d.mts +11 -0
- package/dist/cli/commands/introspect.d.mts.map +1 -0
- package/dist/cli/commands/introspect.mjs +76 -0
- package/dist/cli/commands/introspect.mjs.map +1 -0
- package/dist/cli/index.d.mts +17 -0
- package/dist/cli/index.d.mts.map +1 -0
- package/dist/cli/index.mjs +157 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/constants-DdXFXQtN.mjs +85 -0
- package/dist/constants-DdXFXQtN.mjs.map +1 -0
- package/dist/core/index.d.mts +5 -0
- package/dist/core/index.mjs +4 -0
- package/dist/createApp-CUgNqegw.mjs +560 -0
- package/dist/createApp-CUgNqegw.mjs.map +1 -0
- package/dist/defineResource-k0_BDn8v.mjs +2197 -0
- package/dist/defineResource-k0_BDn8v.mjs.map +1 -0
- package/dist/discovery/index.d.mts +47 -0
- package/dist/discovery/index.d.mts.map +1 -0
- package/dist/discovery/index.mjs +110 -0
- package/dist/discovery/index.mjs.map +1 -0
- package/dist/docs/index.d.mts +163 -0
- package/dist/docs/index.d.mts.map +1 -0
- package/dist/docs/index.mjs +73 -0
- package/dist/docs/index.mjs.map +1 -0
- package/dist/elevation-BRy3yFWT.mjs +113 -0
- package/dist/elevation-BRy3yFWT.mjs.map +1 -0
- package/dist/elevation-B_2dRLVP.d.mts +88 -0
- package/dist/elevation-B_2dRLVP.d.mts.map +1 -0
- package/dist/errorHandler-BbcgBmIH.d.mts +73 -0
- package/dist/errorHandler-BbcgBmIH.d.mts.map +1 -0
- package/dist/errorHandler-C1okiriz.mjs +109 -0
- package/dist/errorHandler-C1okiriz.mjs.map +1 -0
- package/dist/errors-B9bZok84.mjs +212 -0
- package/dist/errors-B9bZok84.mjs.map +1 -0
- package/dist/errors-ChKiFz62.d.mts +125 -0
- package/dist/errors-ChKiFz62.d.mts.map +1 -0
- package/dist/eventPlugin-CTrLH3mt.d.mts +125 -0
- package/dist/eventPlugin-CTrLH3mt.d.mts.map +1 -0
- package/dist/eventPlugin-DGR_B2on.mjs +230 -0
- package/dist/eventPlugin-DGR_B2on.mjs.map +1 -0
- package/dist/events/index.d.mts +54 -0
- package/dist/events/index.d.mts.map +1 -0
- package/dist/events/index.mjs +52 -0
- package/dist/events/index.mjs.map +1 -0
- package/dist/events/transports/redis-stream-entry.d.mts +2 -0
- package/dist/events/transports/redis-stream-entry.mjs +178 -0
- package/dist/events/transports/redis-stream-entry.mjs.map +1 -0
- package/dist/events/transports/redis.d.mts +77 -0
- package/dist/events/transports/redis.d.mts.map +1 -0
- package/dist/events/transports/redis.mjs +125 -0
- package/dist/events/transports/redis.mjs.map +1 -0
- package/dist/externalPaths-DlINfKbP.d.mts +51 -0
- package/dist/externalPaths-DlINfKbP.d.mts.map +1 -0
- package/dist/factory/index.d.mts +64 -0
- package/dist/factory/index.d.mts.map +1 -0
- package/dist/factory/index.mjs +3 -0
- package/dist/fastifyAdapter-BkrGrlFi.d.mts +217 -0
- package/dist/fastifyAdapter-BkrGrlFi.d.mts.map +1 -0
- package/dist/fields-DyaDVX4J.d.mts +110 -0
- package/dist/fields-DyaDVX4J.d.mts.map +1 -0
- package/dist/fields-iagOozy0.mjs +115 -0
- package/dist/fields-iagOozy0.mjs.map +1 -0
- package/dist/hooks/index.d.mts +4 -0
- package/dist/hooks/index.mjs +3 -0
- package/dist/idempotency/index.d.mts +97 -0
- package/dist/idempotency/index.d.mts.map +1 -0
- package/dist/idempotency/index.mjs +320 -0
- package/dist/idempotency/index.mjs.map +1 -0
- package/dist/idempotency/mongodb.d.mts +2 -0
- package/dist/idempotency/mongodb.mjs +115 -0
- package/dist/idempotency/mongodb.mjs.map +1 -0
- package/dist/idempotency/redis.d.mts +2 -0
- package/dist/idempotency/redis.mjs +104 -0
- package/dist/idempotency/redis.mjs.map +1 -0
- package/dist/index.d.mts +261 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +105 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integrations/event-gateway.d.mts +47 -0
- package/dist/integrations/event-gateway.d.mts.map +1 -0
- package/dist/integrations/event-gateway.mjs +44 -0
- package/dist/integrations/event-gateway.mjs.map +1 -0
- package/dist/integrations/index.d.mts +5 -0
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs.d.mts +104 -0
- package/dist/integrations/jobs.d.mts.map +1 -0
- package/dist/integrations/jobs.mjs +124 -0
- package/dist/integrations/jobs.mjs.map +1 -0
- package/dist/integrations/streamline.d.mts +61 -0
- package/dist/integrations/streamline.d.mts.map +1 -0
- package/dist/integrations/streamline.mjs +126 -0
- package/dist/integrations/streamline.mjs.map +1 -0
- package/dist/integrations/websocket.d.mts +83 -0
- package/dist/integrations/websocket.d.mts.map +1 -0
- package/dist/integrations/websocket.mjs +289 -0
- package/dist/integrations/websocket.mjs.map +1 -0
- package/dist/interface-B01JvPVc.d.mts +78 -0
- package/dist/interface-B01JvPVc.d.mts.map +1 -0
- package/dist/interface-CZe8IkMf.d.mts +55 -0
- package/dist/interface-CZe8IkMf.d.mts.map +1 -0
- package/dist/interface-Ch8HU9uM.d.mts +1098 -0
- package/dist/interface-Ch8HU9uM.d.mts.map +1 -0
- package/dist/introspectionPlugin-rFdO8ZUa.mjs +54 -0
- package/dist/introspectionPlugin-rFdO8ZUa.mjs.map +1 -0
- package/dist/keys-BqNejWup.mjs +43 -0
- package/dist/keys-BqNejWup.mjs.map +1 -0
- package/dist/logger-Df2O2WsW.mjs +79 -0
- package/dist/logger-Df2O2WsW.mjs.map +1 -0
- package/dist/memory-cQgelFOj.mjs +144 -0
- package/dist/memory-cQgelFOj.mjs.map +1 -0
- package/dist/migrations/index.d.mts +157 -0
- package/dist/migrations/index.d.mts.map +1 -0
- package/dist/migrations/index.mjs +261 -0
- package/dist/migrations/index.mjs.map +1 -0
- package/dist/mongodb-BfJVlUJH.mjs +94 -0
- package/dist/mongodb-BfJVlUJH.mjs.map +1 -0
- package/dist/mongodb-CGzRbfAK.d.mts +119 -0
- package/dist/mongodb-CGzRbfAK.d.mts.map +1 -0
- package/dist/mongodb-JN-9JA7K.d.mts +72 -0
- package/dist/mongodb-JN-9JA7K.d.mts.map +1 -0
- package/dist/openapi-G3Cw7XuM.mjs +524 -0
- package/dist/openapi-G3Cw7XuM.mjs.map +1 -0
- package/dist/org/index.d.mts +69 -0
- package/dist/org/index.d.mts.map +1 -0
- package/dist/org/index.mjs +514 -0
- package/dist/org/index.mjs.map +1 -0
- package/dist/org/types.d.mts +83 -0
- package/dist/org/types.d.mts.map +1 -0
- package/dist/org/types.mjs +1 -0
- package/dist/permissions/index.d.mts +279 -0
- package/dist/permissions/index.d.mts.map +1 -0
- package/dist/permissions/index.mjs +579 -0
- package/dist/permissions/index.mjs.map +1 -0
- package/dist/plugins/index.d.mts +173 -0
- package/dist/plugins/index.d.mts.map +1 -0
- package/dist/plugins/index.mjs +523 -0
- package/dist/plugins/index.mjs.map +1 -0
- package/dist/plugins/response-cache.d.mts +88 -0
- package/dist/plugins/response-cache.d.mts.map +1 -0
- package/dist/plugins/response-cache.mjs +284 -0
- package/dist/plugins/response-cache.mjs.map +1 -0
- package/dist/plugins/tracing-entry.d.mts +2 -0
- package/dist/plugins/tracing-entry.mjs +186 -0
- package/dist/plugins/tracing-entry.mjs.map +1 -0
- package/dist/pluralize-CEweyOEm.mjs +87 -0
- package/dist/pluralize-CEweyOEm.mjs.map +1 -0
- package/dist/policies/{index.d.ts → index.d.mts} +204 -169
- package/dist/policies/index.d.mts.map +1 -0
- package/dist/policies/index.mjs +322 -0
- package/dist/policies/index.mjs.map +1 -0
- package/dist/presets/{index.d.ts → index.d.mts} +63 -131
- package/dist/presets/index.d.mts.map +1 -0
- package/dist/presets/index.mjs +144 -0
- package/dist/presets/index.mjs.map +1 -0
- package/dist/presets/multiTenant.d.mts +25 -0
- package/dist/presets/multiTenant.d.mts.map +1 -0
- package/dist/presets/multiTenant.mjs +114 -0
- package/dist/presets/multiTenant.mjs.map +1 -0
- package/dist/presets-BITljm96.mjs +120 -0
- package/dist/presets-BITljm96.mjs.map +1 -0
- package/dist/presets-DzSMwlKj.d.mts +58 -0
- package/dist/presets-DzSMwlKj.d.mts.map +1 -0
- package/dist/prisma-DJbMt3yf.mjs +628 -0
- package/dist/prisma-DJbMt3yf.mjs.map +1 -0
- package/dist/prisma-Dg9GoVdj.d.mts +275 -0
- package/dist/prisma-Dg9GoVdj.d.mts.map +1 -0
- package/dist/queryCachePlugin-7THaI5mt.d.mts +72 -0
- package/dist/queryCachePlugin-7THaI5mt.d.mts.map +1 -0
- package/dist/queryCachePlugin-DMBnp2Q0.mjs +139 -0
- package/dist/queryCachePlugin-DMBnp2Q0.mjs.map +1 -0
- package/dist/redis-D-JAeLtm.d.mts +50 -0
- package/dist/redis-D-JAeLtm.d.mts.map +1 -0
- package/dist/redis-stream-Bdh_vUU8.d.mts +104 -0
- package/dist/redis-stream-Bdh_vUU8.d.mts.map +1 -0
- package/dist/registry/index.d.mts +12 -0
- package/dist/registry/index.d.mts.map +1 -0
- package/dist/registry/index.mjs +4 -0
- package/dist/requestContext-QQD6ROJc.mjs +56 -0
- package/dist/requestContext-QQD6ROJc.mjs.map +1 -0
- package/dist/schemaConverter-BwrmWroW.mjs +99 -0
- package/dist/schemaConverter-BwrmWroW.mjs.map +1 -0
- package/dist/schemas/index.d.mts +64 -0
- package/dist/schemas/index.d.mts.map +1 -0
- package/dist/schemas/index.mjs +83 -0
- package/dist/schemas/index.mjs.map +1 -0
- package/dist/scope/index.d.mts +22 -0
- package/dist/scope/index.d.mts.map +1 -0
- package/dist/scope/index.mjs +66 -0
- package/dist/scope/index.mjs.map +1 -0
- package/dist/sessionManager-jPKLbHE0.d.mts +187 -0
- package/dist/sessionManager-jPKLbHE0.d.mts.map +1 -0
- package/dist/sse-B3c3_yZp.mjs +124 -0
- package/dist/sse-B3c3_yZp.mjs.map +1 -0
- package/dist/testing/index.d.mts +908 -0
- package/dist/testing/index.d.mts.map +1 -0
- package/dist/testing/index.mjs +1977 -0
- package/dist/testing/index.mjs.map +1 -0
- package/dist/tracing-Cc7vVQPp.d.mts +71 -0
- package/dist/tracing-Cc7vVQPp.d.mts.map +1 -0
- package/dist/typeGuards-DhMNLuvU.mjs +10 -0
- package/dist/typeGuards-DhMNLuvU.mjs.map +1 -0
- package/dist/types/index.d.mts +947 -0
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/index.mjs +15 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/types-Beqn1Un7.mjs +39 -0
- package/dist/types-Beqn1Un7.mjs.map +1 -0
- package/dist/types-CIgB7UUl.d.mts +446 -0
- package/dist/types-CIgB7UUl.d.mts.map +1 -0
- package/dist/types-aYB4V7uN.d.mts +87 -0
- package/dist/types-aYB4V7uN.d.mts.map +1 -0
- package/dist/utils/index.d.mts +748 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +6 -0
- package/package.json +194 -68
- package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
- package/dist/adapters/index.d.ts +0 -237
- package/dist/adapters/index.js +0 -668
- package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
- package/dist/audit/index.d.ts +0 -195
- package/dist/audit/index.js +0 -319
- package/dist/auth/index.d.ts +0 -47
- package/dist/auth/index.js +0 -174
- package/dist/cli/commands/docs.d.ts +0 -11
- package/dist/cli/commands/docs.js +0 -474
- package/dist/cli/commands/generate.js +0 -334
- package/dist/cli/commands/introspect.d.ts +0 -8
- package/dist/cli/commands/introspect.js +0 -338
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/index.js +0 -3269
- package/dist/core/index.d.ts +0 -220
- package/dist/core/index.js +0 -2786
- package/dist/createApp-Ce9wl8W9.d.ts +0 -77
- package/dist/docs/index.d.ts +0 -166
- package/dist/docs/index.js +0 -658
- package/dist/errors-8WIxGS_6.d.ts +0 -122
- package/dist/events/index.d.ts +0 -117
- package/dist/events/index.js +0 -89
- package/dist/factory/index.d.ts +0 -38
- package/dist/factory/index.js +0 -1652
- package/dist/hooks/index.d.ts +0 -4
- package/dist/hooks/index.js +0 -199
- package/dist/idempotency/index.d.ts +0 -323
- package/dist/idempotency/index.js +0 -500
- package/dist/index-B4t03KQ0.d.ts +0 -1366
- package/dist/index.d.ts +0 -135
- package/dist/index.js +0 -4756
- package/dist/migrations/index.d.ts +0 -185
- package/dist/migrations/index.js +0 -274
- package/dist/org/index.d.ts +0 -129
- package/dist/org/index.js +0 -220
- package/dist/permissions/index.d.ts +0 -144
- package/dist/permissions/index.js +0 -103
- package/dist/plugins/index.d.ts +0 -46
- package/dist/plugins/index.js +0 -1069
- package/dist/policies/index.js +0 -196
- package/dist/presets/index.js +0 -384
- package/dist/presets/multiTenant.d.ts +0 -39
- package/dist/presets/multiTenant.js +0 -112
- package/dist/registry/index.d.ts +0 -16
- package/dist/registry/index.js +0 -253
- package/dist/testing/index.d.ts +0 -618
- package/dist/testing/index.js +0 -48020
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -8
- package/dist/types-B99TBmFV.d.ts +0 -76
- package/dist/types-BvckRbs2.d.ts +0 -143
- package/dist/utils/index.d.ts +0 -679
- package/dist/utils/index.js +0 -931
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
//#region src/migrations/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* Define a migration
|
|
6
|
+
*/
|
|
7
|
+
function defineMigration(migration) {
|
|
8
|
+
return migration;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Migration Runner
|
|
12
|
+
*
|
|
13
|
+
* Manages execution of migrations with tracking and rollback support.
|
|
14
|
+
*/
|
|
15
|
+
var MigrationRunner = class {
|
|
16
|
+
collectionName = "_migrations";
|
|
17
|
+
db;
|
|
18
|
+
constructor(db) {
|
|
19
|
+
this.db = db;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run all pending migrations
|
|
23
|
+
*/
|
|
24
|
+
async up(migrations) {
|
|
25
|
+
const applied = await this.getAppliedMigrations();
|
|
26
|
+
const appliedVersions = new Set(applied.map((m) => `${m.resource}:${m.version}`));
|
|
27
|
+
const pending = migrations.filter((m) => !appliedVersions.has(`${m.resource}:${m.version}`)).sort((a, b) => a.version - b.version);
|
|
28
|
+
if (pending.length === 0) {
|
|
29
|
+
console.log("No pending migrations");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(`Running ${pending.length} migration(s)...\n`);
|
|
33
|
+
for (const migration of pending) await this.runMigration(migration, "up");
|
|
34
|
+
console.log("\nAll migrations completed successfully");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Rollback last migration
|
|
38
|
+
*/
|
|
39
|
+
async down(migrations) {
|
|
40
|
+
const applied = await this.getAppliedMigrations();
|
|
41
|
+
if (applied.length === 0) {
|
|
42
|
+
console.log("No migrations to rollback");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const last = applied[applied.length - 1];
|
|
46
|
+
if (!last) {
|
|
47
|
+
console.log("No migrations to rollback");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const migration = migrations.find((m) => m.resource === last.resource && m.version === last.version);
|
|
51
|
+
if (!migration) throw new Error(`Migration ${last.resource}:${last.version} not found in migration files`);
|
|
52
|
+
console.log(`Rolling back ${migration.resource} v${migration.version}...`);
|
|
53
|
+
await this.runMigration(migration, "down", true);
|
|
54
|
+
console.log("Rollback completed");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Rollback to specific version
|
|
58
|
+
*/
|
|
59
|
+
async downTo(migrations, targetVersion) {
|
|
60
|
+
const toRollback = (await this.getAppliedMigrations()).filter((m) => m.version > targetVersion).reverse();
|
|
61
|
+
if (toRollback.length === 0) {
|
|
62
|
+
console.log(`Already at or below version ${targetVersion}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
console.log(`Rolling back ${toRollback.length} migration(s)...\n`);
|
|
66
|
+
for (const record of toRollback) {
|
|
67
|
+
const migration = migrations.find((m) => m.resource === record.resource && m.version === record.version);
|
|
68
|
+
if (!migration) throw new Error(`Migration ${record.resource}:${record.version} not found`);
|
|
69
|
+
await this.runMigration(migration, "down", true);
|
|
70
|
+
}
|
|
71
|
+
console.log("\nRollback completed");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get all applied migrations
|
|
75
|
+
*/
|
|
76
|
+
async getAppliedMigrations() {
|
|
77
|
+
return await this.db.collection(this.collectionName).find({}).sort({ appliedAt: 1 }).toArray();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get pending migrations
|
|
81
|
+
*/
|
|
82
|
+
async getPendingMigrations(migrations) {
|
|
83
|
+
const applied = await this.getAppliedMigrations();
|
|
84
|
+
const appliedVersions = new Set(applied.map((m) => `${m.resource}:${m.version}`));
|
|
85
|
+
return migrations.filter((m) => !appliedVersions.has(`${m.resource}:${m.version}`));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if migrations are up to date
|
|
89
|
+
*/
|
|
90
|
+
async isUpToDate(migrations) {
|
|
91
|
+
return (await this.getPendingMigrations(migrations)).length === 0;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Run a single migration
|
|
95
|
+
*/
|
|
96
|
+
async runMigration(migration, direction, isRollback = false) {
|
|
97
|
+
const start = Date.now();
|
|
98
|
+
const action = direction === "up" ? "Applying" : "Rolling back";
|
|
99
|
+
console.log(`${action} ${migration.resource} v${migration.version}${migration.description ? `: ${migration.description}` : ""}...`);
|
|
100
|
+
try {
|
|
101
|
+
if (direction === "up") {
|
|
102
|
+
await migration.up(this.db);
|
|
103
|
+
if (migration.validate) {
|
|
104
|
+
if (!await migration.validate(this.db)) throw new Error("Migration validation failed");
|
|
105
|
+
}
|
|
106
|
+
await this.recordMigration(migration, Date.now() - start);
|
|
107
|
+
} else {
|
|
108
|
+
await migration.down(this.db);
|
|
109
|
+
if (isRollback) await this.removeMigration(migration);
|
|
110
|
+
}
|
|
111
|
+
const duration = Date.now() - start;
|
|
112
|
+
console.log(`✅ ${migration.resource} v${migration.version} (${duration}ms)`);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error(`❌ ${migration.resource} v${migration.version} failed:`, error.message);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Record a completed migration
|
|
120
|
+
*/
|
|
121
|
+
async recordMigration(migration, executionTime) {
|
|
122
|
+
await this.db.collection(this.collectionName).insertOne({
|
|
123
|
+
version: migration.version,
|
|
124
|
+
resource: migration.resource,
|
|
125
|
+
description: migration.description,
|
|
126
|
+
appliedAt: /* @__PURE__ */ new Date(),
|
|
127
|
+
executionTime
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Remove a migration record
|
|
132
|
+
*/
|
|
133
|
+
async removeMigration(migration) {
|
|
134
|
+
await this.db.collection(this.collectionName).deleteOne({
|
|
135
|
+
version: migration.version,
|
|
136
|
+
resource: migration.resource
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Add versioning to resource definition
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* export default defineResource({
|
|
145
|
+
* name: 'product',
|
|
146
|
+
* version: 2,
|
|
147
|
+
* migrations: [productV1ToV2Migration],
|
|
148
|
+
* // ... rest of resource definition
|
|
149
|
+
* });
|
|
150
|
+
*/
|
|
151
|
+
function withSchemaVersion(version, migrations) {
|
|
152
|
+
return {
|
|
153
|
+
version,
|
|
154
|
+
migrations
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Global migration registry
|
|
159
|
+
*/
|
|
160
|
+
var MigrationRegistry = class {
|
|
161
|
+
migrations = /* @__PURE__ */ new Map();
|
|
162
|
+
/**
|
|
163
|
+
* Register a migration
|
|
164
|
+
*/
|
|
165
|
+
register(migration) {
|
|
166
|
+
const existing = this.migrations.get(migration.resource) || [];
|
|
167
|
+
existing.push(migration);
|
|
168
|
+
existing.sort((a, b) => a.version - b.version);
|
|
169
|
+
this.migrations.set(migration.resource, existing);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Register multiple migrations
|
|
173
|
+
*/
|
|
174
|
+
registerMany(migrations) {
|
|
175
|
+
for (const migration of migrations) this.register(migration);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get all migrations for a resource
|
|
179
|
+
*/
|
|
180
|
+
getForResource(resource) {
|
|
181
|
+
return this.migrations.get(resource) || [];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get all migrations
|
|
185
|
+
*/
|
|
186
|
+
getAll() {
|
|
187
|
+
const all = [];
|
|
188
|
+
for (const migrations of this.migrations.values()) all.push(...migrations);
|
|
189
|
+
return all.sort((a, b) => a.version - b.version);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get migration by resource and version
|
|
193
|
+
*/
|
|
194
|
+
get(resource, version) {
|
|
195
|
+
return (this.migrations.get(resource) || []).find((m) => m.version === version);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Clear all registrations
|
|
199
|
+
*/
|
|
200
|
+
clear() {
|
|
201
|
+
this.migrations.clear();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Global migration registry instance
|
|
206
|
+
*/
|
|
207
|
+
const migrationRegistry = new MigrationRegistry();
|
|
208
|
+
/**
|
|
209
|
+
* Common migration helpers
|
|
210
|
+
*/
|
|
211
|
+
const migrationHelpers = {
|
|
212
|
+
renameField: (collection, oldName, newName) => defineMigration({
|
|
213
|
+
version: 0,
|
|
214
|
+
resource: collection,
|
|
215
|
+
description: `Rename ${oldName} to ${newName}`,
|
|
216
|
+
up: async (db) => {
|
|
217
|
+
await db.collection(collection).updateMany({}, { $rename: { [oldName]: newName } });
|
|
218
|
+
},
|
|
219
|
+
down: async (db) => {
|
|
220
|
+
await db.collection(collection).updateMany({}, { $rename: { [newName]: oldName } });
|
|
221
|
+
}
|
|
222
|
+
}),
|
|
223
|
+
addField: (collection, fieldName, defaultValue) => defineMigration({
|
|
224
|
+
version: 0,
|
|
225
|
+
resource: collection,
|
|
226
|
+
description: `Add ${fieldName} field`,
|
|
227
|
+
up: async (db) => {
|
|
228
|
+
await db.collection(collection).updateMany({ [fieldName]: { $exists: false } }, { $set: { [fieldName]: defaultValue } });
|
|
229
|
+
},
|
|
230
|
+
down: async (db) => {
|
|
231
|
+
await db.collection(collection).updateMany({}, { $unset: { [fieldName]: "" } });
|
|
232
|
+
}
|
|
233
|
+
}),
|
|
234
|
+
removeField: (collection, fieldName) => defineMigration({
|
|
235
|
+
version: 0,
|
|
236
|
+
resource: collection,
|
|
237
|
+
description: `Remove ${fieldName} field`,
|
|
238
|
+
up: async (db) => {
|
|
239
|
+
await db.collection(collection).updateMany({}, { $unset: { [fieldName]: "" } });
|
|
240
|
+
},
|
|
241
|
+
down: async (db) => {
|
|
242
|
+
console.warn(`Cannot restore ${fieldName} field - data was deleted`);
|
|
243
|
+
}
|
|
244
|
+
}),
|
|
245
|
+
createIndex: (collection, fields, options) => defineMigration({
|
|
246
|
+
version: 0,
|
|
247
|
+
resource: collection,
|
|
248
|
+
description: `Create index on ${Object.keys(fields).join(", ")}`,
|
|
249
|
+
up: async (db) => {
|
|
250
|
+
await db.collection(collection).createIndex(fields, options);
|
|
251
|
+
},
|
|
252
|
+
down: async (db) => {
|
|
253
|
+
const indexName = typeof options?.name === "string" ? options.name : Object.keys(fields).join("_");
|
|
254
|
+
await db.collection(collection).dropIndex(indexName);
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
//#endregion
|
|
260
|
+
export { MigrationRegistry, MigrationRunner, defineMigration, migrationHelpers, migrationRegistry, withSchemaVersion };
|
|
261
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/migrations/index.ts"],"sourcesContent":["/**\n * Schema Versioning and Migrations System\n *\n * Manages database schema changes over time with version tracking.\n * Supports forward migrations, rollbacks, and schema compatibility layers.\n *\n * @example\n * import { defineMigration, MigrationRunner } from '@classytic/arc/migrations';\n *\n * const productV2 = defineMigration({\n * version: 2,\n * resource: 'product',\n * up: async (db) => {\n * await db.collection('products').updateMany(\n * {},\n * { $rename: { 'oldField': 'newField' } }\n * );\n * },\n * down: async (db) => {\n * await db.collection('products').updateMany(\n * {},\n * { $rename: { 'newField': 'oldField' } }\n * );\n * },\n * });\n *\n * const runner = new MigrationRunner(mongoose.connection.db);\n * await runner.up(); // Run all pending migrations\n */\n\nimport mongoose, { type Connection } from 'mongoose';\n\nexport interface Migration {\n /** Migration version (sequential number) */\n version: number;\n\n /** Resource name this migration applies to */\n resource: string;\n\n /** Description of the migration */\n description?: string;\n\n /**\n * Forward migration (apply schema change)\n */\n up: (db: mongoose.mongo.Db) => Promise<void>;\n\n /**\n * Backward migration (revert schema change)\n */\n down: (db: mongoose.mongo.Db) => Promise<void>;\n\n /**\n * Optional validation that data is compatible after migration\n */\n validate?: (db: mongoose.mongo.Db) => Promise<boolean>;\n}\n\nexport interface MigrationRecord {\n version: number;\n resource: string;\n description?: string;\n appliedAt: Date;\n executionTime: number;\n}\n\n/**\n * Define a migration\n */\nexport function defineMigration(migration: Migration): Migration {\n return migration;\n}\n\n/**\n * Migration Runner\n *\n * Manages execution of migrations with tracking and rollback support.\n */\nexport class MigrationRunner {\n private readonly collectionName = '_migrations';\n\n private readonly db: mongoose.mongo.Db;\n\n constructor(db: mongoose.mongo.Db) {\n this.db = db;\n }\n\n /**\n * Run all pending migrations\n */\n async up(migrations: Migration[]): Promise<void> {\n const applied = await this.getAppliedMigrations();\n const appliedVersions = new Set(applied.map((m) => `${m.resource}:${m.version}`));\n\n // Sort migrations by version\n const pending = migrations\n .filter((m) => !appliedVersions.has(`${m.resource}:${m.version}`))\n .sort((a, b) => a.version - b.version);\n\n if (pending.length === 0) {\n console.log('No pending migrations');\n return;\n }\n\n console.log(`Running ${pending.length} migration(s)...\\n`);\n\n for (const migration of pending) {\n await this.runMigration(migration, 'up');\n }\n\n console.log('\\nAll migrations completed successfully');\n }\n\n /**\n * Rollback last migration\n */\n async down(migrations: Migration[]): Promise<void> {\n const applied = await this.getAppliedMigrations();\n if (applied.length === 0) {\n console.log('No migrations to rollback');\n return;\n }\n\n // Get last applied migration\n const last = applied[applied.length - 1];\n if (!last) {\n console.log('No migrations to rollback');\n return;\n }\n\n const migration = migrations.find(\n (m) => m.resource === last.resource && m.version === last.version\n );\n\n if (!migration) {\n throw new Error(\n `Migration ${last.resource}:${last.version} not found in migration files`\n );\n }\n\n console.log(`Rolling back ${migration.resource} v${migration.version}...`);\n await this.runMigration(migration, 'down', true);\n console.log('Rollback completed');\n }\n\n /**\n * Rollback to specific version\n */\n async downTo(migrations: Migration[], targetVersion: number): Promise<void> {\n const applied = await this.getAppliedMigrations();\n const toRollback = applied.filter((m) => m.version > targetVersion).reverse();\n\n if (toRollback.length === 0) {\n console.log(`Already at or below version ${targetVersion}`);\n return;\n }\n\n console.log(`Rolling back ${toRollback.length} migration(s)...\\n`);\n\n for (const record of toRollback) {\n const migration = migrations.find(\n (m) => m.resource === record.resource && m.version === record.version\n );\n\n if (!migration) {\n throw new Error(`Migration ${record.resource}:${record.version} not found`);\n }\n\n await this.runMigration(migration, 'down', true);\n }\n\n console.log('\\nRollback completed');\n }\n\n /**\n * Get all applied migrations\n */\n async getAppliedMigrations(): Promise<MigrationRecord[]> {\n const collection = this.db.collection(this.collectionName);\n const records = await collection.find({}).sort({ appliedAt: 1 }).toArray();\n return records as unknown as MigrationRecord[];\n }\n\n /**\n * Get pending migrations\n */\n async getPendingMigrations(migrations: Migration[]): Promise<Migration[]> {\n const applied = await this.getAppliedMigrations();\n const appliedVersions = new Set(applied.map((m) => `${m.resource}:${m.version}`));\n return migrations.filter((m) => !appliedVersions.has(`${m.resource}:${m.version}`));\n }\n\n /**\n * Check if migrations are up to date\n */\n async isUpToDate(migrations: Migration[]): Promise<boolean> {\n const pending = await this.getPendingMigrations(migrations);\n return pending.length === 0;\n }\n\n /**\n * Run a single migration\n */\n private async runMigration(\n migration: Migration,\n direction: 'up' | 'down',\n isRollback = false\n ): Promise<void> {\n const start = Date.now();\n const action = direction === 'up' ? 'Applying' : 'Rolling back';\n\n console.log(\n `${action} ${migration.resource} v${migration.version}${migration.description ? `: ${migration.description}` : ''}...`\n );\n\n try {\n // Run migration\n if (direction === 'up') {\n await migration.up(this.db);\n\n // Validate if provided\n if (migration.validate) {\n const valid = await migration.validate(this.db);\n if (!valid) {\n throw new Error('Migration validation failed');\n }\n }\n\n // Record migration\n await this.recordMigration(migration, Date.now() - start);\n } else {\n await migration.down(this.db);\n\n // Remove record\n if (isRollback) {\n await this.removeMigration(migration);\n }\n }\n\n const duration = Date.now() - start;\n console.log(`✅ ${migration.resource} v${migration.version} (${duration}ms)`);\n } catch (error) {\n console.error(\n `❌ ${migration.resource} v${migration.version} failed:`,\n (error as Error).message\n );\n throw error;\n }\n }\n\n /**\n * Record a completed migration\n */\n private async recordMigration(migration: Migration, executionTime: number): Promise<void> {\n const collection = this.db.collection(this.collectionName);\n await collection.insertOne({\n version: migration.version,\n resource: migration.resource,\n description: migration.description,\n appliedAt: new Date(),\n executionTime,\n });\n }\n\n /**\n * Remove a migration record\n */\n private async removeMigration(migration: Migration): Promise<void> {\n const collection = this.db.collection(this.collectionName);\n await collection.deleteOne({\n version: migration.version,\n resource: migration.resource,\n });\n }\n}\n\n/**\n * Schema version definition for resources\n */\nexport interface SchemaVersion {\n version: number;\n migrations: Migration[];\n}\n\n/**\n * Add versioning to resource definition\n *\n * @example\n * export default defineResource({\n * name: 'product',\n * version: 2,\n * migrations: [productV1ToV2Migration],\n * // ... rest of resource definition\n * });\n */\nexport function withSchemaVersion(\n version: number,\n migrations: Migration[]\n): SchemaVersion {\n return { version, migrations };\n}\n\n/**\n * Global migration registry\n */\nexport class MigrationRegistry {\n private migrations: Map<string, Migration[]> = new Map();\n\n /**\n * Register a migration\n */\n register(migration: Migration): void {\n const existing = this.migrations.get(migration.resource) || [];\n existing.push(migration);\n existing.sort((a, b) => a.version - b.version);\n this.migrations.set(migration.resource, existing);\n }\n\n /**\n * Register multiple migrations\n */\n registerMany(migrations: Migration[]): void {\n for (const migration of migrations) {\n this.register(migration);\n }\n }\n\n /**\n * Get all migrations for a resource\n */\n getForResource(resource: string): Migration[] {\n return this.migrations.get(resource) || [];\n }\n\n /**\n * Get all migrations\n */\n getAll(): Migration[] {\n const all: Migration[] = [];\n for (const migrations of this.migrations.values()) {\n all.push(...migrations);\n }\n return all.sort((a, b) => a.version - b.version);\n }\n\n /**\n * Get migration by resource and version\n */\n get(resource: string, version: number): Migration | undefined {\n const migrations = this.migrations.get(resource) || [];\n return migrations.find((m) => m.version === version);\n }\n\n /**\n * Clear all registrations\n */\n clear(): void {\n this.migrations.clear();\n }\n}\n\n/**\n * Global migration registry instance\n */\nexport const migrationRegistry = new MigrationRegistry();\n\n/**\n * Common migration helpers\n */\nexport const migrationHelpers = {\n /**\n * Rename a field across all documents\n */\n renameField: (collection: string, oldName: string, newName: string) =>\n defineMigration({\n version: 0,\n resource: collection,\n description: `Rename ${oldName} to ${newName}`,\n up: async (db) => {\n await db.collection(collection).updateMany({}, { $rename: { [oldName]: newName } });\n },\n down: async (db) => {\n await db.collection(collection).updateMany({}, { $rename: { [newName]: oldName } });\n },\n }),\n\n /**\n * Add a new field with default value\n */\n addField: (collection: string, fieldName: string, defaultValue: unknown) =>\n defineMigration({\n version: 0,\n resource: collection,\n description: `Add ${fieldName} field`,\n up: async (db) => {\n await db\n .collection(collection)\n .updateMany({ [fieldName]: { $exists: false } }, { $set: { [fieldName]: defaultValue } });\n },\n down: async (db) => {\n await db.collection(collection).updateMany({}, { $unset: { [fieldName]: '' } });\n },\n }),\n\n /**\n * Remove a field\n */\n removeField: (collection: string, fieldName: string) =>\n defineMigration({\n version: 0,\n resource: collection,\n description: `Remove ${fieldName} field`,\n up: async (db) => {\n await db.collection(collection).updateMany({}, { $unset: { [fieldName]: '' } });\n },\n down: async (db) => {\n // Cannot restore data - this is destructive\n console.warn(`Cannot restore ${fieldName} field - data was deleted`);\n },\n }),\n\n /**\n * Create an index\n */\n createIndex: (collection: string, fields: Record<string, 1 | -1>, options?: Record<string, unknown>) =>\n defineMigration({\n version: 0,\n resource: collection,\n description: `Create index on ${Object.keys(fields).join(', ')}`,\n up: async (db) => {\n await db.collection(collection).createIndex(fields, options);\n },\n down: async (db) => {\n const indexName = typeof options?.name === 'string' ? options.name : Object.keys(fields).join('_');\n await db.collection(collection).dropIndex(indexName);\n },\n }),\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
//#region src/audit/stores/mongodb.ts
|
|
2
|
+
var MongoAuditStore = class {
|
|
3
|
+
name = "mongodb";
|
|
4
|
+
collection;
|
|
5
|
+
initialized = false;
|
|
6
|
+
ttlDays;
|
|
7
|
+
options;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
const collectionName = options.collection ?? "audit_logs";
|
|
11
|
+
this.collection = options.connection.collection(collectionName);
|
|
12
|
+
this.ttlDays = options.ttlDays ?? 90;
|
|
13
|
+
}
|
|
14
|
+
async ensureIndexes() {
|
|
15
|
+
if (this.initialized) return;
|
|
16
|
+
try {
|
|
17
|
+
await this.collection.createIndex({
|
|
18
|
+
resource: 1,
|
|
19
|
+
documentId: 1,
|
|
20
|
+
timestamp: -1
|
|
21
|
+
});
|
|
22
|
+
await this.collection.createIndex({
|
|
23
|
+
userId: 1,
|
|
24
|
+
timestamp: -1
|
|
25
|
+
});
|
|
26
|
+
await this.collection.createIndex({
|
|
27
|
+
organizationId: 1,
|
|
28
|
+
timestamp: -1
|
|
29
|
+
});
|
|
30
|
+
if (this.ttlDays > 0) await this.collection.createIndex({ timestamp: 1 }, { expireAfterSeconds: this.ttlDays * 24 * 60 * 60 });
|
|
31
|
+
this.initialized = true;
|
|
32
|
+
} catch {
|
|
33
|
+
this.initialized = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async log(entry) {
|
|
37
|
+
await this.ensureIndexes();
|
|
38
|
+
await this.collection.insertOne({
|
|
39
|
+
_id: entry.id,
|
|
40
|
+
resource: entry.resource,
|
|
41
|
+
documentId: entry.documentId,
|
|
42
|
+
action: entry.action,
|
|
43
|
+
userId: entry.userId,
|
|
44
|
+
organizationId: entry.organizationId,
|
|
45
|
+
before: entry.before,
|
|
46
|
+
after: entry.after,
|
|
47
|
+
changes: entry.changes,
|
|
48
|
+
requestId: entry.requestId,
|
|
49
|
+
ipAddress: entry.ipAddress,
|
|
50
|
+
userAgent: entry.userAgent,
|
|
51
|
+
metadata: entry.metadata,
|
|
52
|
+
timestamp: entry.timestamp
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async query(options = {}) {
|
|
56
|
+
await this.ensureIndexes();
|
|
57
|
+
const query = {};
|
|
58
|
+
if (options.resource) query.resource = options.resource;
|
|
59
|
+
if (options.documentId) query.documentId = options.documentId;
|
|
60
|
+
if (options.userId) query.userId = options.userId;
|
|
61
|
+
if (options.organizationId) query.organizationId = options.organizationId;
|
|
62
|
+
if (options.action) {
|
|
63
|
+
const actions = Array.isArray(options.action) ? options.action : [options.action];
|
|
64
|
+
query.action = actions.length === 1 ? actions[0] : { $in: actions };
|
|
65
|
+
}
|
|
66
|
+
if (options.from || options.to) {
|
|
67
|
+
query.timestamp = {};
|
|
68
|
+
if (options.from) query.timestamp.$gte = options.from;
|
|
69
|
+
if (options.to) query.timestamp.$lte = options.to;
|
|
70
|
+
}
|
|
71
|
+
const offset = options.offset ?? 0;
|
|
72
|
+
const limit = options.limit ?? 100;
|
|
73
|
+
return (await this.collection.find(query).sort({ timestamp: -1 }).skip(offset).limit(limit).toArray()).map((doc) => ({
|
|
74
|
+
id: String(doc._id),
|
|
75
|
+
resource: doc.resource,
|
|
76
|
+
documentId: doc.documentId,
|
|
77
|
+
action: doc.action,
|
|
78
|
+
userId: doc.userId,
|
|
79
|
+
organizationId: doc.organizationId,
|
|
80
|
+
before: doc.before,
|
|
81
|
+
after: doc.after,
|
|
82
|
+
changes: doc.changes,
|
|
83
|
+
requestId: doc.requestId,
|
|
84
|
+
ipAddress: doc.ipAddress,
|
|
85
|
+
userAgent: doc.userAgent,
|
|
86
|
+
metadata: doc.metadata,
|
|
87
|
+
timestamp: doc.timestamp
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { MongoAuditStore as t };
|
|
94
|
+
//# sourceMappingURL=mongodb-BfJVlUJH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongodb-BfJVlUJH.mjs","names":[],"sources":["../src/audit/stores/mongodb.ts"],"sourcesContent":["/**\n * MongoDB Audit Store\n *\n * Persists audit logs to MongoDB collection with TTL support.\n * Suitable for production use.\n */\n\nimport type { AuditEntry, AuditQueryOptions, AuditStore } from './interface.js';\n\nexport interface MongoAuditStoreOptions {\n /** MongoDB connection or mongoose instance */\n connection: MongoConnection;\n /** Collection name (default: 'audit_logs') */\n collection?: string;\n /** TTL in days (default: 90, 0 = no expiry) */\n ttlDays?: number;\n}\n\n// Minimal MongoDB types to avoid mongoose dependency\nexport interface MongoConnection {\n collection: (name: string) => MongoCollection;\n}\n\ninterface MongoCollection {\n insertOne: (doc: Record<string, unknown>) => Promise<unknown>;\n find: (query: Record<string, unknown>) => MongoCursor;\n createIndex: (spec: Record<string, unknown>, options?: Record<string, unknown>) => Promise<unknown>;\n}\n\ninterface MongoCursor {\n sort: (spec: Record<string, unknown>) => MongoCursor;\n skip: (n: number) => MongoCursor;\n limit: (n: number) => MongoCursor;\n toArray: () => Promise<Record<string, unknown>[]>;\n}\n\nexport class MongoAuditStore implements AuditStore {\n readonly name = 'mongodb';\n private collection: MongoCollection;\n private initialized = false;\n private ttlDays: number;\n\n private options: MongoAuditStoreOptions;\n\n constructor(options: MongoAuditStoreOptions) {\n this.options = options;\n const collectionName = options.collection ?? 'audit_logs';\n this.collection = options.connection.collection(collectionName);\n this.ttlDays = options.ttlDays ?? 90;\n }\n\n private async ensureIndexes(): Promise<void> {\n if (this.initialized) return;\n\n try {\n // Compound index for common queries\n await this.collection.createIndex({\n resource: 1,\n documentId: 1,\n timestamp: -1,\n });\n\n // Index for user queries\n await this.collection.createIndex({ userId: 1, timestamp: -1 });\n\n // Index for org queries\n await this.collection.createIndex({ organizationId: 1, timestamp: -1 });\n\n // TTL index for automatic cleanup\n if (this.ttlDays > 0) {\n await this.collection.createIndex(\n { timestamp: 1 },\n { expireAfterSeconds: this.ttlDays * 24 * 60 * 60 }\n );\n }\n\n this.initialized = true;\n } catch {\n // Indexes may already exist, ignore errors\n this.initialized = true;\n }\n }\n\n async log(entry: AuditEntry): Promise<void> {\n await this.ensureIndexes();\n\n await this.collection.insertOne({\n _id: entry.id,\n resource: entry.resource,\n documentId: entry.documentId,\n action: entry.action,\n userId: entry.userId,\n organizationId: entry.organizationId,\n before: entry.before,\n after: entry.after,\n changes: entry.changes,\n requestId: entry.requestId,\n ipAddress: entry.ipAddress,\n userAgent: entry.userAgent,\n metadata: entry.metadata,\n timestamp: entry.timestamp,\n });\n }\n\n async query(options: AuditQueryOptions = {}): Promise<AuditEntry[]> {\n await this.ensureIndexes();\n\n const query: Record<string, unknown> = {};\n\n if (options.resource) {\n query.resource = options.resource;\n }\n\n if (options.documentId) {\n query.documentId = options.documentId;\n }\n\n if (options.userId) {\n query.userId = options.userId;\n }\n\n if (options.organizationId) {\n query.organizationId = options.organizationId;\n }\n\n if (options.action) {\n const actions = Array.isArray(options.action) ? options.action : [options.action];\n query.action = actions.length === 1 ? actions[0] : { $in: actions };\n }\n\n if (options.from || options.to) {\n query.timestamp = {};\n if (options.from) {\n (query.timestamp as Record<string, unknown>).$gte = options.from;\n }\n if (options.to) {\n (query.timestamp as Record<string, unknown>).$lte = options.to;\n }\n }\n\n const offset = options.offset ?? 0;\n const limit = options.limit ?? 100;\n\n const docs = await this.collection\n .find(query)\n .sort({ timestamp: -1 })\n .skip(offset)\n .limit(limit)\n .toArray();\n\n return docs.map((doc) => ({\n id: String(doc._id),\n resource: doc.resource as string,\n documentId: doc.documentId as string,\n action: doc.action as AuditEntry['action'],\n userId: doc.userId as string | undefined,\n organizationId: doc.organizationId as string | undefined,\n before: doc.before as Record<string, unknown> | undefined,\n after: doc.after as Record<string, unknown> | undefined,\n changes: doc.changes as string[] | undefined,\n requestId: doc.requestId as string | undefined,\n ipAddress: doc.ipAddress as string | undefined,\n userAgent: doc.userAgent as string | undefined,\n metadata: doc.metadata as Record<string, unknown> | undefined,\n timestamp: doc.timestamp as Date,\n }));\n }\n}\n\nexport default MongoAuditStore;\n"],"mappings":";AAoCA,IAAa,kBAAb,MAAmD;CACjD,AAAS,OAAO;CAChB,AAAQ;CACR,AAAQ,cAAc;CACtB,AAAQ;CAER,AAAQ;CAER,YAAY,SAAiC;AAC3C,OAAK,UAAU;EACf,MAAM,iBAAiB,QAAQ,cAAc;AAC7C,OAAK,aAAa,QAAQ,WAAW,WAAW,eAAe;AAC/D,OAAK,UAAU,QAAQ,WAAW;;CAGpC,MAAc,gBAA+B;AAC3C,MAAI,KAAK,YAAa;AAEtB,MAAI;AAEF,SAAM,KAAK,WAAW,YAAY;IAChC,UAAU;IACV,YAAY;IACZ,WAAW;IACZ,CAAC;AAGF,SAAM,KAAK,WAAW,YAAY;IAAE,QAAQ;IAAG,WAAW;IAAI,CAAC;AAG/D,SAAM,KAAK,WAAW,YAAY;IAAE,gBAAgB;IAAG,WAAW;IAAI,CAAC;AAGvE,OAAI,KAAK,UAAU,EACjB,OAAM,KAAK,WAAW,YACpB,EAAE,WAAW,GAAG,EAChB,EAAE,oBAAoB,KAAK,UAAU,KAAK,KAAK,IAAI,CACpD;AAGH,QAAK,cAAc;UACb;AAEN,QAAK,cAAc;;;CAIvB,MAAM,IAAI,OAAkC;AAC1C,QAAM,KAAK,eAAe;AAE1B,QAAM,KAAK,WAAW,UAAU;GAC9B,KAAK,MAAM;GACX,UAAU,MAAM;GAChB,YAAY,MAAM;GAClB,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,gBAAgB,MAAM;GACtB,QAAQ,MAAM;GACd,OAAO,MAAM;GACb,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,WAAW,MAAM;GACjB,WAAW,MAAM;GACjB,UAAU,MAAM;GAChB,WAAW,MAAM;GAClB,CAAC;;CAGJ,MAAM,MAAM,UAA6B,EAAE,EAAyB;AAClE,QAAM,KAAK,eAAe;EAE1B,MAAM,QAAiC,EAAE;AAEzC,MAAI,QAAQ,SACV,OAAM,WAAW,QAAQ;AAG3B,MAAI,QAAQ,WACV,OAAM,aAAa,QAAQ;AAG7B,MAAI,QAAQ,OACV,OAAM,SAAS,QAAQ;AAGzB,MAAI,QAAQ,eACV,OAAM,iBAAiB,QAAQ;AAGjC,MAAI,QAAQ,QAAQ;GAClB,MAAM,UAAU,MAAM,QAAQ,QAAQ,OAAO,GAAG,QAAQ,SAAS,CAAC,QAAQ,OAAO;AACjF,SAAM,SAAS,QAAQ,WAAW,IAAI,QAAQ,KAAK,EAAE,KAAK,SAAS;;AAGrE,MAAI,QAAQ,QAAQ,QAAQ,IAAI;AAC9B,SAAM,YAAY,EAAE;AACpB,OAAI,QAAQ,KACV,CAAC,MAAM,UAAsC,OAAO,QAAQ;AAE9D,OAAI,QAAQ,GACV,CAAC,MAAM,UAAsC,OAAO,QAAQ;;EAIhE,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,QAAQ,QAAQ,SAAS;AAS/B,UAPa,MAAM,KAAK,WACrB,KAAK,MAAM,CACX,KAAK,EAAE,WAAW,IAAI,CAAC,CACvB,KAAK,OAAO,CACZ,MAAM,MAAM,CACZ,SAAS,EAEA,KAAK,SAAS;GACxB,IAAI,OAAO,IAAI,IAAI;GACnB,UAAU,IAAI;GACd,YAAY,IAAI;GAChB,QAAQ,IAAI;GACZ,QAAQ,IAAI;GACZ,gBAAgB,IAAI;GACpB,QAAQ,IAAI;GACZ,OAAO,IAAI;GACX,SAAS,IAAI;GACb,WAAW,IAAI;GACf,WAAW,IAAI;GACf,WAAW,IAAI;GACf,UAAU,IAAI;GACd,WAAW,IAAI;GAChB,EAAE"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { i as UserBase } from "./types-aYB4V7uN.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/audit/stores/interface.d.ts
|
|
4
|
+
type AuditAction = 'create' | 'update' | 'delete' | 'restore' | 'custom';
|
|
5
|
+
interface AuditEntry {
|
|
6
|
+
/** Unique audit log ID */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Resource name (e.g., 'product', 'user') */
|
|
9
|
+
resource: string;
|
|
10
|
+
/** Document/entity ID */
|
|
11
|
+
documentId: string;
|
|
12
|
+
/** Action performed */
|
|
13
|
+
action: AuditAction;
|
|
14
|
+
/** User who performed the action */
|
|
15
|
+
userId?: string;
|
|
16
|
+
/** Organization context */
|
|
17
|
+
organizationId?: string;
|
|
18
|
+
/** Previous state (for updates) */
|
|
19
|
+
before?: Record<string, unknown>;
|
|
20
|
+
/** New state (for creates/updates) */
|
|
21
|
+
after?: Record<string, unknown>;
|
|
22
|
+
/** Changed fields (for updates) */
|
|
23
|
+
changes?: string[];
|
|
24
|
+
/** Request ID for tracing */
|
|
25
|
+
requestId?: string;
|
|
26
|
+
/** IP address */
|
|
27
|
+
ipAddress?: string;
|
|
28
|
+
/** User agent */
|
|
29
|
+
userAgent?: string;
|
|
30
|
+
/** Custom metadata */
|
|
31
|
+
metadata?: Record<string, unknown>;
|
|
32
|
+
/** When the action occurred */
|
|
33
|
+
timestamp: Date;
|
|
34
|
+
}
|
|
35
|
+
interface AuditContext {
|
|
36
|
+
user?: UserBase;
|
|
37
|
+
organizationId?: string;
|
|
38
|
+
requestId?: string;
|
|
39
|
+
ipAddress?: string;
|
|
40
|
+
userAgent?: string;
|
|
41
|
+
/** HTTP method + route pattern (e.g., 'PATCH /api/products/:id') */
|
|
42
|
+
endpoint?: string;
|
|
43
|
+
/** Request duration in milliseconds */
|
|
44
|
+
duration?: number;
|
|
45
|
+
}
|
|
46
|
+
interface AuditStoreOptions {
|
|
47
|
+
/** Store name for logging */
|
|
48
|
+
name: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Abstract audit store interface
|
|
52
|
+
*/
|
|
53
|
+
interface AuditStore {
|
|
54
|
+
/** Store name */
|
|
55
|
+
readonly name: string;
|
|
56
|
+
/** Log an audit entry */
|
|
57
|
+
log(entry: AuditEntry): Promise<void>;
|
|
58
|
+
/** Query audit logs (optional - not all stores support querying) */
|
|
59
|
+
query?(options: AuditQueryOptions): Promise<AuditEntry[]>;
|
|
60
|
+
/** Close/cleanup (optional) */
|
|
61
|
+
close?(): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
interface AuditQueryOptions {
|
|
64
|
+
resource?: string;
|
|
65
|
+
documentId?: string;
|
|
66
|
+
userId?: string;
|
|
67
|
+
organizationId?: string;
|
|
68
|
+
action?: AuditAction | AuditAction[];
|
|
69
|
+
from?: Date;
|
|
70
|
+
to?: Date;
|
|
71
|
+
limit?: number;
|
|
72
|
+
offset?: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create audit entry from context
|
|
76
|
+
*/
|
|
77
|
+
declare function createAuditEntry(resource: string, documentId: string, action: AuditAction, context: AuditContext, data?: {
|
|
78
|
+
before?: Record<string, unknown>;
|
|
79
|
+
after?: Record<string, unknown>;
|
|
80
|
+
metadata?: Record<string, unknown>;
|
|
81
|
+
}): AuditEntry;
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/audit/stores/mongodb.d.ts
|
|
84
|
+
interface MongoAuditStoreOptions {
|
|
85
|
+
/** MongoDB connection or mongoose instance */
|
|
86
|
+
connection: MongoConnection;
|
|
87
|
+
/** Collection name (default: 'audit_logs') */
|
|
88
|
+
collection?: string;
|
|
89
|
+
/** TTL in days (default: 90, 0 = no expiry) */
|
|
90
|
+
ttlDays?: number;
|
|
91
|
+
}
|
|
92
|
+
interface MongoConnection {
|
|
93
|
+
collection: (name: string) => MongoCollection;
|
|
94
|
+
}
|
|
95
|
+
interface MongoCollection {
|
|
96
|
+
insertOne: (doc: Record<string, unknown>) => Promise<unknown>;
|
|
97
|
+
find: (query: Record<string, unknown>) => MongoCursor;
|
|
98
|
+
createIndex: (spec: Record<string, unknown>, options?: Record<string, unknown>) => Promise<unknown>;
|
|
99
|
+
}
|
|
100
|
+
interface MongoCursor {
|
|
101
|
+
sort: (spec: Record<string, unknown>) => MongoCursor;
|
|
102
|
+
skip: (n: number) => MongoCursor;
|
|
103
|
+
limit: (n: number) => MongoCursor;
|
|
104
|
+
toArray: () => Promise<Record<string, unknown>[]>;
|
|
105
|
+
}
|
|
106
|
+
declare class MongoAuditStore implements AuditStore {
|
|
107
|
+
readonly name = "mongodb";
|
|
108
|
+
private collection;
|
|
109
|
+
private initialized;
|
|
110
|
+
private ttlDays;
|
|
111
|
+
private options;
|
|
112
|
+
constructor(options: MongoAuditStoreOptions);
|
|
113
|
+
private ensureIndexes;
|
|
114
|
+
log(entry: AuditEntry): Promise<void>;
|
|
115
|
+
query(options?: AuditQueryOptions): Promise<AuditEntry[]>;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { AuditContext as a, AuditStore as c, AuditAction as i, AuditStoreOptions as l, MongoAuditStoreOptions as n, AuditEntry as o, MongoConnection as r, AuditQueryOptions as s, MongoAuditStore as t, createAuditEntry as u };
|
|
119
|
+
//# sourceMappingURL=mongodb-CGzRbfAK.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongodb-CGzRbfAK.d.mts","names":[],"sources":["../src/audit/stores/interface.ts","../src/audit/stores/mongodb.ts"],"mappings":";;;KASY,WAAA;AAAA,UAEK,UAAA;EAAU;EAEzB,EAAA;EAMQ;EAJR,QAAA;EAYQ;EAVR,UAAA;EAsBW;EApBX,MAAA,EAAQ,WAAA;EAoBO;EAlBf,MAAA;EANA;EAQA,cAAA;EAJA;EAMA,MAAA,GAAS,MAAA;EAJT;EAMA,KAAA,GAAQ,MAAA;EAFR;EAIA,OAAA;EAFA;EAIA,SAAA;EAFA;EAIA,SAAA;EAAA;EAEA,SAAA;EAEA;EAAA,QAAA,GAAW,MAAA;EAEX;EAAA,SAAA,EAAW,IAAA;AAAA;AAAA,UAGI,YAAA;EACf,IAAA,GAAO,QAAA;EACP,cAAA;EACA,SAAA;EACA,SAAA;EACA,SAAA;EAJO;EAMP,QAAA;EAJA;EAMA,QAAA;AAAA;AAAA,UAGe,iBAAA;EAHf;EAKA,IAAA;AAAA;AAFF;;;AAAA,UAQiB,UAAA;EANX;EAAA,SAQK,IAAA;EAFgB;EAKzB,GAAA,CAAI,KAAA,EAAO,UAAA,GAAa,OAAA;EAAb;EAGX,KAAA,EAAO,OAAA,EAAS,iBAAA,GAAoB,OAAA,CAAQ,UAAA;EAA5B;EAGhB,KAAA,KAAU,OAAA;AAAA;AAAA,UAGK,iBAAA;EACf,QAAA;EACA,UAAA;EACA,MAAA;EACA,cAAA;EACA,MAAA,GAAS,WAAA,GAAc,WAAA;EACvB,IAAA,GAAO,IAAA;EACP,EAAA,GAAK,IAAA;EACL,KAAA;EACA,MAAA;AAAA;;;;iBAMc,gBAAA,CACd,QAAA,UACA,UAAA,UACA,MAAA,EAAQ,WAAA,EACR,OAAA,EAAS,YAAA,EACT,IAAA;EACE,MAAA,GAAS,MAAA;EACT,KAAA,GAAQ,MAAA;EACR,QAAA,GAAW,MAAA;AAAA,IAEZ,UAAA;;;UC5Fc,sBAAA;EDEA;ECAf,UAAA,EAAY,eAAA;;EAEZ,UAAA;EDYS;ECVT,OAAA;AAAA;AAAA,UAIe,eAAA;EACf,UAAA,GAAa,IAAA,aAAiB,eAAA;AAAA;AAAA,UAGtB,eAAA;EACR,SAAA,GAAY,GAAA,EAAK,MAAA,sBAA4B,OAAA;EAC7C,IAAA,GAAO,KAAA,EAAO,MAAA,sBAA4B,WAAA;EAC1C,WAAA,GAAc,IAAA,EAAM,MAAA,mBAAyB,OAAA,GAAU,MAAA,sBAA4B,OAAA;AAAA;AAAA,UAG3E,WAAA;EACR,IAAA,GAAO,IAAA,EAAM,MAAA,sBAA4B,WAAA;EACzC,IAAA,GAAO,CAAA,aAAc,WAAA;EACrB,KAAA,GAAQ,CAAA,aAAc,WAAA;EACtB,OAAA,QAAe,OAAA,CAAQ,MAAA;AAAA;AAAA,cAGZ,eAAA,YAA2B,UAAA;EAAA,SAC7B,IAAA;EAAA,QACD,UAAA;EAAA,QACA,WAAA;EAAA,QACA,OAAA;EAAA,QAEA,OAAA;cAEI,OAAA,EAAS,sBAAA;EAAA,QAOP,aAAA;EAgCR,GAAA,CAAI,KAAA,EAAO,UAAA,GAAa,OAAA;EAqBxB,KAAA,CAAM,OAAA,GAAS,iBAAA,GAAyB,OAAA,CAAQ,UAAA;AAAA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-B01JvPVc.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/idempotency/stores/mongodb.d.ts
|
|
4
|
+
interface MongoConnection {
|
|
5
|
+
db: {
|
|
6
|
+
collection(name: string): MongoCollection;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
interface MongoCollection {
|
|
10
|
+
findOne(filter: object): Promise<IdempotencyDocument | null>;
|
|
11
|
+
insertOne(doc: object): Promise<{
|
|
12
|
+
acknowledged: boolean;
|
|
13
|
+
}>;
|
|
14
|
+
updateOne(filter: object, update: object, options?: object): Promise<{
|
|
15
|
+
acknowledged: boolean;
|
|
16
|
+
matchedCount: number;
|
|
17
|
+
modifiedCount: number;
|
|
18
|
+
}>;
|
|
19
|
+
deleteOne(filter: object): Promise<{
|
|
20
|
+
deletedCount: number;
|
|
21
|
+
}>;
|
|
22
|
+
deleteMany(filter: object): Promise<{
|
|
23
|
+
deletedCount: number;
|
|
24
|
+
}>;
|
|
25
|
+
createIndex(spec: object, options?: object): Promise<string>;
|
|
26
|
+
}
|
|
27
|
+
interface IdempotencyDocument {
|
|
28
|
+
_id: string;
|
|
29
|
+
result?: {
|
|
30
|
+
statusCode: number;
|
|
31
|
+
headers: Record<string, string>;
|
|
32
|
+
body: unknown;
|
|
33
|
+
};
|
|
34
|
+
lock?: {
|
|
35
|
+
requestId: string;
|
|
36
|
+
expiresAt: Date;
|
|
37
|
+
};
|
|
38
|
+
createdAt: Date;
|
|
39
|
+
expiresAt: Date;
|
|
40
|
+
}
|
|
41
|
+
interface MongoIdempotencyStoreOptions {
|
|
42
|
+
/** Mongoose connection or MongoDB connection object */
|
|
43
|
+
connection: MongoConnection;
|
|
44
|
+
/** Collection name (default: 'arc_idempotency') */
|
|
45
|
+
collection?: string;
|
|
46
|
+
/** Create TTL index on startup (default: true) */
|
|
47
|
+
createIndex?: boolean;
|
|
48
|
+
/** Default TTL in ms (default: 86400000 = 24 hours) */
|
|
49
|
+
ttlMs?: number;
|
|
50
|
+
}
|
|
51
|
+
declare class MongoIdempotencyStore implements IdempotencyStore {
|
|
52
|
+
readonly name = "mongodb";
|
|
53
|
+
private connection;
|
|
54
|
+
private collectionName;
|
|
55
|
+
private ttlMs;
|
|
56
|
+
private indexCreated;
|
|
57
|
+
constructor(options: MongoIdempotencyStoreOptions);
|
|
58
|
+
private get collection();
|
|
59
|
+
private ensureIndex;
|
|
60
|
+
get(key: string): Promise<IdempotencyResult | undefined>;
|
|
61
|
+
set(key: string, result: Omit<IdempotencyResult, 'key'>): Promise<void>;
|
|
62
|
+
tryLock(key: string, requestId: string, ttlMs: number): Promise<boolean>;
|
|
63
|
+
unlock(key: string, requestId: string): Promise<void>;
|
|
64
|
+
isLocked(key: string): Promise<boolean>;
|
|
65
|
+
delete(key: string): Promise<void>;
|
|
66
|
+
deleteByPrefix(prefix: string): Promise<number>;
|
|
67
|
+
findByPrefix(prefix: string): Promise<IdempotencyResult | undefined>;
|
|
68
|
+
close(): Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { MongoIdempotencyStoreOptions as n, MongoIdempotencyStore as t };
|
|
72
|
+
//# sourceMappingURL=mongodb-JN-9JA7K.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongodb-JN-9JA7K.d.mts","names":[],"sources":["../src/idempotency/stores/mongodb.ts"],"mappings":";;;UAoBiB,eAAA;EACf,EAAA;IACE,UAAA,CAAW,IAAA,WAAe,eAAA;EAAA;AAAA;AAAA,UAIpB,eAAA;EACR,OAAA,CAAQ,MAAA,WAAiB,OAAA,CAAQ,mBAAA;EACjC,SAAA,CAAU,GAAA,WAAc,OAAA;IAAU,YAAA;EAAA;EAClC,SAAA,CAAU,MAAA,UAAgB,MAAA,UAAgB,OAAA,YAAmB,OAAA;IAAU,YAAA;IAAuB,YAAA;IAAsB,aAAA;EAAA;EACpH,SAAA,CAAU,MAAA,WAAiB,OAAA;IAAU,YAAA;EAAA;EACrC,UAAA,CAAW,MAAA,WAAiB,OAAA;IAAU,YAAA;EAAA;EACtC,WAAA,CAAY,IAAA,UAAc,OAAA,YAAmB,OAAA;AAAA;AAAA,UAGrC,mBAAA;EACR,GAAA;EACA,MAAA;IACE,UAAA;IACA,OAAA,EAAS,MAAA;IACT,IAAA;EAAA;EAEF,IAAA;IACE,SAAA;IACA,SAAA,EAAW,IAAA;EAAA;EAEb,SAAA,EAAW,IAAA;EACX,SAAA,EAAW,IAAA;AAAA;AAAA,UAGI,4BAAA;EAfY;EAiB3B,UAAA,EAAY,eAAA;EAbD;EAeX,UAAA;EARW;EAUX,WAAA;EATe;EAWf,KAAA;AAAA;AAAA,cAGW,qBAAA,YAAiC,gBAAA;EAAA,SACnC,IAAA;EAAA,QACD,UAAA;EAAA,QACA,cAAA;EAAA,QACA,KAAA;EAAA,QACA,YAAA;cAEI,OAAA,EAAS,4BAAA;EAAA,YAYT,UAAA,CAAA;EAAA,QAIE,WAAA;EAeR,GAAA,CAAI,GAAA,WAAc,OAAA,CAAQ,iBAAA;EAmB1B,GAAA,CAAI,GAAA,UAAa,MAAA,EAAQ,IAAA,CAAK,iBAAA,WAA4B,OAAA;EAmB1D,OAAA,CAAQ,GAAA,UAAa,SAAA,UAAmB,KAAA,WAAgB,OAAA;EAwCxD,MAAA,CAAO,GAAA,UAAa,SAAA,WAAoB,OAAA;EAQxC,QAAA,CAAS,GAAA,WAAc,OAAA;EAMvB,MAAA,CAAO,GAAA,WAAc,OAAA;EAIrB,cAAA,CAAe,MAAA,WAAiB,OAAA;EAOhC,YAAA,CAAa,MAAA,WAAiB,OAAA,CAAQ,iBAAA;EAoBtC,KAAA,CAAA,GAAS,OAAA;AAAA"}
|