wrangler 2.9.0 → 2.10.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/README.md +3 -3
- package/miniflare-dist/index.mjs +2 -15
- package/package.json +9 -9
- package/src/__tests__/configuration.test.ts +70 -0
- package/src/__tests__/d1/d1.test.ts +3 -6
- package/src/__tests__/d1/execute.test.ts +64 -0
- package/src/__tests__/d1/migrate.test.ts +107 -0
- package/src/__tests__/deployments.test.ts +40 -16
- package/src/__tests__/dev.test.tsx +3 -3
- package/src/__tests__/generate.test.ts +1 -1
- package/src/__tests__/helpers/end-event-loop.ts +6 -0
- package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
- package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +40 -16
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/index.test.ts +3 -4
- package/src/__tests__/init.test.ts +1 -1
- package/src/__tests__/kv.test.ts +8 -8
- package/src/__tests__/middleware.test.ts +65 -0
- package/src/__tests__/mtls-certificates.test.ts +585 -0
- package/src/__tests__/pages/deployment-list.test.ts +78 -0
- package/src/__tests__/pages/functions-build.test.ts +402 -0
- package/src/__tests__/pages/pages.test.ts +81 -0
- package/src/__tests__/pages/project-create.test.ts +63 -0
- package/src/__tests__/pages/project-list.test.ts +108 -0
- package/src/__tests__/pages/project-upload.test.ts +481 -0
- package/src/__tests__/pages/publish.test.ts +2745 -0
- package/src/__tests__/publish.test.ts +58 -27
- package/src/__tests__/queues.test.ts +2 -2
- package/src/__tests__/secret.test.ts +4 -4
- package/src/__tests__/tsconfig.tsbuildinfo +1 -1
- package/src/__tests__/user.test.ts +1 -1
- package/src/__tests__/whoami.test.tsx +1 -1
- package/src/__tests__/worker-namespace.test.ts +1 -1
- package/src/api/index.ts +8 -0
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +75 -0
- package/src/api/pages/publish.tsx +52 -8
- package/src/bundle.ts +6 -5
- package/src/config/config.ts +7 -7
- package/src/config/environment.ts +9 -2
- package/src/config/index.ts +13 -0
- package/src/config/validation.ts +50 -3
- package/src/create-worker-upload-form.ts +9 -0
- package/src/d1/execute.tsx +124 -91
- package/src/d1/migrations/apply.tsx +36 -29
- package/src/d1/migrations/create.tsx +10 -8
- package/src/d1/migrations/helpers.ts +63 -38
- package/src/d1/migrations/list.tsx +31 -20
- package/src/d1/migrations/options.ts +6 -1
- package/src/d1/types.ts +1 -0
- package/src/d1/utils.ts +2 -1
- package/src/deployments.ts +62 -39
- package/src/dev/dev.tsx +1 -15
- package/src/dev/remote.tsx +2 -2
- package/src/dev.tsx +9 -6
- package/src/generate/index.ts +1 -1
- package/src/index.ts +15 -5
- package/src/miniflare-cli/assets.ts +1 -1
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/pages/build.ts +103 -23
- package/src/pages/buildFunctions.ts +32 -31
- package/src/pages/dev.ts +4 -2
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
- package/src/pages/publish.tsx +12 -1
- package/src/pages/utils.ts +1 -1
- package/src/publish/publish.ts +3 -2
- package/src/secret/index.ts +1 -0
- package/src/sites.ts +1 -1
- package/src/tail/filters.ts +1 -1
- package/src/user/user.ts +4 -3
- package/src/worker.ts +6 -0
- package/templates/format-dev-errors.ts +1 -0
- package/templates/new-worker.ts +3 -0
- package/templates/serve-static-assets.ts +1 -0
- package/templates/service-bindings-module-facade.js +1 -0
- package/templates/tsconfig.init.json +1 -1
- package/templates/tsconfig.tsbuildinfo +1 -1
- package/wrangler-dist/cli.d.ts +82 -2
- package/wrangler-dist/cli.js +1726 -1616
- package/src/__tests__/pages.test.ts +0 -2905
|
@@ -60,7 +60,7 @@ describe("User", () => {
|
|
|
60
60
|
expect(counter).toBe(1);
|
|
61
61
|
expect(std.out).toMatchInlineSnapshot(`
|
|
62
62
|
"Attempting to login via OAuth...
|
|
63
|
-
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
|
|
63
|
+
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
|
|
64
64
|
Successfully logged in."
|
|
65
65
|
`);
|
|
66
66
|
expect(readAuthConfigFile()).toEqual<UserAuthConfig>({
|
|
@@ -160,7 +160,7 @@ describe("getUserInfo()", () => {
|
|
|
160
160
|
await getUserInfo();
|
|
161
161
|
|
|
162
162
|
expect(std.warn).toMatchInlineSnapshot(`
|
|
163
|
-
"[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mIt looks like you have used Wrangler
|
|
163
|
+
"[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mIt looks like you have used Wrangler v1's \`config\` command to login with an API token.[0m
|
|
164
164
|
|
|
165
165
|
This is no longer supported in the current version of Wrangler.
|
|
166
166
|
If you wish to authenticate via an API token then please set the \`CLOUDFLARE_API_TOKEN\`
|
|
@@ -17,7 +17,7 @@ describe("dispatch-namespace", () => {
|
|
|
17
17
|
mockAccountId();
|
|
18
18
|
mockApiToken();
|
|
19
19
|
|
|
20
|
-
it("should
|
|
20
|
+
it("should display a list of available subcommands, for dispatch-namespace with no subcommand", async () => {
|
|
21
21
|
await runWrangler("dispatch-namespace");
|
|
22
22
|
|
|
23
23
|
// wait a tick for the help menu to be printed
|
package/src/api/index.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
export { unstable_dev } from "./dev";
|
|
2
2
|
export type { UnstableDevWorker, UnstableDevOptions } from "./dev";
|
|
3
3
|
export { unstable_pages } from "./pages";
|
|
4
|
+
export {
|
|
5
|
+
uploadMTlsCertificate,
|
|
6
|
+
uploadMTlsCertificateFromFs,
|
|
7
|
+
listMTlsCertificates,
|
|
8
|
+
getMTlsCertificate,
|
|
9
|
+
getMTlsCertificateByName,
|
|
10
|
+
deleteMTlsCertificate,
|
|
11
|
+
} from "./mtls-certificate";
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { fetchResult } from "../cfetch";
|
|
2
|
+
import { readFileSync } from "../parse";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* the representation of an mTLS certificate in the account certificate store
|
|
6
|
+
*/
|
|
7
|
+
export interface MTlsCertificateResponse {
|
|
8
|
+
id: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
ca: boolean;
|
|
11
|
+
certificates: string;
|
|
12
|
+
expires_on: string;
|
|
13
|
+
issuer: string;
|
|
14
|
+
serial_number: string;
|
|
15
|
+
signature: string;
|
|
16
|
+
uploaded_on: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* details for uploading an mTLS certificate from disk
|
|
21
|
+
*/
|
|
22
|
+
export interface MTlsCertificateUploadDetails {
|
|
23
|
+
certificateChainFilename: string;
|
|
24
|
+
privateKeyFilename: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* details for uploading an mTLS certificate via the ssl api
|
|
30
|
+
*/
|
|
31
|
+
export interface MTlsCertificateBody {
|
|
32
|
+
certificateChain: string;
|
|
33
|
+
privateKey: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* supported filters for listing mTLS certificates via the ssl api
|
|
39
|
+
*/
|
|
40
|
+
export interface MTlsCertificateListFilter {
|
|
41
|
+
name?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* indicates that looking up a certificate by name failed due to zero matching results
|
|
46
|
+
*/
|
|
47
|
+
export class ErrorMTlsCertificateNameNotFound extends Error {}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* indicates that looking up a certificate by name failed due to more than one matching results
|
|
51
|
+
*/
|
|
52
|
+
export class ErrorMTlsCertificateManyNamesMatch extends Error {}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* reads an mTLS certificate and private key pair from disk and uploads it to the account mTLS certificate store
|
|
56
|
+
*/
|
|
57
|
+
export async function uploadMTlsCertificateFromFs(
|
|
58
|
+
accountId: string,
|
|
59
|
+
details: MTlsCertificateUploadDetails
|
|
60
|
+
): Promise<MTlsCertificateResponse> {
|
|
61
|
+
return await uploadMTlsCertificate(accountId, {
|
|
62
|
+
certificateChain: readFileSync(details.certificateChainFilename),
|
|
63
|
+
privateKey: readFileSync(details.privateKeyFilename),
|
|
64
|
+
name: details.name,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* uploads an mTLS certificate and private key pair to the account mTLS certificate store
|
|
70
|
+
*/
|
|
71
|
+
export async function uploadMTlsCertificate(
|
|
72
|
+
accountId: string,
|
|
73
|
+
body: MTlsCertificateBody
|
|
74
|
+
): Promise<MTlsCertificateResponse> {
|
|
75
|
+
return await fetchResult(`/accounts/${accountId}/mtls_certificates`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: JSON.stringify({
|
|
78
|
+
name: body.name,
|
|
79
|
+
certificates: body.certificateChain,
|
|
80
|
+
private_key: body.privateKey,
|
|
81
|
+
ca: false,
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* fetches an mTLS certificate from the account mTLS certificate store by ID
|
|
88
|
+
*/
|
|
89
|
+
export async function getMTlsCertificate(
|
|
90
|
+
accountId: string,
|
|
91
|
+
id: string
|
|
92
|
+
): Promise<MTlsCertificateResponse> {
|
|
93
|
+
return await fetchResult(
|
|
94
|
+
`/accounts/${accountId}/mtls_certificates/${id}`,
|
|
95
|
+
{}
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* lists mTLS certificates for an account. filtering by name is supported
|
|
101
|
+
*/
|
|
102
|
+
export async function listMTlsCertificates(
|
|
103
|
+
accountId: string,
|
|
104
|
+
filter: MTlsCertificateListFilter
|
|
105
|
+
): Promise<MTlsCertificateResponse[]> {
|
|
106
|
+
const params = new URLSearchParams();
|
|
107
|
+
params.append("ca", "false");
|
|
108
|
+
if (filter.name) {
|
|
109
|
+
params.append("name", filter.name);
|
|
110
|
+
}
|
|
111
|
+
return await fetchResult(
|
|
112
|
+
`/accounts/${accountId}/mtls_certificates`,
|
|
113
|
+
{},
|
|
114
|
+
params
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* fetches an mTLS certificate from the account mTLS certificate store by name. will throw an error if no certificates are found, or multiple are found with that name
|
|
120
|
+
*/
|
|
121
|
+
export async function getMTlsCertificateByName(
|
|
122
|
+
accountId: string,
|
|
123
|
+
name: string
|
|
124
|
+
): Promise<MTlsCertificateResponse> {
|
|
125
|
+
const certificates = await listMTlsCertificates(accountId, { name });
|
|
126
|
+
if (certificates.length === 0) {
|
|
127
|
+
throw new ErrorMTlsCertificateNameNotFound(
|
|
128
|
+
`certificate not found with name "${name}"`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (certificates.length > 1) {
|
|
132
|
+
throw new ErrorMTlsCertificateManyNamesMatch(
|
|
133
|
+
`multiple certificates found with name "${name}"`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const certificate = certificates[0];
|
|
137
|
+
return certificate;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function deleteMTlsCertificate(
|
|
141
|
+
accountId: string,
|
|
142
|
+
certificateId: string
|
|
143
|
+
) {
|
|
144
|
+
return await fetchResult(
|
|
145
|
+
`/accounts/${accountId}/mtls_certificates/${certificateId}`,
|
|
146
|
+
{ method: "DELETE" }
|
|
147
|
+
);
|
|
148
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { Response } from "undici";
|
|
4
|
+
import { createWorkerUploadForm } from "../../create-worker-upload-form";
|
|
5
|
+
import type { BundleResult } from "../../bundle";
|
|
6
|
+
import type { CfWorkerInit } from "../../worker";
|
|
7
|
+
import type { Blob } from "node:buffer";
|
|
8
|
+
import type { FormData } from "undici";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Takes a Worker bundle - `BundleResult` - and generates the _worker.bundle
|
|
12
|
+
* contents
|
|
13
|
+
*/
|
|
14
|
+
export async function createUploadWorkerBundleContents(
|
|
15
|
+
workerBundle: BundleResult
|
|
16
|
+
): Promise<Blob> {
|
|
17
|
+
const workerBundleFormData = createWorkerBundleFormData(workerBundle);
|
|
18
|
+
const metadata = JSON.parse(workerBundleFormData.get("metadata") as string);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Pages doesn't need the metadata bindings returned by
|
|
22
|
+
* `createWorkerBundleFormData`. Let's strip them out and return only
|
|
23
|
+
* the contents we need
|
|
24
|
+
*/
|
|
25
|
+
workerBundleFormData.set(
|
|
26
|
+
"metadata",
|
|
27
|
+
JSON.stringify({ main_module: metadata.main_module })
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return await new Response(workerBundleFormData).blob();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a `FormData` upload from a `BundleResult`
|
|
35
|
+
*/
|
|
36
|
+
function createWorkerBundleFormData(workerBundle: BundleResult): FormData {
|
|
37
|
+
const mainModule = {
|
|
38
|
+
name: path.basename(workerBundle.resolvedEntryPointPath),
|
|
39
|
+
content: readFileSync(workerBundle.resolvedEntryPointPath, {
|
|
40
|
+
encoding: "utf-8",
|
|
41
|
+
}),
|
|
42
|
+
type: workerBundle.bundleType || "esm",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const worker: CfWorkerInit = {
|
|
46
|
+
name: mainModule.name,
|
|
47
|
+
main: mainModule,
|
|
48
|
+
modules: workerBundle.modules,
|
|
49
|
+
bindings: {
|
|
50
|
+
vars: undefined,
|
|
51
|
+
kv_namespaces: undefined,
|
|
52
|
+
wasm_modules: undefined,
|
|
53
|
+
text_blobs: undefined,
|
|
54
|
+
data_blobs: undefined,
|
|
55
|
+
durable_objects: undefined,
|
|
56
|
+
queues: undefined,
|
|
57
|
+
r2_buckets: undefined,
|
|
58
|
+
d1_databases: undefined,
|
|
59
|
+
services: undefined,
|
|
60
|
+
analytics_engine_datasets: undefined,
|
|
61
|
+
dispatch_namespaces: undefined,
|
|
62
|
+
mtls_certificates: undefined,
|
|
63
|
+
logfwdr: undefined,
|
|
64
|
+
unsafe: undefined,
|
|
65
|
+
},
|
|
66
|
+
migrations: undefined,
|
|
67
|
+
compatibility_date: undefined,
|
|
68
|
+
compatibility_flags: undefined,
|
|
69
|
+
usage_model: undefined,
|
|
70
|
+
keepVars: undefined,
|
|
71
|
+
logpush: undefined,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return createWorkerUploadForm(worker);
|
|
75
|
+
}
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
} from "../../pages/functions/buildWorker";
|
|
18
18
|
import { validateRoutes } from "../../pages/functions/routes-validation";
|
|
19
19
|
import { upload } from "../../pages/upload";
|
|
20
|
+
import { createUploadWorkerBundleContents } from "./create-worker-bundle-contents";
|
|
21
|
+
import type { BundleResult } from "../../bundle";
|
|
20
22
|
import type { Project, Deployment } from "@cloudflare/types";
|
|
21
23
|
|
|
22
24
|
interface PagesPublishOptions {
|
|
@@ -67,6 +69,14 @@ interface PagesPublishOptions {
|
|
|
67
69
|
*/
|
|
68
70
|
bundle?: boolean;
|
|
69
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Whether to process non-JS module imports or not, such as
|
|
74
|
+
* wasm/text/binary, when we run bundling on `functions` or
|
|
75
|
+
* `_worker.js`
|
|
76
|
+
* Default: false
|
|
77
|
+
*/
|
|
78
|
+
experimentalWorkerBundle?: boolean;
|
|
79
|
+
|
|
70
80
|
// TODO: Allow passing in the API key and plumb it through
|
|
71
81
|
// to the API calls so that the publish function does not
|
|
72
82
|
// rely on the `CLOUDFLARE_API_KEY` environment variable
|
|
@@ -88,6 +98,7 @@ export async function publish({
|
|
|
88
98
|
commitDirty,
|
|
89
99
|
functionsDirectory: customFunctionsDirectory,
|
|
90
100
|
bundle,
|
|
101
|
+
experimentalWorkerBundle,
|
|
91
102
|
}: PagesPublishOptions) {
|
|
92
103
|
let _headers: string | undefined,
|
|
93
104
|
_redirects: string | undefined,
|
|
@@ -132,6 +143,8 @@ export async function publish({
|
|
|
132
143
|
* Functions first and exit if it failed
|
|
133
144
|
*/
|
|
134
145
|
let builtFunctions: string | undefined = undefined;
|
|
146
|
+
let workerBundle: BundleResult | undefined = undefined;
|
|
147
|
+
|
|
135
148
|
const functionsDirectory =
|
|
136
149
|
customFunctionsDirectory || join(cwd(), "functions");
|
|
137
150
|
const routesOutputPath = !existsSync(join(directory, "_routes.json"))
|
|
@@ -154,7 +167,7 @@ export async function publish({
|
|
|
154
167
|
);
|
|
155
168
|
|
|
156
169
|
try {
|
|
157
|
-
await buildFunctions({
|
|
170
|
+
workerBundle = await buildFunctions({
|
|
158
171
|
outfile,
|
|
159
172
|
outputConfigPath,
|
|
160
173
|
functionsDirectory,
|
|
@@ -163,6 +176,7 @@ export async function publish({
|
|
|
163
176
|
routesOutputPath,
|
|
164
177
|
local: false,
|
|
165
178
|
d1Databases,
|
|
179
|
+
experimentalWorkerBundle,
|
|
166
180
|
});
|
|
167
181
|
|
|
168
182
|
builtFunctions = readFileSync(outfile, "utf-8");
|
|
@@ -234,9 +248,11 @@ export async function publish({
|
|
|
234
248
|
*/
|
|
235
249
|
if (_workerJS) {
|
|
236
250
|
let workerFileContents = _workerJS;
|
|
237
|
-
|
|
251
|
+
const enableBundling = bundle || experimentalWorkerBundle;
|
|
252
|
+
|
|
253
|
+
if (enableBundling) {
|
|
238
254
|
const outfile = join(tmpdir(), `./bundledWorker-${Math.random()}.mjs`);
|
|
239
|
-
await buildRawWorker({
|
|
255
|
+
workerBundle = await buildRawWorker({
|
|
240
256
|
workerScriptPath,
|
|
241
257
|
outfile,
|
|
242
258
|
directory: directory ?? ".",
|
|
@@ -245,14 +261,30 @@ export async function publish({
|
|
|
245
261
|
watch: false,
|
|
246
262
|
onEnd: () => {},
|
|
247
263
|
betaD1Shims: d1Databases,
|
|
264
|
+
experimentalWorkerBundle,
|
|
248
265
|
});
|
|
249
266
|
workerFileContents = readFileSync(outfile, "utf8");
|
|
250
267
|
} else {
|
|
251
268
|
await checkRawWorker(workerScriptPath, () => {});
|
|
252
269
|
}
|
|
253
270
|
|
|
254
|
-
|
|
255
|
-
|
|
271
|
+
if (experimentalWorkerBundle) {
|
|
272
|
+
const workerBundleContents = await createUploadWorkerBundleContents(
|
|
273
|
+
workerBundle as BundleResult
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
formData.append(
|
|
277
|
+
"_worker.bundle",
|
|
278
|
+
new File([workerBundleContents], "_worker.bundle")
|
|
279
|
+
);
|
|
280
|
+
logger.log(`✨ Uploading Worker bundle`);
|
|
281
|
+
} else {
|
|
282
|
+
formData.append(
|
|
283
|
+
"_worker.js",
|
|
284
|
+
new File([workerFileContents], "_worker.js")
|
|
285
|
+
);
|
|
286
|
+
logger.log(`✨ Uploading _worker.js`);
|
|
287
|
+
}
|
|
256
288
|
|
|
257
289
|
if (_routesCustom) {
|
|
258
290
|
// user provided a custom _routes.json file
|
|
@@ -278,9 +310,21 @@ export async function publish({
|
|
|
278
310
|
* https://developers.cloudflare.com/pages/platform/functions/
|
|
279
311
|
*/
|
|
280
312
|
if (builtFunctions && !_workerJS) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
313
|
+
if (experimentalWorkerBundle) {
|
|
314
|
+
const workerBundleContents = await createUploadWorkerBundleContents(
|
|
315
|
+
workerBundle as BundleResult
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
formData.append(
|
|
319
|
+
"_worker.bundle",
|
|
320
|
+
new File([workerBundleContents], "_worker.bundle")
|
|
321
|
+
);
|
|
322
|
+
logger.log(`✨ Uploading Functions bundle`);
|
|
323
|
+
} else {
|
|
324
|
+
// if Functions were build successfully, proceed to uploading the build file
|
|
325
|
+
formData.append("_worker.js", new File([builtFunctions], "_worker.js"));
|
|
326
|
+
logger.log(`✨ Uploading Functions`);
|
|
327
|
+
}
|
|
284
328
|
|
|
285
329
|
if (_routesCustom) {
|
|
286
330
|
// user provided a custom _routes.json file
|
package/src/bundle.ts
CHANGED
|
@@ -116,7 +116,7 @@ export async function bundleWorker(
|
|
|
116
116
|
loader?: Record<string, string>;
|
|
117
117
|
sourcemap?: esbuild.CommonOptions["sourcemap"];
|
|
118
118
|
plugins?: esbuild.Plugin[];
|
|
119
|
-
// TODO: Rip these out https://github.com/cloudflare/
|
|
119
|
+
// TODO: Rip these out https://github.com/cloudflare/workers-sdk/issues/2153
|
|
120
120
|
disableModuleCollection?: boolean;
|
|
121
121
|
isOutfile?: boolean;
|
|
122
122
|
}
|
|
@@ -344,7 +344,7 @@ export async function bundleWorker(
|
|
|
344
344
|
...(process.env.NODE_ENV && {
|
|
345
345
|
define: {
|
|
346
346
|
// use process.env["NODE_ENV" + ""] so that esbuild doesn't replace it
|
|
347
|
-
// when we do a build of wrangler. (re: https://github.com/cloudflare/
|
|
347
|
+
// when we do a build of wrangler. (re: https://github.com/cloudflare/workers-sdk/issues/1477)
|
|
348
348
|
"process.env.NODE_ENV": `"${process.env["NODE_ENV" + ""]}"`,
|
|
349
349
|
...(nodeCompat ? { global: "globalThis" } : {}),
|
|
350
350
|
...(checkFetch ? { fetch: "checkedFetch" } : {}),
|
|
@@ -574,9 +574,10 @@ async function applyMiddlewareLoaderFacade(
|
|
|
574
574
|
],
|
|
575
575
|
outfile: targetPathInsertion,
|
|
576
576
|
});
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
577
|
+
const targetPathLoader = path.join(
|
|
578
|
+
tmpDirPath,
|
|
579
|
+
"middleware-loader.entry.js"
|
|
580
|
+
);
|
|
580
581
|
const loaderPath = path.resolve(
|
|
581
582
|
getBasePath(),
|
|
582
583
|
"templates/middleware/loader-modules.ts"
|
package/src/config/config.ts
CHANGED
|
@@ -18,7 +18,7 @@ import type { CamelCaseKey } from "yargs";
|
|
|
18
18
|
*
|
|
19
19
|
* Legend for the annotations:
|
|
20
20
|
*
|
|
21
|
-
* - `@breaking`: the deprecation/optionality is a breaking change from
|
|
21
|
+
* - `@breaking`: the deprecation/optionality is a breaking change from Wrangler v1.
|
|
22
22
|
* - `@todo`: there's more work to be done (with details attached).
|
|
23
23
|
*/
|
|
24
24
|
export type Config = ConfigFields<DevConfig> & Environment;
|
|
@@ -32,7 +32,7 @@ export interface ConfigFields<Dev extends RawDevConfig> {
|
|
|
32
32
|
configPath: string | undefined;
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* A boolean to enable "legacy" style wrangler environments (from
|
|
35
|
+
* A boolean to enable "legacy" style wrangler environments (from Wrangler v1).
|
|
36
36
|
* These have been superseded by Services, but there may be projects that won't
|
|
37
37
|
* (or can't) use them. If you're using a legacy environment, you can set this
|
|
38
38
|
* to `true` to enable it.
|
|
@@ -96,7 +96,7 @@ export interface ConfigFields<Dev extends RawDevConfig> {
|
|
|
96
96
|
/**
|
|
97
97
|
* The location of your Worker script.
|
|
98
98
|
*
|
|
99
|
-
* @deprecated DO NOT use this (it's a holdover from
|
|
99
|
+
* @deprecated DO NOT use this (it's a holdover from Wrangler v1.x). Either use the top level `main` field, or pass the path to your entry file as a command line argument.
|
|
100
100
|
* @breaking
|
|
101
101
|
*/
|
|
102
102
|
"entry-point"?: string;
|
|
@@ -216,10 +216,10 @@ export interface DevConfig {
|
|
|
216
216
|
* Protocol that wrangler dev forwards requests on
|
|
217
217
|
*
|
|
218
218
|
* Setting this to `http` is not currently implemented.
|
|
219
|
-
* See https://github.com/cloudflare/
|
|
219
|
+
* See https://github.com/cloudflare/workers-sdk/issues/583
|
|
220
220
|
*
|
|
221
221
|
* @default `https`
|
|
222
|
-
* @todo this needs to be implemented https://github.com/cloudflare/
|
|
222
|
+
* @todo this needs to be implemented https://github.com/cloudflare/workers-sdk/issues/583
|
|
223
223
|
*/
|
|
224
224
|
upstream_protocol: "https" | "http";
|
|
225
225
|
|
|
@@ -233,7 +233,7 @@ export type RawDevConfig = Partial<DevConfig>;
|
|
|
233
233
|
|
|
234
234
|
export interface DeprecatedConfigFields {
|
|
235
235
|
/**
|
|
236
|
-
* The project "type". A holdover from
|
|
236
|
+
* The project "type". A holdover from Wrangler v1.x.
|
|
237
237
|
* Valid values were "webpack", "javascript", and "rust".
|
|
238
238
|
*
|
|
239
239
|
* @deprecated DO NOT USE THIS. Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build.
|
|
@@ -243,7 +243,7 @@ export interface DeprecatedConfigFields {
|
|
|
243
243
|
|
|
244
244
|
/**
|
|
245
245
|
* Path to the webpack config to use when building your worker.
|
|
246
|
-
* A holdover from
|
|
246
|
+
* A holdover from Wrangler v1.x, used with `type: "webpack"`.
|
|
247
247
|
*
|
|
248
248
|
* @deprecated DO NOT USE THIS. Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build.
|
|
249
249
|
* @breaking
|
|
@@ -78,7 +78,7 @@ interface EnvironmentInheritable {
|
|
|
78
78
|
* Whether we use <name>.<subdomain>.workers.dev to
|
|
79
79
|
* test and deploy your worker.
|
|
80
80
|
*
|
|
81
|
-
* @default `true` (This is a breaking change from
|
|
81
|
+
* @default `true` (This is a breaking change from Wrangler v1)
|
|
82
82
|
* @breaking
|
|
83
83
|
* @inheritable
|
|
84
84
|
*/
|
|
@@ -480,6 +480,13 @@ interface EnvironmentNonInheritable {
|
|
|
480
480
|
[key: string]: unknown;
|
|
481
481
|
}[];
|
|
482
482
|
};
|
|
483
|
+
|
|
484
|
+
mtls_certificates: {
|
|
485
|
+
/** The binding name used to refer to the certificate in the worker */
|
|
486
|
+
binding: string;
|
|
487
|
+
/** The uuid of the uploaded mTLS certificate */
|
|
488
|
+
certificate_id: string;
|
|
489
|
+
}[];
|
|
483
490
|
}
|
|
484
491
|
|
|
485
492
|
/**
|
|
@@ -497,7 +504,7 @@ interface EnvironmentDeprecated {
|
|
|
497
504
|
/**
|
|
498
505
|
* Legacy way of defining KVNamespaces that is no longer supported.
|
|
499
506
|
*
|
|
500
|
-
* @deprecated DO NOT USE. This was a legacy bug from
|
|
507
|
+
* @deprecated DO NOT USE. This was a legacy bug from Wrangler v1, that we do not want to support.
|
|
501
508
|
*/
|
|
502
509
|
"kv-namespaces"?: string;
|
|
503
510
|
|
package/src/config/index.ts
CHANGED
|
@@ -108,6 +108,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
108
108
|
vars,
|
|
109
109
|
wasm_modules,
|
|
110
110
|
dispatch_namespaces,
|
|
111
|
+
mtls_certificates,
|
|
111
112
|
} = bindings;
|
|
112
113
|
|
|
113
114
|
if (data_blobs !== undefined && Object.keys(data_blobs).length > 0) {
|
|
@@ -306,6 +307,18 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
|
|
|
306
307
|
});
|
|
307
308
|
}
|
|
308
309
|
|
|
310
|
+
if (mtls_certificates !== undefined && mtls_certificates.length > 0) {
|
|
311
|
+
output.push({
|
|
312
|
+
type: "mTLS Certificates",
|
|
313
|
+
entries: mtls_certificates.map(({ binding, certificate_id }) => {
|
|
314
|
+
return {
|
|
315
|
+
key: binding,
|
|
316
|
+
value: certificate_id,
|
|
317
|
+
};
|
|
318
|
+
}),
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
309
322
|
if (output.length === 0) {
|
|
310
323
|
return;
|
|
311
324
|
}
|
package/src/config/validation.ts
CHANGED
|
@@ -741,7 +741,7 @@ function isValidRouteValue(item: unknown): boolean {
|
|
|
741
741
|
|
|
742
742
|
/**
|
|
743
743
|
* If account_id has been passed as an empty string, normalise it to undefined.
|
|
744
|
-
* This is to workaround older
|
|
744
|
+
* This is to workaround older Wrangler v1-era templates that have account_id = '',
|
|
745
745
|
* which isn't a valid value anyway
|
|
746
746
|
*/
|
|
747
747
|
function mutateEmptyStringAccountIDValue(
|
|
@@ -760,7 +760,7 @@ function mutateEmptyStringAccountIDValue(
|
|
|
760
760
|
|
|
761
761
|
/**
|
|
762
762
|
* Normalize empty string to `undefined` by mutating rawEnv.route value.
|
|
763
|
-
* As part of backward compatibility with
|
|
763
|
+
* As part of backward compatibility with Wrangler v1 converting empty string to `undefined`
|
|
764
764
|
*/
|
|
765
765
|
function mutateEmptyStringRouteValue(
|
|
766
766
|
diagnostics: Diagnostics,
|
|
@@ -1134,6 +1134,16 @@ function normalizeAndValidateEnvironment(
|
|
|
1134
1134
|
validateBindingArray(envName, validateWorkerNamespaceBinding),
|
|
1135
1135
|
[]
|
|
1136
1136
|
),
|
|
1137
|
+
mtls_certificates: notInheritable(
|
|
1138
|
+
diagnostics,
|
|
1139
|
+
topLevelEnv,
|
|
1140
|
+
rawConfig,
|
|
1141
|
+
rawEnv,
|
|
1142
|
+
envName,
|
|
1143
|
+
"mtls_certificates",
|
|
1144
|
+
validateBindingArray(envName, validateMTlsCertificateBinding),
|
|
1145
|
+
[]
|
|
1146
|
+
),
|
|
1137
1147
|
logfwdr: inheritable(
|
|
1138
1148
|
diagnostics,
|
|
1139
1149
|
topLevelEnv,
|
|
@@ -1590,6 +1600,7 @@ const validateUnsafeBinding: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1590
1600
|
"r2_bucket",
|
|
1591
1601
|
"service",
|
|
1592
1602
|
"logfwdr",
|
|
1603
|
+
"mtls_certificate",
|
|
1593
1604
|
];
|
|
1594
1605
|
|
|
1595
1606
|
if (safeBindings.includes(value.type)) {
|
|
@@ -1823,7 +1834,7 @@ const validateD1Binding: ValidatorFn = (diagnostics, field, value) => {
|
|
|
1823
1834
|
}
|
|
1824
1835
|
if (isValid && !process.env.NO_D1_WARNING) {
|
|
1825
1836
|
diagnostics.warnings.push(
|
|
1826
|
-
"D1 Bindings are currently in alpha to allow the API to evolve before general availability.\nPlease report any issues to https://github.com/cloudflare/
|
|
1837
|
+
"D1 Bindings are currently in alpha to allow the API to evolve before general availability.\nPlease report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose\nNote: Run this command with the environment variable NO_D1_WARNING=true to hide this message\n\nFor example: `export NO_D1_WARNING=true && wrangler <YOUR COMMAND HERE>`"
|
|
1827
1838
|
);
|
|
1828
1839
|
}
|
|
1829
1840
|
return isValid;
|
|
@@ -2036,6 +2047,42 @@ const validateWorkerNamespaceBinding: ValidatorFn = (
|
|
|
2036
2047
|
return isValid;
|
|
2037
2048
|
};
|
|
2038
2049
|
|
|
2050
|
+
const validateMTlsCertificateBinding: ValidatorFn = (
|
|
2051
|
+
diagnostics,
|
|
2052
|
+
field,
|
|
2053
|
+
value
|
|
2054
|
+
) => {
|
|
2055
|
+
if (typeof value !== "object" || value === null) {
|
|
2056
|
+
diagnostics.errors.push(
|
|
2057
|
+
`"mtls_certificates" bindings should be objects, but got ${JSON.stringify(
|
|
2058
|
+
value
|
|
2059
|
+
)}`
|
|
2060
|
+
);
|
|
2061
|
+
return false;
|
|
2062
|
+
}
|
|
2063
|
+
let isValid = true;
|
|
2064
|
+
if (!isRequiredProperty(value, "binding", "string")) {
|
|
2065
|
+
diagnostics.errors.push(
|
|
2066
|
+
`"${field}" bindings should have a string "binding" field but got ${JSON.stringify(
|
|
2067
|
+
value
|
|
2068
|
+
)}.`
|
|
2069
|
+
);
|
|
2070
|
+
isValid = false;
|
|
2071
|
+
}
|
|
2072
|
+
if (
|
|
2073
|
+
!isRequiredProperty(value, "certificate_id", "string") ||
|
|
2074
|
+
(value as { certificate_id: string }).certificate_id.length === 0
|
|
2075
|
+
) {
|
|
2076
|
+
diagnostics.errors.push(
|
|
2077
|
+
`"${field}" bindings should have a string "certificate_id" field but got ${JSON.stringify(
|
|
2078
|
+
value
|
|
2079
|
+
)}.`
|
|
2080
|
+
);
|
|
2081
|
+
isValid = false;
|
|
2082
|
+
}
|
|
2083
|
+
return isValid;
|
|
2084
|
+
};
|
|
2085
|
+
|
|
2039
2086
|
function validateQueues(envName: string): ValidatorFn {
|
|
2040
2087
|
return (diagnostics, field, value, config) => {
|
|
2041
2088
|
const fieldPath =
|
|
@@ -45,6 +45,7 @@ type WorkerMetadataBinding =
|
|
|
45
45
|
| { type: "service"; name: string; service: string; environment?: string }
|
|
46
46
|
| { type: "analytics_engine"; name: string; dataset?: string }
|
|
47
47
|
| { type: "dispatch_namespace"; name: string; namespace: string }
|
|
48
|
+
| { type: "mtls_certificate"; name: string; certificate_id: string }
|
|
48
49
|
| {
|
|
49
50
|
type: "logfwdr";
|
|
50
51
|
name: string;
|
|
@@ -166,6 +167,14 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
|
|
|
166
167
|
});
|
|
167
168
|
});
|
|
168
169
|
|
|
170
|
+
bindings.mtls_certificates?.forEach(({ binding, certificate_id }) => {
|
|
171
|
+
metadataBindings.push({
|
|
172
|
+
name: binding,
|
|
173
|
+
type: "mtls_certificate",
|
|
174
|
+
certificate_id,
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
169
178
|
bindings.logfwdr?.bindings.forEach(({ name, destination }) => {
|
|
170
179
|
metadataBindings.push({
|
|
171
180
|
name: name,
|