wrangler 0.0.13 → 0.0.14
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 +2 -1
- package/src/__tests__/dev.test.tsx +2 -0
- package/src/__tests__/jest.setup.ts +7 -0
- package/src/__tests__/logout.test.ts +64 -0
- package/src/__tests__/publish.test.ts +31 -0
- package/src/__tests__/secret.test.ts +206 -0
- package/src/__tests__/whoami.test.tsx +1 -1
- package/src/dev.tsx +15 -9
- package/src/index.tsx +59 -45
- package/src/inspect.ts +6 -1
- package/src/pages.tsx +1 -0
- package/src/proxy.ts +29 -3
- package/src/publish.ts +3 -3
- package/wrangler-dist/cli.js +88 -56
- package/wrangler-dist/cli.js.map +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wrangler",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"author": "wrangler@cloudflare.com",
|
|
5
5
|
"description": "Command-line interface for all things Cloudflare Workers",
|
|
6
6
|
"bin": {
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"ink-table": "^3.0.0",
|
|
73
73
|
"ink-testing-library": "^2.1.0",
|
|
74
74
|
"ink-text-input": "^4.0.2",
|
|
75
|
+
"jest-fetch-mock": "^3.0.3",
|
|
75
76
|
"mime": "^3.0.0",
|
|
76
77
|
"node-fetch": "3.1.1",
|
|
77
78
|
"open": "^8.4.0",
|
|
@@ -44,6 +44,7 @@ function renderDev({
|
|
|
44
44
|
compatibilityFlags,
|
|
45
45
|
usageModel,
|
|
46
46
|
buildCommand = {},
|
|
47
|
+
enableLocalPersistence = false,
|
|
47
48
|
}: Partial<DevProps>) {
|
|
48
49
|
return render(
|
|
49
50
|
<Dev
|
|
@@ -62,6 +63,7 @@ function renderDev({
|
|
|
62
63
|
compatibilityFlags={compatibilityFlags}
|
|
63
64
|
usageModel={usageModel}
|
|
64
65
|
bindings={bindings}
|
|
66
|
+
enableLocalPersistence={enableLocalPersistence}
|
|
65
67
|
/>
|
|
66
68
|
);
|
|
67
69
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { mockFetchInternal } from "./mock-cfetch";
|
|
2
2
|
import { confirm, prompt } from "../dialogs";
|
|
3
3
|
import { fetchInternal } from "../cfetch/internal";
|
|
4
|
+
import fetchMock from "jest-fetch-mock";
|
|
5
|
+
|
|
6
|
+
jest.mock("node-fetch", () => jest.requireActual("jest-fetch-mock"));
|
|
7
|
+
fetchMock.doMock(() => {
|
|
8
|
+
// Any un-mocked fetches should throw
|
|
9
|
+
throw new Error("Unexpected fetch request");
|
|
10
|
+
});
|
|
4
11
|
|
|
5
12
|
jest.mock("../cfetch/internal");
|
|
6
13
|
(fetchInternal as jest.Mock).mockImplementation(mockFetchInternal);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import fetchMock from "jest-fetch-mock";
|
|
5
|
+
import { runWrangler } from "./run-wrangler";
|
|
6
|
+
import { runInTempDir } from "./run-in-tmp";
|
|
7
|
+
import { initialise } from "../user";
|
|
8
|
+
import { mockConsoleMethods } from "./mock-console";
|
|
9
|
+
import { writeUserConfig } from "./whoami.test";
|
|
10
|
+
|
|
11
|
+
const ORIGINAL_CF_API_TOKEN = process.env.CF_API_TOKEN;
|
|
12
|
+
const ORIGINAL_CF_ACCOUNT_ID = process.env.CF_ACCOUNT_ID;
|
|
13
|
+
|
|
14
|
+
describe("wrangler", () => {
|
|
15
|
+
runInTempDir({ homedir: "./home" });
|
|
16
|
+
const std = mockConsoleMethods();
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
delete process.env.CF_API_TOKEN;
|
|
20
|
+
delete process.env.CF_ACCOUNT_ID;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
// Reset any changes to the environment variables
|
|
25
|
+
process.env.CF_API_TOKEN = ORIGINAL_CF_API_TOKEN;
|
|
26
|
+
process.env.CF_ACCOUNT_ID = ORIGINAL_CF_ACCOUNT_ID;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("logout", () => {
|
|
30
|
+
it("should exit with a message stating the user is not logged in", async () => {
|
|
31
|
+
await initialise();
|
|
32
|
+
await runWrangler("logout");
|
|
33
|
+
expect(std.out).toMatchInlineSnapshot(`"Not logged in, exiting..."`);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should logout user that has been properly logged in", async () => {
|
|
37
|
+
writeUserConfig("some-oauth-tok", "some-refresh-tok");
|
|
38
|
+
|
|
39
|
+
// Mock out the response for a request to revoke the auth tokens,
|
|
40
|
+
// checking the form of the request is as expected.
|
|
41
|
+
fetchMock.mockResponseOnce(async (req) => {
|
|
42
|
+
expect(req.url).toEqual("https://dash.cloudflare.com/oauth2/revoke");
|
|
43
|
+
expect(req.method).toEqual("POST");
|
|
44
|
+
return "";
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
await initialise();
|
|
48
|
+
await runWrangler("logout");
|
|
49
|
+
|
|
50
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
51
|
+
"💁 Wrangler is configured with an OAuth token. The token has been successfully revoked
|
|
52
|
+
Removing ./home/.wrangler/config/default.toml.. success!"
|
|
53
|
+
`);
|
|
54
|
+
|
|
55
|
+
// Make sure that we made the request to logout.
|
|
56
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
57
|
+
|
|
58
|
+
// Make sure that logout removed the config file containing the auth tokens.
|
|
59
|
+
expect(
|
|
60
|
+
existsSync(path.join(os.homedir(), ".wrangler/config/default.toml"))
|
|
61
|
+
).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -748,6 +748,37 @@ describe("publish", () => {
|
|
|
748
748
|
);
|
|
749
749
|
});
|
|
750
750
|
});
|
|
751
|
+
|
|
752
|
+
describe("custom builds", () => {
|
|
753
|
+
it("should run a custom build before publishing", async () => {
|
|
754
|
+
writeWranglerToml({
|
|
755
|
+
build: {
|
|
756
|
+
command: `echo "custom build" && echo "export default { fetch(){ return new Response(123)} }" > index.js`,
|
|
757
|
+
},
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
mockUploadWorkerRequest({
|
|
761
|
+
expectedBody: "return new Response(123)",
|
|
762
|
+
});
|
|
763
|
+
mockSubDomainRequest();
|
|
764
|
+
|
|
765
|
+
await runWrangler("publish index.js");
|
|
766
|
+
expect(stripTimings(std.out)).toMatchInlineSnapshot(`
|
|
767
|
+
"running:
|
|
768
|
+
echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123)} }\\" > index.js
|
|
769
|
+
Uploaded
|
|
770
|
+
test-name
|
|
771
|
+
(TIMINGS)
|
|
772
|
+
Deployed
|
|
773
|
+
test-name
|
|
774
|
+
(TIMINGS)
|
|
775
|
+
|
|
776
|
+
test-name.test-sub-domain.workers.dev"
|
|
777
|
+
`);
|
|
778
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
779
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
751
782
|
});
|
|
752
783
|
|
|
753
784
|
/** Write a mock wrangler.toml file to disk. */
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { setMockResponse, unsetAllMocks } from "./mock-cfetch";
|
|
2
|
+
import { runWrangler } from "./run-wrangler";
|
|
3
|
+
import { runInTempDir } from "./run-in-tmp";
|
|
4
|
+
import { mockConfirm, mockPrompt } from "./mock-dialogs";
|
|
5
|
+
import { mockConsoleMethods } from "./mock-console";
|
|
6
|
+
|
|
7
|
+
describe("wrangler secret", () => {
|
|
8
|
+
const std = mockConsoleMethods();
|
|
9
|
+
runInTempDir();
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
unsetAllMocks();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("put", () => {
|
|
15
|
+
function mockPutRequest(input: { name: string; text: string }) {
|
|
16
|
+
setMockResponse(
|
|
17
|
+
"/accounts/:accountId/workers/scripts/:scriptName/secrets",
|
|
18
|
+
"PUT",
|
|
19
|
+
([_url, accountId], { body }) => {
|
|
20
|
+
expect(accountId).toEqual("some-account-id");
|
|
21
|
+
const { name, text, type } = JSON.parse(body as string);
|
|
22
|
+
expect(type).toEqual("secret_text");
|
|
23
|
+
expect(name).toEqual(input.name);
|
|
24
|
+
expect(text).toEqual(input.text);
|
|
25
|
+
|
|
26
|
+
return { name, type };
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
it("should create a secret", async () => {
|
|
32
|
+
mockPrompt({
|
|
33
|
+
text: "Enter a secret value:",
|
|
34
|
+
type: "password",
|
|
35
|
+
result: "the-secret",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
mockPutRequest({ name: "the-secret-name", text: "the-secret" });
|
|
39
|
+
await runWrangler("secret put the-key --name script-name");
|
|
40
|
+
|
|
41
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
42
|
+
"🌀 Creating the secret for script script-name
|
|
43
|
+
✨ Success! Uploaded secret the-key"
|
|
44
|
+
`);
|
|
45
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should error without a script name", async () => {
|
|
49
|
+
let error: Error | undefined;
|
|
50
|
+
try {
|
|
51
|
+
await runWrangler("secret put the-key");
|
|
52
|
+
} catch (e) {
|
|
53
|
+
error = e;
|
|
54
|
+
}
|
|
55
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
56
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
57
|
+
"Missing script name
|
|
58
|
+
|
|
59
|
+
[32m%s[0m
|
|
60
|
+
If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
|
|
61
|
+
`);
|
|
62
|
+
expect(error).toMatchInlineSnapshot(`[Error: Missing script name]`);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("warns about being a no-op in local mode", async () => {
|
|
66
|
+
mockPrompt({
|
|
67
|
+
text: "Enter a secret value:",
|
|
68
|
+
type: "password",
|
|
69
|
+
result: "the-secret",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
mockPutRequest({ name: "the-secret-name", text: "the-secret" });
|
|
73
|
+
await runWrangler("secret put the-key --name script-name --local");
|
|
74
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
75
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
76
|
+
expect(std.warn).toMatchInlineSnapshot(
|
|
77
|
+
`"\`wrangler secret put\` is a no-op in --local mode"`
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("delete", () => {
|
|
83
|
+
function mockDeleteRequest(input: {
|
|
84
|
+
scriptName: string;
|
|
85
|
+
secretName: string;
|
|
86
|
+
}) {
|
|
87
|
+
setMockResponse(
|
|
88
|
+
"/accounts/:accountId/workers/scripts/:scriptName/secrets/:secretName",
|
|
89
|
+
"DELETE",
|
|
90
|
+
([_url, accountId, scriptName, secretName]) => {
|
|
91
|
+
expect(accountId).toEqual("some-account-id");
|
|
92
|
+
expect(scriptName).toEqual(input.scriptName);
|
|
93
|
+
expect(secretName).toEqual(input.secretName);
|
|
94
|
+
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
it("should delete a secret", async () => {
|
|
100
|
+
mockDeleteRequest({ scriptName: "script-name", secretName: "the-key" });
|
|
101
|
+
mockConfirm({
|
|
102
|
+
text: "Are you sure you want to permanently delete the variable the-key on the script script-name?",
|
|
103
|
+
result: true,
|
|
104
|
+
});
|
|
105
|
+
await runWrangler("secret delete the-key --name script-name");
|
|
106
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
107
|
+
"🌀 Deleting the secret the-key on script script-name.
|
|
108
|
+
✨ Success! Deleted secret the-key"
|
|
109
|
+
`);
|
|
110
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should error without a script name", async () => {
|
|
114
|
+
let error: Error | undefined;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
await runWrangler("secret delete the-key");
|
|
118
|
+
} catch (e) {
|
|
119
|
+
error = e;
|
|
120
|
+
}
|
|
121
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
122
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
123
|
+
"Missing script name
|
|
124
|
+
|
|
125
|
+
[32m%s[0m
|
|
126
|
+
If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
|
|
127
|
+
`);
|
|
128
|
+
expect(error).toMatchInlineSnapshot(`[Error: Missing script name]`);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("warns about being a no-op in local mode", async () => {
|
|
132
|
+
mockConfirm({
|
|
133
|
+
text: "Are you sure you want to permanently delete the variable the-key on the script script-name?",
|
|
134
|
+
result: true,
|
|
135
|
+
});
|
|
136
|
+
await runWrangler("secret delete the-key --name script-name --local");
|
|
137
|
+
expect(std.out).toMatchInlineSnapshot(
|
|
138
|
+
`"🌀 Deleting the secret the-key on script script-name."`
|
|
139
|
+
);
|
|
140
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
141
|
+
expect(std.warn).toMatchInlineSnapshot(
|
|
142
|
+
`"\`wrangler secret delete\` is a no-op in --local mode"`
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("list", () => {
|
|
148
|
+
function mockListRequest(input: { scriptName: string }) {
|
|
149
|
+
setMockResponse(
|
|
150
|
+
"/accounts/:accountId/workers/scripts/:scriptName/secrets",
|
|
151
|
+
"GET",
|
|
152
|
+
([_url, accountId, scriptName]) => {
|
|
153
|
+
expect(accountId).toEqual("some-account-id");
|
|
154
|
+
expect(scriptName).toEqual(input.scriptName);
|
|
155
|
+
|
|
156
|
+
return [
|
|
157
|
+
{
|
|
158
|
+
name: "the-secret-name",
|
|
159
|
+
type: "secret_text",
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
it("should list secrets", async () => {
|
|
167
|
+
mockListRequest({ scriptName: "script-name" });
|
|
168
|
+
await runWrangler("secret list --name script-name");
|
|
169
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
170
|
+
"[
|
|
171
|
+
{
|
|
172
|
+
\\"name\\": \\"the-secret-name\\",
|
|
173
|
+
\\"type\\": \\"secret_text\\"
|
|
174
|
+
}
|
|
175
|
+
]"
|
|
176
|
+
`);
|
|
177
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should error without a script name", async () => {
|
|
181
|
+
let error: Error | undefined;
|
|
182
|
+
try {
|
|
183
|
+
await runWrangler("secret list");
|
|
184
|
+
} catch (e) {
|
|
185
|
+
error = e;
|
|
186
|
+
}
|
|
187
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
188
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
189
|
+
"Missing script name
|
|
190
|
+
|
|
191
|
+
[32m%s[0m
|
|
192
|
+
If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
|
|
193
|
+
`);
|
|
194
|
+
expect(error).toMatchInlineSnapshot(`[Error: Missing script name]`);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("warns about being a no-op in local mode", async () => {
|
|
198
|
+
await runWrangler("secret list --name script-name --local");
|
|
199
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
200
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
201
|
+
expect(std.warn).toMatchInlineSnapshot(
|
|
202
|
+
`"\`wrangler secret list\` is a no-op in --local mode"`
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
package/src/dev.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import { Box, Text, useApp, useInput } from "ink";
|
|
|
8
8
|
import { watch } from "chokidar";
|
|
9
9
|
import clipboardy from "clipboardy";
|
|
10
10
|
import commandExists from "command-exists";
|
|
11
|
-
import {
|
|
11
|
+
import { execaCommand } from "execa";
|
|
12
12
|
import fetch from "node-fetch";
|
|
13
13
|
import open from "open";
|
|
14
14
|
import React, { useState, useEffect, useRef } from "react";
|
|
@@ -40,6 +40,7 @@ export type DevProps = {
|
|
|
40
40
|
initialMode: "local" | "remote";
|
|
41
41
|
jsxFactory: undefined | string;
|
|
42
42
|
jsxFragment: undefined | string;
|
|
43
|
+
enableLocalPersistence: boolean;
|
|
43
44
|
bindings: CfWorkerInit["bindings"];
|
|
44
45
|
public: undefined | string;
|
|
45
46
|
assetPaths: undefined | AssetPaths;
|
|
@@ -102,6 +103,7 @@ function Dev(props: DevProps): JSX.Element {
|
|
|
102
103
|
site={props.assetPaths}
|
|
103
104
|
public={props.public}
|
|
104
105
|
port={port}
|
|
106
|
+
enableLocalPersistence={props.enableLocalPersistence}
|
|
105
107
|
/>
|
|
106
108
|
) : (
|
|
107
109
|
<Remote
|
|
@@ -184,6 +186,7 @@ function Local(props: {
|
|
|
184
186
|
public: undefined | string;
|
|
185
187
|
site: undefined | AssetPaths;
|
|
186
188
|
port: number;
|
|
189
|
+
enableLocalPersistence: boolean;
|
|
187
190
|
}) {
|
|
188
191
|
const { inspectorUrl } = useLocalWorker({
|
|
189
192
|
name: props.name,
|
|
@@ -191,6 +194,7 @@ function Local(props: {
|
|
|
191
194
|
format: props.format,
|
|
192
195
|
bindings: props.bindings,
|
|
193
196
|
port: props.port,
|
|
197
|
+
enableLocalPersistence: props.enableLocalPersistence,
|
|
194
198
|
});
|
|
195
199
|
useInspector({ inspectorUrl, port: 9229, logToTerminal: false });
|
|
196
200
|
return null;
|
|
@@ -202,6 +206,7 @@ function useLocalWorker(props: {
|
|
|
202
206
|
format: CfScriptFormat;
|
|
203
207
|
bindings: CfWorkerInit["bindings"];
|
|
204
208
|
port: number;
|
|
209
|
+
enableLocalPersistence: boolean;
|
|
205
210
|
}) {
|
|
206
211
|
// TODO: pass vars via command line
|
|
207
212
|
const { bundle, format, bindings, port } = props;
|
|
@@ -238,9 +243,9 @@ function useLocalWorker(props: {
|
|
|
238
243
|
path.join(__dirname, "../miniflare-config-stubs/package.empty.json"),
|
|
239
244
|
"--port",
|
|
240
245
|
port.toString(),
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
...(props.enableLocalPersistence
|
|
247
|
+
? ["--kv-persist", "--cache-persist", "--do-persist"]
|
|
248
|
+
: []),
|
|
244
249
|
...Object.entries(bindings.vars || {}).flatMap(([key, value]) => {
|
|
245
250
|
return ["--binding", `${key}=${value}`];
|
|
246
251
|
}),
|
|
@@ -371,20 +376,21 @@ function useCustomBuild(
|
|
|
371
376
|
if (!command) return;
|
|
372
377
|
let cmd, interval;
|
|
373
378
|
console.log("running:", command);
|
|
374
|
-
|
|
375
|
-
cmd = execa(commandPieces[0], commandPieces.slice(1), {
|
|
379
|
+
cmd = execaCommand(command, {
|
|
376
380
|
...(cwd && { cwd }),
|
|
381
|
+
shell: true,
|
|
377
382
|
stderr: "inherit",
|
|
378
383
|
stdout: "inherit",
|
|
379
384
|
});
|
|
380
385
|
if (watch_dir) {
|
|
381
386
|
watch(watch_dir, { persistent: true, ignoreInitial: true }).on(
|
|
382
387
|
"all",
|
|
383
|
-
(_event,
|
|
384
|
-
console.log(`The file ${
|
|
388
|
+
(_event, filePath) => {
|
|
389
|
+
console.log(`The file ${filePath} changed, restarting build...`);
|
|
385
390
|
cmd.kill();
|
|
386
|
-
cmd =
|
|
391
|
+
cmd = execaCommand(command, {
|
|
387
392
|
...(cwd && { cwd }),
|
|
393
|
+
shell: true,
|
|
388
394
|
stderr: "inherit",
|
|
389
395
|
stdout: "inherit",
|
|
390
396
|
});
|
package/src/index.tsx
CHANGED
|
@@ -238,7 +238,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
238
238
|
" "
|
|
239
239
|
) + "\n"
|
|
240
240
|
);
|
|
241
|
-
await execa("npm", ["install"
|
|
241
|
+
await execa("npm", ["install"], {
|
|
242
242
|
stdio: "inherit",
|
|
243
243
|
});
|
|
244
244
|
console.log(`✨ Created package.json`);
|
|
@@ -264,12 +264,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
264
264
|
if (shouldInstall) {
|
|
265
265
|
await execa(
|
|
266
266
|
"npm",
|
|
267
|
-
[
|
|
268
|
-
"install",
|
|
269
|
-
`wrangler@${wranglerVersion}`,
|
|
270
|
-
"--save-dev",
|
|
271
|
-
"--prefer-offline",
|
|
272
|
-
],
|
|
267
|
+
["install", `wrangler@${wranglerVersion}`, "--save-dev"],
|
|
273
268
|
{
|
|
274
269
|
stdio: "inherit",
|
|
275
270
|
}
|
|
@@ -309,12 +304,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
309
304
|
);
|
|
310
305
|
await execa(
|
|
311
306
|
"npm",
|
|
312
|
-
[
|
|
313
|
-
"install",
|
|
314
|
-
"@cloudflare/workers-types",
|
|
315
|
-
"--save-dev",
|
|
316
|
-
"--prefer-offline",
|
|
317
|
-
],
|
|
307
|
+
["install", "@cloudflare/workers-types", "--save-dev"],
|
|
318
308
|
{ stdio: "inherit" }
|
|
319
309
|
);
|
|
320
310
|
console.log(
|
|
@@ -340,12 +330,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
340
330
|
if (shouldInstall) {
|
|
341
331
|
await execa(
|
|
342
332
|
"npm",
|
|
343
|
-
[
|
|
344
|
-
"install",
|
|
345
|
-
"@cloudflare/workers-types",
|
|
346
|
-
"--save-dev",
|
|
347
|
-
"--prefer-offline",
|
|
348
|
-
],
|
|
333
|
+
["install", "@cloudflare/workers-types", "--save-dev"],
|
|
349
334
|
{
|
|
350
335
|
stdio: "inherit",
|
|
351
336
|
}
|
|
@@ -556,6 +541,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
556
541
|
.option("jsx-fragment", {
|
|
557
542
|
describe: "The function that is called for each JSX fragment",
|
|
558
543
|
type: "string",
|
|
544
|
+
})
|
|
545
|
+
.option("experimental-enable-local-persistence", {
|
|
546
|
+
describe: "Enable persistence for this session (only for local mode)",
|
|
547
|
+
type: "boolean",
|
|
559
548
|
});
|
|
560
549
|
},
|
|
561
550
|
async (args) => {
|
|
@@ -623,6 +612,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
623
612
|
initialMode={args.local ? "local" : "remote"}
|
|
624
613
|
jsxFactory={args["jsx-factory"] || envRootObj?.jsx_factory}
|
|
625
614
|
jsxFragment={args["jsx-fragment"] || envRootObj?.jsx_fragment}
|
|
615
|
+
enableLocalPersistence={
|
|
616
|
+
args["experimental-enable-local-persistence"] || false
|
|
617
|
+
}
|
|
626
618
|
accountId={config.account_id}
|
|
627
619
|
assetPaths={getAssetPaths(
|
|
628
620
|
config,
|
|
@@ -1088,11 +1080,6 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1088
1080
|
});
|
|
1089
1081
|
},
|
|
1090
1082
|
async (args) => {
|
|
1091
|
-
if (args.local) {
|
|
1092
|
-
throw new NotImplementedError(
|
|
1093
|
-
"--local not implemented for this command yet"
|
|
1094
|
-
);
|
|
1095
|
-
}
|
|
1096
1083
|
const config = args.config as Config;
|
|
1097
1084
|
|
|
1098
1085
|
// TODO: use environment (how does current wrangler do it?)
|
|
@@ -1101,6 +1088,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1101
1088
|
throw new Error("Missing script name");
|
|
1102
1089
|
}
|
|
1103
1090
|
|
|
1091
|
+
if (args.local) {
|
|
1092
|
+
console.warn("`wrangler secret put` is a no-op in --local mode");
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1104
1095
|
if (!args.local) {
|
|
1105
1096
|
// -- snip, extract --
|
|
1106
1097
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1123,6 +1114,13 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1123
1114
|
"Enter a secret value:",
|
|
1124
1115
|
"password"
|
|
1125
1116
|
);
|
|
1117
|
+
|
|
1118
|
+
if (args.local) {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
console.log(`🌀 Creating the secret for script ${scriptName}`);
|
|
1123
|
+
|
|
1126
1124
|
async function submitSecret() {
|
|
1127
1125
|
return await fetchResult(
|
|
1128
1126
|
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/`,
|
|
@@ -1139,7 +1137,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1139
1137
|
}
|
|
1140
1138
|
|
|
1141
1139
|
try {
|
|
1142
|
-
|
|
1140
|
+
await submitSecret();
|
|
1143
1141
|
} catch (e) {
|
|
1144
1142
|
if (e.code === 10007) {
|
|
1145
1143
|
// upload a draft worker
|
|
@@ -1165,10 +1163,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1165
1163
|
);
|
|
1166
1164
|
|
|
1167
1165
|
// and then try again
|
|
1168
|
-
|
|
1166
|
+
await submitSecret();
|
|
1169
1167
|
// TODO: delete the draft worker if this failed too?
|
|
1170
1168
|
}
|
|
1171
1169
|
}
|
|
1170
|
+
console.log(`✨ Success! Uploaded secret ${args.key}`);
|
|
1172
1171
|
}
|
|
1173
1172
|
)
|
|
1174
1173
|
.command(
|
|
@@ -1191,11 +1190,6 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1191
1190
|
});
|
|
1192
1191
|
},
|
|
1193
1192
|
async (args) => {
|
|
1194
|
-
if (args.local) {
|
|
1195
|
-
throw new NotImplementedError(
|
|
1196
|
-
"--local not implemented for this command yet"
|
|
1197
|
-
);
|
|
1198
|
-
}
|
|
1199
1193
|
const config = args.config as Config;
|
|
1200
1194
|
|
|
1201
1195
|
// TODO: use environment (how does current wrangler do it?)
|
|
@@ -1204,6 +1198,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1204
1198
|
throw new Error("Missing script name");
|
|
1205
1199
|
}
|
|
1206
1200
|
|
|
1201
|
+
if (args.local) {
|
|
1202
|
+
console.warn(
|
|
1203
|
+
"`wrangler secret delete` is a no-op in --local mode"
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
1207
|
if (!args.local) {
|
|
1208
1208
|
// -- snip, extract --
|
|
1209
1209
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1222,17 +1222,24 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1222
1222
|
// -- snip, end --
|
|
1223
1223
|
}
|
|
1224
1224
|
|
|
1225
|
-
if (
|
|
1225
|
+
if (
|
|
1226
|
+
await confirm(
|
|
1227
|
+
`Are you sure you want to permanently delete the variable ${args.key} on the script ${scriptName}?`
|
|
1228
|
+
)
|
|
1229
|
+
) {
|
|
1226
1230
|
console.log(
|
|
1227
|
-
|
|
1231
|
+
`🌀 Deleting the secret ${args.key} on script ${scriptName}.`
|
|
1228
1232
|
);
|
|
1229
1233
|
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1234
|
+
if (args.local) {
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
await fetchResult(
|
|
1239
|
+
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/${args.key}`,
|
|
1240
|
+
{ method: "DELETE" }
|
|
1235
1241
|
);
|
|
1242
|
+
console.log(`✨ Success! Deleted secret ${args.key}`);
|
|
1236
1243
|
}
|
|
1237
1244
|
}
|
|
1238
1245
|
)
|
|
@@ -1252,11 +1259,6 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1252
1259
|
});
|
|
1253
1260
|
},
|
|
1254
1261
|
async (args) => {
|
|
1255
|
-
if (args.local) {
|
|
1256
|
-
throw new NotImplementedError(
|
|
1257
|
-
"--local not implemented for this command yet"
|
|
1258
|
-
);
|
|
1259
|
-
}
|
|
1260
1262
|
const config = args.config as Config;
|
|
1261
1263
|
|
|
1262
1264
|
// TODO: use environment (how does current wrangler do it?)
|
|
@@ -1265,6 +1267,10 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1265
1267
|
throw new Error("Missing script name");
|
|
1266
1268
|
}
|
|
1267
1269
|
|
|
1270
|
+
if (args.local) {
|
|
1271
|
+
console.warn("`wrangler secret list` is a no-op in --local mode");
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1268
1274
|
if (!args.local) {
|
|
1269
1275
|
// -- snip, extract --
|
|
1270
1276
|
const loggedIn = await loginOrRefreshIfRequired();
|
|
@@ -1283,9 +1289,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1283
1289
|
// -- snip, end --
|
|
1284
1290
|
}
|
|
1285
1291
|
|
|
1292
|
+
if (args.local) {
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1286
1296
|
console.log(
|
|
1287
|
-
|
|
1288
|
-
|
|
1297
|
+
JSON.stringify(
|
|
1298
|
+
await fetchResult(
|
|
1299
|
+
`/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets`
|
|
1300
|
+
),
|
|
1301
|
+
null,
|
|
1302
|
+
" "
|
|
1289
1303
|
)
|
|
1290
1304
|
);
|
|
1291
1305
|
}
|