@styleflow.app/flowpress-deploy 1.0.0-beta.24 → 1.0.0-beta.26
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/CHANGELOG.md +7 -0
- package/dist/development.d.ts +8 -0
- package/dist/development.d.ts.map +1 -1
- package/dist/development.js +47 -0
- package/dist/development.js.map +1 -1
- package/dist/ops/check.d.ts +2 -6
- package/dist/ops/check.d.ts.map +1 -1
- package/dist/ops/check.js +3 -7
- package/dist/ops/check.js.map +1 -1
- package/dist/ops/cli.js +17 -1
- package/dist/ops/cli.js.map +1 -1
- package/dist/ops/cms-migrate.d.ts +11 -0
- package/dist/ops/cms-migrate.d.ts.map +1 -0
- package/dist/ops/cms-migrate.js +125 -0
- package/dist/ops/cms-migrate.js.map +1 -0
- package/dist/ops/cms-template/command.d.mts +19 -0
- package/dist/ops/cms-template/command.d.mts.map +1 -0
- package/dist/ops/cms-template/command.mjs +145 -0
- package/dist/ops/cms-template/command.mjs.map +1 -0
- package/dist/ops/cms-template/confirm.d.mts +11 -0
- package/dist/ops/cms-template/confirm.d.mts.map +1 -0
- package/dist/ops/cms-template/confirm.mjs +18 -0
- package/dist/ops/cms-template/confirm.mjs.map +1 -0
- package/dist/ops/cms-template/entry.d.mts +2 -0
- package/dist/ops/cms-template/entry.d.mts.map +1 -0
- package/dist/ops/cms-template/entry.mjs +22 -0
- package/dist/ops/cms-template/entry.mjs.map +1 -0
- package/dist/ops/cms-template/git.d.mts +7 -0
- package/dist/ops/cms-template/git.d.mts.map +1 -0
- package/dist/ops/cms-template/git.mjs +22 -0
- package/dist/ops/cms-template/git.mjs.map +1 -0
- package/dist/ops/cms-template/plan.d.mts +7 -0
- package/dist/ops/cms-template/plan.d.mts.map +1 -0
- package/dist/ops/cms-template/plan.mjs +54 -0
- package/dist/ops/cms-template/plan.mjs.map +1 -0
- package/dist/ops/cms-template/store.d.mts +21 -0
- package/dist/ops/cms-template/store.d.mts.map +1 -0
- package/dist/ops/cms-template/store.mjs +184 -0
- package/dist/ops/cms-template/store.mjs.map +1 -0
- package/dist/ops/cms-template/target.d.mts +15 -0
- package/dist/ops/cms-template/target.d.mts.map +1 -0
- package/dist/ops/cms-template/target.mjs +24 -0
- package/dist/ops/cms-template/target.mjs.map +1 -0
- package/dist/ops/cms-template/transport.d.mts +26 -0
- package/dist/ops/cms-template/transport.d.mts.map +1 -0
- package/dist/ops/cms-template/transport.mjs +115 -0
- package/dist/ops/cms-template/transport.mjs.map +1 -0
- package/dist/ops/features.d.ts +12 -0
- package/dist/ops/features.d.ts.map +1 -0
- package/dist/ops/features.js +71 -0
- package/dist/ops/features.js.map +1 -0
- package/dist/ops/monitor.d.ts +2 -0
- package/dist/ops/monitor.d.ts.map +1 -1
- package/dist/ops/monitor.js +1 -1
- package/dist/ops/monitor.js.map +1 -1
- package/dist/ops/static-config.d.ts +1 -1
- package/dist/ops/static-config.d.ts.map +1 -1
- package/dist/ops/static-config.js +16 -20
- package/dist/ops/static-config.js.map +1 -1
- package/includes/pilot-aliases.php +69 -0
- package/package.json +5 -2
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
/** y/n prompt, default No. Without a TTY only --yes can confirm. */
|
|
3
|
+
export async function confirm(question, { yes = false, input = process.stdin, output = process.stdout } = {}) {
|
|
4
|
+
if (yes)
|
|
5
|
+
return true;
|
|
6
|
+
if (!input.isTTY) {
|
|
7
|
+
throw new Error("Confirmation required but stdin is not interactive: re-run with --yes.");
|
|
8
|
+
}
|
|
9
|
+
const readline = createInterface({ input, output });
|
|
10
|
+
try {
|
|
11
|
+
const answer = await readline.question(`${question} [y/N] `);
|
|
12
|
+
return /^(y|yes|s|si|sì)$/i.test(answer.trim());
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
readline.close();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=confirm.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/confirm.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAQ,EAAE,EAAE,GAAG,GAAG,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;IAC1G,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACrB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC;QAC7D,OAAO,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.mts","sourceRoot":"","sources":["../../../src/ops/cms-template/entry.mjs"],"names":[],"mappings":"AASA,iFAWC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { allowedComponents } from "../config.js";
|
|
3
|
+
import { runCmsTemplate } from "./command.mjs";
|
|
4
|
+
import { confirm } from "./confirm.mjs";
|
|
5
|
+
import { createGit } from "./git.mjs";
|
|
6
|
+
import { readStore, writePulled } from "./store.mjs";
|
|
7
|
+
import { resolveTarget } from "./target.mjs";
|
|
8
|
+
import { dockerTransport, restTransport } from "./transport.mjs";
|
|
9
|
+
export async function cmsTemplate(root, manifest, args) {
|
|
10
|
+
const themePath = "apps/cms/theme", themeDir = join(root, themePath);
|
|
11
|
+
return runCmsTemplate(args, {
|
|
12
|
+
root, themePath,
|
|
13
|
+
resolveTarget: flag => resolveTarget({ root, manifest, flag }),
|
|
14
|
+
assertWritable: target => { if (!target.local)
|
|
15
|
+
allowedComponents(manifest, target.backendName, ["cms"]); },
|
|
16
|
+
transport: target => target.local ? dockerTransport({ root }) : restTransport({ backendUrl: target.backendUrl, auth: target.auth, targetName: target.backendName }),
|
|
17
|
+
git: createGit(root),
|
|
18
|
+
store: { read: () => readStore(themeDir), write: items => writePulled(themeDir, items, themePath) },
|
|
19
|
+
confirm, log: line => console.log(`[cms:template] ${line}`), now: () => new Date(),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=entry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/entry.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI;IACpD,MAAM,SAAS,GAAG,gBAAgB,EAAE,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACrE,OAAO,cAAc,CAAC,IAAI,EAAE;QAC1B,IAAI,EAAE,SAAS;QACf,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC9D,cAAc,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1G,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QACnK,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC;QACpB,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE;QACnG,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE;KACnF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.mts","sourceRoot":"","sources":["../../../src/ops/cms-template/git.mjs"],"names":[],"mappings":"AAEA;;;;EAiBC;0BAnByB,oBAAoB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
export function createGit(root, run = spawnSync) {
|
|
3
|
+
const git = (...args) => run("git", args, { cwd: root, encoding: "utf8" });
|
|
4
|
+
return {
|
|
5
|
+
head() {
|
|
6
|
+
const result = git("rev-parse", "HEAD");
|
|
7
|
+
if (result.status !== 0)
|
|
8
|
+
throw new Error("cms:template runs from the git repository only.");
|
|
9
|
+
return result.stdout.trim();
|
|
10
|
+
},
|
|
11
|
+
dirty(path) {
|
|
12
|
+
const result = git("status", "--porcelain", "--", path);
|
|
13
|
+
if (result.status !== 0)
|
|
14
|
+
throw new Error(String(result.stderr).trim());
|
|
15
|
+
return result.stdout.split("\n").filter(Boolean);
|
|
16
|
+
},
|
|
17
|
+
isAncestor(commit) {
|
|
18
|
+
return git("merge-base", "--is-ancestor", commit, "HEAD").status === 0;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=git.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/git.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,UAAU,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,SAAS;IAC7C,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3E,OAAO;QACL,IAAI;YACF,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YACxC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YAC5F,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,CAAC;QACD,KAAK,CAAC,IAAI;YACR,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACxD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACvE,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QACD,UAAU,CAAC,MAAM;YACf,OAAO,GAAG,CAAC,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QACzE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Push only: never overwrite what another branch pushed after our base. */
|
|
2
|
+
export function applyAncestry(plan: any, isAncestor: any, force: any): any;
|
|
3
|
+
/** Rows whose sync marker the push sets without changing content. */
|
|
4
|
+
export function pendingMarkers(plan: any): any;
|
|
5
|
+
export function pendingChanges(plan: any): any;
|
|
6
|
+
export function renderPlan(plan: any, target: any, log: any): void;
|
|
7
|
+
//# sourceMappingURL=plan.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.d.mts","sourceRoot":"","sources":["../../../src/ops/cms-template/plan.mjs"],"names":[],"mappings":"AAYA,4EAA4E;AAC5E,2EASC;AAED,qEAAqE;AACrE,+CAGC;AAED,+CAEC;AAED,mEAmBC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const HINTS = {
|
|
2
|
+
"new-in-repo": "only in the repository",
|
|
3
|
+
"new-in-cms": "only in the CMS",
|
|
4
|
+
"repo-ahead": "the repository is newer",
|
|
5
|
+
"cms-ahead": "changed in the CMS since the last push",
|
|
6
|
+
untracked: "edited in the CMS, never pushed from the repository",
|
|
7
|
+
conflict: "changed in both the CMS and the repository",
|
|
8
|
+
diverged: "last pushed from a commit that is not in this branch",
|
|
9
|
+
};
|
|
10
|
+
const key = (item) => `${item.kind}:${item.slug}`;
|
|
11
|
+
/** Push only: never overwrite what another branch pushed after our base. */
|
|
12
|
+
export function applyAncestry(plan, isAncestor, force) {
|
|
13
|
+
for (const item of plan.items) {
|
|
14
|
+
const commit = String(item.marker?.commit ?? "").replace(/\+dirty$/, "");
|
|
15
|
+
if (force || item.action !== "update" || item.state !== "repo-ahead" || !commit || isAncestor(commit))
|
|
16
|
+
continue;
|
|
17
|
+
item.state = "diverged";
|
|
18
|
+
item.action = "blocked";
|
|
19
|
+
plan.blocked.push(`${key(item)} was last pushed from ${commit.slice(0, 10)}, which is not in this branch`);
|
|
20
|
+
}
|
|
21
|
+
return plan;
|
|
22
|
+
}
|
|
23
|
+
/** Rows whose sync marker the push sets without changing content. */
|
|
24
|
+
export function pendingMarkers(plan) {
|
|
25
|
+
return plan.items.filter((item) => item.action === "none" && item.row && item.hashes.repo
|
|
26
|
+
&& item.marker?.hash !== item.hashes.repo);
|
|
27
|
+
}
|
|
28
|
+
export function pendingChanges(plan) {
|
|
29
|
+
return plan.items.filter((item) => ["write", "create", "update", "delete"].includes(item.action));
|
|
30
|
+
}
|
|
31
|
+
export function renderPlan(plan, target, log) {
|
|
32
|
+
const arrow = plan.direction === "pull" ? "←" : "→";
|
|
33
|
+
log(`${plan.direction} ${arrow} ${target.name} (${target.origin}) · theme ${plan.stylesheet} · WordPress ${plan.wordpress}`);
|
|
34
|
+
const counts = {};
|
|
35
|
+
for (const item of plan.items) {
|
|
36
|
+
const bucket = item.action === "blocked" ? "BLOCKED"
|
|
37
|
+
: item.action !== "none" ? item.action
|
|
38
|
+
: item.state === "unchanged" ? "unchanged" : "skip";
|
|
39
|
+
counts[bucket] = (counts[bucket] ?? 0) + 1;
|
|
40
|
+
if (bucket !== "unchanged") {
|
|
41
|
+
const hint = HINTS[item.state] ? ` — ${HINTS[item.state]}` : "";
|
|
42
|
+
log(` ${bucket.padEnd(8)} ${key(item).padEnd(44)}${hint}`);
|
|
43
|
+
}
|
|
44
|
+
for (const missing of item.unresolved ?? [])
|
|
45
|
+
log(` unresolved ${missing}`);
|
|
46
|
+
for (const warning of item.warnings ?? [])
|
|
47
|
+
log(` warning: ${warning}`);
|
|
48
|
+
}
|
|
49
|
+
const markers = plan.direction === "push" ? pendingMarkers(plan).length : 0;
|
|
50
|
+
if (markers)
|
|
51
|
+
counts["sync markers"] = markers;
|
|
52
|
+
log(`summary: ${Object.entries(counts).map(([label, count]) => `${count} ${label}`).join(", ") || "nothing"}`);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=plan.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/plan.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function readStore(themeDir: any): {
|
|
2
|
+
kind: string;
|
|
3
|
+
slug: string;
|
|
4
|
+
content: string;
|
|
5
|
+
meta: {};
|
|
6
|
+
}[];
|
|
7
|
+
/** Writes the pulled items; returns the repository paths it touched. */
|
|
8
|
+
export function writePulled(themeDir: any, items: any, themePath?: string): string[];
|
|
9
|
+
/** One entry per line, like the compact objects already used in theme.json. */
|
|
10
|
+
export function formatEntries(entries: any): string;
|
|
11
|
+
/**
|
|
12
|
+
* Replaces (or appends) one top-level value and leaves every other byte of
|
|
13
|
+
* the file untouched: theme.json is formatted by hand.
|
|
14
|
+
*/
|
|
15
|
+
export function setTopLevelJsonValue(text: any, key: any, valueText: any): any;
|
|
16
|
+
export namespace STORE_DIRECTORIES {
|
|
17
|
+
let template: string;
|
|
18
|
+
let part: string;
|
|
19
|
+
let pattern: string;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=store.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.mts","sourceRoot":"","sources":["../../../src/ops/cms-template/store.mjs"],"names":[],"mappings":"AA4BA;;;;;IAwBC;AAYD,wEAAwE;AACxE,qFAsCC;AAED,+EAA+E;AAC/E,oDAKC;AA+BD;;;GAGG;AACH,+EAwBC"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* The theme is the store: templates/ and parts/ are read by WordPress as
|
|
5
|
+
* fallbacks, user-patterns/ is not (patterns/ would register theme patterns).
|
|
6
|
+
* Template and part metadata live in theme.json (customTemplates/templateParts).
|
|
7
|
+
*/
|
|
8
|
+
export const STORE_DIRECTORIES = { template: "templates", part: "parts", pattern: "user-patterns" };
|
|
9
|
+
const SLUG = /^[a-z0-9][a-z0-9_-]*$/;
|
|
10
|
+
function htmlSlugs(directory) {
|
|
11
|
+
if (!existsSync(directory))
|
|
12
|
+
return [];
|
|
13
|
+
return readdirSync(directory)
|
|
14
|
+
.filter((file) => file.endsWith(".html"))
|
|
15
|
+
.map((file) => {
|
|
16
|
+
const slug = file.slice(0, -5);
|
|
17
|
+
if (!SLUG.test(slug))
|
|
18
|
+
throw new Error(`Invalid file name ${join(directory, file)}: use a-z, 0-9, - and _.`);
|
|
19
|
+
return slug;
|
|
20
|
+
})
|
|
21
|
+
.sort();
|
|
22
|
+
}
|
|
23
|
+
function readTheme(themeDir) {
|
|
24
|
+
const text = readFileSync(join(themeDir, "theme.json"), "utf8");
|
|
25
|
+
return { text, json: JSON.parse(text) };
|
|
26
|
+
}
|
|
27
|
+
export function readStore(themeDir) {
|
|
28
|
+
const { json } = readTheme(themeDir);
|
|
29
|
+
const customTemplates = new Map((json.customTemplates ?? []).map((entry) => [entry.name, entry]));
|
|
30
|
+
const templateParts = new Map((json.templateParts ?? []).map((entry) => [entry.name, entry]));
|
|
31
|
+
const entities = [];
|
|
32
|
+
for (const [kind, folder] of Object.entries(STORE_DIRECTORIES)) {
|
|
33
|
+
const directory = join(themeDir, folder);
|
|
34
|
+
for (const slug of htmlSlugs(directory)) {
|
|
35
|
+
const content = readFileSync(join(directory, `${slug}.html`), "utf8");
|
|
36
|
+
let meta = {};
|
|
37
|
+
if (kind === "template" && customTemplates.has(slug)) {
|
|
38
|
+
meta = { title: customTemplates.get(slug).title };
|
|
39
|
+
}
|
|
40
|
+
else if (kind === "part") {
|
|
41
|
+
const entry = templateParts.get(slug) ?? {};
|
|
42
|
+
meta = { title: entry.title, area: entry.area };
|
|
43
|
+
}
|
|
44
|
+
else if (kind === "pattern") {
|
|
45
|
+
const metaPath = join(directory, `${slug}.json`);
|
|
46
|
+
if (!existsSync(metaPath))
|
|
47
|
+
throw new Error(`Missing ${metaPath} next to ${slug}.html.`);
|
|
48
|
+
meta = JSON.parse(readFileSync(metaPath, "utf8"));
|
|
49
|
+
}
|
|
50
|
+
entities.push({ kind, slug, content, meta });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return entities;
|
|
54
|
+
}
|
|
55
|
+
function patternMeta(meta) {
|
|
56
|
+
return {
|
|
57
|
+
title: meta.title,
|
|
58
|
+
syncStatus: meta.syncStatus,
|
|
59
|
+
status: meta.status,
|
|
60
|
+
menuOrder: meta.menuOrder,
|
|
61
|
+
categories: (meta.categories ?? []).map(({ slug, name }) => ({ slug, name })),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Writes the pulled items; returns the repository paths it touched. */
|
|
65
|
+
export function writePulled(themeDir, items, themePath = "apps/cms/theme") {
|
|
66
|
+
const touched = [];
|
|
67
|
+
const theme = readTheme(themeDir);
|
|
68
|
+
const customTemplates = new Map((theme.json.customTemplates ?? []).map((entry) => [entry.name, entry]));
|
|
69
|
+
const templateParts = new Map((theme.json.templateParts ?? []).map((entry) => [entry.name, entry]));
|
|
70
|
+
for (const item of items) {
|
|
71
|
+
const directory = join(themeDir, STORE_DIRECTORIES[item.kind]);
|
|
72
|
+
const html = join(directory, `${item.slug}.html`);
|
|
73
|
+
const sidecar = join(directory, `${item.slug}.json`);
|
|
74
|
+
if (item.action === "delete") {
|
|
75
|
+
rmSync(html, { force: true });
|
|
76
|
+
rmSync(sidecar, { force: true });
|
|
77
|
+
touched.push(`${themePath}/${STORE_DIRECTORIES[item.kind]}/${item.slug}.{html,json}`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (item.action !== "write")
|
|
81
|
+
continue;
|
|
82
|
+
mkdirSync(directory, { recursive: true });
|
|
83
|
+
writeFileSync(html, item.content);
|
|
84
|
+
touched.push(`${themePath}/${STORE_DIRECTORIES[item.kind]}/${item.slug}.html`);
|
|
85
|
+
if (item.kind === "pattern") {
|
|
86
|
+
writeFileSync(sidecar, `${JSON.stringify(patternMeta(item.meta), null, 2)}\n`);
|
|
87
|
+
}
|
|
88
|
+
else if (item.kind === "part") {
|
|
89
|
+
const { name: _name, title: _title, area: _area, ...rest } = templateParts.get(item.slug) ?? {};
|
|
90
|
+
templateParts.set(item.slug, { name: item.slug, title: item.meta.title, area: item.meta.area, ...rest });
|
|
91
|
+
}
|
|
92
|
+
else if (item.meta?.title !== undefined) {
|
|
93
|
+
const { name: _name, title: _title, ...rest } = customTemplates.get(item.slug) ?? {};
|
|
94
|
+
customTemplates.set(item.slug, { name: item.slug, title: item.meta.title, ...rest });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
let text = theme.text;
|
|
98
|
+
const sorted = (entries) => [...entries.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
99
|
+
if (customTemplates.size)
|
|
100
|
+
text = setTopLevelJsonValue(text, "customTemplates", formatEntries(sorted(customTemplates)));
|
|
101
|
+
if (templateParts.size)
|
|
102
|
+
text = setTopLevelJsonValue(text, "templateParts", formatEntries(sorted(templateParts)));
|
|
103
|
+
if (text !== theme.text) {
|
|
104
|
+
writeFileSync(join(themeDir, "theme.json"), text);
|
|
105
|
+
touched.push(`${themePath}/theme.json`);
|
|
106
|
+
}
|
|
107
|
+
return touched;
|
|
108
|
+
}
|
|
109
|
+
/** One entry per line, like the compact objects already used in theme.json. */
|
|
110
|
+
export function formatEntries(entries) {
|
|
111
|
+
if (!entries.length)
|
|
112
|
+
return "[]";
|
|
113
|
+
const inline = (entry) => `{ ${Object.entries(entry).map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`).join(", ")} }`;
|
|
114
|
+
return `[\n${entries.map((entry) => ` ${inline(entry)}`).join(",\n")}\n ]`;
|
|
115
|
+
}
|
|
116
|
+
/** Index just past the JSON value starting at `start`. */
|
|
117
|
+
function valueEnd(text, start) {
|
|
118
|
+
let depth = 0;
|
|
119
|
+
for (let index = start; index < text.length; index++) {
|
|
120
|
+
const char = text[index];
|
|
121
|
+
if (char === '"') {
|
|
122
|
+
index = stringEnd(text, index) - 1;
|
|
123
|
+
if (depth === 0)
|
|
124
|
+
return index + 1;
|
|
125
|
+
}
|
|
126
|
+
else if (char === "{" || char === "[") {
|
|
127
|
+
depth++;
|
|
128
|
+
}
|
|
129
|
+
else if (char === "}" || char === "]") {
|
|
130
|
+
depth--;
|
|
131
|
+
if (depth === 0)
|
|
132
|
+
return index + 1;
|
|
133
|
+
if (depth < 0)
|
|
134
|
+
return index;
|
|
135
|
+
}
|
|
136
|
+
else if (depth === 0 && (char === "," || /\s/.test(char))) {
|
|
137
|
+
return index;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return text.length;
|
|
141
|
+
}
|
|
142
|
+
function stringEnd(text, start) {
|
|
143
|
+
for (let index = start + 1; index < text.length; index++) {
|
|
144
|
+
if (text[index] === "\\")
|
|
145
|
+
index++;
|
|
146
|
+
else if (text[index] === '"')
|
|
147
|
+
return index + 1;
|
|
148
|
+
}
|
|
149
|
+
throw new Error("Unterminated string in theme.json.");
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Replaces (or appends) one top-level value and leaves every other byte of
|
|
153
|
+
* the file untouched: theme.json is formatted by hand.
|
|
154
|
+
*/
|
|
155
|
+
export function setTopLevelJsonValue(text, key, valueText) {
|
|
156
|
+
JSON.parse(text);
|
|
157
|
+
const open = text.indexOf("{");
|
|
158
|
+
let index = open + 1;
|
|
159
|
+
while (index < text.length) {
|
|
160
|
+
const char = text[index];
|
|
161
|
+
if (char === '"') {
|
|
162
|
+
const end = stringEnd(text, index);
|
|
163
|
+
const name = JSON.parse(text.slice(index, end));
|
|
164
|
+
const colon = text.indexOf(":", end);
|
|
165
|
+
let start = colon + 1;
|
|
166
|
+
while (/\s/.test(text[start]))
|
|
167
|
+
start++;
|
|
168
|
+
const finish = valueEnd(text, start);
|
|
169
|
+
if (name === key)
|
|
170
|
+
return text.slice(0, start) + valueText + text.slice(finish);
|
|
171
|
+
index = finish;
|
|
172
|
+
}
|
|
173
|
+
else if (char === "}") {
|
|
174
|
+
const head = text.slice(0, index).replace(/\s*$/, "");
|
|
175
|
+
const separator = head.endsWith("{") ? "" : ",";
|
|
176
|
+
return `${head}${separator}\n ${JSON.stringify(key)}: ${valueText}\n${text.slice(index)}`;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
index++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
throw new Error("theme.json is not a JSON object.");
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=store.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/store.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Backend identity and credentials come from the backend's own environment. */
|
|
2
|
+
export function resolveTarget({ root, manifest, flag, env, readTarget }?: {
|
|
3
|
+
manifest?: any;
|
|
4
|
+
flag?: string | undefined;
|
|
5
|
+
env?: import("dotenv-expand").DotenvParseOutput | undefined;
|
|
6
|
+
readTarget?: ((name: any) => any) | undefined;
|
|
7
|
+
}): {
|
|
8
|
+
name: string;
|
|
9
|
+
backendName: string;
|
|
10
|
+
backendUrl: string;
|
|
11
|
+
origin: string;
|
|
12
|
+
local: boolean;
|
|
13
|
+
auth: string;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=target.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.d.mts","sourceRoot":"","sources":["../../../src/ops/cms-template/target.mjs"],"names":[],"mappings":"AAGA,gFAAgF;AAChF;;;;;;;;;;;;EAgBC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { readManifest, targetConfig } from "../config.js";
|
|
2
|
+
import { loadEnvironment, manifestEnvironment } from "../environment.js";
|
|
3
|
+
/** Backend identity and credentials come from the backend's own environment. */
|
|
4
|
+
export function resolveTarget({ root, manifest = readManifest(root), flag = "", env = loadEnvironment("local", root), readTarget = name => manifestEnvironment(root, name, {}) } = {}) {
|
|
5
|
+
const name = String(flag || env.FRONTEND_BACKEND_TARGET || "local").trim();
|
|
6
|
+
if (!Object.hasOwn(manifest.environments, name))
|
|
7
|
+
throw new Error(`Unknown target "${name}".`);
|
|
8
|
+
let backendName = name;
|
|
9
|
+
const seen = new Set();
|
|
10
|
+
while (targetConfig(manifest, backendName).backend) {
|
|
11
|
+
if (seen.has(backendName))
|
|
12
|
+
throw new Error("Cyclic backend reference.");
|
|
13
|
+
seen.add(backendName);
|
|
14
|
+
backendName = targetConfig(manifest, backendName).backend;
|
|
15
|
+
}
|
|
16
|
+
const backend = readTarget(backendName);
|
|
17
|
+
const backendUrl = String(targetConfig(manifest, backendName).backendUrl || backend.BACKEND_URL || "").replace(/\/+$/, "");
|
|
18
|
+
const url = new URL(backendUrl);
|
|
19
|
+
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.search || url.hash)
|
|
20
|
+
throw new Error("Invalid backend URL.");
|
|
21
|
+
const local = manifest.environments.local?.backendUrl && url.origin === new URL(manifest.environments.local.backendUrl).origin;
|
|
22
|
+
return { name, backendName, backendUrl, origin: url.origin, local: Boolean(local), auth: local ? "" : String(backend.CMS_SYNC_AUTH || "").trim() };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=target.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/target.mjs"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEzE,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE;IACnL,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,uBAAuB,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,IAAI,CAAC,CAAC;IAC9F,IAAI,WAAW,GAAG,IAAI,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,OAAO,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;QACnD,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACxE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtB,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC;IAC5D,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3H,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACnJ,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IAC/H,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AACrJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local backend: the command runs inside the Docker CMS through `wp eval`. The
|
|
3
|
+
* request goes through the bind-mounted .local/ folder instead of argv, which
|
|
4
|
+
* would hit ARG_MAX with large templates.
|
|
5
|
+
*/
|
|
6
|
+
export function dockerTransport({ root, run }: {
|
|
7
|
+
root: any;
|
|
8
|
+
run?: typeof spawnSync | undefined;
|
|
9
|
+
}): {
|
|
10
|
+
kind: string;
|
|
11
|
+
call(operation: any, args?: {}): Promise<any>;
|
|
12
|
+
};
|
|
13
|
+
export function dockerProgram(path: any): string;
|
|
14
|
+
export function parseDockerResponse(result: any): any;
|
|
15
|
+
/** Remote backends: official Site Editor sync REST routes, Application Password (Basic) auth. */
|
|
16
|
+
export function restTransport({ backendUrl, auth, targetName, fetchImpl }: {
|
|
17
|
+
backendUrl: any;
|
|
18
|
+
auth: any;
|
|
19
|
+
targetName: any;
|
|
20
|
+
fetchImpl?: typeof fetch | undefined;
|
|
21
|
+
}): {
|
|
22
|
+
kind: string;
|
|
23
|
+
call(operation: any, args?: {}): Promise<any>;
|
|
24
|
+
};
|
|
25
|
+
import { spawnSync } from "node:child_process";
|
|
26
|
+
//# sourceMappingURL=transport.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.mts","sourceRoot":"","sources":["../../../src/ops/cms-template/transport.mjs"],"names":[],"mappings":"AASA;;;;GAIG;AACH;;;;;;EAuBC;AAED,iDAiBC;AAED,sDAYC;AAED,iGAAiG;AACjG;;;;;;;;EAmDC;0BA1HyB,oBAAoB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { localComposeArgs } from "../local.js";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
const RESPONSE_MARKER = "@@cms-template@@";
|
|
7
|
+
const ROUTE = "wp-json/flowpress/v1/site-editor-sync";
|
|
8
|
+
/**
|
|
9
|
+
* Local backend: the command runs inside the Docker CMS through `wp eval`. The
|
|
10
|
+
* request goes through the bind-mounted .local/ folder instead of argv, which
|
|
11
|
+
* would hit ARG_MAX with large templates.
|
|
12
|
+
*/
|
|
13
|
+
export function dockerTransport({ root, run = spawnSync }) {
|
|
14
|
+
return {
|
|
15
|
+
kind: "docker",
|
|
16
|
+
async call(operation, args = {}) {
|
|
17
|
+
const directory = join(root, ".local", "cms-template");
|
|
18
|
+
const name = `request-${randomUUID()}.json`;
|
|
19
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
20
|
+
writeFileSync(join(directory, name), JSON.stringify({ operation, args }), { mode: 0o600, flag: "wx" });
|
|
21
|
+
try {
|
|
22
|
+
const result = run("docker", [
|
|
23
|
+
...localComposeArgs(root),
|
|
24
|
+
"exec", "-T", "cms",
|
|
25
|
+
"/workspace/apps/cms/vendor/bin/wp",
|
|
26
|
+
"--allow-root",
|
|
27
|
+
"--path=/workspace/apps/cms/web/wp",
|
|
28
|
+
"eval", dockerProgram(`/workspace/.local/cms-template/${name}`),
|
|
29
|
+
], { cwd: root, encoding: "utf8", maxBuffer: 256 * 1024 * 1024 });
|
|
30
|
+
return parseDockerResponse(result);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
rmSync(join(directory, name), { force: true });
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function dockerProgram(path) {
|
|
39
|
+
return String.raw `
|
|
40
|
+
$request = json_decode((string) file_get_contents(${JSON.stringify(path)}), true, 512, JSON_THROW_ON_ERROR);
|
|
41
|
+
try {
|
|
42
|
+
if (! function_exists('flowpress_site_editor_sync_dispatch')) {
|
|
43
|
+
throw new RuntimeException('The CMS does not load the official FlowPress Site Editor sync module.');
|
|
44
|
+
}
|
|
45
|
+
$admins = get_users(['role' => 'administrator', 'number' => 1, 'orderby' => 'ID', 'order' => 'ASC', 'fields' => 'ID']);
|
|
46
|
+
if (! $admins) throw new RuntimeException('The local CMS has no administrator.');
|
|
47
|
+
// Saves run as an administrator, like an editor session (trusted code, kses).
|
|
48
|
+
wp_set_current_user((int) $admins[0]);
|
|
49
|
+
$response = ['ok' => true, 'result' => flowpress_site_editor_sync_dispatch((string) $request['operation'], (array) $request['args'])];
|
|
50
|
+
} catch (Throwable $error) {
|
|
51
|
+
$response = ['ok' => false, 'error' => $error->getMessage()];
|
|
52
|
+
}
|
|
53
|
+
echo "\n${RESPONSE_MARKER}\n", wp_json_encode($response);
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
export function parseDockerResponse(result) {
|
|
57
|
+
if (result.error || result.status !== 0)
|
|
58
|
+
throw new Error(`The local CMS command failed (exit ${result.status ?? "unknown"}). ${String(result.stderr ?? "").trim()}`);
|
|
59
|
+
const output = String(result.stdout ?? "");
|
|
60
|
+
const index = output.lastIndexOf(RESPONSE_MARKER);
|
|
61
|
+
if (index < 0) {
|
|
62
|
+
throw new Error(`The local CMS did not answer (exit ${result.status}). Is the Docker stack running (pnpm dev)?\n${String(result.stderr || output).trim()}`);
|
|
63
|
+
}
|
|
64
|
+
const response = JSON.parse(output.slice(index + RESPONSE_MARKER.length));
|
|
65
|
+
if (!response.ok)
|
|
66
|
+
throw new Error(response.error);
|
|
67
|
+
return response.result;
|
|
68
|
+
}
|
|
69
|
+
/** Remote backends: official Site Editor sync REST routes, Application Password (Basic) auth. */
|
|
70
|
+
export function restTransport({ backendUrl, auth, targetName, fetchImpl = fetch }) {
|
|
71
|
+
if (!/^[^:]+:.+$/.test(auth)) {
|
|
72
|
+
throw new Error(`CMS_SYNC_AUTH is missing in .env.${targetName}: set it to "<user>:<application password>" ` +
|
|
73
|
+
"for a user with the edit_theme_options capability (Users → Profile → Application Passwords).");
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
kind: "rest",
|
|
77
|
+
async call(operation, args = {}) {
|
|
78
|
+
const read = operation === "status";
|
|
79
|
+
const response = await fetchImpl(`${backendUrl}/${ROUTE}/${operation}`, {
|
|
80
|
+
method: read ? "GET" : "POST",
|
|
81
|
+
headers: {
|
|
82
|
+
accept: "application/json",
|
|
83
|
+
authorization: `Basic ${Buffer.from(auth).toString("base64")}`,
|
|
84
|
+
...(read ? {} : { "content-type": "application/json" }),
|
|
85
|
+
},
|
|
86
|
+
body: read ? undefined : JSON.stringify(args),
|
|
87
|
+
});
|
|
88
|
+
const text = await response.text();
|
|
89
|
+
let body = null;
|
|
90
|
+
try {
|
|
91
|
+
body = JSON.parse(text);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Reported below with the HTTP status.
|
|
95
|
+
}
|
|
96
|
+
if (response.status === 404 && body?.code === "rest_no_route") {
|
|
97
|
+
throw new Error(`${backendUrl} does not expose the Site Editor sync routes: deploy the backend first (pnpm backend:deploy).`);
|
|
98
|
+
}
|
|
99
|
+
if (["rest_forbidden", "rest_not_logged_in"].includes(body?.code)) {
|
|
100
|
+
// This stack answers a wrong password as anonymous too, not only a dropped header.
|
|
101
|
+
throw new Error(`${backendUrl} treated the request as anonymous (${body.code}): check CMS_SYNC_AUTH in .env.${targetName} ` +
|
|
102
|
+
"and that the user has edit_theme_options; if both are right, the host strips the Authorization header " +
|
|
103
|
+
"(see apps/cms/web/.htaccess).");
|
|
104
|
+
}
|
|
105
|
+
if (response.status === 401 || response.status === 403) {
|
|
106
|
+
throw new Error(`${backendUrl} refused the credentials (${body?.code ?? response.status}): check CMS_SYNC_AUTH in .env.${targetName}.`);
|
|
107
|
+
}
|
|
108
|
+
if (!response.ok || body === null) {
|
|
109
|
+
throw new Error(body?.message ?? `${backendUrl} answered HTTP ${response.status}.`);
|
|
110
|
+
}
|
|
111
|
+
return body;
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=transport.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.mjs","sourceRoot":"","sources":["../../../src/ops/cms-template/transport.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function featurePackages(id: any): {
|
|
2
|
+
npm: string;
|
|
3
|
+
composer: string;
|
|
4
|
+
};
|
|
5
|
+
export function readFeatures(root: any): any;
|
|
6
|
+
export function checkFeatures(root: any, id: any): {
|
|
7
|
+
features: any;
|
|
8
|
+
valid: boolean;
|
|
9
|
+
};
|
|
10
|
+
export function featureCommand(root: any, args: any, execute?: typeof run): any;
|
|
11
|
+
import { run } from "./process.js";
|
|
12
|
+
//# sourceMappingURL=features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/ops/features.js"],"names":[],"mappings":"AAIA;;;EAGC;AACD,6CAUC;AACD;;;EAQC;AACD,gFAyBC;oBAnDmB,cAAc"}
|