devflare 1.0.0-next.22 → 1.0.0-next.23
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/LLM.md +144 -5
- package/dist/account-j8nfggg4.js +475 -0
- package/dist/account-qhe8vtds.js +475 -0
- package/dist/bridge/miniflare.d.ts +1 -1
- package/dist/bridge/miniflare.d.ts.map +1 -1
- package/dist/browser.d.ts +13 -13
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +4 -2
- package/dist/build-vy95gy3f.js +54 -0
- package/dist/build-yzx0gsaj.js +54 -0
- package/dist/cli/commands/build-artifacts.d.ts.map +1 -1
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/type-generation/generator.d.ts +4 -2
- package/dist/cli/commands/type-generation/generator.d.ts.map +1 -1
- package/dist/cli/commands/types.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/config/compiler/types.d.ts +1 -1
- package/dist/config/compiler/types.d.ts.map +1 -1
- package/dist/config/define.d.ts +7 -4
- package/dist/config/define.d.ts.map +1 -1
- package/dist/config/env-vars.d.ts +309 -0
- package/dist/config/env-vars.d.ts.map +1 -0
- package/dist/config/index.d.ts +2 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/local-dev-vars.d.ts +2 -2
- package/dist/config/local-dev-vars.d.ts.map +1 -1
- package/dist/config/schema-env.d.ts +6 -6
- package/dist/config/schema-types-bindings-platform.d.ts +378 -0
- package/dist/config/schema-types-bindings-platform.d.ts.map +1 -0
- package/dist/config/schema-types-bindings-resources.d.ts +551 -0
- package/dist/config/schema-types-bindings-resources.d.ts.map +1 -0
- package/dist/config/schema-types-bindings.d.ts +254 -0
- package/dist/config/schema-types-bindings.d.ts.map +1 -0
- package/dist/config/schema-types-build.d.ts +86 -0
- package/dist/config/schema-types-build.d.ts.map +1 -0
- package/dist/config/schema-types-runtime.d.ts +882 -0
- package/dist/config/schema-types-runtime.d.ts.map +1 -0
- package/dist/config/schema-types.d.ts +377 -0
- package/dist/config/schema-types.d.ts.map +1 -0
- package/dist/config/schema.d.ts +14 -15
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config-entry.d.ts +2 -0
- package/dist/config-entry.d.ts.map +1 -1
- package/dist/config-entry.js +3 -1
- package/dist/config-gq5jh4cx.js +105 -0
- package/dist/config-vec13050.js +105 -0
- package/dist/deploy-01j0ep5n.js +1055 -0
- package/dist/deploy-tjypkhg7.js +1055 -0
- package/dist/dev-bh581ew3.js +2597 -0
- package/dist/dev-gn5y93z9.js +2597 -0
- package/dist/dev-server/server.d.ts.map +1 -1
- package/dist/doctor-h5q28qt1.js +259 -0
- package/dist/doctor-khk550tw.js +259 -0
- package/dist/env.d.ts +10 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/index-0bv2qjs1.js +1555 -0
- package/dist/index-3tkzn06q.js +413 -0
- package/dist/index-8fyz6gcm.js +699 -0
- package/dist/index-97z629zr.js +109 -0
- package/dist/index-b28c4yr4.js +1205 -0
- package/dist/index-c8p4njqy.js +479 -0
- package/dist/index-cr06zrgw.js +1033 -0
- package/dist/index-cwjjdtgn.js +74 -0
- package/dist/index-dref9ecb.js +476 -0
- package/dist/index-e151t4ge.js +895 -0
- package/dist/index-e7kakw0j.js +1033 -0
- package/dist/index-f1g5jdm8.js +1426 -0
- package/dist/index-f46984zs.js +1554 -0
- package/dist/index-grk8pzhr.js +185 -0
- package/dist/index-hzmpecq9.js +52 -0
- package/dist/index-j1csb7gb.js +581 -0
- package/dist/index-j7x7f72h.js +185 -0
- package/dist/index-jkqbjwt2.js +476 -0
- package/dist/index-mh5renra.js +895 -0
- package/dist/index-p9xq83p7.js +147 -0
- package/dist/index-q15nj71j.js +52 -0
- package/dist/index-qqp65pyv.js +699 -0
- package/dist/index-s0fmwxbk.js +74 -0
- package/dist/index-stzx8nc4.js +111 -0
- package/dist/index-th4vrnbk.js +1205 -0
- package/dist/index-vtcmsgaf.js +581 -0
- package/dist/index-x2k3awjs.js +147 -0
- package/dist/index-x8x547tz.js +1426 -0
- package/dist/index-xxxd0mvw.js +109 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/login-280p2cm9.js +77 -0
- package/dist/login-4n266whq.js +77 -0
- package/dist/previews-3m3ffpaw.js +1337 -0
- package/dist/previews-tr8sm03d.js +1337 -0
- package/dist/productions-62y489ff.js +505 -0
- package/dist/productions-cgn3fz7d.js +505 -0
- package/dist/runtime/exports.d.ts +23 -0
- package/dist/runtime/exports.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +5 -3
- package/dist/secrets-4050kqf5.js +91 -0
- package/dist/secrets-p112cajt.js +91 -0
- package/dist/sveltekit/index.js +4 -4
- package/dist/test/index.js +23 -11
- package/dist/test/resolve-service-bindings.d.ts +1 -1
- package/dist/test/resolve-service-bindings.d.ts.map +1 -1
- package/dist/test/simple-context-lifecycle.d.ts.map +1 -1
- package/dist/types-apmt10yj.js +705 -0
- package/dist/types-ttrrgdfj.js +705 -0
- package/dist/vite/index.js +5 -5
- package/dist/vite/plugin-context.d.ts.map +1 -1
- package/dist/vite/plugin-programmatic.d.ts.map +1 -1
- package/dist/worker-2k1jyr6p.js +513 -0
- package/dist/worker-jqgn6jyj.js +513 -0
- package/package.json +1 -1
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureGeneratedDirectory,
|
|
3
|
+
getGeneratedArtifactPaths
|
|
4
|
+
} from "./index-aabgympv.js";
|
|
5
|
+
import {
|
|
6
|
+
getDependencies
|
|
7
|
+
} from "./index-z9gy8w6b.js";
|
|
8
|
+
import {
|
|
9
|
+
detectViteProject
|
|
10
|
+
} from "./index-gn5wy09x.js";
|
|
11
|
+
import {
|
|
12
|
+
getPackageVersion
|
|
13
|
+
} from "./index-627srx16.js";
|
|
14
|
+
import {
|
|
15
|
+
logLine
|
|
16
|
+
} from "./index-stgn34cr.js";
|
|
17
|
+
import {
|
|
18
|
+
bundleWorkerEntry
|
|
19
|
+
} from "./index-e151t4ge.js";
|
|
20
|
+
import {
|
|
21
|
+
prepareComposedWorkerEntrypoint,
|
|
22
|
+
resolveEffectiveViteProject,
|
|
23
|
+
writeGeneratedViteConfig
|
|
24
|
+
} from "./index-b28c4yr4.js";
|
|
25
|
+
import {
|
|
26
|
+
resolvePackageSpecifier
|
|
27
|
+
} from "./index-3edvz3hs.js";
|
|
28
|
+
import {
|
|
29
|
+
compileBuildConfig,
|
|
30
|
+
isolateViteBuildOutputPaths,
|
|
31
|
+
rebaseWranglerConfigPaths,
|
|
32
|
+
writeWranglerConfig
|
|
33
|
+
} from "./index-8fyz6gcm.js";
|
|
34
|
+
import {
|
|
35
|
+
loadConfig,
|
|
36
|
+
resolveConfigForEnvironment
|
|
37
|
+
} from "./index-0bv2qjs1.js";
|
|
38
|
+
import {
|
|
39
|
+
resolveConfigEnvVars
|
|
40
|
+
} from "./index-c8p4njqy.js";
|
|
41
|
+
import {
|
|
42
|
+
__require
|
|
43
|
+
} from "./index-37x76zdn.js";
|
|
44
|
+
|
|
45
|
+
// src/cli/deploy-strategy.ts
|
|
46
|
+
function normalizeBranchScope(value) {
|
|
47
|
+
const trimmed = value?.trim();
|
|
48
|
+
return trimmed ? trimmed : undefined;
|
|
49
|
+
}
|
|
50
|
+
function shouldIncludePreviewCrons(config) {
|
|
51
|
+
return config.previews?.includeCrons === true;
|
|
52
|
+
}
|
|
53
|
+
function omitQueueConsumers(config) {
|
|
54
|
+
if (!config.bindings?.queues?.consumers?.length) {
|
|
55
|
+
return config;
|
|
56
|
+
}
|
|
57
|
+
const nextBindings = {
|
|
58
|
+
...config.bindings
|
|
59
|
+
};
|
|
60
|
+
const nextQueues = {
|
|
61
|
+
...nextBindings.queues
|
|
62
|
+
};
|
|
63
|
+
delete nextQueues.consumers;
|
|
64
|
+
if (!nextQueues.producers || Object.keys(nextQueues.producers).length === 0) {
|
|
65
|
+
delete nextBindings.queues;
|
|
66
|
+
} else {
|
|
67
|
+
nextBindings.queues = nextQueues;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
...config,
|
|
71
|
+
bindings: nextBindings
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function omitCronTriggers(config) {
|
|
75
|
+
if (!config.triggers?.crons?.length) {
|
|
76
|
+
return config;
|
|
77
|
+
}
|
|
78
|
+
const nextTriggers = {
|
|
79
|
+
...config.triggers
|
|
80
|
+
};
|
|
81
|
+
delete nextTriggers.crons;
|
|
82
|
+
if (Object.keys(nextTriggers).length === 0) {
|
|
83
|
+
const { triggers: _triggers, ...rest } = config;
|
|
84
|
+
return rest;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
...config,
|
|
88
|
+
triggers: nextTriggers
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function applyDeploymentStrategy(config, options = {}) {
|
|
92
|
+
const branchScope = normalizeBranchScope(options.previewBranch) ?? normalizeBranchScope(options.branchName);
|
|
93
|
+
const isBranchScopedPreviewDeploy = !options.preview && options.environment === "preview" && Boolean(branchScope);
|
|
94
|
+
if (!isBranchScopedPreviewDeploy) {
|
|
95
|
+
return {
|
|
96
|
+
config,
|
|
97
|
+
strategy: "default",
|
|
98
|
+
omittedResources: []
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const omittedResources = [];
|
|
102
|
+
let nextConfig = config;
|
|
103
|
+
if (nextConfig.bindings?.queues?.consumers?.length) {
|
|
104
|
+
nextConfig = omitQueueConsumers(nextConfig);
|
|
105
|
+
omittedResources.push("queue-consumers");
|
|
106
|
+
}
|
|
107
|
+
if (!shouldIncludePreviewCrons(nextConfig) && nextConfig.triggers?.crons?.length) {
|
|
108
|
+
nextConfig = omitCronTriggers(nextConfig);
|
|
109
|
+
omittedResources.push("cron-triggers");
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
config: nextConfig,
|
|
113
|
+
strategy: "preview-scope",
|
|
114
|
+
branchScope,
|
|
115
|
+
omittedResources
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function describeDeploymentStrategy(result) {
|
|
119
|
+
if (result.strategy !== "preview-scope" || result.omittedResources.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const labels = result.omittedResources.map((resource) => {
|
|
123
|
+
return resource === "queue-consumers" ? "queue consumers" : "cron triggers";
|
|
124
|
+
});
|
|
125
|
+
const formattedLabels = labels.length === 2 ? `${labels[0]} and ${labels[1]}` : labels[0];
|
|
126
|
+
const scopeSuffix = result.branchScope ? ` (${result.branchScope})` : "";
|
|
127
|
+
return `Named preview-scope deploy detected${scopeSuffix}; omitting shared ${formattedLabels} from the deployed Wrangler config to avoid singleton Cloudflare resource conflicts.`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/cli/commands/build-artifacts.ts
|
|
131
|
+
import { dirname, relative, resolve as resolve2 } from "pathe";
|
|
132
|
+
|
|
133
|
+
// src/cli/build-manifest.ts
|
|
134
|
+
import { createHash } from "node:crypto";
|
|
135
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
136
|
+
import { resolve } from "pathe";
|
|
137
|
+
var BUILD_MANIFEST_VERSION = 1;
|
|
138
|
+
var BUILD_MANIFEST_FILENAME = "manifest.json";
|
|
139
|
+
function hashSourceConfig(config) {
|
|
140
|
+
const normalized = JSON.stringify(config, (key, value) => {
|
|
141
|
+
if (key === "accountId")
|
|
142
|
+
return;
|
|
143
|
+
if (value === null || value === undefined)
|
|
144
|
+
return;
|
|
145
|
+
if (key === "__ref" && value && typeof value === "object") {
|
|
146
|
+
const nameOverride = value.__nameOverride;
|
|
147
|
+
return nameOverride ? `ref:${nameOverride}` : "ref:<unresolved>";
|
|
148
|
+
}
|
|
149
|
+
return value;
|
|
150
|
+
});
|
|
151
|
+
return createHash("sha256").update(normalized).digest("hex");
|
|
152
|
+
}
|
|
153
|
+
function summarizeBindings(config) {
|
|
154
|
+
const bindings = config.bindings ?? {};
|
|
155
|
+
return {
|
|
156
|
+
kv: Object.keys(bindings.kv ?? {}).sort(),
|
|
157
|
+
d1: Object.keys(bindings.d1 ?? {}).sort(),
|
|
158
|
+
r2: Object.keys(bindings.r2 ?? {}).sort(),
|
|
159
|
+
queues: Object.keys(bindings.queues ?? {}).sort(),
|
|
160
|
+
rateLimits: Object.keys(bindings.rateLimits ?? {}).sort(),
|
|
161
|
+
versionMetadata: bindings.versionMetadata ? [bindings.versionMetadata.binding] : [],
|
|
162
|
+
workerLoaders: Object.keys(bindings.workerLoaders ?? {}).sort(),
|
|
163
|
+
mtlsCertificates: Object.keys(bindings.mtlsCertificates ?? {}).sort(),
|
|
164
|
+
dispatchNamespaces: Object.keys(bindings.dispatchNamespaces ?? {}).sort(),
|
|
165
|
+
workflows: Object.keys(bindings.workflows ?? {}).sort(),
|
|
166
|
+
pipelines: Object.keys(bindings.pipelines ?? {}).sort(),
|
|
167
|
+
images: Object.keys(bindings.images ?? {}).sort(),
|
|
168
|
+
media: Object.keys(bindings.media ?? {}).sort(),
|
|
169
|
+
artifacts: Object.keys(bindings.artifacts ?? {}).sort(),
|
|
170
|
+
secretsStore: Object.keys(bindings.secretsStore ?? {}).sort(),
|
|
171
|
+
tailConsumers: (config.tailConsumers ?? []).map((consumer) => typeof consumer === "string" ? consumer : consumer.service).sort(),
|
|
172
|
+
hyperdrive: Object.keys(bindings.hyperdrive ?? {}).sort(),
|
|
173
|
+
vectorize: Object.keys(bindings.vectorize ?? {}).sort(),
|
|
174
|
+
services: Object.keys(bindings.services ?? {}).sort()
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function createBuildManifest(config, options) {
|
|
178
|
+
return {
|
|
179
|
+
manifestVersion: BUILD_MANIFEST_VERSION,
|
|
180
|
+
devflareVersion: options.devflareVersion,
|
|
181
|
+
createdAt: new Date().toISOString(),
|
|
182
|
+
sourceConfigHash: hashSourceConfig(config),
|
|
183
|
+
intendedTarget: options.intendedTarget,
|
|
184
|
+
bindingsSnapshot: summarizeBindings(config)
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
async function writeBuildManifest(buildDir, manifest) {
|
|
188
|
+
const manifestPath = resolve(buildDir, BUILD_MANIFEST_FILENAME);
|
|
189
|
+
await writeFile(manifestPath, `${JSON.stringify(manifest, null, "\t")}
|
|
190
|
+
`, "utf-8");
|
|
191
|
+
return manifestPath;
|
|
192
|
+
}
|
|
193
|
+
async function readBuildManifest(buildDir) {
|
|
194
|
+
const manifestPath = resolve(buildDir, BUILD_MANIFEST_FILENAME);
|
|
195
|
+
try {
|
|
196
|
+
const raw = await readFile(manifestPath, "utf-8");
|
|
197
|
+
const parsed = JSON.parse(raw);
|
|
198
|
+
if (typeof parsed?.manifestVersion !== "number")
|
|
199
|
+
return null;
|
|
200
|
+
return parsed;
|
|
201
|
+
} catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function targetsEqual(a, b) {
|
|
206
|
+
return a.environment === b.environment && a.preview === b.preview && a.previewScope === b.previewScope && a.branchName === b.branchName;
|
|
207
|
+
}
|
|
208
|
+
function compareManifests(previous, current) {
|
|
209
|
+
const prevBindings = new Set(Object.entries(previous.bindingsSnapshot).flatMap(([k, v]) => v.map((n) => `${k}:${n}`)));
|
|
210
|
+
const currBindings = new Set(Object.entries(current.bindingsSnapshot).flatMap(([k, v]) => v.map((n) => `${k}:${n}`)));
|
|
211
|
+
const bindingsAdded = [...currBindings].filter((b) => !prevBindings.has(b));
|
|
212
|
+
const bindingsRemoved = [...prevBindings].filter((b) => !currBindings.has(b));
|
|
213
|
+
return {
|
|
214
|
+
configChanged: previous.sourceConfigHash !== current.sourceConfigHash,
|
|
215
|
+
versionChanged: previous.devflareVersion !== current.devflareVersion,
|
|
216
|
+
targetChanged: !targetsEqual(previous.intendedTarget, current.intendedTarget),
|
|
217
|
+
previousVersion: previous.devflareVersion,
|
|
218
|
+
currentVersion: current.devflareVersion,
|
|
219
|
+
previousTarget: previous.intendedTarget,
|
|
220
|
+
currentTarget: current.intendedTarget,
|
|
221
|
+
bindingsAdded,
|
|
222
|
+
bindingsRemoved
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function formatDriftWarning(drift) {
|
|
226
|
+
const lines = [];
|
|
227
|
+
if (drift.versionChanged) {
|
|
228
|
+
lines.push(`devflare version differs (built with ${drift.previousVersion}, deploying with ${drift.currentVersion})`);
|
|
229
|
+
}
|
|
230
|
+
if (drift.targetChanged) {
|
|
231
|
+
lines.push(`deployment target differs (built for ${formatTarget(drift.previousTarget)}, ` + `deploying as ${formatTarget(drift.currentTarget)})`);
|
|
232
|
+
}
|
|
233
|
+
if (drift.configChanged) {
|
|
234
|
+
lines.push("source config changed since build (devflare.config.ts hash differs)");
|
|
235
|
+
}
|
|
236
|
+
if (drift.bindingsAdded.length > 0) {
|
|
237
|
+
lines.push(`bindings added since build: ${drift.bindingsAdded.join(", ")}`);
|
|
238
|
+
}
|
|
239
|
+
if (drift.bindingsRemoved.length > 0) {
|
|
240
|
+
lines.push(`bindings removed since build: ${drift.bindingsRemoved.join(", ")}`);
|
|
241
|
+
}
|
|
242
|
+
if (lines.length === 0)
|
|
243
|
+
return null;
|
|
244
|
+
return [
|
|
245
|
+
"Build artefact drift detected:",
|
|
246
|
+
...lines.map((line) => ` - ${line}`),
|
|
247
|
+
"Re-run `devflare build` to refresh the artefact, or pass --force to deploy anyway."
|
|
248
|
+
].join(`
|
|
249
|
+
`);
|
|
250
|
+
}
|
|
251
|
+
function formatTarget(t) {
|
|
252
|
+
const parts = [];
|
|
253
|
+
if (t.environment)
|
|
254
|
+
parts.push(`env=${t.environment}`);
|
|
255
|
+
parts.push(t.preview ? "preview" : "production");
|
|
256
|
+
if (t.previewScope)
|
|
257
|
+
parts.push(`scope=${t.previewScope}`);
|
|
258
|
+
if (t.branchName)
|
|
259
|
+
parts.push(`branch=${t.branchName}`);
|
|
260
|
+
return parts.join(" ");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// src/cli/commands/build-artifacts.ts
|
|
264
|
+
function getBuildArtifactPaths(cwd) {
|
|
265
|
+
return getGeneratedArtifactPaths(cwd);
|
|
266
|
+
}
|
|
267
|
+
function isNestedPath(parentPath, candidatePath) {
|
|
268
|
+
const normalizedParentPath = parentPath.replace(/\\/g, "/");
|
|
269
|
+
const normalizedCandidatePath = candidatePath.replace(/\\/g, "/");
|
|
270
|
+
return normalizedCandidatePath.startsWith(`${normalizedParentPath}/`);
|
|
271
|
+
}
|
|
272
|
+
function isolateViteBuildOutputPaths2(cwd, wranglerConfig) {
|
|
273
|
+
return isolateViteBuildOutputPaths(cwd, wranglerConfig);
|
|
274
|
+
}
|
|
275
|
+
function getViteBuildCleanupTargets(cwd, wranglerConfig) {
|
|
276
|
+
const targets = [];
|
|
277
|
+
const assetsDirectory = wranglerConfig.assets?.directory;
|
|
278
|
+
const mainEntry = wranglerConfig.main;
|
|
279
|
+
if (assetsDirectory) {
|
|
280
|
+
targets.push(resolve2(cwd, assetsDirectory));
|
|
281
|
+
}
|
|
282
|
+
if (mainEntry) {
|
|
283
|
+
const mainEntryPath = resolve2(cwd, mainEntry);
|
|
284
|
+
const isCoveredByAssetsDirectory = targets.some((targetPath) => {
|
|
285
|
+
return mainEntryPath === targetPath || isNestedPath(targetPath, mainEntryPath);
|
|
286
|
+
});
|
|
287
|
+
if (!isCoveredByAssetsDirectory) {
|
|
288
|
+
targets.push(mainEntryPath);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return targets;
|
|
292
|
+
}
|
|
293
|
+
function shouldRetryCleanup(error) {
|
|
294
|
+
if (!error || typeof error !== "object") {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
const errorCode = error.code;
|
|
298
|
+
return errorCode === "EBUSY" || errorCode === "EPERM" || errorCode === "ENOTEMPTY";
|
|
299
|
+
}
|
|
300
|
+
async function getCleanupFileSystem() {
|
|
301
|
+
return await import("node:fs/promises");
|
|
302
|
+
}
|
|
303
|
+
async function pathExists(cleanupFs, targetPath) {
|
|
304
|
+
try {
|
|
305
|
+
await cleanupFs.access(targetPath);
|
|
306
|
+
return true;
|
|
307
|
+
} catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function createDeferredCleanupPath(targetPath, uniqueSuffix) {
|
|
312
|
+
const suffix = uniqueSuffix ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
313
|
+
return `${targetPath}.devflare-stale-${suffix}`;
|
|
314
|
+
}
|
|
315
|
+
async function tryMoveLockedPathAside(targetPath, logger, cleanupFs) {
|
|
316
|
+
if (!await pathExists(cleanupFs, targetPath)) {
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
const deferredCleanupPath = createDeferredCleanupPath(targetPath);
|
|
320
|
+
try {
|
|
321
|
+
await cleanupFs.rename(targetPath, deferredCleanupPath);
|
|
322
|
+
} catch {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
logger.warn(`Moved locked build output aside to ${deferredCleanupPath} after repeated cleanup failures; continuing build`);
|
|
326
|
+
try {
|
|
327
|
+
await cleanupFs.rm(deferredCleanupPath, {
|
|
328
|
+
recursive: true,
|
|
329
|
+
force: true
|
|
330
|
+
});
|
|
331
|
+
} catch (error) {
|
|
332
|
+
const cleanupErrorCode = error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : "an unknown error";
|
|
333
|
+
logger.warn(`Deferred cleanup for ${deferredCleanupPath} is still blocked by ${cleanupErrorCode}; you can remove it manually later`);
|
|
334
|
+
}
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
async function removePathWithRetries(targetPath, logger, attempts = 5, cleanupFs) {
|
|
338
|
+
const fs = cleanupFs ?? await getCleanupFileSystem();
|
|
339
|
+
let lastError;
|
|
340
|
+
for (let attempt = 1;attempt <= attempts; attempt++) {
|
|
341
|
+
try {
|
|
342
|
+
await fs.rm(targetPath, {
|
|
343
|
+
recursive: true,
|
|
344
|
+
force: true
|
|
345
|
+
});
|
|
346
|
+
return;
|
|
347
|
+
} catch (error) {
|
|
348
|
+
lastError = error;
|
|
349
|
+
if (!shouldRetryCleanup(error) || attempt === attempts) {
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
logger.warn(`Retrying cleanup for ${targetPath} after ${error.code} (${attempt}/${attempts})`);
|
|
353
|
+
await new Promise((resolveRetry) => setTimeout(resolveRetry, attempt * 100));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (shouldRetryCleanup(lastError) && await tryMoveLockedPathAside(targetPath, logger, fs)) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (shouldRetryCleanup(lastError)) {
|
|
360
|
+
const cleanupErrorCode = lastError instanceof Error && "code" in lastError && typeof lastError.code === "string" ? lastError.code : "an unknown error";
|
|
361
|
+
logger.warn(`Continuing build without pre-clean for ${targetPath} because cleanup is still blocked by ${cleanupErrorCode}`);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
throw lastError;
|
|
365
|
+
}
|
|
366
|
+
async function cleanupViteBuildOutputs(cwd, wranglerConfig, logger) {
|
|
367
|
+
const cleanupTargets = getViteBuildCleanupTargets(cwd, wranglerConfig);
|
|
368
|
+
for (const cleanupTarget of cleanupTargets) {
|
|
369
|
+
await removePathWithRetries(cleanupTarget, logger);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function writeDeployRedirect(cwd, generatedConfigPath) {
|
|
373
|
+
const fs = await import("node:fs/promises");
|
|
374
|
+
const paths = getBuildArtifactPaths(cwd);
|
|
375
|
+
await ensureGeneratedDirectory(paths.deployDir);
|
|
376
|
+
const configPath = relative(paths.deployDir, generatedConfigPath).replace(/\\/g, "/");
|
|
377
|
+
await fs.writeFile(paths.deployRedirectPath, `${JSON.stringify({ configPath }, null, "\t")}
|
|
378
|
+
`, "utf-8");
|
|
379
|
+
}
|
|
380
|
+
async function readDeployRedirect(cwd) {
|
|
381
|
+
const fs = await import("node:fs/promises");
|
|
382
|
+
const paths = getBuildArtifactPaths(cwd);
|
|
383
|
+
try {
|
|
384
|
+
const rawConfig = await fs.readFile(paths.deployRedirectPath, "utf-8");
|
|
385
|
+
const parsed = JSON.parse(rawConfig);
|
|
386
|
+
if (typeof parsed.configPath !== "string" || parsed.configPath.length === 0) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
return resolve2(dirname(paths.deployRedirectPath), parsed.configPath);
|
|
390
|
+
} catch {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async function writeGeneratedDeployWranglerConfig(cwd, wranglerConfig, options = {}) {
|
|
395
|
+
const paths = getBuildArtifactPaths(cwd);
|
|
396
|
+
await ensureGeneratedDirectory(paths.buildDir, true);
|
|
397
|
+
const buildConfig = rebaseWranglerConfigPaths(cwd, paths.buildDir, wranglerConfig);
|
|
398
|
+
if (options.main) {
|
|
399
|
+
buildConfig.main = options.main;
|
|
400
|
+
}
|
|
401
|
+
await writeWranglerConfig(paths.buildDir, buildConfig, "wrangler.jsonc");
|
|
402
|
+
return paths.buildWranglerConfigPath;
|
|
403
|
+
}
|
|
404
|
+
async function writeGeneratedDevWranglerConfig(cwd, wranglerConfig) {
|
|
405
|
+
const paths = getGeneratedArtifactPaths(cwd);
|
|
406
|
+
await ensureGeneratedDirectory(paths.devflareDir, true);
|
|
407
|
+
const devConfig = rebaseWranglerConfigPaths(cwd, paths.devflareDir, wranglerConfig);
|
|
408
|
+
await writeWranglerConfig(paths.devflareDir, devConfig, "wrangler.jsonc");
|
|
409
|
+
return paths.devWranglerConfigPath;
|
|
410
|
+
}
|
|
411
|
+
async function buildWorkerOnlyDeployArtifact(cwd, wranglerConfig, config, logger) {
|
|
412
|
+
if (!wranglerConfig.main) {
|
|
413
|
+
return await writeGeneratedDeployWranglerConfig(cwd, wranglerConfig);
|
|
414
|
+
}
|
|
415
|
+
const paths = getBuildArtifactPaths(cwd);
|
|
416
|
+
const bundledMainEntryPath = await bundleWorkerEntry({
|
|
417
|
+
cwd,
|
|
418
|
+
inputFile: resolve2(cwd, wranglerConfig.main),
|
|
419
|
+
outFile: paths.buildWorkerPath,
|
|
420
|
+
rolldownOptions: config.rolldown?.options,
|
|
421
|
+
sourcemap: config.rolldown?.sourcemap,
|
|
422
|
+
minify: config.rolldown?.minify,
|
|
423
|
+
logger
|
|
424
|
+
});
|
|
425
|
+
logLine(logger, `Generated deploy artifact: ${relative(cwd, bundledMainEntryPath).replace(/\\/g, "/")}`);
|
|
426
|
+
return await writeGeneratedDeployWranglerConfig(cwd, wranglerConfig, {
|
|
427
|
+
main: "./worker.js"
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
async function resolveLocalViteExecutable(cwd, fs) {
|
|
431
|
+
const workspaceLocal = await findWorkspaceLocalBinary(cwd, fs, ["vite", "bin", "vite.js"]);
|
|
432
|
+
if (workspaceLocal) {
|
|
433
|
+
return workspaceLocal;
|
|
434
|
+
}
|
|
435
|
+
const viteExecutablePath = resolvePackageSpecifier("vite/bin/vite.js", cwd);
|
|
436
|
+
try {
|
|
437
|
+
await fs.access(viteExecutablePath);
|
|
438
|
+
} catch {
|
|
439
|
+
throw new Error(`Could not resolve a local Vite CLI entrypoint from ${cwd}. Install vite in this package before running a Vite-backed Devflare build.`);
|
|
440
|
+
}
|
|
441
|
+
return viteExecutablePath;
|
|
442
|
+
}
|
|
443
|
+
async function findWorkspaceLocalBinary(startDir, fs, segments) {
|
|
444
|
+
let currentDir = resolve2(startDir);
|
|
445
|
+
for (let depth = 0;depth < 64; depth++) {
|
|
446
|
+
const candidate = resolve2(currentDir, "node_modules", ...segments);
|
|
447
|
+
try {
|
|
448
|
+
await fs.access(candidate);
|
|
449
|
+
return candidate;
|
|
450
|
+
} catch {}
|
|
451
|
+
const parent = dirname(currentDir);
|
|
452
|
+
if (parent === currentDir) {
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
currentDir = parent;
|
|
456
|
+
}
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
function isRunningUnderBun() {
|
|
460
|
+
return typeof globalThis.Bun !== "undefined" || typeof process.versions.bun === "string";
|
|
461
|
+
}
|
|
462
|
+
async function prepareBuildArtifacts(parsed, logger, options) {
|
|
463
|
+
const cwd = options.cwd || process.cwd();
|
|
464
|
+
const configPath = parsed.options.config;
|
|
465
|
+
const environment = parsed.options.env;
|
|
466
|
+
const rawConfig = await loadConfig({ cwd, configFile: configPath });
|
|
467
|
+
const config = await resolveConfigEnvVars(resolveConfigForEnvironment(rawConfig, environment), {
|
|
468
|
+
cwd,
|
|
469
|
+
configPath,
|
|
470
|
+
mode: "build"
|
|
471
|
+
});
|
|
472
|
+
logLine(logger, `Building: ${config.name}`);
|
|
473
|
+
const composedMainEntry = await prepareComposedWorkerEntrypoint(cwd, config, environment);
|
|
474
|
+
const deps = await getDependencies();
|
|
475
|
+
const viteProject = resolveEffectiveViteProject(await detectViteProject(cwd, deps.fs), config, environment);
|
|
476
|
+
const deploymentStrategy = applyDeploymentStrategy(config, {
|
|
477
|
+
environment,
|
|
478
|
+
preview: parsed.options.preview === true,
|
|
479
|
+
branchName: parsed.options["branch-name"],
|
|
480
|
+
previewBranch: process.env.DEVFLARE_PREVIEW_BRANCH
|
|
481
|
+
});
|
|
482
|
+
const deploymentStrategyMessage = describeDeploymentStrategy(deploymentStrategy);
|
|
483
|
+
if (deploymentStrategyMessage) {
|
|
484
|
+
logLine(logger, deploymentStrategyMessage);
|
|
485
|
+
}
|
|
486
|
+
const devWranglerConfig = viteProject.shouldStartVite ? isolateViteBuildOutputPaths2(cwd, compileBuildConfig(config)) : compileBuildConfig(config);
|
|
487
|
+
const deployWranglerConfig = viteProject.shouldStartVite ? isolateViteBuildOutputPaths2(cwd, compileBuildConfig(deploymentStrategy.config)) : compileBuildConfig(deploymentStrategy.config);
|
|
488
|
+
if (viteProject.shouldStartVite) {
|
|
489
|
+
if (composedMainEntry) {
|
|
490
|
+
deployWranglerConfig.main = relative(cwd, composedMainEntry);
|
|
491
|
+
logLine(logger, `Generated composed worker entry: ${deployWranglerConfig.main}`);
|
|
492
|
+
}
|
|
493
|
+
} else if (composedMainEntry) {
|
|
494
|
+
const bundledMainEntryPath = await bundleWorkerEntry({
|
|
495
|
+
cwd,
|
|
496
|
+
inputFile: composedMainEntry,
|
|
497
|
+
outFile: resolve2(cwd, ".devflare", "worker-entrypoints", "main.js"),
|
|
498
|
+
rolldownOptions: config.rolldown?.options,
|
|
499
|
+
sourcemap: config.rolldown?.sourcemap,
|
|
500
|
+
minify: config.rolldown?.minify,
|
|
501
|
+
logger
|
|
502
|
+
});
|
|
503
|
+
const bundledMainPath = relative(cwd, bundledMainEntryPath).replace(/\\/g, "/");
|
|
504
|
+
devWranglerConfig.main = bundledMainPath;
|
|
505
|
+
deployWranglerConfig.main = bundledMainPath;
|
|
506
|
+
logLine(logger, `Generated bundled worker entry: ${bundledMainPath}`);
|
|
507
|
+
}
|
|
508
|
+
let deployConfigPath;
|
|
509
|
+
if (viteProject.shouldStartVite) {
|
|
510
|
+
const generatedViteConfigPath = await writeGeneratedViteConfig({
|
|
511
|
+
cwd,
|
|
512
|
+
configPath,
|
|
513
|
+
environment,
|
|
514
|
+
localConfigPath: viteProject.viteConfigPath
|
|
515
|
+
});
|
|
516
|
+
const viteExecutablePath = await resolveLocalViteExecutable(cwd, deps.fs);
|
|
517
|
+
await cleanupViteBuildOutputs(cwd, devWranglerConfig, logger);
|
|
518
|
+
logLine(logger, "Running vite build...");
|
|
519
|
+
const useBunRuntime = isRunningUnderBun();
|
|
520
|
+
const buildCommand = useBunRuntime ? "bun" : viteExecutablePath;
|
|
521
|
+
const buildArgs = useBunRuntime ? ["--bun", viteExecutablePath, "build", "--config", generatedViteConfigPath] : ["build", "--config", generatedViteConfigPath];
|
|
522
|
+
const buildProc = await deps.exec.exec(buildCommand, buildArgs, {
|
|
523
|
+
cwd,
|
|
524
|
+
stdio: "inherit",
|
|
525
|
+
env: {
|
|
526
|
+
...process.env,
|
|
527
|
+
DEVFLARE_BUILD: "true"
|
|
528
|
+
},
|
|
529
|
+
reject: false
|
|
530
|
+
});
|
|
531
|
+
if (buildProc.exitCode !== 0) {
|
|
532
|
+
throw new Error(`Vite build failed (exit code ${buildProc.exitCode}).
|
|
533
|
+
|
|
534
|
+
Command: ${buildCommand} ${buildArgs.join(" ")}
|
|
535
|
+
Working directory: ${cwd}
|
|
536
|
+
Vite executable: ${viteExecutablePath}
|
|
537
|
+
Runtime: ${useBunRuntime ? "bun --bun" : "node (default execa runtime)"}
|
|
538
|
+
|
|
539
|
+
Vite's own output is printed above. If you only see "UNHANDLED PROMISE REJECTION"
|
|
540
|
+
with no other detail, common causes are:
|
|
541
|
+
- A Vite plugin or transitive dependency (e.g. rolldown) cannot be resolved
|
|
542
|
+
from the executable's physical path. This commonly happens when the package
|
|
543
|
+
manager resolves the Vite binary to a global cache directory outside the
|
|
544
|
+
workspace's node_modules tree. Try reinstalling, or run vite directly to
|
|
545
|
+
isolate: \`bunx --bun vite build --config ${relative(cwd, generatedViteConfigPath).replace(/\\/g, "/")}\`.
|
|
546
|
+
- A peer dependency or framework adapter is missing. Re-check the package's
|
|
547
|
+
devDependencies against the framework's documented requirements.
|
|
548
|
+
- The generated vite config references a path that does not yet exist.`);
|
|
549
|
+
}
|
|
550
|
+
const existingDeployConfigPath = await readDeployRedirect(cwd);
|
|
551
|
+
const generatedDeployConfigPath = deployWranglerConfig.main && deployWranglerConfig.main !== devWranglerConfig.main ? await buildWorkerOnlyDeployArtifact(cwd, deployWranglerConfig, config, logger) : await writeGeneratedDeployWranglerConfig(cwd, deployWranglerConfig);
|
|
552
|
+
deployConfigPath = existingDeployConfigPath && existingDeployConfigPath !== generatedDeployConfigPath ? existingDeployConfigPath : generatedDeployConfigPath;
|
|
553
|
+
} else {
|
|
554
|
+
logLine(logger, "Skipping Vite build (no effective Vite config found for this package)");
|
|
555
|
+
deployConfigPath = await buildWorkerOnlyDeployArtifact(cwd, deployWranglerConfig, config, logger);
|
|
556
|
+
}
|
|
557
|
+
const generatedDevConfigPath = await writeGeneratedDevWranglerConfig(cwd, devWranglerConfig);
|
|
558
|
+
logger.debug(`Generated dev Wrangler config: ${relative(cwd, generatedDevConfigPath).replace(/\\/g, "/")}`);
|
|
559
|
+
await writeDeployRedirect(cwd, deployConfigPath);
|
|
560
|
+
logLine(logger, `Generated deploy Wrangler config: ${relative(cwd, deployConfigPath).replace(/\\/g, "/")}`);
|
|
561
|
+
logLine(logger, `Generated deploy redirect: ${relative(cwd, getBuildArtifactPaths(cwd).deployRedirectPath).replace(/\\/g, "/")}`);
|
|
562
|
+
const manifest = createBuildManifest(config, {
|
|
563
|
+
devflareVersion: await getPackageVersion(),
|
|
564
|
+
intendedTarget: {
|
|
565
|
+
environment,
|
|
566
|
+
preview: parsed.options.preview === true,
|
|
567
|
+
previewScope: typeof parsed.options.preview === "string" ? parsed.options.preview : undefined,
|
|
568
|
+
branchName: parsed.options["branch-name"]
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
const manifestPath = await writeBuildManifest(getBuildArtifactPaths(cwd).buildDir, manifest);
|
|
572
|
+
logger.debug(`Generated build manifest: ${relative(cwd, manifestPath).replace(/\\/g, "/")}`);
|
|
573
|
+
return {
|
|
574
|
+
config,
|
|
575
|
+
wranglerConfig: deployWranglerConfig,
|
|
576
|
+
deployConfigPath,
|
|
577
|
+
viteProject
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export { applyDeploymentStrategy, describeDeploymentStrategy, createBuildManifest, readBuildManifest, compareManifests, formatDriftWarning, prepareBuildArtifacts };
|