@softure-ai/db 0.1.5 → 0.1.6

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +215 -21
  3. package/dist/cli/run.d.ts +8 -1
  4. package/dist/cli/run.d.ts.map +1 -1
  5. package/dist/cli/run.js +71 -21
  6. package/dist/cli/run.js.map +1 -1
  7. package/dist/client.d.ts +39 -8
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +64 -8
  10. package/dist/client.js.map +1 -1
  11. package/dist/configured.d.ts +31 -0
  12. package/dist/configured.d.ts.map +1 -0
  13. package/dist/configured.js +74 -0
  14. package/dist/configured.js.map +1 -0
  15. package/dist/index.d.ts +3 -2
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +3 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/migrations/adopt.d.ts +8 -1
  20. package/dist/migrations/adopt.d.ts.map +1 -1
  21. package/dist/migrations/adopt.js +53 -87
  22. package/dist/migrations/adopt.js.map +1 -1
  23. package/dist/migrations/apply.d.ts +35 -0
  24. package/dist/migrations/apply.d.ts.map +1 -0
  25. package/dist/migrations/apply.js +115 -0
  26. package/dist/migrations/apply.js.map +1 -0
  27. package/dist/migrations/migrator.d.ts +55 -27
  28. package/dist/migrations/migrator.d.ts.map +1 -1
  29. package/dist/migrations/migrator.js +187 -103
  30. package/dist/migrations/migrator.js.map +1 -1
  31. package/dist/migrations/problems.d.ts +9 -0
  32. package/dist/migrations/problems.d.ts.map +1 -1
  33. package/dist/migrations/problems.js +9 -3
  34. package/dist/migrations/problems.js.map +1 -1
  35. package/dist/migrations/reference.d.ts +23 -0
  36. package/dist/migrations/reference.d.ts.map +1 -0
  37. package/dist/migrations/reference.js +64 -0
  38. package/dist/migrations/reference.js.map +1 -0
  39. package/dist/migrations/session.d.ts +2 -1
  40. package/dist/migrations/session.d.ts.map +1 -1
  41. package/dist/migrations/session.js +19 -2
  42. package/dist/migrations/session.js.map +1 -1
  43. package/dist/migrations/stubs.d.ts +23 -0
  44. package/dist/migrations/stubs.d.ts.map +1 -0
  45. package/dist/migrations/stubs.js +99 -0
  46. package/dist/migrations/stubs.js.map +1 -0
  47. package/dist/testing.d.ts +11 -2
  48. package/dist/testing.d.ts.map +1 -1
  49. package/dist/testing.js +28 -9
  50. package/dist/testing.js.map +1 -1
  51. package/package.json +22 -5
  52. package/src/cli/run.ts +84 -23
  53. package/src/client.ts +88 -16
  54. package/src/configured.ts +109 -0
  55. package/src/index.ts +9 -0
  56. package/src/migrations/adopt.ts +65 -100
  57. package/src/migrations/apply.ts +135 -0
  58. package/src/migrations/migrator.ts +246 -128
  59. package/src/migrations/problems.ts +13 -5
  60. package/src/migrations/reference.ts +78 -0
  61. package/src/migrations/session.ts +28 -2
  62. package/src/migrations/stubs.ts +139 -0
  63. package/src/testing.ts +38 -10
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ Newest first. Each version lists what changed for an app that uses `@softure-ai/db`. When an app has run a version in
4
+ production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
5
+ "Definition of done"). Versions before the first one below are described in their GitHub Releases (`db@x.y.z`).
6
+
7
+ ## 0.1.6
8
+
9
+ - One database handle per process: `getConfiguredDatabase` opens the config's `database.handle` or URL once, and modules, health route and commands share it.
10
+ - App migrations run around module migrations (`before` and `after` hooks).
11
+ - Adoption: app baselines, `--adopt <module>@<version> --through <n>`, dependencies adopted first, and modules whose SQL references app tables (stub tables).
12
+ - **Breaking:** `pg` and `@electric-sql/pglite` are optional peer dependencies, no longer dependencies. An app installs
13
+ the driver its `DATABASE_URL` uses and lists `"@softure-ai/db"` and that driver in `serverExternalPackages`
14
+ ([README §2](README.md#2-installation)); a URL whose driver is missing fails with a message naming the package.
15
+ - A migrate bundle keeps drizzle's driver adapters external (`--external:drizzle-orm/pglite`,
16
+ `--external:drizzle-orm/node-postgres`).
package/README.md CHANGED
@@ -1,10 +1,7 @@
1
1
  # @softure-ai/db
2
2
 
3
- **Status:** wave 0 · implemented in FD-4 (`db-migrator`), 0.1.5, prepared for its first release (the owner's tag, `scripts/release/README.md`).
4
-
5
3
  The database layer every SOFTURE module stands on. Standard:
6
- [docs/02-module-standard.md](../../docs/02-module-standard.md) §4. Sources in FIRE_TRACKER:
7
- `src/db/client.ts`, `src/db/test-db.ts`, `scripts/migrate.ts`, `docker/Dockerfile` (`migrate.cjs`).
4
+ [docs/02-module-standard.md](../../docs/02-module-standard.md) §4.
8
5
 
9
6
  ## 1. What it provides
10
7
 
@@ -18,9 +15,49 @@ Postgres schema (with a ledger, checksums, a lock, a dry run and adoption of exi
18
15
  npm install @softure-ai/db drizzle-orm
19
16
  ```
20
17
 
21
- Node ≥ 22, ESM only. `drizzle-orm` (`^0.45.2`) is a peer dependency, so the app, the modules and
22
- this package share one drizzle. `pg` and `@electric-sql/pglite` come with the package and load
23
- only when used.
18
+ Node ≥ 22, **ESM only**: module packages locate their migrations through `import.meta.url`, which a
19
+ CJS bundle (esbuild `--format=cjs`) leaves empty, so `resolveMigrationsDir` throws naming the bundle
20
+ format; the app script below also uses top-level await. Bundle migrate scripts with `--format=esm`.
21
+ `drizzle-orm` (`^0.45.2`) is a peer dependency, so the app, the modules and
22
+ this package share one drizzle.
23
+
24
+ The drivers are optional peers: install the one the app's URL uses, and only that one goes into the
25
+ app image. Each loads only when a URL needs it.
26
+
27
+ ```bash
28
+ npm install pg # postgres:// and postgresql://
29
+ npm install @electric-sql/pglite # pglite:// (dev without a server)
30
+ npm install -D @electric-sql/pglite # a Postgres app's createTestDatabase, --adopt and baseline
31
+ npm install -D @types/pg # only with skipLibCheck: false
32
+ ```
33
+
34
+ | Needs | `pg` (`^8.11.0`) | `@electric-sql/pglite` (`^0.5.0`) |
35
+ | --- | --- | --- |
36
+ | `postgres://`, `postgresql://` | yes | no |
37
+ | `pglite://` | no | yes |
38
+ | `createTestDatabase` (`@softure-ai/db/testing`) | no | yes (dev) |
39
+ | `softure migrate --adopt`, an app `baseline` (compare against a scratch PGlite) | URL's driver | yes |
40
+
41
+ A URL whose driver is missing fails at the first connection: `createDatabase: postgres:// URLs need
42
+ the "pg" package, which is not installed; …`, with Node's error as `cause`.
43
+
44
+ **Next.js.** List this package and the driver in `serverExternalPackages`:
45
+
46
+ ```ts
47
+ // next.config.ts
48
+ const nextConfig: NextConfig = {
49
+ serverExternalPackages: ["@softure-ai/db", "pg"], // or "@electric-sql/pglite" for pglite://
50
+ };
51
+ ```
52
+
53
+ Bundled, the package's `import()` of each driver and drizzle adapter is resolved at build time, so
54
+ `next build` fails with `Can't resolve '@electric-sql/pglite'` in an app without PGlite (drizzle's
55
+ adapter imports it statically). External, it loads from `node_modules` at run time, and standalone
56
+ output tracing follows the same imports, so `.next/standalone` carries the installed driver and
57
+ drizzle and nothing else (the example app installs `pg` only:
58
+ [`next.config.ts`](../../examples/next-app/next.config.ts)). The config and the shared handles live on `globalThis`, so this copy and the modules bundled next
59
+ to it share them. Hiding the imports from the bundler instead (`turbopackIgnore`) builds, but
60
+ tracing skips the driver and the image fails at the first query.
24
61
 
25
62
  ## 3. Configuration
26
63
 
@@ -42,11 +79,67 @@ await handle.close();
42
79
  ```
43
80
 
44
81
  - `DatabaseHandle` is `{ kind: "postgres", db, pool, close } | { kind: "pglite", db, client, close }`.
45
- - `Database` is the drizzle database of either driver; `Queryable` is a `Database` or an open
46
- transaction, so one helper serves both (`db.transaction(async (tx) => helper(tx))`).
82
+ - `Database<TSchema>` is the drizzle database of either driver; `Queryable<TSchema>` is a `Database`
83
+ or an open transaction, so one helper serves both (`db.transaction(async (tx) => helper(tx))`).
84
+ Without a type argument both accept any schema, so an app database made with
85
+ `drizzle({ client, schema })`, and its transactions, pass to module functions as they are.
47
86
  - An unsupported scheme throws, naming the scheme only; the URL (and its password) is never
48
87
  printed.
49
88
 
89
+ ### One handle per process
90
+
91
+ Modules open their database through the config, never on their own: the app's handle when
92
+ `database.handle` is set, otherwise one process-wide handle per URL (`getSharedDatabase(url)`). An
93
+ app that also has its own client must make sure both are the same handle. A second handle is a second
94
+ pool on Postgres; on `pglite://` it is a second PGlite instance on the same directory, which corrupts
95
+ it without an error (the next open fails with `could not locate a valid checkpoint record`).
96
+
97
+ **Either** hand the app's client to the config. The function is called on first use, never while the
98
+ config is defined (a build does not connect), and must return the app's one handle:
99
+
100
+ ```ts
101
+ // db/client.ts: the app's own client, memoized: `next dev` re-evaluates modules on every change
102
+ import { PGlite } from "@electric-sql/pglite";
103
+ import { createPgliteHandle, createPostgresHandle, type DatabaseHandle } from "@softure-ai/db";
104
+ import pg from "pg";
105
+
106
+ const cache = globalThis as typeof globalThis & { appDatabase?: Promise<DatabaseHandle> };
107
+
108
+ export function getAppDatabase(url: string): Promise<DatabaseHandle> {
109
+ cache.appDatabase ??= url.startsWith("pglite://")
110
+ ? createPgliteHandle(new PGlite(url.slice("pglite://".length)))
111
+ : createPostgresHandle(new pg.Pool({ connectionString: url }).on("error", () => undefined));
112
+ return cache.appDatabase;
113
+ }
114
+
115
+ // softure.config.ts
116
+ const url = process.env.DATABASE_URL ?? "";
117
+ defineSoftureConfig({ database: { url, handle: () => getAppDatabase(url) }, /* … */ });
118
+ ```
119
+
120
+ Every module adapter, the ops health route, `softure migrate` (and the app's migration hooks it
121
+ runs), `softure-blog`, `softure-mail` and ops scripts then use that handle; a command closes it
122
+ when it is done, which writes a `pglite://` directory back.
123
+
124
+ **Or** build the app's typed drizzle instance over the shared handle, so there is nothing to hand
125
+ over:
126
+
127
+ ```ts
128
+ import { getSharedDatabase } from "@softure-ai/db";
129
+ import { drizzle as drizzlePg } from "drizzle-orm/node-postgres";
130
+ import { drizzle as drizzlePglite } from "drizzle-orm/pglite";
131
+ import * as schema from "./schema";
132
+
133
+ export async function getDb() {
134
+ const handle = await getSharedDatabase(config.database.url);
135
+ return handle.kind === "postgres" ? drizzlePg({ client: handle.pool, schema }) : drizzlePglite({ client: handle.client, schema });
136
+ }
137
+ ```
138
+
139
+ `getConfiguredDatabase(config.database)` is what modules call; app code that needs the database
140
+ the modules use can call it too. A migration run on a PGlite handle the app shares keeps the app's
141
+ session settings (`TimeZone`, `search_path`); only what the run changed is put back.
142
+
50
143
  ## 4. Mounting
51
144
 
52
145
  Nothing to mount. Migrations run as a deploy step:
@@ -69,31 +162,117 @@ process.exitCode = await runMigrateCli({ config, argv: process.argv.slice(2) });
69
162
  # build stage: copy each module's SQL next to the bundle, then bundle the runner
70
163
  RUN npx tsx scripts/migrate.ts --export-migrations ./softure-migrations
71
164
  RUN npx esbuild scripts/migrate.ts --bundle --platform=node --format=esm --target=node22 \
72
- --external:pg --external:@electric-sql/pglite --outfile=migrate.mjs
73
- # run stage (needs pg, and @electric-sql/pglite for --adopt)
165
+ --external:pg --external:@electric-sql/pglite \
166
+ --external:drizzle-orm/pglite --external:drizzle-orm/node-postgres --outfile=migrate.mjs
167
+ # run stage (needs the URL's driver, and @electric-sql/pglite for --adopt or an app baseline)
74
168
  COPY --from=builder /app/migrate.mjs ./migrate.mjs
75
169
  COPY --from=builder /app/softure-migrations ./softure-migrations
76
170
  CMD ["node", "migrate.mjs", "--migrations-dir", "./softure-migrations"]
77
171
  ```
78
172
 
173
+ A config that imports `server-only` throws under plain Node: run the export as
174
+ `npx tsx --conditions=react-server scripts/migrate.ts --export-migrations …` and bundle with
175
+ `--alias:server-only=./scripts/empty.mjs` (an empty file). Path aliases (`@/…`) need nothing extra: tsx and
176
+ esbuild both read `paths` from `tsconfig.json`. The [ops container recipe](../../modules/ops/README.md#container-recipe)
177
+ uses the same commands.
178
+
179
+ The drivers and drizzle's two driver adapters stay external: bundled, the adapter of a driver the app
180
+ does not install imports it at the top of `migrate.mjs`, which then fails at start. At run time they
181
+ come from the standalone output, which carries the installed driver and its adapter.
182
+
79
183
  A bundle cannot find package folders (`import.meta.url` points at the bundle), hence
80
- `--export-migrations` at build time and `--migrations-dir` at run time. The ledger's own migration
184
+ `--export-migrations` at build time and `--migrations-dir` at run time. The build stage needs no
185
+ `DATABASE_URL`: the config accepts an empty `database.url` (`DATABASE_URL ?? ""`) and only a command that
186
+ connects refuses it. The ledger's own migration
81
187
  ships as code.
82
188
 
189
+ **The app's own migrations** run in the same step, through hooks. `before` runs ahead of the module
190
+ files (app tables a module references, normally the app's whole history), `after` behind them (app
191
+ migrations that reference a table a module creates). With drizzle, define them once and pass the same
192
+ object to the migrate script and to `createTestDatabase`:
193
+
194
+ ```ts
195
+ // db/app-migrations.ts
196
+ import type { AppMigrations, DatabaseHandle } from "@softure-ai/db";
197
+
198
+ async function runDrizzle(handle: DatabaseHandle, migrationsFolder: string): Promise<void> {
199
+ if (handle.kind === "postgres") {
200
+ const { migrate } = await import("drizzle-orm/node-postgres/migrator");
201
+ await migrate(handle.db, { migrationsFolder });
202
+ } else {
203
+ const { migrate } = await import("drizzle-orm/pglite/migrator");
204
+ await migrate(handle.db, { migrationsFolder });
205
+ }
206
+ }
207
+
208
+ export const appMigrations: AppMigrations = {
209
+ before: (handle) => runDrizzle(handle, "./drizzle"),
210
+ // only when an app migration needs a module table: a second drizzle folder
211
+ // after: (handle) => runDrizzle(handle, "./drizzle-after"),
212
+ };
213
+
214
+ // scripts/migrate.ts
215
+ process.exitCode = await runMigrateCli({ config, argv: process.argv.slice(2), app: appMigrations });
216
+ ```
217
+
218
+ - Order of a run: the ledger, `before`, the module files in dependency order, `after`. Everything
219
+ runs under the migration lock, after every module file passed its checks; nothing runs when a check
220
+ fails. The hooks run on every run, so they must skip what they already applied (drizzle does).
221
+ - A hook that throws is reported as `db.app_migration_failed` with the error and its causes (drizzle
222
+ puts the Postgres message in `cause`). A failing `before` stops the run before any module file; a
223
+ failing `after` leaves the module files applied.
224
+ - `--plan` runs no hook (it says so); `--adopt` without `--plan` runs `before` first, so the app
225
+ migration that moves a table into the module's schema and the adoption are one command.
226
+
227
+ **A baseline: fresh databases after an adoption.** The app keeps its old migrations, so every fresh
228
+ database (the unit-test template, an integration stack, a reset dev database) recreates the tables it
229
+ moved into a module's schema before the module files run. `baseline` names, per module, the last module
230
+ file the app's own history creates; `migrate` then adopts or migrates by itself, on every database:
231
+
232
+ ```ts
233
+ export const appMigrations: AppMigrations = {
234
+ before: (handle) => runDrizzle(handle, "./drizzle"),
235
+ // the app's history creates auth's 0001 (users, sessions); 0002.. are new to it
236
+ baseline: { auth: 1 },
237
+ };
238
+ ```
239
+
240
+ - For a listed module the ledger has never seen, after `before` and after the modules it depends on:
241
+ an empty schema is migrated normally; otherwise the schema is compared with what files 1..n create
242
+ (as `--adopt` does), files 1..n are recorded as `adopted` and the later files are applied. A
243
+ difference stops the run (`db.schema_mismatch`, every difference printed); nothing of that module is
244
+ recorded and `after` does not run.
245
+ - Once the module is in the ledger the entry has no effect, so the same command serves every deploy.
246
+ Keep the number when the module ships new files: it describes the app's history, which no longer
247
+ changes.
248
+ - Only a prefix 1..n can be adopted (the ledger refuses a file numbered below an applied one): when the
249
+ app's tables already carry a later file's change, align them in the app's own migration or raise n.
250
+ - A module that is not enabled, has no schema, or an n outside 1..files refuses the run before anything
251
+ runs. `--plan` marks the files a baseline may adopt (`adopted if its schema already holds objects`).
252
+ - The comparison builds the reference on a scratch PGlite, only when a module is actually adopted,
253
+ with stubs of the app tables `before` created (section 5, adoption).
254
+ - Under node-postgres a hook queries through the pool while the migrator holds one connection, so the
255
+ pool needs at least two (`createDatabase`'s default is 10).
256
+ - The `softure` bin reads only the config; an app with its own migrations uses the script above.
257
+ - In a bundle, the drizzle folder must be copied next to the bundle, as the module files are.
258
+
83
259
  **Options of `softure migrate`:**
84
260
 
85
261
  | Option | Effect |
86
262
  | --- | --- |
87
263
  | (none) | apply every pending migration |
88
264
  | `--plan` | print what would be applied (or adopted); change nothing |
89
- | `--adopt <module>@<version>` | record an existing schema as migrated after comparing it (section 5) |
265
+ | `--adopt <module>@<version>` | record an existing schema as migrated after comparing it, after applying the pending migrations of its dependencies (section 5) |
266
+ | `--through <n>` | with `--adopt`: adopt files 1..n only; the next migrate applies the rest |
90
267
  | `--migrations-dir <dir>` | read module files from `<dir>/<module id>/` |
91
268
  | `--export-migrations <dir>` | copy module files to `<dir>/<module id>/` and exit; needs no database; replaces older `.sql` copies and refuses a module folder holding anything else |
92
269
 
93
270
  Exit codes: 0 done, 1 a problem or failure (each printed on stderr), 2 a usage error.
94
271
 
95
- The same operations as functions: `migrate(handle, { modules, migrationsDir?, onApplied? })`,
96
- `planMigrations(handle, { modules })`, `adoptModule(handle, { modules, module, version, dryRun? })`,
272
+ The same operations as functions: `migrate(handle, { modules, migrationsDir?, app?, onApplied?, onAdopted?, onAppMigrated? })`
273
+ (`runAppMigrations(handle, app, phase)` runs one hook alone under the lock),
274
+ `planMigrations(handle, { modules, app? })` (`pending`, and `baseline`: the pending files a baseline may adopt),
275
+ `adoptModule(handle, { modules, module, version, through?, dryRun? })`,
97
276
  `exportMigrations(modules, dir)`. Each returns `{ ok: true, value } | { ok: false, error, problems }`;
98
277
  `describeProblem(problem)` gives the English line.
99
278
 
@@ -118,16 +297,16 @@ module_version, method ('applied' | 'adopted'), applied_at`, primary key `(modul
118
297
  `SET LOCAL search_path TO <schema>, public` first. Name other modules' tables with their schema
119
298
  (`REFERENCES notes.notes (id)`), and create extensions `WITH SCHEMA public`.
120
299
 
121
- **Each run:** modules in dependency order (`sortModulesByDependencies`), files in number order.
300
+ **Each run:** the ledger, the app's `before` hook, modules in dependency order (`sortModulesByDependencies`), files in number order.
122
301
  Before anything runs, every file of every module is checked: an applied file that was edited or
123
302
  renamed (`db.migration_changed`), deleted (`db.migration_missing`), or a new file numbered below an
124
303
  applied one (`db.migration_out_of_order`) refuses the whole run. The run holds a session-level
125
304
  `pg_advisory_lock`, so a second runner waits, then finds nothing to do. A failing file is rolled
126
305
  back completely and stops the run; the files before it stay applied. The migration connection is
127
- closed after the run, never returned to the pool.
306
+ closed after the run, never returned to the pool. The app's `after` hook runs last (section 4).
128
307
 
129
308
  **Refused modules:** the id `softure`; the schemas `softure`, `public`, `information_schema`,
130
- `pg_*` and names over 63 bytes; migrations without a `dbSchema`.
309
+ `drizzle` (drizzle's ledger in every app), `pg_*` and names over 63 bytes; migrations without a `dbSchema`.
131
310
 
132
311
  **Adoption** ([docs/05](../../docs/05-adoption-playbook.md) step 3): after the app's own migration
133
312
  moved its tables into the module's schema, `--adopt <module>@<version>` (with `--plan` first)
@@ -136,14 +315,26 @@ one through `pg_catalog`: relations (and whether they are unlogged), columns (ty
136
315
  not null, default, identity, generated), sequences with their parameters, constraints and indexes
137
316
  (names and definitions), triggers, functions, and enum, domain, range and composite types. Only an
138
317
  exact match records the files as `adopted`; every difference is printed (`missing in database: …`,
139
- `unexpected in database: …`). The version must equal the enabled module's, the module must be new
140
- to the ledger, and the modules it depends on must be fully migrated or adopted first. Undo:
318
+ `unexpected in database: …`). `--through <n>` compares with and adopts files 1..n only; the next
319
+ migrate applies the rest. The version must equal the enabled module's and the module must be new to
320
+ the ledger. The pending migrations of the modules it depends on are applied first (listed as
321
+ `apply` lines; a dry run applies nothing); when one fails because its tables exist too, adopt that
322
+ module first. Module SQL may reference the app's own tables (`REFERENCES public.app_users (id)`):
323
+ the scratch database first gets stubs of every table outside the ledger, the enabled modules'
324
+ schemas and `drizzle`, copied from the live database (columns with their types, primary keys,
325
+ unique constraints, plain unique indexes and the enum types they use; no defaults, NOT NULL, checks
326
+ or foreign keys). The tables must therefore exist when the comparison runs: `--adopt` and a baseline
327
+ run `before` first, a `--plan` dry run reads only what is already there. A stub that cannot be
328
+ created (a domain or extension type) is skipped, and named in the failure when the module needs it.
329
+ For fresh databases of an app that adopted a module, declare a baseline (section 4). Undo:
141
330
  `DELETE FROM softure.migrations WHERE module = '<id>' AND method = 'adopted'`.
142
331
 
143
332
  **Tests:** `createTestDatabase(modules)` from `@softure-ai/db/testing` returns `{ db, client, close }`:
144
333
  an in-memory PGlite with the ledger and the listed modules migrated (list the module and the
145
334
  modules it depends on). Each module set is migrated once per test worker and copied per call; a
146
- broken migration throws naming the file.
335
+ broken migration throws naming the file. An app with its own migrations passes the same hooks,
336
+ `createTestDatabase(modules, { app: appMigrations })`, so module tables can reference app tables; the
337
+ template is cached per hook object, so import the shared object rather than writing hooks inline.
147
338
 
148
339
  ```ts
149
340
  import { createTestDatabase } from "@softure-ai/db/testing";
@@ -187,4 +378,7 @@ No personal data. The ledger holds module ids, file names and checksums.
187
378
  transaction-mode PgBouncer.
188
379
  - Adoption does not compare grants, comments, column order, row-level security policies or view
189
380
  bodies, and needs PGlite installed where it runs (also in an image that otherwise uses `pg`).
381
+ - The app table stubs of the reference carry no domains, extension types, views or functions: a
382
+ module whose SQL needs one of those from the app cannot be adopted (`db.adopt_reference_failed`
383
+ names the skipped stub objects).
190
384
  - No cached connection for Next.js dev reloads yet; the Next adapter (identity ID-1, FD-7) adds it.
package/dist/cli/run.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { SoftureConfig } from "@softure-ai/core";
2
+ import { type AppMigrations } from "../migrations/migrator.js";
2
3
  export interface CliOutput {
3
4
  readonly log: (line: string) => void;
4
5
  readonly error: (line: string) => void;
@@ -10,11 +11,17 @@ export interface RunMigrateCliOptions {
10
11
  /** Relative paths resolve against it. Default: `process.cwd()`. */
11
12
  readonly cwd?: string;
12
13
  readonly output?: CliOutput;
14
+ /**
15
+ * The app's own migrations: migrate runs `before`, the module files (adopting `baseline` where
16
+ * it applies), then `after`; `--adopt` (without `--plan`) runs `before` first; `--plan` runs no
17
+ * hook and marks the files a baseline may adopt.
18
+ */
19
+ readonly app?: AppMigrations;
13
20
  }
14
21
  export declare const EXIT_OK = 0;
15
22
  export declare const EXIT_FAILED = 1;
16
23
  export declare const EXIT_USAGE = 2;
17
- export declare const MIGRATE_USAGE = "Usage: softure migrate [options]\n\nApplies the SQL migrations of every enabled module, each in its own schema.\n\nOptions:\n --plan show what would be applied (or adopted) and change nothing\n --adopt <module>@<version> record an existing schema as migrated, after comparing it\n --migrations-dir <dir> read module files from <dir>/<module id>/ (bundled runners)\n --export-migrations <dir> copy module files to <dir>/<module id>/ and exit (build stage)\n --help show this help";
24
+ export declare const MIGRATE_USAGE = "Usage: softure migrate [options]\n\nApplies the SQL migrations of every enabled module, each in its own schema.\n\nOptions:\n --plan show what would be applied (or adopted) and change nothing\n --adopt <module>@<version> record an existing schema as migrated, after comparing it;\n applies the pending migrations of its dependencies first\n --through <n> with --adopt: adopt files 1..n only, leave the rest to migrate\n --migrations-dir <dir> read module files from <dir>/<module id>/ (bundled runners)\n --export-migrations <dir> copy module files to <dir>/<module id>/ and exit (build stage)\n --help show this help";
18
25
  /** Runs the command and returns the process exit code: 0 done, 1 failed, 2 usage error. */
19
26
  export declare function runMigrateCli(options: RunMigrateCliOptions): Promise<number>;
20
27
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAC7D,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AAED,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,eAAO,MAAM,aAAa,oiBASqB,CAAC;AAehD,2FAA2F;AAC3F,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0ClF"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKtD,OAAO,EAA6C,KAAK,aAAa,EAAsB,MAAM,2BAA2B,CAAC;AAG9H,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAC7D,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC;CAC9B;AAED,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,eAAO,MAAM,aAAa,+tBAWqB,CAAC;AAehD,2FAA2F;AAC3F,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClF"}
package/dist/cli/run.js CHANGED
@@ -5,13 +5,15 @@
5
5
  // import { runMigrateCli } from "@softure-ai/db/cli";
6
6
  // import config from "../softure.config";
7
7
  // process.exitCode = await runMigrateCli({ config, argv: process.argv.slice(2) });
8
+ //
9
+ // An app with its own migrations passes them as `app: { before, after }` (see MigrateOptions.app).
8
10
  import { resolve } from "node:path";
9
11
  import { parseArgs } from "node:util";
10
12
  import { pathToFileURL } from "node:url";
11
- import { createDatabase } from "../client.js";
13
+ import { openCommandDatabase } from "../configured.js";
12
14
  import { adoptModule } from "../migrations/adopt.js";
13
15
  import { exportMigrations } from "../migrations/export.js";
14
- import { migrate, planMigrations } from "../migrations/migrator.js";
16
+ import { migrate, planMigrations, runAppMigrations } from "../migrations/migrator.js";
15
17
  import { describeProblem } from "../migrations/problems.js";
16
18
  export const EXIT_OK = 0;
17
19
  export const EXIT_FAILED = 1;
@@ -22,7 +24,9 @@ Applies the SQL migrations of every enabled module, each in its own schema.
22
24
 
23
25
  Options:
24
26
  --plan show what would be applied (or adopted) and change nothing
25
- --adopt <module>@<version> record an existing schema as migrated, after comparing it
27
+ --adopt <module>@<version> record an existing schema as migrated, after comparing it;
28
+ applies the pending migrations of its dependencies first
29
+ --through <n> with --adopt: adopt files 1..n only, leave the rest to migrate
26
30
  --migrations-dir <dir> read module files from <dir>/<module id>/ (bundled runners)
27
31
  --export-migrations <dir> copy module files to <dir>/<module id>/ and exit (build stage)
28
32
  --help show this help`;
@@ -52,22 +56,24 @@ export async function runMigrateCli(options) {
52
56
  result.value.forEach((step) => output.log(`exported ${formatStep(step)}`));
53
57
  return EXIT_OK;
54
58
  }
55
- const url = options.config.database?.url;
56
- if (url === undefined) {
59
+ const database = options.config.database;
60
+ if (database === null) {
57
61
  output.error("softure migrate: the config has no database; set database.url in softure.config");
58
62
  return EXIT_FAILED;
59
63
  }
60
- let handle;
64
+ let opened;
61
65
  try {
62
- handle = await createDatabase(url);
66
+ // The app's configured handle when it set one, so the app's hooks and the run share one instance.
67
+ opened = await openCommandDatabase(database);
63
68
  }
64
69
  catch (error) {
65
70
  output.error(`softure migrate: ${describeError(error)}`);
66
71
  return EXIT_FAILED;
67
72
  }
73
+ const { handle } = opened;
68
74
  try {
69
75
  const migrationsDir = command.migrationsDir === undefined ? undefined : pathToFileURL(`${resolve(cwd, command.migrationsDir)}/`);
70
- return await runDatabaseCommand(handle, { command, modules: options.config.modules, migrationsDir, output });
76
+ return await runDatabaseCommand(handle, { command, modules: options.config.modules, migrationsDir, output, app: options.app ?? {} });
71
77
  }
72
78
  catch (error) {
73
79
  // Connection and driver errors: the message only, never a stack or the database URL.
@@ -75,34 +81,61 @@ export async function runMigrateCli(options) {
75
81
  return EXIT_FAILED;
76
82
  }
77
83
  finally {
78
- await handle.close();
84
+ await opened.close();
79
85
  }
80
86
  }
81
87
  async function runDatabaseCommand(handle, input) {
82
- const { command, modules, output } = input;
88
+ const { command, modules, output, app } = input;
83
89
  const dirOption = input.migrationsDir === undefined ? {} : { migrationsDir: input.migrationsDir };
90
+ const hasAppMigrations = app.before !== undefined || app.after !== undefined;
91
+ if (command.plan && hasAppMigrations) {
92
+ output.log("app migrations: not planned; the app runs them itself on migrate");
93
+ }
84
94
  if (command.kind === "adopt") {
85
- const result = await adoptModule(handle, { modules, module: command.module, version: command.version, dryRun: command.plan, ...dirOption });
95
+ if (!command.plan) {
96
+ const before = await runAppMigrations(handle, app, "before");
97
+ if (!before.ok)
98
+ return reportFailure(output, before);
99
+ if (before.value.ran)
100
+ output.log("applied app migrations (before)");
101
+ }
102
+ const result = await adoptModule(handle, {
103
+ modules,
104
+ module: command.module,
105
+ version: command.version,
106
+ dryRun: command.plan,
107
+ ...(command.through === undefined ? {} : { through: command.through }),
108
+ ...dirOption,
109
+ });
86
110
  if (!result.ok)
87
111
  return reportFailure(output, result);
88
112
  const verb = command.plan ? "would" : "did";
89
- result.value.ledger.forEach((step) => output.log(`${verb} apply ${formatStep(step)}`));
113
+ [...result.value.ledger, ...result.value.dependencies].forEach((step) => output.log(`${verb} apply ${formatStep(step)}`));
90
114
  result.value.adopted.forEach((step) => output.log(`${verb} adopt ${formatStep(step)}`));
91
- output.log(`${command.module}@${command.version}: the schema matches its migrations${command.plan ? " (plan only, nothing written)" : "; adopted"}`);
115
+ const scope = command.through === undefined ? "" : ` through ${formatVersion(command.through)}`;
116
+ output.log(`${command.module}@${command.version}: the schema matches its migrations${scope}${command.plan ? " (plan only, nothing written)" : "; adopted"}`);
92
117
  return EXIT_OK;
93
118
  }
94
119
  if (command.plan) {
95
- const result = await planMigrations(handle, { modules, ...dirOption });
120
+ const result = await planMigrations(handle, { modules, ...dirOption, app });
96
121
  if (!result.ok)
97
122
  return reportFailure(output, result);
98
- result.value.pending.forEach((step) => output.log(`pending ${formatStep(step)}`));
123
+ const baseline = new Set(result.value.baseline);
124
+ result.value.pending.forEach((step) => output.log(`pending ${formatStep(step)}${baseline.has(step) ? " (adopted if its schema already holds objects)" : ""}`));
99
125
  output.log(result.value.pending.length === 0 ? "nothing to apply" : `${result.value.pending.length} migration(s) to apply`);
100
126
  return EXIT_OK;
101
127
  }
102
- const result = await migrate(handle, { modules, ...dirOption, onApplied: (step) => output.log(`applied ${formatStep(step)}`) });
128
+ const result = await migrate(handle, {
129
+ modules,
130
+ ...dirOption,
131
+ app,
132
+ onApplied: (step) => output.log(`applied ${formatStep(step)}`),
133
+ onAdopted: (step) => output.log(`adopted ${formatStep(step)}`),
134
+ onAppMigrated: (phase) => output.log(`applied app migrations (${phase})`),
135
+ });
103
136
  if (!result.ok)
104
137
  return reportFailure(output, result);
105
- output.log(result.value.applied.length === 0 ? "nothing to apply" : `${result.value.applied.length} migration(s) applied`);
138
+ output.log(formatSummary(result.value.applied.length, result.value.adopted.length));
106
139
  return EXIT_OK;
107
140
  }
108
141
  function parseCommand(argv) {
@@ -113,6 +146,7 @@ function parseCommand(argv) {
113
146
  options: {
114
147
  plan: { type: "boolean" },
115
148
  adopt: { type: "string" },
149
+ through: { type: "string" },
116
150
  "migrations-dir": { type: "string" },
117
151
  "export-migrations": { type: "string" },
118
152
  help: { type: "boolean" },
@@ -128,26 +162,42 @@ function parseCommand(argv) {
128
162
  return { kind: "help" };
129
163
  const exportDir = values["export-migrations"];
130
164
  if (exportDir !== undefined) {
131
- const others = ["plan", "adopt", "migrations-dir"].filter((name) => values[name] !== undefined);
165
+ const others = ["plan", "adopt", "through", "migrations-dir"].filter((name) => values[name] !== undefined);
132
166
  return others.length > 0 ? `--export-migrations cannot be combined with --${others.join(", --")}` : { kind: "export", targetDir: exportDir };
133
167
  }
134
168
  const plan = values.plan === true;
135
169
  const migrationsDir = values["migrations-dir"];
136
170
  if (values.adopt === undefined) {
137
- return { kind: "migrate", plan, migrationsDir };
171
+ return values.through === undefined ? { kind: "migrate", plan, migrationsDir } : "--through needs --adopt <module>@<version>";
138
172
  }
139
173
  const match = ADOPT_TARGET.exec(values.adopt);
140
174
  if (match?.[1] === undefined || match[2] === undefined) {
141
175
  return `--adopt expects <module>@<x.y.z>, e.g. auth@0.1.0, got "${values.adopt}"`;
142
176
  }
143
- return { kind: "adopt", plan, module: match[1], version: match[2], migrationsDir };
177
+ const through = values.through === undefined ? undefined : parseThrough(values.through);
178
+ if (through === null) {
179
+ return `--through expects a positive whole number, got "${values.through ?? ""}"`;
180
+ }
181
+ return { kind: "adopt", plan, module: match[1], version: match[2], through, migrationsDir };
182
+ }
183
+ /** A positive whole number written in digits, or null. */
184
+ function parseThrough(text) {
185
+ return /^[1-9]\d*$/.test(text) ? Number(text) : null;
144
186
  }
145
187
  function reportFailure(output, failure) {
146
188
  failure.problems.forEach((problem) => output.error(describeProblem(problem)));
147
189
  return EXIT_FAILED;
148
190
  }
149
191
  function formatStep(step) {
150
- return `${step.module} ${String(step.version).padStart(4, "0")}_${step.name}.sql`;
192
+ return `${step.module} ${formatVersion(step.version)}_${step.name}.sql`;
193
+ }
194
+ function formatVersion(version) {
195
+ return String(version).padStart(4, "0");
196
+ }
197
+ function formatSummary(applied, adopted) {
198
+ if (applied === 0 && adopted === 0)
199
+ return "nothing to apply";
200
+ return adopted === 0 ? `${applied} migration(s) applied` : `${applied} migration(s) applied, ${adopted} adopted`;
151
201
  }
152
202
  function describeError(error) {
153
203
  return error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,iGAAiG;AACjG,EAAE;AACF,0BAA0B;AAC1B,wDAAwD;AACxD,4CAA4C;AAC5C,qFAAqF;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAsB,MAAM,2BAA2B,CAAC;AACxF,OAAO,EAAE,eAAe,EAAyB,MAAM,2BAA2B,CAAC;AAgBnF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAE5B,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;+CASkB,CAAC;AAEhD,MAAM,YAAY,GAAG,mDAAmD,CAAC;AAEzE,MAAM,aAAa,GAAc;IAC/B,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;CACrC,CAAC;AAQF,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC5B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/F,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC;IACzC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,iFAAiF,CAAC,CAAC;QAChG,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,MAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,oBAAoB,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzD,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACjI,OAAO,MAAM,kBAAkB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/G,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qFAAqF;QACrF,MAAM,CAAC,KAAK,CAAC,oBAAoB,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzD,OAAO,WAAW,CAAC;IACrB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,MAAsB,EACtB,KAKC;IAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC;IAElG,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;QAC5I,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,UAAU,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACvF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,UAAU,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACxF,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,sCAAsC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACrJ,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,wBAAwB,CAAC,CAAC;QAC5H,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAChI,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,uBAAuB,CAAC,CAAC;IAC3H,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,IAAuB;IAC3C,IAAI,MAAmH,CAAC;IACxH,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;YACtB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;YACf,OAAO,EAAE;gBACP,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACpC,mBAAmB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACvC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;aAC1B;YACD,MAAM,EAAE,IAAI;YACZ,gBAAgB,EAAE,KAAK;SACxB,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC9C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAI,CAAC,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;QAC3G,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iDAAiD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IAC/I,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC;IAClC,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QACvD,OAAO,2DAA2D,MAAM,CAAC,KAAK,GAAG,CAAC;IACpF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;AACrF,CAAC;AAED,SAAS,aAAa,CAAC,MAAiB,EAAE,OAAyB;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9E,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,UAAU,CAAC,IAAmB;IACrC,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,MAAM,CAAC;AACpF,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}