wrangler 2.0.5 → 2.0.6
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__/configuration.test.ts +204 -27
- package/src/__tests__/dev.test.tsx +60 -7
- package/src/__tests__/index.test.ts +5 -6
- package/src/__tests__/kv.test.ts +85 -85
- package/src/__tests__/pages.test.ts +28 -5
- package/src/__tests__/publish.test.ts +306 -7
- package/src/__tests__/r2.test.ts +47 -24
- package/src/__tests__/secret.test.ts +35 -0
- package/src/bundle.ts +32 -1
- package/src/config/environment.ts +40 -14
- package/src/config/validation.ts +102 -35
- package/src/create-worker-upload-form.ts +22 -8
- package/src/dev/local.tsx +6 -0
- package/src/index.tsx +45 -20
- package/src/kv.ts +18 -3
- package/src/pages.tsx +3 -4
- package/src/publish.ts +210 -21
- package/src/sites.tsx +3 -1
- package/src/worker.ts +8 -0
- package/wrangler-dist/cli.js +432 -234
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
unsetMockFetchKVGetValues,
|
|
13
13
|
} from "./helpers/mock-cfetch";
|
|
14
14
|
import { mockConsoleMethods, normalizeSlashes } from "./helpers/mock-console";
|
|
15
|
+
import { mockConfirm } from "./helpers/mock-dialogs";
|
|
15
16
|
import { useMockIsTTY } from "./helpers/mock-istty";
|
|
16
17
|
import { mockKeyListRequest } from "./helpers/mock-kv";
|
|
17
18
|
import { mockOAuthFlow } from "./helpers/mock-oauth-flow";
|
|
@@ -645,6 +646,136 @@ describe("publish", () => {
|
|
|
645
646
|
await runWrangler("publish ./index --env dev --legacy-env false");
|
|
646
647
|
});
|
|
647
648
|
|
|
649
|
+
describe("custom domains", () => {
|
|
650
|
+
it("should publish routes marked with 'custom_domain' as seperate custom domains", async () => {
|
|
651
|
+
writeWranglerToml({
|
|
652
|
+
routes: [{ pattern: "api.example.com", custom_domain: true }],
|
|
653
|
+
});
|
|
654
|
+
writeWorkerSource();
|
|
655
|
+
mockUpdateWorkerRequest({ enabled: false });
|
|
656
|
+
mockUploadWorkerRequest({ expectedType: "esm" });
|
|
657
|
+
mockPublishCustomDomainsRequest({
|
|
658
|
+
publishFlags: {
|
|
659
|
+
override_scope: true,
|
|
660
|
+
override_existing_origin: false,
|
|
661
|
+
override_existing_dns_record: false,
|
|
662
|
+
},
|
|
663
|
+
domains: [{ hostname: "api.example.com" }],
|
|
664
|
+
});
|
|
665
|
+
await runWrangler("publish ./index");
|
|
666
|
+
expect(std.out).toContain("api.example.com (custom domain)");
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
it("should allow retrying if publish fails with a conflicting custom domain error", async () => {
|
|
670
|
+
writeWranglerToml({
|
|
671
|
+
routes: [{ pattern: "api.example.com", custom_domain: true }],
|
|
672
|
+
});
|
|
673
|
+
writeWorkerSource();
|
|
674
|
+
mockUpdateWorkerRequest({ enabled: false });
|
|
675
|
+
mockUploadWorkerRequest({ expectedType: "esm" });
|
|
676
|
+
mockPublishCustomDomainsRequestConflictWithoutOverride({
|
|
677
|
+
originConflicts: true,
|
|
678
|
+
domains: [{ hostname: "api.example.com" }],
|
|
679
|
+
});
|
|
680
|
+
mockConfirm({
|
|
681
|
+
text: `Custom Domains already exist for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
|
|
682
|
+
result: true,
|
|
683
|
+
});
|
|
684
|
+
await runWrangler("publish ./index");
|
|
685
|
+
expect(std.out).toContain("api.example.com (custom domain)");
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
it("should allow retrying if publish fails with a conflicting DNS record error", async () => {
|
|
689
|
+
writeWranglerToml({
|
|
690
|
+
routes: [{ pattern: "api.example.com", custom_domain: true }],
|
|
691
|
+
});
|
|
692
|
+
writeWorkerSource();
|
|
693
|
+
mockUpdateWorkerRequest({ enabled: false });
|
|
694
|
+
mockUploadWorkerRequest({ expectedType: "esm" });
|
|
695
|
+
mockPublishCustomDomainsRequestConflictWithoutOverride({
|
|
696
|
+
dnsRecordConflicts: true,
|
|
697
|
+
domains: [{ hostname: "api.example.com" }],
|
|
698
|
+
});
|
|
699
|
+
mockConfirm({
|
|
700
|
+
text: `You already have conflicting DNS records for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
|
|
701
|
+
result: true,
|
|
702
|
+
});
|
|
703
|
+
await runWrangler("publish ./index");
|
|
704
|
+
expect(std.out).toContain("api.example.com (custom domain)");
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
it("should allow retrying for conflicting custom domains and then again for conflicting dns", async () => {
|
|
708
|
+
writeWranglerToml({
|
|
709
|
+
routes: [{ pattern: "api.example.com", custom_domain: true }],
|
|
710
|
+
});
|
|
711
|
+
writeWorkerSource();
|
|
712
|
+
mockUpdateWorkerRequest({ enabled: false });
|
|
713
|
+
mockUploadWorkerRequest({ expectedType: "esm" });
|
|
714
|
+
mockPublishCustomDomainsRequestConflictWithoutOverride({
|
|
715
|
+
originConflicts: true,
|
|
716
|
+
dnsRecordConflicts: true,
|
|
717
|
+
domains: [{ hostname: "api.example.com" }],
|
|
718
|
+
});
|
|
719
|
+
mockConfirm(
|
|
720
|
+
{
|
|
721
|
+
text: `Custom Domains already exist for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
|
|
722
|
+
result: true,
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
text: `You already have conflicting DNS records for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
|
|
726
|
+
result: true,
|
|
727
|
+
}
|
|
728
|
+
);
|
|
729
|
+
await runWrangler("publish ./index");
|
|
730
|
+
expect(std.out).toContain("api.example.com (custom domain)");
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
it("should throw if an invalid custom domain is requested", async () => {
|
|
734
|
+
writeWranglerToml({
|
|
735
|
+
routes: [{ pattern: "*.example.com", custom_domain: true }],
|
|
736
|
+
});
|
|
737
|
+
writeWorkerSource();
|
|
738
|
+
await expect(
|
|
739
|
+
runWrangler("publish ./index")
|
|
740
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
741
|
+
`"Cannot use \\"*.example.com\\" as a Custom Domain; wildcard operators (*) are not allowed"`
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
writeWranglerToml({
|
|
745
|
+
routes: [
|
|
746
|
+
{ pattern: "api.example.com/at/a/path", custom_domain: true },
|
|
747
|
+
],
|
|
748
|
+
});
|
|
749
|
+
writeWorkerSource();
|
|
750
|
+
await expect(
|
|
751
|
+
runWrangler("publish ./index")
|
|
752
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
753
|
+
`"Cannot use \\"api.example.com/at/a/path\\" as a Custom Domain; paths are not allowed"`
|
|
754
|
+
);
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
it("should not retry publish on error if user does not confirm", async () => {
|
|
758
|
+
writeWranglerToml({
|
|
759
|
+
routes: [{ pattern: "api.example.com", custom_domain: true }],
|
|
760
|
+
});
|
|
761
|
+
writeWorkerSource();
|
|
762
|
+
mockUpdateWorkerRequest({ enabled: false });
|
|
763
|
+
mockUploadWorkerRequest({ expectedType: "esm" });
|
|
764
|
+
mockPublishCustomDomainsRequestConflictWithoutOverride({
|
|
765
|
+
dnsRecordConflicts: true,
|
|
766
|
+
domains: [{ hostname: "api.example.com" }],
|
|
767
|
+
});
|
|
768
|
+
mockConfirm({
|
|
769
|
+
text: `You already have conflicting DNS records for these domains: "api.example.com"\nUpdate them to point to this script instead?`,
|
|
770
|
+
result: false,
|
|
771
|
+
});
|
|
772
|
+
await runWrangler("publish ./index");
|
|
773
|
+
expect(std.out).toContain(
|
|
774
|
+
'Publishing to Custom Domain "api.example.com" was skipped, fix conflict and try again'
|
|
775
|
+
);
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
|
|
648
779
|
it.todo("should error if it's a workers.dev route");
|
|
649
780
|
});
|
|
650
781
|
|
|
@@ -3106,6 +3237,7 @@ addEventListener('fetch', event => {});`
|
|
|
3106
3237
|
name: "DURABLE_OBJECT_TWO",
|
|
3107
3238
|
class_name: "AnotherDurableObject",
|
|
3108
3239
|
script_name: "another-durable-object-worker",
|
|
3240
|
+
environment: "staging",
|
|
3109
3241
|
},
|
|
3110
3242
|
],
|
|
3111
3243
|
},
|
|
@@ -3164,6 +3296,12 @@ addEventListener('fetch', event => {});`
|
|
|
3164
3296
|
mockUploadWorkerRequest({
|
|
3165
3297
|
expectedType: "sw",
|
|
3166
3298
|
expectedBindings: [
|
|
3299
|
+
{ json: 123, name: "ENV_VAR_ONE", type: "json" },
|
|
3300
|
+
{
|
|
3301
|
+
name: "ENV_VAR_TWO",
|
|
3302
|
+
text: "Hello, I'm an environment variable",
|
|
3303
|
+
type: "plain_text",
|
|
3304
|
+
},
|
|
3167
3305
|
{
|
|
3168
3306
|
name: "KV_NAMESPACE_ONE",
|
|
3169
3307
|
namespace_id: "kv-ns-one-id",
|
|
@@ -3182,6 +3320,7 @@ addEventListener('fetch', event => {});`
|
|
|
3182
3320
|
},
|
|
3183
3321
|
{
|
|
3184
3322
|
class_name: "AnotherDurableObject",
|
|
3323
|
+
environment: "staging",
|
|
3185
3324
|
name: "DURABLE_OBJECT_TWO",
|
|
3186
3325
|
script_name: "another-durable-object-worker",
|
|
3187
3326
|
type: "durable_object_namespace",
|
|
@@ -3196,12 +3335,6 @@ addEventListener('fetch', event => {});`
|
|
|
3196
3335
|
name: "R2_BUCKET_TWO",
|
|
3197
3336
|
type: "r2_bucket",
|
|
3198
3337
|
},
|
|
3199
|
-
{ json: 123, name: "ENV_VAR_ONE", type: "json" },
|
|
3200
|
-
{
|
|
3201
|
-
name: "ENV_VAR_TWO",
|
|
3202
|
-
text: "Hello, I'm an environment variable",
|
|
3203
|
-
type: "plain_text",
|
|
3204
|
-
},
|
|
3205
3338
|
{
|
|
3206
3339
|
name: "WASM_MODULE_ONE",
|
|
3207
3340
|
part: "WASM_MODULE_ONE",
|
|
@@ -4123,6 +4256,47 @@ addEventListener('fetch', event => {});`
|
|
|
4123
4256
|
});
|
|
4124
4257
|
});
|
|
4125
4258
|
|
|
4259
|
+
describe("[services]", () => {
|
|
4260
|
+
it("should support service bindings", async () => {
|
|
4261
|
+
writeWranglerToml({
|
|
4262
|
+
services: [
|
|
4263
|
+
{
|
|
4264
|
+
binding: "FOO",
|
|
4265
|
+
service: "foo-service",
|
|
4266
|
+
environment: "production",
|
|
4267
|
+
},
|
|
4268
|
+
],
|
|
4269
|
+
});
|
|
4270
|
+
writeWorkerSource();
|
|
4271
|
+
mockSubDomainRequest();
|
|
4272
|
+
mockUploadWorkerRequest({
|
|
4273
|
+
expectedBindings: [
|
|
4274
|
+
{
|
|
4275
|
+
type: "service",
|
|
4276
|
+
name: "FOO",
|
|
4277
|
+
service: "foo-service",
|
|
4278
|
+
environment: "production",
|
|
4279
|
+
},
|
|
4280
|
+
],
|
|
4281
|
+
});
|
|
4282
|
+
|
|
4283
|
+
await runWrangler("publish index.js");
|
|
4284
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
4285
|
+
"Uploaded test-name (TIMINGS)
|
|
4286
|
+
Published test-name (TIMINGS)
|
|
4287
|
+
test-name.test-sub-domain.workers.dev"
|
|
4288
|
+
`);
|
|
4289
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
4290
|
+
expect(std.warn).toMatchInlineSnapshot(`
|
|
4291
|
+
"[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mProcessing wrangler.toml configuration:[0m
|
|
4292
|
+
|
|
4293
|
+
- \\"services\\" fields are experimental and may change or break at any time.
|
|
4294
|
+
|
|
4295
|
+
"
|
|
4296
|
+
`);
|
|
4297
|
+
});
|
|
4298
|
+
});
|
|
4299
|
+
|
|
4126
4300
|
describe("[unsafe]", () => {
|
|
4127
4301
|
it("should warn if using unsafe bindings", async () => {
|
|
4128
4302
|
writeWranglerToml({
|
|
@@ -4625,8 +4799,16 @@ addEventListener('fetch', event => {});`
|
|
|
4625
4799
|
|
|
4626
4800
|
describe("--dry-run", () => {
|
|
4627
4801
|
it("should not publish the worker if --dry-run is specified", async () => {
|
|
4628
|
-
writeWranglerToml(
|
|
4802
|
+
writeWranglerToml({
|
|
4803
|
+
// add a durable object with migrations
|
|
4804
|
+
// to make sure we _don't_ fetch migration status
|
|
4805
|
+
durable_objects: {
|
|
4806
|
+
bindings: [{ name: "NAME", class_name: "SomeClass" }],
|
|
4807
|
+
},
|
|
4808
|
+
migrations: [{ tag: "v1", new_classes: ["SomeClass"] }],
|
|
4809
|
+
});
|
|
4629
4810
|
writeWorkerSource();
|
|
4811
|
+
process.env.CLOUDFLARE_ACCOUNT_ID = "";
|
|
4630
4812
|
await runWrangler("publish index.js --dry-run");
|
|
4631
4813
|
expect(std).toMatchInlineSnapshot(`
|
|
4632
4814
|
Object {
|
|
@@ -4656,6 +4838,27 @@ addEventListener('fetch', event => {});`
|
|
|
4656
4838
|
`);
|
|
4657
4839
|
});
|
|
4658
4840
|
|
|
4841
|
+
it("should recommend node compatibility mode when using node builtins and node-compat isn't enabled", async () => {
|
|
4842
|
+
writeWranglerToml();
|
|
4843
|
+
fs.writeFileSync(
|
|
4844
|
+
"index.js",
|
|
4845
|
+
`
|
|
4846
|
+
import path from 'path';
|
|
4847
|
+
console.log(path.join("some/path/to", "a/file.txt"));
|
|
4848
|
+
export default {}
|
|
4849
|
+
`
|
|
4850
|
+
);
|
|
4851
|
+
let err: Error | undefined;
|
|
4852
|
+
try {
|
|
4853
|
+
await runWrangler("publish index.js --dry-run"); // expecting this to throw, as node compatibility isn't enabled
|
|
4854
|
+
} catch (e) {
|
|
4855
|
+
err = e as Error;
|
|
4856
|
+
}
|
|
4857
|
+
expect(err?.message).toMatch(
|
|
4858
|
+
`Detected a Node builtin module import while Node compatibility is disabled.\nAdd node_compat = true to your wrangler.toml file to enable Node compatibility.`
|
|
4859
|
+
);
|
|
4860
|
+
});
|
|
4861
|
+
|
|
4659
4862
|
it("should polyfill node builtins when enabled", async () => {
|
|
4660
4863
|
writeWranglerToml();
|
|
4661
4864
|
fs.writeFileSync(
|
|
@@ -4850,6 +5053,102 @@ function mockPublishRoutesRequest({
|
|
|
4850
5053
|
);
|
|
4851
5054
|
}
|
|
4852
5055
|
|
|
5056
|
+
function mockPublishCustomDomainsRequest({
|
|
5057
|
+
publishFlags,
|
|
5058
|
+
domains = [],
|
|
5059
|
+
env = undefined,
|
|
5060
|
+
legacyEnv = false,
|
|
5061
|
+
}: {
|
|
5062
|
+
publishFlags: {
|
|
5063
|
+
override_scope: boolean;
|
|
5064
|
+
override_existing_origin: boolean;
|
|
5065
|
+
override_existing_dns_record: boolean;
|
|
5066
|
+
};
|
|
5067
|
+
domains: Array<
|
|
5068
|
+
{ hostname: string } & ({ zone_id?: string } | { zone_name?: string })
|
|
5069
|
+
>;
|
|
5070
|
+
env?: string | undefined;
|
|
5071
|
+
legacyEnv?: boolean | undefined;
|
|
5072
|
+
}) {
|
|
5073
|
+
const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
|
|
5074
|
+
const environment = env && !legacyEnv ? "/environments/:envName" : "";
|
|
5075
|
+
|
|
5076
|
+
setMockResponse(
|
|
5077
|
+
`/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/domains`,
|
|
5078
|
+
"PUT",
|
|
5079
|
+
([_url, accountId, scriptName, envName], { body }) => {
|
|
5080
|
+
expect(accountId).toEqual("some-account-id");
|
|
5081
|
+
expect(scriptName).toEqual(
|
|
5082
|
+
legacyEnv && env ? `test-name-${env}` : "test-name"
|
|
5083
|
+
);
|
|
5084
|
+
if (!legacyEnv) {
|
|
5085
|
+
expect(envName).toEqual(env);
|
|
5086
|
+
}
|
|
5087
|
+
|
|
5088
|
+
expect(JSON.parse(body as string)).toEqual({
|
|
5089
|
+
...publishFlags,
|
|
5090
|
+
origins: domains,
|
|
5091
|
+
});
|
|
5092
|
+
|
|
5093
|
+
return null;
|
|
5094
|
+
}
|
|
5095
|
+
);
|
|
5096
|
+
}
|
|
5097
|
+
|
|
5098
|
+
function mockPublishCustomDomainsRequestConflictWithoutOverride({
|
|
5099
|
+
domains = [],
|
|
5100
|
+
originConflicts = false,
|
|
5101
|
+
dnsRecordConflicts = false,
|
|
5102
|
+
env = undefined,
|
|
5103
|
+
legacyEnv = false,
|
|
5104
|
+
}: {
|
|
5105
|
+
originConflicts?: boolean;
|
|
5106
|
+
dnsRecordConflicts?: boolean;
|
|
5107
|
+
domains: Array<
|
|
5108
|
+
{ hostname: string } & ({ zone_id?: string } | { zone_name?: string })
|
|
5109
|
+
>;
|
|
5110
|
+
env?: string | undefined;
|
|
5111
|
+
legacyEnv?: boolean | undefined;
|
|
5112
|
+
}) {
|
|
5113
|
+
const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
|
|
5114
|
+
const environment = env && !legacyEnv ? "/environments/:envName" : "";
|
|
5115
|
+
|
|
5116
|
+
setMockRawResponse(
|
|
5117
|
+
`/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/domains`,
|
|
5118
|
+
"PUT",
|
|
5119
|
+
([_url, accountId, scriptName, envName], { body }) => {
|
|
5120
|
+
expect(accountId).toEqual("some-account-id");
|
|
5121
|
+
expect(scriptName).toEqual(
|
|
5122
|
+
legacyEnv && env ? `test-name-${env}` : "test-name"
|
|
5123
|
+
);
|
|
5124
|
+
if (!legacyEnv) {
|
|
5125
|
+
expect(envName).toEqual(env);
|
|
5126
|
+
}
|
|
5127
|
+
|
|
5128
|
+
const parsed = JSON.parse(body as string);
|
|
5129
|
+
expect(parsed.origins).toEqual(domains);
|
|
5130
|
+
|
|
5131
|
+
if (originConflicts && !parsed.override_existing_origin) {
|
|
5132
|
+
return createFetchResult(null, false, [
|
|
5133
|
+
{
|
|
5134
|
+
code: 100116,
|
|
5135
|
+
message: `Cannot create Custom Domain "${domains[0].hostname}": Custom Domain already exists and points to a different script; retry and use option "override_existing_origin" to override`,
|
|
5136
|
+
},
|
|
5137
|
+
]);
|
|
5138
|
+
}
|
|
5139
|
+
if (dnsRecordConflicts && !parsed.override_existing_dns_record) {
|
|
5140
|
+
return createFetchResult(null, false, [
|
|
5141
|
+
{
|
|
5142
|
+
code: 100117,
|
|
5143
|
+
message: `Cannot create Custom Domain "${domains[0].hostname}": a DNS record already exists for this origin; retry and use option "override_existing_dns_record" to override`,
|
|
5144
|
+
},
|
|
5145
|
+
]);
|
|
5146
|
+
}
|
|
5147
|
+
return createFetchResult(null, true);
|
|
5148
|
+
}
|
|
5149
|
+
);
|
|
5150
|
+
}
|
|
5151
|
+
|
|
4853
5152
|
/** Create a mock handler for the request to get a list of all KV namespaces. */
|
|
4854
5153
|
function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
|
|
4855
5154
|
setMockResponse(
|
package/src/__tests__/r2.test.ts
CHANGED
|
@@ -17,6 +17,33 @@ describe("wrangler", () => {
|
|
|
17
17
|
|
|
18
18
|
describe("r2", () => {
|
|
19
19
|
describe("bucket", () => {
|
|
20
|
+
it("should show the correct help when an invalid command is passed", async () => {
|
|
21
|
+
await expect(() =>
|
|
22
|
+
runWrangler("r2 bucket foo")
|
|
23
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(`"Unknown argument: foo"`);
|
|
24
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
25
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown argument: foo[0m
|
|
26
|
+
|
|
27
|
+
"
|
|
28
|
+
`);
|
|
29
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
30
|
+
"
|
|
31
|
+
wrangler r2 bucket
|
|
32
|
+
|
|
33
|
+
Manage R2 buckets
|
|
34
|
+
|
|
35
|
+
Commands:
|
|
36
|
+
wrangler r2 bucket create <name> Create a new R2 bucket
|
|
37
|
+
wrangler r2 bucket list List R2 buckets
|
|
38
|
+
wrangler r2 bucket delete <name> Delete an R2 bucket
|
|
39
|
+
|
|
40
|
+
Flags:
|
|
41
|
+
-c, --config Path to .toml configuration file [string]
|
|
42
|
+
-h, --help Show help [boolean]
|
|
43
|
+
-v, --version Show version number [boolean]"
|
|
44
|
+
`);
|
|
45
|
+
});
|
|
46
|
+
|
|
20
47
|
describe("list", () => {
|
|
21
48
|
function mockListRequest(buckets: R2BucketInfo[]) {
|
|
22
49
|
const requests = { count: 0 };
|
|
@@ -69,10 +96,7 @@ describe("wrangler", () => {
|
|
|
69
96
|
);
|
|
70
97
|
expect(std.out).toMatchInlineSnapshot(`
|
|
71
98
|
"
|
|
72
|
-
|
|
73
|
-
`);
|
|
74
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
75
|
-
"wrangler r2 bucket create <name>
|
|
99
|
+
wrangler r2 bucket create <name>
|
|
76
100
|
|
|
77
101
|
Create a new R2 bucket
|
|
78
102
|
|
|
@@ -82,8 +106,10 @@ describe("wrangler", () => {
|
|
|
82
106
|
Flags:
|
|
83
107
|
-c, --config Path to .toml configuration file [string]
|
|
84
108
|
-h, --help Show help [boolean]
|
|
85
|
-
-v, --version Show version number [boolean]
|
|
86
|
-
|
|
109
|
+
-v, --version Show version number [boolean]"
|
|
110
|
+
`);
|
|
111
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
112
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
|
|
87
113
|
|
|
88
114
|
"
|
|
89
115
|
`);
|
|
@@ -97,10 +123,7 @@ describe("wrangler", () => {
|
|
|
97
123
|
);
|
|
98
124
|
expect(std.out).toMatchInlineSnapshot(`
|
|
99
125
|
"
|
|
100
|
-
|
|
101
|
-
`);
|
|
102
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
103
|
-
"wrangler r2 bucket create <name>
|
|
126
|
+
wrangler r2 bucket create <name>
|
|
104
127
|
|
|
105
128
|
Create a new R2 bucket
|
|
106
129
|
|
|
@@ -110,8 +133,10 @@ describe("wrangler", () => {
|
|
|
110
133
|
Flags:
|
|
111
134
|
-c, --config Path to .toml configuration file [string]
|
|
112
135
|
-h, --help Show help [boolean]
|
|
113
|
-
-v, --version Show version number [boolean]
|
|
114
|
-
|
|
136
|
+
-v, --version Show version number [boolean]"
|
|
137
|
+
`);
|
|
138
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
139
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
|
|
115
140
|
|
|
116
141
|
"
|
|
117
142
|
`);
|
|
@@ -151,10 +176,7 @@ describe("wrangler", () => {
|
|
|
151
176
|
);
|
|
152
177
|
expect(std.out).toMatchInlineSnapshot(`
|
|
153
178
|
"
|
|
154
|
-
|
|
155
|
-
`);
|
|
156
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
157
|
-
"wrangler r2 bucket delete <name>
|
|
179
|
+
wrangler r2 bucket delete <name>
|
|
158
180
|
|
|
159
181
|
Delete an R2 bucket
|
|
160
182
|
|
|
@@ -164,8 +186,10 @@ describe("wrangler", () => {
|
|
|
164
186
|
Flags:
|
|
165
187
|
-c, --config Path to .toml configuration file [string]
|
|
166
188
|
-h, --help Show help [boolean]
|
|
167
|
-
-v, --version Show version number [boolean]
|
|
168
|
-
|
|
189
|
+
-v, --version Show version number [boolean]"
|
|
190
|
+
`);
|
|
191
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
192
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mNot enough non-option arguments: got 0, need at least 1[0m
|
|
169
193
|
|
|
170
194
|
"
|
|
171
195
|
`);
|
|
@@ -179,10 +203,7 @@ describe("wrangler", () => {
|
|
|
179
203
|
);
|
|
180
204
|
expect(std.out).toMatchInlineSnapshot(`
|
|
181
205
|
"
|
|
182
|
-
|
|
183
|
-
`);
|
|
184
|
-
expect(std.err).toMatchInlineSnapshot(`
|
|
185
|
-
"wrangler r2 bucket delete <name>
|
|
206
|
+
wrangler r2 bucket delete <name>
|
|
186
207
|
|
|
187
208
|
Delete an R2 bucket
|
|
188
209
|
|
|
@@ -192,8 +213,10 @@ describe("wrangler", () => {
|
|
|
192
213
|
Flags:
|
|
193
214
|
-c, --config Path to .toml configuration file [string]
|
|
194
215
|
-h, --help Show help [boolean]
|
|
195
|
-
-v, --version Show version number [boolean]
|
|
196
|
-
|
|
216
|
+
-v, --version Show version number [boolean]"
|
|
217
|
+
`);
|
|
218
|
+
expect(std.err).toMatchInlineSnapshot(`
|
|
219
|
+
"[31mX [41;31m[[41;97mERROR[41;31m][0m [1mUnknown arguments: def, ghi[0m
|
|
197
220
|
|
|
198
221
|
"
|
|
199
222
|
`);
|
|
@@ -60,6 +60,22 @@ describe("wrangler secret", () => {
|
|
|
60
60
|
describe("interactive", () => {
|
|
61
61
|
useMockStdin({ isTTY: true });
|
|
62
62
|
|
|
63
|
+
it("should trim stdin secret value", async () => {
|
|
64
|
+
mockPrompt({
|
|
65
|
+
text: "Enter a secret value:",
|
|
66
|
+
type: "password",
|
|
67
|
+
result: `hunter2
|
|
68
|
+
`,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
mockPutRequest({ name: `secret-name`, text: `hunter2` });
|
|
72
|
+
await runWrangler("secret put secret-name --name script-name");
|
|
73
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
74
|
+
"🌀 Creating the secret for script script-name
|
|
75
|
+
✨ Success! Uploaded secret secret-name"
|
|
76
|
+
`);
|
|
77
|
+
});
|
|
78
|
+
|
|
63
79
|
it("should create a secret", async () => {
|
|
64
80
|
mockPrompt({
|
|
65
81
|
text: "Enter a secret value:",
|
|
@@ -146,6 +162,25 @@ describe("wrangler secret", () => {
|
|
|
146
162
|
describe("non-interactive", () => {
|
|
147
163
|
const mockStdIn = useMockStdin({ isTTY: false });
|
|
148
164
|
|
|
165
|
+
it("should trim stdin secret value, from piped input", async () => {
|
|
166
|
+
mockPutRequest({ name: "the-key", text: "the-secret" });
|
|
167
|
+
// Pipe the secret in as three chunks to test that we reconstitute it correctly.
|
|
168
|
+
mockStdIn.send(
|
|
169
|
+
`the`,
|
|
170
|
+
`-`,
|
|
171
|
+
`secret
|
|
172
|
+
` // whitespace & newline being removed
|
|
173
|
+
);
|
|
174
|
+
await runWrangler("secret put the-key --name script-name");
|
|
175
|
+
|
|
176
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
177
|
+
"🌀 Creating the secret for script script-name
|
|
178
|
+
✨ Success! Uploaded secret the-key"
|
|
179
|
+
`);
|
|
180
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
181
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
182
|
+
});
|
|
183
|
+
|
|
149
184
|
it("should create a secret, from piped input", async () => {
|
|
150
185
|
mockPutRequest({ name: "the-key", text: "the-secret" });
|
|
151
186
|
// Pipe the secret in as three chunks to test that we reconstitute it correctly.
|
package/src/bundle.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
|
+
import { builtinModules } from "node:module";
|
|
3
4
|
import * as path from "node:path";
|
|
4
5
|
import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
|
|
5
6
|
import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
|
|
@@ -16,6 +17,33 @@ type BundleResult = {
|
|
|
16
17
|
stop: (() => void) | undefined;
|
|
17
18
|
};
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Searches for any uses of node's builtin modules, and throws an error if it
|
|
22
|
+
* finds anything. This plugin is only used when nodeCompat is not enabled.
|
|
23
|
+
* Supports both regular node builtins, and the new "node:<MODULE>" format.
|
|
24
|
+
*/
|
|
25
|
+
const checkForNodeBuiltinsPlugin = {
|
|
26
|
+
name: "checkForNodeBuiltins",
|
|
27
|
+
setup(build: esbuild.PluginBuild) {
|
|
28
|
+
build.onResolve(
|
|
29
|
+
{
|
|
30
|
+
filter: new RegExp(
|
|
31
|
+
"^(" +
|
|
32
|
+
builtinModules.join("|") +
|
|
33
|
+
"|" +
|
|
34
|
+
builtinModules.map((module) => "node:" + module).join("|") +
|
|
35
|
+
")$"
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
() => {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Detected a Node builtin module import while Node compatibility is disabled.\nAdd node_compat = true to your wrangler.toml file to enable Node compatibility.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
19
47
|
/**
|
|
20
48
|
* Generate a bundle for the worker identified by the arguments passed in.
|
|
21
49
|
*/
|
|
@@ -60,6 +88,7 @@ export async function bundleWorker(
|
|
|
60
88
|
format: entry.format,
|
|
61
89
|
rules,
|
|
62
90
|
});
|
|
91
|
+
|
|
63
92
|
const result = await esbuild.build({
|
|
64
93
|
...getEntryPoint(entry.file, serveAssetsFromWorker),
|
|
65
94
|
bundle: true,
|
|
@@ -87,7 +116,9 @@ export async function bundleWorker(
|
|
|
87
116
|
moduleCollector.plugin,
|
|
88
117
|
...(nodeCompat
|
|
89
118
|
? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
|
|
90
|
-
:
|
|
119
|
+
: // we use checkForNodeBuiltinsPlugin to throw a nicer error
|
|
120
|
+
// if we find node builtins when nodeCompat isn't turned on
|
|
121
|
+
[checkForNodeBuiltinsPlugin]),
|
|
91
122
|
],
|
|
92
123
|
...(jsxFactory && { jsxFactory }),
|
|
93
124
|
...(jsxFragment && { jsxFragment }),
|