@jundle/cloudflare 0.0.0-stage → 0.0.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/package.json +22 -3
- package/src/bindings.js +295 -0
- package/src/build.d.ts +145 -0
- package/src/build.js +327 -0
- package/src/config.js +82 -0
- package/src/harness.js +707 -0
- package/src/index.d.ts +389 -0
- package/src/index.js +446 -0
- package/README.md +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jundle/cloudflare",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Cloudflare Workers runtime for the jundle dev server (workerd via Miniflare).",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "src/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./build": {
|
|
14
|
+
"types": "./src/build.d.ts",
|
|
15
|
+
"default": "./src/build.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"miniflare": "4.20260730.0",
|
|
20
|
+
"unplugin": "3.7.0"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"wrangler": "4.156.0"
|
|
24
|
+
}
|
|
6
25
|
}
|
package/src/bindings.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// Wrangler config -> Miniflare options (SPEC §16.3).
|
|
2
|
+
// Every binding is wired; nothing is silently stubbed or
|
|
3
|
+
// downgraded. Local by default; remote only where the spec
|
|
4
|
+
// says so (AI / Browser Rendering / Vectorize are always
|
|
5
|
+
// remote, and per-binding remote is a dev-server CLI flag,
|
|
6
|
+
// handled by the caller via remoteBindings, not config).
|
|
7
|
+
// Persistence mirrors wrangler dev: .wrangler/state/v3 under
|
|
8
|
+
// the project root (KV, R2, D1, Durable Objects, Workflows
|
|
9
|
+
// each get their own subdir there where Miniflare supports a
|
|
10
|
+
// separate persist path).
|
|
11
|
+
// D1 migrations: Miniflare itself has no migrations option —
|
|
12
|
+
// wrangler dev applies them. The mapping keeps migrations_dir
|
|
13
|
+
// on the database entry so the runner (CF-2) can apply the SQL
|
|
14
|
+
// files after Miniflare starts; it is not dropped.
|
|
15
|
+
// Remote credentials come from CLOUDFLARE_ACCOUNT_ID /
|
|
16
|
+
// CLOUDFLARE_API_TOKEN. Without them, a remote-only binding
|
|
17
|
+
// is a clear error naming what's missing (not a silent local
|
|
18
|
+
// fallback).
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
|
|
21
|
+
function persistDir(configDir, sub) {
|
|
22
|
+
return path.join(configDir, ".wrangler", "state", "v3", sub);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function wranglerToMiniflareOptions({
|
|
26
|
+
config,
|
|
27
|
+
devVars,
|
|
28
|
+
configDir,
|
|
29
|
+
wranglerFile,
|
|
30
|
+
remoteBindings,
|
|
31
|
+
}) {
|
|
32
|
+
const options = {
|
|
33
|
+
modules: true,
|
|
34
|
+
// The main Worker's name (from wrangler config): dispatch
|
|
35
|
+
// routes to it, not to the first worker in `workers`.
|
|
36
|
+
...(config.name ? { name: config.name } : {}),
|
|
37
|
+
compatibilityDate: config.compatibility_date,
|
|
38
|
+
compatibilityFlags: config.compatibility_flags,
|
|
39
|
+
// Workerd runs with TZ=UTC (workerd does not read the
|
|
40
|
+
// system timezone; Date is always UTC there).
|
|
41
|
+
bindings: { ...config.vars, ...devVars },
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Remote bindings (CF-3): AI / Browser Rendering / Vectorize
|
|
45
|
+
// are ALWAYS remote (no local emulation), and any binding
|
|
46
|
+
// named in the entry options' remoteBindings list is remote
|
|
47
|
+
// for this session.
|
|
48
|
+
// Remote requires Cloudflare credentials AND a deployed
|
|
49
|
+
// remote proxy Worker URL (Miniflare's
|
|
50
|
+
// remoteProxyConnectionString is a URL to a proxy Worker —
|
|
51
|
+
// it is what `wrangler dev --remote` deploys). Without
|
|
52
|
+
// either, that is a clear error naming what is missing —
|
|
53
|
+
// never a silent local fallback (SPEC §16.3). Native proxy
|
|
54
|
+
// deployment (deploying the proxy Worker from jundle via
|
|
55
|
+
// the Cloudflare API) is a follow-up; until then, a
|
|
56
|
+
// pre-deployed proxy URL comes from
|
|
57
|
+
// CLOUDFLARE_REMOTE_PROXY_URL (e.g. one wrangler deployed).
|
|
58
|
+
const remoteNames = new Set(remoteBindings || []);
|
|
59
|
+
const alwaysRemote = [];
|
|
60
|
+
if (config.ai?.binding) alwaysRemote.push(["AI", config.ai.binding]);
|
|
61
|
+
if (config.browser?.binding) alwaysRemote.push(["Browser Rendering", config.browser.binding]);
|
|
62
|
+
if (config.vectorize?.length) {
|
|
63
|
+
for (const v of config.vectorize) alwaysRemote.push(["Vectorize", v.binding]);
|
|
64
|
+
}
|
|
65
|
+
for (const [, binding] of alwaysRemote) remoteNames.add(binding);
|
|
66
|
+
// Validate remoteBindings names against the bindings
|
|
67
|
+
// actually in the wrangler file (a typo must not silently
|
|
68
|
+
// do nothing — it must be a clear error).
|
|
69
|
+
if (remoteBindings?.length) {
|
|
70
|
+
const known = new Set([
|
|
71
|
+
...(config.kv_namespaces || []).map((ns) => ns.binding),
|
|
72
|
+
...(config.r2_buckets || []).map((b) => b.binding),
|
|
73
|
+
...(config.d1_databases || []).map((db) => db.binding),
|
|
74
|
+
...(config.durable_objects?.bindings || []).map((b) => b.name),
|
|
75
|
+
...(config.queues?.producers || []).map((p) => p.binding),
|
|
76
|
+
...(config.workflows || []).map((w) => w.binding),
|
|
77
|
+
...(config.ai?.binding ? [config.ai.binding] : []),
|
|
78
|
+
...(config.browser?.binding ? [config.browser.binding] : []),
|
|
79
|
+
...(config.vectorize || []).map((v) => v.binding),
|
|
80
|
+
...(config.services || []).map((s) => s.binding),
|
|
81
|
+
]);
|
|
82
|
+
const unknown = remoteBindings.filter((b) => !known.has(b));
|
|
83
|
+
if (unknown.length) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`CF plugin: remoteBindings (entry options) names unknown binding(s): ${unknown.join(", ")} (not in the wrangler file)`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
const remoteServices = (config.services || []).filter((s) => remoteNames.has(s.binding));
|
|
89
|
+
if (remoteServices.length) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`CF plugin: remote service binding(s) ${remoteServices.map((s) => s.binding).join(", ")} are not supported yet (a remote service needs a service URL, not just a proxy — local service bindings via the workers array are supported; see CF-3 multi-worker)`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
let remoteProxyUrl = null;
|
|
96
|
+
if (remoteNames.size) {
|
|
97
|
+
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
98
|
+
const apiToken = process.env.CLOUDFLARE_API_TOKEN;
|
|
99
|
+
const missing = [
|
|
100
|
+
!accountId && "CLOUDFLARE_ACCOUNT_ID",
|
|
101
|
+
!apiToken && "CLOUDFLARE_API_TOKEN",
|
|
102
|
+
].filter(Boolean);
|
|
103
|
+
if (missing.length) {
|
|
104
|
+
const names = [
|
|
105
|
+
...alwaysRemote.map(([kind, binding]) => `${kind} (${binding})`),
|
|
106
|
+
...[...remoteNames].filter((b) => !alwaysRemote.some(([, ab]) => ab === b)),
|
|
107
|
+
].join(", ");
|
|
108
|
+
throw new Error(
|
|
109
|
+
`CF plugin: remote binding(s) ${names} require Cloudflare credentials, but missing: ${missing.join(", ")}. ` +
|
|
110
|
+
`Set ${missing.join(" and ")} to use them (remote bindings have no local fallback).`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
remoteProxyUrl = process.env.CLOUDFLARE_REMOTE_PROXY_URL || null;
|
|
114
|
+
if (!remoteProxyUrl) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`CF plugin: remote binding(s) ${[...remoteNames].join(", ")} require a deployed remote proxy Worker URL (Miniflare remoteProxyConnectionString), but CLOUDFLARE_REMOTE_PROXY_URL is not set. ` +
|
|
117
|
+
`Deploy a remote proxy (e.g. via \`wrangler dev --remote\`, which deploys one) and set CLOUDFLARE_REMOTE_PROXY_URL to its URL. ` +
|
|
118
|
+
`Native proxy deployment from jundle is a follow-up; until then this is a clear error, not a silent local fallback.`,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
options.cloudflareAccountId = accountId;
|
|
122
|
+
options.cloudflareApiToken = apiToken;
|
|
123
|
+
}
|
|
124
|
+
const isRemote = (binding) => remoteProxyUrl && remoteNames.has(binding);
|
|
125
|
+
|
|
126
|
+
// KV: local by default, persisted. Remote namespaces use
|
|
127
|
+
// the object form ({ id, remoteProxyConnectionString });
|
|
128
|
+
// if any namespace is remote the whole list becomes a
|
|
129
|
+
// Record (local entries keep their id as a plain string).
|
|
130
|
+
if (config.kv_namespaces?.length) {
|
|
131
|
+
if (config.kv_namespaces.some((ns) => isRemote(ns.binding))) {
|
|
132
|
+
options.kvNamespaces = {};
|
|
133
|
+
for (const ns of config.kv_namespaces) {
|
|
134
|
+
options.kvNamespaces[ns.binding] = isRemote(ns.binding)
|
|
135
|
+
? { id: ns.id, remoteProxyConnectionString: remoteProxyUrl }
|
|
136
|
+
: ns.id;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
options.kvNamespaces = config.kv_namespaces.map((ns) => ns.binding);
|
|
140
|
+
}
|
|
141
|
+
options.kvPersist = persistDir(configDir, "kv");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// R2: local by default, persisted. Same Record-form
|
|
145
|
+
// conversion as KV when any bucket is remote (id = the
|
|
146
|
+
// binding, matching the string[] form's bucket naming).
|
|
147
|
+
if (config.r2_buckets?.length) {
|
|
148
|
+
if (config.r2_buckets.some((b) => isRemote(b.binding))) {
|
|
149
|
+
options.r2Buckets = {};
|
|
150
|
+
for (const b of config.r2_buckets) {
|
|
151
|
+
options.r2Buckets[b.binding] = isRemote(b.binding)
|
|
152
|
+
? { id: b.binding, remoteProxyConnectionString: remoteProxyUrl }
|
|
153
|
+
: b.binding;
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
options.r2Buckets = config.r2_buckets.map((b) => b.binding);
|
|
157
|
+
}
|
|
158
|
+
options.r2Persist = persistDir(configDir, "r2");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// D1: local by default, persisted. migrations_dir is kept
|
|
162
|
+
// for the runner to apply (see header).
|
|
163
|
+
if (config.d1_databases?.length) {
|
|
164
|
+
options.d1Databases = {};
|
|
165
|
+
for (const db of config.d1_databases) {
|
|
166
|
+
const id = db.database_id || db.database_name;
|
|
167
|
+
options.d1Databases[db.binding] = isRemote(db.binding)
|
|
168
|
+
? { id, remoteProxyConnectionString: remoteProxyUrl }
|
|
169
|
+
: id;
|
|
170
|
+
}
|
|
171
|
+
options.d1Persist = persistDir(configDir, "d1");
|
|
172
|
+
options.d1Migrations = config.d1_databases
|
|
173
|
+
.filter((db) => db.migrations_dir)
|
|
174
|
+
.map((db) => ({
|
|
175
|
+
binding: db.binding,
|
|
176
|
+
dir: path.resolve(
|
|
177
|
+
path.dirname(wranglerFile || path.join(configDir, "wrangler.jsonc")),
|
|
178
|
+
db.migrations_dir,
|
|
179
|
+
),
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Durable Objects: class bindings mapped to classes the app
|
|
184
|
+
// exports; storage persisted; alarms are a runtime feature
|
|
185
|
+
// (no option needed — the DO class's alarm() handler runs).
|
|
186
|
+
if (config.durable_objects?.bindings?.length) {
|
|
187
|
+
options.durableObjects = {};
|
|
188
|
+
for (const b of config.durable_objects.bindings) {
|
|
189
|
+
options.durableObjects[b.name] = isRemote(b.name)
|
|
190
|
+
? { className: b.class_name, remoteProxyConnectionString: remoteProxyUrl }
|
|
191
|
+
: b.class_name;
|
|
192
|
+
}
|
|
193
|
+
options.durableObjectsPersist = persistDir(configDir, "do");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Queues: producers + consumers, local by default (local
|
|
197
|
+
// queues are in-memory only — Miniflare behavior, not
|
|
198
|
+
// hidden). Consumers dispatch to the app's exported queue()
|
|
199
|
+
// handler (Miniflare does this when the Worker exports it).
|
|
200
|
+
// A remote producer sends to the real Cloudflare queue;
|
|
201
|
+
// the consumer stays local (it is this Worker's handler).
|
|
202
|
+
if (config.queues?.producers?.length) {
|
|
203
|
+
options.queueProducers = {};
|
|
204
|
+
for (const p of config.queues.producers) {
|
|
205
|
+
options.queueProducers[p.binding] = isRemote(p.binding)
|
|
206
|
+
? { queueName: p.queue, remoteProxyConnectionString: remoteProxyUrl }
|
|
207
|
+
: p.queue;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (config.queues?.consumers?.length) {
|
|
211
|
+
options.queueConsumers = {};
|
|
212
|
+
for (const c of config.queues.consumers) {
|
|
213
|
+
options.queueConsumers[c.queue] = {
|
|
214
|
+
...(c.max_batch_size !== undefined ? { maxBatchSize: c.max_batch_size } : {}),
|
|
215
|
+
...(c.max_batch_timeout !== undefined ? { maxBatchTimeout: c.max_batch_timeout } : {}),
|
|
216
|
+
...(c.max_retries !== undefined ? { maxRetries: c.max_retries } : {}),
|
|
217
|
+
...(c.dead_letter_queue !== undefined ? { deadLetterQueue: c.dead_letter_queue } : {}),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Workflows: mapped to Workflow classes the app exports;
|
|
223
|
+
// state persisted in Durable Objects (Miniflare handles the
|
|
224
|
+
// storage when workflowsPersist is set).
|
|
225
|
+
if (config.workflows?.length) {
|
|
226
|
+
options.workflows = {};
|
|
227
|
+
for (const w of config.workflows) {
|
|
228
|
+
options.workflows[w.binding] = isRemote(w.binding)
|
|
229
|
+
? { name: w.name, className: w.class_name, remoteProxyConnectionString: remoteProxyUrl }
|
|
230
|
+
: { name: w.name, className: w.class_name };
|
|
231
|
+
}
|
|
232
|
+
options.workflowsPersist = persistDir(configDir, "workflows");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Cron triggers (wrangler `triggers.crons`): Miniflare runs
|
|
236
|
+
// scheduled handlers on this schedule (and
|
|
237
|
+
// dispatchScheduled triggers one on demand). Mapped here
|
|
238
|
+
// so the config is honored, not dropped.
|
|
239
|
+
if (config.triggers?.crons?.length) {
|
|
240
|
+
options.crons = [...config.triggers.crons];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Service bindings: a local Worker (by service name) or a
|
|
244
|
+
// remote service. Local services are resolved by the runner
|
|
245
|
+
// (CF-2) via Miniflare's worker registry; remote services
|
|
246
|
+
// need credentials and are handled in CF-3.
|
|
247
|
+
if (config.services?.length) {
|
|
248
|
+
options.serviceBindings = {};
|
|
249
|
+
for (const s of config.services) {
|
|
250
|
+
if (s.service) options.serviceBindings[s.binding] = s.service;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Assets: bound to a local directory (wrangler `assets`
|
|
255
|
+
// config: { directory } or a plain path string).
|
|
256
|
+
// routerConfig.has_user_worker tells Miniflare's assets
|
|
257
|
+
// router that a user Worker exists to fall through to for
|
|
258
|
+
// non-asset paths; without it, Miniflare serves ONLY static
|
|
259
|
+
// files and every Worker route 404s (assets-only mode).
|
|
260
|
+
// With it, static files win for matching paths and the
|
|
261
|
+
// Worker handles the rest (the Workers Static Assets model).
|
|
262
|
+
if (config.assets) {
|
|
263
|
+
const dir = typeof config.assets === "string" ? config.assets : config.assets.directory;
|
|
264
|
+
if (dir)
|
|
265
|
+
options.assets = {
|
|
266
|
+
directory: path.resolve(configDir, dir),
|
|
267
|
+
routerConfig: { has_user_worker: true },
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// AI / Browser Rendering / Vectorize: ALWAYS remote (no
|
|
272
|
+
// local emulation). Wired here (not just recorded) when a
|
|
273
|
+
// proxy URL is present; without credentials or a proxy URL
|
|
274
|
+
// the top-of-function checks already threw a clear error.
|
|
275
|
+
if (config.ai?.binding) {
|
|
276
|
+
options.ai = { binding: config.ai.binding, remoteProxyConnectionString: remoteProxyUrl };
|
|
277
|
+
}
|
|
278
|
+
if (config.browser?.binding) {
|
|
279
|
+
options.browserRendering = {
|
|
280
|
+
binding: config.browser.binding,
|
|
281
|
+
remoteProxyConnectionString: remoteProxyUrl,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
if (config.vectorize?.length) {
|
|
285
|
+
options.vectorize = {};
|
|
286
|
+
for (const v of config.vectorize) {
|
|
287
|
+
options.vectorize[v.binding] = {
|
|
288
|
+
index_name: v.index_name,
|
|
289
|
+
remoteProxyConnectionString: remoteProxyUrl,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return options;
|
|
295
|
+
}
|
package/src/build.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Type declarations for @jundle/cloudflare/build — the
|
|
2
|
+
// Cloudflare Workers BUILD plugin (SPEC §16.13). See
|
|
3
|
+
// src/build.js for the implementation; src/index.d.ts for
|
|
4
|
+
// the runtime plugin and the WranglerConfig type (imported
|
|
5
|
+
// here, not duplicated).
|
|
6
|
+
import type { WranglerConfig } from "./index.js";
|
|
7
|
+
|
|
8
|
+
/** The five Workers runtime builtins, exactly
|
|
9
|
+
* @cloudflare/vite-plugin's cloudflareBuiltInModules. */
|
|
10
|
+
export declare const CLOUDFLARE_BUILTINS: readonly [
|
|
11
|
+
"cloudflare:email",
|
|
12
|
+
"cloudflare:node",
|
|
13
|
+
"cloudflare:sockets",
|
|
14
|
+
"cloudflare:workers",
|
|
15
|
+
"cloudflare:workflows",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
/** Options for the build plugin, core-managed when
|
|
19
|
+
* auto-registered (SPEC §16.13). `configDir` is
|
|
20
|
+
* required: the writeBundle handler only receives
|
|
21
|
+
* { dir } + the file list, so the project directory
|
|
22
|
+
* must be captured at construction time. */
|
|
23
|
+
export interface CloudflareBuildPluginOptions {
|
|
24
|
+
/** Project root: the wrangler file is resolved against this. */
|
|
25
|
+
configDir: string;
|
|
26
|
+
/**
|
|
27
|
+
* Path to the wrangler config file, resolved against
|
|
28
|
+
* configDir. Null/omitted auto-discovers wrangler.jsonc,
|
|
29
|
+
* wrangler.json, then wrangler.toml in the config directory.
|
|
30
|
+
*/
|
|
31
|
+
wranglerConfig?: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Inputs to {@link getOutputConfig}. */
|
|
35
|
+
export interface OutputConfigArgs {
|
|
36
|
+
/** The user's wrangler config, as read by readWranglerConfig. */
|
|
37
|
+
userConfig: WranglerConfig;
|
|
38
|
+
/** The server entry chunk, outDir-relative (e.g. "server/server.js"). */
|
|
39
|
+
main: string;
|
|
40
|
+
/** Whether the build has client output (drives assets.directory). */
|
|
41
|
+
includeAssets: boolean;
|
|
42
|
+
/** Absolute output directory (the worker outDir). */
|
|
43
|
+
outDir: string;
|
|
44
|
+
/** Project root, for rebasing source-relative paths. */
|
|
45
|
+
configDir: string;
|
|
46
|
+
/** Whether the entry chunk has a .map in the bundle. */
|
|
47
|
+
sourcemaps: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The generated <outDir>/wrangler.json (upstream
|
|
52
|
+
* getOutputConfig): the user's config with main,
|
|
53
|
+
* no_bundle, rules, rebased assets/containers/d1, and
|
|
54
|
+
* upload_source_maps applied. Other fields pass through
|
|
55
|
+
* verbatim; the return type is the input config plus the
|
|
56
|
+
* overrides, so it stays open via the index signature.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getOutputConfig(args: OutputConfigArgs): WranglerConfig & {
|
|
59
|
+
main: string;
|
|
60
|
+
no_bundle: true;
|
|
61
|
+
rules: Array<{ type: "ESModule"; globs: string[] }>;
|
|
62
|
+
upload_source_maps?: boolean;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/** Quote one value for .dev.vars (upstream quoteForDotenv). */
|
|
66
|
+
export declare function quoteForDotenv(value: string): string;
|
|
67
|
+
|
|
68
|
+
/** Serialize local dev vars to .dev.vars file contents. */
|
|
69
|
+
export declare function serializeDevVars(devVars: Record<string, string>): string;
|
|
70
|
+
|
|
71
|
+
/** The <configDir>/.wrangler/deploy/config.json contents. */
|
|
72
|
+
export interface DeployConfig {
|
|
73
|
+
/** Path relative from .wrangler/deploy/ to <outDir>/wrangler.json. */
|
|
74
|
+
configPath: string;
|
|
75
|
+
/** No auxiliary workers in single-worker jundle. */
|
|
76
|
+
auxiliaryWorkers: Array<{ configPath: string }>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export declare function buildDeployConfig(args: {
|
|
80
|
+
configDir: string;
|
|
81
|
+
outDir: string;
|
|
82
|
+
}): DeployConfig;
|
|
83
|
+
|
|
84
|
+
/** Rewrite a D1 migrations_pattern from the source
|
|
85
|
+
* migrations dir to the output migrations dir. */
|
|
86
|
+
export declare function rewriteMigrationsPattern(
|
|
87
|
+
migrationsPattern: string | undefined,
|
|
88
|
+
fromMigrationsDir: string,
|
|
89
|
+
toMigrationsDir: string,
|
|
90
|
+
): string | undefined;
|
|
91
|
+
|
|
92
|
+
/** The meta object core passes to the factory's `raw`. */
|
|
93
|
+
export interface CloudflareBuildPluginMeta {
|
|
94
|
+
framework: "jundle";
|
|
95
|
+
versions: { unplugin: string; jundle: string };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** The plugin object the factory produces. */
|
|
99
|
+
export interface CloudflareBuildPlugin {
|
|
100
|
+
name: "@jundle/cloudflare";
|
|
101
|
+
enforce: "pre";
|
|
102
|
+
/**
|
|
103
|
+
* Returns `{ id: source, external: true }` for the
|
|
104
|
+
* exact five `cloudflare:*` builtins, `null` otherwise.
|
|
105
|
+
*/
|
|
106
|
+
resolveId: (
|
|
107
|
+
source: string,
|
|
108
|
+
importer: string | undefined,
|
|
109
|
+
options: {
|
|
110
|
+
isEntry: boolean;
|
|
111
|
+
attributes: Record<string, string>;
|
|
112
|
+
custom?: unknown;
|
|
113
|
+
kind: "static" | "dynamic";
|
|
114
|
+
},
|
|
115
|
+
) => { id: string; external: true } | null;
|
|
116
|
+
/** Emits the deployment config after the write phase. */
|
|
117
|
+
writeBundle: (options: { dir: string }, bundle: string[]) => Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The build plugin factory (unplugin, as the demo plugin
|
|
122
|
+
* in examples/rsc-app/plugins/demo-plugin.js). Core
|
|
123
|
+
* auto-registers it for a @jundle/cloudflare runtime
|
|
124
|
+
* entry; it can also be declared explicitly in
|
|
125
|
+
* config.plugins with the same options.
|
|
126
|
+
*
|
|
127
|
+
* Deliberately NOT typed via `unplugin`'s own types:
|
|
128
|
+
* core only ever calls `.raw(options, meta)` (see
|
|
129
|
+
* `plugin-inventory.js`), and importing unplugin's
|
|
130
|
+
* declarations pulls in its optional peer declarations
|
|
131
|
+
* (`@farmfe/core`, `rollup`, ...) which are not
|
|
132
|
+
* installed, breaking consumers' typechecks. The other
|
|
133
|
+
* framework adapters (`.vite`, `.rollup`, ...) exist at
|
|
134
|
+
* runtime but are not part of jundle's contract, so they
|
|
135
|
+
* are not declared here.
|
|
136
|
+
*/
|
|
137
|
+
export interface CloudflareBuildPluginFactory {
|
|
138
|
+
raw: (
|
|
139
|
+
options: CloudflareBuildPluginOptions,
|
|
140
|
+
meta: CloudflareBuildPluginMeta,
|
|
141
|
+
) => CloudflareBuildPlugin | CloudflareBuildPlugin[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
declare const _default: CloudflareBuildPluginFactory;
|
|
145
|
+
export default _default;
|