@fragno-dev/cli 0.1.2 → 0.1.4
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/.turbo/turbo-build.log +11 -8
- package/CHANGELOG.md +23 -0
- package/LICENSE.md +16 -0
- package/dist/cli.d.ts +33 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +212 -227
- package/dist/cli.js.map +1 -1
- package/package.json +11 -12
- package/src/cli.ts +12 -80
- package/src/commands/db/generate.ts +164 -157
- package/src/commands/db/info.ts +161 -76
- package/src/commands/db/migrate.ts +116 -114
- package/.turbo/turbo-types$colon$check.log +0 -1
|
@@ -1,168 +1,175 @@
|
|
|
1
|
-
import { writeFile,
|
|
2
|
-
import { resolve,
|
|
3
|
-
import
|
|
4
|
-
import { findFragnoDatabases } from "../../utils/find-fragno-databases
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
1
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { resolve, dirname } from "node:path";
|
|
3
|
+
import { define } from "gunshi";
|
|
4
|
+
import { findFragnoDatabases } from "../../utils/find-fragno-databases";
|
|
5
|
+
import type { FragnoDatabase } from "@fragno-dev/db";
|
|
6
|
+
import type { AnySchema } from "@fragno-dev/db/schema";
|
|
7
|
+
import { generateMigrationsOrSchema } from "@fragno-dev/db/generation-engine";
|
|
8
|
+
|
|
9
|
+
// Define the db generate command with type safety
|
|
10
|
+
export const generateCommand = define({
|
|
11
|
+
name: "generate",
|
|
12
|
+
description: "Generate schema files from FragnoDatabase definitions",
|
|
13
|
+
args: {
|
|
14
|
+
output: {
|
|
15
|
+
type: "string",
|
|
16
|
+
short: "o",
|
|
17
|
+
description:
|
|
18
|
+
"Output path: for single file, exact file path; for multiple files, output directory (default: current directory)",
|
|
19
|
+
},
|
|
20
|
+
from: {
|
|
21
|
+
type: "number",
|
|
22
|
+
short: "f",
|
|
23
|
+
description: "Source version to generate migration from (default: current database version)",
|
|
24
|
+
},
|
|
25
|
+
to: {
|
|
26
|
+
type: "number",
|
|
27
|
+
short: "t",
|
|
28
|
+
description: "Target version to generate migration to (default: latest schema version)",
|
|
29
|
+
},
|
|
30
|
+
prefix: {
|
|
31
|
+
type: "string",
|
|
32
|
+
short: "p",
|
|
33
|
+
description: "String to prepend to the generated file (e.g., '/* eslint-disable */')",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
run: async (ctx) => {
|
|
37
|
+
// With `define()` and `multiple: true`, targets is properly typed as string[]
|
|
38
|
+
const targets = ctx.positionals;
|
|
39
|
+
const output = ctx.values.output;
|
|
40
|
+
const toVersion = ctx.values.to;
|
|
41
|
+
const fromVersion = ctx.values.from;
|
|
42
|
+
const prefix = ctx.values.prefix;
|
|
43
|
+
|
|
44
|
+
// De-duplicate targets (in case same file was specified multiple times)
|
|
45
|
+
const uniqueTargets = Array.from(new Set(targets));
|
|
46
|
+
|
|
47
|
+
// Load all target files and collect FragnoDatabase instances
|
|
48
|
+
const allFragnoDatabases: FragnoDatabase<AnySchema>[] = [];
|
|
49
|
+
|
|
50
|
+
for (const target of uniqueTargets) {
|
|
51
|
+
const targetPath = resolve(process.cwd(), target);
|
|
52
|
+
console.log(`Loading target file: ${targetPath}`);
|
|
53
|
+
|
|
54
|
+
// Dynamically import the target file
|
|
55
|
+
let targetModule: Record<string, unknown>;
|
|
56
|
+
try {
|
|
57
|
+
targetModule = await import(targetPath);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Failed to import target file ${target}: ${error instanceof Error ? error.message : String(error)}`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Find all FragnoDatabase instances or instantiated fragments with databases
|
|
65
|
+
const fragnoDatabases = findFragnoDatabases(targetModule);
|
|
66
|
+
|
|
67
|
+
if (fragnoDatabases.length === 0) {
|
|
68
|
+
console.warn(
|
|
69
|
+
`Warning: No FragnoDatabase instances found in ${target}.\n` +
|
|
70
|
+
`Make sure you export either:\n` +
|
|
71
|
+
` - A FragnoDatabase instance created with .create(adapter)\n` +
|
|
72
|
+
` - An instantiated fragment with embedded database definition\n`,
|
|
73
|
+
);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (fragnoDatabases.length > 1) {
|
|
78
|
+
console.warn(
|
|
79
|
+
`Warning: Multiple FragnoDatabase instances found in ${target} (${fragnoDatabases.length}). Using all of them.`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
allFragnoDatabases.push(...fragnoDatabases);
|
|
84
|
+
}
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
86
|
+
if (allFragnoDatabases.length === 0) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`No FragnoDatabase instances found in any of the target files.\n` +
|
|
89
|
+
`Make sure your files export either:\n` +
|
|
90
|
+
` - A FragnoDatabase instance created with .create(adapter)\n` +
|
|
91
|
+
` - An instantiated fragment with embedded database definition\n`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
63
94
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`Warning: Multiple FragnoDatabase instances found (${fragnoDatabases.length}). Using the first one.`,
|
|
95
|
+
console.log(
|
|
96
|
+
`Found ${allFragnoDatabases.length} FragnoDatabase instance(s) across ${uniqueTargets.length} file(s)`,
|
|
67
97
|
);
|
|
68
|
-
}
|
|
69
98
|
|
|
70
|
-
|
|
71
|
-
|
|
99
|
+
// Validate all databases use the same adapter object (identity)
|
|
100
|
+
const firstDb = allFragnoDatabases[0];
|
|
101
|
+
const firstAdapter = firstDb.adapter;
|
|
102
|
+
const allSameAdapter = allFragnoDatabases.every((db) => db.adapter === firstAdapter);
|
|
72
103
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
throw new Error(`Invalid version number: ${toVersion}`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (sourceVersion !== undefined && isNaN(sourceVersion)) {
|
|
82
|
-
throw new Error(`Invalid version number: ${fromVersion}`);
|
|
83
|
-
}
|
|
104
|
+
if (!allSameAdapter) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
"All fragments must use the same database adapter instance. Mixed adapters are not supported.",
|
|
107
|
+
);
|
|
108
|
+
}
|
|
84
109
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
93
|
-
} else if (sourceVersion !== undefined) {
|
|
94
|
-
console.log(
|
|
95
|
-
`Generating schema for namespace: ${fragnoDb.namespace} (from version ${sourceVersion})`,
|
|
96
|
-
);
|
|
97
|
-
} else {
|
|
98
|
-
console.log(`Generating schema for namespace: ${fragnoDb.namespace}`);
|
|
99
|
-
}
|
|
110
|
+
// Check if adapter supports any form of schema generation
|
|
111
|
+
if (!firstDb.adapter.createSchemaGenerator && !firstDb.adapter.createMigrationEngine) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`The adapter does not support schema generation. ` +
|
|
114
|
+
`Please use an adapter that implements either createSchemaGenerator or createMigrationEngine.`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
100
117
|
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
// Generate schema for all fragments
|
|
119
|
+
console.log("Generating schema...");
|
|
103
120
|
|
|
104
|
-
|
|
105
|
-
const resolvedOutput = resolve(process.cwd(), output);
|
|
121
|
+
let results: { schema: string; path: string; namespace: string }[];
|
|
106
122
|
try {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
results = await generateMigrationsOrSchema(allFragnoDatabases, {
|
|
124
|
+
path: output,
|
|
125
|
+
toVersion,
|
|
126
|
+
fromVersion,
|
|
127
|
+
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Failed to generate schema: ${error instanceof Error ? error.message : String(error)}`,
|
|
131
|
+
);
|
|
112
132
|
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Generate schema
|
|
116
|
-
let result: { schema: string; path: string };
|
|
117
|
-
try {
|
|
118
|
-
// If output is a directory, pass undefined to get the default file name
|
|
119
|
-
// Otherwise pass the output path as-is
|
|
120
|
-
result = await fragnoDb.generateSchema({
|
|
121
|
-
path: isDirectory ? undefined : output,
|
|
122
|
-
toVersion: targetVersion,
|
|
123
|
-
fromVersion: sourceVersion,
|
|
124
|
-
});
|
|
125
|
-
} catch (error) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
`Failed to generate schema: ${error instanceof Error ? error.message : String(error)}`,
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Resolve final output path
|
|
132
|
-
let finalOutputPath: string;
|
|
133
|
-
if (isDirectory && output) {
|
|
134
|
-
// Combine directory with generated file name
|
|
135
|
-
const resolvedDir = resolve(process.cwd(), output);
|
|
136
|
-
finalOutputPath = join(resolvedDir, basename(result.path));
|
|
137
|
-
} else if (output) {
|
|
138
|
-
// Use the provided path as-is
|
|
139
|
-
finalOutputPath = resolve(process.cwd(), output);
|
|
140
|
-
} else {
|
|
141
|
-
// Use the generated file name in current directory
|
|
142
|
-
finalOutputPath = resolve(process.cwd(), result.path);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Ensure parent directory exists
|
|
146
|
-
const parentDir = dirname(finalOutputPath);
|
|
147
|
-
try {
|
|
148
|
-
await mkdir(parentDir, { recursive: true });
|
|
149
|
-
} catch (error) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
`Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Write schema to file
|
|
156
|
-
try {
|
|
157
|
-
const content = prefix ? `${prefix}\n${result.schema}` : result.schema;
|
|
158
|
-
await writeFile(finalOutputPath, content, { encoding: "utf-8" });
|
|
159
|
-
} catch (error) {
|
|
160
|
-
throw new Error(
|
|
161
|
-
`Failed to write schema file: ${error instanceof Error ? error.message : String(error)}`,
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
133
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
134
|
+
// Write all generated files
|
|
135
|
+
for (const result of results) {
|
|
136
|
+
// For single file: use output as exact file path
|
|
137
|
+
// For multiple files: use output as base directory
|
|
138
|
+
const finalOutputPath =
|
|
139
|
+
output && results.length === 1
|
|
140
|
+
? resolve(process.cwd(), output)
|
|
141
|
+
: output
|
|
142
|
+
? resolve(process.cwd(), output, result.path)
|
|
143
|
+
: resolve(process.cwd(), result.path);
|
|
144
|
+
|
|
145
|
+
// Ensure parent directory exists
|
|
146
|
+
const parentDir = dirname(finalOutputPath);
|
|
147
|
+
try {
|
|
148
|
+
await mkdir(parentDir, { recursive: true });
|
|
149
|
+
} catch (error) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Write schema to file
|
|
156
|
+
try {
|
|
157
|
+
const content = prefix ? `${prefix}\n${result.schema}` : result.schema;
|
|
158
|
+
await writeFile(finalOutputPath, content, { encoding: "utf-8" });
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Failed to write schema file: ${error instanceof Error ? error.message : String(error)}`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log(`✓ Generated: ${finalOutputPath}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.log(`\n✓ Schema generated successfully!`);
|
|
169
|
+
console.log(` Files generated: ${results.length}`);
|
|
170
|
+
console.log(` Fragments:`);
|
|
171
|
+
for (const db of allFragnoDatabases) {
|
|
172
|
+
console.log(` - ${db.namespace} (version ${db.schema.version})`);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
});
|
package/src/commands/db/info.ts
CHANGED
|
@@ -1,93 +1,178 @@
|
|
|
1
|
-
import { isFragnoDatabase, type FragnoDatabase } from "@fragno-dev/db";
|
|
2
|
-
import type { AnySchema } from "@fragno-dev/db/schema";
|
|
3
1
|
import { resolve } from "node:path";
|
|
4
|
-
import
|
|
2
|
+
import { define } from "gunshi";
|
|
3
|
+
import { findFragnoDatabases } from "../../utils/find-fragno-databases";
|
|
4
|
+
import type { FragnoDatabase } from "@fragno-dev/db";
|
|
5
|
+
import type { AnySchema } from "@fragno-dev/db/schema";
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
-
|
|
7
|
+
export const infoCommand = define({
|
|
8
|
+
name: "info",
|
|
9
|
+
description: "Display database information and migration status",
|
|
10
|
+
args: {},
|
|
11
|
+
run: async (ctx) => {
|
|
12
|
+
const targets = ctx.positionals;
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
if (targets.length === 0) {
|
|
15
|
+
throw new Error("At least one target file path is required");
|
|
16
|
+
}
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
// De-duplicate targets (in case same file was specified multiple times)
|
|
19
|
+
const uniqueTargets = Array.from(new Set(targets));
|
|
20
|
+
|
|
21
|
+
// Load all target files and collect FragnoDatabase instances
|
|
22
|
+
const allFragnoDatabases: FragnoDatabase<AnySchema>[] = [];
|
|
23
|
+
|
|
24
|
+
for (const target of uniqueTargets) {
|
|
25
|
+
const targetPath = resolve(process.cwd(), target);
|
|
26
|
+
console.log(`Loading target file: ${targetPath}`);
|
|
27
|
+
|
|
28
|
+
// Dynamically import the target file
|
|
29
|
+
let targetModule: Record<string, unknown>;
|
|
30
|
+
try {
|
|
31
|
+
targetModule = await import(targetPath);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Failed to import target file ${target}: ${error instanceof Error ? error.message : String(error)}`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Find all FragnoDatabase instances or instantiated fragments with databases
|
|
39
|
+
const fragnoDatabases = findFragnoDatabases(targetModule);
|
|
40
|
+
|
|
41
|
+
if (fragnoDatabases.length === 0) {
|
|
42
|
+
console.warn(
|
|
43
|
+
`Warning: No FragnoDatabase instances found in ${target}.\n` +
|
|
44
|
+
`Make sure you export either:\n` +
|
|
45
|
+
` - A FragnoDatabase instance created with .create(adapter)\n` +
|
|
46
|
+
` - An instantiated fragment with embedded database definition\n`,
|
|
47
|
+
);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (fragnoDatabases.length > 1) {
|
|
52
|
+
console.warn(
|
|
53
|
+
`Warning: Multiple FragnoDatabase instances found in ${target} (${fragnoDatabases.length}). Showing info for all of them.`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
allFragnoDatabases.push(...fragnoDatabases);
|
|
58
|
+
}
|
|
15
59
|
|
|
16
|
-
|
|
60
|
+
if (allFragnoDatabases.length === 0) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`No FragnoDatabase instances found in any of the target files.\n` +
|
|
63
|
+
`Make sure your files export either:\n` +
|
|
64
|
+
` - A FragnoDatabase instance created with .create(adapter)\n` +
|
|
65
|
+
` - An instantiated fragment with embedded database definition\n`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
17
68
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
69
|
+
// Collect database information
|
|
70
|
+
const dbInfos = await Promise.all(
|
|
71
|
+
allFragnoDatabases.map(async (fragnoDb) => {
|
|
72
|
+
const info: {
|
|
73
|
+
namespace: string;
|
|
74
|
+
schemaVersion: number;
|
|
75
|
+
migrationSupport: boolean;
|
|
76
|
+
currentVersion?: number;
|
|
77
|
+
pendingVersions?: number;
|
|
78
|
+
status?: string;
|
|
79
|
+
error?: string;
|
|
80
|
+
} = {
|
|
81
|
+
namespace: fragnoDb.namespace,
|
|
82
|
+
schemaVersion: fragnoDb.schema.version,
|
|
83
|
+
migrationSupport: !!fragnoDb.adapter.createMigrationEngine,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Get current database version if migrations are supported
|
|
87
|
+
if (fragnoDb.adapter.createMigrationEngine) {
|
|
88
|
+
try {
|
|
89
|
+
const migrator = fragnoDb.adapter.createMigrationEngine(
|
|
90
|
+
fragnoDb.schema,
|
|
91
|
+
fragnoDb.namespace,
|
|
92
|
+
);
|
|
93
|
+
const currentVersion = await migrator.getVersion();
|
|
94
|
+
info.currentVersion = currentVersion;
|
|
95
|
+
info.pendingVersions = fragnoDb.schema.version - currentVersion;
|
|
96
|
+
|
|
97
|
+
if (info.pendingVersions > 0) {
|
|
98
|
+
info.status = `Pending (${info.pendingVersions} migration(s))`;
|
|
99
|
+
} else if (info.pendingVersions === 0) {
|
|
100
|
+
info.status = "Up to date";
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
info.error = error instanceof Error ? error.message : String(error);
|
|
104
|
+
info.status = "Error";
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
info.status = "Schema only";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return info;
|
|
111
|
+
}),
|
|
25
112
|
);
|
|
26
|
-
}
|
|
27
113
|
|
|
28
|
-
|
|
29
|
-
|
|
114
|
+
// Determine if any database supports migrations
|
|
115
|
+
const hasMigrationSupport = dbInfos.some((info) => info.migrationSupport);
|
|
30
116
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
117
|
+
// Print compact table
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log(
|
|
120
|
+
`Found ${allFragnoDatabases.length} database(s) across ${uniqueTargets.length} file(s):`,
|
|
121
|
+
);
|
|
122
|
+
console.log("");
|
|
37
123
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
124
|
+
// Table header
|
|
125
|
+
const namespaceHeader = "Namespace";
|
|
126
|
+
const versionHeader = "Schema";
|
|
127
|
+
const currentHeader = "Current";
|
|
128
|
+
const statusHeader = "Status";
|
|
41
129
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
130
|
+
const maxNamespaceLen = Math.max(
|
|
131
|
+
namespaceHeader.length,
|
|
132
|
+
...dbInfos.map((info) => info.namespace.length),
|
|
45
133
|
);
|
|
46
|
-
|
|
134
|
+
const namespaceWidth = Math.max(maxNamespaceLen + 2, 20);
|
|
135
|
+
const versionWidth = 8;
|
|
136
|
+
const currentWidth = 9;
|
|
137
|
+
const statusWidth = 25;
|
|
47
138
|
|
|
48
|
-
|
|
49
|
-
|
|
139
|
+
// Print table
|
|
140
|
+
console.log(
|
|
141
|
+
namespaceHeader.padEnd(namespaceWidth) +
|
|
142
|
+
versionHeader.padEnd(versionWidth) +
|
|
143
|
+
(hasMigrationSupport ? currentHeader.padEnd(currentWidth) : "") +
|
|
144
|
+
statusHeader,
|
|
145
|
+
);
|
|
146
|
+
console.log(
|
|
147
|
+
"-".repeat(namespaceWidth) +
|
|
148
|
+
"-".repeat(versionWidth) +
|
|
149
|
+
(hasMigrationSupport ? "-".repeat(currentWidth) : "") +
|
|
150
|
+
"-".repeat(statusWidth),
|
|
151
|
+
);
|
|
50
152
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
153
|
+
for (const info of dbInfos) {
|
|
154
|
+
const currentVersionStr =
|
|
155
|
+
info.currentVersion !== undefined ? String(info.currentVersion) : "-";
|
|
156
|
+
console.log(
|
|
157
|
+
info.namespace.padEnd(namespaceWidth) +
|
|
158
|
+
String(info.schemaVersion).padEnd(versionWidth) +
|
|
159
|
+
(hasMigrationSupport ? currentVersionStr.padEnd(currentWidth) : "") +
|
|
160
|
+
(info.status || "-"),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
56
163
|
|
|
57
|
-
|
|
58
|
-
if (!fragnoDb.adapter.createMigrationEngine) {
|
|
59
|
-
console.log(`Migration Support: No`);
|
|
164
|
+
// Print help text
|
|
60
165
|
console.log("");
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const currentVersion = await migrator.getVersion();
|
|
72
|
-
|
|
73
|
-
console.log(`Current Database Version: ${currentVersion}`);
|
|
74
|
-
|
|
75
|
-
// Check if migrations are pending
|
|
76
|
-
const pendingVersions = fragnoDb.schema.version - currentVersion;
|
|
77
|
-
if (pendingVersions > 0) {
|
|
78
|
-
console.log("");
|
|
79
|
-
console.log(`⚠ Pending Migrations: ${pendingVersions} version(s) behind`);
|
|
80
|
-
console.log(` Run '@fragno-dev/cli db migrate --target ${target}' to update`);
|
|
81
|
-
} else if (pendingVersions === 0) {
|
|
82
|
-
console.log("");
|
|
83
|
-
console.log(`✓ Database is up to date`);
|
|
166
|
+
if (!hasMigrationSupport) {
|
|
167
|
+
console.log("Note: These adapters do not support migrations.");
|
|
168
|
+
console.log("Use '@fragno-dev/cli db generate' to generate schema files.");
|
|
169
|
+
} else {
|
|
170
|
+
const hasPendingMigrations = dbInfos.some(
|
|
171
|
+
(info) => info.pendingVersions && info.pendingVersions > 0,
|
|
172
|
+
);
|
|
173
|
+
if (hasPendingMigrations) {
|
|
174
|
+
console.log("Run '@fragno-dev/cli db migrate <target>' to apply pending migrations.");
|
|
175
|
+
}
|
|
84
176
|
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
console.log(
|
|
88
|
-
`Warning: Could not retrieve current version: ${error instanceof Error ? error.message : String(error)}`,
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
console.log("=".repeat(50));
|
|
93
|
-
}
|
|
177
|
+
},
|
|
178
|
+
});
|