wrangler 0.0.21 → 0.0.24
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 +1 -1
- package/bin/wrangler.js +10 -1
- package/miniflare-dist/index.mjs +79 -0
- package/miniflare-dist/index.mjs.map +7 -0
- package/package.json +3 -4
- package/src/__tests__/configuration.test.ts +522 -300
- package/src/__tests__/dev.test.tsx +99 -3
- package/src/__tests__/guess-worker-format.test.ts +10 -0
- package/src/__tests__/index.test.ts +3 -11
- package/src/__tests__/kv.test.ts +16 -18
- package/src/__tests__/pages.test.ts +48 -10
- package/src/__tests__/publish.test.ts +1319 -421
- package/src/__tests__/r2.test.ts +4 -4
- package/src/__tests__/tail.test.ts +29 -4
- package/src/bundle.ts +15 -2
- package/src/config/README.md +6 -6
- package/src/config/config.ts +16 -77
- package/src/config/environment.ts +67 -1
- package/src/config/index.ts +13 -3
- package/src/config/validation-helpers.ts +105 -19
- package/src/config/validation.ts +272 -97
- package/src/dev/dev.tsx +72 -42
- package/src/dev/local.tsx +103 -118
- package/src/dev/use-esbuild.ts +4 -0
- package/src/entry.ts +84 -3
- package/src/index.tsx +137 -113
- package/src/intl-polyfill.d.ts +139 -0
- package/src/kv.ts +7 -27
- package/src/miniflare-cli/README.md +30 -0
- package/src/miniflare-cli/enum-keys.ts +17 -0
- package/src/miniflare-cli/index.ts +37 -0
- package/src/module-collection.ts +58 -53
- package/src/pages.tsx +26 -10
- package/src/publish.ts +17 -21
- package/src/sites.tsx +59 -52
- package/src/tail/printing.ts +2 -2
- package/src/user.tsx +12 -3
- package/wrangler-dist/cli.js +836 -649
- package/wrangler-dist/cli.js.map +2 -2
- package/src/__tests__/dev2.test.tsx +0 -154
package/src/sites.tsx
CHANGED
|
@@ -4,13 +4,13 @@ import ignore from "ignore";
|
|
|
4
4
|
import xxhash from "xxhash-wasm";
|
|
5
5
|
import {
|
|
6
6
|
createNamespace,
|
|
7
|
-
getKeyValue,
|
|
8
7
|
listNamespaceKeys,
|
|
9
8
|
listNamespaces,
|
|
10
9
|
putBulkKeyValue,
|
|
10
|
+
deleteBulkKeyValue,
|
|
11
11
|
} from "./kv";
|
|
12
12
|
import type { Config } from "./config";
|
|
13
|
-
import type { KeyValue
|
|
13
|
+
import type { KeyValue } from "./kv";
|
|
14
14
|
import type { XXHashAPI } from "xxhash-wasm";
|
|
15
15
|
|
|
16
16
|
/** Paths to always ignore. */
|
|
@@ -18,7 +18,6 @@ const ALWAYS_IGNORE = new Set(["node_modules"]);
|
|
|
18
18
|
const HIDDEN_FILES_TO_INCLUDE = new Set([
|
|
19
19
|
".well-known", // See https://datatracker.ietf.org/doc/html/rfc8615
|
|
20
20
|
]);
|
|
21
|
-
const FIVE_MINUTES = 60 * 5; // expressed in seconds, since that's what the api expects
|
|
22
21
|
|
|
23
22
|
async function* getFilesInFolder(dirPath: string): AsyncIterable<string> {
|
|
24
23
|
const files = await readdir(dirPath, { withFileTypes: true });
|
|
@@ -125,10 +124,7 @@ export async function syncAssets(
|
|
|
125
124
|
|
|
126
125
|
// let's get all the keys in this namespace
|
|
127
126
|
const result = await listNamespaceKeys(accountId, namespace);
|
|
128
|
-
const
|
|
129
|
-
(km, key) => Object.assign(km, { [key.name]: key }),
|
|
130
|
-
{}
|
|
131
|
-
);
|
|
127
|
+
const keys = new Set(result.map((x) => x.name));
|
|
132
128
|
|
|
133
129
|
const manifest: Record<string, string> = {};
|
|
134
130
|
const toUpload: KeyValue[] = [];
|
|
@@ -137,23 +133,28 @@ export async function syncAssets(
|
|
|
137
133
|
const exclude = createPatternMatcher(siteAssets.excludePatterns, true);
|
|
138
134
|
const hasher = await xxhash();
|
|
139
135
|
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
const assetDirectory = path.join(
|
|
137
|
+
siteAssets.baseDirectory,
|
|
138
|
+
siteAssets.assetDirectory
|
|
139
|
+
);
|
|
140
|
+
for await (const absAssetFile of getFilesInFolder(assetDirectory)) {
|
|
141
|
+
const assetFile = path.relative(siteAssets.baseDirectory, absAssetFile);
|
|
142
|
+
if (!include(assetFile)) {
|
|
142
143
|
continue;
|
|
143
144
|
}
|
|
144
|
-
if (exclude(
|
|
145
|
+
if (exclude(assetFile)) {
|
|
145
146
|
continue;
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
await validateAssetSize(
|
|
149
|
-
console.log(`reading ${
|
|
150
|
-
const content = await readFile(
|
|
149
|
+
await validateAssetSize(absAssetFile, assetFile);
|
|
150
|
+
console.log(`reading ${assetFile}...`);
|
|
151
|
+
const content = await readFile(absAssetFile, "base64");
|
|
151
152
|
|
|
152
|
-
const assetKey = hashAsset(hasher,
|
|
153
|
+
const assetKey = hashAsset(hasher, assetFile, content);
|
|
153
154
|
validateAssetKey(assetKey);
|
|
154
155
|
|
|
155
156
|
// now put each of the files into kv
|
|
156
|
-
if (!(assetKey
|
|
157
|
+
if (!keys.has(assetKey)) {
|
|
157
158
|
console.log(`uploading as ${assetKey}...`);
|
|
158
159
|
toUpload.push({
|
|
159
160
|
key: assetKey,
|
|
@@ -163,43 +164,26 @@ export async function syncAssets(
|
|
|
163
164
|
} else {
|
|
164
165
|
console.log(`skipping - already uploaded`);
|
|
165
166
|
}
|
|
166
|
-
// remove the key from the set so we know we've seen it
|
|
167
|
-
delete keyMap[assetKey];
|
|
168
|
-
manifest[path.relative(siteAssets.baseDirectory, file)] = assetKey;
|
|
169
|
-
}
|
|
170
167
|
|
|
171
|
-
|
|
168
|
+
// remove the key from the set so we know what we've already uploaded
|
|
169
|
+
keys.delete(assetKey);
|
|
170
|
+
manifest[path.relative(siteAssets.assetDirectory, absAssetFile)] = assetKey;
|
|
171
|
+
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
for (const
|
|
175
|
-
|
|
176
|
-
console.log(`expiring unused ${asset.name}...`);
|
|
177
|
-
toExpire.push({
|
|
178
|
-
key: asset.name,
|
|
179
|
-
value: "", // we'll fill all the values in one go
|
|
180
|
-
// we use expiration_ttl, since we can't trust the time
|
|
181
|
-
// that a deploy source might provide (eg - https://github.com/cloudflare/wrangler/issues/2224)
|
|
182
|
-
expiration_ttl: FIVE_MINUTES,
|
|
183
|
-
base64: true,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
173
|
+
// keys now contains all the files we're deleting
|
|
174
|
+
for (const key of keys) {
|
|
175
|
+
console.log(`deleting ${key} from the asset store...`);
|
|
186
176
|
}
|
|
187
177
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
);
|
|
178
|
+
await Promise.all([
|
|
179
|
+
// upload all the new assets
|
|
180
|
+
putBulkKeyValue(accountId, namespace, toUpload, () => {}),
|
|
181
|
+
// delete all the unused assets
|
|
182
|
+
deleteBulkKeyValue(accountId, namespace, Array.from(keys), () => {}),
|
|
183
|
+
]);
|
|
184
|
+
|
|
185
|
+
console.log("↗️ Done syncing assets");
|
|
196
186
|
|
|
197
|
-
await putBulkKeyValue(
|
|
198
|
-
accountId,
|
|
199
|
-
namespace,
|
|
200
|
-
toUpload.concat(toExpire),
|
|
201
|
-
() => {}
|
|
202
|
-
);
|
|
203
187
|
return { manifest, namespace };
|
|
204
188
|
}
|
|
205
189
|
|
|
@@ -215,11 +199,14 @@ function createPatternMatcher(
|
|
|
215
199
|
}
|
|
216
200
|
}
|
|
217
201
|
|
|
218
|
-
async function validateAssetSize(
|
|
219
|
-
|
|
202
|
+
async function validateAssetSize(
|
|
203
|
+
absFilePath: string,
|
|
204
|
+
relativeFilePath: string
|
|
205
|
+
) {
|
|
206
|
+
const { size } = await stat(absFilePath);
|
|
220
207
|
if (size > 25 * 1024 * 1024) {
|
|
221
208
|
throw new Error(
|
|
222
|
-
`File ${
|
|
209
|
+
`File ${relativeFilePath} is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits`
|
|
223
210
|
);
|
|
224
211
|
}
|
|
225
212
|
}
|
|
@@ -245,8 +232,23 @@ function urlSafe(filePath: string): string {
|
|
|
245
232
|
* Information about the assets that should be uploaded
|
|
246
233
|
*/
|
|
247
234
|
export interface AssetPaths {
|
|
235
|
+
/**
|
|
236
|
+
* Absolute path to the root of the project.
|
|
237
|
+
*
|
|
238
|
+
* This is the directory containing wrangler.toml or cwd if no config.
|
|
239
|
+
*/
|
|
248
240
|
baseDirectory: string;
|
|
241
|
+
/**
|
|
242
|
+
* The path to the assets directory, relative to the `baseDirectory`.
|
|
243
|
+
*/
|
|
244
|
+
assetDirectory: string;
|
|
245
|
+
/**
|
|
246
|
+
* An array of patterns that match files that should be uploaded.
|
|
247
|
+
*/
|
|
249
248
|
includePatterns: string[];
|
|
249
|
+
/**
|
|
250
|
+
* An array of patterns that match files that should not be uploaded.
|
|
251
|
+
*/
|
|
250
252
|
excludePatterns: string[];
|
|
251
253
|
}
|
|
252
254
|
|
|
@@ -259,13 +261,18 @@ export interface AssetPaths {
|
|
|
259
261
|
*/
|
|
260
262
|
export function getAssetPaths(
|
|
261
263
|
config: Config,
|
|
262
|
-
|
|
264
|
+
assetDirectory = config.site?.bucket,
|
|
263
265
|
includePatterns = config.site?.include ?? [],
|
|
264
266
|
excludePatterns = config.site?.exclude ?? []
|
|
265
267
|
): undefined | AssetPaths {
|
|
266
|
-
|
|
268
|
+
const baseDirectory = path.resolve(
|
|
269
|
+
path.dirname(config.configPath ?? "wrangler.toml")
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
return assetDirectory
|
|
267
273
|
? {
|
|
268
274
|
baseDirectory,
|
|
275
|
+
assetDirectory,
|
|
269
276
|
includePatterns,
|
|
270
277
|
excludePatterns,
|
|
271
278
|
}
|
package/src/tail/printing.ts
CHANGED
|
@@ -24,13 +24,13 @@ export function prettyPrintLogs(data: WebSocket.RawData): void {
|
|
|
24
24
|
|
|
25
25
|
if (eventMessage.logs.length > 0) {
|
|
26
26
|
eventMessage.logs.forEach(({ level, message }) => {
|
|
27
|
-
console.log(` (${level})
|
|
27
|
+
console.log(` (${level})`, message);
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
if (eventMessage.exceptions.length > 0) {
|
|
32
32
|
eventMessage.exceptions.forEach(({ name, message }) => {
|
|
33
|
-
console.error(` ${name}
|
|
33
|
+
console.error(` ${name}:`, message);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/user.tsx
CHANGED
|
@@ -610,8 +610,8 @@ export async function getAuthURL(scopes = ScopeKeys): Promise<string> {
|
|
|
610
610
|
`?response_type=code&` +
|
|
611
611
|
`client_id=${encodeURIComponent(CLIENT_ID)}&` +
|
|
612
612
|
`redirect_uri=${encodeURIComponent(CALLBACK_URL)}&` +
|
|
613
|
-
//
|
|
614
|
-
`scope=${encodeURIComponent(scopes
|
|
613
|
+
// we add offline_access manually for every request
|
|
614
|
+
`scope=${encodeURIComponent([...scopes, "offline_access"].join(" "))}&` +
|
|
615
615
|
`state=${stateQueryParam}&` +
|
|
616
616
|
`code_challenge=${encodeURIComponent(codeChallenge)}&` +
|
|
617
617
|
`code_challenge_method=S256`
|
|
@@ -864,7 +864,16 @@ export async function loginOrRefreshIfRequired(
|
|
|
864
864
|
// If we are not interactive, we cannot ask the user to login
|
|
865
865
|
return isInteractive && (await login());
|
|
866
866
|
} else if (isAccessTokenExpired()) {
|
|
867
|
-
|
|
867
|
+
// We're logged in, but the refresh token seems to have expired,
|
|
868
|
+
// so let's try to refresh it
|
|
869
|
+
const didRefresh = await refreshToken();
|
|
870
|
+
if (didRefresh) {
|
|
871
|
+
// The token was refreshed, so we're done here
|
|
872
|
+
return true;
|
|
873
|
+
} else {
|
|
874
|
+
// If the refresh token isn't valid, then we ask the user to login again
|
|
875
|
+
return isInteractive && (await login());
|
|
876
|
+
}
|
|
868
877
|
} else {
|
|
869
878
|
return true;
|
|
870
879
|
}
|