wrangler 2.1.3 → 2.1.4
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 +1 -1
- package/src/__tests__/api-dev.test.ts +170 -0
- package/src/__tests__/api.test.ts +80 -0
- package/src/__tests__/init.test.ts +127 -3
- package/src/__tests__/secret.test.ts +76 -2
- package/src/api/dev.ts +57 -12
- package/src/api/index.ts +1 -0
- package/src/cli.ts +2 -0
- package/src/create-worker-preview.ts +21 -3
- package/src/index.tsx +11 -2
- package/src/init.ts +189 -121
- package/templates/init-tests/test-jest-new-worker.js +25 -0
- package/templates/init-tests/test-vitest-new-worker.js +26 -0
- package/wrangler-dist/cli.d.ts +62 -3
- package/wrangler-dist/cli.js +241 -130
package/package.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { Request } from "undici";
|
|
1
3
|
import { unstable_dev } from "../api";
|
|
4
|
+
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
2
5
|
|
|
3
6
|
jest.unmock("undici");
|
|
4
7
|
|
|
@@ -17,3 +20,170 @@ describe("unstable_dev", () => {
|
|
|
17
20
|
await worker.stop();
|
|
18
21
|
});
|
|
19
22
|
});
|
|
23
|
+
|
|
24
|
+
describe("unstable dev fetch input protocol", () => {
|
|
25
|
+
it("should use http localProtocol", async () => {
|
|
26
|
+
const worker = await unstable_dev(
|
|
27
|
+
"src/__tests__/helpers/hello-world-worker.js",
|
|
28
|
+
{ localProtocol: "http" },
|
|
29
|
+
{ disableExperimentalWarning: true }
|
|
30
|
+
);
|
|
31
|
+
const res = await worker.fetch();
|
|
32
|
+
if (res) {
|
|
33
|
+
const text = await res.text();
|
|
34
|
+
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
|
|
35
|
+
}
|
|
36
|
+
await worker.stop();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should use undefined localProtocol", async () => {
|
|
40
|
+
const worker = await unstable_dev(
|
|
41
|
+
"src/__tests__/helpers/hello-world-worker.js",
|
|
42
|
+
{ localProtocol: undefined },
|
|
43
|
+
{ disableExperimentalWarning: true }
|
|
44
|
+
);
|
|
45
|
+
const res = await worker.fetch();
|
|
46
|
+
if (res) {
|
|
47
|
+
const text = await res.text();
|
|
48
|
+
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
|
|
49
|
+
}
|
|
50
|
+
await worker.stop();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe("unstable dev fetch input parsing", () => {
|
|
55
|
+
runInTempDir();
|
|
56
|
+
|
|
57
|
+
it("should pass in a request object unchanged", async () => {
|
|
58
|
+
const scriptContent = `
|
|
59
|
+
export default {
|
|
60
|
+
fetch(request, env, ctx) {
|
|
61
|
+
const url = new URL(request.url);
|
|
62
|
+
if (url.pathname === "/test") {
|
|
63
|
+
if (request.method === "POST") {
|
|
64
|
+
return new Response("requestPOST");
|
|
65
|
+
}
|
|
66
|
+
return new Response("requestGET");
|
|
67
|
+
}
|
|
68
|
+
return new Response('Hello world');
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
`;
|
|
72
|
+
fs.writeFileSync("index.js", scriptContent);
|
|
73
|
+
const port = 21213;
|
|
74
|
+
const worker = await unstable_dev(
|
|
75
|
+
"index.js",
|
|
76
|
+
{ port },
|
|
77
|
+
{ disableExperimentalWarning: true }
|
|
78
|
+
);
|
|
79
|
+
const req = new Request("http://0.0.0.0:21213/test", {
|
|
80
|
+
method: "POST",
|
|
81
|
+
});
|
|
82
|
+
const resp = await worker.fetch(req);
|
|
83
|
+
let text;
|
|
84
|
+
if (resp) text = await resp.text();
|
|
85
|
+
expect(text).toMatchInlineSnapshot(`"requestPOST"`);
|
|
86
|
+
await worker.stop();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("should strip back to pathname for URL objects", async () => {
|
|
90
|
+
const scriptContent = `
|
|
91
|
+
export default {
|
|
92
|
+
fetch(request, env, ctx) {
|
|
93
|
+
const url = new URL(request.url);
|
|
94
|
+
if (url.pathname === "/test") {
|
|
95
|
+
return new Response("request");
|
|
96
|
+
}
|
|
97
|
+
return new Response('Hello world');
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
`;
|
|
101
|
+
fs.writeFileSync("index.js", scriptContent);
|
|
102
|
+
const worker = await unstable_dev(
|
|
103
|
+
"index.js",
|
|
104
|
+
{},
|
|
105
|
+
{ disableExperimentalWarning: true }
|
|
106
|
+
);
|
|
107
|
+
const url = new URL("http://localhost:80/test");
|
|
108
|
+
const resp = await worker.fetch(url);
|
|
109
|
+
let text;
|
|
110
|
+
if (resp) text = await resp.text();
|
|
111
|
+
expect(text).toMatchInlineSnapshot(`"request"`);
|
|
112
|
+
await worker.stop();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("should allow full url passed in string, and stripped back to pathname", async () => {
|
|
116
|
+
const scriptContent = `
|
|
117
|
+
export default {
|
|
118
|
+
fetch(request, env, ctx) {
|
|
119
|
+
const url = new URL(request.url);
|
|
120
|
+
if (url.pathname === "/test") {
|
|
121
|
+
return new Response("request");
|
|
122
|
+
}
|
|
123
|
+
return new Response('Hello world');
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
`;
|
|
127
|
+
fs.writeFileSync("index.js", scriptContent);
|
|
128
|
+
const worker = await unstable_dev(
|
|
129
|
+
"index.js",
|
|
130
|
+
{},
|
|
131
|
+
{ disableExperimentalWarning: true }
|
|
132
|
+
);
|
|
133
|
+
const resp = await worker.fetch("http://example.com/test");
|
|
134
|
+
let text;
|
|
135
|
+
if (resp) text = await resp.text();
|
|
136
|
+
expect(text).toMatchInlineSnapshot(`"request"`);
|
|
137
|
+
await worker.stop();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("should allow pathname to be passed in", async () => {
|
|
141
|
+
const scriptContent = `
|
|
142
|
+
export default {
|
|
143
|
+
fetch(request, env, ctx) {
|
|
144
|
+
const url = new URL(request.url);
|
|
145
|
+
if (url.pathname === "/test") {
|
|
146
|
+
return new Response("request");
|
|
147
|
+
}
|
|
148
|
+
return new Response('Hello world');
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
`;
|
|
152
|
+
fs.writeFileSync("index.js", scriptContent);
|
|
153
|
+
const worker = await unstable_dev(
|
|
154
|
+
"index.js",
|
|
155
|
+
{},
|
|
156
|
+
{ disableExperimentalWarning: true }
|
|
157
|
+
);
|
|
158
|
+
const resp = await worker.fetch("/test");
|
|
159
|
+
let text;
|
|
160
|
+
if (resp) text = await resp.text();
|
|
161
|
+
expect(text).toMatchInlineSnapshot(`"request"`);
|
|
162
|
+
await worker.stop();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("should allow no input be passed in", async () => {
|
|
166
|
+
const scriptContent = `
|
|
167
|
+
export default {
|
|
168
|
+
fetch(request, env, ctx) {
|
|
169
|
+
const url = new URL(request.url);
|
|
170
|
+
if (url.pathname === "/test") {
|
|
171
|
+
return new Response("request");
|
|
172
|
+
}
|
|
173
|
+
return new Response('Hello world');
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
`;
|
|
177
|
+
fs.writeFileSync("index.js", scriptContent);
|
|
178
|
+
const worker = await unstable_dev(
|
|
179
|
+
"index.js",
|
|
180
|
+
{},
|
|
181
|
+
{ disableExperimentalWarning: true }
|
|
182
|
+
);
|
|
183
|
+
const resp = await worker.fetch("");
|
|
184
|
+
let text;
|
|
185
|
+
if (resp) text = await resp.text();
|
|
186
|
+
expect(text).toMatchInlineSnapshot(`"Hello world"`);
|
|
187
|
+
await worker.stop();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Request } from "undici";
|
|
2
|
+
import { parseRequestInput } from "../api/dev";
|
|
3
|
+
|
|
4
|
+
describe("parseRequestInput for fetch on unstable dev", () => {
|
|
5
|
+
it("should allow no input to be passed in", () => {
|
|
6
|
+
const [input, _] = parseRequestInput("0.0.0.0", 8080);
|
|
7
|
+
|
|
8
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080"`);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should allow string of pathname to be passed in", () => {
|
|
12
|
+
const [input, _] = parseRequestInput("0.0.0.0", 8080, "/test");
|
|
13
|
+
|
|
14
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080/test"`);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should allow full url to be passed in as string and stripped", () => {
|
|
18
|
+
const [input, _] = parseRequestInput(
|
|
19
|
+
"0.0.0.0",
|
|
20
|
+
8080,
|
|
21
|
+
"http://cloudflare.com/test"
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080/test"`);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should allow URL object without pathname to be passed in and stripped", () => {
|
|
28
|
+
const [input, _] = parseRequestInput(
|
|
29
|
+
"0.0.0.0",
|
|
30
|
+
8080,
|
|
31
|
+
new URL("http://cloudflare.com")
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080/"`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should allow URL object with pathname to be passed in and stripped", () => {
|
|
38
|
+
const [input, _] = parseRequestInput(
|
|
39
|
+
"0.0.0.0",
|
|
40
|
+
8080,
|
|
41
|
+
new URL("http://cloudflare.com/test")
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080/test"`);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should allow request object to be passed in", () => {
|
|
48
|
+
const [input, init] = parseRequestInput(
|
|
49
|
+
"0.0.0.0",
|
|
50
|
+
8080,
|
|
51
|
+
new Request("http://cloudflare.com/test", { method: "POST" })
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(init).toBeUndefined();
|
|
55
|
+
expect(input).toBeInstanceOf(Request);
|
|
56
|
+
// We don't expect the request to be modified
|
|
57
|
+
expect((input as Request).url).toMatchInlineSnapshot(
|
|
58
|
+
`"http://cloudflare.com/test"`
|
|
59
|
+
);
|
|
60
|
+
expect((input as Request).method).toMatchInlineSnapshot(`"POST"`);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("should parse to give https url with localProtocol = https", () => {
|
|
64
|
+
const [input, _] = parseRequestInput("0.0.0.0", 8080, "/test", {}, "https");
|
|
65
|
+
|
|
66
|
+
expect(input).toMatchInlineSnapshot(`"https://0.0.0.0:8080/test"`);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should parse to give http url with localProtocol = http", () => {
|
|
70
|
+
const [input, _] = parseRequestInput("0.0.0.0", 8080, "/test", {}, "http");
|
|
71
|
+
|
|
72
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080/test"`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should parse to give http url with localProtocol not set", () => {
|
|
76
|
+
const [input, _] = parseRequestInput("0.0.0.0", 8080, "/test", {});
|
|
77
|
+
|
|
78
|
+
expect(input).toMatchInlineSnapshot(`"http://0.0.0.0:8080/test"`);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -982,7 +982,8 @@ describe("init", () => {
|
|
|
982
982
|
{
|
|
983
983
|
text: "Would you like to use TypeScript?",
|
|
984
984
|
result: false,
|
|
985
|
-
}
|
|
985
|
+
},
|
|
986
|
+
{ text: "Would you like us to write your first test?", result: false }
|
|
986
987
|
);
|
|
987
988
|
mockSelect({
|
|
988
989
|
text: "Would you like to create a Worker at src/index.js?",
|
|
@@ -1562,7 +1563,8 @@ describe("init", () => {
|
|
|
1562
1563
|
{
|
|
1563
1564
|
text: "Would you like to use TypeScript?",
|
|
1564
1565
|
result: false,
|
|
1565
|
-
}
|
|
1566
|
+
},
|
|
1567
|
+
{ text: "Would you like us to write your first test?", result: false }
|
|
1566
1568
|
);
|
|
1567
1569
|
mockSelect({
|
|
1568
1570
|
text: "Would you like to create a Worker at src/index.js?",
|
|
@@ -1596,6 +1598,127 @@ describe("init", () => {
|
|
|
1596
1598
|
To publish your Worker to the Internet, run \`npm run deploy\`"
|
|
1597
1599
|
`);
|
|
1598
1600
|
});
|
|
1601
|
+
it("should add a jest test for a non-ts project with .js extension", async () => {
|
|
1602
|
+
mockConfirm(
|
|
1603
|
+
{
|
|
1604
|
+
text: "Would you like to use git to manage this Worker?",
|
|
1605
|
+
result: false,
|
|
1606
|
+
},
|
|
1607
|
+
{
|
|
1608
|
+
text: "No package.json found. Would you like to create one?",
|
|
1609
|
+
result: true,
|
|
1610
|
+
},
|
|
1611
|
+
{
|
|
1612
|
+
text: "Would you like to install wrangler into package.json?",
|
|
1613
|
+
result: false,
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
text: "Would you like to use TypeScript?",
|
|
1617
|
+
result: false,
|
|
1618
|
+
},
|
|
1619
|
+
{ text: "Would you like us to write your first test?", result: true }
|
|
1620
|
+
);
|
|
1621
|
+
mockSelect(
|
|
1622
|
+
{
|
|
1623
|
+
text: "Would you like to create a Worker at src/index.js?",
|
|
1624
|
+
result: "fetch",
|
|
1625
|
+
},
|
|
1626
|
+
{ text: "Which test runner would you like to use?", result: "jest" }
|
|
1627
|
+
);
|
|
1628
|
+
|
|
1629
|
+
await runWrangler("init");
|
|
1630
|
+
|
|
1631
|
+
checkFiles({
|
|
1632
|
+
items: {
|
|
1633
|
+
"src/index.js": true,
|
|
1634
|
+
"src/index.test.js": true,
|
|
1635
|
+
"src/index.ts": false,
|
|
1636
|
+
"package.json": {
|
|
1637
|
+
contents: expect.objectContaining({
|
|
1638
|
+
name: expect.stringContaining("wrangler-tests"),
|
|
1639
|
+
version: "0.0.0",
|
|
1640
|
+
scripts: {
|
|
1641
|
+
start: "wrangler dev",
|
|
1642
|
+
deploy: "wrangler publish",
|
|
1643
|
+
test: "jest",
|
|
1644
|
+
},
|
|
1645
|
+
}),
|
|
1646
|
+
},
|
|
1647
|
+
},
|
|
1648
|
+
});
|
|
1649
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
1650
|
+
"✨ Created wrangler.toml
|
|
1651
|
+
✨ Created package.json
|
|
1652
|
+
✨ Created src/index.js
|
|
1653
|
+
✨ Created src/index.test.js
|
|
1654
|
+
✨ Installed jest into devDependencies
|
|
1655
|
+
|
|
1656
|
+
To start developing your Worker, run \`npm start\`
|
|
1657
|
+
To start testing your Worker, run \`npm test\`
|
|
1658
|
+
To publish your Worker to the Internet, run \`npm run deploy\`"
|
|
1659
|
+
`);
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1662
|
+
it("should add a vitest test for a non-ts project with .js extension", async () => {
|
|
1663
|
+
mockConfirm(
|
|
1664
|
+
{
|
|
1665
|
+
text: "Would you like to use git to manage this Worker?",
|
|
1666
|
+
result: false,
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
text: "No package.json found. Would you like to create one?",
|
|
1670
|
+
result: true,
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
text: "Would you like to install wrangler into package.json?",
|
|
1674
|
+
result: false,
|
|
1675
|
+
},
|
|
1676
|
+
{
|
|
1677
|
+
text: "Would you like to use TypeScript?",
|
|
1678
|
+
result: false,
|
|
1679
|
+
},
|
|
1680
|
+
{ text: "Would you like us to write your first test?", result: true }
|
|
1681
|
+
);
|
|
1682
|
+
mockSelect(
|
|
1683
|
+
{
|
|
1684
|
+
text: "Would you like to create a Worker at src/index.js?",
|
|
1685
|
+
result: "fetch",
|
|
1686
|
+
},
|
|
1687
|
+
{ text: "Which test runner would you like to use?", result: "vitest" }
|
|
1688
|
+
);
|
|
1689
|
+
|
|
1690
|
+
await runWrangler("init");
|
|
1691
|
+
|
|
1692
|
+
checkFiles({
|
|
1693
|
+
items: {
|
|
1694
|
+
"src/index.js": true,
|
|
1695
|
+
"src/index.test.js": true,
|
|
1696
|
+
"src/index.ts": false,
|
|
1697
|
+
"package.json": {
|
|
1698
|
+
contents: expect.objectContaining({
|
|
1699
|
+
name: expect.stringContaining("wrangler-tests"),
|
|
1700
|
+
version: "0.0.0",
|
|
1701
|
+
scripts: {
|
|
1702
|
+
start: "wrangler dev",
|
|
1703
|
+
deploy: "wrangler publish",
|
|
1704
|
+
test: "vitest",
|
|
1705
|
+
},
|
|
1706
|
+
}),
|
|
1707
|
+
},
|
|
1708
|
+
},
|
|
1709
|
+
});
|
|
1710
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
1711
|
+
"✨ Created wrangler.toml
|
|
1712
|
+
✨ Created package.json
|
|
1713
|
+
✨ Created src/index.js
|
|
1714
|
+
✨ Created src/index.test.js
|
|
1715
|
+
✨ Installed vitest into devDependencies
|
|
1716
|
+
|
|
1717
|
+
To start developing your Worker, run \`npm start\`
|
|
1718
|
+
To start testing your Worker, run \`npm test\`
|
|
1719
|
+
To publish your Worker to the Internet, run \`npm run deploy\`"
|
|
1720
|
+
`);
|
|
1721
|
+
});
|
|
1599
1722
|
|
|
1600
1723
|
it("should not overwrite package.json scripts for a non-ts project with .js extension", async () => {
|
|
1601
1724
|
mockConfirm(
|
|
@@ -1610,7 +1733,8 @@ describe("init", () => {
|
|
|
1610
1733
|
{
|
|
1611
1734
|
text: "Would you like to use TypeScript?",
|
|
1612
1735
|
result: false,
|
|
1613
|
-
}
|
|
1736
|
+
},
|
|
1737
|
+
{ text: "Would you like us to write your first test?", result: false }
|
|
1614
1738
|
);
|
|
1615
1739
|
mockSelect({
|
|
1616
1740
|
text: "Would you like to create a Worker at src/index.js?",
|
|
@@ -124,7 +124,9 @@ describe("wrangler secret", () => {
|
|
|
124
124
|
"🌀 Creating the secrets for the Worker \\"script-name\\"
|
|
125
125
|
✨ Successfully created secret for key: secret-name-1
|
|
126
126
|
✨ Successfully created secret for key: secret-name-2
|
|
127
|
-
|
|
127
|
+
|
|
128
|
+
Finished processing secrets JSON file:
|
|
129
|
+
✨ 2 secrets successfully uploaded"
|
|
128
130
|
`);
|
|
129
131
|
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
130
132
|
});
|
|
@@ -157,7 +159,10 @@ describe("wrangler secret", () => {
|
|
|
157
159
|
|
|
158
160
|
expect(std.out).toMatchInlineSnapshot(`
|
|
159
161
|
"🌀 Creating the secrets for the Worker \\"script-name\\"
|
|
160
|
-
|
|
162
|
+
|
|
163
|
+
Finished processing secrets JSON file:
|
|
164
|
+
✨ 0 secrets successfully uploaded
|
|
165
|
+
🚨 2 secrets failed to upload"
|
|
161
166
|
`);
|
|
162
167
|
expect(std.err).toMatchInlineSnapshot(`
|
|
163
168
|
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-1:[0m
|
|
@@ -173,6 +178,75 @@ describe("wrangler secret", () => {
|
|
|
173
178
|
`);
|
|
174
179
|
});
|
|
175
180
|
|
|
181
|
+
it("should count success and failed secret:bulk", async () => {
|
|
182
|
+
writeFileSync(
|
|
183
|
+
"secret.json",
|
|
184
|
+
JSON.stringify({
|
|
185
|
+
"secret-name-1": "secret_text",
|
|
186
|
+
"secret-name-2": "secret_text",
|
|
187
|
+
"secret-name-3": "secret_text",
|
|
188
|
+
"secret-name-4": "secret_text",
|
|
189
|
+
"secret-name-5": "secret_text",
|
|
190
|
+
"secret-name-6": "secret_text",
|
|
191
|
+
"secret-name-7": "secret_text",
|
|
192
|
+
})
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
// User counter to pass different secrets to the request mock
|
|
196
|
+
let counter = 0;
|
|
197
|
+
setMockResponse(
|
|
198
|
+
`/accounts/:accountId/workers/scripts/:scriptName/secrets`,
|
|
199
|
+
"PUT",
|
|
200
|
+
([_url, accountId]) => {
|
|
201
|
+
expect(accountId).toEqual("some-account-id");
|
|
202
|
+
counter++;
|
|
203
|
+
|
|
204
|
+
if (counter % 2 === 0) {
|
|
205
|
+
return { name: `secret-name-${counter}`, type: "secret_text" };
|
|
206
|
+
} else {
|
|
207
|
+
return Promise.reject(
|
|
208
|
+
new Error(`Failed to create secret ${counter}`)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
await runWrangler("secret:bulk ./secret.json --name script-name");
|
|
215
|
+
|
|
216
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
217
|
+
"🌀 Creating the secrets for the Worker \\"script-name\\"
|
|
218
|
+
✨ Successfully created secret for key: secret-name-2
|
|
219
|
+
✨ Successfully created secret for key: secret-name-4
|
|
220
|
+
✨ Successfully created secret for key: secret-name-6
|
|
221
|
+
|
|
222
|
+
Finished processing secrets JSON file:
|
|
223
|
+
✨ 3 secrets successfully uploaded
|
|
224
|
+
🚨 4 secrets failed to upload"
|
|
225
|
+
`);
|
|
226
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
227
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-1:[0m
|
|
228
|
+
|
|
229
|
+
Failed to create secret 1
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-3:[0m
|
|
233
|
+
|
|
234
|
+
Failed to create secret 3
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-5:[0m
|
|
238
|
+
|
|
239
|
+
Failed to create secret 5
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
[31mX [41;31m[[41;97mERROR[41;31m][0m [1m🚨 Error uploading secret for key: secret-name-7:[0m
|
|
243
|
+
|
|
244
|
+
Failed to create secret 7
|
|
245
|
+
|
|
246
|
+
"
|
|
247
|
+
`);
|
|
248
|
+
});
|
|
249
|
+
|
|
176
250
|
it("should create a secret: legacy envs", async () => {
|
|
177
251
|
mockPrompt({
|
|
178
252
|
text: "Enter a secret value:",
|
package/src/api/dev.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { fetch } from "undici";
|
|
1
|
+
import { fetch, Request } from "undici";
|
|
2
2
|
import { startApiDev, startDev } from "../dev";
|
|
3
3
|
import { logger } from "../logger";
|
|
4
4
|
|
|
5
5
|
import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
|
|
6
|
-
import type { RequestInit, Response } from "undici";
|
|
6
|
+
import type { RequestInit, Response, RequestInfo } from "undici";
|
|
7
7
|
|
|
8
8
|
interface DevOptions {
|
|
9
9
|
config?: string;
|
|
@@ -57,9 +57,12 @@ interface DevApiOptions {
|
|
|
57
57
|
disableExperimentalWarning?: boolean;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
interface
|
|
60
|
+
export interface UnstableDevWorker {
|
|
61
61
|
stop: () => Promise<void>;
|
|
62
|
-
fetch: (
|
|
62
|
+
fetch: (
|
|
63
|
+
input?: RequestInfo,
|
|
64
|
+
init?: RequestInit
|
|
65
|
+
) => Promise<Response | undefined>;
|
|
63
66
|
waitUntilExit: () => Promise<void>;
|
|
64
67
|
}
|
|
65
68
|
/**
|
|
@@ -86,7 +89,7 @@ export async function unstable_dev(
|
|
|
86
89
|
//due to Pages adoption of unstable_dev, we can't *just* disable rebuilds and watching. instead, we'll have two versions of startDev, which will converge.
|
|
87
90
|
if (testMode) {
|
|
88
91
|
//in testMode, we can run multiple wranglers in parallel, but rebuilds might not work out of the box
|
|
89
|
-
return new Promise<
|
|
92
|
+
return new Promise<UnstableDevWorker>((resolve) => {
|
|
90
93
|
//lmao
|
|
91
94
|
return new Promise<Awaited<ReturnType<typeof startApiDev>>>((ready) => {
|
|
92
95
|
// once the devServer is ready for requests, we resolve the inner promise
|
|
@@ -112,9 +115,16 @@ export async function unstable_dev(
|
|
|
112
115
|
// with an object that lets you fetch and stop the dev server
|
|
113
116
|
resolve({
|
|
114
117
|
stop: devServer.stop,
|
|
115
|
-
fetch: async (init?: RequestInit) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
fetch: async (input?: RequestInfo, init?: RequestInit) => {
|
|
119
|
+
return await fetch(
|
|
120
|
+
...parseRequestInput(
|
|
121
|
+
readyAddress,
|
|
122
|
+
readyPort,
|
|
123
|
+
input,
|
|
124
|
+
init,
|
|
125
|
+
options?.localProtocol
|
|
126
|
+
)
|
|
127
|
+
);
|
|
118
128
|
},
|
|
119
129
|
//no-op, does nothing in tests
|
|
120
130
|
waitUntilExit: async () => {
|
|
@@ -126,7 +136,7 @@ export async function unstable_dev(
|
|
|
126
136
|
} else {
|
|
127
137
|
//outside of test mode, rebuilds work fine, but only one instance of wrangler will work at a time
|
|
128
138
|
|
|
129
|
-
return new Promise<
|
|
139
|
+
return new Promise<UnstableDevWorker>((resolve) => {
|
|
130
140
|
//lmao
|
|
131
141
|
return new Promise<Awaited<ReturnType<typeof startDev>>>((ready) => {
|
|
132
142
|
const devServer = startDev({
|
|
@@ -147,9 +157,16 @@ export async function unstable_dev(
|
|
|
147
157
|
}).then((devServer) => {
|
|
148
158
|
resolve({
|
|
149
159
|
stop: devServer.stop,
|
|
150
|
-
fetch: async (init?: RequestInit) => {
|
|
151
|
-
|
|
152
|
-
|
|
160
|
+
fetch: async (input?: RequestInfo, init?: RequestInit) => {
|
|
161
|
+
return await fetch(
|
|
162
|
+
...parseRequestInput(
|
|
163
|
+
readyAddress,
|
|
164
|
+
readyPort,
|
|
165
|
+
input,
|
|
166
|
+
init,
|
|
167
|
+
options?.localProtocol
|
|
168
|
+
)
|
|
169
|
+
);
|
|
153
170
|
},
|
|
154
171
|
waitUntilExit: devServer.devReactElement.waitUntilExit,
|
|
155
172
|
});
|
|
@@ -157,3 +174,31 @@ export async function unstable_dev(
|
|
|
157
174
|
});
|
|
158
175
|
}
|
|
159
176
|
}
|
|
177
|
+
|
|
178
|
+
export function parseRequestInput(
|
|
179
|
+
readyAddress: string,
|
|
180
|
+
readyPort: number,
|
|
181
|
+
input?: RequestInfo,
|
|
182
|
+
init?: RequestInit,
|
|
183
|
+
protocol: "http" | "https" = "http"
|
|
184
|
+
): [RequestInfo, RequestInit | undefined] {
|
|
185
|
+
if (input instanceof Request) {
|
|
186
|
+
return [input, undefined];
|
|
187
|
+
} else if (input instanceof URL) {
|
|
188
|
+
input = `${protocol}://${readyAddress}:${readyPort}${input.pathname}`;
|
|
189
|
+
} else if (typeof input === "string") {
|
|
190
|
+
try {
|
|
191
|
+
// Want to strip the URL to only get the pathname, but the user could pass in only the pathname
|
|
192
|
+
// Will error if we try and pass "/something" into new URL("/something")
|
|
193
|
+
input = `${protocol}://${readyAddress}:${readyPort}${
|
|
194
|
+
new URL(input).pathname
|
|
195
|
+
}`;
|
|
196
|
+
} catch {
|
|
197
|
+
input = `${protocol}://${readyAddress}:${readyPort}${input}`;
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
input = `${protocol}://${readyAddress}:${readyPort}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return [input, init];
|
|
204
|
+
}
|
package/src/api/index.ts
CHANGED
package/src/cli.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { unstable_dev } from "./api";
|
|
|
5
5
|
import { FatalError } from "./errors";
|
|
6
6
|
import { main } from ".";
|
|
7
7
|
|
|
8
|
+
import type { UnstableDevWorker } from "./api";
|
|
8
9
|
/**
|
|
9
10
|
* The main entrypoint for the CLI.
|
|
10
11
|
* main only gets called when the script is run directly, not when it's imported as a module.
|
|
@@ -25,3 +26,4 @@ if (typeof jest === "undefined" && require.main) {
|
|
|
25
26
|
* and call wrangler.unstable_dev().
|
|
26
27
|
*/
|
|
27
28
|
export { unstable_dev };
|
|
29
|
+
export type { UnstableDevWorker };
|
|
@@ -3,6 +3,7 @@ import { fetch } from "undici";
|
|
|
3
3
|
import { fetchResult } from "./cfetch";
|
|
4
4
|
import { createWorkerUploadForm } from "./create-worker-upload-form";
|
|
5
5
|
import { logger } from "./logger";
|
|
6
|
+
import { parseJSON } from "./parse";
|
|
6
7
|
import type { CfAccount, CfWorkerContext, CfWorkerInit } from "./worker";
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -125,9 +126,26 @@ export async function createPreviewSession(
|
|
|
125
126
|
undefined,
|
|
126
127
|
abortSignal
|
|
127
128
|
);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
|
|
130
|
+
logger.debug(`-- START EXCHANGE API REQUEST: GET ${exchange_url}`);
|
|
131
|
+
logger.debug("-- END EXCHANGE API REQUEST");
|
|
132
|
+
const exchangeResponse = await fetch(exchange_url, { signal: abortSignal });
|
|
133
|
+
const bodyText = await exchangeResponse.text();
|
|
134
|
+
logger.debug(
|
|
135
|
+
"-- START EXCHANGE API RESPONSE:",
|
|
136
|
+
exchangeResponse.statusText,
|
|
137
|
+
exchangeResponse.status
|
|
138
|
+
);
|
|
139
|
+
logger.debug("HEADERS:", JSON.stringify(exchangeResponse.headers, null, 2));
|
|
140
|
+
logger.debug("RESPONSE:", bodyText);
|
|
141
|
+
logger.debug("-- END EXCHANGE API RESPONSE");
|
|
142
|
+
|
|
143
|
+
const { inspector_websocket, prewarm, token } = parseJSON<{
|
|
144
|
+
inspector_websocket: string;
|
|
145
|
+
token: string;
|
|
146
|
+
prewarm: string;
|
|
147
|
+
}>(bodyText);
|
|
148
|
+
|
|
131
149
|
const { host } = new URL(inspector_websocket);
|
|
132
150
|
const query = `cf_workers_preview_token=${token}`;
|
|
133
151
|
|