@styleflow.app/flowpress-deploy 0.1.0-beta.0
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 +6 -0
- package/README.md +11 -0
- package/composer.json +11 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -0
- package/flowpress-deploy.php +25 -0
- package/package.json +37 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# FlowPress Deploy
|
|
2
|
+
|
|
3
|
+
Installable npm/Composer feature pack for safe Cloudflare Pages and Workers
|
|
4
|
+
build orchestration. CMS partial builds require a successful compatible
|
|
5
|
+
baseline; code and manual triggers remain full builds.
|
|
6
|
+
|
|
7
|
+
The public API validates paths and `_routes.json`, merges partial artifacts
|
|
8
|
+
without traversal or case collisions, regenerates sitemaps, selects Pages for
|
|
9
|
+
static targets and Workers for dev, requires `ASTRO_KEY` for protected batches,
|
|
10
|
+
and acknowledges the CMS queue only after deploy and smoke test. Failed
|
|
11
|
+
batches are released for retry.
|
package/composer.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flowpress/deploy",
|
|
3
|
+
"description": "WordPress capability registration for FlowPress deploy.",
|
|
4
|
+
"type": "wordpress-muplugin",
|
|
5
|
+
"license": "proprietary",
|
|
6
|
+
"require": {
|
|
7
|
+
"php": ">=8.1",
|
|
8
|
+
"flowpress/wordpress-core": "^0.2.10"
|
|
9
|
+
},
|
|
10
|
+
"extra": {"installer-name": "flowpress-deploy"}
|
|
11
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type FlowpressDeployTrigger = "push" | "manual" | "cms";
|
|
2
|
+
export type FlowpressDeployMode = "full" | "partial";
|
|
3
|
+
export type FlowpressCloudflareTarget = "pages" | "workers";
|
|
4
|
+
export interface FlowpressDeployBaseline {
|
|
5
|
+
environment: string;
|
|
6
|
+
fingerprint: string;
|
|
7
|
+
artifactId: string;
|
|
8
|
+
completedAt: string;
|
|
9
|
+
}
|
|
10
|
+
export interface FlowpressDeployRequest {
|
|
11
|
+
trigger: FlowpressDeployTrigger;
|
|
12
|
+
environment: string;
|
|
13
|
+
fingerprint: string;
|
|
14
|
+
paths?: string[];
|
|
15
|
+
deletedPaths?: string[];
|
|
16
|
+
forceFull?: boolean;
|
|
17
|
+
baseline?: FlowpressDeployBaseline | null;
|
|
18
|
+
}
|
|
19
|
+
export interface FlowpressDeployDecision {
|
|
20
|
+
mode: FlowpressDeployMode;
|
|
21
|
+
paths: string[];
|
|
22
|
+
deletedPaths: string[];
|
|
23
|
+
baseline?: FlowpressDeployBaseline;
|
|
24
|
+
}
|
|
25
|
+
export interface FlowpressBuildEntry {
|
|
26
|
+
path: string;
|
|
27
|
+
contentHash: string;
|
|
28
|
+
}
|
|
29
|
+
export interface FlowpressQueueBatch {
|
|
30
|
+
id: string;
|
|
31
|
+
requiresAstroKey?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface FlowpressQueueLifecycle<T> {
|
|
34
|
+
deploy: () => Promise<T>;
|
|
35
|
+
smokeTest: (result: T) => Promise<void>;
|
|
36
|
+
acknowledge: (batchId: string) => Promise<void>;
|
|
37
|
+
release: (batchId: string, reason: string) => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export declare function normalizeDeployPath(value: string): string;
|
|
40
|
+
export declare function resolveDeploy(request: FlowpressDeployRequest): FlowpressDeployDecision;
|
|
41
|
+
export declare function assertNoOutputCollisions(entries: string[]): void;
|
|
42
|
+
export declare function mergeBuildEntries(baseline: FlowpressBuildEntry[], partial: FlowpressBuildEntry[], deletedPaths?: string[]): FlowpressBuildEntry[];
|
|
43
|
+
export declare function buildSitemapXml(paths: string[], siteUrl: string): string;
|
|
44
|
+
export declare function assertAstroKey(requiresAstroKey: boolean, environment: Record<string, string | undefined>): void;
|
|
45
|
+
export declare function cloudflareTargetForEnvironment(environment: string): FlowpressCloudflareTarget;
|
|
46
|
+
export declare function deployQueueBatch<T>(batch: FlowpressQueueBatch, lifecycle: FlowpressQueueLifecycle<T>): Promise<T>;
|
|
47
|
+
export declare function validateCloudflareRoutes(input: unknown): void;
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC/D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,CAAC;AACrD,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,sBAAsB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBzD;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,sBAAsB,GAAG,uBAAuB,CAqBtF;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAQhE;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,OAAO,EAAE,mBAAmB,EAAE,EAC9B,YAAY,GAAE,MAAM,EAAO,GAC1B,mBAAmB,EAAE,CAqBvB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAexE;AAWD,wBAAgB,cAAc,CAC5B,gBAAgB,EAAE,OAAO,EACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC9C,IAAI,CAIN;AAED,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,GAClB,yBAAyB,CAE3B;AAED,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,uBAAuB,CAAC,CAAC,CAAC,GACpC,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAa7D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export function normalizeDeployPath(value) {
|
|
2
|
+
if (typeof value !== "string"
|
|
3
|
+
|| !value.startsWith("/")
|
|
4
|
+
|| value.includes("\\")
|
|
5
|
+
|| value.includes("\0")
|
|
6
|
+
|| /(^|\/)\.\.?($|\/)/.test(value)
|
|
7
|
+
|| /^\/\//.test(value)) {
|
|
8
|
+
throw new Error(`Unsafe FlowPress deploy path: ${value}`);
|
|
9
|
+
}
|
|
10
|
+
const url = new URL(value, "https://flowpress.invalid");
|
|
11
|
+
if (url.origin !== "https://flowpress.invalid" || url.search || url.hash) {
|
|
12
|
+
throw new Error(`Unsafe FlowPress deploy path: ${value}`);
|
|
13
|
+
}
|
|
14
|
+
return url.pathname.replace(/\/{2,}/g, "/");
|
|
15
|
+
}
|
|
16
|
+
function uniquePaths(values = []) {
|
|
17
|
+
return [...new Set(values.map(normalizeDeployPath))].sort();
|
|
18
|
+
}
|
|
19
|
+
export function resolveDeploy(request) {
|
|
20
|
+
if (request.trigger !== "cms" || request.forceFull) {
|
|
21
|
+
return { mode: "full", paths: [], deletedPaths: [] };
|
|
22
|
+
}
|
|
23
|
+
const baseline = request.baseline;
|
|
24
|
+
if (!baseline
|
|
25
|
+
|| baseline.environment !== request.environment
|
|
26
|
+
|| baseline.fingerprint !== request.fingerprint
|
|
27
|
+
|| !baseline.artifactId) {
|
|
28
|
+
throw new Error(`No compatible successful baseline for ${request.environment}/${request.fingerprint}.`);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
mode: "partial",
|
|
32
|
+
paths: uniquePaths(request.paths),
|
|
33
|
+
deletedPaths: uniquePaths(request.deletedPaths),
|
|
34
|
+
baseline
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function assertNoOutputCollisions(entries) {
|
|
38
|
+
const normalized = entries.map(normalizeDeployPath);
|
|
39
|
+
const seen = new Set();
|
|
40
|
+
for (const entry of normalized) {
|
|
41
|
+
const key = entry.toLocaleLowerCase("en-US");
|
|
42
|
+
if (seen.has(key))
|
|
43
|
+
throw new Error(`Build output collision: ${entry}`);
|
|
44
|
+
seen.add(key);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function mergeBuildEntries(baseline, partial, deletedPaths = []) {
|
|
48
|
+
assertNoOutputCollisions(baseline.map(({ path }) => path));
|
|
49
|
+
assertNoOutputCollisions(partial.map(({ path }) => path));
|
|
50
|
+
const deleted = new Set(uniquePaths(deletedPaths).map((path) => path.toLowerCase()));
|
|
51
|
+
const merged = new Map();
|
|
52
|
+
for (const entry of baseline) {
|
|
53
|
+
const path = normalizeDeployPath(entry.path);
|
|
54
|
+
if (!deleted.has(path.toLowerCase())) {
|
|
55
|
+
merged.set(path.toLowerCase(), { ...entry, path });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const entry of partial) {
|
|
59
|
+
const path = normalizeDeployPath(entry.path);
|
|
60
|
+
const key = path.toLowerCase();
|
|
61
|
+
const existing = merged.get(key);
|
|
62
|
+
if (existing && existing.path !== path) {
|
|
63
|
+
throw new Error(`Build output collision: ${existing.path} / ${path}`);
|
|
64
|
+
}
|
|
65
|
+
merged.set(key, { ...entry, path });
|
|
66
|
+
}
|
|
67
|
+
return [...merged.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
68
|
+
}
|
|
69
|
+
export function buildSitemapXml(paths, siteUrl) {
|
|
70
|
+
const origin = new URL(siteUrl);
|
|
71
|
+
if (!["http:", "https:"].includes(origin.protocol)) {
|
|
72
|
+
throw new Error("Sitemap site URL must use HTTP or HTTPS.");
|
|
73
|
+
}
|
|
74
|
+
const locations = uniquePaths(paths)
|
|
75
|
+
.filter((path) => !path.startsWith("/404"))
|
|
76
|
+
.map((path) => new URL(path, origin).toString());
|
|
77
|
+
return [
|
|
78
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
79
|
+
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
80
|
+
...locations.map((location) => ` <url><loc>${escapeXml(location)}</loc></url>`),
|
|
81
|
+
"</urlset>",
|
|
82
|
+
""
|
|
83
|
+
].join("\n");
|
|
84
|
+
}
|
|
85
|
+
function escapeXml(value) {
|
|
86
|
+
return value
|
|
87
|
+
.replaceAll("&", "&")
|
|
88
|
+
.replaceAll("<", "<")
|
|
89
|
+
.replaceAll(">", ">")
|
|
90
|
+
.replaceAll('"', """)
|
|
91
|
+
.replaceAll("'", "'");
|
|
92
|
+
}
|
|
93
|
+
export function assertAstroKey(requiresAstroKey, environment) {
|
|
94
|
+
if (requiresAstroKey && !environment.ASTRO_KEY?.trim()) {
|
|
95
|
+
throw new Error("ASTRO_KEY is required for this content batch.");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export function cloudflareTargetForEnvironment(environment) {
|
|
99
|
+
return environment === "dev" ? "workers" : "pages";
|
|
100
|
+
}
|
|
101
|
+
export async function deployQueueBatch(batch, lifecycle) {
|
|
102
|
+
try {
|
|
103
|
+
const result = await lifecycle.deploy();
|
|
104
|
+
await lifecycle.smokeTest(result);
|
|
105
|
+
await lifecycle.acknowledge(batch.id);
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
110
|
+
try {
|
|
111
|
+
await lifecycle.release(batch.id, reason);
|
|
112
|
+
}
|
|
113
|
+
catch (releaseError) {
|
|
114
|
+
throw new AggregateError([error, releaseError], `Deploy failed and queue batch ${batch.id} could not be released.`);
|
|
115
|
+
}
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function validateCloudflareRoutes(input) {
|
|
120
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
121
|
+
throw new Error("Cloudflare routes must be an object.");
|
|
122
|
+
}
|
|
123
|
+
const routes = input;
|
|
124
|
+
for (const [key, value] of Object.entries({
|
|
125
|
+
include: routes.include,
|
|
126
|
+
exclude: routes.exclude
|
|
127
|
+
})) {
|
|
128
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
129
|
+
throw new Error(`Cloudflare routes ${key} must be a string array.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* Plugin Name: FlowPress Deploy
|
|
4
|
+
* Description: Installable deployment capability for FlowPress.
|
|
5
|
+
* Version: 0.1.0-beta.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
if (! defined('ABSPATH')) {
|
|
9
|
+
exit;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
add_action('muplugins_loaded', static function (): void {
|
|
13
|
+
if (! function_exists('flowpress_register_feature')) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
flowpress_register_feature('deploy', [
|
|
17
|
+
'version' => '0.1.0-beta.0',
|
|
18
|
+
'capabilities' => ['full-build', 'partial-build', 'build-callback'],
|
|
19
|
+
'config' => [
|
|
20
|
+
'targets' => function_exists('flowpress_static_targets')
|
|
21
|
+
? flowpress_static_targets()
|
|
22
|
+
: [],
|
|
23
|
+
],
|
|
24
|
+
]);
|
|
25
|
+
}, 120);
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@styleflow.app/flowpress-deploy",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "Safe full and partial deployment primitives for FlowPress.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/StyleFlow-App/flowpress-deploy.git"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public",
|
|
13
|
+
"registry": "https://registry.npmjs.org/"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": ["dist", "flowpress-deploy.php", "composer.json", "README.md", "CHANGELOG.md"],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -b",
|
|
24
|
+
"typecheck": "tsc -b --pretty false",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"release:check": "npm run typecheck && npm test && npm pack --dry-run",
|
|
27
|
+
"release:publish:next": "npm publish --access public --tag next",
|
|
28
|
+
"prepublishOnly": "npm run typecheck && npm test"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.19.3",
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"vitest": "^3.2.4"
|
|
34
|
+
},
|
|
35
|
+
"engines": {"node": ">=22.0.0"},
|
|
36
|
+
"packageManager": "npm@10.9.3"
|
|
37
|
+
}
|