arkormx 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +380 -78
- package/dist/index.cjs +328 -12
- package/dist/index.d.cts +74 -1
- package/dist/index.d.mts +74 -1
- package/dist/index.mjs +379 -79
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -26,17 +26,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
}) : target, mod));
|
|
27
27
|
|
|
28
28
|
//#endregion
|
|
29
|
-
let fs = require("fs");
|
|
30
|
-
let path = require("path");
|
|
31
|
-
path = __toESM(path);
|
|
32
|
-
let module$1 = require("module");
|
|
33
29
|
let node_fs = require("node:fs");
|
|
34
30
|
let node_path = require("node:path");
|
|
35
31
|
let node_child_process = require("node:child_process");
|
|
36
32
|
let _h3ravel_support = require("@h3ravel/support");
|
|
33
|
+
let path = require("path");
|
|
34
|
+
path = __toESM(path);
|
|
35
|
+
let fs = require("fs");
|
|
37
36
|
let url = require("url");
|
|
37
|
+
let module$1 = require("module");
|
|
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
|
|
|
@@ -1151,6 +1152,26 @@ const applyMigrationToPrismaSchema = async (migration, options = {}) => {
|
|
|
1151
1152
|
};
|
|
1152
1153
|
};
|
|
1153
1154
|
/**
|
|
1155
|
+
* Apply the rollback (down) operations defined in a migration to a Prisma schema file.
|
|
1156
|
+
*
|
|
1157
|
+
* @param migration The migration class or instance to rollback.
|
|
1158
|
+
* @param options Options for applying the rollback, including schema path and write flag.
|
|
1159
|
+
* @returns A promise that resolves to an object containing the updated schema, schema path, and rollback operations applied.
|
|
1160
|
+
*/
|
|
1161
|
+
const applyMigrationRollbackToPrismaSchema = async (migration, options = {}) => {
|
|
1162
|
+
const schemaPath = options.schemaPath ?? (0, node_path.join)(process.cwd(), "prisma", "schema.prisma");
|
|
1163
|
+
if (!(0, node_fs.existsSync)(schemaPath)) throw new ArkormException(`Prisma schema file not found: ${schemaPath}`);
|
|
1164
|
+
const source = (0, node_fs.readFileSync)(schemaPath, "utf-8");
|
|
1165
|
+
const operations = await getMigrationPlan(migration, "down");
|
|
1166
|
+
const schema = applyOperationsToPrismaSchema(source, operations);
|
|
1167
|
+
if (options.write ?? true) (0, node_fs.writeFileSync)(schemaPath, schema);
|
|
1168
|
+
return {
|
|
1169
|
+
schema,
|
|
1170
|
+
schemaPath,
|
|
1171
|
+
operations
|
|
1172
|
+
};
|
|
1173
|
+
};
|
|
1174
|
+
/**
|
|
1154
1175
|
* Run a migration by applying its schema operations to a Prisma schema
|
|
1155
1176
|
* file, optionally generating Prisma client code and running migrations after
|
|
1156
1177
|
* applying the schema changes.
|
|
@@ -1701,7 +1722,9 @@ var CliApp = class {
|
|
|
1701
1722
|
name: "id",
|
|
1702
1723
|
type: "id",
|
|
1703
1724
|
primary: true
|
|
1704
|
-
}]
|
|
1725
|
+
}],
|
|
1726
|
+
indexes: [],
|
|
1727
|
+
foreignKeys: []
|
|
1705
1728
|
}));
|
|
1706
1729
|
return {
|
|
1707
1730
|
path: schemaPath,
|
|
@@ -1753,14 +1776,14 @@ var CliApp = class {
|
|
|
1753
1776
|
body.split("\n").forEach((rawLine) => {
|
|
1754
1777
|
const line = rawLine.trim();
|
|
1755
1778
|
if (!line || line.startsWith("@@") || line.startsWith("//")) return;
|
|
1756
|
-
const fieldMatch = line.match(/^(\w+)\s+([A-Za-z]+)(\?)
|
|
1779
|
+
const fieldMatch = line.match(/^(\w+)\s+([A-Za-z]+)(\?)?(?:\s|$)/);
|
|
1757
1780
|
if (!fieldMatch) return;
|
|
1758
1781
|
const fieldType = fieldMatch[2];
|
|
1759
1782
|
if (!scalarTypes.has(fieldType)) return;
|
|
1760
1783
|
fields.push({
|
|
1761
1784
|
name: fieldMatch[1],
|
|
1762
1785
|
type: this.prismaTypeToTs(fieldType),
|
|
1763
|
-
|
|
1786
|
+
nullable: Boolean(fieldMatch[3])
|
|
1764
1787
|
});
|
|
1765
1788
|
});
|
|
1766
1789
|
models.push({
|
|
@@ -1851,7 +1874,7 @@ var CliApp = class {
|
|
|
1851
1874
|
skipped.push(filePath);
|
|
1852
1875
|
return;
|
|
1853
1876
|
}
|
|
1854
|
-
const declarations = prismaModel.fields.map((field) => `declare ${field.name}${field.
|
|
1877
|
+
const declarations = prismaModel.fields.map((field) => `declare ${field.name}: ${field.type}${field.nullable ? " | null" : ""}`);
|
|
1855
1878
|
const synced = this.syncModelDeclarations(source, declarations);
|
|
1856
1879
|
if (!synced.updated) {
|
|
1857
1880
|
skipped.push(filePath);
|
|
@@ -2031,6 +2054,98 @@ var MakeSeederCommand = class extends _h3ravel_musket.Command {
|
|
|
2031
2054
|
}
|
|
2032
2055
|
};
|
|
2033
2056
|
|
|
2057
|
+
//#endregion
|
|
2058
|
+
//#region src/helpers/migration-history.ts
|
|
2059
|
+
const DEFAULT_STATE = {
|
|
2060
|
+
version: 1,
|
|
2061
|
+
migrations: [],
|
|
2062
|
+
runs: []
|
|
2063
|
+
};
|
|
2064
|
+
const resolveMigrationStateFilePath = (cwd, configuredPath) => {
|
|
2065
|
+
if (configuredPath && configuredPath.trim().length > 0) return (0, node_path.resolve)(configuredPath);
|
|
2066
|
+
return (0, node_path.join)(cwd, ".arkormx", "migrations.applied.json");
|
|
2067
|
+
};
|
|
2068
|
+
const buildMigrationIdentity = (filePath, className) => {
|
|
2069
|
+
const fileName = filePath.split("/").pop()?.split("\\").pop() ?? filePath;
|
|
2070
|
+
return `${fileName.slice(0, fileName.length - (0, node_path.extname)(fileName).length)}:${className}`;
|
|
2071
|
+
};
|
|
2072
|
+
const computeMigrationChecksum = (filePath) => {
|
|
2073
|
+
const source = (0, node_fs.readFileSync)(filePath, "utf-8");
|
|
2074
|
+
return (0, node_crypto.createHash)("sha256").update(source).digest("hex");
|
|
2075
|
+
};
|
|
2076
|
+
const readAppliedMigrationsState = (stateFilePath) => {
|
|
2077
|
+
if (!(0, node_fs.existsSync)(stateFilePath)) return { ...DEFAULT_STATE };
|
|
2078
|
+
try {
|
|
2079
|
+
const parsed = JSON.parse((0, node_fs.readFileSync)(stateFilePath, "utf-8"));
|
|
2080
|
+
if (!Array.isArray(parsed.migrations)) return { ...DEFAULT_STATE };
|
|
2081
|
+
return {
|
|
2082
|
+
version: 1,
|
|
2083
|
+
migrations: parsed.migrations.filter((migration) => {
|
|
2084
|
+
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");
|
|
2085
|
+
}),
|
|
2086
|
+
runs: Array.isArray(parsed.runs) ? parsed.runs.filter((run) => {
|
|
2087
|
+
return typeof run?.id === "string" && typeof run?.appliedAt === "string" && Array.isArray(run?.migrationIds) && run.migrationIds.every((item) => typeof item === "string");
|
|
2088
|
+
}) : []
|
|
2089
|
+
};
|
|
2090
|
+
} catch {
|
|
2091
|
+
return { ...DEFAULT_STATE };
|
|
2092
|
+
}
|
|
2093
|
+
};
|
|
2094
|
+
const writeAppliedMigrationsState = (stateFilePath, state) => {
|
|
2095
|
+
const directory = (0, node_path.dirname)(stateFilePath);
|
|
2096
|
+
if (!(0, node_fs.existsSync)(directory)) (0, node_fs.mkdirSync)(directory, { recursive: true });
|
|
2097
|
+
(0, node_fs.writeFileSync)(stateFilePath, JSON.stringify(state, null, 2));
|
|
2098
|
+
};
|
|
2099
|
+
const isMigrationApplied = (state, identity, checksum) => {
|
|
2100
|
+
const matched = state.migrations.find((migration) => migration.id === identity);
|
|
2101
|
+
if (!matched) return false;
|
|
2102
|
+
if (checksum && matched.checksum) return matched.checksum === checksum;
|
|
2103
|
+
if (checksum && !matched.checksum) return false;
|
|
2104
|
+
return true;
|
|
2105
|
+
};
|
|
2106
|
+
const findAppliedMigration = (state, identity) => {
|
|
2107
|
+
return state.migrations.find((migration) => migration.id === identity);
|
|
2108
|
+
};
|
|
2109
|
+
const markMigrationApplied = (state, entry) => {
|
|
2110
|
+
const next = state.migrations.filter((migration) => migration.id !== entry.id);
|
|
2111
|
+
next.push(entry);
|
|
2112
|
+
return {
|
|
2113
|
+
version: 1,
|
|
2114
|
+
migrations: next,
|
|
2115
|
+
runs: state.runs ?? []
|
|
2116
|
+
};
|
|
2117
|
+
};
|
|
2118
|
+
const removeAppliedMigration = (state, identity) => {
|
|
2119
|
+
return {
|
|
2120
|
+
version: 1,
|
|
2121
|
+
migrations: state.migrations.filter((migration) => migration.id !== identity),
|
|
2122
|
+
runs: (state.runs ?? []).map((run) => ({
|
|
2123
|
+
...run,
|
|
2124
|
+
migrationIds: run.migrationIds.filter((id) => id !== identity)
|
|
2125
|
+
})).filter((run) => run.migrationIds.length > 0)
|
|
2126
|
+
};
|
|
2127
|
+
};
|
|
2128
|
+
const buildMigrationRunId = () => {
|
|
2129
|
+
return `run_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
2130
|
+
};
|
|
2131
|
+
const markMigrationRun = (state, run) => {
|
|
2132
|
+
const nextRuns = (state.runs ?? []).filter((existing) => existing.id !== run.id);
|
|
2133
|
+
nextRuns.push(run);
|
|
2134
|
+
return {
|
|
2135
|
+
version: 1,
|
|
2136
|
+
migrations: state.migrations,
|
|
2137
|
+
runs: nextRuns
|
|
2138
|
+
};
|
|
2139
|
+
};
|
|
2140
|
+
const getLastMigrationRun = (state) => {
|
|
2141
|
+
const runs = state.runs ?? [];
|
|
2142
|
+
if (runs.length === 0) return void 0;
|
|
2143
|
+
return [...runs].sort((left, right) => right.appliedAt.localeCompare(left.appliedAt))[0];
|
|
2144
|
+
};
|
|
2145
|
+
const getLatestAppliedMigrations = (state, steps) => {
|
|
2146
|
+
return [...state.migrations].sort((left, right) => right.appliedAt.localeCompare(left.appliedAt)).slice(0, Math.max(0, steps));
|
|
2147
|
+
};
|
|
2148
|
+
|
|
2034
2149
|
//#endregion
|
|
2035
2150
|
//#region src/database/Migration.ts
|
|
2036
2151
|
const MIGRATION_BRAND = Symbol.for("arkormx.migration");
|
|
@@ -2062,6 +2177,7 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2062
2177
|
{--deploy : Use prisma migrate deploy instead of migrate dev}
|
|
2063
2178
|
{--skip-generate : Skip prisma generate}
|
|
2064
2179
|
{--skip-migrate : Skip prisma migrate command}
|
|
2180
|
+
{--state-file= : Path to applied migration state file}
|
|
2065
2181
|
{--schema= : Explicit prisma schema path}
|
|
2066
2182
|
{--migration-name= : Name for prisma migrate dev}
|
|
2067
2183
|
`;
|
|
@@ -2083,10 +2199,53 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2083
2199
|
const schemaPath = this.option("schema") ? (0, node_path.resolve)(String(this.option("schema"))) : (0, node_path.join)(process.cwd(), "prisma", "schema.prisma");
|
|
2084
2200
|
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
2201
|
if (classes.length === 0) return void this.error("Error: No migration classes found to run.");
|
|
2086
|
-
|
|
2202
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2203
|
+
let appliedState = readAppliedMigrationsState(stateFilePath);
|
|
2204
|
+
const skipped = [];
|
|
2205
|
+
const changed = [];
|
|
2206
|
+
const pending = classes.filter(([migrationClass, file]) => {
|
|
2207
|
+
if (!appliedState) return true;
|
|
2208
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2209
|
+
const checksum = computeMigrationChecksum(file);
|
|
2210
|
+
const alreadyApplied = isMigrationApplied(appliedState, identity, checksum);
|
|
2211
|
+
if (alreadyApplied) skipped.push([migrationClass, file]);
|
|
2212
|
+
else if (findAppliedMigration(appliedState, identity)) changed.push([migrationClass, file]);
|
|
2213
|
+
return !alreadyApplied;
|
|
2214
|
+
});
|
|
2215
|
+
skipped.forEach(([migrationClass, file]) => {
|
|
2216
|
+
this.success(this.app.splitLogger("Skipped", `${file} (${migrationClass.name})`));
|
|
2217
|
+
});
|
|
2218
|
+
changed.forEach(([migrationClass, file]) => {
|
|
2219
|
+
this.success(this.app.splitLogger("Changed", `${file} (${migrationClass.name})`));
|
|
2220
|
+
});
|
|
2221
|
+
if (pending.length === 0) {
|
|
2222
|
+
this.success("No pending migration classes to apply.");
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
for (const [MigrationClassItem] of pending) await applyMigrationToPrismaSchema(MigrationClassItem, {
|
|
2087
2226
|
schemaPath,
|
|
2088
2227
|
write: true
|
|
2089
2228
|
});
|
|
2229
|
+
if (appliedState) {
|
|
2230
|
+
const runAppliedIds = [];
|
|
2231
|
+
for (const [migrationClass, file] of pending) {
|
|
2232
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2233
|
+
appliedState = markMigrationApplied(appliedState, {
|
|
2234
|
+
id: identity,
|
|
2235
|
+
file,
|
|
2236
|
+
className: migrationClass.name,
|
|
2237
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2238
|
+
checksum: computeMigrationChecksum(file)
|
|
2239
|
+
});
|
|
2240
|
+
runAppliedIds.push(identity);
|
|
2241
|
+
}
|
|
2242
|
+
appliedState = markMigrationRun(appliedState, {
|
|
2243
|
+
id: buildMigrationRunId(),
|
|
2244
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2245
|
+
migrationIds: runAppliedIds
|
|
2246
|
+
});
|
|
2247
|
+
writeAppliedMigrationsState(stateFilePath, appliedState);
|
|
2248
|
+
}
|
|
2090
2249
|
if (!this.option("skip-generate")) runPrismaCommand(["generate"], process.cwd());
|
|
2091
2250
|
if (!this.option("skip-migrate")) if (this.option("deploy")) runPrismaCommand(["migrate", "deploy"], process.cwd());
|
|
2092
2251
|
else runPrismaCommand([
|
|
@@ -2095,8 +2254,8 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2095
2254
|
"--name",
|
|
2096
2255
|
this.option("migration-name") ? String(this.option("migration-name")) : `arkorm_cli_${Date.now()}`
|
|
2097
2256
|
], process.cwd());
|
|
2098
|
-
this.success(`Applied ${
|
|
2099
|
-
|
|
2257
|
+
this.success(`Applied ${pending.length} migration(s).`);
|
|
2258
|
+
pending.forEach(([_, file]) => this.success(this.app.splitLogger("Migrated", file)));
|
|
2100
2259
|
}
|
|
2101
2260
|
/**
|
|
2102
2261
|
* Load all migration classes from the specified directory.
|
|
@@ -2148,6 +2307,147 @@ var MigrateCommand = class extends _h3ravel_musket.Command {
|
|
|
2148
2307
|
}
|
|
2149
2308
|
};
|
|
2150
2309
|
|
|
2310
|
+
//#endregion
|
|
2311
|
+
//#region src/cli/commands/MigrateRollbackCommand.ts
|
|
2312
|
+
/**
|
|
2313
|
+
* Rollback migration classes from the Prisma schema and run Prisma workflow.
|
|
2314
|
+
* By default, rolls back classes applied in the last migrate run.
|
|
2315
|
+
*
|
|
2316
|
+
* @author Legacy (3m1n3nc3)
|
|
2317
|
+
* @since 0.2.4
|
|
2318
|
+
*/
|
|
2319
|
+
var MigrateRollbackCommand = class extends _h3ravel_musket.Command {
|
|
2320
|
+
signature = `migrate:rollback
|
|
2321
|
+
{--step= : Number of latest applied migration classes to rollback}
|
|
2322
|
+
{--dry-run : Preview rollback targets without applying changes}
|
|
2323
|
+
{--deploy : Use prisma migrate deploy instead of migrate dev}
|
|
2324
|
+
{--skip-generate : Skip prisma generate}
|
|
2325
|
+
{--skip-migrate : Skip prisma migrate command}
|
|
2326
|
+
{--state-file= : Path to applied migration state file}
|
|
2327
|
+
{--schema= : Explicit prisma schema path}
|
|
2328
|
+
{--migration-name= : Name for prisma migrate dev}
|
|
2329
|
+
`;
|
|
2330
|
+
description = "Rollback migration classes from schema.prisma and run Prisma workflow";
|
|
2331
|
+
async handle() {
|
|
2332
|
+
this.app.command = this;
|
|
2333
|
+
const configuredMigrationsDir = this.app.getConfig("paths")?.migrations ?? (0, node_path.join)(process.cwd(), "database", "migrations");
|
|
2334
|
+
const migrationsDir = this.app.resolveRuntimeDirectoryPath(configuredMigrationsDir);
|
|
2335
|
+
if (!(0, node_fs.existsSync)(migrationsDir)) return void this.error(`Error: Migrations directory not found: ${this.app.formatPathForLog(configuredMigrationsDir)}`);
|
|
2336
|
+
const schemaPath = this.option("schema") ? (0, node_path.resolve)(String(this.option("schema"))) : (0, node_path.join)(process.cwd(), "prisma", "schema.prisma");
|
|
2337
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2338
|
+
let appliedState = readAppliedMigrationsState(stateFilePath);
|
|
2339
|
+
const stepOption = this.option("step");
|
|
2340
|
+
const stepCount = stepOption == null ? void 0 : Number(stepOption);
|
|
2341
|
+
if (stepCount != null && (!Number.isFinite(stepCount) || stepCount <= 0 || !Number.isInteger(stepCount))) return void this.error("Error: --step must be a positive integer.");
|
|
2342
|
+
const targets = stepCount ? getLatestAppliedMigrations(appliedState, stepCount) : (() => {
|
|
2343
|
+
const lastRun = getLastMigrationRun(appliedState);
|
|
2344
|
+
if (!lastRun) return [];
|
|
2345
|
+
return lastRun.migrationIds.map((id) => appliedState.migrations.find((migration) => migration.id === id)).filter((migration) => Boolean(migration));
|
|
2346
|
+
})();
|
|
2347
|
+
if (targets.length === 0) return void this.error("Error: No tracked migrations available to rollback.");
|
|
2348
|
+
const available = await this.loadAllMigrations(migrationsDir);
|
|
2349
|
+
const rollbackClasses = targets.map((target) => {
|
|
2350
|
+
return available.find(([migrationClass, file]) => {
|
|
2351
|
+
return buildMigrationIdentity(file, migrationClass.name) === target.id || migrationClass.name === target.className;
|
|
2352
|
+
});
|
|
2353
|
+
}).filter((entry) => Boolean(entry));
|
|
2354
|
+
if (rollbackClasses.length === 0) return void this.error("Error: Unable to resolve rollback migration classes from tracked history.");
|
|
2355
|
+
if (this.option("dry-run")) {
|
|
2356
|
+
this.success(`Dry run: ${rollbackClasses.length} migration(s) would be rolled back.`);
|
|
2357
|
+
rollbackClasses.forEach(([_, file]) => this.success(this.app.splitLogger("WouldRollback", file)));
|
|
2358
|
+
return;
|
|
2359
|
+
}
|
|
2360
|
+
for (const [MigrationClassItem] of rollbackClasses) await applyMigrationRollbackToPrismaSchema(MigrationClassItem, {
|
|
2361
|
+
schemaPath,
|
|
2362
|
+
write: true
|
|
2363
|
+
});
|
|
2364
|
+
for (const [migrationClass, file] of rollbackClasses) {
|
|
2365
|
+
const identity = buildMigrationIdentity(file, migrationClass.name);
|
|
2366
|
+
appliedState = removeAppliedMigration(appliedState, identity);
|
|
2367
|
+
}
|
|
2368
|
+
writeAppliedMigrationsState(stateFilePath, appliedState);
|
|
2369
|
+
if (!this.option("skip-generate")) runPrismaCommand(["generate"], process.cwd());
|
|
2370
|
+
if (!this.option("skip-migrate")) if (this.option("deploy")) runPrismaCommand(["migrate", "deploy"], process.cwd());
|
|
2371
|
+
else runPrismaCommand([
|
|
2372
|
+
"migrate",
|
|
2373
|
+
"dev",
|
|
2374
|
+
"--name",
|
|
2375
|
+
this.option("migration-name") ? String(this.option("migration-name")) : `arkorm_cli_rollback_${Date.now()}`
|
|
2376
|
+
], process.cwd());
|
|
2377
|
+
this.success(`Rolled back ${rollbackClasses.length} migration(s).`);
|
|
2378
|
+
rollbackClasses.forEach(([_, file]) => this.success(this.app.splitLogger("RolledBack", file)));
|
|
2379
|
+
}
|
|
2380
|
+
async loadAllMigrations(migrationsDir) {
|
|
2381
|
+
const files = (0, node_fs.readdirSync)(migrationsDir).filter((file) => /\.(ts|js|mjs|cjs)$/i.test(file)).sort((left, right) => left.localeCompare(right)).map((file) => this.app.resolveRuntimeScriptPath((0, node_path.join)(migrationsDir, file)));
|
|
2382
|
+
return (await Promise.all(files.map(async (file) => (await this.loadMigrationClassesFromFile(file)).map((cls) => [cls, file])))).flat();
|
|
2383
|
+
}
|
|
2384
|
+
async loadMigrationClassesFromFile(filePath) {
|
|
2385
|
+
const imported = await import(`${(0, node_url.pathToFileURL)((0, node_path.resolve)(filePath)).href}?arkorm_rollback=${Date.now()}`);
|
|
2386
|
+
return Object.values(imported).filter((value) => {
|
|
2387
|
+
if (typeof value !== "function") return false;
|
|
2388
|
+
const candidate = value;
|
|
2389
|
+
const prototype = candidate.prototype;
|
|
2390
|
+
return candidate[MIGRATION_BRAND] === true || typeof prototype?.up === "function" && typeof prototype?.down === "function";
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2393
|
+
};
|
|
2394
|
+
|
|
2395
|
+
//#endregion
|
|
2396
|
+
//#region src/cli/commands/MigrationHistoryCommand.ts
|
|
2397
|
+
/**
|
|
2398
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2399
|
+
*
|
|
2400
|
+
* @author Legacy (3m1n3nc3)
|
|
2401
|
+
* @since 0.2.4
|
|
2402
|
+
*/
|
|
2403
|
+
var MigrationHistoryCommand = class extends _h3ravel_musket.Command {
|
|
2404
|
+
signature = `migrate:history
|
|
2405
|
+
{--state-file= : Path to applied migration state file}
|
|
2406
|
+
{--reset : Clear tracked migration history file}
|
|
2407
|
+
{--delete : Delete tracked migration history file}
|
|
2408
|
+
{--json : Print raw JSON output}
|
|
2409
|
+
`;
|
|
2410
|
+
description = "Inspect or reset tracked migration history";
|
|
2411
|
+
async handle() {
|
|
2412
|
+
this.app.command = this;
|
|
2413
|
+
const stateFilePath = resolveMigrationStateFilePath(process.cwd(), this.option("state-file") ? String(this.option("state-file")) : void 0);
|
|
2414
|
+
if (this.option("delete")) {
|
|
2415
|
+
if (!(0, node_fs.existsSync)(stateFilePath)) {
|
|
2416
|
+
this.success(`No migration state file found at ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
(0, node_fs.rmSync)(stateFilePath);
|
|
2420
|
+
this.success(`Deleted migration state file: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2423
|
+
if (this.option("reset")) {
|
|
2424
|
+
writeAppliedMigrationsState(stateFilePath, {
|
|
2425
|
+
version: 1,
|
|
2426
|
+
migrations: []
|
|
2427
|
+
});
|
|
2428
|
+
this.success(`Reset migration state: ${this.app.formatPathForLog(stateFilePath)}`);
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
const state = readAppliedMigrationsState(stateFilePath);
|
|
2432
|
+
if (this.option("json")) {
|
|
2433
|
+
this.success(JSON.stringify({
|
|
2434
|
+
path: stateFilePath,
|
|
2435
|
+
...state
|
|
2436
|
+
}, null, 2));
|
|
2437
|
+
return;
|
|
2438
|
+
}
|
|
2439
|
+
this.success(this.app.splitLogger("State", stateFilePath));
|
|
2440
|
+
this.success(this.app.splitLogger("Tracked", String(state.migrations.length)));
|
|
2441
|
+
if (state.migrations.length === 0) {
|
|
2442
|
+
this.success("No tracked migrations found.");
|
|
2443
|
+
return;
|
|
2444
|
+
}
|
|
2445
|
+
state.migrations.sort((left, right) => left.appliedAt.localeCompare(right.appliedAt)).forEach((migration) => {
|
|
2446
|
+
this.success(this.app.splitLogger("Applied", `${migration.id} @ ${migration.appliedAt}`));
|
|
2447
|
+
});
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
|
|
2151
2451
|
//#endregion
|
|
2152
2452
|
//#region src/cli/commands/ModelsSyncCommand.ts
|
|
2153
2453
|
var ModelsSyncCommand = class extends _h3ravel_musket.Command {
|
|
@@ -5129,7 +5429,9 @@ exports.MakeMigrationCommand = MakeMigrationCommand;
|
|
|
5129
5429
|
exports.MakeModelCommand = MakeModelCommand;
|
|
5130
5430
|
exports.MakeSeederCommand = MakeSeederCommand;
|
|
5131
5431
|
exports.MigrateCommand = MigrateCommand;
|
|
5432
|
+
exports.MigrateRollbackCommand = MigrateRollbackCommand;
|
|
5132
5433
|
exports.Migration = Migration;
|
|
5434
|
+
exports.MigrationHistoryCommand = MigrationHistoryCommand;
|
|
5133
5435
|
exports.Model = Model;
|
|
5134
5436
|
exports.ModelFactory = ModelFactory;
|
|
5135
5437
|
exports.ModelNotFoundException = ModelNotFoundException;
|
|
@@ -5146,14 +5448,18 @@ exports.URLDriver = URLDriver;
|
|
|
5146
5448
|
exports.applyAlterTableOperation = applyAlterTableOperation;
|
|
5147
5449
|
exports.applyCreateTableOperation = applyCreateTableOperation;
|
|
5148
5450
|
exports.applyDropTableOperation = applyDropTableOperation;
|
|
5451
|
+
exports.applyMigrationRollbackToPrismaSchema = applyMigrationRollbackToPrismaSchema;
|
|
5149
5452
|
exports.applyMigrationToPrismaSchema = applyMigrationToPrismaSchema;
|
|
5150
5453
|
exports.applyOperationsToPrismaSchema = applyOperationsToPrismaSchema;
|
|
5151
5454
|
exports.buildFieldLine = buildFieldLine;
|
|
5152
5455
|
exports.buildIndexLine = buildIndexLine;
|
|
5153
5456
|
exports.buildInverseRelationLine = buildInverseRelationLine;
|
|
5457
|
+
exports.buildMigrationIdentity = buildMigrationIdentity;
|
|
5458
|
+
exports.buildMigrationRunId = buildMigrationRunId;
|
|
5154
5459
|
exports.buildMigrationSource = buildMigrationSource;
|
|
5155
5460
|
exports.buildModelBlock = buildModelBlock;
|
|
5156
5461
|
exports.buildRelationLine = buildRelationLine;
|
|
5462
|
+
exports.computeMigrationChecksum = computeMigrationChecksum;
|
|
5157
5463
|
exports.configureArkormRuntime = configureArkormRuntime;
|
|
5158
5464
|
exports.createMigrationTimestamp = createMigrationTimestamp;
|
|
5159
5465
|
exports.createPrismaAdapter = createPrismaAdapter;
|
|
@@ -5165,24 +5471,34 @@ exports.deriveInverseRelationAlias = deriveInverseRelationAlias;
|
|
|
5165
5471
|
exports.deriveRelationFieldName = deriveRelationFieldName;
|
|
5166
5472
|
exports.ensureArkormConfigLoading = ensureArkormConfigLoading;
|
|
5167
5473
|
exports.escapeRegex = escapeRegex;
|
|
5474
|
+
exports.findAppliedMigration = findAppliedMigration;
|
|
5168
5475
|
exports.findModelBlock = findModelBlock;
|
|
5169
5476
|
exports.formatDefaultValue = formatDefaultValue;
|
|
5170
5477
|
exports.formatRelationAction = formatRelationAction;
|
|
5171
5478
|
exports.generateMigrationFile = generateMigrationFile;
|
|
5172
5479
|
exports.getDefaultStubsPath = getDefaultStubsPath;
|
|
5480
|
+
exports.getLastMigrationRun = getLastMigrationRun;
|
|
5481
|
+
exports.getLatestAppliedMigrations = getLatestAppliedMigrations;
|
|
5173
5482
|
exports.getMigrationPlan = getMigrationPlan;
|
|
5174
5483
|
exports.getRuntimePaginationURLDriverFactory = getRuntimePaginationURLDriverFactory;
|
|
5175
5484
|
exports.getRuntimePrismaClient = getRuntimePrismaClient;
|
|
5176
5485
|
exports.getUserConfig = getUserConfig;
|
|
5177
5486
|
exports.inferDelegateName = inferDelegateName;
|
|
5178
5487
|
exports.isDelegateLike = isDelegateLike;
|
|
5488
|
+
exports.isMigrationApplied = isMigrationApplied;
|
|
5179
5489
|
exports.loadArkormConfig = loadArkormConfig;
|
|
5490
|
+
exports.markMigrationApplied = markMigrationApplied;
|
|
5491
|
+
exports.markMigrationRun = markMigrationRun;
|
|
5180
5492
|
exports.pad = pad;
|
|
5493
|
+
exports.readAppliedMigrationsState = readAppliedMigrationsState;
|
|
5494
|
+
exports.removeAppliedMigration = removeAppliedMigration;
|
|
5181
5495
|
exports.resetArkormRuntimeForTests = resetArkormRuntimeForTests;
|
|
5182
5496
|
exports.resolveCast = resolveCast;
|
|
5183
5497
|
exports.resolveMigrationClassName = resolveMigrationClassName;
|
|
5498
|
+
exports.resolveMigrationStateFilePath = resolveMigrationStateFilePath;
|
|
5184
5499
|
exports.resolvePrismaType = resolvePrismaType;
|
|
5185
5500
|
exports.runMigrationWithPrisma = runMigrationWithPrisma;
|
|
5186
5501
|
exports.runPrismaCommand = runPrismaCommand;
|
|
5187
5502
|
exports.toMigrationFileSlug = toMigrationFileSlug;
|
|
5188
|
-
exports.toModelName = toModelName;
|
|
5503
|
+
exports.toModelName = toModelName;
|
|
5504
|
+
exports.writeAppliedMigrationsState = writeAppliedMigrationsState;
|
package/dist/index.d.cts
CHANGED
|
@@ -79,6 +79,23 @@ 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 AppliedMigrationRun {
|
|
90
|
+
id: string;
|
|
91
|
+
appliedAt: string;
|
|
92
|
+
migrationIds: string[];
|
|
93
|
+
}
|
|
94
|
+
interface AppliedMigrationsState {
|
|
95
|
+
version: 1;
|
|
96
|
+
migrations: AppliedMigrationEntry[];
|
|
97
|
+
runs?: AppliedMigrationRun[];
|
|
98
|
+
}
|
|
82
99
|
//#endregion
|
|
83
100
|
//#region src/Collection.d.ts
|
|
84
101
|
declare class ArkormCollection<T = any, X = T[]> extends Collection<T, X> {}
|
|
@@ -2251,6 +2268,35 @@ declare class MigrateCommand extends Command<CliApp> {
|
|
|
2251
2268
|
private loadMigrationClassesFromFile;
|
|
2252
2269
|
}
|
|
2253
2270
|
//#endregion
|
|
2271
|
+
//#region src/cli/commands/MigrateRollbackCommand.d.ts
|
|
2272
|
+
/**
|
|
2273
|
+
* Rollback migration classes from the Prisma schema and run Prisma workflow.
|
|
2274
|
+
* By default, rolls back classes applied in the last migrate run.
|
|
2275
|
+
*
|
|
2276
|
+
* @author Legacy (3m1n3nc3)
|
|
2277
|
+
* @since 0.2.4
|
|
2278
|
+
*/
|
|
2279
|
+
declare class MigrateRollbackCommand extends Command<CliApp> {
|
|
2280
|
+
protected signature: string;
|
|
2281
|
+
protected description: string;
|
|
2282
|
+
handle(): Promise<undefined>;
|
|
2283
|
+
private loadAllMigrations;
|
|
2284
|
+
private loadMigrationClassesFromFile;
|
|
2285
|
+
}
|
|
2286
|
+
//#endregion
|
|
2287
|
+
//#region src/cli/commands/MigrationHistoryCommand.d.ts
|
|
2288
|
+
/**
|
|
2289
|
+
* The MigrationHistoryCommand class manages tracked migration run history.
|
|
2290
|
+
*
|
|
2291
|
+
* @author Legacy (3m1n3nc3)
|
|
2292
|
+
* @since 0.2.4
|
|
2293
|
+
*/
|
|
2294
|
+
declare class MigrationHistoryCommand extends Command<CliApp> {
|
|
2295
|
+
protected signature: string;
|
|
2296
|
+
protected description: string;
|
|
2297
|
+
handle(): Promise<void>;
|
|
2298
|
+
}
|
|
2299
|
+
//#endregion
|
|
2254
2300
|
//#region src/cli/commands/ModelsSyncCommand.d.ts
|
|
2255
2301
|
declare class ModelsSyncCommand extends Command<CliApp> {
|
|
2256
2302
|
protected signature: string;
|
|
@@ -2731,6 +2777,21 @@ declare class ModelNotFoundException extends ArkormException {
|
|
|
2731
2777
|
getModelName(): string;
|
|
2732
2778
|
}
|
|
2733
2779
|
//#endregion
|
|
2780
|
+
//#region src/helpers/migration-history.d.ts
|
|
2781
|
+
declare const resolveMigrationStateFilePath: (cwd: string, configuredPath?: string) => string;
|
|
2782
|
+
declare const buildMigrationIdentity: (filePath: string, className: string) => string;
|
|
2783
|
+
declare const computeMigrationChecksum: (filePath: string) => string;
|
|
2784
|
+
declare const readAppliedMigrationsState: (stateFilePath: string) => AppliedMigrationsState;
|
|
2785
|
+
declare const writeAppliedMigrationsState: (stateFilePath: string, state: AppliedMigrationsState) => void;
|
|
2786
|
+
declare const isMigrationApplied: (state: AppliedMigrationsState, identity: string, checksum?: string) => boolean;
|
|
2787
|
+
declare const findAppliedMigration: (state: AppliedMigrationsState, identity: string) => AppliedMigrationEntry | undefined;
|
|
2788
|
+
declare const markMigrationApplied: (state: AppliedMigrationsState, entry: AppliedMigrationEntry) => AppliedMigrationsState;
|
|
2789
|
+
declare const removeAppliedMigration: (state: AppliedMigrationsState, identity: string) => AppliedMigrationsState;
|
|
2790
|
+
declare const buildMigrationRunId: () => string;
|
|
2791
|
+
declare const markMigrationRun: (state: AppliedMigrationsState, run: AppliedMigrationRun) => AppliedMigrationsState;
|
|
2792
|
+
declare const getLastMigrationRun: (state: AppliedMigrationsState) => AppliedMigrationRun | undefined;
|
|
2793
|
+
declare const getLatestAppliedMigrations: (state: AppliedMigrationsState, steps: number) => AppliedMigrationEntry[];
|
|
2794
|
+
//#endregion
|
|
2734
2795
|
//#region src/helpers/migrations.d.ts
|
|
2735
2796
|
declare const PRISMA_MODEL_REGEX: RegExp;
|
|
2736
2797
|
/**
|
|
@@ -2956,6 +3017,18 @@ declare const applyMigrationToPrismaSchema: (migration: Migration | (new () => M
|
|
|
2956
3017
|
schemaPath: string;
|
|
2957
3018
|
operations: SchemaOperation[];
|
|
2958
3019
|
}>;
|
|
3020
|
+
/**
|
|
3021
|
+
* Apply the rollback (down) operations defined in a migration to a Prisma schema file.
|
|
3022
|
+
*
|
|
3023
|
+
* @param migration The migration class or instance to rollback.
|
|
3024
|
+
* @param options Options for applying the rollback, including schema path and write flag.
|
|
3025
|
+
* @returns A promise that resolves to an object containing the updated schema, schema path, and rollback operations applied.
|
|
3026
|
+
*/
|
|
3027
|
+
declare const applyMigrationRollbackToPrismaSchema: (migration: Migration | (new () => Migration), options?: PrismaSchemaSyncOptions) => Promise<{
|
|
3028
|
+
schema: string;
|
|
3029
|
+
schemaPath: string;
|
|
3030
|
+
operations: SchemaOperation[];
|
|
3031
|
+
}>;
|
|
2959
3032
|
/**
|
|
2960
3033
|
* Run a migration by applying its schema operations to a Prisma schema
|
|
2961
3034
|
* file, optionally generating Prisma client code and running migrations after
|
|
@@ -3080,4 +3153,4 @@ declare class URLDriver {
|
|
|
3080
3153
|
url(page: number): string;
|
|
3081
3154
|
}
|
|
3082
3155
|
//#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 };
|
|
3156
|
+
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, MigrateRollbackCommand, 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, applyMigrationRollbackToPrismaSchema, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationIdentity, buildMigrationRunId, buildMigrationSource, buildModelBlock, buildRelationLine, computeMigrationChecksum, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findAppliedMigration, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getLastMigrationRun, getLatestAppliedMigrations, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, isMigrationApplied, loadArkormConfig, markMigrationApplied, markMigrationRun, pad, readAppliedMigrationsState, removeAppliedMigration, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolveMigrationStateFilePath, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName, writeAppliedMigrationsState };
|