wrangler 2.0.9 → 2.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.
Files changed (61) hide show
  1. package/kv-asset-handler.js +1 -0
  2. package/package.json +4 -2
  3. package/src/__tests__/configuration.test.ts +255 -142
  4. package/src/__tests__/dev.test.tsx +27 -0
  5. package/src/__tests__/index.test.ts +2 -1
  6. package/src/__tests__/jest.setup.ts +30 -0
  7. package/src/__tests__/publish.test.ts +393 -160
  8. package/src/__tests__/user.test.ts +1 -0
  9. package/src/bundle.ts +9 -5
  10. package/src/config/environment.ts +1 -1
  11. package/src/config/validation-helpers.ts +10 -1
  12. package/src/config/validation.ts +22 -13
  13. package/src/dev/dev.tsx +29 -45
  14. package/src/dev/local.tsx +10 -7
  15. package/src/dev/remote.tsx +4 -1
  16. package/src/dev/use-esbuild.ts +1 -4
  17. package/src/generate-auth-url.ts +33 -0
  18. package/src/generate-random-state.ts +16 -0
  19. package/src/index.tsx +234 -179
  20. package/src/open-in-browser.ts +1 -3
  21. package/src/pages.tsx +295 -240
  22. package/src/parse.ts +2 -1
  23. package/src/proxy.ts +19 -6
  24. package/src/publish.ts +6 -1
  25. package/src/sites.tsx +49 -18
  26. package/src/user.tsx +12 -24
  27. package/templates/static-asset-facade.js +2 -6
  28. package/wrangler-dist/cli.js +73627 -73462
  29. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  30. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  31. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  32. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  33. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  34. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  35. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  36. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  37. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  38. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  39. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  40. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  41. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  42. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  43. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  44. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  45. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  46. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  47. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  48. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  49. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  50. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  51. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  52. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  53. package/vendor/wrangler-mime/LICENSE +0 -21
  54. package/vendor/wrangler-mime/Mime.js +0 -97
  55. package/vendor/wrangler-mime/README.md +0 -187
  56. package/vendor/wrangler-mime/cli.js +0 -46
  57. package/vendor/wrangler-mime/index.js +0 -4
  58. package/vendor/wrangler-mime/lite.js +0 -4
  59. package/vendor/wrangler-mime/package.json +0 -52
  60. package/vendor/wrangler-mime/types/other.js +0 -1
  61. package/vendor/wrangler-mime/types/standard.js +0 -1
package/src/pages.tsx CHANGED
@@ -821,6 +821,299 @@ interface CreateDeploymentArgs {
821
821
  commitDirty?: boolean;
822
822
  }
823
823
 
824
+ const upload = async ({
825
+ directory,
826
+ accountId,
827
+ projectName,
828
+ }: {
829
+ directory: string;
830
+ accountId: string;
831
+ projectName: string;
832
+ }) => {
833
+ type FileContainer = {
834
+ content: string;
835
+ contentType: string;
836
+ sizeInBytes: number;
837
+ hash: string;
838
+ };
839
+
840
+ const IGNORE_LIST = [
841
+ "_worker.js",
842
+ "_redirects",
843
+ "_headers",
844
+ ".DS_Store",
845
+ "node_modules",
846
+ ".git",
847
+ ];
848
+
849
+ const walk = async (
850
+ dir: string,
851
+ fileMap: Map<string, FileContainer> = new Map(),
852
+ depth = 0
853
+ ) => {
854
+ const files = await readdir(dir);
855
+
856
+ await Promise.all(
857
+ files.map(async (file) => {
858
+ const filepath = join(dir, file);
859
+ const filestat = await stat(filepath);
860
+
861
+ if (IGNORE_LIST.includes(file)) {
862
+ return;
863
+ }
864
+
865
+ if (filestat.isSymbolicLink()) {
866
+ return;
867
+ }
868
+
869
+ if (filestat.isDirectory()) {
870
+ fileMap = await walk(filepath, fileMap, depth + 1);
871
+ } else {
872
+ let name;
873
+ if (depth) {
874
+ name = filepath.split(sep).slice(1).join("/");
875
+ } else {
876
+ name = file;
877
+ }
878
+
879
+ // TODO: Move this to later so we don't hold as much in memory
880
+ const fileContent = await readFile(filepath);
881
+
882
+ const base64Content = fileContent.toString("base64");
883
+ const extension = extname(basename(name)).substring(1);
884
+
885
+ if (filestat.size > 25 * 1024 * 1024) {
886
+ throw new Error(
887
+ `Error: Pages only supports files up to ${prettyBytes(
888
+ 25 * 1024 * 1024
889
+ )} in size\n${name} is ${prettyBytes(filestat.size)} in size`
890
+ );
891
+ }
892
+
893
+ fileMap.set(name, {
894
+ content: base64Content,
895
+ contentType: getType(name) || "application/octet-stream",
896
+ sizeInBytes: filestat.size,
897
+ hash: hash(base64Content + extension)
898
+ .toString("hex")
899
+ .slice(0, 32),
900
+ });
901
+ }
902
+ })
903
+ );
904
+
905
+ return fileMap;
906
+ };
907
+
908
+ const fileMap = await walk(directory);
909
+
910
+ if (fileMap.size > 20000) {
911
+ throw new FatalError(
912
+ `Error: Pages only supports up to 20,000 files in a deployment. Ensure you have specified your build output directory correctly.`,
913
+ 1
914
+ );
915
+ }
916
+
917
+ const files = [...fileMap.values()];
918
+
919
+ async function fetchJwt(): Promise<string> {
920
+ return (
921
+ await fetchResult<{ jwt: string }>(
922
+ `/accounts/${accountId}/pages/projects/${projectName}/upload-token`
923
+ )
924
+ ).jwt;
925
+ }
926
+
927
+ let jwt = await fetchJwt();
928
+
929
+ const start = Date.now();
930
+
931
+ const missingHashes = await fetchResult<string[]>(
932
+ `/pages/assets/check-missing`,
933
+ {
934
+ method: "POST",
935
+ headers: {
936
+ "Content-Type": "application/json",
937
+ Authorization: `Bearer ${jwt}`,
938
+ },
939
+ body: JSON.stringify({
940
+ hashes: files.map(({ hash }) => hash),
941
+ }),
942
+ }
943
+ );
944
+
945
+ const sortedFiles = files
946
+ .filter((file) => missingHashes.includes(file.hash))
947
+ .sort((a, b) => b.sizeInBytes - a.sizeInBytes);
948
+
949
+ // Start with a few buckets so small projects still get
950
+ // the benefit of multiple upload streams
951
+ const buckets: {
952
+ files: FileContainer[];
953
+ remainingSize: number;
954
+ }[] = new Array(BULK_UPLOAD_CONCURRENCY).fill(null).map(() => ({
955
+ files: [],
956
+ remainingSize: MAX_BUCKET_SIZE,
957
+ }));
958
+
959
+ let bucketOffset = 0;
960
+ for (const file of sortedFiles) {
961
+ let inserted = false;
962
+
963
+ for (let i = 0; i < buckets.length; i++) {
964
+ // Start at a different bucket for each new file
965
+ const bucket = buckets[(i + bucketOffset) % buckets.length];
966
+ if (
967
+ bucket.remainingSize >= file.sizeInBytes &&
968
+ bucket.files.length < MAX_BUCKET_FILE_COUNT
969
+ ) {
970
+ bucket.files.push(file);
971
+ bucket.remainingSize -= file.sizeInBytes;
972
+ inserted = true;
973
+ break;
974
+ }
975
+ }
976
+
977
+ if (!inserted) {
978
+ buckets.push({
979
+ files: [file],
980
+ remainingSize: MAX_BUCKET_SIZE - file.sizeInBytes,
981
+ });
982
+ }
983
+ bucketOffset++;
984
+ }
985
+
986
+ let counter = fileMap.size - sortedFiles.length;
987
+ const { rerender, unmount } = render(
988
+ <Progress done={counter} total={fileMap.size} />
989
+ );
990
+
991
+ const queue = new PQueue({ concurrency: BULK_UPLOAD_CONCURRENCY });
992
+
993
+ for (const bucket of buckets) {
994
+ // Don't upload empty buckets (can happen for tiny projects)
995
+ if (bucket.files.length === 0) continue;
996
+
997
+ const payload: UploadPayloadFile[] = bucket.files.map((file) => ({
998
+ key: file.hash,
999
+ value: file.content,
1000
+ metadata: {
1001
+ contentType: file.contentType,
1002
+ },
1003
+ base64: true,
1004
+ }));
1005
+
1006
+ let attempts = 0;
1007
+ const doUpload = async (): Promise<void> => {
1008
+ try {
1009
+ return await fetchResult(`/pages/assets/upload`, {
1010
+ method: "POST",
1011
+ headers: {
1012
+ "Content-Type": "application/json",
1013
+ Authorization: `Bearer ${jwt}`,
1014
+ },
1015
+ body: JSON.stringify(payload),
1016
+ });
1017
+ } catch (e) {
1018
+ if (attempts < MAX_UPLOAD_ATTEMPTS) {
1019
+ // Linear backoff, 0 second first time, then 1 second etc.
1020
+ await new Promise((resolve) =>
1021
+ setTimeout(resolve, attempts++ * 1000)
1022
+ );
1023
+
1024
+ if ((e as { code: number }).code === 8000013) {
1025
+ // Looks like the JWT expired, fetch another one
1026
+ jwt = await fetchJwt();
1027
+ }
1028
+ return doUpload();
1029
+ } else {
1030
+ throw e;
1031
+ }
1032
+ }
1033
+ };
1034
+
1035
+ queue.add(() =>
1036
+ doUpload().then(
1037
+ () => {
1038
+ counter += bucket.files.length;
1039
+ rerender(<Progress done={counter} total={fileMap.size} />);
1040
+ },
1041
+ (error) => {
1042
+ return Promise.reject(
1043
+ new FatalError(
1044
+ "Failed to upload files. Please try again.",
1045
+ error.code || 1
1046
+ )
1047
+ );
1048
+ }
1049
+ )
1050
+ );
1051
+ }
1052
+
1053
+ await queue.onIdle();
1054
+
1055
+ unmount();
1056
+
1057
+ const uploadMs = Date.now() - start;
1058
+
1059
+ const skipped = fileMap.size - missingHashes.length;
1060
+ const skippedMessage = skipped > 0 ? `(${skipped} already uploaded) ` : "";
1061
+
1062
+ logger.log(
1063
+ `✨ Success! Uploaded ${
1064
+ sortedFiles.length
1065
+ } files ${skippedMessage}${formatTime(uploadMs)}\n`
1066
+ );
1067
+
1068
+ const doUpsertHashes = async (): Promise<void> => {
1069
+ try {
1070
+ return await fetchResult(`/pages/assets/upsert-hashes`, {
1071
+ method: "POST",
1072
+ headers: {
1073
+ "Content-Type": "application/json",
1074
+ Authorization: `Bearer ${jwt}`,
1075
+ },
1076
+ body: JSON.stringify({
1077
+ hashes: files.map(({ hash }) => hash),
1078
+ }),
1079
+ });
1080
+ } catch (e) {
1081
+ await new Promise((resolve) => setTimeout(resolve, 1000));
1082
+
1083
+ if ((e as { code: number }).code === 8000013) {
1084
+ // Looks like the JWT expired, fetch another one
1085
+ jwt = await fetchJwt();
1086
+ }
1087
+
1088
+ return await fetchResult(`/pages/assets/upsert-hashes`, {
1089
+ method: "POST",
1090
+ headers: {
1091
+ "Content-Type": "application/json",
1092
+ Authorization: `Bearer ${jwt}`,
1093
+ },
1094
+ body: JSON.stringify({
1095
+ hashes: files.map(({ hash }) => hash),
1096
+ }),
1097
+ });
1098
+ }
1099
+ };
1100
+
1101
+ try {
1102
+ await doUpsertHashes();
1103
+ } catch {
1104
+ logger.warn(
1105
+ "Failed to update file hashes. Every upload appeared to succeed for this deployment, but you might need to re-upload for future deployments. This shouldn't have any impact other than slowing the upload speed of your next deployment."
1106
+ );
1107
+ }
1108
+
1109
+ return Object.fromEntries(
1110
+ [...fileMap.entries()].map(([fileName, file]) => [
1111
+ `/${fileName}`,
1112
+ file.hash,
1113
+ ])
1114
+ );
1115
+ };
1116
+
824
1117
  const createDeployment: CommandModule<
825
1118
  CreateDeploymentArgs,
826
1119
  CreateDeploymentArgs
@@ -1053,249 +1346,11 @@ const createDeployment: CommandModule<
1053
1346
  builtFunctions = readFileSync(outfile, "utf-8");
1054
1347
  }
1055
1348
 
1056
- type FileContainer = {
1057
- content: string;
1058
- contentType: string;
1059
- sizeInBytes: number;
1060
- hash: string;
1061
- };
1062
-
1063
- const IGNORE_LIST = [
1064
- "_worker.js",
1065
- "_redirects",
1066
- "_headers",
1067
- ".DS_Store",
1068
- "node_modules",
1069
- ".git",
1070
- ];
1071
-
1072
- const walk = async (
1073
- dir: string,
1074
- fileMap: Map<string, FileContainer> = new Map(),
1075
- depth = 0
1076
- ) => {
1077
- const files = await readdir(dir);
1078
-
1079
- await Promise.all(
1080
- files.map(async (file) => {
1081
- const filepath = join(dir, file);
1082
- const filestat = await stat(filepath);
1083
-
1084
- if (IGNORE_LIST.includes(file)) {
1085
- return;
1086
- }
1087
-
1088
- if (filestat.isSymbolicLink()) {
1089
- return;
1090
- }
1091
-
1092
- if (filestat.isDirectory()) {
1093
- fileMap = await walk(filepath, fileMap, depth + 1);
1094
- } else {
1095
- let name;
1096
- if (depth) {
1097
- name = filepath.split(sep).slice(1).join("/");
1098
- } else {
1099
- name = file;
1100
- }
1101
-
1102
- // TODO: Move this to later so we don't hold as much in memory
1103
- const fileContent = await readFile(filepath);
1104
-
1105
- const base64Content = fileContent.toString("base64");
1106
- const extension = extname(basename(name)).substring(1);
1107
-
1108
- if (filestat.size > 25 * 1024 * 1024) {
1109
- throw new Error(
1110
- `Error: Pages only supports files up to ${prettyBytes(
1111
- 25 * 1024 * 1024
1112
- )} in size\n${name} is ${prettyBytes(filestat.size)} in size`
1113
- );
1114
- }
1115
-
1116
- fileMap.set(name, {
1117
- content: base64Content,
1118
- contentType: getType(name) || "application/octet-stream",
1119
- sizeInBytes: filestat.size,
1120
- hash: hash(base64Content + extension)
1121
- .toString("hex")
1122
- .slice(0, 32),
1123
- });
1124
- }
1125
- })
1126
- );
1127
-
1128
- return fileMap;
1129
- };
1130
-
1131
- const fileMap = await walk(directory);
1132
-
1133
- if (fileMap.size > 20000) {
1134
- throw new FatalError(
1135
- `Error: Pages only supports up to 20,000 files in a deployment. Ensure you have specified your build output directory correctly.`,
1136
- 1
1137
- );
1138
- }
1139
-
1140
- const files = [...fileMap.values()];
1141
-
1142
- async function fetchJwt(): Promise<string> {
1143
- return (
1144
- await fetchResult<{ jwt: string }>(
1145
- `/accounts/${accountId}/pages/projects/${projectName}/upload-token`
1146
- )
1147
- ).jwt;
1148
- }
1149
-
1150
- let jwt = await fetchJwt();
1151
-
1152
- const start = Date.now();
1153
-
1154
- const missingHashes = await fetchResult<string[]>(
1155
- `/pages/assets/check-missing`,
1156
- {
1157
- method: "POST",
1158
- headers: {
1159
- "Content-Type": "application/json",
1160
- Authorization: `Bearer ${jwt}`,
1161
- },
1162
- body: JSON.stringify({
1163
- hashes: files.map(({ hash }) => hash),
1164
- }),
1165
- }
1166
- );
1167
-
1168
- const sortedFiles = files
1169
- .filter((file) => missingHashes.includes(file.hash))
1170
- .sort((a, b) => b.sizeInBytes - a.sizeInBytes);
1171
-
1172
- // Start with a few buckets so small projects still get
1173
- // the benefit of multiple upload streams
1174
- const buckets: {
1175
- files: FileContainer[];
1176
- remainingSize: number;
1177
- }[] = new Array(BULK_UPLOAD_CONCURRENCY).fill(null).map(() => ({
1178
- files: [],
1179
- remainingSize: MAX_BUCKET_SIZE,
1180
- }));
1181
-
1182
- let bucketOffset = 0;
1183
- for (const file of sortedFiles) {
1184
- let inserted = false;
1185
-
1186
- for (let i = 0; i < buckets.length; i++) {
1187
- // Start at a different bucket for each new file
1188
- const bucket = buckets[(i + bucketOffset) % buckets.length];
1189
- if (
1190
- bucket.remainingSize >= file.sizeInBytes &&
1191
- bucket.files.length < MAX_BUCKET_FILE_COUNT
1192
- ) {
1193
- bucket.files.push(file);
1194
- bucket.remainingSize -= file.sizeInBytes;
1195
- inserted = true;
1196
- break;
1197
- }
1198
- }
1199
-
1200
- if (!inserted) {
1201
- buckets.push({
1202
- files: [file],
1203
- remainingSize: MAX_BUCKET_SIZE - file.sizeInBytes,
1204
- });
1205
- }
1206
- bucketOffset++;
1207
- }
1208
-
1209
- let counter = fileMap.size - sortedFiles.length;
1210
- const { rerender, unmount } = render(
1211
- <Progress done={counter} total={fileMap.size} />
1212
- );
1213
-
1214
- const queue = new PQueue({ concurrency: BULK_UPLOAD_CONCURRENCY });
1215
-
1216
- for (const bucket of buckets) {
1217
- // Don't upload empty buckets (can happen for tiny projects)
1218
- if (bucket.files.length === 0) continue;
1219
-
1220
- const payload: UploadPayloadFile[] = bucket.files.map((file) => ({
1221
- key: file.hash,
1222
- value: file.content,
1223
- metadata: {
1224
- contentType: file.contentType,
1225
- },
1226
- base64: true,
1227
- }));
1228
-
1229
- let attempts = 0;
1230
- const doUpload = async (): Promise<void> => {
1231
- try {
1232
- return await fetchResult(`/pages/assets/upload`, {
1233
- method: "POST",
1234
- headers: {
1235
- "Content-Type": "application/json",
1236
- Authorization: `Bearer ${jwt}`,
1237
- },
1238
- body: JSON.stringify(payload),
1239
- });
1240
- } catch (e) {
1241
- if (attempts < MAX_UPLOAD_ATTEMPTS) {
1242
- // Linear backoff, 0 second first time, then 1 second etc.
1243
- await new Promise((resolve) =>
1244
- setTimeout(resolve, attempts++ * 1000)
1245
- );
1246
-
1247
- if ((e as { code: number }).code === 8000013) {
1248
- // Looks like the JWT expired, fetch another one
1249
- jwt = await fetchJwt();
1250
- }
1251
- return doUpload();
1252
- } else {
1253
- throw e;
1254
- }
1255
- }
1256
- };
1257
-
1258
- queue.add(() =>
1259
- doUpload().then(
1260
- () => {
1261
- counter += bucket.files.length;
1262
- rerender(<Progress done={counter} total={fileMap.size} />);
1263
- },
1264
- (error) => {
1265
- return Promise.reject(
1266
- new FatalError(
1267
- "Failed to upload files. Please try again.",
1268
- error.code || 1
1269
- )
1270
- );
1271
- }
1272
- )
1273
- );
1274
- }
1275
-
1276
- await queue.onIdle();
1277
-
1278
- unmount();
1279
-
1280
- const uploadMs = Date.now() - start;
1281
-
1282
- logger.log(
1283
- `✨ Success! Uploaded ${fileMap.size} files ${formatTime(uploadMs)}\n`
1284
- );
1349
+ const manifest = await upload({ directory, accountId, projectName });
1285
1350
 
1286
1351
  const formData = new FormData();
1287
1352
 
1288
- formData.append(
1289
- "manifest",
1290
- JSON.stringify(
1291
- Object.fromEntries(
1292
- [...fileMap.entries()].map(([fileName, file]) => [
1293
- `/${fileName}`,
1294
- file.hash,
1295
- ])
1296
- )
1297
- )
1298
- );
1353
+ formData.append("manifest", JSON.stringify(manifest));
1299
1354
 
1300
1355
  if (branch) {
1301
1356
  formData.append("branch", branch);
package/src/parse.ts CHANGED
@@ -2,6 +2,7 @@ import * as fs from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import TOML from "@iarna/toml";
4
4
  import { formatMessagesSync } from "esbuild";
5
+ import { logger } from "./logger";
5
6
 
6
7
  export type Message = {
7
8
  text: string;
@@ -38,7 +39,7 @@ export function formatMessage(
38
39
  const lines = formatMessagesSync([input], {
39
40
  color,
40
41
  kind: kind,
41
- terminalWidth: process.stderr.columns,
42
+ terminalWidth: logger.columns,
42
43
  });
43
44
  return lines.join("\n");
44
45
  }
package/src/proxy.ts CHANGED
@@ -100,7 +100,10 @@ export function usePreviewServer({
100
100
  .then((server) => {
101
101
  setProxy({
102
102
  server,
103
- terminator: createHttpTerminator({ server }),
103
+ terminator: createHttpTerminator({
104
+ server,
105
+ gracefulTerminationTimeout: 0,
106
+ }),
104
107
  });
105
108
  })
106
109
  .catch(async (err) => {
@@ -330,7 +333,9 @@ export function usePreviewServer({
330
333
  abortController.abort();
331
334
  // Running `proxy.server.close()` does not close open connections, preventing the process from exiting.
332
335
  // So we use this `terminator` to close all the connections and force the server to shutdown.
333
- proxy.terminator.terminate();
336
+ proxy.terminator
337
+ .terminate()
338
+ .catch(() => logger.error("Failed to terminate the proxy server."));
334
339
  };
335
340
  }, [port, ip, proxy, localProtocol]);
336
341
  }
@@ -450,16 +455,24 @@ export async function waitForPortToBeAvailable(
450
455
  // trying to make a server listen on that port, and retrying
451
456
  // until it succeeds.
452
457
  const server = createHttpServer();
458
+ const terminator = createHttpTerminator({
459
+ server,
460
+ gracefulTerminationTimeout: 0, // default 1000
461
+ });
462
+
453
463
  server.on("error", (err) => {
454
464
  // @ts-expect-error non standard property on Error
455
465
  if (err.code !== "EADDRINUSE") {
456
466
  doReject(err);
457
467
  }
458
468
  });
459
- server.listen(port, () => {
460
- server.close();
461
- doResolve();
462
- });
469
+ server.listen(port, () =>
470
+ terminator
471
+ .terminate()
472
+ .then(doResolve, () =>
473
+ logger.error("Failed to terminate the port checker.")
474
+ )
475
+ );
463
476
  }
464
477
  });
465
478
  }
package/src/publish.ts CHANGED
@@ -430,7 +430,12 @@ export default async function publish(props: Props): Promise<void> {
430
430
  method: "PUT",
431
431
  body: createWorkerUploadForm(worker),
432
432
  },
433
- new URLSearchParams({ include_subdomain_availability: "true" })
433
+ new URLSearchParams({
434
+ include_subdomain_availability: "true",
435
+ // pass excludeScript so the whole body of the
436
+ // script doesn't get included in the response
437
+ excludeScript: "true",
438
+ })
434
439
  )
435
440
  ).available_on_subdomain;
436
441
  }