@contentrail/cli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -17
- package/dist/cli.d.ts +9 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +253 -31
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare/pages-client.d.ts +52 -0
- package/dist/cloudflare/pages-client.d.ts.map +1 -0
- package/dist/cloudflare/pages-client.js +118 -0
- package/dist/cloudflare/pages-client.js.map +1 -0
- package/dist/commands/connect.d.ts +15 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +132 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/deploy.d.ts +19 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +136 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +4 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +31 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +33 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/import.d.ts +10 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +87 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +206 -15
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pages.d.ts +2 -0
- package/dist/commands/pages.d.ts.map +1 -0
- package/dist/commands/pages.js +2 -0
- package/dist/commands/pages.js.map +1 -0
- package/dist/commands/publish.d.ts +15 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +105 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/config/save.d.ts +4 -0
- package/dist/config/save.d.ts.map +1 -0
- package/dist/config/save.js +22 -0
- package/dist/config/save.js.map +1 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +62 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/types.d.ts +24 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/detect/framework.d.ts +1 -1
- package/dist/detect/framework.d.ts.map +1 -1
- package/dist/detect/framework.js +9 -2
- package/dist/detect/framework.js.map +1 -1
- package/dist/editor/validate-config.d.ts.map +1 -1
- package/dist/editor/validate-config.js +16 -2
- package/dist/editor/validate-config.js.map +1 -1
- package/dist/git/remote.d.ts +8 -0
- package/dist/git/remote.d.ts.map +1 -0
- package/dist/git/remote.js +32 -0
- package/dist/git/remote.js.map +1 -0
- package/dist/import/csv.d.ts +6 -0
- package/dist/import/csv.d.ts.map +1 -0
- package/dist/import/csv.js +78 -0
- package/dist/import/csv.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { validateEntry } from "@contentrail/core";
|
|
4
|
+
import { loadCollectionsModule } from "../collections/load.js";
|
|
5
|
+
import { loadProject } from "../config/load.js";
|
|
6
|
+
import { ExitCode } from "../exit-codes.js";
|
|
7
|
+
import { parseCsv } from "../import/csv.js";
|
|
8
|
+
import { ensureDir, writeFileSafe } from "../util/fs.js";
|
|
9
|
+
export async function runImport(options, log) {
|
|
10
|
+
const project = await loadProject(options.projectRoot);
|
|
11
|
+
const collections = await loadCollectionsModule(project.collectionsAbs);
|
|
12
|
+
const collection = collections.find((item) => item.name === options.collection);
|
|
13
|
+
if (collection === undefined) {
|
|
14
|
+
log.error(`Unknown collection "${options.collection}". Registered: ${collections
|
|
15
|
+
.map((item) => item.name)
|
|
16
|
+
.join(", ")}.`);
|
|
17
|
+
return ExitCode.Config;
|
|
18
|
+
}
|
|
19
|
+
const csvPath = path.resolve(options.projectRoot, options.file);
|
|
20
|
+
const text = await fs.readFile(csvPath, "utf8");
|
|
21
|
+
const table = parseCsv(text);
|
|
22
|
+
const targetDir = path.join(project.contentRootAbs, collection.name);
|
|
23
|
+
await ensureDir(targetDir);
|
|
24
|
+
let failed = 0;
|
|
25
|
+
let written = 0;
|
|
26
|
+
const planned = [];
|
|
27
|
+
for (const row of table.rows) {
|
|
28
|
+
const id = (row.id ?? row.slug ?? "").trim();
|
|
29
|
+
if (id === "") {
|
|
30
|
+
failed += 1;
|
|
31
|
+
log.error("CSV row is missing id or slug.");
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const data = coerceRow(row);
|
|
35
|
+
const result = validateEntry(collection, data);
|
|
36
|
+
if (!result.success) {
|
|
37
|
+
failed += 1;
|
|
38
|
+
log.error(`Invalid row "${id}": ${result.error.message}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const relative = path.join(project.config.contentRoot, collection.name, `${id}.json`);
|
|
42
|
+
planned.push(relative);
|
|
43
|
+
if (options.dryRun) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const outcome = await writeFileSafe(path.join(targetDir, `${id}.json`), `${JSON.stringify(result.data, null, 2)}\n`, { force: options.force });
|
|
47
|
+
if (outcome === "skipped") {
|
|
48
|
+
log.warn(`Left existing file unchanged: ${relative} (use --force)`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
written += 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (options.dryRun) {
|
|
55
|
+
log.info(`Dry run: ${planned.length} valid row(s) would be written under ${path.join(project.config.contentRoot, collection.name)}/.`);
|
|
56
|
+
for (const item of planned) {
|
|
57
|
+
log.info(` - ${item}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
log.info(`Imported ${written} record(s) into ${collection.name}.`);
|
|
62
|
+
}
|
|
63
|
+
if (failed > 0) {
|
|
64
|
+
log.error(`${failed} CSV row(s) failed validation.`);
|
|
65
|
+
return ExitCode.Failure;
|
|
66
|
+
}
|
|
67
|
+
return ExitCode.Success;
|
|
68
|
+
}
|
|
69
|
+
function coerceRow(row) {
|
|
70
|
+
const data = {};
|
|
71
|
+
for (const [key, value] of Object.entries(row)) {
|
|
72
|
+
if (key === "id") {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (value === "true" || value === "false") {
|
|
76
|
+
data[key] = value === "true";
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (value !== "" && /^-?\d+(\.\d+)?$/.test(value)) {
|
|
80
|
+
data[key] = Number(value);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
data[key] = value;
|
|
84
|
+
}
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { ExitCode } from "../exit-codes.js";
|
|
|
2
2
|
import type { Logger } from "../util/print.js";
|
|
3
3
|
export interface InitOptions {
|
|
4
4
|
readonly projectRoot: string;
|
|
5
|
-
readonly framework?: "astro" | "vite" | "auto";
|
|
5
|
+
readonly framework?: "astro" | "vite" | "next" | "static" | "auto";
|
|
6
6
|
readonly force?: boolean;
|
|
7
7
|
readonly withEditor?: boolean;
|
|
8
|
+
readonly withFunctions?: boolean;
|
|
9
|
+
readonly dryRun?: boolean;
|
|
8
10
|
readonly yes?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export declare function runInit(options: InitOptions, log: Logger): Promise<ExitCode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,CAAC,CA8OnB"}
|
package/dist/commands/init.js
CHANGED
|
@@ -4,37 +4,65 @@ import { detectFrameworkFromPackage, readPackageJson, } from "../detect/framewor
|
|
|
4
4
|
import { ExitCode } from "../exit-codes.js";
|
|
5
5
|
import { ensureDir, writeFileSafe } from "../util/fs.js";
|
|
6
6
|
export async function runInit(options, log) {
|
|
7
|
+
const nodeMajor = Number(process.versions.node.split(".")[0]);
|
|
8
|
+
if (Number.isNaN(nodeMajor) || nodeMajor < 22) {
|
|
9
|
+
log.error(`Node.js >= 22 is required (found ${process.versions.node}).`);
|
|
10
|
+
return ExitCode.Failure;
|
|
11
|
+
}
|
|
7
12
|
const pkg = await readPackageJson(options.projectRoot);
|
|
8
13
|
if (pkg === null) {
|
|
9
|
-
log.error("No package.json found. Create
|
|
14
|
+
log.error("No package.json found. Create your static site first (Next.js, React, vanilla, Astro, Vite, …), then run contentrail init.");
|
|
10
15
|
return ExitCode.Config;
|
|
11
16
|
}
|
|
12
17
|
const detected = detectFrameworkFromPackage(pkg);
|
|
13
|
-
const framework = options.framework === "astro" ||
|
|
18
|
+
const framework = options.framework === "astro" ||
|
|
19
|
+
options.framework === "vite" ||
|
|
20
|
+
options.framework === "next" ||
|
|
21
|
+
options.framework === "static"
|
|
14
22
|
? options.framework
|
|
15
23
|
: detected === "unknown"
|
|
16
|
-
?
|
|
24
|
+
? "static"
|
|
17
25
|
: detected;
|
|
18
|
-
if (framework ===
|
|
19
|
-
log.
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
if (detected === "unknown" &&
|
|
24
|
-
options.framework === undefined &&
|
|
25
|
-
!options.yes) {
|
|
26
|
-
log.warn(`No framework dependency detected; using --framework ${framework} from flags/defaults.`);
|
|
26
|
+
if (framework === "static" || framework === "next") {
|
|
27
|
+
log.info(framework === "next"
|
|
28
|
+
? 'Next.js detected: ContentRail will not generate App Router pages. Use output: "export" so Pages can serve `out/`. Init adds content, /admin source, and Pages Functions.'
|
|
29
|
+
: "Generic static site: ContentRail will not generate your HTML/React pages. Init adds content, /admin source, and Pages Functions.");
|
|
27
30
|
}
|
|
28
31
|
const collectionsPath = framework === "astro" ? "src/contentrail/config.ts" : "content/config.ts";
|
|
32
|
+
const withEditor = options.withEditor !== false;
|
|
33
|
+
const withFunctions = options.withFunctions !== false;
|
|
29
34
|
const config = {
|
|
30
35
|
...DEFAULT_CONFIG,
|
|
31
36
|
framework,
|
|
32
37
|
collections: collectionsPath,
|
|
33
38
|
contentRoot: "content",
|
|
34
|
-
|
|
39
|
+
admin: { path: "/admin" },
|
|
40
|
+
...(withEditor ? { editorConfig: "contentrail.editor.json" } : {}),
|
|
35
41
|
};
|
|
36
42
|
const written = [];
|
|
37
43
|
const skipped = [];
|
|
44
|
+
const planned = [
|
|
45
|
+
CONFIG_FILE_NAME,
|
|
46
|
+
collectionsPath,
|
|
47
|
+
"content/articles/welcome.json",
|
|
48
|
+
];
|
|
49
|
+
if (withEditor) {
|
|
50
|
+
planned.push("contentrail.editor.json");
|
|
51
|
+
}
|
|
52
|
+
if (framework === "static" || framework === "next") {
|
|
53
|
+
planned.push("admin/index.html", "admin/main.ts");
|
|
54
|
+
}
|
|
55
|
+
if (withFunctions) {
|
|
56
|
+
planned.push("functions/api/[[path]].ts", "functions/_middleware.ts", ".dev.vars.example");
|
|
57
|
+
}
|
|
58
|
+
if (options.dryRun) {
|
|
59
|
+
log.info(`Dry run: would create or skip these files for ${framework}:`);
|
|
60
|
+
for (const item of planned) {
|
|
61
|
+
log.info(` - ${item}`);
|
|
62
|
+
}
|
|
63
|
+
log.info("No files were written.");
|
|
64
|
+
return ExitCode.Success;
|
|
65
|
+
}
|
|
38
66
|
const configResult = await writeFileSafe(path.join(options.projectRoot, CONFIG_FILE_NAME), `${JSON.stringify(config, null, 2)}\n`, { force: options.force });
|
|
39
67
|
(configResult === "written" ? written : skipped).push(CONFIG_FILE_NAME);
|
|
40
68
|
const collectionSource = collectionModuleSource();
|
|
@@ -50,7 +78,7 @@ export async function runInit(options, log) {
|
|
|
50
78
|
body: "Edit this JSON or use the ContentRail editor.",
|
|
51
79
|
}, null, 2)}\n`, { force: options.force });
|
|
52
80
|
(entryResult === "written" ? written : skipped).push("content/articles/welcome.json");
|
|
53
|
-
if (
|
|
81
|
+
if (withEditor) {
|
|
54
82
|
const editorResult = await writeFileSafe(path.join(options.projectRoot, "contentrail.editor.json"), `${JSON.stringify({
|
|
55
83
|
collections: [
|
|
56
84
|
{
|
|
@@ -98,6 +126,23 @@ export async function runInit(options, log) {
|
|
|
98
126
|
}, null, 2)}\n`, { force: options.force });
|
|
99
127
|
(editorResult === "written" ? written : skipped).push("contentrail.editor.json");
|
|
100
128
|
}
|
|
129
|
+
if (framework === "static" || framework === "next") {
|
|
130
|
+
const htmlResult = await writeFileSafe(path.join(options.projectRoot, "admin/index.html"), ADMIN_HTML, { force: options.force });
|
|
131
|
+
(htmlResult === "written" ? written : skipped).push("admin/index.html");
|
|
132
|
+
const mainResult = await writeFileSafe(path.join(options.projectRoot, "admin/main.ts"), ADMIN_MAIN, { force: options.force });
|
|
133
|
+
(mainResult === "written" ? written : skipped).push("admin/main.ts");
|
|
134
|
+
}
|
|
135
|
+
if (withFunctions) {
|
|
136
|
+
const importPath = framework === "astro"
|
|
137
|
+
? "../../src/contentrail/config"
|
|
138
|
+
: "../../content/config";
|
|
139
|
+
const apiResult = await writeFileSafe(path.join(options.projectRoot, "functions/api/[[path]].ts"), pagesApiSource(importPath), { force: options.force });
|
|
140
|
+
(apiResult === "written" ? written : skipped).push("functions/api/[[path]].ts");
|
|
141
|
+
const middlewareResult = await writeFileSafe(path.join(options.projectRoot, "functions/_middleware.ts"), PAGES_MIDDLEWARE, { force: options.force });
|
|
142
|
+
(middlewareResult === "written" ? written : skipped).push("functions/_middleware.ts");
|
|
143
|
+
const varsResult = await writeFileSafe(path.join(options.projectRoot, ".dev.vars.example"), DEV_VARS_EXAMPLE, { force: options.force });
|
|
144
|
+
(varsResult === "written" ? written : skipped).push(".dev.vars.example");
|
|
145
|
+
}
|
|
101
146
|
log.info(`ContentRail initialized for ${framework}.`);
|
|
102
147
|
if (written.length > 0) {
|
|
103
148
|
log.info(`Created:\n${written.map((item) => ` - ${item}`).join("\n")}`);
|
|
@@ -107,9 +152,155 @@ export async function runInit(options, log) {
|
|
|
107
152
|
.map((item) => ` - ${item}`)
|
|
108
153
|
.join("\n")}`);
|
|
109
154
|
}
|
|
110
|
-
log.info("Next:
|
|
155
|
+
log.info("Next: npm install @contentrail/core @contentrail/editor @contentrail/cloudflare @contentrail/publisher preact zod. Export CF_API_TOKEN. Then `contentrail connect --confirm --yes` and `contentrail deploy`. Protect /admin with Cloudflare Access.");
|
|
111
156
|
return ExitCode.Success;
|
|
112
157
|
}
|
|
158
|
+
const ADMIN_HTML = `<!doctype html>
|
|
159
|
+
<html lang="en">
|
|
160
|
+
<head>
|
|
161
|
+
<meta charset="utf-8" />
|
|
162
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
163
|
+
<meta name="robots" content="noindex" />
|
|
164
|
+
<title>ContentRail Admin</title>
|
|
165
|
+
</head>
|
|
166
|
+
<body>
|
|
167
|
+
<div id="contentrail-admin"></div>
|
|
168
|
+
<script type="module" src="./main.ts"></script>
|
|
169
|
+
</body>
|
|
170
|
+
</html>
|
|
171
|
+
`;
|
|
172
|
+
const ADMIN_MAIN = `import {
|
|
173
|
+
createAdminSiteConfig,
|
|
174
|
+
mountAdmin,
|
|
175
|
+
} from "@contentrail/editor";
|
|
176
|
+
import { articles } from "../content/config";
|
|
177
|
+
|
|
178
|
+
const target = document.getElementById("contentrail-admin");
|
|
179
|
+
if (target === null) {
|
|
180
|
+
throw new Error("Missing #contentrail-admin");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
mountAdmin({
|
|
184
|
+
target,
|
|
185
|
+
apiBaseUrl: window.location.origin,
|
|
186
|
+
sites: [
|
|
187
|
+
createAdminSiteConfig({
|
|
188
|
+
siteId: "site",
|
|
189
|
+
label: "Site",
|
|
190
|
+
collections: [{ collection: articles }],
|
|
191
|
+
}),
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
`;
|
|
195
|
+
const DEV_VARS_EXAMPLE = `# Copy to .dev.vars (gitignored). Never commit secrets.
|
|
196
|
+
# Do not use PUBLIC_* or VITE_* for secrets.
|
|
197
|
+
|
|
198
|
+
CONTENTRAIL_ACCESS_TEAM_DOMAIN=
|
|
199
|
+
CONTENTRAIL_ACCESS_AUD=
|
|
200
|
+
CONTENTRAIL_SITE_ID=
|
|
201
|
+
CONTENTRAIL_GIT_OWNER=
|
|
202
|
+
CONTENTRAIL_GIT_REPO=
|
|
203
|
+
CONTENTRAIL_GIT_BRANCH=main
|
|
204
|
+
CONTENTRAIL_CONTENT_ROOT=content
|
|
205
|
+
CONTENTRAIL_ADMIN_ORIGIN=http://localhost:4321
|
|
206
|
+
CONTENTRAIL_GITHUB_TOKEN=
|
|
207
|
+
`;
|
|
208
|
+
const PAGES_MIDDLEWARE = `/**
|
|
209
|
+
* Rejects unauthenticated API calls early.
|
|
210
|
+
* Static /admin HTML is NOT covered — configure Cloudflare Access on /admin*.
|
|
211
|
+
*/
|
|
212
|
+
export const onRequest: PagesFunction = async (context) => {
|
|
213
|
+
const url = new URL(context.request.url);
|
|
214
|
+
if (
|
|
215
|
+
url.pathname.startsWith("/api/") &&
|
|
216
|
+
url.pathname !== "/api/health" &&
|
|
217
|
+
context.request.method !== "OPTIONS"
|
|
218
|
+
) {
|
|
219
|
+
const access = context.request.headers.get("Cf-Access-Jwt-Assertion");
|
|
220
|
+
const authorization = context.request.headers.get("Authorization");
|
|
221
|
+
const hasBearer =
|
|
222
|
+
authorization !== null && /^Bearer\\s+\\S+/i.test(authorization);
|
|
223
|
+
if ((access === null || access.trim() === "") && !hasBearer) {
|
|
224
|
+
return new Response(
|
|
225
|
+
JSON.stringify({
|
|
226
|
+
error: {
|
|
227
|
+
code: "MISSING_CREDENTIAL",
|
|
228
|
+
message: "Missing Access JWT credential.",
|
|
229
|
+
},
|
|
230
|
+
}),
|
|
231
|
+
{ status: 401, headers: { "content-type": "application/json" } },
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return context.next();
|
|
236
|
+
};
|
|
237
|
+
`;
|
|
238
|
+
function pagesApiSource(collectionsImport) {
|
|
239
|
+
return `/**
|
|
240
|
+
* ContentRail Pages Functions API. Server-only.
|
|
241
|
+
* Bind secrets in Pages / .dev.vars — never PUBLIC_* or VITE_*.
|
|
242
|
+
*/
|
|
243
|
+
import {
|
|
244
|
+
createCloudflareAccessAuthenticator,
|
|
245
|
+
createPagesSiteHandler,
|
|
246
|
+
createSiteAuthorizer,
|
|
247
|
+
} from "@contentrail/cloudflare";
|
|
248
|
+
import {
|
|
249
|
+
createGitHubGitDataClient,
|
|
250
|
+
createGitPublishProvider,
|
|
251
|
+
createPublisher,
|
|
252
|
+
} from "@contentrail/publisher";
|
|
253
|
+
import { articles } from "${collectionsImport}";
|
|
254
|
+
|
|
255
|
+
interface Env {
|
|
256
|
+
CONTENTRAIL_ACCESS_TEAM_DOMAIN: string;
|
|
257
|
+
CONTENTRAIL_ACCESS_AUD: string;
|
|
258
|
+
CONTENTRAIL_SITE_ID: string;
|
|
259
|
+
CONTENTRAIL_GIT_OWNER: string;
|
|
260
|
+
CONTENTRAIL_GIT_REPO: string;
|
|
261
|
+
CONTENTRAIL_GIT_BRANCH: string;
|
|
262
|
+
CONTENTRAIL_CONTENT_ROOT: string;
|
|
263
|
+
CONTENTRAIL_ADMIN_ORIGIN: string;
|
|
264
|
+
CONTENTRAIL_GITHUB_TOKEN: string;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export const onRequest: PagesFunction<Env> = async (context) => {
|
|
268
|
+
const env = context.env;
|
|
269
|
+
const handler = createPagesSiteHandler({
|
|
270
|
+
siteId: env.CONTENTRAIL_SITE_ID,
|
|
271
|
+
authenticator: createCloudflareAccessAuthenticator({
|
|
272
|
+
teamDomain: env.CONTENTRAIL_ACCESS_TEAM_DOMAIN,
|
|
273
|
+
audience: env.CONTENTRAIL_ACCESS_AUD,
|
|
274
|
+
}),
|
|
275
|
+
authorizer: createSiteAuthorizer({
|
|
276
|
+
sites: {
|
|
277
|
+
[env.CONTENTRAIL_SITE_ID]: {
|
|
278
|
+
destinationRef: "git:allowlisted",
|
|
279
|
+
permissions: ["read", "publish", "status", "rollback", "validate"],
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
collections: { articles },
|
|
284
|
+
corsAllowedOrigins: [env.CONTENTRAIL_ADMIN_ORIGIN],
|
|
285
|
+
getPublisher: () =>
|
|
286
|
+
createPublisher({
|
|
287
|
+
provider: createGitPublishProvider({
|
|
288
|
+
branch: env.CONTENTRAIL_GIT_BRANCH,
|
|
289
|
+
contentRoot: env.CONTENTRAIL_CONTENT_ROOT,
|
|
290
|
+
hasCredential: Boolean(env.CONTENTRAIL_GITHUB_TOKEN),
|
|
291
|
+
client: createGitHubGitDataClient({
|
|
292
|
+
token: env.CONTENTRAIL_GITHUB_TOKEN,
|
|
293
|
+
owner: env.CONTENTRAIL_GIT_OWNER,
|
|
294
|
+
repo: env.CONTENTRAIL_GIT_REPO,
|
|
295
|
+
allowedPathPrefix: env.CONTENTRAIL_CONTENT_ROOT,
|
|
296
|
+
}),
|
|
297
|
+
}),
|
|
298
|
+
}),
|
|
299
|
+
});
|
|
300
|
+
return handler(context.request);
|
|
301
|
+
};
|
|
302
|
+
`;
|
|
303
|
+
}
|
|
113
304
|
function collectionModuleSource() {
|
|
114
305
|
return `import { defineCollection } from "@contentrail/core";
|
|
115
306
|
import { z } from "zod";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,cAAc,GAEf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0BAA0B,EAC1B,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/commands/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/commands/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ExitCode } from "../exit-codes.js";
|
|
2
|
+
import type { Logger } from "../util/print.js";
|
|
3
|
+
/**
|
|
4
|
+
* Publishes local JSON through the authenticated ContentRail API.
|
|
5
|
+
* Does not talk to GitHub. Token stays in CONTENTRAIL_PUBLISH_TOKEN.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runPublish(options: {
|
|
8
|
+
readonly projectRoot: string;
|
|
9
|
+
readonly collection: string;
|
|
10
|
+
readonly expectedVersion?: string | null;
|
|
11
|
+
readonly dryRun: boolean;
|
|
12
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
13
|
+
readonly fetchImpl?: typeof fetch;
|
|
14
|
+
}, log: Logger): Promise<ExitCode>;
|
|
15
|
+
//# sourceMappingURL=publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE;IACP,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC,EACD,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,CAAC,CAkFnB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createLocalJsonSource, loadCollection } from "@contentrail/reader";
|
|
2
|
+
import { loadCollectionsModule } from "../collections/load.js";
|
|
3
|
+
import { loadProject } from "../config/load.js";
|
|
4
|
+
import { ExitCode } from "../exit-codes.js";
|
|
5
|
+
/**
|
|
6
|
+
* Publishes local JSON through the authenticated ContentRail API.
|
|
7
|
+
* Does not talk to GitHub. Token stays in CONTENTRAIL_PUBLISH_TOKEN.
|
|
8
|
+
*/
|
|
9
|
+
export async function runPublish(options, log) {
|
|
10
|
+
const env = options.env ?? process.env;
|
|
11
|
+
const project = await loadProject(options.projectRoot);
|
|
12
|
+
const publishApiUrl = project.config.publishApiUrl;
|
|
13
|
+
if (publishApiUrl === undefined) {
|
|
14
|
+
log.error("publishApiUrl is not set in contentrail.config.json. CLI publish posts to the Worker/Pages API; it does not embed GitHub tokens (ADR 020).");
|
|
15
|
+
return ExitCode.Config;
|
|
16
|
+
}
|
|
17
|
+
const token = env.CONTENTRAIL_PUBLISH_TOKEN;
|
|
18
|
+
if (token === undefined || token.trim() === "") {
|
|
19
|
+
log.error("CONTENTRAIL_PUBLISH_TOKEN is missing. Use a Cloudflare Access service token or JWT from a local secret file — never commit it.");
|
|
20
|
+
return ExitCode.Config;
|
|
21
|
+
}
|
|
22
|
+
const siteId = env.CONTENTRAIL_SITE_ID;
|
|
23
|
+
if (siteId === undefined || siteId.trim() === "") {
|
|
24
|
+
log.error("CONTENTRAIL_SITE_ID is required so the CLI cannot guess a site.");
|
|
25
|
+
return ExitCode.Config;
|
|
26
|
+
}
|
|
27
|
+
const collections = await loadCollectionsModule(project.collectionsAbs);
|
|
28
|
+
const collection = collections.find((item) => item.name === options.collection);
|
|
29
|
+
if (collection === undefined) {
|
|
30
|
+
log.error(`Unknown collection "${options.collection}".`);
|
|
31
|
+
return ExitCode.Config;
|
|
32
|
+
}
|
|
33
|
+
const source = await createLocalJsonSource({
|
|
34
|
+
rootDir: project.contentRootAbs,
|
|
35
|
+
});
|
|
36
|
+
const entries = await loadCollection(source, collection);
|
|
37
|
+
const payload = {
|
|
38
|
+
collection: collection.name,
|
|
39
|
+
expectedVersion: options.expectedVersion === undefined ? null : options.expectedVersion,
|
|
40
|
+
entries: entries.map((entry) => ({ id: entry.id, data: entry.data })),
|
|
41
|
+
};
|
|
42
|
+
if (options.dryRun) {
|
|
43
|
+
log.info(`Dry run: would POST ${entries.length} ${collection.name} entr${entries.length === 1 ? "y" : "ies"} to ${originOf(publishApiUrl)} (token not logged).`);
|
|
44
|
+
return ExitCode.Success;
|
|
45
|
+
}
|
|
46
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
47
|
+
const endpoint = pagesOrWorkerPublishUrl(publishApiUrl, siteId, collection.name);
|
|
48
|
+
const response = await fetchImpl(endpoint, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${token}`,
|
|
52
|
+
"content-type": "application/json",
|
|
53
|
+
},
|
|
54
|
+
body: JSON.stringify(endpoint.includes("/api/publish")
|
|
55
|
+
? payload
|
|
56
|
+
: {
|
|
57
|
+
expectedVersion: payload.expectedVersion,
|
|
58
|
+
entries: payload.entries,
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
const text = await response.text();
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
log.error(`Publish API returned ${response.status}.`);
|
|
64
|
+
log.error(safeApiError(text));
|
|
65
|
+
return ExitCode.Failure;
|
|
66
|
+
}
|
|
67
|
+
log.info(`Publish API accepted collection "${collection.name}".`);
|
|
68
|
+
log.info(safeApiError(text));
|
|
69
|
+
return ExitCode.Success;
|
|
70
|
+
}
|
|
71
|
+
function pagesOrWorkerPublishUrl(publishApiUrl, siteId, collection) {
|
|
72
|
+
const base = publishApiUrl.replace(/\/+$/, "");
|
|
73
|
+
if (base.endsWith("/api") || /pages\.dev$/i.test(new URL(base).host)) {
|
|
74
|
+
const origin = base.endsWith("/api") ? base.slice(0, -4) : base;
|
|
75
|
+
return `${origin}/api/publish`;
|
|
76
|
+
}
|
|
77
|
+
return `${base}/v1/sites/${encodeURIComponent(siteId)}/collections/${encodeURIComponent(collection)}/publish`;
|
|
78
|
+
}
|
|
79
|
+
function originOf(url) {
|
|
80
|
+
try {
|
|
81
|
+
return new URL(url).origin;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return "(invalid url)";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function safeApiError(text) {
|
|
88
|
+
try {
|
|
89
|
+
const json = JSON.parse(text);
|
|
90
|
+
if (json.error?.code !== undefined) {
|
|
91
|
+
return `${json.error.code}: ${json.error.message ?? ""}`;
|
|
92
|
+
}
|
|
93
|
+
if (json.version !== undefined) {
|
|
94
|
+
return `version ${json.version}`;
|
|
95
|
+
}
|
|
96
|
+
if (json.success === true) {
|
|
97
|
+
return "success";
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Fall through to a truncated generic body.
|
|
102
|
+
}
|
|
103
|
+
return text.length > 200 ? `${text.slice(0, 200)}…` : text;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ContentRailProjectConfig } from "./types.js";
|
|
2
|
+
export declare function writeProjectConfig(projectRoot: string, config: ContentRailProjectConfig): Promise<void>;
|
|
3
|
+
export declare function mergeProjectConfig(current: ContentRailProjectConfig, patch: Partial<ContentRailProjectConfig>): ContentRailProjectConfig;
|
|
4
|
+
//# sourceMappingURL=save.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../../src/config/save.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAG7E,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,OAAO,CAAC,wBAAwB,CAAC,GACvC,wBAAwB,CAY1B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { parseProjectConfig } from "./schema.js";
|
|
3
|
+
import { CONFIG_FILE_NAME } from "./types.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
export async function writeProjectConfig(projectRoot, config) {
|
|
6
|
+
parseProjectConfig(config);
|
|
7
|
+
await fs.writeFile(path.join(projectRoot, CONFIG_FILE_NAME), `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
8
|
+
}
|
|
9
|
+
export function mergeProjectConfig(current, patch) {
|
|
10
|
+
return parseProjectConfig({
|
|
11
|
+
...current,
|
|
12
|
+
...patch,
|
|
13
|
+
...(patch.admin !== undefined
|
|
14
|
+
? { admin: { ...current.admin, ...patch.admin } }
|
|
15
|
+
: {}),
|
|
16
|
+
...(patch.git !== undefined ? { git: patch.git } : {}),
|
|
17
|
+
...(patch.cloudflare !== undefined
|
|
18
|
+
? { cloudflare: { ...current.cloudflare, ...patch.cloudflare } }
|
|
19
|
+
: {}),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.js","sourceRoot":"","sources":["../../src/config/save.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAiC,MAAM,YAAY,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAAmB,EACnB,MAAgC;IAEhC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,EACxC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EACtC,MAAM,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAiC,EACjC,KAAwC;IAExC,OAAO,kBAAkB,CAAC;QACxB,GAAG,OAAO;QACV,GAAG,KAAK;QACR,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS;YAC3B,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE;YACjD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS;YAChC,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,EAAE;YAChE,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AA8C3D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,wBAAwB,CAoDzE"}
|