@styleflow.app/flowpress-deploy 1.0.0-beta.1 → 1.0.0-beta.11

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +6 -29
  3. package/containers/cms/Dockerfile +35 -0
  4. package/containers/cms/Dockerfile.dockerignore +20 -0
  5. package/containers/cms/healthz.php +17 -0
  6. package/containers/cms/install-languages.sh +16 -0
  7. package/containers/cms/mpm.conf +10 -0
  8. package/containers/cms/php.ini +16 -0
  9. package/containers/cms/sanitize.php +37 -0
  10. package/containers/cms/smtp.php +13 -0
  11. package/containers/cms/vhost.conf +61 -0
  12. package/containers/cms/wp-cli.yml +1 -0
  13. package/containers/php-runtime/Dockerfile +21 -0
  14. package/containers/web-ssr/Dockerfile +25 -0
  15. package/containers/web-ssr/Dockerfile.dockerignore +10 -0
  16. package/containers/web-static/Caddyfile +40 -0
  17. package/containers/web-static/Dockerfile +15 -0
  18. package/containers/web-static/Dockerfile.dockerignore +7 -0
  19. package/dist/frontend-assets.d.ts +2 -0
  20. package/dist/frontend-assets.d.ts.map +1 -0
  21. package/dist/frontend-assets.js +44 -0
  22. package/dist/frontend-assets.js.map +1 -0
  23. package/dist/frontend-links.d.ts +14 -0
  24. package/dist/frontend-links.d.ts.map +1 -0
  25. package/dist/frontend-links.js +82 -0
  26. package/dist/frontend-links.js.map +1 -0
  27. package/dist/ops/bootstrap.d.ts +21 -0
  28. package/dist/ops/bootstrap.d.ts.map +1 -0
  29. package/dist/ops/bootstrap.js +123 -0
  30. package/dist/ops/bootstrap.js.map +1 -0
  31. package/dist/ops/build.d.ts +39 -0
  32. package/dist/ops/build.d.ts.map +1 -0
  33. package/dist/ops/build.js +108 -0
  34. package/dist/ops/build.js.map +1 -0
  35. package/dist/ops/cli.d.ts +3 -0
  36. package/dist/ops/cli.d.ts.map +1 -0
  37. package/dist/ops/cli.js +140 -0
  38. package/dist/ops/cli.js.map +1 -0
  39. package/dist/ops/config.d.ts +54 -0
  40. package/dist/ops/config.d.ts.map +1 -0
  41. package/dist/ops/config.js +177 -0
  42. package/dist/ops/config.js.map +1 -0
  43. package/dist/ops/coolify.d.ts +2 -0
  44. package/dist/ops/coolify.d.ts.map +1 -0
  45. package/dist/ops/coolify.js +44 -0
  46. package/dist/ops/coolify.js.map +1 -0
  47. package/dist/ops/data.d.ts +27 -0
  48. package/dist/ops/data.d.ts.map +1 -0
  49. package/dist/ops/data.js +148 -0
  50. package/dist/ops/data.js.map +1 -0
  51. package/dist/ops/deploy.d.ts +18 -0
  52. package/dist/ops/deploy.d.ts.map +1 -0
  53. package/dist/ops/deploy.js +100 -0
  54. package/dist/ops/deploy.js.map +1 -0
  55. package/dist/ops/editorial.d.ts +23 -0
  56. package/dist/ops/editorial.d.ts.map +1 -0
  57. package/dist/ops/editorial.js +79 -0
  58. package/dist/ops/editorial.js.map +1 -0
  59. package/dist/ops/environment.d.ts +29 -0
  60. package/dist/ops/environment.d.ts.map +1 -0
  61. package/dist/ops/environment.js +159 -0
  62. package/dist/ops/environment.js.map +1 -0
  63. package/dist/ops/health.d.ts +25 -0
  64. package/dist/ops/health.d.ts.map +1 -0
  65. package/dist/ops/health.js +22 -0
  66. package/dist/ops/health.js.map +1 -0
  67. package/dist/ops/monitor.d.ts +23 -0
  68. package/dist/ops/monitor.d.ts.map +1 -0
  69. package/dist/ops/monitor.js +143 -0
  70. package/dist/ops/monitor.js.map +1 -0
  71. package/dist/ops/process.d.ts +9 -0
  72. package/dist/ops/process.d.ts.map +1 -0
  73. package/dist/ops/process.js +48 -0
  74. package/dist/ops/process.js.map +1 -0
  75. package/dist/ops/provision.d.ts +41 -0
  76. package/dist/ops/provision.d.ts.map +1 -0
  77. package/dist/ops/provision.js +262 -0
  78. package/dist/ops/provision.js.map +1 -0
  79. package/dist/ops/registry.d.ts +2 -0
  80. package/dist/ops/registry.d.ts.map +1 -0
  81. package/dist/ops/registry.js +36 -0
  82. package/dist/ops/registry.js.map +1 -0
  83. package/dist/ops/release.d.ts +26 -0
  84. package/dist/ops/release.d.ts.map +1 -0
  85. package/dist/ops/release.js +79 -0
  86. package/dist/ops/release.js.map +1 -0
  87. package/dist/ops/s3.d.ts +8 -0
  88. package/dist/ops/s3.d.ts.map +1 -0
  89. package/dist/ops/s3.js +38 -0
  90. package/dist/ops/s3.js.map +1 -0
  91. package/dist/ops/static-config.d.ts +14 -0
  92. package/dist/ops/static-config.d.ts.map +1 -0
  93. package/dist/ops/static-config.js +96 -0
  94. package/dist/ops/static-config.js.map +1 -0
  95. package/dist/worker-assets.d.ts +5 -0
  96. package/dist/worker-assets.d.ts.map +1 -0
  97. package/dist/worker-assets.js +35 -0
  98. package/dist/worker-assets.js.map +1 -0
  99. package/flowpress-deploy.php +3 -2
  100. package/includes/automatic-build.php +98 -0
  101. package/includes/queue-provider.php +2 -0
  102. package/package.json +50 -7
  103. package/schema/deployment.schema.json +45 -0
@@ -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":"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"}
@@ -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" : "production",
98
+ FLOWPRESS_RUNTIME_POLICY: "container",
99
+ FLOWPRESS_MEDIA_STORAGE: manifest.media,
100
+ FLOWPRESS_MEDIA: manifest.media === "local" ? "" : (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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/ops/environment.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export function backupHealth({ executions, objects, maxAgeHours, now }: {
2
+ executions?: never[] | undefined;
3
+ objects: any;
4
+ maxAgeHours: any;
5
+ now?: number | undefined;
6
+ }): {
7
+ ok: boolean;
8
+ lastAttempt: {
9
+ status: any;
10
+ created_at: any;
11
+ } | null;
12
+ lastSuccess: {
13
+ status: any;
14
+ created_at: any;
15
+ } | null;
16
+ latestObject: any;
17
+ ageHours: number | null;
18
+ maxAgeHours: any;
19
+ issues: string[];
20
+ };
21
+ export namespace backupMaxAgeHours {
22
+ let daily: number;
23
+ let weekly: number;
24
+ }
25
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/ops/health.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;EAeC"}
@@ -0,0 +1,22 @@
1
+ export const backupMaxAgeHours = { daily: 36, weekly: 8 * 24 };
2
+ export function backupHealth({ executions = [], objects, maxAgeHours, now = Date.now() }) {
3
+ const sorted = [...executions].sort((a, b) => Date.parse(b.created_at) - Date.parse(a.created_at));
4
+ const lastAttempt = sorted[0] ?? null;
5
+ const lastSuccess = sorted.find((item) => item.status === "success") ?? null;
6
+ const latestObject = objects === undefined ? null : [...objects].filter((item) => item.size > 0)
7
+ .sort((a, b) => Date.parse(b.modified) - Date.parse(a.modified))[0] ?? null;
8
+ const timestamp = latestObject?.modified || lastSuccess?.created_at;
9
+ const ageHours = timestamp ? (now - Date.parse(timestamp)) / 3_600_000 : null;
10
+ const issues = [];
11
+ if (!timestamp)
12
+ issues.push("no successful backup");
13
+ if (ageHours !== null && (!Number.isFinite(ageHours) || ageHours > maxAgeHours || ageHours < -1))
14
+ issues.push("backup stale or invalid timestamp");
15
+ if (lastAttempt && !["success", "running", "in_progress", "in-progress"].includes(lastAttempt.status))
16
+ issues.push("last backup attempt failed");
17
+ if (objects !== undefined && !latestObject)
18
+ issues.push("no nonempty offsite backup object");
19
+ const summary = (attempt) => attempt ? { status: attempt.status, created_at: attempt.created_at } : null;
20
+ return { ok: !issues.length, lastAttempt: summary(lastAttempt), lastSuccess: summary(lastSuccess), latestObject, ageHours, maxAgeHours, issues };
21
+ }
22
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/ops/health.js"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;AAE/D,MAAM,UAAU,YAAY,CAAC,EAAE,UAAU,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE;IACtF,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IACnG,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACtC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,IAAI,IAAI,CAAC;IAC7E,MAAM,YAAY,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;SAC7F,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC9E,MAAM,SAAS,GAAG,YAAY,EAAE,QAAQ,IAAI,WAAW,EAAE,UAAU,CAAC;IACpE,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,CAAC,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACpD,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,WAAW,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACnJ,IAAI,WAAW,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACjJ,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,YAAY;QAAE,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACzG,OAAO,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACnJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ export function backupRun(root: any, manifest: any, name: any): Promise<{
2
+ environment: any;
3
+ database: string;
4
+ uploads: string;
5
+ filename: any;
6
+ }>;
7
+ export function backupVerify(root: any, manifest: any, name: any): Promise<{
8
+ environment: any;
9
+ database: {
10
+ tables: number;
11
+ home: any;
12
+ };
13
+ uploads: {
14
+ files: number;
15
+ };
16
+ offsite: boolean;
17
+ }>;
18
+ export function status(root: any, manifest: any, only: any): Promise<{
19
+ ok: boolean;
20
+ checkedAt: string;
21
+ environments: {};
22
+ }>;
23
+ //# sourceMappingURL=monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../src/ops/monitor.js"],"names":[],"mappings":"AAWA;;;;;GAgBC;AAQD;;;;;;;;;;GAuCC;AACD;;;;GAgCC"}
@@ -0,0 +1,143 @@
1
+ import { mkdtempSync, rmSync, mkdirSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { allowedComponents, loadState, operatorEnvironment, readEnv } from "./config.js";
5
+ import { coolifyClient } from "./coolify.js";
6
+ import { backupHealth } from "./health.js";
7
+ import { s3Get, s3List } from "./s3.js";
8
+ import { safeArchiveEntries } from "./data.js";
9
+ import { capture, run, sleep } from "./process.js";
10
+ const list = data => Array.isArray(data) ? data : data?.executions || data?.data || [];
11
+ export async function backupRun(root, manifest, name) {
12
+ allowedComponents(manifest, name, ["cms"]);
13
+ const state = loadState(root, name);
14
+ const api = coolifyClient(state.platform.coolifyUrl, operatorEnvironment(root).COOLIFY_TOKEN);
15
+ const before = Date.now() - 2000;
16
+ await api("PATCH", "/databases/" + state.platform.poolUuid + "/backups/" + state.database.backupUuid, { backup_now: true });
17
+ const app = state.apps.cms;
18
+ await api("POST", "/applications/" + app.uuid + "/storages/" + app.uploadsStorageUuid + "/backups/run");
19
+ for (let attempt = 0; attempt < 90; attempt++) {
20
+ const executions = list(await api("GET", "/databases/" + state.platform.poolUuid + "/backups/" + state.database.backupUuid + "/executions"));
21
+ const last = executions.filter(item => Date.parse(item.created_at + (item.created_at.endsWith("Z") ? "" : "Z")) >= before).sort((a, b) => b.created_at.localeCompare(a.created_at))[0];
22
+ if (last?.status === "failed")
23
+ throw new Error("Offsite database backup failed.");
24
+ if (last?.status === "success")
25
+ return { environment: name, database: "success", uploads: "queued", filename: last.filename };
26
+ await sleep(4000);
27
+ }
28
+ throw new Error("Offsite database backup timed out.");
29
+ }
30
+ async function bucketConfig(root, state, api) {
31
+ const secret = readEnv(join(root, ".secrets/backup.env"));
32
+ if (secret.BACKUP_S3_ENDPOINT)
33
+ return { endpoint: secret.BACKUP_S3_ENDPOINT, bucket: secret.BACKUP_S3_BUCKET, region: secret.BACKUP_S3_REGION, user: secret.BACKUP_S3_ACCESS_KEY_ID + ":" + secret.BACKUP_S3_SECRET_ACCESS_KEY };
34
+ const storage = await api("GET", "/s3-storages/" + state.platform.backupStorageUuid);
35
+ if (!storage.key || !storage.secret)
36
+ throw new Error("Set private .secrets/backup.env to verify the offsite backup objects.");
37
+ return { endpoint: storage.endpoint, bucket: storage.bucket, region: storage.region, user: storage.key + ":" + storage.secret };
38
+ }
39
+ export async function backupVerify(root, manifest, name) {
40
+ allowedComponents(manifest, name, ["cms"]);
41
+ const state = loadState(root, name), values = readEnv(join(root, ".secrets", name + ".env"));
42
+ const api = coolifyClient(state.platform.coolifyUrl, operatorEnvironment(root).COOLIFY_TOKEN);
43
+ const bucket = await bucketConfig(root, state, api);
44
+ const objects = s3List(bucket, "data/coolify/backups/").filter(item => item.size > 0).sort((a, b) => b.modified.localeCompare(a.modified));
45
+ const database = objects.find(item => item.key.includes(state.platform.poolUuid) && item.key.includes(state.database.name));
46
+ const uploads = objects.find(item => item.key.includes(state.apps.cms.name + "-uploads"));
47
+ if (!database || !uploads)
48
+ throw new Error("Both nonempty offsite database and uploads backups are required.");
49
+ const directory = mkdtempSync(join(tmpdir(), "flowpress-restore-"));
50
+ const id = "flowpress-restore-" + process.pid;
51
+ try {
52
+ const file = join(directory, database.key.endsWith(".gz") ? "database.sql.gz" : "database.sql");
53
+ s3Get(bucket, database.key, file);
54
+ if (file.endsWith(".gz"))
55
+ run("gunzip", ["-k", file]);
56
+ run("docker", ["run", "--rm", "-d", "--network", "none", "--memory", "1536m", "--name", id, "-e", "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1", "-e", "MARIADB_DATABASE=restore", "mariadb:11.4"], { stdio: "ignore" });
57
+ for (let attempt = 0; attempt < 60; attempt++) {
58
+ const ready = run;
59
+ try {
60
+ capture("docker", ["exec", id, "healthcheck.sh", "--connect", "--innodb_initialized"]);
61
+ break;
62
+ }
63
+ catch {
64
+ if (attempt === 59)
65
+ throw new Error("Restore test database did not start.");
66
+ await sleep(2000);
67
+ }
68
+ }
69
+ const { readFileSync } = await import("node:fs");
70
+ run("docker", ["exec", "-i", id, "mariadb", "-uroot", "restore"], { input: readFileSync(file.replace(/\.gz$/, "")), stdio: ["pipe", "pipe", "pipe"] });
71
+ if (!/^[a-zA-Z0-9_]+$/.test(values.DB_PREFIX || ""))
72
+ throw new Error("Unsafe WordPress table prefix.");
73
+ const query = sql => capture("docker", ["exec", id, "mariadb", "-uroot", "-N", "restore", "-e", sql]);
74
+ const home = query("SELECT option_value FROM " + values.DB_PREFIX + "options WHERE option_name='home'");
75
+ const tables = Number(query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='restore'"));
76
+ if (tables < 10 || new URL(home).origin !== new URL(state.apps.cms.url).origin)
77
+ throw new Error("Restored database identity mismatch.");
78
+ const archive = join(directory, "uploads.tar.gz");
79
+ s3Get(bucket, uploads.key, archive);
80
+ const options = ["run", "--rm", "--network", "none", "--read-only", "--user", String(process.getuid?.() || 0) + ":" + String(process.getgid?.() || 0),
81
+ "--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--tmpfs", "/restore:rw,size=1g,mode=1777", "-v", archive + ":/backup.tar.gz:ro", "alpine:3.22"];
82
+ safeArchiveEntries(capture("docker", [...options, "tar", "-tzf", "/backup.tar.gz"]).split("\n").filter(Boolean));
83
+ const files = capture("docker", [...options, "sh", "-ec", 'tar -xzf /backup.tar.gz -C /restore; find /restore -type f | wc -l']);
84
+ if (Number(files) < 1)
85
+ throw new Error("Restored uploads are empty.");
86
+ return { environment: name, database: { tables, home }, uploads: { files: Number(files) }, offsite: true };
87
+ }
88
+ finally {
89
+ try {
90
+ run("docker", ["rm", "-f", id], { stdio: "ignore" });
91
+ }
92
+ catch { /* startup may have failed */ }
93
+ rmSync(directory, { recursive: true, force: true });
94
+ }
95
+ }
96
+ export async function status(root, manifest, only) {
97
+ const report = { ok: true, checkedAt: new Date().toISOString(), environments: {} };
98
+ for (const name of only ? [only] : Object.keys(manifest.environments)) {
99
+ const state = loadState(root, name);
100
+ if (!Object.keys(state.apps || {}).length) {
101
+ report.environments[name] = { active: false, ok: true };
102
+ continue;
103
+ }
104
+ const result = { active: true, ok: true, apps: {}, backups: {} };
105
+ const api = coolifyClient(state.platform.coolifyUrl, operatorEnvironment(root).COOLIFY_TOKEN);
106
+ for (const [component, app] of Object.entries(state.apps)) {
107
+ try {
108
+ const current = await api("GET", "/applications/" + app.uuid);
109
+ const response = await fetch(app.url + app.health + "?status=" + Date.now(), { signal: AbortSignal.timeout(10000), redirect: "error" });
110
+ const data = await response.json();
111
+ const configuredSha = current.docker_registry_image_tag?.match(/(?:^sha-|^[a-z]+-)([a-f0-9]{40})(?:-|$)/)?.[1];
112
+ const ok = current.status === "running:healthy" && response.ok && data.status === "ok" && Boolean(configuredSha) && data.release === configuredSha;
113
+ result.apps[component] = { ok, status: current.status, release: data.release };
114
+ if (!ok)
115
+ result.ok = false;
116
+ }
117
+ catch {
118
+ result.apps[component] = { ok: false, status: "unknown" };
119
+ result.ok = false;
120
+ }
121
+ }
122
+ if (state.database?.backupUuid) {
123
+ try {
124
+ const executions = list(await api("GET", "/databases/" + state.platform.poolUuid + "/backups/" + state.database.backupUuid + "/executions"));
125
+ const bucket = await bucketConfig(root, state, api);
126
+ const objects = s3List(bucket, "data/coolify/backups/");
127
+ result.backups.database = backupHealth({ executions, objects: objects.filter(item => item.key.includes(state.platform.poolUuid) && item.key.includes(state.database.name)), maxAgeHours: 36 });
128
+ result.backups.uploads = backupHealth({ objects: objects.filter(item => item.key.includes(state.apps.cms.name + "-uploads")), maxAgeHours: 36 });
129
+ if (!result.backups.database.ok || !result.backups.uploads.ok)
130
+ result.ok = false;
131
+ }
132
+ catch {
133
+ result.backups = { ok: false, status: "unknown" };
134
+ result.ok = false;
135
+ }
136
+ }
137
+ report.environments[name] = result;
138
+ if (!result.ok)
139
+ report.ok = false;
140
+ }
141
+ return report;
142
+ }
143
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/ops/monitor.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export function run(command: any, args: any, options?: {}): import("child_process").SpawnSyncReturns<NonSharedBuffer>;
2
+ export function capture(command: any, args: any, options?: {}): any;
3
+ export function shellQuote(value: any): string;
4
+ export function ssh(platform: any, command: any, options?: {}): any;
5
+ export function sshFile(platform: any, command: any, { input, output }?: {}): Promise<void>;
6
+ export function argValue(args: any, flag: any): any;
7
+ export function containerFor(platform: any, uuid: any): any;
8
+ export function sleep(ms: any): Promise<any>;
9
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/ops/process.js"],"names":[],"mappings":"AAIA,sHAKC;AACD,oEAEC;AACD,+CAAgG;AAChG,oEAGC;AACD,4FAQC;AAED,oDAKC;AACD,4DAKC;AAZM,6CAAmE"}
@@ -0,0 +1,48 @@
1
+ import { spawnSync, spawn } from "node:child_process";
2
+ import { createReadStream, createWriteStream } from "node:fs";
3
+ import { pipeline } from "node:stream/promises";
4
+ export function run(command, args, options = {}) {
5
+ const result = spawnSync(command, args, { stdio: "inherit", ...options });
6
+ if (result.error)
7
+ throw new Error("Cannot start " + command + ": " + result.error.code);
8
+ if (result.status !== 0)
9
+ throw new Error(command + " failed (exit " + result.status + ").");
10
+ return result;
11
+ }
12
+ export function capture(command, args, options = {}) {
13
+ return run(command, args, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], maxBuffer: 64 * 1024 * 1024, ...options }).stdout.trim();
14
+ }
15
+ export function shellQuote(value) { return "'" + String(value).replaceAll("'", "'\\''") + "'"; }
16
+ export function ssh(platform, command, options = {}) {
17
+ if (!/^[a-zA-Z0-9_.@-]+$/.test(platform.ssh || ""))
18
+ throw new Error("Invalid SSH target.");
19
+ return capture("ssh", ["-o", "BatchMode=yes", "-o", "ConnectTimeout=15", platform.ssh, command], options);
20
+ }
21
+ export async function sshFile(platform, command, { input, output } = {}) {
22
+ if (!/^[a-zA-Z0-9_.@-]+$/.test(platform.ssh || ""))
23
+ throw new Error("Invalid SSH target.");
24
+ const child = spawn("ssh", ["-o", "BatchMode=yes", "-o", "ConnectTimeout=15", platform.ssh, command], { stdio: [input ? "pipe" : "ignore", output ? "pipe" : "inherit", "inherit"] });
25
+ const completion = new Promise((resolve, reject) => {
26
+ child.on("error", reject);
27
+ child.on("exit", code => code === 0 ? resolve() : reject(new Error("SSH stream failed (exit " + code + ").")));
28
+ });
29
+ await Promise.all([completion, ...(input ? [pipeline(createReadStream(input), child.stdin)] : []), ...(output ? [pipeline(child.stdout, createWriteStream(output, { mode: 0o600 }))] : [])]);
30
+ }
31
+ export const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
32
+ export function argValue(args, flag) {
33
+ const index = args.indexOf(flag);
34
+ if (index < 0)
35
+ return undefined;
36
+ if (!args[index + 1] || args[index + 1].startsWith("--"))
37
+ throw new Error("Missing value for " + flag);
38
+ return args[index + 1];
39
+ }
40
+ export function containerFor(platform, uuid) {
41
+ if (!/^[a-z0-9]+$/.test(uuid || ""))
42
+ throw new Error("Invalid resource UUID.");
43
+ const names = ssh(platform, "docker ps --filter name=^" + uuid + " --format '{{.Names}}'").split("\n").filter(Boolean);
44
+ if (names.length !== 1)
45
+ throw new Error("Expected exactly one running container for " + uuid + ".");
46
+ return names[0];
47
+ }
48
+ //# sourceMappingURL=process.js.map