@actuate-media/cli 0.1.0 → 0.1.2
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 +2 -1
- package/CHANGELOG.md +44 -0
- package/LICENSE +21 -0
- package/dist/commands/export.js +1 -1
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/generate.js +1 -1
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/import.js +1 -1
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/seed.js +1 -1
- package/dist/commands/seed.js.map +1 -1
- package/dist/commands/update-check.js +2 -2
- package/dist/commands/update-check.js.map +1 -1
- package/dist/commands/upgrade.js +4 -4
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/index.js +0 -0
- package/package.json +33 -33
- package/src/commands/export.ts +131 -131
- package/src/commands/generate.ts +28 -28
- package/src/commands/import.ts +243 -243
- package/src/commands/migrate.ts +62 -62
- package/src/commands/seed.ts +388 -388
- package/src/commands/update-check.ts +147 -147
- package/src/commands/upgrade.ts +173 -173
- package/src/index.ts +26 -26
- package/src/utils/logger.ts +26 -26
- package/tsconfig.json +9 -9
package/src/commands/export.ts
CHANGED
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
2
|
-
import { writeFile } from "node:fs/promises";
|
|
3
|
-
import ora from "ora";
|
|
4
|
-
import { logger } from "../utils/logger.js";
|
|
5
|
-
|
|
6
|
-
interface ExportOptions {
|
|
7
|
-
collection?: string;
|
|
8
|
-
format: string;
|
|
9
|
-
output?: string;
|
|
10
|
-
includeDrafts?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function buildOutputPath(options: ExportOptions): string {
|
|
14
|
-
if (options.output) return options.output;
|
|
15
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16
|
-
const ext = options.format === "csv" ? "csv" : "json";
|
|
17
|
-
return `actuate-export-${timestamp}.${ext}`;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function jsonToCsv(docs: any[]): string {
|
|
21
|
-
if (docs.length === 0) return "";
|
|
22
|
-
|
|
23
|
-
const keySet = new Set<string>();
|
|
24
|
-
for (const doc of docs) {
|
|
25
|
-
keySet.add("id");
|
|
26
|
-
keySet.add("collection");
|
|
27
|
-
keySet.add("status");
|
|
28
|
-
keySet.add("createdAt");
|
|
29
|
-
keySet.add("updatedAt");
|
|
30
|
-
if (doc.data && typeof doc.data === "object") {
|
|
31
|
-
for (const key of Object.keys(doc.data)) {
|
|
32
|
-
keySet.add(`data.${key}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
const headers = Array.from(keySet);
|
|
37
|
-
|
|
38
|
-
const escapeCsvValue = (val: unknown): string => {
|
|
39
|
-
if (val === null || val === undefined) return "";
|
|
40
|
-
const str = typeof val === "object" ? JSON.stringify(val) : String(val);
|
|
41
|
-
if (str.includes(",") || str.includes('"') || str.includes("\n")) {
|
|
42
|
-
return `"${str.replace(/"/g, '""')}"`;
|
|
43
|
-
}
|
|
44
|
-
return str;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const rows = docs.map((doc) => {
|
|
48
|
-
return headers
|
|
49
|
-
.map((header) => {
|
|
50
|
-
if (header.startsWith("data.")) {
|
|
51
|
-
const field = header.slice(5);
|
|
52
|
-
return escapeCsvValue(doc.data?.[field]);
|
|
53
|
-
}
|
|
54
|
-
return escapeCsvValue(doc[header]);
|
|
55
|
-
})
|
|
56
|
-
.join(",");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
return [headers.join(","), ...rows].join("\n");
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function runExport(options: ExportOptions): Promise<void> {
|
|
63
|
-
const target = options.collection ?? "all collections";
|
|
64
|
-
const spinner = ora(`Exporting ${target}…`).start();
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
const { getDB } = await import("@actuate-media/cms-core");
|
|
68
|
-
const db = getDB<any>();
|
|
69
|
-
|
|
70
|
-
const where: any = { deletedAt: null };
|
|
71
|
-
|
|
72
|
-
if (options.collection) {
|
|
73
|
-
where.collection = options.collection;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!options.includeDrafts) {
|
|
77
|
-
where.status = "PUBLISHED";
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const docs = await db.document.findMany({
|
|
81
|
-
where,
|
|
82
|
-
orderBy: { createdAt: "desc" },
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
if (docs.length === 0) {
|
|
86
|
-
spinner.warn("No documents found matching the criteria.");
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const outputPath = buildOutputPath(options);
|
|
91
|
-
let content: string;
|
|
92
|
-
|
|
93
|
-
if (options.format === "csv") {
|
|
94
|
-
content = jsonToCsv(docs);
|
|
95
|
-
} else {
|
|
96
|
-
content = JSON.stringify(docs, null, 2);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
await writeFile(outputPath, content, "utf-8");
|
|
100
|
-
spinner.succeed(`Exported ${docs.length} documents to ${outputPath}`);
|
|
101
|
-
} catch (err) {
|
|
102
|
-
spinner.fail("Export failed.");
|
|
103
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
104
|
-
logger.error(message);
|
|
105
|
-
process.exit(1);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function registerExportCommand(program: Command): void {
|
|
110
|
-
program
|
|
111
|
-
.command("export")
|
|
112
|
-
.description("Export content to JSON or CSV files")
|
|
113
|
-
.option(
|
|
114
|
-
"-c, --collection <slug>",
|
|
115
|
-
"Export only the specified collection (default: all)",
|
|
116
|
-
)
|
|
117
|
-
.option(
|
|
118
|
-
"-f, --format <type>",
|
|
119
|
-
"Output format: json or csv",
|
|
120
|
-
"json",
|
|
121
|
-
)
|
|
122
|
-
.option(
|
|
123
|
-
"-o, --output <path>",
|
|
124
|
-
"Output file path (default: actuate-export-{timestamp}.{format})",
|
|
125
|
-
)
|
|
126
|
-
.option(
|
|
127
|
-
"--include-drafts",
|
|
128
|
-
"Include draft documents (default: published only)",
|
|
129
|
-
)
|
|
130
|
-
.action(runExport);
|
|
131
|
-
}
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import { logger } from "../utils/logger.js";
|
|
5
|
+
|
|
6
|
+
interface ExportOptions {
|
|
7
|
+
collection?: string;
|
|
8
|
+
format: string;
|
|
9
|
+
output?: string;
|
|
10
|
+
includeDrafts?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function buildOutputPath(options: ExportOptions): string {
|
|
14
|
+
if (options.output) return options.output;
|
|
15
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16
|
+
const ext = options.format === "csv" ? "csv" : "json";
|
|
17
|
+
return `actuate-export-${timestamp}.${ext}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function jsonToCsv(docs: any[]): string {
|
|
21
|
+
if (docs.length === 0) return "";
|
|
22
|
+
|
|
23
|
+
const keySet = new Set<string>();
|
|
24
|
+
for (const doc of docs) {
|
|
25
|
+
keySet.add("id");
|
|
26
|
+
keySet.add("collection");
|
|
27
|
+
keySet.add("status");
|
|
28
|
+
keySet.add("createdAt");
|
|
29
|
+
keySet.add("updatedAt");
|
|
30
|
+
if (doc.data && typeof doc.data === "object") {
|
|
31
|
+
for (const key of Object.keys(doc.data)) {
|
|
32
|
+
keySet.add(`data.${key}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const headers = Array.from(keySet);
|
|
37
|
+
|
|
38
|
+
const escapeCsvValue = (val: unknown): string => {
|
|
39
|
+
if (val === null || val === undefined) return "";
|
|
40
|
+
const str = typeof val === "object" ? JSON.stringify(val) : String(val);
|
|
41
|
+
if (str.includes(",") || str.includes('"') || str.includes("\n")) {
|
|
42
|
+
return `"${str.replace(/"/g, '""')}"`;
|
|
43
|
+
}
|
|
44
|
+
return str;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const rows = docs.map((doc) => {
|
|
48
|
+
return headers
|
|
49
|
+
.map((header) => {
|
|
50
|
+
if (header.startsWith("data.")) {
|
|
51
|
+
const field = header.slice(5);
|
|
52
|
+
return escapeCsvValue(doc.data?.[field]);
|
|
53
|
+
}
|
|
54
|
+
return escapeCsvValue(doc[header]);
|
|
55
|
+
})
|
|
56
|
+
.join(",");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return [headers.join(","), ...rows].join("\n");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function runExport(options: ExportOptions): Promise<void> {
|
|
63
|
+
const target = options.collection ?? "all collections";
|
|
64
|
+
const spinner = ora(`Exporting ${target}…`).start();
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const { getDB } = await import("@actuate-media/cms-core");
|
|
68
|
+
const db = getDB<any>();
|
|
69
|
+
|
|
70
|
+
const where: any = { deletedAt: null };
|
|
71
|
+
|
|
72
|
+
if (options.collection) {
|
|
73
|
+
where.collection = options.collection;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!options.includeDrafts) {
|
|
77
|
+
where.status = "PUBLISHED";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const docs = await db.document.findMany({
|
|
81
|
+
where,
|
|
82
|
+
orderBy: { createdAt: "desc" },
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (docs.length === 0) {
|
|
86
|
+
spinner.warn("No documents found matching the criteria.");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const outputPath = buildOutputPath(options);
|
|
91
|
+
let content: string;
|
|
92
|
+
|
|
93
|
+
if (options.format === "csv") {
|
|
94
|
+
content = jsonToCsv(docs);
|
|
95
|
+
} else {
|
|
96
|
+
content = JSON.stringify(docs, null, 2);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await writeFile(outputPath, content, "utf-8");
|
|
100
|
+
spinner.succeed(`Exported ${docs.length} documents to ${outputPath}`);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
spinner.fail("Export failed.");
|
|
103
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
104
|
+
logger.error(message);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function registerExportCommand(program: Command): void {
|
|
110
|
+
program
|
|
111
|
+
.command("export")
|
|
112
|
+
.description("Export content to JSON or CSV files")
|
|
113
|
+
.option(
|
|
114
|
+
"-c, --collection <slug>",
|
|
115
|
+
"Export only the specified collection (default: all)",
|
|
116
|
+
)
|
|
117
|
+
.option(
|
|
118
|
+
"-f, --format <type>",
|
|
119
|
+
"Output format: json or csv",
|
|
120
|
+
"json",
|
|
121
|
+
)
|
|
122
|
+
.option(
|
|
123
|
+
"-o, --output <path>",
|
|
124
|
+
"Output file path (default: actuate-export-{timestamp}.{format})",
|
|
125
|
+
)
|
|
126
|
+
.option(
|
|
127
|
+
"--include-drafts",
|
|
128
|
+
"Include draft documents (default: published only)",
|
|
129
|
+
)
|
|
130
|
+
.action(runExport);
|
|
131
|
+
}
|
package/src/commands/generate.ts
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
2
|
-
import ora from "ora";
|
|
3
|
-
import { logger } from "../utils/logger.js";
|
|
4
|
-
|
|
5
|
-
async function runGenerate(): Promise<void> {
|
|
6
|
-
const spinner = ora("Generating TypeScript types from schema…").start();
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
// Dynamically import the codegen module from cms-core
|
|
10
|
-
const { runCodegen } = await import("@actuate-media/cms-core/codegen");
|
|
11
|
-
await runCodegen();
|
|
12
|
-
spinner.succeed("Type generation complete.");
|
|
13
|
-
} catch (err) {
|
|
14
|
-
spinner.fail("Type generation failed.");
|
|
15
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
16
|
-
logger.error(message);
|
|
17
|
-
process.exitCode = 1;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function registerGenerateCommand(program: Command): void {
|
|
22
|
-
program
|
|
23
|
-
.command("generate")
|
|
24
|
-
.description(
|
|
25
|
-
"Run the TypeScript type generator from the cms-core codegen module",
|
|
26
|
-
)
|
|
27
|
-
.action(runGenerate);
|
|
28
|
-
}
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
|
|
5
|
+
async function runGenerate(): Promise<void> {
|
|
6
|
+
const spinner = ora("Generating TypeScript types from schema…").start();
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
// Dynamically import the codegen module from cms-core
|
|
10
|
+
const { runCodegen } = await import("@actuate-media/cms-core/codegen");
|
|
11
|
+
await runCodegen();
|
|
12
|
+
spinner.succeed("Type generation complete.");
|
|
13
|
+
} catch (err) {
|
|
14
|
+
spinner.fail("Type generation failed.");
|
|
15
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16
|
+
logger.error(message);
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function registerGenerateCommand(program: Command): void {
|
|
22
|
+
program
|
|
23
|
+
.command("generate")
|
|
24
|
+
.description(
|
|
25
|
+
"Run the TypeScript type generator from the cms-core codegen module",
|
|
26
|
+
)
|
|
27
|
+
.action(runGenerate);
|
|
28
|
+
}
|