@memberjunction/cli 5.37.0 → 5.39.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 +74 -0
- package/dist/baseline/cli-helpers.d.ts +12 -0
- package/dist/baseline/cli-helpers.d.ts.map +1 -0
- package/dist/baseline/cli-helpers.js +40 -0
- package/dist/baseline/cli-helpers.js.map +1 -0
- package/dist/baseline/comparator.d.ts +26 -0
- package/dist/baseline/comparator.d.ts.map +1 -0
- package/dist/baseline/comparator.js +527 -0
- package/dist/baseline/comparator.js.map +1 -0
- package/dist/baseline/connection.d.ts +39 -0
- package/dist/baseline/connection.d.ts.map +1 -0
- package/dist/baseline/connection.js +104 -0
- package/dist/baseline/connection.js.map +1 -0
- package/dist/baseline/data-dumper.d.ts +23 -0
- package/dist/baseline/data-dumper.d.ts.map +1 -0
- package/dist/baseline/data-dumper.js +94 -0
- package/dist/baseline/data-dumper.js.map +1 -0
- package/dist/baseline/emitter.d.ts +36 -0
- package/dist/baseline/emitter.d.ts.map +1 -0
- package/dist/baseline/emitter.js +519 -0
- package/dist/baseline/emitter.js.map +1 -0
- package/dist/baseline/index.d.ts +18 -0
- package/dist/baseline/index.d.ts.map +1 -0
- package/dist/baseline/index.js +14 -0
- package/dist/baseline/index.js.map +1 -0
- package/dist/baseline/introspector-mssql.d.ts +15 -0
- package/dist/baseline/introspector-mssql.d.ts.map +1 -0
- package/dist/baseline/introspector-mssql.js +673 -0
- package/dist/baseline/introspector-mssql.js.map +1 -0
- package/dist/baseline/introspector-postgres.d.ts +14 -0
- package/dist/baseline/introspector-postgres.d.ts.map +1 -0
- package/dist/baseline/introspector-postgres.js +277 -0
- package/dist/baseline/introspector-postgres.js.map +1 -0
- package/dist/baseline/report.d.ts +7 -0
- package/dist/baseline/report.d.ts.map +1 -0
- package/dist/baseline/report.js +105 -0
- package/dist/baseline/report.js.map +1 -0
- package/dist/baseline/types.d.ts +286 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +10 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/baseline/util.d.ts +112 -0
- package/dist/baseline/util.d.ts.map +1 -0
- package/dist/baseline/util.js +325 -0
- package/dist/baseline/util.js.map +1 -0
- package/dist/commands/baseline/build.d.ts +29 -0
- package/dist/commands/baseline/build.d.ts.map +1 -0
- package/dist/commands/baseline/build.js +188 -0
- package/dist/commands/baseline/build.js.map +1 -0
- package/dist/commands/baseline/compare.d.ts +19 -0
- package/dist/commands/baseline/compare.d.ts.map +1 -0
- package/dist/commands/baseline/compare.js +133 -0
- package/dist/commands/baseline/compare.js.map +1 -0
- package/dist/commands/baseline/roundtrip.d.ts +23 -0
- package/dist/commands/baseline/roundtrip.d.ts.map +1 -0
- package/dist/commands/baseline/roundtrip.js +245 -0
- package/dist/commands/baseline/roundtrip.js.map +1 -0
- package/dist/commands/bundle/index.d.ts +21 -0
- package/dist/commands/bundle/index.d.ts.map +1 -0
- package/dist/commands/bundle/index.js +62 -0
- package/dist/commands/bundle/index.js.map +1 -0
- package/dist/commands/migrate/index.d.ts +29 -0
- package/dist/commands/migrate/index.d.ts.map +1 -1
- package/dist/commands/migrate/index.js +111 -5
- package/dist/commands/migrate/index.js.map +1 -1
- package/dist/commands/test/compare.d.ts +3 -0
- package/dist/commands/test/compare.d.ts.map +1 -1
- package/dist/commands/test/compare.js +23 -3
- package/dist/commands/test/compare.js.map +1 -1
- package/dist/commands/test/regression/build.d.ts +14 -0
- package/dist/commands/test/regression/build.d.ts.map +1 -0
- package/dist/commands/test/regression/build.js +48 -0
- package/dist/commands/test/regression/build.js.map +1 -0
- package/dist/commands/test/regression/compare.d.ts +15 -0
- package/dist/commands/test/regression/compare.d.ts.map +1 -0
- package/dist/commands/test/regression/compare.js +66 -0
- package/dist/commands/test/regression/compare.js.map +1 -0
- package/dist/commands/test/regression/down.d.ts +10 -0
- package/dist/commands/test/regression/down.d.ts.map +1 -0
- package/dist/commands/test/regression/down.js +29 -0
- package/dist/commands/test/regression/down.js.map +1 -0
- package/dist/commands/test/regression/export.d.ts +11 -0
- package/dist/commands/test/regression/export.d.ts.map +1 -0
- package/dist/commands/test/regression/export.js +56 -0
- package/dist/commands/test/regression/export.js.map +1 -0
- package/dist/commands/test/regression/gen-forms.d.ts +7 -0
- package/dist/commands/test/regression/gen-forms.d.ts.map +1 -0
- package/dist/commands/test/regression/gen-forms.js +18 -0
- package/dist/commands/test/regression/gen-forms.js.map +1 -0
- package/dist/commands/test/regression/index.d.ts +7 -0
- package/dist/commands/test/regression/index.d.ts.map +1 -0
- package/dist/commands/test/regression/index.js +33 -0
- package/dist/commands/test/regression/index.js.map +1 -0
- package/dist/commands/test/regression/init.d.ts +21 -0
- package/dist/commands/test/regression/init.d.ts.map +1 -0
- package/dist/commands/test/regression/init.js +111 -0
- package/dist/commands/test/regression/init.js.map +1 -0
- package/dist/commands/test/regression/remote.d.ts +23 -0
- package/dist/commands/test/regression/remote.d.ts.map +1 -0
- package/dist/commands/test/regression/remote.js +140 -0
- package/dist/commands/test/regression/remote.js.map +1 -0
- package/dist/commands/test/regression/up.d.ts +21 -0
- package/dist/commands/test/regression/up.d.ts.map +1 -0
- package/dist/commands/test/regression/up.js +111 -0
- package/dist/commands/test/regression/up.js.map +1 -0
- package/dist/commands/test/run.d.ts +1 -0
- package/dist/commands/test/run.d.ts.map +1 -1
- package/dist/commands/test/run.js +6 -0
- package/dist/commands/test/run.js.map +1 -1
- package/dist/commands/test/suite.d.ts +5 -0
- package/dist/commands/test/suite.d.ts.map +1 -1
- package/dist/commands/test/suite.js +27 -0
- package/dist/commands/test/suite.js.map +1 -1
- package/dist/commands/translate-sql/index.d.ts.map +1 -1
- package/dist/commands/translate-sql/index.js +3 -2
- package/dist/commands/translate-sql/index.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -1
- package/dist/init-templates/bring-your-own-app/README.md +74 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/.mj-sync.json +10 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.byo-suite.json +51 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.mj-sync.json +12 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T01-counter-increment.json +63 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T02-contact-form-submit.json +63 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.mj-sync.json +12 -0
- package/dist/init-templates/bring-your-own-app/docker-compose.app.yml +76 -0
- package/dist/init-templates/bring-your-own-app/target.json +23 -0
- package/dist/init-templates/generic-web/README.md +115 -0
- package/dist/init-templates/generic-web/metadata/.mj-sync.json +10 -0
- package/dist/init-templates/generic-web/metadata/test-suites/.generic-web-suite.json +48 -0
- package/dist/init-templates/generic-web/metadata/test-suites/.mj-sync.json +12 -0
- package/dist/init-templates/generic-web/metadata/tests/.GW01-home-loads.json +74 -0
- package/dist/init-templates/generic-web/metadata/tests/.GW02-search-array-map.json +82 -0
- package/dist/init-templates/generic-web/metadata/tests/.mj-sync.json +12 -0
- package/dist/init-templates/generic-web/oracles/mdn-oracles.cjs +121 -0
- package/dist/init-templates/generic-web/target.json +25 -0
- package/dist/init-templates/github-actions/README.md +26 -0
- package/dist/init-templates/github-actions/regression.yml +52 -0
- package/dist/init-templates/remote-mj/README.md +95 -0
- package/dist/init-templates/remote-mj/target.json +22 -0
- package/dist/init-templates/static-file-server/Dockerfile +23 -0
- package/dist/init-templates/static-file-server/README.md +88 -0
- package/dist/init-templates/static-file-server/docker-compose.app.yml +44 -0
- package/dist/init-templates/static-file-server/metadata/.mj-sync.json +10 -0
- package/dist/init-templates/static-file-server/metadata/test-suites/.mj-sync.json +12 -0
- package/dist/init-templates/static-file-server/metadata/test-suites/.static-server-suite.json +27 -0
- package/dist/init-templates/static-file-server/metadata/tests/.SS01-home-loads.json +45 -0
- package/dist/init-templates/static-file-server/metadata/tests/.SS02-navigate-about.json +45 -0
- package/dist/init-templates/static-file-server/metadata/tests/.mj-sync.json +12 -0
- package/dist/init-templates/static-file-server/public/about.html +12 -0
- package/dist/init-templates/static-file-server/public/index.html +27 -0
- package/dist/init-templates/static-file-server/target.json +16 -0
- package/dist/lib/db-preflight.d.ts +42 -0
- package/dist/lib/db-preflight.d.ts.map +1 -0
- package/dist/lib/db-preflight.js +113 -0
- package/dist/lib/db-preflight.js.map +1 -0
- package/dist/lib/db-version.d.ts +36 -0
- package/dist/lib/db-version.d.ts.map +1 -0
- package/dist/lib/db-version.js +45 -0
- package/dist/lib/db-version.js.map +1 -0
- package/dist/lib/migration-fetch.d.ts +49 -0
- package/dist/lib/migration-fetch.d.ts.map +1 -0
- package/dist/lib/migration-fetch.js +152 -0
- package/dist/lib/migration-fetch.js.map +1 -0
- package/dist/lib/regression/docker-helpers.d.ts +98 -0
- package/dist/lib/regression/docker-helpers.d.ts.map +1 -0
- package/dist/lib/regression/docker-helpers.js +184 -0
- package/dist/lib/regression/docker-helpers.js.map +1 -0
- package/dist/light-commands.d.ts.map +1 -1
- package/dist/light-commands.js +2 -0
- package/dist/light-commands.js.map +1 -1
- package/oclif.manifest.json +1635 -702
- package/package.json +22 -17
- package/regression-compose/docker-compose.bacpac-standalone.yml +109 -0
- package/regression-compose/docker-compose.standalone.yml +50 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the highest migration version already applied to the target database from
|
|
3
|
+
* Skyway's history table.
|
|
4
|
+
*
|
|
5
|
+
* Returns `null` when there is no history (a fresh database) — which tells the fetch
|
|
6
|
+
* layer to use `baseline + tail`. A non-null version means "existing database, upgrade
|
|
7
|
+
* from here", so the fetch returns only the versioned migrations after it (no baseline,
|
|
8
|
+
* which Skyway never applies to a database that already has history).
|
|
9
|
+
*
|
|
10
|
+
* @module lib/db-version
|
|
11
|
+
*/
|
|
12
|
+
/** Minimal shape of a Skyway history record we read (the real record carries more fields). */
|
|
13
|
+
interface HistoryRecordLike {
|
|
14
|
+
Version: string | null;
|
|
15
|
+
Type: string;
|
|
16
|
+
Success?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Minimal shape of the Skyway provider we use to read history (structurally compatible with the real one). */
|
|
19
|
+
export interface MigrationHistoryProvider {
|
|
20
|
+
Connect(): Promise<void>;
|
|
21
|
+
Disconnect(): Promise<void>;
|
|
22
|
+
History: {
|
|
23
|
+
Exists(schema: string, tableName: string): Promise<boolean>;
|
|
24
|
+
GetAllRecords(schema: string, tableName: string): Promise<readonly HistoryRecordLike[]>;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* SIDE EFFECTS: connects to the database to read the history table, then disconnects
|
|
29
|
+
* (on every exit path).
|
|
30
|
+
*
|
|
31
|
+
* @returns the highest applied version (Skyway's `<timestamp>` key), or `null` if the
|
|
32
|
+
* history table does not exist yet (fresh database).
|
|
33
|
+
*/
|
|
34
|
+
export declare function readCurrentDbVersion(provider: MigrationHistoryProvider, schema: string, historyTable: string): Promise<string | null>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=db-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-version.d.ts","sourceRoot":"","sources":["../../src/lib/db-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,8FAA8F;AAC9F,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,+GAA+G;AAC/G,MAAM,WAAW,wBAAwB;IACvC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE;QACP,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5D,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC;KACzF,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW3I"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the highest migration version already applied to the target database from
|
|
3
|
+
* Skyway's history table.
|
|
4
|
+
*
|
|
5
|
+
* Returns `null` when there is no history (a fresh database) — which tells the fetch
|
|
6
|
+
* layer to use `baseline + tail`. A non-null version means "existing database, upgrade
|
|
7
|
+
* from here", so the fetch returns only the versioned migrations after it (no baseline,
|
|
8
|
+
* which Skyway never applies to a database that already has history).
|
|
9
|
+
*
|
|
10
|
+
* @module lib/db-version
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* SIDE EFFECTS: connects to the database to read the history table, then disconnects
|
|
14
|
+
* (on every exit path).
|
|
15
|
+
*
|
|
16
|
+
* @returns the highest applied version (Skyway's `<timestamp>` key), or `null` if the
|
|
17
|
+
* history table does not exist yet (fresh database).
|
|
18
|
+
*/
|
|
19
|
+
export async function readCurrentDbVersion(provider, schema, historyTable) {
|
|
20
|
+
await provider.Connect();
|
|
21
|
+
try {
|
|
22
|
+
if (!(await provider.History.Exists(schema, historyTable))) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const records = await provider.History.GetAllRecords(schema, historyTable);
|
|
26
|
+
return highestAppliedVersion(records);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await provider.Disconnect();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Highest successful, non-schema-marker version among history records (mirrors Skyway's own rule). */
|
|
33
|
+
function highestAppliedVersion(records) {
|
|
34
|
+
let highest = null;
|
|
35
|
+
for (const record of records) {
|
|
36
|
+
if (record.Version === null || record.Type === 'SCHEMA' || record.Success === false) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (highest === null || record.Version > highest) {
|
|
40
|
+
highest = record.Version;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return highest;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=db-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-version.js","sourceRoot":"","sources":["../../src/lib/db-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,QAAkC,EAAE,MAAc,EAAE,YAAoB;IACjH,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3E,OAAO,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;YAAS,CAAC;QACT,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,uGAAuG;AACvG,SAAS,qBAAqB,CAAC,OAAqC;IAClE,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YACpF,SAAS;QACX,CAAC;QACD,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,GAAG,OAAO,EAAE,CAAC;YACjD,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type MigrationDialect = 'sqlserver' | 'postgresql';
|
|
2
|
+
export interface MigrationFetchResult {
|
|
3
|
+
/** Temp clone root to hand to Skyway as the migration location. */
|
|
4
|
+
dir: string;
|
|
5
|
+
/** Repo-relative migration paths checked out (empty when the full-history fallback was used). */
|
|
6
|
+
selected: string[];
|
|
7
|
+
/** True when partial clone was unavailable and the full `migrations/` dir was fetched instead. */
|
|
8
|
+
usedFallback: boolean;
|
|
9
|
+
/** Removes the temp clone. Callers MUST invoke this in a finally on every exit path. */
|
|
10
|
+
cleanup: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolves a user-supplied tag/branch into a git ref.
|
|
14
|
+
* A semantic version (`2.123.0` / `v2.123.0`) maps to the `vX.Y.Z` release tag;
|
|
15
|
+
* anything else (e.g. `main`) is treated as a branch name unchanged.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveGitRef(tagOrBranch: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Pure selector: given the repo-relative migration paths present at a ref, return
|
|
20
|
+
* the minimal slice Skyway needs. Repeatable migrations are always included.
|
|
21
|
+
*
|
|
22
|
+
* Two modes, keyed on `currentVersion` (the highest migration already applied to the
|
|
23
|
+
* target database, or `null` for a fresh one):
|
|
24
|
+
*
|
|
25
|
+
* - **Fresh install** (`currentVersion == null`): `baseline + tail` — the highest `B`
|
|
26
|
+
* baseline plus every `V` after it. Skyway applies the baseline (consolidated schema)
|
|
27
|
+
* then the tail. This is the bandwidth-optimal path for a brand-new database.
|
|
28
|
+
* - **Existing-DB upgrade** (`currentVersion` set): every `V` strictly after the current
|
|
29
|
+
* version, with **no baseline**. Skyway never applies a `B` file to a database that
|
|
30
|
+
* already has history, and the baseline floor would wrongly skip the intermediate
|
|
31
|
+
* versioned migrations the DB still needs (e.g. a v5.36 file below a v5.37 baseline
|
|
32
|
+
* when upgrading a v5.35 database).
|
|
33
|
+
*
|
|
34
|
+
* With no baseline present (e.g. legacy v2) the fresh path returns the full versioned history.
|
|
35
|
+
*/
|
|
36
|
+
export declare function selectMigrationSlice(paths: readonly string[], currentVersion?: string | null): string[];
|
|
37
|
+
/**
|
|
38
|
+
* SIDE EFFECTS: clones from `repoUrl` over the network into a temp dir and checks out
|
|
39
|
+
* only the selected migration slice. Returns the temp dir plus a `cleanup` the caller
|
|
40
|
+
* MUST run in a finally. On any internal failure the temp dir is removed before throwing.
|
|
41
|
+
*/
|
|
42
|
+
export declare function fetchMigrationSlice(opts: {
|
|
43
|
+
repoUrl: string;
|
|
44
|
+
ref: string;
|
|
45
|
+
dialect: MigrationDialect;
|
|
46
|
+
/** Highest version already applied to the target DB; `null`/omitted = fresh install (baseline + tail). */
|
|
47
|
+
currentVersion?: string | null;
|
|
48
|
+
}): Promise<MigrationFetchResult>;
|
|
49
|
+
//# sourceMappingURL=migration-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-fetch.d.ts","sourceRoot":"","sources":["../../src/lib/migration-fetch.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,YAAY,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAC;IACZ,iGAAiG;IACjG,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kGAAkG;IAClG,YAAY,EAAE,OAAO,CAAC;IACtB,wFAAwF;IACxF,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAcvG;AA4BD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,gBAAgB,CAAC;IAC1B,0GAA0G;IAC1G,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA2BhC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module lib/migration-fetch
|
|
3
|
+
*
|
|
4
|
+
* Fetches the *minimal* slice of migration files needed to bring a database to a
|
|
5
|
+
* target version, instead of cloning the entire `migrations/` history.
|
|
6
|
+
*
|
|
7
|
+
* The selection depends on whether the target database is fresh or existing, because
|
|
8
|
+
* Skyway only ever applies baselines to a fresh (no-history) database:
|
|
9
|
+
*
|
|
10
|
+
* fresh install → [ highest `B` baseline ] + [ every `V` after it ] + [ all `R` repeatables ]
|
|
11
|
+
* existing upgrade → [ every `V` after the DB's current version ] + [ all `R` repeatables ] (no baseline)
|
|
12
|
+
*
|
|
13
|
+
* The existing-upgrade path is what makes incremental upgrades correct: a baseline floor
|
|
14
|
+
* would skip the intermediate versioned migrations a behind-the-baseline DB still needs.
|
|
15
|
+
* The git ref bounds the top of the range (only migrations at/below the target are in the
|
|
16
|
+
* tree). Selection uses the numeric `<timestamp>` filename token — Skyway's version key —
|
|
17
|
+
* via the shared {@link parseMigrationFilename}.
|
|
18
|
+
*/
|
|
19
|
+
import { mkdtempSync } from 'node:fs';
|
|
20
|
+
import { rm } from 'node:fs/promises';
|
|
21
|
+
import { tmpdir } from 'node:os';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import { parseMigrationFilename } from '../baseline/util.js';
|
|
24
|
+
/** Matches Flyway/Skyway repeatable migrations (`R__<desc>.sql`), which always run. */
|
|
25
|
+
const REPEATABLE_PATTERN = /^R__.+\.sql$/i;
|
|
26
|
+
/**
|
|
27
|
+
* Resolves a user-supplied tag/branch into a git ref.
|
|
28
|
+
* A semantic version (`2.123.0` / `v2.123.0`) maps to the `vX.Y.Z` release tag;
|
|
29
|
+
* anything else (e.g. `main`) is treated as a branch name unchanged.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveGitRef(tagOrBranch) {
|
|
32
|
+
const isSemver = /^v?\d+\.\d+\.\d+$/.test(tagOrBranch);
|
|
33
|
+
if (!isSemver)
|
|
34
|
+
return tagOrBranch;
|
|
35
|
+
return tagOrBranch.startsWith('v') ? tagOrBranch : `v${tagOrBranch}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pure selector: given the repo-relative migration paths present at a ref, return
|
|
39
|
+
* the minimal slice Skyway needs. Repeatable migrations are always included.
|
|
40
|
+
*
|
|
41
|
+
* Two modes, keyed on `currentVersion` (the highest migration already applied to the
|
|
42
|
+
* target database, or `null` for a fresh one):
|
|
43
|
+
*
|
|
44
|
+
* - **Fresh install** (`currentVersion == null`): `baseline + tail` — the highest `B`
|
|
45
|
+
* baseline plus every `V` after it. Skyway applies the baseline (consolidated schema)
|
|
46
|
+
* then the tail. This is the bandwidth-optimal path for a brand-new database.
|
|
47
|
+
* - **Existing-DB upgrade** (`currentVersion` set): every `V` strictly after the current
|
|
48
|
+
* version, with **no baseline**. Skyway never applies a `B` file to a database that
|
|
49
|
+
* already has history, and the baseline floor would wrongly skip the intermediate
|
|
50
|
+
* versioned migrations the DB still needs (e.g. a v5.36 file below a v5.37 baseline
|
|
51
|
+
* when upgrading a v5.35 database).
|
|
52
|
+
*
|
|
53
|
+
* With no baseline present (e.g. legacy v2) the fresh path returns the full versioned history.
|
|
54
|
+
*/
|
|
55
|
+
export function selectMigrationSlice(paths, currentVersion) {
|
|
56
|
+
const sqlPaths = paths.filter((p) => p.toLowerCase().endsWith('.sql'));
|
|
57
|
+
const repeatables = sqlPaths.filter((p) => REPEATABLE_PATTERN.test(path.basename(p)));
|
|
58
|
+
if (currentVersion != null) {
|
|
59
|
+
// Existing DB: upgrade with versioned migrations after the current version only.
|
|
60
|
+
const versioned = sqlPaths.filter((p) => isVersionedAfter(p, currentVersion));
|
|
61
|
+
return Array.from(new Set([...versioned, ...repeatables]));
|
|
62
|
+
}
|
|
63
|
+
// Fresh DB: baseline + everything after it.
|
|
64
|
+
const floorTimestamp = highestBaselineTimestamp(sqlPaths);
|
|
65
|
+
const versioned = sqlPaths.filter((p) => isInVersionedSlice(p, floorTimestamp));
|
|
66
|
+
return Array.from(new Set([...versioned, ...repeatables]));
|
|
67
|
+
}
|
|
68
|
+
/** True if `filePath` is a versioned (`V`) migration whose timestamp is strictly after `currentVersion`. */
|
|
69
|
+
function isVersionedAfter(filePath, currentVersion) {
|
|
70
|
+
const parsed = parseMigrationFilename(path.basename(filePath));
|
|
71
|
+
return parsed?.kind === 'V' && parsed.timestamp > currentVersion;
|
|
72
|
+
}
|
|
73
|
+
/** Returns the timestamp of the latest `B` baseline among the paths, or null if none. */
|
|
74
|
+
function highestBaselineTimestamp(sqlPaths) {
|
|
75
|
+
let floor = null;
|
|
76
|
+
for (const p of sqlPaths) {
|
|
77
|
+
const parsed = parseMigrationFilename(path.basename(p));
|
|
78
|
+
if (!parsed || parsed.kind !== 'B')
|
|
79
|
+
continue;
|
|
80
|
+
if (floor === null || parsed.timestamp > floor)
|
|
81
|
+
floor = parsed.timestamp;
|
|
82
|
+
}
|
|
83
|
+
return floor;
|
|
84
|
+
}
|
|
85
|
+
/** True if a versioned/baseline path belongs in the slice given the baseline floor. */
|
|
86
|
+
function isInVersionedSlice(filePath, floorTimestamp) {
|
|
87
|
+
const parsed = parseMigrationFilename(path.basename(filePath));
|
|
88
|
+
if (!parsed)
|
|
89
|
+
return false; // repeatables and non-migration files handled elsewhere
|
|
90
|
+
if (floorTimestamp === null)
|
|
91
|
+
return parsed.kind === 'V'; // no baseline → all versioned
|
|
92
|
+
if (parsed.kind === 'B')
|
|
93
|
+
return parsed.timestamp === floorTimestamp; // only the floor baseline
|
|
94
|
+
return parsed.timestamp > floorTimestamp; // versioned migrations strictly after the baseline
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* SIDE EFFECTS: clones from `repoUrl` over the network into a temp dir and checks out
|
|
98
|
+
* only the selected migration slice. Returns the temp dir plus a `cleanup` the caller
|
|
99
|
+
* MUST run in a finally. On any internal failure the temp dir is removed before throwing.
|
|
100
|
+
*/
|
|
101
|
+
export async function fetchMigrationSlice(opts) {
|
|
102
|
+
const migrationsRoot = opts.dialect === 'postgresql' ? 'migrations-pg' : 'migrations';
|
|
103
|
+
const dir = mkdtempSync(path.join(tmpdir(), 'mj-migrations-'));
|
|
104
|
+
const cleanup = async () => {
|
|
105
|
+
await rm(dir, { recursive: true, force: true });
|
|
106
|
+
};
|
|
107
|
+
try {
|
|
108
|
+
// Deferred load: the pure selector (selectMigrationSlice/resolveGitRef) carries no
|
|
109
|
+
// runtime dependency on simple-git — only an actual fetch pulls it in.
|
|
110
|
+
const { simpleGit } = await import('simple-git');
|
|
111
|
+
const git = simpleGit(dir);
|
|
112
|
+
const partialOk = await tryPartialClone(git, opts.repoUrl, opts.ref, dir);
|
|
113
|
+
if (!partialOk) {
|
|
114
|
+
await fullSparseClone(git, opts.repoUrl, opts.ref, dir, migrationsRoot);
|
|
115
|
+
return { dir, selected: [], usedFallback: true, cleanup };
|
|
116
|
+
}
|
|
117
|
+
const allPaths = await listTreePaths(git, migrationsRoot);
|
|
118
|
+
const selected = selectMigrationSlice(allPaths, opts.currentVersion);
|
|
119
|
+
const checkoutTargets = selected.length > 0 ? selected : [migrationsRoot];
|
|
120
|
+
await git.raw(['sparse-checkout', 'set', '--no-cone', ...checkoutTargets]);
|
|
121
|
+
await git.raw(['checkout']);
|
|
122
|
+
return { dir, selected, usedFallback: false, cleanup };
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
await cleanup();
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Attempts a blobless, no-checkout shallow clone. Returns false if the server/git rejects the filter. */
|
|
130
|
+
async function tryPartialClone(git, repoUrl, ref, dir) {
|
|
131
|
+
try {
|
|
132
|
+
await git.clone(repoUrl, dir, ['--no-checkout', '--filter=blob:none', '--depth=1', '--branch', ref]);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return false; // caller falls back to a full sparse clone
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Fallback path: full shallow sparse clone of the whole migrations dir (today's behavior). */
|
|
140
|
+
async function fullSparseClone(git, repoUrl, ref, dir, migrationsRoot) {
|
|
141
|
+
await git.clone(repoUrl, dir, ['--sparse', '--depth=1', '--branch', ref]);
|
|
142
|
+
await git.raw(['sparse-checkout', 'set', migrationsRoot]);
|
|
143
|
+
}
|
|
144
|
+
/** Lists repo-relative file paths under `migrationsRoot` at HEAD without downloading blobs. */
|
|
145
|
+
async function listTreePaths(git, migrationsRoot) {
|
|
146
|
+
const out = await git.raw(['ls-tree', '-r', '--name-only', 'HEAD', '--', migrationsRoot]);
|
|
147
|
+
return out
|
|
148
|
+
.split('\n')
|
|
149
|
+
.map((line) => line.trim())
|
|
150
|
+
.filter((line) => line.length > 0);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=migration-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-fetch.js","sourceRoot":"","sources":["../../src/lib/migration-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for `mj test regression *` subcommands.
|
|
3
|
+
*
|
|
4
|
+
* The CLI commands themselves are thin oclif wrappers — they just spawn
|
|
5
|
+
* `docker compose` / `bash` with the right flags. All the wiring (path
|
|
6
|
+
* resolution, profile selection, error reporting) lives here so the same
|
|
7
|
+
* conventions apply across every subcommand.
|
|
8
|
+
*/
|
|
9
|
+
import { type SpawnOptions } from 'node:child_process';
|
|
10
|
+
export declare const REGRESSION_DIR = "docker/regression";
|
|
11
|
+
export declare const COMPOSE_FILE = "docker/regression/docker-compose.test.yml";
|
|
12
|
+
export declare const BACPAC_OVERLAY = "docker/regression/docker-compose.bacpac.yml";
|
|
13
|
+
export declare const STANDALONE_COMPOSE = "docker/regression/docker-compose.standalone.yml";
|
|
14
|
+
export declare const BACPAC_STANDALONE_COMPOSE = "docker/regression/docker-compose.bacpac-standalone.yml";
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a standalone compose file. Prefers the monorepo copy (cwd-relative
|
|
17
|
+
* `docker/regression/<name>`); falls back to the copy bundled into this CLI
|
|
18
|
+
* package at build time (`<pkg>/regression-compose/<name>`) so external users
|
|
19
|
+
* who only `npm i -g @memberjunction/cli` still have it. Returns the first path
|
|
20
|
+
* that exists, or the bundled path (so the caller can surface a clear error).
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveStandaloneCompose(monorepoRelPath: string): string;
|
|
23
|
+
export declare const ENV_FILE = "docker/regression/.env.test";
|
|
24
|
+
export declare const TARGETS_DIR = "docker/regression/targets";
|
|
25
|
+
export declare const LOAD_TARGET_SCRIPT = "docker/regression/scripts/load-target-profile.cjs";
|
|
26
|
+
export declare const GEN_FORMS_SCRIPT = "docker/regression/gen-forms.sh";
|
|
27
|
+
export declare const RESULTS_DIR = "docker/regression/test-results";
|
|
28
|
+
export declare const INLINE_REPORT_SCRIPT = "docker/regression/scripts/inline-report.cjs";
|
|
29
|
+
/**
|
|
30
|
+
* The pinned runner image tag used when `init` (and future external invocations)
|
|
31
|
+
* shell out to `docker run memberjunction/agentic-test-runner …`. Kept here so
|
|
32
|
+
* a single bump updates every CLI command that consumes the image. The
|
|
33
|
+
* version is pinned to the most recent release that includes Phase 8.
|
|
34
|
+
*/
|
|
35
|
+
export declare const AGENTIC_TEST_RUNNER_IMAGE = "memberjunction/agentic-test-runner:latest";
|
|
36
|
+
/**
|
|
37
|
+
* Verify the current working directory is the MJ monorepo root. If it isn't,
|
|
38
|
+
* print a helpful message and exit. Phase 4 still requires the user to be in
|
|
39
|
+
* the monorepo; Phase 8 will publish the docker image and lift this guard.
|
|
40
|
+
*/
|
|
41
|
+
export declare function requireMonorepoRoot(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Soft check — returns true when there's an MJ monorepo at-or-above cwd.
|
|
44
|
+
* Used by commands (compare, up, export, remote) to pick monorepo-relative
|
|
45
|
+
* paths over external/published-image paths. Unlike `requireMonorepoRoot()`,
|
|
46
|
+
* this does NOT exit on failure.
|
|
47
|
+
*
|
|
48
|
+
* The sentinel is the regression base compose file: it lives in every
|
|
49
|
+
* monorepo checkout and is never present in an external `npm i -g` install.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isInsideMonorepo(startDir?: string): boolean;
|
|
52
|
+
/** Returns true when `<cwd>/<ENV_FILE>` exists (e.g. user copied .env.test.example). */
|
|
53
|
+
export declare function envFileExists(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Spawn a child process inheriting stdio. Resolves with the exit code.
|
|
56
|
+
* The promise NEVER rejects on a non-zero exit code — callers inspect the
|
|
57
|
+
* resolved number and propagate it to the user.
|
|
58
|
+
*/
|
|
59
|
+
export declare function spawnInherit(command: string, args: string[], options?: SpawnOptions): Promise<number>;
|
|
60
|
+
/**
|
|
61
|
+
* Capture stdout from a child process (stderr inherited so errors surface).
|
|
62
|
+
* Resolves with { code, stdout }. Used by the remote subcommand to read the
|
|
63
|
+
* target-profile loader's JSON output without printing it to the user.
|
|
64
|
+
*/
|
|
65
|
+
export declare function spawnCapture(command: string, args: string[], options?: SpawnOptions): Promise<{
|
|
66
|
+
code: number;
|
|
67
|
+
stdout: string;
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Build the base `docker compose -f <file> --env-file <file>` argument list.
|
|
71
|
+
* Optionally prepends a profile and additional overlay files (Mode D).
|
|
72
|
+
*
|
|
73
|
+
* Overlays are passed as additional `-f` flags AFTER the base compose file —
|
|
74
|
+
* compose merges them in order, so later overlays override earlier ones.
|
|
75
|
+
* Relative paths inside an overlay resolve against the FIRST `-f` file's
|
|
76
|
+
* directory (the base compose file at `docker/regression/`), NOT against the
|
|
77
|
+
* overlay's own location.
|
|
78
|
+
*/
|
|
79
|
+
export declare function dockerComposeArgs(profile?: string, extra?: string[], overlays?: string[]): string[];
|
|
80
|
+
/**
|
|
81
|
+
* Resolve a target-profile argument to an absolute path. Accepts:
|
|
82
|
+
* - "staging-mj" → docker/regression/targets/staging-mj.target.json
|
|
83
|
+
* - "staging-mj.target.json" → docker/regression/targets/staging-mj.target.json
|
|
84
|
+
* - "./my/elsewhere.target.json" → ./my/elsewhere.target.json (passthrough)
|
|
85
|
+
* - absolute path → unchanged
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveTargetPath(input: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* Build a `docker run …` argument list for the published image (external,
|
|
90
|
+
* no-monorepo path). Mounts are [hostPath, containerPath] pairs; envFile is
|
|
91
|
+
* injected with `--env-file`; `host.docker.internal` is always mapped so a DB
|
|
92
|
+
* published on the host is reachable on Linux too.
|
|
93
|
+
*/
|
|
94
|
+
export declare function dockerRunArgs(image: string, subArgs: string[], opts?: {
|
|
95
|
+
mounts?: Array<[string, string]>;
|
|
96
|
+
envFile?: string;
|
|
97
|
+
}): string[];
|
|
98
|
+
//# sourceMappingURL=docker-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/regression/docker-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK9D,eAAO,MAAM,cAAc,sBAAsB,CAAC;AAClD,eAAO,MAAM,YAAY,8CAA8C,CAAC;AACxE,eAAO,MAAM,cAAc,gDAAgD,CAAC;AAC5E,eAAO,MAAM,kBAAkB,oDAAoD,CAAC;AACpF,eAAO,MAAM,yBAAyB,2DAA2D,CAAC;AASlG;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAKxE;AACD,eAAO,MAAM,QAAQ,gCAAgC,CAAC;AACtD,eAAO,MAAM,WAAW,8BAA8B,CAAC;AACvD,eAAO,MAAM,kBAAkB,sDAAsD,CAAC;AACtF,eAAO,MAAM,gBAAgB,mCAAmC,CAAC;AACjE,eAAO,MAAM,WAAW,mCAAmC,CAAC;AAC5D,eAAO,MAAM,oBAAoB,gDAAgD,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,8CAA8C,CAAC;AAErF;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAU1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAQ1E;AAED,wFAAwF;AACxF,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAiB3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,GAAE,MAAM,EAAO,EACpB,QAAQ,GAAE,MAAM,EAAO,GACtB,MAAM,EAAE,CAYV;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,MAAM,EAAE,CAUV"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for `mj test regression *` subcommands.
|
|
3
|
+
*
|
|
4
|
+
* The CLI commands themselves are thin oclif wrappers — they just spawn
|
|
5
|
+
* `docker compose` / `bash` with the right flags. All the wiring (path
|
|
6
|
+
* resolution, profile selection, error reporting) lives here so the same
|
|
7
|
+
* conventions apply across every subcommand.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process';
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
export const REGRESSION_DIR = 'docker/regression';
|
|
14
|
+
export const COMPOSE_FILE = `${REGRESSION_DIR}/docker-compose.test.yml`;
|
|
15
|
+
export const BACPAC_OVERLAY = `${REGRESSION_DIR}/docker-compose.bacpac.yml`;
|
|
16
|
+
export const STANDALONE_COMPOSE = `${REGRESSION_DIR}/docker-compose.standalone.yml`;
|
|
17
|
+
export const BACPAC_STANDALONE_COMPOSE = `${REGRESSION_DIR}/docker-compose.bacpac-standalone.yml`;
|
|
18
|
+
/**
|
|
19
|
+
* Package root of @memberjunction/cli (resolved from this compiled module at
|
|
20
|
+
* dist/lib/regression/docker-helpers.js → up 3). Used to locate compose assets
|
|
21
|
+
* bundled into the published package for external (no-monorepo) use.
|
|
22
|
+
*/
|
|
23
|
+
const PKG_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a standalone compose file. Prefers the monorepo copy (cwd-relative
|
|
26
|
+
* `docker/regression/<name>`); falls back to the copy bundled into this CLI
|
|
27
|
+
* package at build time (`<pkg>/regression-compose/<name>`) so external users
|
|
28
|
+
* who only `npm i -g @memberjunction/cli` still have it. Returns the first path
|
|
29
|
+
* that exists, or the bundled path (so the caller can surface a clear error).
|
|
30
|
+
*/
|
|
31
|
+
export function resolveStandaloneCompose(monorepoRelPath) {
|
|
32
|
+
const monorepo = path.resolve(monorepoRelPath);
|
|
33
|
+
if (existsSync(monorepo))
|
|
34
|
+
return monorepo;
|
|
35
|
+
const bundled = path.join(PKG_ROOT, 'regression-compose', path.basename(monorepoRelPath));
|
|
36
|
+
return existsSync(bundled) ? bundled : monorepo;
|
|
37
|
+
}
|
|
38
|
+
export const ENV_FILE = `${REGRESSION_DIR}/.env.test`;
|
|
39
|
+
export const TARGETS_DIR = `${REGRESSION_DIR}/targets`;
|
|
40
|
+
export const LOAD_TARGET_SCRIPT = `${REGRESSION_DIR}/scripts/load-target-profile.cjs`;
|
|
41
|
+
export const GEN_FORMS_SCRIPT = `${REGRESSION_DIR}/gen-forms.sh`;
|
|
42
|
+
export const RESULTS_DIR = `${REGRESSION_DIR}/test-results`;
|
|
43
|
+
export const INLINE_REPORT_SCRIPT = `${REGRESSION_DIR}/scripts/inline-report.cjs`;
|
|
44
|
+
/**
|
|
45
|
+
* The pinned runner image tag used when `init` (and future external invocations)
|
|
46
|
+
* shell out to `docker run memberjunction/agentic-test-runner …`. Kept here so
|
|
47
|
+
* a single bump updates every CLI command that consumes the image. The
|
|
48
|
+
* version is pinned to the most recent release that includes Phase 8.
|
|
49
|
+
*/
|
|
50
|
+
export const AGENTIC_TEST_RUNNER_IMAGE = 'memberjunction/agentic-test-runner:latest';
|
|
51
|
+
/**
|
|
52
|
+
* Verify the current working directory is the MJ monorepo root. If it isn't,
|
|
53
|
+
* print a helpful message and exit. Phase 4 still requires the user to be in
|
|
54
|
+
* the monorepo; Phase 8 will publish the docker image and lift this guard.
|
|
55
|
+
*/
|
|
56
|
+
export function requireMonorepoRoot() {
|
|
57
|
+
if (!existsSync(COMPOSE_FILE)) {
|
|
58
|
+
process.stderr.write(`✗ Expected to find ${COMPOSE_FILE} relative to the current directory.\n` +
|
|
59
|
+
` 'mj test regression *' commands must be run from the MemberJunction\n` +
|
|
60
|
+
` monorepo root. (Phase 8 will lift this requirement by publishing the\n` +
|
|
61
|
+
` test-runner image; for now, cd into the MJ repo first.)\n`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Soft check — returns true when there's an MJ monorepo at-or-above cwd.
|
|
67
|
+
* Used by commands (compare, up, export, remote) to pick monorepo-relative
|
|
68
|
+
* paths over external/published-image paths. Unlike `requireMonorepoRoot()`,
|
|
69
|
+
* this does NOT exit on failure.
|
|
70
|
+
*
|
|
71
|
+
* The sentinel is the regression base compose file: it lives in every
|
|
72
|
+
* monorepo checkout and is never present in an external `npm i -g` install.
|
|
73
|
+
*/
|
|
74
|
+
export function isInsideMonorepo(startDir = process.cwd()) {
|
|
75
|
+
let dir = path.resolve(startDir);
|
|
76
|
+
const root = path.parse(dir).root;
|
|
77
|
+
while (dir !== root) {
|
|
78
|
+
if (existsSync(path.join(dir, COMPOSE_FILE)))
|
|
79
|
+
return true;
|
|
80
|
+
dir = path.dirname(dir);
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
/** Returns true when `<cwd>/<ENV_FILE>` exists (e.g. user copied .env.test.example). */
|
|
85
|
+
export function envFileExists() {
|
|
86
|
+
return existsSync(ENV_FILE);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Spawn a child process inheriting stdio. Resolves with the exit code.
|
|
90
|
+
* The promise NEVER rejects on a non-zero exit code — callers inspect the
|
|
91
|
+
* resolved number and propagate it to the user.
|
|
92
|
+
*/
|
|
93
|
+
export function spawnInherit(command, args, options = {}) {
|
|
94
|
+
return new Promise((resolve) => {
|
|
95
|
+
const child = spawn(command, args, {
|
|
96
|
+
stdio: 'inherit',
|
|
97
|
+
...options,
|
|
98
|
+
});
|
|
99
|
+
child.on('exit', (code) => resolve(code ?? 1));
|
|
100
|
+
child.on('error', (err) => {
|
|
101
|
+
process.stderr.write(`✗ failed to spawn ${command}: ${err.message}\n`);
|
|
102
|
+
resolve(1);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Capture stdout from a child process (stderr inherited so errors surface).
|
|
108
|
+
* Resolves with { code, stdout }. Used by the remote subcommand to read the
|
|
109
|
+
* target-profile loader's JSON output without printing it to the user.
|
|
110
|
+
*/
|
|
111
|
+
export function spawnCapture(command, args, options = {}) {
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
const child = spawn(command, args, {
|
|
114
|
+
stdio: ['inherit', 'pipe', 'inherit'],
|
|
115
|
+
...options,
|
|
116
|
+
});
|
|
117
|
+
let stdout = '';
|
|
118
|
+
child.stdout?.setEncoding('utf8');
|
|
119
|
+
child.stdout?.on('data', (chunk) => {
|
|
120
|
+
stdout += chunk;
|
|
121
|
+
});
|
|
122
|
+
child.on('exit', (code) => resolve({ code: code ?? 1, stdout }));
|
|
123
|
+
child.on('error', (err) => {
|
|
124
|
+
process.stderr.write(`✗ failed to spawn ${command}: ${err.message}\n`);
|
|
125
|
+
resolve({ code: 1, stdout: '' });
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Build the base `docker compose -f <file> --env-file <file>` argument list.
|
|
131
|
+
* Optionally prepends a profile and additional overlay files (Mode D).
|
|
132
|
+
*
|
|
133
|
+
* Overlays are passed as additional `-f` flags AFTER the base compose file —
|
|
134
|
+
* compose merges them in order, so later overlays override earlier ones.
|
|
135
|
+
* Relative paths inside an overlay resolve against the FIRST `-f` file's
|
|
136
|
+
* directory (the base compose file at `docker/regression/`), NOT against the
|
|
137
|
+
* overlay's own location.
|
|
138
|
+
*/
|
|
139
|
+
export function dockerComposeArgs(profile, extra = [], overlays = []) {
|
|
140
|
+
const args = ['compose', '-f', COMPOSE_FILE];
|
|
141
|
+
for (const overlay of overlays) {
|
|
142
|
+
args.push('-f', overlay);
|
|
143
|
+
}
|
|
144
|
+
if (envFileExists()) {
|
|
145
|
+
args.push('--env-file', ENV_FILE);
|
|
146
|
+
}
|
|
147
|
+
if (profile) {
|
|
148
|
+
args.push('--profile', profile);
|
|
149
|
+
}
|
|
150
|
+
return args.concat(extra);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Resolve a target-profile argument to an absolute path. Accepts:
|
|
154
|
+
* - "staging-mj" → docker/regression/targets/staging-mj.target.json
|
|
155
|
+
* - "staging-mj.target.json" → docker/regression/targets/staging-mj.target.json
|
|
156
|
+
* - "./my/elsewhere.target.json" → ./my/elsewhere.target.json (passthrough)
|
|
157
|
+
* - absolute path → unchanged
|
|
158
|
+
*/
|
|
159
|
+
export function resolveTargetPath(input) {
|
|
160
|
+
if (path.isAbsolute(input))
|
|
161
|
+
return input;
|
|
162
|
+
if (input.includes('/'))
|
|
163
|
+
return path.resolve(input);
|
|
164
|
+
const withSuffix = input.endsWith('.target.json') ? input : `${input}.target.json`;
|
|
165
|
+
return path.resolve(TARGETS_DIR, withSuffix);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Build a `docker run …` argument list for the published image (external,
|
|
169
|
+
* no-monorepo path). Mounts are [hostPath, containerPath] pairs; envFile is
|
|
170
|
+
* injected with `--env-file`; `host.docker.internal` is always mapped so a DB
|
|
171
|
+
* published on the host is reachable on Linux too.
|
|
172
|
+
*/
|
|
173
|
+
export function dockerRunArgs(image, subArgs, opts = {}) {
|
|
174
|
+
const args = ['run', '--rm', '--add-host', 'host.docker.internal:host-gateway'];
|
|
175
|
+
if (opts.envFile && existsSync(opts.envFile)) {
|
|
176
|
+
args.push('--env-file', opts.envFile);
|
|
177
|
+
}
|
|
178
|
+
for (const [hostPath, containerPath] of opts.mounts ?? []) {
|
|
179
|
+
args.push('-v', `${hostPath}:${containerPath}`);
|
|
180
|
+
}
|
|
181
|
+
args.push(image, ...subArgs);
|
|
182
|
+
return args;
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=docker-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-helpers.js","sourceRoot":"","sources":["../../../src/lib/regression/docker-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"light-commands.d.ts","sourceRoot":"","sources":["../src/light-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"light-commands.d.ts","sourceRoot":"","sources":["../src/light-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAyC7C,CAAC"}
|
package/dist/light-commands.js
CHANGED
|
@@ -28,6 +28,8 @@ export const LIGHT_COMMANDS = new Set([
|
|
|
28
28
|
'install',
|
|
29
29
|
// Doctor - uses @memberjunction/installer engine (lightweight, no bootstrap)
|
|
30
30
|
'doctor',
|
|
31
|
+
// Bundle - uses @memberjunction/installer distribution assembly (lightweight, no bootstrap)
|
|
32
|
+
'bundle',
|
|
31
33
|
// Topic index commands (just display help text, no heavy imports)
|
|
32
34
|
'ai',
|
|
33
35
|
'ai audit',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"light-commands.js","sourceRoot":"","sources":["../src/light-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC;IACzD,yBAAyB;IACzB,SAAS;IACT,MAAM;IAEN,sCAAsC;IACtC,MAAM;IAEN,oEAAoE;IACpE,OAAO;IACP,SAAS;IACT,iBAAiB;IACjB,gBAAgB;IAEhB,qFAAqF;IACrF,SAAS;IAET,6EAA6E;IAC7E,QAAQ;IAER,kEAAkE;IAClE,IAAI;IACJ,UAAU;IACV,MAAM;IACN,OAAO;IAEP,gFAAgF;IAChF,aAAa;IACb,WAAW;IAEX,0DAA0D;IAC1D,YAAY;IACZ,eAAe;IACf,cAAc;IACd,6BAA6B;IAC7B,wBAAwB;IACxB,aAAa;IACb,cAAc;CACf,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"light-commands.js","sourceRoot":"","sources":["../src/light-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC;IACzD,yBAAyB;IACzB,SAAS;IACT,MAAM;IAEN,sCAAsC;IACtC,MAAM;IAEN,oEAAoE;IACpE,OAAO;IACP,SAAS;IACT,iBAAiB;IACjB,gBAAgB;IAEhB,qFAAqF;IACrF,SAAS;IAET,6EAA6E;IAC7E,QAAQ;IAER,4FAA4F;IAC5F,QAAQ;IAER,kEAAkE;IAClE,IAAI;IACJ,UAAU;IACV,MAAM;IACN,OAAO;IAEP,gFAAgF;IAChF,aAAa;IACb,WAAW;IAEX,0DAA0D;IAC1D,YAAY;IACZ,eAAe;IACf,cAAc;IACd,6BAA6B;IAC7B,wBAAwB;IACxB,aAAa;IACb,cAAc;CACf,CAAC,CAAC"}
|