okmodel 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +882 -48
- package/dist/contracts/catalog/document.d.ts +6 -2
- package/dist/contracts/catalog/enum.d.ts +31 -4
- package/dist/contracts/catalog/extension.d.ts +61 -0
- package/dist/contracts/catalog/privilege.d.ts +64 -0
- package/dist/contracts/catalog/routine.d.ts +56 -0
- package/dist/contracts/catalog/types.d.ts +164 -10
- package/dist/contracts/catalog/view.d.ts +73 -0
- package/dist/dialects/pg/column.d.ts +3 -1
- package/dist/dialects/pg/ddl.d.ts +65 -1
- package/dist/dialects/pg/enum.d.ts +10 -8
- package/dist/dialects/pg/ext/citext.d.ts +14 -0
- package/dist/dialects/pg/ext/citext.js +11 -0
- package/dist/dialects/pg/ext/index.d.ts +52 -0
- package/dist/dialects/pg/ext/index.js +6 -0
- package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
- package/dist/dialects/pg/ext/pg-trgm.js +42 -0
- package/dist/dialects/pg/fn/index.d.ts +107 -0
- package/dist/dialects/pg/fn/index.js +175 -0
- package/dist/dialects/pg/fn/touch.d.ts +14 -0
- package/dist/dialects/pg/index.js +104 -19
- package/dist/dialects/pg/introspect.d.ts +10 -1
- package/dist/dialects/pg/operators.d.ts +8 -1
- package/dist/dialects/pg/role/check.d.ts +45 -0
- package/dist/dialects/pg/role/index.d.ts +50 -0
- package/dist/dialects/pg/role/sql.d.ts +51 -0
- package/dist/dialects/pg/table.d.ts +24 -1
- package/dist/dialects/pg/tenancy.d.ts +9 -0
- package/dist/dialects/pg/view/client.d.ts +30 -0
- package/dist/dialects/pg/view/depend.d.ts +35 -0
- package/dist/dialects/pg/view/index.d.ts +114 -0
- package/dist/dialects/pg/view/index.js +289 -0
- package/dist/dialects/pg/view/scratch.d.ts +22 -0
- package/dist/dialects/pg/where.d.ts +2 -2
- package/dist/runtime/catalog-cache.d.ts +17 -0
- package/dist/runtime/compat-words.d.ts +23 -0
- package/dist/runtime/drift-detail.d.ts +20 -4
- package/dist/runtime/drift.d.ts +4 -2
- package/dist/runtime/pg/bun.js +3 -3
- package/dist/runtime/pg/pg.js +3 -3
- package/dist/runtime/pg/pglite.js +3 -3
- package/dist/runtime/pg/postgresjs.js +3 -3
- package/dist/runtime/tenancy/index.js +6 -3
- package/dist/runtime/traits/index.d.ts +7 -2
- package/dist/runtime/traits/index.js +151 -13
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/validate/index.js +4 -4
- package/dist/shared/{xkz8g6by.js → 1g0drakv.js} +2 -2
- package/dist/shared/2321avmn.js +418 -0
- package/dist/shared/{7mht49yd.js → 3p4b1fg0.js} +57 -18
- package/dist/shared/41kv2xdm.js +318 -0
- package/dist/shared/{97g2jnrw.js → 4ef7mmqf.js} +3 -3
- package/dist/shared/{sacqha1y.js → 4m9fn52z.js} +2 -2
- package/dist/shared/5mtf6cj3.js +94 -0
- package/dist/shared/{1dp5knt7.js → 5vdm4sgp.js} +2 -2
- package/dist/shared/{a1gdp7j9.js → 6693j9rs.js} +1 -1
- package/dist/shared/{38crxbgn.js → 6p5k20sm.js} +3 -3
- package/dist/shared/7nk68fj8.js +751 -0
- package/dist/shared/84ptn35q.js +71 -0
- package/dist/shared/{d2whjz4k.js → 8jb4ymh2.js} +581 -28
- package/dist/shared/8ktwd3rh.js +97 -0
- package/dist/shared/94ez8kzh.js +19 -0
- package/dist/shared/{3a5ne750.js → 9m80mkac.js} +2 -2
- package/dist/shared/9x25fxhc.js +150 -0
- package/dist/shared/9yn6a2vd.js +11 -0
- package/dist/shared/ady1ms74.js +72 -0
- package/dist/shared/{4jzzghr6.js → awrsqrn7.js} +6 -6
- package/dist/shared/{4b9da9d7.js → axhk06q1.js} +19 -1
- package/dist/shared/{d04j53v8.js → c5g81ngb.js} +82 -14
- package/dist/shared/{n47rd821.js → c8aghh05.js} +1 -1
- package/dist/shared/{dd4f8mnx.js → c9z5g0fm.js} +4 -2
- package/dist/shared/{ps43134h.js → dyj86cmj.js} +4 -4
- package/dist/shared/{0qkxbm1f.js → fa9vt245.js} +1 -1
- package/dist/shared/{qa5dsc7z.js → fb00y8fp.js} +3 -3
- package/dist/shared/{qxa0yb9j.js → g7ez901n.js} +30 -1
- package/dist/shared/{py3nh7jy.js → gdh9mrtp.js} +2 -2
- package/dist/shared/{yw5c610b.js → gjthds9j.js} +2 -2
- package/dist/shared/hcmdtwgh.js +102 -0
- package/dist/shared/hqjsxnz7.js +13 -0
- package/dist/shared/htnaj77v.js +17 -0
- package/dist/shared/{v18jva5b.js → jgxzjzcz.js} +1 -1
- package/dist/shared/{x9v1qgeb.js → jsd07prz.js} +3 -3
- package/dist/shared/{g9f0zqce.js → kafaa5zv.js} +1 -1
- package/dist/shared/kj680nxv.js +19 -0
- package/dist/shared/{mxmcdsh5.js → kkzwp3d2.js} +9 -9
- package/dist/shared/{g1b5zzj9.js → n0dgs0pb.js} +1 -1
- package/dist/shared/n5y9zyj1.js +2431 -0
- package/dist/shared/{zt8y0wzb.js → n7mcc1gk.js} +1 -1
- package/dist/shared/{ge03bfca.js → nxb42q7h.js} +2 -2
- package/dist/shared/q6zsyh31.js +2192 -0
- package/dist/shared/{sfh4pk75.js → q795afwa.js} +26 -21
- package/dist/shared/{10tjenmd.js → qn0srwwq.js} +1 -1
- package/dist/shared/s4mb6a4b.js +545 -0
- package/dist/shared/{ytg3xf9p.js → sf8m6tfy.js} +3 -3
- package/dist/shared/{zd93g3rq.js → sr5ms7b3.js} +1 -1
- package/dist/shared/{xatfg0gn.js → tmbdywx0.js} +4 -19
- package/dist/shared/tny2t3sm.js +100 -0
- package/dist/shared/{e7a268fy.js → v7tpnhnz.js} +1 -1
- package/dist/shared/{ecdzej21.js → wqem4jed.js} +7 -7
- package/dist/shared/xghkt7a9.js +1144 -0
- package/dist/shared/y005b761.js +112 -0
- package/dist/shared/ycatkxmq.js +84 -0
- package/dist/shared/ygem90rn.js +900 -0
- package/dist/shared/{eaxwrgby.js → yjw02enp.js} +6 -3
- package/dist/shared/{mrq77sgw.js → zg24x0hm.js} +1 -1
- package/dist/shared/{cstgkzdx.js → zvbjc949.js} +1 -1
- package/dist/tooling/cli.js +66 -13
- package/dist/tooling/migrate/apply.d.ts +75 -5
- package/dist/tooling/migrate/backfill.d.ts +136 -0
- package/dist/tooling/migrate/check.d.ts +65 -0
- package/dist/tooling/migrate/classify.d.ts +108 -0
- package/dist/tooling/migrate/commands.d.ts +2 -1
- package/dist/tooling/migrate/config.d.ts +30 -0
- package/dist/tooling/migrate/doctor.d.ts +28 -0
- package/dist/tooling/migrate/drift.d.ts +35 -0
- package/dist/tooling/migrate/estimate.d.ts +50 -0
- package/dist/tooling/migrate/ext.d.ts +17 -0
- package/dist/tooling/migrate/extensions.d.ts +53 -0
- package/dist/tooling/migrate/files.d.ts +12 -0
- package/dist/tooling/migrate/index.d.ts +3 -2
- package/dist/tooling/migrate/index.js +67 -1
- package/dist/tooling/migrate/lint-rules.d.ts +51 -0
- package/dist/tooling/migrate/lint.d.ts +71 -0
- package/dist/tooling/migrate/managed.d.ts +17 -0
- package/dist/tooling/migrate/plan.d.ts +78 -10
- package/dist/tooling/migrate/project.d.ts +64 -5
- package/dist/tooling/migrate/provision.d.ts +18 -0
- package/dist/tooling/migrate/reference.d.ts +40 -0
- package/dist/tooling/migrate/runner.d.ts +108 -0
- package/dist/tooling/migrate/safe.d.ts +77 -0
- package/dist/tooling/migrate/seed.d.ts +20 -0
- package/dist/tooling/migrate/snapshot.d.ts +78 -0
- package/dist/tooling/migrate/status.d.ts +25 -6
- package/dist/tooling/migrate/type-name.d.ts +19 -0
- package/dist/tooling/testing/factories.d.ts +117 -0
- package/dist/tooling/testing/facts.d.ts +72 -0
- package/dist/tooling/testing/index.d.ts +89 -0
- package/dist/tooling/testing/index.js +8 -0
- package/dist/tooling/testing/isolation.d.ts +30 -0
- package/dist/tooling/testing/random.d.ts +40 -0
- package/dist/tooling/testing/record.d.ts +38 -0
- package/package.json +26 -2
- package/dist/shared/5z4q2zda.js +0 -2073
- package/dist/shared/eqmtn1bj.js +0 -399
- package/dist/shared/rtnaqre0.js +0 -37
- package/dist/shared/zwmqxb0g.js +0 -79
- package/dist/shared/{m9tv7xn7.js → radd3z4g.js} +3 -3
- /package/dist/shared/{9k6vetvf.js → rrstp3kb.js} +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `okm doctor`.
|
|
3
|
+
*
|
|
4
|
+
* A code prints the registry entry. With no code, the project is loaded and
|
|
5
|
+
* each table's triggers are listed. When `roles` is set, the command also
|
|
6
|
+
* connects and checks that those roles exist, that a managed role can be
|
|
7
|
+
* created, and that the application role can reach each managed object.
|
|
8
|
+
*/
|
|
9
|
+
import type { CatalogObject } from "../../contracts/catalog/types.js";
|
|
10
|
+
import { type InvokeFlags } from "./policy.js";
|
|
11
|
+
/**
|
|
12
|
+
* Explains one code, or lists the triggers on each table.
|
|
13
|
+
*
|
|
14
|
+
* A role check connects as the read-only `check` class. A protected target
|
|
15
|
+
* is allowed. The command does not change the database.
|
|
16
|
+
*
|
|
17
|
+
* @param cwd - Project directory
|
|
18
|
+
* @param code - Spec code, when the caller passed one
|
|
19
|
+
* @returns Text for stdout, including the trailing newline
|
|
20
|
+
*/
|
|
21
|
+
export declare function doctorProject(cwd: string, code: string | undefined, flags?: InvokeFlags): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* One line per table that has a trigger.
|
|
24
|
+
*
|
|
25
|
+
* @param objects - Catalog objects
|
|
26
|
+
* @returns The listing, or `no triggers` when none are present
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatTriggers(objects: readonly CatalogObject[]): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live drift for `okm check`.
|
|
3
|
+
*
|
|
4
|
+
* A database that has never been pushed has no `okm_meta` and is left alone.
|
|
5
|
+
* After push, the introspected catalog is planned back to the schema. Each
|
|
6
|
+
* view is reprinted on this server first, so a `pg_get_viewdef` spelling is
|
|
7
|
+
* not drift. Any remaining statement is OKM1520. `okm_meta`, `okm_history`,
|
|
8
|
+
* and `okm_backfill` are omitted by the planner.
|
|
9
|
+
*/
|
|
10
|
+
import { type Sql } from "postgres";
|
|
11
|
+
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
12
|
+
import { type CatalogQuery, type IntrospectOptions } from "../../dialects/pg/introspect.js";
|
|
13
|
+
import type { RolesInput } from "../../dialects/pg/role/index.js";
|
|
14
|
+
/**
|
|
15
|
+
* Refuses when the connected database differs from the schema.
|
|
16
|
+
*
|
|
17
|
+
* @param url - Target URL
|
|
18
|
+
* @param author - Schema catalog, including roles when the config names them
|
|
19
|
+
* @param roles - `defineConfig({ roles })`, when set
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertAuthorDrift(url: string, author: Catalog, roles?: RolesInput): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Turns a postgres.js handle into the query shape introspection uses.
|
|
24
|
+
*
|
|
25
|
+
* @param sql - One connection
|
|
26
|
+
* @returns A {@link CatalogQuery}
|
|
27
|
+
*/
|
|
28
|
+
export declare function catalogQuery(sql: Sql): CatalogQuery;
|
|
29
|
+
/**
|
|
30
|
+
* Role names introspection should read, when the config names them.
|
|
31
|
+
*
|
|
32
|
+
* @param roles - `defineConfig({ roles })`, when set
|
|
33
|
+
* @returns The introspect option, or `undefined` when roles are not configured
|
|
34
|
+
*/
|
|
35
|
+
export declare function managedRoleOptions(roles: RolesInput | undefined): IntrospectOptions | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row estimates for `okm migrate plan` (D194).
|
|
3
|
+
*
|
|
4
|
+
* The numbers come from `pg_class.reltuples` on a selected target. They are
|
|
5
|
+
* printed next to the lock and then discarded. The linter never reads them,
|
|
6
|
+
* and `okm generate` never asks for them.
|
|
7
|
+
*/
|
|
8
|
+
import type { PlanStep } from "./plan.js";
|
|
9
|
+
/**
|
|
10
|
+
* Estimated rows above which an `ACCESS EXCLUSIVE` lock prints a note.
|
|
11
|
+
*
|
|
12
|
+
* The note is text on the lock line. It is not a lint finding.
|
|
13
|
+
*/
|
|
14
|
+
export declare const LARGE_TABLE_ROWS = 1000000;
|
|
15
|
+
/** What `pg_class` said about one table. */
|
|
16
|
+
export type RowEstimate = {
|
|
17
|
+
readonly kind: "rows";
|
|
18
|
+
readonly reltuples: number;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: "unknown";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Reads `reltuples` for the named tables.
|
|
24
|
+
*
|
|
25
|
+
* The statements run in one read-only transaction. A table that is absent
|
|
26
|
+
* from the result is not entered in the map: the printer treats that as
|
|
27
|
+
* `new table`. `reltuples` of `-1` is {@link RowEstimate} `unknown`. This
|
|
28
|
+
* never scans a table.
|
|
29
|
+
*
|
|
30
|
+
* @param url - Target URL
|
|
31
|
+
* @param schema - Schema the plan qualifies, usually `public`
|
|
32
|
+
* @param tables - Table names the plan steps name
|
|
33
|
+
* @returns One entry per relation `pg_class` returned
|
|
34
|
+
*/
|
|
35
|
+
export declare function readRowEstimates(url: string, schema: string, tables: readonly string[]): Promise<ReadonlyMap<string, RowEstimate>>;
|
|
36
|
+
/**
|
|
37
|
+
* Lock line with estimates, the safe-rewrite label, and the large-table note.
|
|
38
|
+
*
|
|
39
|
+
* @param step - One plan step
|
|
40
|
+
* @param estimates - `reltuples` for tables that exist on the target
|
|
41
|
+
* @returns The text after `-- lock: `
|
|
42
|
+
*/
|
|
43
|
+
export declare function annotateLock(step: PlanStep, estimates: ReadonlyMap<string, RowEstimate>): string;
|
|
44
|
+
/**
|
|
45
|
+
* Compact phrase for one estimate.
|
|
46
|
+
*
|
|
47
|
+
* @param count - Rounded `reltuples`
|
|
48
|
+
* @returns `about 4.2M rows` and the same shape for thousands and billions
|
|
49
|
+
*/
|
|
50
|
+
export declare function aboutRows(count: number): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `okm ext list` and `okm ext check`.
|
|
3
|
+
*
|
|
4
|
+
* Both talk to the selected target. List prints every extension the server
|
|
5
|
+
* can install, and the installed version when one is present. Check compares
|
|
6
|
+
* the schema's declarations with what is installed.
|
|
7
|
+
*/
|
|
8
|
+
import { type InvokeFlags } from "./policy.js";
|
|
9
|
+
/**
|
|
10
|
+
* Runs `list` or `check` against the selected target.
|
|
11
|
+
*
|
|
12
|
+
* @param cwd - Project directory
|
|
13
|
+
* @param command - `list` or `check`
|
|
14
|
+
* @param flags - Target and protection flags
|
|
15
|
+
* @returns Text for stdout, including the trailing newline
|
|
16
|
+
*/
|
|
17
|
+
export declare function extProject(cwd: string, command: "list" | "check", flags: InvokeFlags): Promise<string>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension alters and the apply preflight.
|
|
3
|
+
*
|
|
4
|
+
* Create and drop SQL come from the dialect. An upgrade is `ALTER EXTENSION
|
|
5
|
+
* … UPDATE`, marked `path-unverified` until apply checks
|
|
6
|
+
* `pg_extension_update_paths`. A move is `SET SCHEMA` and only when the
|
|
7
|
+
* declaration is relocatable.
|
|
8
|
+
*/
|
|
9
|
+
import type { CatalogObject } from "../../contracts/catalog/types.js";
|
|
10
|
+
import type { DriverConnection } from "../../contracts/driver.js";
|
|
11
|
+
import { type StepKind } from "./classify.js";
|
|
12
|
+
/** One extension alter. The planner stores it as a plan step. */
|
|
13
|
+
export type ExtensionStep = {
|
|
14
|
+
readonly sql: string;
|
|
15
|
+
readonly kind: StepKind;
|
|
16
|
+
readonly class: "expand" | "contract";
|
|
17
|
+
readonly action: "ddl";
|
|
18
|
+
readonly lock: string;
|
|
19
|
+
readonly transactional: boolean;
|
|
20
|
+
readonly path?: "unverified";
|
|
21
|
+
};
|
|
22
|
+
/** Migrations the preflight reads. Only the statement text is used. */
|
|
23
|
+
type MigrationSql = {
|
|
24
|
+
readonly steps: readonly {
|
|
25
|
+
readonly sql: string;
|
|
26
|
+
}[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Upgrade and move steps for extensions whose definition changed.
|
|
30
|
+
*
|
|
31
|
+
* Exact downgrades and moves of a non-relocatable extension are OKM1814.
|
|
32
|
+
* Dropping an extension that an object in the next catalog still uses is
|
|
33
|
+
* OKM1814. `DROP` is never `CASCADE`.
|
|
34
|
+
*
|
|
35
|
+
* @param beforeBy - Previous objects, keyed by identity
|
|
36
|
+
* @param afterBy - Next objects, keyed by identity
|
|
37
|
+
* @param dropKeys - Identities the plan drops
|
|
38
|
+
* @returns Alter steps. Creates and drops stay in the main planner
|
|
39
|
+
*/
|
|
40
|
+
export declare function extensionAlterSteps(beforeBy: ReadonlyMap<string, CatalogObject>, afterBy: ReadonlyMap<string, CatalogObject>, dropKeys: ReadonlySet<string>): ExtensionStep[];
|
|
41
|
+
/**
|
|
42
|
+
* Refuses a migration that names an extension the server cannot install,
|
|
43
|
+
* or an upgrade with no path.
|
|
44
|
+
*
|
|
45
|
+
* The server is asked only when a step creates or upgrades an extension.
|
|
46
|
+
* The check runs before any statement.
|
|
47
|
+
*
|
|
48
|
+
* @param connection - The reserved apply connection
|
|
49
|
+
* @param migrations - Migrations in apply order
|
|
50
|
+
* @throws OkmError OKM1811 when the extension is not available, OKM1814 when the update path is missing
|
|
51
|
+
*/
|
|
52
|
+
export declare function assertExtensionsAvailable(connection: DriverConnection, migrations: readonly MigrationSql[]): Promise<void>;
|
|
53
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Migration files on disk: SQL from {@link formatPlan} plus the catalog hash.
|
|
3
3
|
*/
|
|
4
|
+
import { parseCatalog } from "../../contracts/catalog/document.js";
|
|
4
5
|
import { type PlanStep } from "./plan.js";
|
|
5
6
|
/** One migration the applier can run and resume. */
|
|
6
7
|
export type StoredMigration = {
|
|
@@ -17,3 +18,14 @@ export type StoredMigration = {
|
|
|
17
18
|
* @returns Migrations in apply order
|
|
18
19
|
*/
|
|
19
20
|
export declare function loadMigrations(directory: string): readonly StoredMigration[];
|
|
21
|
+
/**
|
|
22
|
+
* Loads the last migration's catalog, which is the head snapshot.
|
|
23
|
+
*
|
|
24
|
+
* @param directory - Migrations directory
|
|
25
|
+
* @returns The last file, or `undefined` when there are none
|
|
26
|
+
*/
|
|
27
|
+
export declare function loadHeadSnapshot(directory: string): {
|
|
28
|
+
readonly id: string;
|
|
29
|
+
readonly catalogHash: string;
|
|
30
|
+
readonly catalog: ReturnType<typeof parseCatalog>;
|
|
31
|
+
} | undefined;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public entry for `okmodel/migrate`.
|
|
3
3
|
*
|
|
4
|
-
* `defineConfig
|
|
5
|
-
*
|
|
4
|
+
* `defineConfig`, its types, and `provision` for one configured target.
|
|
5
|
+
* The CLI imports planning and apply helpers from their modules.
|
|
6
6
|
*/
|
|
7
7
|
export { defineConfig, type MigrateConfig, type TargetInput } from "./config.js";
|
|
8
|
+
export { provision } from "./provision.js";
|
|
@@ -1,7 +1,73 @@
|
|
|
1
|
+
import"../../shared/wqem4jed.js";
|
|
2
|
+
import"../../shared/8jb4ymh2.js";
|
|
3
|
+
import"../../shared/n442h54c.js";
|
|
4
|
+
import {
|
|
5
|
+
applyTarget2,
|
|
6
|
+
backfillTiming2
|
|
7
|
+
} from "../../shared/s4mb6a4b.js";
|
|
8
|
+
import {
|
|
9
|
+
loadMigrations,
|
|
10
|
+
loadHeadSnapshot,
|
|
11
|
+
readReference
|
|
12
|
+
} from "../../shared/7nk68fj8.js";
|
|
13
|
+
import {
|
|
14
|
+
assertTargetPolicy,
|
|
15
|
+
selectTarget,
|
|
16
|
+
loadBuiltSchema,
|
|
17
|
+
loadConfig
|
|
18
|
+
} from "../../shared/q6zsyh31.js";
|
|
19
|
+
import"../../shared/n5y9zyj1.js";
|
|
20
|
+
import"../../shared/41kv2xdm.js";
|
|
21
|
+
import {
|
|
22
|
+
OkmError2
|
|
23
|
+
} from "../../shared/52szzakm.js";
|
|
24
|
+
|
|
1
25
|
// src/tooling/migrate/config.ts
|
|
2
26
|
function defineConfig(config) {
|
|
3
27
|
return config;
|
|
4
28
|
}
|
|
29
|
+
// src/tooling/migrate/provision.ts
|
|
30
|
+
import { join } from "node:path";
|
|
31
|
+
async function provision(target, cwd = process.cwd()) {
|
|
32
|
+
const config = await loadConfig(cwd);
|
|
33
|
+
const selected = selectTarget(config, target);
|
|
34
|
+
assertTargetPolicy(selected, "provision");
|
|
35
|
+
const directory = join(cwd, config.migrations ?? "migrations");
|
|
36
|
+
const migrations = loadMigrations(directory);
|
|
37
|
+
const head = loadHeadSnapshot(directory);
|
|
38
|
+
if (head === undefined) {
|
|
39
|
+
throw new OkmError2("invalid", "There is no head snapshot to provision.", {
|
|
40
|
+
fix: { summary: "Run okm generate before provision." }
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const built = await loadBuiltSchema(cwd, config);
|
|
44
|
+
const report = await applyTarget2({
|
|
45
|
+
url: selected.url,
|
|
46
|
+
target: selected.name,
|
|
47
|
+
protected: selected.protected,
|
|
48
|
+
allowPooler: config.allowPooler === true,
|
|
49
|
+
...backfillTiming2(config.backfill),
|
|
50
|
+
migrations,
|
|
51
|
+
snapshot: {
|
|
52
|
+
catalog: head.catalog,
|
|
53
|
+
migrationId: head.id,
|
|
54
|
+
catalogHash: head.catalogHash,
|
|
55
|
+
reference: readReference(built.tables, built.casing, head.catalog),
|
|
56
|
+
only: true
|
|
57
|
+
},
|
|
58
|
+
...config.roles !== undefined ? { migrationRole: config.roles.migration } : {},
|
|
59
|
+
lintDirectory: directory
|
|
60
|
+
});
|
|
61
|
+
if (report.applied.length === 0)
|
|
62
|
+
return `target ${report.target}
|
|
63
|
+
nothing to apply
|
|
64
|
+
`;
|
|
65
|
+
return `target ${report.target}
|
|
66
|
+
${report.applied.map((id) => `applied ${id}`).join(`
|
|
67
|
+
`)}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
5
70
|
export {
|
|
6
|
-
defineConfig
|
|
71
|
+
defineConfig,
|
|
72
|
+
provision
|
|
7
73
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lint rules for one plan step or one catalog column.
|
|
3
|
+
*
|
|
4
|
+
* A rule reads the statement and the catalogs. It does not connect.
|
|
5
|
+
*/
|
|
6
|
+
import type { Catalog, ColumnObject } from "../../contracts/catalog/types.js";
|
|
7
|
+
import type { PlanStep } from "./plan.js";
|
|
8
|
+
/** Destructive, compatibility, data, locking, or a schema type preference. */
|
|
9
|
+
export type LintCategory = "destructive" | "backward-incompatible" | "data-dependent" | "locking" | "type-preference";
|
|
10
|
+
/** An error blocks plan, check, and apply. A warning is printed and does not. */
|
|
11
|
+
export type LintSeverity = "error" | "warning";
|
|
12
|
+
/** What a step rule can see. Catalogs are the plan's before and after. */
|
|
13
|
+
export type StepInput = {
|
|
14
|
+
readonly step: PlanStep;
|
|
15
|
+
readonly before: Catalog;
|
|
16
|
+
readonly after: Catalog;
|
|
17
|
+
readonly existingTables: ReadonlySet<string>;
|
|
18
|
+
/** Steps before this one. A safe `SET NOT NULL` is recognised from them. */
|
|
19
|
+
readonly earlier: readonly PlanStep[];
|
|
20
|
+
/** Steps after this one. A unique index built for a constraint is recognised from them. */
|
|
21
|
+
readonly later: readonly PlanStep[];
|
|
22
|
+
};
|
|
23
|
+
/** One step rule. `check` returns a reason for each hit, or nothing. */
|
|
24
|
+
export type StepRule = {
|
|
25
|
+
readonly code: string;
|
|
26
|
+
readonly category: Exclude<LintCategory, "type-preference">;
|
|
27
|
+
readonly severity: LintSeverity;
|
|
28
|
+
/** One line for the codes table. */
|
|
29
|
+
readonly doc: string;
|
|
30
|
+
readonly check: (input: StepInput) => readonly string[];
|
|
31
|
+
};
|
|
32
|
+
/** One schema rule. `okm check` runs these on the author catalog. */
|
|
33
|
+
export type ColumnRule = {
|
|
34
|
+
readonly code: string;
|
|
35
|
+
readonly category: "type-preference";
|
|
36
|
+
readonly severity: "warning";
|
|
37
|
+
/** One line for the codes table. */
|
|
38
|
+
readonly doc: string;
|
|
39
|
+
readonly check: (column: ColumnObject) => string | undefined;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Step rules, lowest free code in each category.
|
|
43
|
+
*
|
|
44
|
+
* OKM1534 to OKM1537 are errors when the statement is not the safe form.
|
|
45
|
+
* OKM1538 stays a warning: a rewriting type change has no safe form here.
|
|
46
|
+
*/
|
|
47
|
+
export declare const STEP_RULES: readonly StepRule[];
|
|
48
|
+
/**
|
|
49
|
+
* Type preferences. Warnings, read from the schema catalog by `okm check`.
|
|
50
|
+
*/
|
|
51
|
+
export declare const COLUMN_RULES: readonly ColumnRule[];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs the migration linter.
|
|
3
|
+
*
|
|
4
|
+
* The linter reads a plan and the two catalogs. It does not connect.
|
|
5
|
+
* An override is a `-- okm-allow` line on the statement. It silences only
|
|
6
|
+
* the code it names, and only with a reason.
|
|
7
|
+
*/
|
|
8
|
+
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
9
|
+
import { OkmError } from "../../contracts/error.js";
|
|
10
|
+
import { type LintSeverity } from "./lint-rules.js";
|
|
11
|
+
import { type MigrationPlan } from "./plan.js";
|
|
12
|
+
/** One finding. `place` is `step N` or `table.column`, optionally prefixed with the file. */
|
|
13
|
+
export type Finding = {
|
|
14
|
+
readonly severity: LintSeverity;
|
|
15
|
+
readonly code: string;
|
|
16
|
+
readonly place: string;
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
readonly fix: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Lints every step. Type preferences are {@link lintCatalog}, not here.
|
|
22
|
+
*
|
|
23
|
+
* @param plan - Parsed or planned steps, including `-- okm-allow` lines
|
|
24
|
+
* @param before - Catalog the statements start from
|
|
25
|
+
* @param after - Catalog the statements end on
|
|
26
|
+
* @returns Findings in step order, then code order
|
|
27
|
+
*/
|
|
28
|
+
export declare function lintPlan(plan: MigrationPlan, before: Catalog, after: Catalog): readonly Finding[];
|
|
29
|
+
/**
|
|
30
|
+
* Lints type preferences on the author catalog.
|
|
31
|
+
*
|
|
32
|
+
* @param source - Schema catalog `okm check` loaded
|
|
33
|
+
* @returns One warning per column that prefers another type
|
|
34
|
+
*/
|
|
35
|
+
export declare function lintCatalog(source: Catalog): readonly Finding[];
|
|
36
|
+
/**
|
|
37
|
+
* Lints each SQL file against the previous file's catalog.
|
|
38
|
+
*
|
|
39
|
+
* The walk starts at the first file, against an empty catalog, so a later
|
|
40
|
+
* file sees the catalog the file before it left. The sibling `.catalog.json`
|
|
41
|
+
* is the catalog after that file. When `pending` is passed, only those
|
|
42
|
+
* migration ids contribute findings. The earlier files are still read.
|
|
43
|
+
*
|
|
44
|
+
* @param directory - Migrations directory. Missing means there are none
|
|
45
|
+
* @param pending - Migration ids still to run. Omit to lint every file
|
|
46
|
+
* @returns Findings, each place prefixed with the migration id
|
|
47
|
+
*/
|
|
48
|
+
export declare function lintMigrationDirectory(directory: string, pending?: ReadonlySet<string>): readonly Finding[];
|
|
49
|
+
/**
|
|
50
|
+
* Prints findings one per line, in a form CI can grep.
|
|
51
|
+
*
|
|
52
|
+
* @param findings - Findings from {@link lintPlan} or {@link lintCatalog}
|
|
53
|
+
* @returns The text, or `""` when there are none. A non-empty result ends in a newline
|
|
54
|
+
*/
|
|
55
|
+
export declare function formatFindings(findings: readonly Finding[]): string;
|
|
56
|
+
/**
|
|
57
|
+
* Reports whether any finding is an error.
|
|
58
|
+
*
|
|
59
|
+
* @param findings - Findings to scan
|
|
60
|
+
* @returns `true` when plan, check, or apply must fail
|
|
61
|
+
*/
|
|
62
|
+
export declare function hasError(findings: readonly Finding[]): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* OKM1510 for an unresolved error finding.
|
|
65
|
+
*
|
|
66
|
+
* The message is the finding lines, so the failure text stays greppable.
|
|
67
|
+
*
|
|
68
|
+
* @param findings - Findings that include at least one error
|
|
69
|
+
* @returns The error apply, plan, and check throw before continuing
|
|
70
|
+
*/
|
|
71
|
+
export declare function lintRefusal(findings: readonly Finding[]): OkmError;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tables OKModel owns: `okm_meta`, `okm_history`, and `okm_backfill`.
|
|
3
|
+
*
|
|
4
|
+
* Apply creates them. They are not part of the author schema. Plan, push,
|
|
5
|
+
* check, and doctor omit them on both sides, so a diff neither drops them
|
|
6
|
+
* nor creates them.
|
|
7
|
+
*/
|
|
8
|
+
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Removes the migration history tables and the objects that belong to them.
|
|
11
|
+
*
|
|
12
|
+
* A catalog that has neither is returned as itself.
|
|
13
|
+
*
|
|
14
|
+
* @param source - Catalog about to be diffed or diagnosed
|
|
15
|
+
* @returns The catalog without OKModel's own tables
|
|
16
|
+
*/
|
|
17
|
+
export declare function omitManagedObjects(source: Catalog): Catalog;
|
|
@@ -6,26 +6,81 @@
|
|
|
6
6
|
* OKM1530. The planner never prompts.
|
|
7
7
|
*
|
|
8
8
|
* Picklist and enum removals are expand `UPDATE`s plus a contract swap
|
|
9
|
-
* (D131).
|
|
9
|
+
* (D131). Each data step is a backfill: one idempotent `UPDATE` per batch,
|
|
10
|
+
* with `-- backfill` naming the primary key (D195).
|
|
10
11
|
*/
|
|
11
12
|
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
12
13
|
import type { DeclaredRename } from "../../dialects/pg/declarations.js";
|
|
14
|
+
import { type BackfillSpec } from "./backfill.js";
|
|
15
|
+
import { type MigrationClass, type StepKind } from "./classify.js";
|
|
13
16
|
import { type Replacement } from "./values.js";
|
|
14
|
-
|
|
15
|
-
export type MigrationClass = "expand" | "contract" | "unclassified";
|
|
17
|
+
export type { MigrationClass, StepKind };
|
|
16
18
|
/**
|
|
17
19
|
* One statement in a plan.
|
|
18
20
|
*
|
|
19
|
-
* `backfill` is data
|
|
20
|
-
*
|
|
21
|
-
* VALUE`,
|
|
21
|
+
* `backfill` is data. A step with {@link PlanStep.backfill} is one idempotent
|
|
22
|
+
* `UPDATE` per batch, outside the migration transaction. `transactional: false`
|
|
23
|
+
* also marks a step that cannot share a transaction (`ALTER TYPE … ADD VALUE`,
|
|
24
|
+
* a concurrent index).
|
|
22
25
|
*/
|
|
23
26
|
export type PlanStep = {
|
|
24
27
|
readonly sql: string;
|
|
25
28
|
readonly class: MigrationClass;
|
|
29
|
+
/**
|
|
30
|
+
* Planner operation. Absent on a step built by hand.
|
|
31
|
+
*
|
|
32
|
+
* The class comes from this kind. A statement with no kind and no class
|
|
33
|
+
* comment is `raw-sql`.
|
|
34
|
+
*/
|
|
35
|
+
readonly kind?: StepKind;
|
|
26
36
|
readonly action: "ddl" | "backfill";
|
|
27
37
|
readonly lock: string;
|
|
38
|
+
/**
|
|
39
|
+
* Tables the statement names.
|
|
40
|
+
*
|
|
41
|
+
* Used to look up `pg_class.reltuples` when a plan is printed against a
|
|
42
|
+
* reachable target. {@link formatPlan} does not write this into a file.
|
|
43
|
+
*/
|
|
44
|
+
readonly tables?: readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* Set when the step was emitted by a safe rewrite (D193).
|
|
47
|
+
*
|
|
48
|
+
* Display only. A migration file does not record it.
|
|
49
|
+
*/
|
|
50
|
+
readonly safeRewrite?: true;
|
|
28
51
|
readonly transactional: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Set when the statement is a batched backfill.
|
|
54
|
+
*
|
|
55
|
+
* The header is `table`, `key`, and `batch`. The statement receives `$1`
|
|
56
|
+
* and `$2`. Absent on a data step written without that header.
|
|
57
|
+
*/
|
|
58
|
+
readonly backfill?: BackfillSpec;
|
|
59
|
+
/**
|
|
60
|
+
* Set on an extension upgrade the planner could not check.
|
|
61
|
+
*
|
|
62
|
+
* Apply reads `pg_extension_update_paths` before any statement and refuses
|
|
63
|
+
* a missing path. Offline `okm migrate plan` leaves this unverified.
|
|
64
|
+
*/
|
|
65
|
+
readonly path?: "unverified";
|
|
66
|
+
/**
|
|
67
|
+
* Set on `CREATE OR REPLACE` of a function whose signature did not change.
|
|
68
|
+
*
|
|
69
|
+
* The statement is expand. The flag says the body or the settings changed.
|
|
70
|
+
*/
|
|
71
|
+
readonly behavior?: "change";
|
|
72
|
+
/**
|
|
73
|
+
* `-- okm-allow` lines directly above the statement.
|
|
74
|
+
*
|
|
75
|
+
* A reason silences that code only. An empty reason, or a code the
|
|
76
|
+
* statement did not trigger, is OKM1510 and silences nothing.
|
|
77
|
+
*/
|
|
78
|
+
readonly allows?: readonly StepAllow[];
|
|
79
|
+
};
|
|
80
|
+
/** One `-- okm-allow CODE: reason` line above a statement. */
|
|
81
|
+
export type StepAllow = {
|
|
82
|
+
readonly code: string;
|
|
83
|
+
readonly reason: string;
|
|
29
84
|
};
|
|
30
85
|
/** A named plan and the class of its strictest step. */
|
|
31
86
|
export type MigrationPlan = {
|
|
@@ -42,6 +97,13 @@ export type PlanRequest = {
|
|
|
42
97
|
readonly schema?: string;
|
|
43
98
|
/** Concrete schema written into the SQL. Identities stay logical. */
|
|
44
99
|
readonly name?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Rows per backfill batch written into the step header.
|
|
102
|
+
*
|
|
103
|
+
* Omitted uses the built-in default of 1000. A later apply reads `batch=`
|
|
104
|
+
* from the file, which overrides `defineConfig({ backfill })`.
|
|
105
|
+
*/
|
|
106
|
+
readonly batchSize?: number;
|
|
45
107
|
};
|
|
46
108
|
/**
|
|
47
109
|
* Builds a plan from catalog `before` to catalog `after`.
|
|
@@ -49,14 +111,20 @@ export type PlanRequest = {
|
|
|
49
111
|
* @param request - Catalogs, declared renames, and `--replace` flags
|
|
50
112
|
* @returns Steps in apply order, with one class for the plan
|
|
51
113
|
*/
|
|
52
|
-
export declare function planMigration(
|
|
114
|
+
export declare function planMigration(input: PlanRequest): MigrationPlan;
|
|
53
115
|
/**
|
|
54
|
-
* Prints a plan. The
|
|
116
|
+
* Prints a plan. The header is the strictest class. Each step prints its
|
|
117
|
+
* class and lock. The text is SQL plus those comments, never TypeScript.
|
|
118
|
+
*
|
|
119
|
+
* `okm generate` calls this with no `lockText`, so a file stays free of row
|
|
120
|
+
* estimates. `okm migrate plan` passes `lockText` only after a reachable
|
|
121
|
+
* target has answered.
|
|
55
122
|
*
|
|
56
123
|
* @param plan - Plan from {@link planMigration}
|
|
57
|
-
* @
|
|
124
|
+
* @param lockText - Replaces the lock comment when a target supplied estimates
|
|
125
|
+
* @returns The text `okm generate` writes. `okm migrate plan` uses the same text offline
|
|
58
126
|
*/
|
|
59
|
-
export declare function formatPlan(plan: MigrationPlan): string;
|
|
127
|
+
export declare function formatPlan(plan: MigrationPlan, lockText?: (step: PlanStep) => string): string;
|
|
60
128
|
/**
|
|
61
129
|
* Reads a plan written by {@link formatPlan}.
|
|
62
130
|
*
|
|
@@ -5,9 +5,14 @@
|
|
|
5
5
|
* `.catalog`, which runs that validation. Generate writes SQL only.
|
|
6
6
|
*/
|
|
7
7
|
import { type DeclaredRename } from "../../dialects/pg/declarations.js";
|
|
8
|
+
import type { BuiltSchema } from "../../dialects/pg/schema.js";
|
|
9
|
+
import type { AnyTable } from "../../dialects/pg/table.js";
|
|
8
10
|
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
9
11
|
import { type MigrateConfig } from "./config.js";
|
|
12
|
+
import { type InvokeFlags } from "./policy.js";
|
|
10
13
|
import { type MigrationPlan } from "./plan.js";
|
|
14
|
+
import { type Finding } from "./lint.js";
|
|
15
|
+
type Built = BuiltSchema<readonly AnyTable[]>;
|
|
11
16
|
/**
|
|
12
17
|
* Validates the schema and writes `.okm/`.
|
|
13
18
|
*
|
|
@@ -23,24 +28,47 @@ export declare function buildProject(cwd: string): Promise<string>;
|
|
|
23
28
|
* @param cwd - Project directory
|
|
24
29
|
* @param name - Migration name
|
|
25
30
|
* @param flags - `--replace` values
|
|
26
|
-
* @returns The SQL path, or `undefined` when nothing changed
|
|
31
|
+
* @returns The SQL path and lint findings, or `undefined` when nothing changed
|
|
27
32
|
*/
|
|
28
|
-
export declare function generateProject(cwd: string, name: string, flags: readonly string[]): Promise<
|
|
33
|
+
export declare function generateProject(cwd: string, name: string, flags: readonly string[]): Promise<{
|
|
34
|
+
readonly path: string;
|
|
35
|
+
readonly findings: readonly Finding[];
|
|
36
|
+
} | undefined>;
|
|
29
37
|
/**
|
|
30
38
|
* Plans and returns the text. Nothing is written.
|
|
31
39
|
*
|
|
40
|
+
* When one target is configured, or `--target` names one, and that database
|
|
41
|
+
* answers, the printed lock lines include `pg_class` row estimates. No
|
|
42
|
+
* target, several targets without `--target`, or a target that cannot be
|
|
43
|
+
* reached leaves the text identical to {@link formatPlan}.
|
|
44
|
+
*
|
|
32
45
|
* @param cwd - Project directory
|
|
33
46
|
* @param name - Plan name
|
|
34
47
|
* @param flags - `--replace` values
|
|
35
|
-
* @
|
|
48
|
+
* @param invoke - Target and protection flags, when the command passed them
|
|
49
|
+
* @returns The plan, its lint findings, and the text to print
|
|
36
50
|
*/
|
|
37
|
-
export declare function planProject(cwd: string, name: string, flags: readonly string[]): Promise<
|
|
51
|
+
export declare function planProject(cwd: string, name: string, flags: readonly string[], invoke?: InvokeFlags): Promise<{
|
|
52
|
+
readonly plan: MigrationPlan;
|
|
53
|
+
readonly findings: readonly Finding[];
|
|
54
|
+
readonly text: string;
|
|
55
|
+
}>;
|
|
38
56
|
/**
|
|
39
57
|
* Validates the schema, then reports stale renames and unlisted table files.
|
|
40
58
|
*
|
|
59
|
+
* When exactly one target is configured, or `--target` names one, the
|
|
60
|
+
* read-only `check` and `drift` classes are allowed and a database that
|
|
61
|
+
* already has `okm_meta` is compared with the schema. A difference is
|
|
62
|
+
* OKM1520. Several targets and no `--target` skip that comparison.
|
|
63
|
+
*
|
|
64
|
+
* Lint findings are computed from the plan and the catalog before any
|
|
65
|
+
* connection. An error finding is OKM1510. Warnings are returned.
|
|
66
|
+
*
|
|
41
67
|
* @param cwd - Project directory
|
|
68
|
+
* @param flags - `--target`, when the caller passed one
|
|
69
|
+
* @returns Warning findings. Errors throw
|
|
42
70
|
*/
|
|
43
|
-
export declare function checkProject(cwd: string): Promise<
|
|
71
|
+
export declare function checkProject(cwd: string, flags?: InvokeFlags): Promise<readonly Finding[]>;
|
|
44
72
|
/**
|
|
45
73
|
* Table files whose names do not appear in the schema module.
|
|
46
74
|
*
|
|
@@ -60,6 +88,28 @@ export declare function projectHead(cwd: string): Promise<{
|
|
|
60
88
|
readonly catalog: Catalog;
|
|
61
89
|
readonly renames: readonly DeclaredRename[];
|
|
62
90
|
}>;
|
|
91
|
+
/**
|
|
92
|
+
* Loads the config, the schema, and the previous catalog snapshot.
|
|
93
|
+
*
|
|
94
|
+
* A `renamedFrom` that the previous catalog does not contain is OKM1020.
|
|
95
|
+
*
|
|
96
|
+
* @param cwd - Project directory
|
|
97
|
+
* @returns The loaded project
|
|
98
|
+
*/
|
|
99
|
+
export declare function openProject(cwd: string): Promise<{
|
|
100
|
+
readonly config: MigrateConfig;
|
|
101
|
+
readonly built: Built;
|
|
102
|
+
readonly previous: Catalog;
|
|
103
|
+
readonly renames: readonly DeclaredRename[];
|
|
104
|
+
}>;
|
|
105
|
+
/**
|
|
106
|
+
* Loads the schema named by `config`.
|
|
107
|
+
*
|
|
108
|
+
* @param cwd - Project directory
|
|
109
|
+
* @param config - Project config
|
|
110
|
+
* @returns The built schema, with roles attached when the config declares them
|
|
111
|
+
*/
|
|
112
|
+
export declare function loadBuiltSchema(cwd: string, config: MigrateConfig): Promise<Built>;
|
|
63
113
|
/**
|
|
64
114
|
* Loads `okmodel.config.ts`.
|
|
65
115
|
*
|
|
@@ -67,3 +117,12 @@ export declare function projectHead(cwd: string): Promise<{
|
|
|
67
117
|
* @returns The config object
|
|
68
118
|
*/
|
|
69
119
|
export declare function loadConfig(cwd: string): Promise<MigrateConfig>;
|
|
120
|
+
/**
|
|
121
|
+
* Loads the module named by `spec` and returns the schema it exports.
|
|
122
|
+
*
|
|
123
|
+
* @param cwd - Project directory
|
|
124
|
+
* @param spec - Path from `defineConfig({ schema })`, relative to `cwd`
|
|
125
|
+
* @returns The built schema
|
|
126
|
+
*/
|
|
127
|
+
export declare function loadSchema(cwd: string, spec: string): Promise<Built>;
|
|
128
|
+
export {};
|