@styleflow.app/flowpress-deploy 1.0.0-beta.2 → 1.0.0-beta.20
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 +111 -0
- package/README.md +5 -0
- package/containers/cms/Dockerfile +35 -0
- package/containers/cms/Dockerfile.dockerignore +20 -0
- package/containers/cms/healthz.php +17 -0
- package/containers/cms/install-languages.sh +16 -0
- package/containers/cms/mpm.conf +10 -0
- package/containers/cms/php.ini +16 -0
- package/containers/cms/sanitize-integrations.php +14 -0
- package/containers/cms/sanitize.php +37 -0
- package/containers/cms/smtp.php +13 -0
- package/containers/cms/vhost.conf +61 -0
- package/containers/cms/wp-cli.yml +1 -0
- package/containers/local/cms/Dockerfile +18 -0
- package/containers/local/cms/entrypoint.sh +7 -0
- package/containers/local/cms/php.ini +8 -0
- package/containers/local/cms/vhost.conf +14 -0
- package/containers/local/web/Dockerfile +8 -0
- package/containers/local/web/entrypoint.sh +10 -0
- package/containers/php-runtime/Dockerfile +21 -0
- package/containers/web-ssr/Dockerfile +27 -0
- package/containers/web-ssr/Dockerfile.dockerignore +10 -0
- package/containers/web-static/Caddyfile +40 -0
- package/containers/web-static/Dockerfile +17 -0
- package/containers/web-static/Dockerfile.dockerignore +7 -0
- package/dist/development.d.ts +4 -0
- package/dist/development.d.ts.map +1 -0
- package/dist/development.js +10 -0
- package/dist/development.js.map +1 -0
- package/dist/node-fetch.d.ts +3 -0
- package/dist/node-fetch.d.ts.map +1 -0
- package/dist/node-fetch.js +20 -0
- package/dist/node-fetch.js.map +1 -0
- package/dist/ops/bootstrap.d.ts +21 -0
- package/dist/ops/bootstrap.d.ts.map +1 -0
- package/dist/ops/bootstrap.js +123 -0
- package/dist/ops/bootstrap.js.map +1 -0
- package/dist/ops/build.d.ts +39 -0
- package/dist/ops/build.d.ts.map +1 -0
- package/dist/ops/build.js +110 -0
- package/dist/ops/build.js.map +1 -0
- package/dist/ops/check.d.ts +18 -0
- package/dist/ops/check.d.ts.map +1 -0
- package/dist/ops/check.js +46 -0
- package/dist/ops/check.js.map +1 -0
- package/dist/ops/cli.d.ts +3 -0
- package/dist/ops/cli.d.ts.map +1 -0
- package/dist/ops/cli.js +166 -0
- package/dist/ops/cli.js.map +1 -0
- package/dist/ops/config.d.ts +54 -0
- package/dist/ops/config.d.ts.map +1 -0
- package/dist/ops/config.js +202 -0
- package/dist/ops/config.js.map +1 -0
- package/dist/ops/coolify.d.ts +2 -0
- package/dist/ops/coolify.d.ts.map +1 -0
- package/dist/ops/coolify.js +44 -0
- package/dist/ops/coolify.js.map +1 -0
- package/dist/ops/data.d.ts +31 -0
- package/dist/ops/data.d.ts.map +1 -0
- package/dist/ops/data.js +163 -0
- package/dist/ops/data.js.map +1 -0
- package/dist/ops/deploy.d.ts +38 -0
- package/dist/ops/deploy.d.ts.map +1 -0
- package/dist/ops/deploy.js +127 -0
- package/dist/ops/deploy.js.map +1 -0
- package/dist/ops/editorial.d.ts +23 -0
- package/dist/ops/editorial.d.ts.map +1 -0
- package/dist/ops/editorial.js +79 -0
- package/dist/ops/editorial.js.map +1 -0
- package/dist/ops/environment-files.d.ts +9 -0
- package/dist/ops/environment-files.d.ts.map +1 -0
- package/dist/ops/environment-files.js +125 -0
- package/dist/ops/environment-files.js.map +1 -0
- package/dist/ops/environment.d.ts +29 -0
- package/dist/ops/environment.d.ts.map +1 -0
- package/dist/ops/environment.js +159 -0
- package/dist/ops/environment.js.map +1 -0
- package/dist/ops/health.d.ts +26 -0
- package/dist/ops/health.d.ts.map +1 -0
- package/dist/ops/health.js +27 -0
- package/dist/ops/health.js.map +1 -0
- package/dist/ops/local.d.ts +161 -0
- package/dist/ops/local.d.ts.map +1 -0
- package/dist/ops/local.js +173 -0
- package/dist/ops/local.js.map +1 -0
- package/dist/ops/monitor.d.ts +23 -0
- package/dist/ops/monitor.d.ts.map +1 -0
- package/dist/ops/monitor.js +143 -0
- package/dist/ops/monitor.js.map +1 -0
- package/dist/ops/process.d.ts +9 -0
- package/dist/ops/process.d.ts.map +1 -0
- package/dist/ops/process.js +56 -0
- package/dist/ops/process.js.map +1 -0
- package/dist/ops/provision.d.ts +41 -0
- package/dist/ops/provision.d.ts.map +1 -0
- package/dist/ops/provision.js +268 -0
- package/dist/ops/provision.js.map +1 -0
- package/dist/ops/registry.d.ts +7 -0
- package/dist/ops/registry.d.ts.map +1 -0
- package/dist/ops/registry.js +73 -0
- package/dist/ops/registry.js.map +1 -0
- package/dist/ops/release.d.ts +26 -0
- package/dist/ops/release.d.ts.map +1 -0
- package/dist/ops/release.js +79 -0
- package/dist/ops/release.js.map +1 -0
- package/dist/ops/s3.d.ts +8 -0
- package/dist/ops/s3.d.ts.map +1 -0
- package/dist/ops/s3.js +38 -0
- package/dist/ops/s3.js.map +1 -0
- package/dist/ops/static-config.d.ts +14 -0
- package/dist/ops/static-config.d.ts.map +1 -0
- package/dist/ops/static-config.js +96 -0
- package/dist/ops/static-config.js.map +1 -0
- package/flowpress-deploy.php +2 -2
- package/includes/automatic-build.php +22 -5
- package/package.json +40 -6
- package/schema/deployment.schema.json +185 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { allowedComponents, loadState, operatorEnvironment, readJson, releaseTag, saveState } from "./config.js";
|
|
3
|
+
import { existingDigest, imageMetadata } from "./registry.js";
|
|
4
|
+
import { coolifyClient } from "./coolify.js";
|
|
5
|
+
import { inspectDigest, registryLogin } from "./build.js";
|
|
6
|
+
import { run, sleep } from "./process.js";
|
|
7
|
+
export function assertRelease(release, app, name, component) {
|
|
8
|
+
if (!release || release.environment !== name || release.component !== component || release.repository !== app.repository
|
|
9
|
+
|| !/^[a-f0-9]{40}$/.test(release.sha || "") || !/^sha256:[a-f0-9]{64}$/.test(release.digest || "")
|
|
10
|
+
|| !/^[a-zA-Z0-9_.-]+$/.test(release.tag || ""))
|
|
11
|
+
throw new Error("Invalid or mismatched immutable release record.");
|
|
12
|
+
}
|
|
13
|
+
export async function waitHealth(app, release, { fetchImpl = fetch, attempts = 60, delay = 3000 } = {}) {
|
|
14
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
15
|
+
try {
|
|
16
|
+
const res = await fetchImpl(app.url + app.health + "?release=" + Date.now(), { signal: AbortSignal.timeout(10000), redirect: "error", headers: { "cache-control": "no-cache" } });
|
|
17
|
+
const data = await res.json();
|
|
18
|
+
if (res.ok && data.status === "ok" && data.release === release.sha && (!release.environment || data.environment === release.environment) && (!release.buildId || data.buildId === release.buildId)) {
|
|
19
|
+
if (app.health === "/healthz.php") {
|
|
20
|
+
const graphql = await fetchImpl(app.url + "/index.php?graphql", { method: "POST", redirect: "error", signal: AbortSignal.timeout(10000), headers: { "content-type": "application/json" }, body: JSON.stringify({ query: "{ __typename }" }) });
|
|
21
|
+
const schema = await graphql.json();
|
|
22
|
+
if (!graphql.ok || !schema.data?.__typename || schema.errors?.length)
|
|
23
|
+
throw new Error("WordPress GraphQL runtime is not ready.");
|
|
24
|
+
}
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch { /* rolling replacement is expected to fail briefly */ }
|
|
29
|
+
if (attempt + 1 < attempts)
|
|
30
|
+
await sleep(delay);
|
|
31
|
+
}
|
|
32
|
+
throw new Error("Release health verification failed for " + app.name + ".");
|
|
33
|
+
}
|
|
34
|
+
export async function waitDeployment(api, id) {
|
|
35
|
+
if (!id)
|
|
36
|
+
throw new Error("Coolify returned no deployment ID.");
|
|
37
|
+
for (let attempt = 0; attempt < 240; attempt++) {
|
|
38
|
+
const result = await api("GET", "/deployments/" + id);
|
|
39
|
+
if (result.status === "finished")
|
|
40
|
+
return;
|
|
41
|
+
if (["failed", "cancelled", "cancelled-by-user"].includes(result.status))
|
|
42
|
+
throw new Error("Coolify deployment " + result.status + ".");
|
|
43
|
+
await sleep(5000);
|
|
44
|
+
}
|
|
45
|
+
throw new Error("Coolify deployment timeout.");
|
|
46
|
+
}
|
|
47
|
+
export async function registryRelease(app, name, component, alias, operator) {
|
|
48
|
+
const metadata = await imageMetadata(app.repository + ":" + alias, operator);
|
|
49
|
+
if (!metadata)
|
|
50
|
+
return null;
|
|
51
|
+
const tag = releaseTag(component, name, metadata.sha, metadata.buildId);
|
|
52
|
+
if (await existingDigest(app.repository + ":" + tag, operator) !== metadata.digest)
|
|
53
|
+
throw new Error("Release alias differs from its immutable tag.");
|
|
54
|
+
return { component, environment: name, repository: app.repository, tag, sha: metadata.sha, digest: metadata.digest, buildId: component === "cms" ? undefined : metadata.buildId, pushed: true };
|
|
55
|
+
}
|
|
56
|
+
export async function deployedRelease(root, name, component) {
|
|
57
|
+
const state = loadState(root, name), app = state.apps?.[component];
|
|
58
|
+
if (!app?.uuid)
|
|
59
|
+
throw new Error("Component not provisioned.");
|
|
60
|
+
return registryRelease(app, name, component, name, operatorEnvironment(root));
|
|
61
|
+
}
|
|
62
|
+
function retain(app, alias, release) {
|
|
63
|
+
run("docker", ["buildx", "imagetools", "create", "--prefer-index=false", "--tag", app.repository + ":" + alias, release.repository + "@" + release.digest]);
|
|
64
|
+
if (inspectDigest(app.repository + ":" + alias) !== release.digest)
|
|
65
|
+
throw new Error("Retained image digest mismatch.");
|
|
66
|
+
}
|
|
67
|
+
async function launch(api, app, release, name) {
|
|
68
|
+
retain(app, name, release);
|
|
69
|
+
const response = await api("POST", "/deploy?uuid=" + app.uuid + "&force=false");
|
|
70
|
+
const deployment = (response.deployments || [response]).find(item => item.deployment_uuid);
|
|
71
|
+
await waitDeployment(api, deployment?.deployment_uuid);
|
|
72
|
+
return waitHealth(app, release);
|
|
73
|
+
}
|
|
74
|
+
export async function deploy(root, manifest, name, component, { rollback = false, release: supplied } = {}) {
|
|
75
|
+
allowedComponents(manifest, name, [component]);
|
|
76
|
+
const state = loadState(root, name);
|
|
77
|
+
const app = state.apps?.[component];
|
|
78
|
+
if (!app?.uuid)
|
|
79
|
+
throw new Error("Provision this component first.");
|
|
80
|
+
const operator = operatorEnvironment(root);
|
|
81
|
+
registryLogin(state.platform, operator);
|
|
82
|
+
const record = supplied || (rollback ? await registryRelease(app, name, component, name + "-previous", operator) : readJson(join(root, ".local/flowpress", "release-" + name + "-" + component + ".json")));
|
|
83
|
+
assertRelease(record, app, name, component);
|
|
84
|
+
if (name === "production" && component === "cms" && !rollback) {
|
|
85
|
+
const staging = loadState(root, "staging").apps?.cms;
|
|
86
|
+
const verified = staging && await registryRelease(staging, "staging", "cms", "staging", operator);
|
|
87
|
+
if (!verified || verified.sha !== record.sha || verified.digest !== record.digest)
|
|
88
|
+
throw new Error("Production must promote the exact CMS image verified on staging.");
|
|
89
|
+
await waitHealth(staging, verified);
|
|
90
|
+
}
|
|
91
|
+
if (inspectDigest(record.repository + ":" + record.tag) !== record.digest)
|
|
92
|
+
throw new Error("Registry digest changed; deployment refused.");
|
|
93
|
+
const api = coolifyClient(state.platform.coolifyUrl, operator.COOLIFY_TOKEN);
|
|
94
|
+
const configured = await api("GET", "/applications/" + app.uuid);
|
|
95
|
+
if (configured.docker_registry_image_name !== app.repository)
|
|
96
|
+
throw new Error("Application repository drift; review provisioning before deployment.");
|
|
97
|
+
if (configured.docker_registry_image_tag !== name)
|
|
98
|
+
throw new Error("Run operator provisioning to configure the managed environment tag.");
|
|
99
|
+
let previous = await registryRelease(app, name, component, name, operator);
|
|
100
|
+
if (previous) {
|
|
101
|
+
try {
|
|
102
|
+
await waitHealth(app, previous, { attempts: 1 });
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
previous = await registryRelease(app, name, component, name + "-previous", operator);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (previous && previous.digest !== record.digest)
|
|
109
|
+
retain(app, name + "-previous", previous);
|
|
110
|
+
try {
|
|
111
|
+
await launch(api, app, record, name);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (previous && previous.digest !== record.digest) {
|
|
115
|
+
await launch(api, app, previous, name);
|
|
116
|
+
throw new Error(error.message + " Previous image restored; database was not rolled back.");
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
if (previous && previous.digest !== record.digest)
|
|
121
|
+
app.previous = previous;
|
|
122
|
+
app.current = record;
|
|
123
|
+
app.deployedAt = new Date().toISOString();
|
|
124
|
+
saveState(root, name, state);
|
|
125
|
+
return { component, environment: name, release: record.sha, digest: record.digest, url: app.url, rollback };
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/ops/deploy.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS;IACzD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,GAAG,CAAC,UAAU;WACnH,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;WAChG,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACxH,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,SAAS,GAAG,KAAK,EAAE,QAAQ,GAAG,EAAE,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE;IACpG,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;YAClL,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnM,IAAI,GAAG,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;oBAClC,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,oBAAoB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC;oBAC/O,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;oBACpC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM;wBAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;gBACnI,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,qDAAqD,CAAC,CAAC;QACjE,IAAI,OAAO,GAAG,CAAC,GAAG,QAAQ;YAAE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AAC9E,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAG,EAAE,EAAE;IAC1C,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAC/D,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,eAAe,GAAG,EAAE,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO;QACzC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,mBAAmB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QACvI,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ;IACzE,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7E,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxE,IAAI,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,GAAG,GAAG,EAAE,QAAQ,CAAC,KAAK,QAAQ,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACrJ,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClM,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS;IACzD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,CAAC,GAAG,EAAE,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC9D,OAAO,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;AAChF,CAAC;AACD,SAAS,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO;IACjC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,GAAG,GAAG,GAAG,KAAK,EAAE,OAAO,CAAC,UAAU,GAAG,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5J,IAAI,aAAa,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;AACzH,CAAC;AACD,KAAK,UAAU,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI;IAC3C,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,eAAe,GAAG,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC;IAChF,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC3F,MAAM,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;IACvD,OAAO,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,GAAG,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE;IACxG,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG,EAAE,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC3C,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,UAAU,GAAG,IAAI,GAAG,GAAG,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5M,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5C,IAAI,IAAI,KAAK,YAAY,IAAI,SAAS,KAAK,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC;QACrD,MAAM,QAAQ,GAAG,OAAO,IAAI,MAAM,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAClG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACvK,MAAM,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,CAAC,UAAU,GAAG,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC3I,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,gBAAgB,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,UAAU,CAAC,0BAA0B,KAAK,GAAG,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IACtJ,IAAI,UAAU,CAAC,yBAAyB,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IAC1I,IAAI,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3E,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YAAC,MAAM,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;QACzD,MAAM,CAAC;YAAC,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,WAAW,EAAE,QAAQ,CAAC,CAAC;QAAC,CAAC;IACjG,CAAC;IACD,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,EAAE,IAAI,GAAG,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE7F,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YAClD,MAAM,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,yDAAyD,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3E,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC;IACrB,GAAG,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAE7B,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC;AAC9G,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function validateBuildRequest(payload: any): {
|
|
2
|
+
target: any;
|
|
3
|
+
batchId: any;
|
|
4
|
+
mode: any;
|
|
5
|
+
paths: string[];
|
|
6
|
+
deletedPaths: string[];
|
|
7
|
+
};
|
|
8
|
+
export function validateBuildId(value: any): any;
|
|
9
|
+
export function purgeFiles(site: any, routes: any, assets?: any[]): string[];
|
|
10
|
+
export function purgeFrontendFiles({ files, token, zone, fetchImpl }: {
|
|
11
|
+
files: any;
|
|
12
|
+
token: any;
|
|
13
|
+
zone: any;
|
|
14
|
+
fetchImpl?: typeof fetch | undefined;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export function acknowledgeBatch({ request, backend, token, status, fetchImpl }: {
|
|
17
|
+
request: any;
|
|
18
|
+
backend: any;
|
|
19
|
+
token: any;
|
|
20
|
+
status: any;
|
|
21
|
+
fetchImpl?: typeof fetch | undefined;
|
|
22
|
+
}): Promise<any>;
|
|
23
|
+
//# sourceMappingURL=editorial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorial.d.ts","sourceRoot":"","sources":["../../src/ops/editorial.js"],"names":[],"mappings":"AAEA;;;;;;EAUC;AAED,iDAIC;AAED,6EAgBC;AAED;;;;;kBAWC;AAED;;;;;;iBAkBC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { normalizeDeployPath } from "@styleflow.app/flowpress-deploy";
|
|
2
|
+
export function validateBuildRequest(payload) {
|
|
3
|
+
if (!payload || !["staging", "production"].includes(payload.target))
|
|
4
|
+
throw new Error("Invalid editorial target.");
|
|
5
|
+
if (!/^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i.test(payload.batchId || ""))
|
|
6
|
+
throw new Error("Invalid editorial batchId.");
|
|
7
|
+
if (!["full", "partial"].includes(payload.mode))
|
|
8
|
+
throw new Error("Invalid editorial build mode.");
|
|
9
|
+
const paths = (key) => {
|
|
10
|
+
const values = payload[key] ?? [];
|
|
11
|
+
if (!Array.isArray(values) || values.length > 1000 || values.some((value) => typeof value !== "string" || value.length > 2048))
|
|
12
|
+
throw new Error(`Invalid editorial ${key}.`);
|
|
13
|
+
return [...new Set(values.map(normalizeDeployPath))];
|
|
14
|
+
};
|
|
15
|
+
return { target: payload.target, batchId: payload.batchId, mode: payload.mode, paths: paths("paths"), deletedPaths: paths("deletedPaths") };
|
|
16
|
+
}
|
|
17
|
+
export function validateBuildId(value) {
|
|
18
|
+
// Leave room for the environment and full SHA within the OCI tag limit (128).
|
|
19
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(value || ""))
|
|
20
|
+
throw new Error("Invalid frontend build ID.");
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
export function purgeFiles(site, routes, assets = []) {
|
|
24
|
+
const origin = new URL(site).origin;
|
|
25
|
+
const paths = new Set(["/", "/robots.txt", "/sitemap_index.xml", "/healthz.json", "/404.html"]);
|
|
26
|
+
for (const route of routes) {
|
|
27
|
+
const path = normalizeDeployPath(route);
|
|
28
|
+
paths.add(path);
|
|
29
|
+
if (path !== "/" && !path.split("/").at(-1)?.includes(".")) {
|
|
30
|
+
paths.add(path.replace(/\/+$/, ""));
|
|
31
|
+
paths.add(`${path.replace(/\/+$/, "")}/`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const asset of assets) {
|
|
35
|
+
if (typeof asset !== "string" || !/^\/_astro\/[A-Za-z0-9_./@-]+$/.test(asset) || asset.split("/").some(part => [".", ".."].includes(part)))
|
|
36
|
+
throw new Error("Invalid frontend asset purge path.");
|
|
37
|
+
paths.add(asset);
|
|
38
|
+
}
|
|
39
|
+
return [...paths].map((path) => new URL(path, origin).href);
|
|
40
|
+
}
|
|
41
|
+
export async function purgeFrontendFiles({ files, token, zone, fetchImpl = fetch }) {
|
|
42
|
+
if (!token || !/^[a-f0-9]{32}$/i.test(zone || ""))
|
|
43
|
+
throw new Error("Missing purge-only Cloudflare token or CLOUDFLARE_ZONE_ID.");
|
|
44
|
+
for (let offset = 0; offset < files.length; offset += 30) {
|
|
45
|
+
const response = await fetchImpl(`https://api.cloudflare.com/client/v4/zones/${zone}/purge_cache`, {
|
|
46
|
+
method: "POST", signal: AbortSignal.timeout(30_000), redirect: "error",
|
|
47
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
48
|
+
body: JSON.stringify({ files: files.slice(offset, offset + 30) }),
|
|
49
|
+
});
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
if (!response.ok || !data.success)
|
|
52
|
+
throw new Error(`Cloudflare URL purge failed (${response.status}).`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export async function acknowledgeBatch({ request, backend, token, status, fetchImpl = fetch }) {
|
|
56
|
+
validateBuildRequest(request);
|
|
57
|
+
if (!["success", "failure"].includes(status) || !token)
|
|
58
|
+
throw new Error("Missing callback token or invalid callback status.");
|
|
59
|
+
const url = new URL("/wp-json/flowpress/v1/build-complete", backend);
|
|
60
|
+
let last;
|
|
61
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetchImpl(url, {
|
|
64
|
+
method: "POST", redirect: "error", signal: AbortSignal.timeout(15_000),
|
|
65
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
66
|
+
body: JSON.stringify({ batchId: request.batchId, status }),
|
|
67
|
+
});
|
|
68
|
+
const body = await response.json();
|
|
69
|
+
if (!response.ok || body.ok !== true)
|
|
70
|
+
throw new Error(`CMS callback failed (${response.status}).`);
|
|
71
|
+
return body;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
last = error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
throw last;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=editorial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorial.js","sourceRoot":"","sources":["../../src/ops/editorial.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,UAAU,oBAAoB,CAAC,OAAO;IAC1C,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAClH,IAAI,CAAC,4EAA4E,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC7J,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAClG,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,EAAE;QACpB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,GAAG,CAAC,CAAC;QAC7K,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;AAC9I,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAK;IACnC,8EAA8E;IAC9E,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC1G,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE;IAClD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;IAChG,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACxC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YACpC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAClM,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAG,KAAK,EAAE;IAChF,IAAI,CAAC,KAAK,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IACjI,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,8CAA8C,IAAI,cAAc,EAAE;YACjG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO;YACtE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YACjF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC;SAClE,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;IAC1G,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE;IAC3F,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC9H,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,sCAAsC,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,IAAI,CAAC;IACT,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;gBACpC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;gBACtE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBACjF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;aAC3D,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;YACnG,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,GAAG,KAAK,CAAC;QAAC,CAAC;IACnC,CAAC;IACD,MAAM,IAAI,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function synchronizeEnvironmentFiles(root: any, { apply, localSecrets, manifest }?: {
|
|
2
|
+
apply?: boolean | undefined;
|
|
3
|
+
localSecrets?: boolean | undefined;
|
|
4
|
+
manifest?: any;
|
|
5
|
+
}): {
|
|
6
|
+
changed: string[];
|
|
7
|
+
applied: boolean;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=environment-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment-files.d.ts","sourceRoot":"","sources":["../../src/ops/environment-files.js"],"names":[],"mappings":"AAqBA;;;;;;;EAkFC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { assertManifest, identity, readEnv, readManifest, saltKeys } from "./config.js";
|
|
5
|
+
const derived = new Set(["APP_ENV", "PROJECT_NAME", "PROJECT_SLUG", "ASTRO_OUTPUT_MODE", "SITE_URL", "SITE_ALIASES_JSON", "BACKEND_URL", "BACKEND_GRAPHQL_URL", "WP_ENV", "WP_HOME", "WP_SITEURL", "FLOWPRESS_RUNTIME_POLICY", "FLOWPRESS_MEDIA_STORAGE", "FLOWPRESS_MEDIA", "FLOWPRESS_MAIL_MODE", "SF_STATIC_TARGETS_JSON", "SF_DIST_DIR", "FLOWPRESS_FRONTENDS_JSON", "FLOWPRESS_FRONTEND_VIEW_ID", "FLOWPRESS_FRONTEND_REDIRECT_ID"]);
|
|
6
|
+
const legacy = /^(CLOUDFLARE_|CF_|BACKEND_DEPLOY_|DEPLOY_BRANCH_MAP_JSON$)/;
|
|
7
|
+
const credential = /(?:PASSWORD|SECRET|TOKEN|AUTH_KEY|NONCE_KEY|LOGGED_IN_KEY|SALT|COMPOSER_AUTH|WP_USER|^ADVMO_.*_KEY$)/;
|
|
8
|
+
function envValue(value) {
|
|
9
|
+
const text = String(value);
|
|
10
|
+
if (!text || /^[a-zA-Z0-9_./:@?&=,+%-]+$/.test(text))
|
|
11
|
+
return text;
|
|
12
|
+
// dotenv does not decode JSON's escaped double quotes. JSON settings must
|
|
13
|
+
// retain their literal quotes so Node and PHP read the same JSON value.
|
|
14
|
+
if (!text.includes("'") && !/[\r\n]/.test(text))
|
|
15
|
+
return "'" + text + "'";
|
|
16
|
+
if (!/["\\\r\n]/.test(text))
|
|
17
|
+
return '"' + text + '"';
|
|
18
|
+
return JSON.stringify(text);
|
|
19
|
+
}
|
|
20
|
+
const serialize = (values, original = {}) => Object.entries(values).filter(([, value]) => value !== undefined).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => original[key] || key + "=" + envValue(value)).join("\n") + "\n";
|
|
21
|
+
// The manifest owns endpoints; each file retains only its own custom settings
|
|
22
|
+
// and credentials. A remote environment never inherits the local file.
|
|
23
|
+
export function synchronizeEnvironmentFiles(root, { apply = false, localSecrets = false, manifest = readManifest(root) } = {}) {
|
|
24
|
+
assertManifest(manifest);
|
|
25
|
+
const project = identity(root).slug;
|
|
26
|
+
const localExample = readEnv(join(root, ".env.example"));
|
|
27
|
+
const ports = manifest.development?.ports || {};
|
|
28
|
+
const port = String(ports.web || localExample.LOCAL_ASTRO_PORT || "4321");
|
|
29
|
+
const changed = [], backupRoot = join(root, ".local/flowpress-environment-backup");
|
|
30
|
+
function backup(relative) {
|
|
31
|
+
const file = join(root, relative), backup = join(backupRoot, relative);
|
|
32
|
+
if (existsSync(file) && !existsSync(backup)) {
|
|
33
|
+
mkdirSync(dirname(backup), { recursive: true, mode: 0o700 });
|
|
34
|
+
copyFileSync(file, backup);
|
|
35
|
+
chmodSync(backup, 0o600);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function write(relative, content, mode) {
|
|
39
|
+
const file = join(root, relative);
|
|
40
|
+
if (existsSync(file) && readFileSync(file, "utf8") === content)
|
|
41
|
+
return;
|
|
42
|
+
changed.push(relative);
|
|
43
|
+
if (apply) {
|
|
44
|
+
backup(relative);
|
|
45
|
+
writeFileSync(file, content, { mode });
|
|
46
|
+
chmodSync(file, mode);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const [name, target] of Object.entries(manifest.environments)) {
|
|
50
|
+
const source = manifest.environments[target.backend || name];
|
|
51
|
+
const backend = target.backendUrl || source.backendUrl;
|
|
52
|
+
const frontend = target.frontendUrl || backend;
|
|
53
|
+
const publicFile = name === "local" ? ".env.example" : ".env." + name + ".example";
|
|
54
|
+
const privateFile = name === "local" ? ".env" : ".env." + name;
|
|
55
|
+
const frontends = Object.entries(manifest.environments).filter(([id, item]) => item.frontendUrl && (name === "local" || id !== "local")).map(([id, item]) => ({ id, url: item.frontendUrl, aliases: item.aliases || [], indexing: id === "production" ? "index" : "noindex" }));
|
|
56
|
+
const configured = {
|
|
57
|
+
APP_ENV: name, PROJECT_NAME: project, PROJECT_SLUG: project,
|
|
58
|
+
ASTRO_OUTPUT_MODE: name === "local" || name === "preview" || (target.profile || manifest.profile) === "headless-ssr" ? "server" : "static",
|
|
59
|
+
SITE_URL: frontend, SITE_ALIASES_JSON: JSON.stringify(target.aliases || []),
|
|
60
|
+
BACKEND_URL: backend, BACKEND_GRAPHQL_URL: source.graphqlUrl || (backend ? backend + "/index.php?graphql" : undefined),
|
|
61
|
+
WP_ENV: name === "local" ? "development" : name === "production" ? "production" : "staging",
|
|
62
|
+
WP_HOME: backend, WP_SITEURL: backend ? backend + "/wp" : undefined,
|
|
63
|
+
FLOWPRESS_RUNTIME_POLICY: "container", FLOWPRESS_MEDIA_STORAGE: manifest.media,
|
|
64
|
+
FLOWPRESS_MEDIA: source.mediaUrl || "", FLOWPRESS_MAIL_MODE: name === "production" ? target.mail || "disabled" : target.mail === "capture" ? "capture" : "disabled",
|
|
65
|
+
SF_STATIC_TARGETS_JSON: target.publish.includes("web-static") ? JSON.stringify([name]) : "[]",
|
|
66
|
+
SF_DIST_DIR: "apps/web/dist-" + name,
|
|
67
|
+
FLOWPRESS_FRONTENDS_JSON: JSON.stringify(frontends), FLOWPRESS_FRONTEND_VIEW_ID: name, FLOWPRESS_FRONTEND_REDIRECT_ID: name,
|
|
68
|
+
};
|
|
69
|
+
function normalize(values, publicExample) {
|
|
70
|
+
const kept = Object.fromEntries(Object.entries(values).filter(([key]) => !derived.has(key) && !legacy.test(key)
|
|
71
|
+
&& !(manifest.media === "local" && key.startsWith("ADVMO_CLOUDFLARE_R2_"))
|
|
72
|
+
&& !(name !== "local" && (key.startsWith("LOCAL_") || key === "DB_HOST"))));
|
|
73
|
+
// Examples describe configuration, never carry live credentials.
|
|
74
|
+
if (publicExample)
|
|
75
|
+
for (const key of Object.keys(kept))
|
|
76
|
+
if (credential.test(key))
|
|
77
|
+
kept[key] = "";
|
|
78
|
+
const result = { ...configured, ...kept };
|
|
79
|
+
result.FRONTEND_BACKEND_TARGET = target.backend || (name === "local" ? values.FRONTEND_BACKEND_TARGET || "local" : name);
|
|
80
|
+
result.FLOWPRESS_COMPOSITION_MODE = values.FLOWPRESS_COMPOSITION_MODE || "site-editor";
|
|
81
|
+
result.LOCAL_ASTRO_PORT = port;
|
|
82
|
+
if (!target.publish.includes("web-static"))
|
|
83
|
+
result.CMS_GITHUB_DISPATCH_TOKEN = "";
|
|
84
|
+
if (name === "local") {
|
|
85
|
+
result.LOCAL_BACKEND_HTTP_PORT = String(ports.cms || values.LOCAL_BACKEND_HTTP_PORT || "8080");
|
|
86
|
+
result.LOCAL_HTTPS_PORT = String(ports.https || new URL(frontend).port || "443");
|
|
87
|
+
result.LOCAL_DB_PORT = String(ports.database || values.LOCAL_DB_PORT || "3306");
|
|
88
|
+
result.DB_HOST = "db:3306";
|
|
89
|
+
if (localSecrets && !publicExample) {
|
|
90
|
+
result.DB_NAME ||= project.replace(/[^a-z0-9]/g, "_");
|
|
91
|
+
result.DB_USER ||= "flowpress";
|
|
92
|
+
result.DB_PREFIX ||= "fp_";
|
|
93
|
+
for (const key of [...saltKeys, "DB_PASSWORD", "DB_ROOT_PASSWORD", "CMS_BUILD_CALLBACK_TOKEN"]) {
|
|
94
|
+
if (!result[key] || /^(GENERATE_|CHANGE_ME)/.test(result[key]))
|
|
95
|
+
result[key] = randomBytes(32).toString("hex");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
const example = normalize(readEnv(join(root, publicFile)), true);
|
|
102
|
+
write(publicFile, "# URL e identità sincronizzati da flowpress.deploy.yaml: pnpm ops env sync --apply\n" + serialize(example), 0o644);
|
|
103
|
+
const current = readEnv(join(root, privateFile));
|
|
104
|
+
// No values or secret files from other environments are copied here.
|
|
105
|
+
const settings = normalize({ ...example, ...current }, false);
|
|
106
|
+
const original = {};
|
|
107
|
+
if (existsSync(join(root, privateFile)))
|
|
108
|
+
for (const line of readFileSync(join(root, privateFile), "utf8").split("\n")) {
|
|
109
|
+
const key = line.match(/^([A-Z][A-Z0-9_]*)=/)?.[1];
|
|
110
|
+
if (key && !derived.has(key) && current[key] === settings[key] && !/[\r\n]/.test(current[key]))
|
|
111
|
+
original[key] = line;
|
|
112
|
+
}
|
|
113
|
+
write(privateFile, "# Impostazioni e segreti privati di " + name + ". Non versionare.\n" + serialize(settings, original), 0o600);
|
|
114
|
+
}
|
|
115
|
+
for (const relative of [".env.dev.example", ".env.dev"])
|
|
116
|
+
if (existsSync(join(root, relative))) {
|
|
117
|
+
changed.push(relative);
|
|
118
|
+
if (apply) {
|
|
119
|
+
backup(relative);
|
|
120
|
+
unlinkSync(join(root, relative));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { changed, applied: apply };
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=environment-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment-files.js","sourceRoot":"","sources":["../../src/ops/environment-files.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,UAAU,EAAE,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,aAAa,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,gCAAgC,CAAC,CAAC,CAAC;AAC1a,MAAM,MAAM,GAAG,4DAA4D,CAAC;AAC5E,MAAM,UAAU,GAAG,sGAAsG,CAAC;AAC1H,SAAS,QAAQ,CAAC,KAAK;IACrB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,0EAA0E;IAC1E,wEAAwE;IACxE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;IACzE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AACD,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE5O,8EAA8E;AAC9E,uEAAuE;AACvE,MAAM,UAAU,2BAA2B,CAAC,IAAI,EAAE,EAAE,KAAK,GAAG,KAAK,EAAE,YAAY,GAAG,KAAK,EAAE,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE;IAC3H,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,YAAY,CAAC,gBAAgB,IAAI,MAAM,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,EAAE,EAAE,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,qCAAqC,CAAC,CAAC;IACnF,SAAS,MAAM,CAAC,QAAQ;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACvE,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7D,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IACD,SAAS,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAClC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,OAAO;YAAE,OAAO;QACvE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,IAAI,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;IACjG,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnE,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC;QACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,IAAI,OAAO,CAAC;QAC/C,MAAM,UAAU,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;QACnF,MAAM,WAAW,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;QAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAChR,MAAM,UAAU,GAAG;YACjB,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO;YAC3D,iBAAiB,EAAE,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;YAC1I,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;YAC3E,WAAW,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC;YACtH,MAAM,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;YAC3F,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS;YACnE,wBAAwB,EAAE,WAAW,EAAE,uBAAuB,EAAE,QAAQ,CAAC,KAAK;YAC9E,eAAe,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,mBAAmB,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU;YACnK,sBAAsB,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;YAC7F,WAAW,EAAE,gBAAgB,GAAG,IAAI;YACpC,wBAAwB,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,0BAA0B,EAAE,IAAI,EAAE,8BAA8B,EAAE,IAAI;SAC5H,CAAC;QACF,SAAS,SAAS,CAAC,MAAM,EAAE,aAAa;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;mBAC1G,CAAC,CAAC,QAAQ,CAAC,KAAK,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;mBACvE,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,iEAAiE;YACjE,IAAI,aAAa;gBAAE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;wBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACjG,MAAM,MAAM,GAAG,EAAE,GAAG,UAAU,EAAE,GAAG,IAAI,EAAE,CAAC;YAC1C,MAAM,CAAC,uBAAuB,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,uBAAuB,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACzH,MAAM,CAAC,0BAA0B,GAAG,MAAM,CAAC,0BAA0B,IAAI,aAAa,CAAC;YACvF,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,yBAAyB,GAAG,EAAE,CAAC;YAClF,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,MAAM,CAAC,uBAAuB,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,uBAAuB,IAAI,MAAM,CAAC,CAAC;gBAC/F,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;gBACjF,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,CAAC;gBAChF,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;gBAC3B,IAAI,YAAY,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnC,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;oBAAC,MAAM,CAAC,OAAO,KAAK,WAAW,CAAC;oBAAC,MAAM,CAAC,SAAS,KAAK,KAAK,CAAC;oBAClH,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,QAAQ,EAAE,aAAa,EAAE,kBAAkB,EAAE,0BAA0B,CAAC,EAAE,CAAC;wBAC/F,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;4BAAE,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;oBAChH,CAAC;gBACH,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACjE,KAAK,CAAC,UAAU,EAAE,sFAAsF,GAAG,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;QACtI,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QACjD,qEAAqE;QACrE,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAAE,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACnD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;oBAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACvH,CAAC;QACD,KAAK,CAAC,WAAW,EAAE,sCAAsC,GAAG,IAAI,GAAG,qBAAqB,GAAG,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IACnI,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC;QAAE,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YAC9F,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,IAAI,KAAK,EAAE,CAAC;gBAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YAAC,CAAC;QACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function required(env: any, key: any): string;
|
|
2
|
+
export function requiredUrl(env: any, key: any): string;
|
|
3
|
+
export function json(env: any, key: any, fallback: any): any;
|
|
4
|
+
export function port(env: any, key: any): number;
|
|
5
|
+
export function shellEnvironment(env: any): {
|
|
6
|
+
[k: string]: any;
|
|
7
|
+
};
|
|
8
|
+
export function siteOrigins(env: any): string[];
|
|
9
|
+
export function siteHostnames(env: any): string[];
|
|
10
|
+
export function resolveMediaUrl(env: any): string;
|
|
11
|
+
export function localizeFrontendUrl(value: any, env: any): any;
|
|
12
|
+
export function manifestEnvironment(root: any, name: any, inherited?: {}): import("dotenv-expand").DotenvParseOutput | undefined;
|
|
13
|
+
export function loadEnvironment(name?: string, root?: string, inherited?: NodeJS.ProcessEnv): import("dotenv-expand").DotenvParseOutput | undefined;
|
|
14
|
+
export function resolveFrontendEnvironment(env: any, loadTargetEnvironment?: (target: any) => import("dotenv-expand").DotenvParseOutput | undefined): any;
|
|
15
|
+
export function loadFrontendEnvironment(): any;
|
|
16
|
+
export function cmsEnvironment(root: any, name: any): {
|
|
17
|
+
DB_HOST: string;
|
|
18
|
+
DISABLE_WP_CRON: string;
|
|
19
|
+
FORCE_SSL_ADMIN: string;
|
|
20
|
+
DISALLOW_FILE_MODS: string;
|
|
21
|
+
};
|
|
22
|
+
export const repoRoot: string;
|
|
23
|
+
export namespace frontendBackendTargets {
|
|
24
|
+
let local: string[];
|
|
25
|
+
let staging: string[];
|
|
26
|
+
let preview: string[];
|
|
27
|
+
let production: string[];
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/ops/environment.js"],"names":[],"mappings":"AAMA,qDAIC;AACD,wDAMC;AACD,6DAIC;AACD,iDAIC;AACD;;EAA0I;AAC1I,gDAOC;AACD,kDAAqG;AACrG,kDAIC;AACD,+DAKC;AACD,iIAyCC;AACD,oJAGC;AACD,8EAAwE,WAAM,iEAe7E;AACD,+CAAmG;AACnG;;;;;EAWC;AAvHD,8BAAoG"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { expand } from "dotenv-expand";
|
|
3
|
+
import { projectRoot, readEnv, readManifest, targetConfig, loadState, saltKeys } from "./config.js";
|
|
4
|
+
export const repoRoot = (() => { try {
|
|
5
|
+
return projectRoot();
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return process.cwd();
|
|
9
|
+
} })();
|
|
10
|
+
export const frontendBackendTargets = { local: ["local", "staging", "production"], staging: ["staging", "production"], preview: ["production", "staging"], production: ["production"] };
|
|
11
|
+
export function required(env, key) {
|
|
12
|
+
const value = String(env[key] ?? "").trim();
|
|
13
|
+
if (!value)
|
|
14
|
+
throw new Error("Missing required environment variable " + key + ".");
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
export function requiredUrl(env, key) {
|
|
18
|
+
const value = required(env, key);
|
|
19
|
+
let url;
|
|
20
|
+
try {
|
|
21
|
+
url = new URL(value);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new Error(key + " must be an absolute HTTP(S) URL.");
|
|
25
|
+
}
|
|
26
|
+
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.hash)
|
|
27
|
+
throw new Error("Invalid " + key + ".");
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
export function json(env, key, fallback) {
|
|
31
|
+
const value = String(env[key] ?? "").trim();
|
|
32
|
+
if (!value)
|
|
33
|
+
return fallback;
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(value);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
throw new Error(key + " must contain valid JSON.");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function port(env, key) {
|
|
42
|
+
const value = Number(required(env, key));
|
|
43
|
+
if (!Number.isInteger(value) || value < 1 || value > 65535)
|
|
44
|
+
throw new Error("Invalid TCP port: " + key);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
export function shellEnvironment(env) { return Object.fromEntries(Object.entries(env).filter(([, value]) => typeof value === "string")); }
|
|
48
|
+
export function siteOrigins(env) {
|
|
49
|
+
const values = [requiredUrl(env, "SITE_URL"), ...json(env, "SITE_ALIASES_JSON", [])];
|
|
50
|
+
return [...new Set(values.map(value => {
|
|
51
|
+
const url = new URL(value);
|
|
52
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.pathname !== "/" || url.search || url.hash)
|
|
53
|
+
throw new Error("Site URLs must be origins.");
|
|
54
|
+
return url.origin;
|
|
55
|
+
}))];
|
|
56
|
+
}
|
|
57
|
+
export function siteHostnames(env) { return siteOrigins(env).map(value => new URL(value).hostname); }
|
|
58
|
+
export function resolveMediaUrl(env) {
|
|
59
|
+
const value = requiredUrl(env, String(env.FLOWPRESS_MEDIA ?? "").trim() ? "FLOWPRESS_MEDIA" : "BACKEND_URL");
|
|
60
|
+
if (new URL(value).search)
|
|
61
|
+
throw new Error("Media URL cannot contain a query.");
|
|
62
|
+
return value.replace(/\/+$/, "");
|
|
63
|
+
}
|
|
64
|
+
export function localizeFrontendUrl(value, env) {
|
|
65
|
+
let url;
|
|
66
|
+
try {
|
|
67
|
+
url = new URL(value);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
return json(env, "FRONTEND_BACKEND_TARGET_ORIGINS_JSON", []).includes(url.origin)
|
|
73
|
+
? new URL(url.pathname + url.search + url.hash, requiredUrl(env, "SITE_URL")).href : value;
|
|
74
|
+
}
|
|
75
|
+
export function manifestEnvironment(root, name, inherited = {}) {
|
|
76
|
+
const manifest = readManifest(root);
|
|
77
|
+
const target = targetConfig(manifest, name);
|
|
78
|
+
const source = manifest.environments[target.backend || name] || target;
|
|
79
|
+
const existing = {
|
|
80
|
+
...readEnv(join(root, name === "local" ? ".env.example" : ".env." + name + ".example")),
|
|
81
|
+
...readEnv(join(root, name === "local" ? ".env" : ".env." + name)),
|
|
82
|
+
...readEnv(join(root, ".secrets", name + ".env")),
|
|
83
|
+
};
|
|
84
|
+
const profile = target.profile || manifest.profile;
|
|
85
|
+
const backend = target.backendUrl || source.backendUrl;
|
|
86
|
+
const frontend = target.frontendUrl || existing.SITE_URL || backend;
|
|
87
|
+
const values = {
|
|
88
|
+
...existing,
|
|
89
|
+
...inherited,
|
|
90
|
+
APP_ENV: name,
|
|
91
|
+
ASTRO_OUTPUT_MODE: inherited.ASTRO_OUTPUT_MODE || (name === "local" || name === "preview" || profile === "headless-ssr" ? "server" : "static"),
|
|
92
|
+
SITE_URL: inherited.SITE_URL || frontend,
|
|
93
|
+
BACKEND_URL: inherited.BACKEND_URL || backend,
|
|
94
|
+
BACKEND_GRAPHQL_URL: inherited.BACKEND_GRAPHQL_URL || source.graphqlUrl || backend + "/index.php?graphql",
|
|
95
|
+
WP_HOME: backend,
|
|
96
|
+
WP_SITEURL: backend + "/wp",
|
|
97
|
+
WP_ENV: name === "local" ? "development" : name === "production" ? "production" : "staging",
|
|
98
|
+
FLOWPRESS_RUNTIME_POLICY: "container",
|
|
99
|
+
FLOWPRESS_MEDIA_STORAGE: manifest.media,
|
|
100
|
+
FLOWPRESS_MEDIA: source.mediaUrl || "",
|
|
101
|
+
SF_STATIC_TARGETS_JSON: target.publish.includes("web-static") ? JSON.stringify([name]) : "[]",
|
|
102
|
+
CMS_GITHUB_DISPATCH_TOKEN: target.publish.includes("web-static") ? (existing.CMS_GITHUB_DISPATCH_TOKEN || "") : "",
|
|
103
|
+
FLOWPRESS_MAIL_MODE: name === "production" ? (target.mail || "disabled") : (target.mail === "capture" ? "capture" : "disabled"),
|
|
104
|
+
FRONTEND_BACKEND_TARGET: inherited.FRONTEND_BACKEND_TARGET || target.backend || (name === "local" ? existing.FRONTEND_BACKEND_TARGET : undefined) || name,
|
|
105
|
+
SF_DIST_DIR: inherited.SF_DIST_DIR || "apps/web/dist-" + name,
|
|
106
|
+
};
|
|
107
|
+
if (!values.PROJECT_NAME)
|
|
108
|
+
values.PROJECT_NAME = manifest.project || readEnv(join(root, ".env.example")).PROJECT_NAME;
|
|
109
|
+
if (!values.PROJECT_SLUG)
|
|
110
|
+
values.PROJECT_SLUG = values.PROJECT_NAME;
|
|
111
|
+
const frontends = Object.entries(manifest.environments).filter(([id, item]) => item.frontendUrl && (name === "local" || id !== "local")).map(([id, item]) => ({ id, url: item.frontendUrl, aliases: item.aliases || [], indexing: id === "production" ? "index" : "noindex" }));
|
|
112
|
+
values.FLOWPRESS_FRONTENDS_JSON = inherited.FLOWPRESS_FRONTENDS_JSON || JSON.stringify(frontends);
|
|
113
|
+
values.FLOWPRESS_FRONTEND_VIEW_ID = inherited.FLOWPRESS_FRONTEND_VIEW_ID || name;
|
|
114
|
+
values.FLOWPRESS_FRONTEND_REDIRECT_ID = inherited.FLOWPRESS_FRONTEND_REDIRECT_ID || name;
|
|
115
|
+
values.SITE_ALIASES_JSON = inherited.SITE_ALIASES_JSON || JSON.stringify(target.aliases || []);
|
|
116
|
+
// Expansion is limited to this environment. The local file never supplies remote secrets.
|
|
117
|
+
return expand({ parsed: shellEnvironment(values), processEnv: {} }).parsed;
|
|
118
|
+
}
|
|
119
|
+
export function loadEnvironment(name = "", root = repoRoot, inherited = process.env) {
|
|
120
|
+
const selected = name || inherited.APP_ENV || readEnv(join(root, ".env")).APP_ENV || "local";
|
|
121
|
+
return manifestEnvironment(root, selected, inherited);
|
|
122
|
+
}
|
|
123
|
+
export function resolveFrontendEnvironment(env, loadTargetEnvironment = target => manifestEnvironment(repoRoot, target)) {
|
|
124
|
+
const name = required(env, "APP_ENV");
|
|
125
|
+
const allowed = frontendBackendTargets[name];
|
|
126
|
+
const target = String(env.FRONTEND_BACKEND_TARGET || name);
|
|
127
|
+
if (!allowed?.includes(target))
|
|
128
|
+
throw new Error("Invalid frontend backend target for " + name + ": " + target);
|
|
129
|
+
if (target === name)
|
|
130
|
+
return { ...env, FLOWPRESS_MEDIA: resolveMediaUrl(env), FRONTEND_BACKEND_TARGET_ORIGINS_JSON: "[]" };
|
|
131
|
+
const source = loadTargetEnvironment(target);
|
|
132
|
+
if (source.APP_ENV !== target)
|
|
133
|
+
throw new Error("Backend environment identity mismatch.");
|
|
134
|
+
return {
|
|
135
|
+
...env,
|
|
136
|
+
BACKEND_URL: requiredUrl(source, "BACKEND_URL"),
|
|
137
|
+
BACKEND_GRAPHQL_URL: requiredUrl(source, "BACKEND_GRAPHQL_URL"),
|
|
138
|
+
FLOWPRESS_MEDIA: resolveMediaUrl(source),
|
|
139
|
+
FRONTEND_BACKEND_TARGET_ORIGINS_JSON: JSON.stringify(siteOrigins(source)),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function loadFrontendEnvironment() { return resolveFrontendEnvironment(loadEnvironment()); }
|
|
143
|
+
export function cmsEnvironment(root, name) {
|
|
144
|
+
const values = manifestEnvironment(root, name);
|
|
145
|
+
const state = loadState(root, name);
|
|
146
|
+
if (!state.platform?.poolUuid)
|
|
147
|
+
throw new Error("Provision the shared database binding first.");
|
|
148
|
+
const keys = ["APP_ENV", "PROJECT_NAME", "PROJECT_SLUG", "SITE_URL", "SITE_ALIASES_JSON", "BACKEND_URL", "BACKEND_GRAPHQL_URL", "WP_HOME", "WP_SITEURL", "WP_ENV", "DB_NAME", "DB_USER", "DB_PASSWORD", "DB_PREFIX", ...saltKeys,
|
|
149
|
+
"FLOWPRESS_RUNTIME_POLICY", "FLOWPRESS_MEDIA_STORAGE", "FLOWPRESS_MAIL_MODE", "FLOWPRESS_MEDIA", "FLOWPRESS_COMPOSITION_MODE", "FLOWPRESS_FRONTENDS_JSON", "FLOWPRESS_FRONTEND_VIEW_ID", "FLOWPRESS_FRONTEND_REDIRECT_ID", "SF_STATIC_TARGETS_JSON", "CMS_BUILD_CALLBACK_TOKEN", "CMS_GITHUB_DISPATCH_TOKEN", "GITHUB_REPOSITORY_SLUG",
|
|
150
|
+
"FLOWPRESS_RESERVED_AREA_ENABLED", "FLOWPRESS_TRACKING_ENABLED", "FLOWPRESS_GTM_CONTAINER_ID", "FLOWPRESS_IUBENDA_SITE_ID", "FLOWPRESS_IUBENDA_COOKIE_POLICY_ID", "FLOWPRESS_IUBENDA_PRIVACY_POLICY_ID", "GOOGLE_MAPS_API_KEY", "STAGING_MAIL_TO"];
|
|
151
|
+
if (values.FLOWPRESS_MAIL_MODE === "smtp")
|
|
152
|
+
keys.push("SMTP_HOST", "SMTP_PORT", "SMTP_ENCRYPTION", "SMTP_USER", "SMTP_PASSWORD", "SMTP_FROM", "SMTP_FROM_NAME");
|
|
153
|
+
if (values.FLOWPRESS_MEDIA_STORAGE === "s3")
|
|
154
|
+
keys.push("ADVMO_CLOUDFLARE_R2_KEY", "ADVMO_CLOUDFLARE_R2_SECRET", "ADVMO_CLOUDFLARE_R2_ENDPOINT", "ADVMO_CLOUDFLARE_R2_BUCKET", "ADVMO_CLOUDFLARE_R2_DOMAIN");
|
|
155
|
+
for (const key of ["DB_NAME", "DB_USER", "DB_PASSWORD", "DB_PREFIX", ...saltKeys])
|
|
156
|
+
required(values, key);
|
|
157
|
+
return { ...Object.fromEntries(keys.filter(key => values[key] !== undefined).map(key => [key, String(values[key])])), DB_HOST: state.platform.poolUuid + ":3306", DISABLE_WP_CRON: "true", FORCE_SSL_ADMIN: "true", DISALLOW_FILE_MODS: "true" };
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=environment.js.map
|