arkormx 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +159 -6
- package/dist/index.cjs +165 -4
- package/dist/index.d.cts +35 -1
- package/dist/index.d.mts +35 -1
- package/dist/index.mjs +158 -6
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
3
3
|
import path, { dirname, extname, join, relative } from "path";
|
|
4
4
|
import { createRequire } from "module";
|
|
5
|
-
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
|
|
6
|
-
import { join as join$1, resolve } from "node:path";
|
|
5
|
+
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
|
|
6
|
+
import { dirname as dirname$1, extname as extname$1, join as join$1, resolve } from "node:path";
|
|
7
7
|
import { spawnSync } from "node:child_process";
|
|
8
8
|
import { str } from "@h3ravel/support";
|
|
9
9
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
10
10
|
import { Logger } from "@h3ravel/shared";
|
|
11
11
|
import { Command, Kernel } from "@h3ravel/musket";
|
|
12
|
+
import { createHash } from "node:crypto";
|
|
12
13
|
import { pathToFileURL as pathToFileURL$1 } from "node:url";
|
|
13
14
|
|
|
14
15
|
//#region src/Exceptions/ArkormException.ts
|
|
@@ -1823,6 +1824,63 @@ var MakeSeederCommand = class extends Command {
|
|
|
1823
1824
|
}
|
|
1824
1825
|
};
|
|
1825
1826
|
|
|
1827
|
+
//#endregion
|
|
1828
|
+
//#region src/helpers/migration-history.ts
|
|
1829
|
+
const DEFAULT_STATE = {
|
|
1830
|
+
version: 1,
|
|
1831
|
+
migrations: []
|
|
1832
|
+
};
|
|
1833
|
+
const resolveMigrationStateFilePath = (cwd, configuredPath) => {
|
|
1834
|
+
if (configuredPath && configuredPath.trim().length > 0) return resolve(configuredPath);
|
|
1835
|
+
return join$1(cwd, ".arkormx", "migrations.applied.json");
|
|
1836
|
+
};
|
|
1837
|
+
const buildMigrationIdentity = (filePath, className) => {
|
|
1838
|
+
const fileName = filePath.split("/").pop()?.split("\\").pop() ?? filePath;
|
|
1839
|
+
return `${fileName.slice(0, fileName.length - extname$1(fileName).length)}:${className}`;
|
|
1840
|
+
};
|
|
1841
|
+
const computeMigrationChecksum = (filePath) => {
|
|
1842
|
+
const source = readFileSync$1(filePath, "utf-8");
|
|
1843
|
+
return createHash("sha256").update(source).digest("hex");
|
|
1844
|
+
};
|
|
1845
|
+
const readAppliedMigrationsState = (stateFilePath) => {
|
|
1846
|
+
if (!existsSync$1(stateFilePath)) return { ...DEFAULT_STATE };
|
|
1847
|
+
try {
|
|
1848
|
+
const parsed = JSON.parse(readFileSync$1(stateFilePath, "utf-8"));
|
|
1849
|
+
if (!Array.isArray(parsed.migrations)) return { ...DEFAULT_STATE };
|
|
1850
|
+
return {
|
|
1851
|
+
version: 1,
|
|
1852
|
+
migrations: parsed.migrations.filter((migration) => {
|
|
1853
|
+
return typeof migration?.id === "string" && typeof migration?.file === "string" && typeof migration?.className === "string" && typeof migration?.appliedAt === "string" && (migration?.checksum === void 0 || typeof migration?.checksum === "string");
|
|
1854
|
+
})
|
|
1855
|
+
};
|
|
1856
|
+
} catch {
|
|
1857
|
+
return { ...DEFAULT_STATE };
|
|
1858
|
+
}
|
|
1859
|
+
};
|
|
1860
|
+
const writeAppliedMigrationsState = (stateFilePath, state) => {
|
|
1861
|
+
const directory = dirname$1(stateFilePath);
|
|
1862
|
+
if (!existsSync$1(directory)) mkdirSync$1(directory, { recursive: true });
|
|
1863
|
+
writeFileSync$1(stateFilePath, JSON.stringify(state, null, 2));
|
|
1864
|
+
};
|
|
1865
|
+
const isMigrationApplied = (state, identity, checksum) => {
|
|
1866
|
+
const matched = state.migrations.find((migration) => migration.id === identity);
|
|
1867
|
+
if (!matched) return false;
|
|
1868
|
+
if (checksum && matched.checksum) return matched.checksum === checksum;
|
|
1869
|
+
if (checksum && !matched.checksum) return false;
|
|
1870
|
+
return true;
|
|
1871
|
+
};
|
|
1872
|
+
const findAppliedMigration = (state, identity) => {
|
|
1873
|
+
return state.migrations.find((migration) => migration.id === identity);
|
|
1874
|
+
};
|
|
1875
|
+
const markMigrationApplied = (state, entry) => {
|
|
1876
|
+
const next = state.migrations.filter((migration) => migration.id !== entry.id);
|
|
1877
|
+
next.push(entry);
|
|
1878
|
+
return {
|
|
1879
|
+
version: 1,
|
|
1880
|
+
migrations: next
|
|
1881
|
+
};
|
|
1882
|
+
};
|
|
1883
|
+
|
|
1826
1884
|
//#endregion
|
|
1827
1885
|
//#region src/database/Migration.ts
|
|
1828
1886
|
const MIGRATION_BRAND = Symbol.for("arkormx.migration");
|
|
@@ -1854,6 +1912,7 @@ var MigrateCommand = class extends Command {
|
|
|
1854
1912
|
{--deploy : Use prisma migrate deploy instead of migrate dev}
|
|
1855
1913
|
{--skip-generate : Skip prisma generate}
|
|
1856
1914
|
{--skip-migrate : Skip prisma migrate command}
|
|
1915
|
+
{--state-file= : Path to applied migration state file}
|
|
1857
1916
|
{--schema= : Explicit prisma schema path}
|
|
1858
1917
|
{--migration-name= : Name for prisma migrate dev}
|
|
1859
1918
|
`;
|
|
@@ -1875,10 +1934,47 @@ var MigrateCommand = class extends Command {
|
|
|
1875
1934
|
const schemaPath = this.option("schema") ? resolve(String(this.option("schema"))) : join$1(process.cwd(), "prisma", "schema.prisma");
|
|
1876
1935
|
const classes = this.option("all") || !this.argument("name") ? await this.loadAllMigrations(migrationsDir) : (await this.loadNamedMigration(migrationsDir, this.argument("name"))).filter(([cls]) => cls !== void 0);
|
|
1877
1936
|
if (classes.length === 0) return void this.error("Error: No migration classes found to run.");
|
|
1878
|
-
|
|
1937
|
+
const shouldTrackApplied = Boolean(this.option("all") || !this.argument("name") || this.option("state-file"));
|
|
1938
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
1939
|
+
let appliedState = shouldTrackApplied ? readAppliedMigrationsState(stateFilePath) : void 0;
|
|
1940
|
+
const skipped = [];
|
|
1941
|
+
const changed = [];
|
|
1942
|
+
const pending = classes.filter(([migrationClass, file]) => {
|
|
1943
|
+
if (!appliedState) return true;
|
|
1944
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
1945
|
+
const checksum = computeMigrationChecksum(file);
|
|
1946
|
+
const alreadyApplied = isMigrationApplied(appliedState, identity, checksum);
|
|
1947
|
+
if (alreadyApplied) skipped.push([migrationClass, file]);
|
|
1948
|
+
else if (findAppliedMigration(appliedState, identity)) changed.push([migrationClass, file]);
|
|
1949
|
+
return !alreadyApplied;
|
|
1950
|
+
});
|
|
1951
|
+
skipped.forEach(([migrationClass, file]) => {
|
|
1952
|
+
this.success(this.app.splitLogger("Skipped", `${file} (${migrationClass.name})`));
|
|
1953
|
+
});
|
|
1954
|
+
changed.forEach(([migrationClass, file]) => {
|
|
1955
|
+
this.success(this.app.splitLogger("Changed", `${file} (${migrationClass.name})`));
|
|
1956
|
+
});
|
|
1957
|
+
if (pending.length === 0) {
|
|
1958
|
+
this.success("No pending migration classes to apply.");
|
|
1959
|
+
return;
|
|
1960
|
+
}
|
|
1961
|
+
for (const [MigrationClassItem] of pending) await applyMigrationToPrismaSchema(MigrationClassItem, {
|
|
1879
1962
|
schemaPath,
|
|
1880
1963
|
write: true
|
|
1881
1964
|
});
|
|
1965
|
+
if (appliedState) {
|
|
1966
|
+
for (const [migrationClass, file] of pending) {
|
|
1967
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
1968
|
+
appliedState = markMigrationApplied(appliedState, {
|
|
1969
|
+
id: identity,
|
|
1970
|
+
file,
|
|
1971
|
+
className: migrationClass.name,
|
|
1972
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1973
|
+
checksum: computeMigrationChecksum(file)
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
writeAppliedMigrationsState(stateFilePath, appliedState);
|
|
1977
|
+
}
|
|
1882
1978
|
if (!this.option("skip-generate")) runPrismaCommand(["generate"], process.cwd());
|
|
1883
1979
|
if (!this.option("skip-migrate")) if (this.option("deploy")) runPrismaCommand(["migrate", "deploy"], process.cwd());
|
|
1884
1980
|
else runPrismaCommand([
|
|
@@ -1887,8 +1983,8 @@ var MigrateCommand = class extends Command {
|
|
|
1887
1983
|
"--name",
|
|
1888
1984
|
this.option("migration-name") ? String(this.option("migration-name")) : `arkorm_cli_${Date.now()}`
|
|
1889
1985
|
], process.cwd());
|
|
1890
|
-
this.success(`Applied ${
|
|
1891
|
-
|
|
1986
|
+
this.success(`Applied ${pending.length} migration(s).`);
|
|
1987
|
+
pending.forEach(([_, file]) => this.success(this.app.splitLogger("Migrated", file)));
|
|
1892
1988
|
}
|
|
1893
1989
|
/**
|
|
1894
1990
|
* Load all migration classes from the specified directory.
|
|
@@ -1940,6 +2036,62 @@ var MigrateCommand = class extends Command {
|
|
|
1940
2036
|
}
|
|
1941
2037
|
};
|
|
1942
2038
|
|
|
2039
|
+
//#endregion
|
|
2040
|
+
//#region src/cli/commands/MigrationHistoryCommand.ts
|
|
2041
|
+
/**
|
|
2042
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2043
|
+
*
|
|
2044
|
+
* @author Legacy (3m1n3nc3)
|
|
2045
|
+
* @since 0.2.4
|
|
2046
|
+
*/
|
|
2047
|
+
var MigrationHistoryCommand = class extends Command {
|
|
2048
|
+
signature = `migrate:history
|
|
2049
|
+
{--state-file= : Path to applied migration state file}
|
|
2050
|
+
{--reset : Clear tracked migration history file}
|
|
2051
|
+
{--delete : Delete tracked migration history file}
|
|
2052
|
+
{--json : Print raw JSON output}
|
|
2053
|
+
`;
|
|
2054
|
+
description = "Inspect or reset tracked migration history";
|
|
2055
|
+
async handle() {
|
|
2056
|
+
this.app.command = this;
|
|
2057
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2058
|
+
if (this.option("delete")) {
|
|
2059
|
+
if (!existsSync$1(stateFilePath)) {
|
|
2060
|
+
this.success(`No migration state file found at ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
rmSync$1(stateFilePath);
|
|
2064
|
+
this.success(`Deleted migration state file: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
if (this.option("reset")) {
|
|
2068
|
+
writeAppliedMigrationsState(stateFilePath, {
|
|
2069
|
+
version: 1,
|
|
2070
|
+
migrations: []
|
|
2071
|
+
});
|
|
2072
|
+
this.success(`Reset migration state: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2073
|
+
return;
|
|
2074
|
+
}
|
|
2075
|
+
const state = readAppliedMigrationsState(stateFilePath);
|
|
2076
|
+
if (this.option("json")) {
|
|
2077
|
+
this.success(JSON.stringify({
|
|
2078
|
+
path: stateFilePath,
|
|
2079
|
+
...state
|
|
2080
|
+
}, null, 2));
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
this.success(this.app.splitLogger("State", stateFilePath));
|
|
2084
|
+
this.success(this.app.splitLogger("Tracked", String(state.migrations.length)));
|
|
2085
|
+
if (state.migrations.length === 0) {
|
|
2086
|
+
this.success("No tracked migrations found.");
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
state.migrations.sort((left, right) => left.appliedAt.localeCompare(right.appliedAt)).forEach((migration) => {
|
|
2090
|
+
this.success(this.app.splitLogger("Applied", `${migration.id} @ ${migration.appliedAt}`));
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
};
|
|
2094
|
+
|
|
1943
2095
|
//#endregion
|
|
1944
2096
|
//#region src/cli/commands/ModelsSyncCommand.ts
|
|
1945
2097
|
var ModelsSyncCommand = class extends Command {
|
|
@@ -2119,7 +2271,8 @@ await Kernel.init(app, {
|
|
|
2119
2271
|
MakeMigrationCommand,
|
|
2120
2272
|
ModelsSyncCommand,
|
|
2121
2273
|
SeedCommand,
|
|
2122
|
-
MigrateCommand
|
|
2274
|
+
MigrateCommand,
|
|
2275
|
+
MigrationHistoryCommand
|
|
2123
2276
|
],
|
|
2124
2277
|
exceptionHandler(exception) {
|
|
2125
2278
|
throw exception;
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ let _h3ravel_support = require("@h3ravel/support");
|
|
|
37
37
|
let url = require("url");
|
|
38
38
|
let _h3ravel_shared = require("@h3ravel/shared");
|
|
39
39
|
let _h3ravel_musket = require("@h3ravel/musket");
|
|
40
|
+
let node_crypto = require("node:crypto");
|
|
40
41
|
let node_url = require("node:url");
|
|
41
42
|
let _h3ravel_collect_js = require("@h3ravel/collect.js");
|
|
42
43
|
|
|
@@ -2031,6 +2032,63 @@ var MakeSeederCommand = class extends _h3ravel_musket.Command {
|
|
|
2031
2032
|
}
|
|
2032
2033
|
};
|
|
2033
2034
|
|
|
2035
|
+
//#endregion
|
|
2036
|
+
//#region src/helpers/migration-history.ts
|
|
2037
|
+
const DEFAULT_STATE = {
|
|
2038
|
+
version: 1,
|
|
2039
|
+
migrations: []
|
|
2040
|
+
};
|
|
2041
|
+
const resolveMigrationStateFilePath = (cwd, configuredPath) => {
|
|
2042
|
+
if (configuredPath && configuredPath.trim().length > 0) return (0, node_path.resolve)(configuredPath);
|
|
2043
|
+
return (0, node_path.join)(cwd, ".arkormx", "migrations.applied.json");
|
|
2044
|
+
};
|
|
2045
|
+
const buildMigrationIdentity = (filePath, className) => {
|
|
2046
|
+
const fileName = filePath.split("/").pop()?.split("\\").pop() ?? filePath;
|
|
2047
|
+
return `${fileName.slice(0, fileName.length - (0, node_path.extname)(fileName).length)}:${className}`;
|
|
2048
|
+
};
|
|
2049
|
+
const computeMigrationChecksum = (filePath) => {
|
|
2050
|
+
const source = (0, node_fs.readFileSync)(filePath, "utf-8");
|
|
2051
|
+
return (0, node_crypto.createHash)("sha256").update(source).digest("hex");
|
|
2052
|
+
};
|
|
2053
|
+
const readAppliedMigrationsState = (stateFilePath) => {
|
|
2054
|
+
if (!(0, node_fs.existsSync)(stateFilePath)) return { ...DEFAULT_STATE };
|
|
2055
|
+
try {
|
|
2056
|
+
const parsed = JSON.parse((0, node_fs.readFileSync)(stateFilePath, "utf-8"));
|
|
2057
|
+
if (!Array.isArray(parsed.migrations)) return { ...DEFAULT_STATE };
|
|
2058
|
+
return {
|
|
2059
|
+
version: 1,
|
|
2060
|
+
migrations: parsed.migrations.filter((migration) => {
|
|
2061
|
+
return typeof migration?.id === "string" && typeof migration?.file === "string" && typeof migration?.className === "string" && typeof migration?.appliedAt === "string" && (migration?.checksum === void 0 || typeof migration?.checksum === "string");
|
|
2062
|
+
})
|
|
2063
|
+
};
|
|
2064
|
+
} catch {
|
|
2065
|
+
return { ...DEFAULT_STATE };
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
2068
|
+
const writeAppliedMigrationsState = (stateFilePath, state) => {
|
|
2069
|
+
const directory = (0, node_path.dirname)(stateFilePath);
|
|
2070
|
+
if (!(0, node_fs.existsSync)(directory)) (0, node_fs.mkdirSync)(directory, { recursive: true });
|
|
2071
|
+
(0, node_fs.writeFileSync)(stateFilePath, JSON.stringify(state, null, 2));
|
|
2072
|
+
};
|
|
2073
|
+
const isMigrationApplied = (state, identity, checksum) => {
|
|
2074
|
+
const matched = state.migrations.find((migration) => migration.id === identity);
|
|
2075
|
+
if (!matched) return false;
|
|
2076
|
+
if (checksum && matched.checksum) return matched.checksum === checksum;
|
|
2077
|
+
if (checksum && !matched.checksum) return false;
|
|
2078
|
+
return true;
|
|
2079
|
+
};
|
|
2080
|
+
const findAppliedMigration = (state, identity) => {
|
|
2081
|
+
return state.migrations.find((migration) => migration.id === identity);
|
|
2082
|
+
};
|
|
2083
|
+
const markMigrationApplied = (state, entry) => {
|
|
2084
|
+
const next = state.migrations.filter((migration) => migration.id !== entry.id);
|
|
2085
|
+
next.push(entry);
|
|
2086
|
+
return {
|
|
2087
|
+
version: 1,
|
|
2088
|
+
migrations: next
|
|
2089
|
+
};
|
|
2090
|
+
};
|
|
2091
|
+
|
|
2034
2092
|
//#endregion
|
|
2035
2093
|
//#region src/database/Migration.ts
|
|
2036
2094
|
const MIGRATION_BRAND = Symbol.for("arkormx.migration");
|
|
@@ -2062,6 +2120,7 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2062
2120
|
{--deploy : Use prisma migrate deploy instead of migrate dev}
|
|
2063
2121
|
{--skip-generate : Skip prisma generate}
|
|
2064
2122
|
{--skip-migrate : Skip prisma migrate command}
|
|
2123
|
+
{--state-file= : Path to applied migration state file}
|
|
2065
2124
|
{--schema= : Explicit prisma schema path}
|
|
2066
2125
|
{--migration-name= : Name for prisma migrate dev}
|
|
2067
2126
|
`;
|
|
@@ -2083,10 +2142,47 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2083
2142
|
const schemaPath = this.option("schema") ? (0, node_path.resolve)(String(this.option("schema"))) : (0, node_path.join)(process.cwd(), "prisma", "schema.prisma");
|
|
2084
2143
|
const classes = this.option("all") || !this.argument("name") ? await this.loadAllMigrations(migrationsDir) : (await this.loadNamedMigration(migrationsDir, this.argument("name"))).filter(([cls]) => cls !== void 0);
|
|
2085
2144
|
if (classes.length === 0) return void this.error("Error: No migration classes found to run.");
|
|
2086
|
-
|
|
2145
|
+
const shouldTrackApplied = Boolean(this.option("all") || !this.argument("name") || this.option("state-file"));
|
|
2146
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2147
|
+
let appliedState = shouldTrackApplied ? readAppliedMigrationsState(stateFilePath) : void 0;
|
|
2148
|
+
const skipped = [];
|
|
2149
|
+
const changed = [];
|
|
2150
|
+
const pending = classes.filter(([migrationClass, file]) => {
|
|
2151
|
+
if (!appliedState) return true;
|
|
2152
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2153
|
+
const checksum = computeMigrationChecksum(file);
|
|
2154
|
+
const alreadyApplied = isMigrationApplied(appliedState, identity, checksum);
|
|
2155
|
+
if (alreadyApplied) skipped.push([migrationClass, file]);
|
|
2156
|
+
else if (findAppliedMigration(appliedState, identity)) changed.push([migrationClass, file]);
|
|
2157
|
+
return !alreadyApplied;
|
|
2158
|
+
});
|
|
2159
|
+
skipped.forEach(([migrationClass, file]) => {
|
|
2160
|
+
this.success(this.app.splitLogger("Skipped", `${file} (${migrationClass.name})`));
|
|
2161
|
+
});
|
|
2162
|
+
changed.forEach(([migrationClass, file]) => {
|
|
2163
|
+
this.success(this.app.splitLogger("Changed", `${file} (${migrationClass.name})`));
|
|
2164
|
+
});
|
|
2165
|
+
if (pending.length === 0) {
|
|
2166
|
+
this.success("No pending migration classes to apply.");
|
|
2167
|
+
return;
|
|
2168
|
+
}
|
|
2169
|
+
for (const [MigrationClassItem] of pending) await applyMigrationToPrismaSchema(MigrationClassItem, {
|
|
2087
2170
|
schemaPath,
|
|
2088
2171
|
write: true
|
|
2089
2172
|
});
|
|
2173
|
+
if (appliedState) {
|
|
2174
|
+
for (const [migrationClass, file] of pending) {
|
|
2175
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2176
|
+
appliedState = markMigrationApplied(appliedState, {
|
|
2177
|
+
id: identity,
|
|
2178
|
+
file,
|
|
2179
|
+
className: migrationClass.name,
|
|
2180
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2181
|
+
checksum: computeMigrationChecksum(file)
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
writeAppliedMigrationsState(stateFilePath, appliedState);
|
|
2185
|
+
}
|
|
2090
2186
|
if (!this.option("skip-generate")) runPrismaCommand(["generate"], process.cwd());
|
|
2091
2187
|
if (!this.option("skip-migrate")) if (this.option("deploy")) runPrismaCommand(["migrate", "deploy"], process.cwd());
|
|
2092
2188
|
else runPrismaCommand([
|
|
@@ -2095,8 +2191,8 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2095
2191
|
"--name",
|
|
2096
2192
|
this.option("migration-name") ? String(this.option("migration-name")) : `arkorm_cli_${Date.now()}`
|
|
2097
2193
|
], process.cwd());
|
|
2098
|
-
this.success(`Applied ${
|
|
2099
|
-
|
|
2194
|
+
this.success(`Applied ${pending.length} migration(s).`);
|
|
2195
|
+
pending.forEach(([_, file]) => this.success(this.app.splitLogger("Migrated", file)));
|
|
2100
2196
|
}
|
|
2101
2197
|
/**
|
|
2102
2198
|
* Load all migration classes from the specified directory.
|
|
@@ -2148,6 +2244,62 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2148
2244
|
}
|
|
2149
2245
|
};
|
|
2150
2246
|
|
|
2247
|
+
//#endregion
|
|
2248
|
+
//#region src/cli/commands/MigrationHistoryCommand.ts
|
|
2249
|
+
/**
|
|
2250
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2251
|
+
*
|
|
2252
|
+
* @author Legacy (3m1n3nc3)
|
|
2253
|
+
* @since 0.2.4
|
|
2254
|
+
*/
|
|
2255
|
+
var MigrationHistoryCommand = class extends _h3ravel_musket.Command {
|
|
2256
|
+
signature = `migrate:history
|
|
2257
|
+
{--state-file= : Path to applied migration state file}
|
|
2258
|
+
{--reset : Clear tracked migration history file}
|
|
2259
|
+
{--delete : Delete tracked migration history file}
|
|
2260
|
+
{--json : Print raw JSON output}
|
|
2261
|
+
`;
|
|
2262
|
+
description = "Inspect or reset tracked migration history";
|
|
2263
|
+
async handle() {
|
|
2264
|
+
this.app.command = this;
|
|
2265
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2266
|
+
if (this.option("delete")) {
|
|
2267
|
+
if (!(0, node_fs.existsSync)(stateFilePath)) {
|
|
2268
|
+
this.success(`No migration state file found at ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2269
|
+
return;
|
|
2270
|
+
}
|
|
2271
|
+
(0, node_fs.rmSync)(stateFilePath);
|
|
2272
|
+
this.success(`Deleted migration state file: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
2275
|
+
if (this.option("reset")) {
|
|
2276
|
+
writeAppliedMigrationsState(stateFilePath, {
|
|
2277
|
+
version: 1,
|
|
2278
|
+
migrations: []
|
|
2279
|
+
});
|
|
2280
|
+
this.success(`Reset migration state: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
const state = readAppliedMigrationsState(stateFilePath);
|
|
2284
|
+
if (this.option("json")) {
|
|
2285
|
+
this.success(JSON.stringify({
|
|
2286
|
+
path: stateFilePath,
|
|
2287
|
+
...state
|
|
2288
|
+
}, null, 2));
|
|
2289
|
+
return;
|
|
2290
|
+
}
|
|
2291
|
+
this.success(this.app.splitLogger("State", stateFilePath));
|
|
2292
|
+
this.success(this.app.splitLogger("Tracked", String(state.migrations.length)));
|
|
2293
|
+
if (state.migrations.length === 0) {
|
|
2294
|
+
this.success("No tracked migrations found.");
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
state.migrations.sort((left, right) => left.appliedAt.localeCompare(right.appliedAt)).forEach((migration) => {
|
|
2298
|
+
this.success(this.app.splitLogger("Applied", `${migration.id} @ ${migration.appliedAt}`));
|
|
2299
|
+
});
|
|
2300
|
+
}
|
|
2301
|
+
};
|
|
2302
|
+
|
|
2151
2303
|
//#endregion
|
|
2152
2304
|
//#region src/cli/commands/ModelsSyncCommand.ts
|
|
2153
2305
|
var ModelsSyncCommand = class extends _h3ravel_musket.Command {
|
|
@@ -5130,6 +5282,7 @@ exports.MakeModelCommand = MakeModelCommand;
|
|
|
5130
5282
|
exports.MakeSeederCommand = MakeSeederCommand;
|
|
5131
5283
|
exports.MigrateCommand = MigrateCommand;
|
|
5132
5284
|
exports.Migration = Migration;
|
|
5285
|
+
exports.MigrationHistoryCommand = MigrationHistoryCommand;
|
|
5133
5286
|
exports.Model = Model;
|
|
5134
5287
|
exports.ModelFactory = ModelFactory;
|
|
5135
5288
|
exports.ModelNotFoundException = ModelNotFoundException;
|
|
@@ -5151,9 +5304,11 @@ exports.applyOperationsToPrismaSchema = applyOperationsToPrismaSchema;
|
|
|
5151
5304
|
exports.buildFieldLine = buildFieldLine;
|
|
5152
5305
|
exports.buildIndexLine = buildIndexLine;
|
|
5153
5306
|
exports.buildInverseRelationLine = buildInverseRelationLine;
|
|
5307
|
+
exports.buildMigrationIdentity = buildMigrationIdentity;
|
|
5154
5308
|
exports.buildMigrationSource = buildMigrationSource;
|
|
5155
5309
|
exports.buildModelBlock = buildModelBlock;
|
|
5156
5310
|
exports.buildRelationLine = buildRelationLine;
|
|
5311
|
+
exports.computeMigrationChecksum = computeMigrationChecksum;
|
|
5157
5312
|
exports.configureArkormRuntime = configureArkormRuntime;
|
|
5158
5313
|
exports.createMigrationTimestamp = createMigrationTimestamp;
|
|
5159
5314
|
exports.createPrismaAdapter = createPrismaAdapter;
|
|
@@ -5165,6 +5320,7 @@ exports.deriveInverseRelationAlias = deriveInverseRelationAlias;
|
|
|
5165
5320
|
exports.deriveRelationFieldName = deriveRelationFieldName;
|
|
5166
5321
|
exports.ensureArkormConfigLoading = ensureArkormConfigLoading;
|
|
5167
5322
|
exports.escapeRegex = escapeRegex;
|
|
5323
|
+
exports.findAppliedMigration = findAppliedMigration;
|
|
5168
5324
|
exports.findModelBlock = findModelBlock;
|
|
5169
5325
|
exports.formatDefaultValue = formatDefaultValue;
|
|
5170
5326
|
exports.formatRelationAction = formatRelationAction;
|
|
@@ -5176,13 +5332,18 @@ exports.getRuntimePrismaClient = getRuntimePrismaClient;
|
|
|
5176
5332
|
exports.getUserConfig = getUserConfig;
|
|
5177
5333
|
exports.inferDelegateName = inferDelegateName;
|
|
5178
5334
|
exports.isDelegateLike = isDelegateLike;
|
|
5335
|
+
exports.isMigrationApplied = isMigrationApplied;
|
|
5179
5336
|
exports.loadArkormConfig = loadArkormConfig;
|
|
5337
|
+
exports.markMigrationApplied = markMigrationApplied;
|
|
5180
5338
|
exports.pad = pad;
|
|
5339
|
+
exports.readAppliedMigrationsState = readAppliedMigrationsState;
|
|
5181
5340
|
exports.resetArkormRuntimeForTests = resetArkormRuntimeForTests;
|
|
5182
5341
|
exports.resolveCast = resolveCast;
|
|
5183
5342
|
exports.resolveMigrationClassName = resolveMigrationClassName;
|
|
5343
|
+
exports.resolveMigrationStateFilePath = resolveMigrationStateFilePath;
|
|
5184
5344
|
exports.resolvePrismaType = resolvePrismaType;
|
|
5185
5345
|
exports.runMigrationWithPrisma = runMigrationWithPrisma;
|
|
5186
5346
|
exports.runPrismaCommand = runPrismaCommand;
|
|
5187
5347
|
exports.toMigrationFileSlug = toMigrationFileSlug;
|
|
5188
|
-
exports.toModelName = toModelName;
|
|
5348
|
+
exports.toModelName = toModelName;
|
|
5349
|
+
exports.writeAppliedMigrationsState = writeAppliedMigrationsState;
|
package/dist/index.d.cts
CHANGED
|
@@ -79,6 +79,17 @@ interface PrismaMigrationWorkflowOptions extends PrismaSchemaSyncOptions {
|
|
|
79
79
|
migrateMode?: 'dev' | 'deploy';
|
|
80
80
|
migrationName?: string;
|
|
81
81
|
}
|
|
82
|
+
interface AppliedMigrationEntry {
|
|
83
|
+
id: string;
|
|
84
|
+
file: string;
|
|
85
|
+
className: string;
|
|
86
|
+
appliedAt: string;
|
|
87
|
+
checksum?: string;
|
|
88
|
+
}
|
|
89
|
+
interface AppliedMigrationsState {
|
|
90
|
+
version: 1;
|
|
91
|
+
migrations: AppliedMigrationEntry[];
|
|
92
|
+
}
|
|
82
93
|
//#endregion
|
|
83
94
|
//#region src/Collection.d.ts
|
|
84
95
|
declare class ArkormCollection<T = any, X = T[]> extends Collection<T, X> {}
|
|
@@ -2251,6 +2262,19 @@ declare class MigrateCommand extends Command<CliApp> {
|
|
|
2251
2262
|
private loadMigrationClassesFromFile;
|
|
2252
2263
|
}
|
|
2253
2264
|
//#endregion
|
|
2265
|
+
//#region src/cli/commands/MigrationHistoryCommand.d.ts
|
|
2266
|
+
/**
|
|
2267
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2268
|
+
*
|
|
2269
|
+
* @author Legacy (3m1n3nc3)
|
|
2270
|
+
* @since 0.2.4
|
|
2271
|
+
*/
|
|
2272
|
+
declare class MigrationHistoryCommand extends Command<CliApp> {
|
|
2273
|
+
protected signature: string;
|
|
2274
|
+
protected description: string;
|
|
2275
|
+
handle(): Promise<void>;
|
|
2276
|
+
}
|
|
2277
|
+
//#endregion
|
|
2254
2278
|
//#region src/cli/commands/ModelsSyncCommand.d.ts
|
|
2255
2279
|
declare class ModelsSyncCommand extends Command<CliApp> {
|
|
2256
2280
|
protected signature: string;
|
|
@@ -2731,6 +2755,16 @@ declare class ModelNotFoundException extends ArkormException {
|
|
|
2731
2755
|
getModelName(): string;
|
|
2732
2756
|
}
|
|
2733
2757
|
//#endregion
|
|
2758
|
+
//#region src/helpers/migration-history.d.ts
|
|
2759
|
+
declare const resolveMigrationStateFilePath: (cwd: string, configuredPath?: string) => string;
|
|
2760
|
+
declare const buildMigrationIdentity: (filePath: string, className: string) => string;
|
|
2761
|
+
declare const computeMigrationChecksum: (filePath: string) => string;
|
|
2762
|
+
declare const readAppliedMigrationsState: (stateFilePath: string) => AppliedMigrationsState;
|
|
2763
|
+
declare const writeAppliedMigrationsState: (stateFilePath: string, state: AppliedMigrationsState) => void;
|
|
2764
|
+
declare const isMigrationApplied: (state: AppliedMigrationsState, identity: string, checksum?: string) => boolean;
|
|
2765
|
+
declare const findAppliedMigration: (state: AppliedMigrationsState, identity: string) => AppliedMigrationEntry | undefined;
|
|
2766
|
+
declare const markMigrationApplied: (state: AppliedMigrationsState, entry: AppliedMigrationEntry) => AppliedMigrationsState;
|
|
2767
|
+
//#endregion
|
|
2734
2768
|
//#region src/helpers/migrations.d.ts
|
|
2735
2769
|
declare const PRISMA_MODEL_REGEX: RegExp;
|
|
2736
2770
|
/**
|
|
@@ -3080,4 +3114,4 @@ declare class URLDriver {
|
|
|
3080
3114
|
url(page: number): string;
|
|
3081
3115
|
}
|
|
3082
3116
|
//#endregion
|
|
3083
|
-
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, PrismaDelegateMap, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, SeederCallArgument, SeederConstructor, SeederInput, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationSource, buildModelBlock, buildRelationLine, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|
|
3117
|
+
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, MigrationHistoryCommand, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, PrismaDelegateMap, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, SeederCallArgument, SeederConstructor, SeederInput, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationSource, buildModelBlock, buildRelationLine, computeMigrationChecksum, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, loadArkormConfig, markMigrationApplied, pad, readAppliedMigrationsState, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName, writeAppliedMigrationsState };
|
package/dist/index.d.mts
CHANGED
|
@@ -79,6 +79,17 @@ interface PrismaMigrationWorkflowOptions extends PrismaSchemaSyncOptions {
|
|
|
79
79
|
migrateMode?: 'dev' | 'deploy';
|
|
80
80
|
migrationName?: string;
|
|
81
81
|
}
|
|
82
|
+
interface AppliedMigrationEntry {
|
|
83
|
+
id: string;
|
|
84
|
+
file: string;
|
|
85
|
+
className: string;
|
|
86
|
+
appliedAt: string;
|
|
87
|
+
checksum?: string;
|
|
88
|
+
}
|
|
89
|
+
interface AppliedMigrationsState {
|
|
90
|
+
version: 1;
|
|
91
|
+
migrations: AppliedMigrationEntry[];
|
|
92
|
+
}
|
|
82
93
|
//#endregion
|
|
83
94
|
//#region src/Collection.d.ts
|
|
84
95
|
declare class ArkormCollection<T = any, X = T[]> extends Collection<T, X> {}
|
|
@@ -2251,6 +2262,19 @@ declare class MigrateCommand extends Command<CliApp> {
|
|
|
2251
2262
|
private loadMigrationClassesFromFile;
|
|
2252
2263
|
}
|
|
2253
2264
|
//#endregion
|
|
2265
|
+
//#region src/cli/commands/MigrationHistoryCommand.d.ts
|
|
2266
|
+
/**
|
|
2267
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2268
|
+
*
|
|
2269
|
+
* @author Legacy (3m1n3nc3)
|
|
2270
|
+
* @since 0.2.4
|
|
2271
|
+
*/
|
|
2272
|
+
declare class MigrationHistoryCommand extends Command<CliApp> {
|
|
2273
|
+
protected signature: string;
|
|
2274
|
+
protected description: string;
|
|
2275
|
+
handle(): Promise<void>;
|
|
2276
|
+
}
|
|
2277
|
+
//#endregion
|
|
2254
2278
|
//#region src/cli/commands/ModelsSyncCommand.d.ts
|
|
2255
2279
|
declare class ModelsSyncCommand extends Command<CliApp> {
|
|
2256
2280
|
protected signature: string;
|
|
@@ -2731,6 +2755,16 @@ declare class ModelNotFoundException extends ArkormException {
|
|
|
2731
2755
|
getModelName(): string;
|
|
2732
2756
|
}
|
|
2733
2757
|
//#endregion
|
|
2758
|
+
//#region src/helpers/migration-history.d.ts
|
|
2759
|
+
declare const resolveMigrationStateFilePath: (cwd: string, configuredPath?: string) => string;
|
|
2760
|
+
declare const buildMigrationIdentity: (filePath: string, className: string) => string;
|
|
2761
|
+
declare const computeMigrationChecksum: (filePath: string) => string;
|
|
2762
|
+
declare const readAppliedMigrationsState: (stateFilePath: string) => AppliedMigrationsState;
|
|
2763
|
+
declare const writeAppliedMigrationsState: (stateFilePath: string, state: AppliedMigrationsState) => void;
|
|
2764
|
+
declare const isMigrationApplied: (state: AppliedMigrationsState, identity: string, checksum?: string) => boolean;
|
|
2765
|
+
declare const findAppliedMigration: (state: AppliedMigrationsState, identity: string) => AppliedMigrationEntry | undefined;
|
|
2766
|
+
declare const markMigrationApplied: (state: AppliedMigrationsState, entry: AppliedMigrationEntry) => AppliedMigrationsState;
|
|
2767
|
+
//#endregion
|
|
2734
2768
|
//#region src/helpers/migrations.d.ts
|
|
2735
2769
|
declare const PRISMA_MODEL_REGEX: RegExp;
|
|
2736
2770
|
/**
|
|
@@ -3080,4 +3114,4 @@ declare class URLDriver {
|
|
|
3080
3114
|
url(page: number): string;
|
|
3081
3115
|
}
|
|
3082
3116
|
//#endregion
|
|
3083
|
-
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, PrismaDelegateMap, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, SeederCallArgument, SeederConstructor, SeederInput, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationSource, buildModelBlock, buildRelationLine, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|
|
3117
|
+
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, MigrationHistoryCommand, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, PrismaDelegateMap, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, SeederCallArgument, SeederConstructor, SeederInput, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationSource, buildModelBlock, buildRelationLine, computeMigrationChecksum, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, loadArkormConfig, markMigrationApplied, pad, readAppliedMigrationsState, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName, writeAppliedMigrationsState };
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
2
2
|
import path, { dirname, extname, join, relative } from "path";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
|
-
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
|
|
5
|
-
import { join as join$1, resolve } from "node:path";
|
|
4
|
+
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "node:fs";
|
|
5
|
+
import { dirname as dirname$1, extname as extname$1, join as join$1, resolve } from "node:path";
|
|
6
6
|
import { spawnSync } from "node:child_process";
|
|
7
7
|
import { str } from "@h3ravel/support";
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
9
9
|
import { Logger } from "@h3ravel/shared";
|
|
10
10
|
import { Command } from "@h3ravel/musket";
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
11
12
|
import { pathToFileURL as pathToFileURL$1 } from "node:url";
|
|
12
13
|
import { Collection } from "@h3ravel/collect.js";
|
|
13
14
|
|
|
@@ -2002,6 +2003,63 @@ var MakeSeederCommand = class extends Command {
|
|
|
2002
2003
|
}
|
|
2003
2004
|
};
|
|
2004
2005
|
|
|
2006
|
+
//#endregion
|
|
2007
|
+
//#region src/helpers/migration-history.ts
|
|
2008
|
+
const DEFAULT_STATE = {
|
|
2009
|
+
version: 1,
|
|
2010
|
+
migrations: []
|
|
2011
|
+
};
|
|
2012
|
+
const resolveMigrationStateFilePath = (cwd, configuredPath) => {
|
|
2013
|
+
if (configuredPath && configuredPath.trim().length > 0) return resolve(configuredPath);
|
|
2014
|
+
return join$1(cwd, ".arkormx", "migrations.applied.json");
|
|
2015
|
+
};
|
|
2016
|
+
const buildMigrationIdentity = (filePath, className) => {
|
|
2017
|
+
const fileName = filePath.split("/").pop()?.split("\\").pop() ?? filePath;
|
|
2018
|
+
return `${fileName.slice(0, fileName.length - extname$1(fileName).length)}:${className}`;
|
|
2019
|
+
};
|
|
2020
|
+
const computeMigrationChecksum = (filePath) => {
|
|
2021
|
+
const source = readFileSync$1(filePath, "utf-8");
|
|
2022
|
+
return createHash("sha256").update(source).digest("hex");
|
|
2023
|
+
};
|
|
2024
|
+
const readAppliedMigrationsState = (stateFilePath) => {
|
|
2025
|
+
if (!existsSync$1(stateFilePath)) return { ...DEFAULT_STATE };
|
|
2026
|
+
try {
|
|
2027
|
+
const parsed = JSON.parse(readFileSync$1(stateFilePath, "utf-8"));
|
|
2028
|
+
if (!Array.isArray(parsed.migrations)) return { ...DEFAULT_STATE };
|
|
2029
|
+
return {
|
|
2030
|
+
version: 1,
|
|
2031
|
+
migrations: parsed.migrations.filter((migration) => {
|
|
2032
|
+
return typeof migration?.id === "string" && typeof migration?.file === "string" && typeof migration?.className === "string" && typeof migration?.appliedAt === "string" && (migration?.checksum === void 0 || typeof migration?.checksum === "string");
|
|
2033
|
+
})
|
|
2034
|
+
};
|
|
2035
|
+
} catch {
|
|
2036
|
+
return { ...DEFAULT_STATE };
|
|
2037
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
const writeAppliedMigrationsState = (stateFilePath, state) => {
|
|
2040
|
+
const directory = dirname$1(stateFilePath);
|
|
2041
|
+
if (!existsSync$1(directory)) mkdirSync$1(directory, { recursive: true });
|
|
2042
|
+
writeFileSync$1(stateFilePath, JSON.stringify(state, null, 2));
|
|
2043
|
+
};
|
|
2044
|
+
const isMigrationApplied = (state, identity, checksum) => {
|
|
2045
|
+
const matched = state.migrations.find((migration) => migration.id === identity);
|
|
2046
|
+
if (!matched) return false;
|
|
2047
|
+
if (checksum && matched.checksum) return matched.checksum === checksum;
|
|
2048
|
+
if (checksum && !matched.checksum) return false;
|
|
2049
|
+
return true;
|
|
2050
|
+
};
|
|
2051
|
+
const findAppliedMigration = (state, identity) => {
|
|
2052
|
+
return state.migrations.find((migration) => migration.id === identity);
|
|
2053
|
+
};
|
|
2054
|
+
const markMigrationApplied = (state, entry) => {
|
|
2055
|
+
const next = state.migrations.filter((migration) => migration.id !== entry.id);
|
|
2056
|
+
next.push(entry);
|
|
2057
|
+
return {
|
|
2058
|
+
version: 1,
|
|
2059
|
+
migrations: next
|
|
2060
|
+
};
|
|
2061
|
+
};
|
|
2062
|
+
|
|
2005
2063
|
//#endregion
|
|
2006
2064
|
//#region src/database/Migration.ts
|
|
2007
2065
|
const MIGRATION_BRAND = Symbol.for("arkormx.migration");
|
|
@@ -2033,6 +2091,7 @@ var MigrateCommand = class extends Command {
|
|
|
2033
2091
|
{--deploy : Use prisma migrate deploy instead of migrate dev}
|
|
2034
2092
|
{--skip-generate : Skip prisma generate}
|
|
2035
2093
|
{--skip-migrate : Skip prisma migrate command}
|
|
2094
|
+
{--state-file= : Path to applied migration state file}
|
|
2036
2095
|
{--schema= : Explicit prisma schema path}
|
|
2037
2096
|
{--migration-name= : Name for prisma migrate dev}
|
|
2038
2097
|
`;
|
|
@@ -2054,10 +2113,47 @@ var MigrateCommand = class extends Command {
|
|
|
2054
2113
|
const schemaPath = this.option("schema") ? resolve(String(this.option("schema"))) : join$1(process.cwd(), "prisma", "schema.prisma");
|
|
2055
2114
|
const classes = this.option("all") || !this.argument("name") ? await this.loadAllMigrations(migrationsDir) : (await this.loadNamedMigration(migrationsDir, this.argument("name"))).filter(([cls]) => cls !== void 0);
|
|
2056
2115
|
if (classes.length === 0) return void this.error("Error: No migration classes found to run.");
|
|
2057
|
-
|
|
2116
|
+
const shouldTrackApplied = Boolean(this.option("all") || !this.argument("name") || this.option("state-file"));
|
|
2117
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2118
|
+
let appliedState = shouldTrackApplied ? readAppliedMigrationsState(stateFilePath) : void 0;
|
|
2119
|
+
const skipped = [];
|
|
2120
|
+
const changed = [];
|
|
2121
|
+
const pending = classes.filter(([migrationClass, file]) => {
|
|
2122
|
+
if (!appliedState) return true;
|
|
2123
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2124
|
+
const checksum = computeMigrationChecksum(file);
|
|
2125
|
+
const alreadyApplied = isMigrationApplied(appliedState, identity, checksum);
|
|
2126
|
+
if (alreadyApplied) skipped.push([migrationClass, file]);
|
|
2127
|
+
else if (findAppliedMigration(appliedState, identity)) changed.push([migrationClass, file]);
|
|
2128
|
+
return !alreadyApplied;
|
|
2129
|
+
});
|
|
2130
|
+
skipped.forEach(([migrationClass, file]) => {
|
|
2131
|
+
this.success(this.app.splitLogger("Skipped", `${file} (${migrationClass.name})`));
|
|
2132
|
+
});
|
|
2133
|
+
changed.forEach(([migrationClass, file]) => {
|
|
2134
|
+
this.success(this.app.splitLogger("Changed", `${file} (${migrationClass.name})`));
|
|
2135
|
+
});
|
|
2136
|
+
if (pending.length === 0) {
|
|
2137
|
+
this.success("No pending migration classes to apply.");
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
for (const [MigrationClassItem] of pending) await applyMigrationToPrismaSchema(MigrationClassItem, {
|
|
2058
2141
|
schemaPath,
|
|
2059
2142
|
write: true
|
|
2060
2143
|
});
|
|
2144
|
+
if (appliedState) {
|
|
2145
|
+
for (const [migrationClass, file] of pending) {
|
|
2146
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2147
|
+
appliedState = markMigrationApplied(appliedState, {
|
|
2148
|
+
id: identity,
|
|
2149
|
+
file,
|
|
2150
|
+
className: migrationClass.name,
|
|
2151
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2152
|
+
checksum: computeMigrationChecksum(file)
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
writeAppliedMigrationsState(stateFilePath, appliedState);
|
|
2156
|
+
}
|
|
2061
2157
|
if (!this.option("skip-generate")) runPrismaCommand(["generate"], process.cwd());
|
|
2062
2158
|
if (!this.option("skip-migrate")) if (this.option("deploy")) runPrismaCommand(["migrate", "deploy"], process.cwd());
|
|
2063
2159
|
else runPrismaCommand([
|
|
@@ -2066,8 +2162,8 @@ var MigrateCommand = class extends Command {
|
|
|
2066
2162
|
"--name",
|
|
2067
2163
|
this.option("migration-name") ? String(this.option("migration-name")) : `arkorm_cli_${Date.now()}`
|
|
2068
2164
|
], process.cwd());
|
|
2069
|
-
this.success(`Applied ${
|
|
2070
|
-
|
|
2165
|
+
this.success(`Applied ${pending.length} migration(s).`);
|
|
2166
|
+
pending.forEach(([_, file]) => this.success(this.app.splitLogger("Migrated", file)));
|
|
2071
2167
|
}
|
|
2072
2168
|
/**
|
|
2073
2169
|
* Load all migration classes from the specified directory.
|
|
@@ -2119,6 +2215,62 @@ var MigrateCommand = class extends Command {
|
|
|
2119
2215
|
}
|
|
2120
2216
|
};
|
|
2121
2217
|
|
|
2218
|
+
//#endregion
|
|
2219
|
+
//#region src/cli/commands/MigrationHistoryCommand.ts
|
|
2220
|
+
/**
|
|
2221
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2222
|
+
*
|
|
2223
|
+
* @author Legacy (3m1n3nc3)
|
|
2224
|
+
* @since 0.2.4
|
|
2225
|
+
*/
|
|
2226
|
+
var MigrationHistoryCommand = class extends Command {
|
|
2227
|
+
signature = `migrate:history
|
|
2228
|
+
{--state-file= : Path to applied migration state file}
|
|
2229
|
+
{--reset : Clear tracked migration history file}
|
|
2230
|
+
{--delete : Delete tracked migration history file}
|
|
2231
|
+
{--json : Print raw JSON output}
|
|
2232
|
+
`;
|
|
2233
|
+
description = "Inspect or reset tracked migration history";
|
|
2234
|
+
async handle() {
|
|
2235
|
+
this.app.command = this;
|
|
2236
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2237
|
+
if (this.option("delete")) {
|
|
2238
|
+
if (!existsSync$1(stateFilePath)) {
|
|
2239
|
+
this.success(`No migration state file found at ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2240
|
+
return;
|
|
2241
|
+
}
|
|
2242
|
+
rmSync$1(stateFilePath);
|
|
2243
|
+
this.success(`Deleted migration state file: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2244
|
+
return;
|
|
2245
|
+
}
|
|
2246
|
+
if (this.option("reset")) {
|
|
2247
|
+
writeAppliedMigrationsState(stateFilePath, {
|
|
2248
|
+
version: 1,
|
|
2249
|
+
migrations: []
|
|
2250
|
+
});
|
|
2251
|
+
this.success(`Reset migration state: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2252
|
+
return;
|
|
2253
|
+
}
|
|
2254
|
+
const state = readAppliedMigrationsState(stateFilePath);
|
|
2255
|
+
if (this.option("json")) {
|
|
2256
|
+
this.success(JSON.stringify({
|
|
2257
|
+
path: stateFilePath,
|
|
2258
|
+
...state
|
|
2259
|
+
}, null, 2));
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
2262
|
+
this.success(this.app.splitLogger("State", stateFilePath));
|
|
2263
|
+
this.success(this.app.splitLogger("Tracked", String(state.migrations.length)));
|
|
2264
|
+
if (state.migrations.length === 0) {
|
|
2265
|
+
this.success("No tracked migrations found.");
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
state.migrations.sort((left, right) => left.appliedAt.localeCompare(right.appliedAt)).forEach((migration) => {
|
|
2269
|
+
this.success(this.app.splitLogger("Applied", `${migration.id} @ ${migration.appliedAt}`));
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
};
|
|
2273
|
+
|
|
2122
2274
|
//#endregion
|
|
2123
2275
|
//#region src/cli/commands/ModelsSyncCommand.ts
|
|
2124
2276
|
var ModelsSyncCommand = class extends Command {
|
|
@@ -5087,4 +5239,4 @@ var Model = class Model {
|
|
|
5087
5239
|
};
|
|
5088
5240
|
|
|
5089
5241
|
//#endregion
|
|
5090
|
-
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationSource, buildModelBlock, buildRelationLine, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|
|
5242
|
+
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, MigrationHistoryCommand, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationSource, buildModelBlock, buildRelationLine, computeMigrationChecksum, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, loadArkormConfig, markMigrationApplied, pad, readAppliedMigrationsState, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName, writeAppliedMigrationsState };
|