1
1
#!/usr/bin/env -S npm run tsn -T
2
2
3
- /*
4
- * Generate an API token: https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
5
- * (Not Global API Key!)
3
+ /**
4
+ * Create a Worker with a Version and Deployment
5
+ *
6
+ * Docs
7
+ * - https://developers.cloudflare.com/workers/configuration/versions-and-deployments/
8
+ * - https://developers.cloudflare.com/workers/platform/infrastructure-as-code/
9
+ *
10
+ * Generate an API token:
11
+ * https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
12
+ * (Not Global API Key!)
6
13
*
7
- * Find your account id: https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
14
+ * Find your account id:
15
+ * https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
16
+ *
17
+ * Find your workers.dev subdomain:
18
+ * https://developers.cloudflare.com/workers/configuration/routing/workers-dev/
8
19
*
9
20
* Set these environment variables:
10
- * - CLOUDFLARE_API_TOKEN
11
- * - CLOUDFLARE_ACCOUNT_ID
12
- *
13
- * ### Workers for Platforms ###
14
- *
15
- * For uploading a User Worker to a dispatch namespace:
16
- * https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/
17
- *
18
- * Define a "dispatchNamespaceName" variable and change the entire "const script = " line to the following:
19
- * "const script = await client.workersForPlatforms.dispatch.namespaces.scripts.update(dispatchNamespaceName, scriptName, {"
21
+ * - CLOUDFLARE_API_TOKEN
22
+ * - CLOUDFLARE_ACCOUNT_ID
23
+ * - CLOUDFLARE_SUBDOMAIN
20
24
*/
21
25
22
26
import Cloudflare from 'cloudflare' ;
23
- import { toFile } from 'cloudflare/index' ;
24
27
25
28
const apiToken = process . env [ 'CLOUDFLARE_API_TOKEN' ] ?? '' ;
26
29
if ( ! apiToken ) {
27
- throw new Error ( 'Please set envar CLOUDFLARE_ACCOUNT_ID ' ) ;
30
+ throw new Error ( 'Please set envar CLOUDFLARE_API_TOKEN ' ) ;
28
31
}
29
32
30
33
const accountID = process . env [ 'CLOUDFLARE_ACCOUNT_ID' ] ?? '' ;
31
34
if ( ! accountID ) {
32
- throw new Error ( 'Please set envar CLOUDFLARE_API_TOKEN ' ) ;
35
+ throw new Error ( 'Please set envar CLOUDFLARE_ACCOUNT_ID ' ) ;
33
36
}
34
37
38
+ const subdomain = process . env [ 'CLOUDFLARE_SUBDOMAIN' ] ?? '' ;
39
+
35
40
const client = new Cloudflare ( {
36
- apiToken : apiToken ,
41
+ apiToken,
37
42
} ) ;
38
43
39
44
async function main ( ) {
40
- const scriptName = 'my-hello-world-script ' ;
41
- const scriptFileName = `${ scriptName } .mjs` ;
45
+ const workerName = 'my-hello-world-worker ' ;
46
+ const scriptFileName = `${ workerName } .mjs` ;
42
47
43
- // Workers Scripts prefer Module Syntax
48
+ // Workers Scripts use ES Module Syntax
44
49
// https://blog.cloudflare.com/workers-javascript-modules/
45
50
const scriptContent = `
46
51
export default {
@@ -50,37 +55,65 @@ async function main() {
50
55
};
51
56
` ;
52
57
53
- try {
54
- // https://developers.cloudflare.com/api/resources/workers/subresources/scripts/methods/update/
55
- const script = await client . workers . scripts . update ( scriptName , {
56
- account_id : accountID ,
57
- // https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/
58
- metadata : {
59
- main_module : scriptFileName ,
60
- bindings : [
61
- {
62
- type : 'plain_text' ,
63
- name : 'MESSAGE' ,
64
- text : 'Hello World!' ,
65
- } ,
66
- ] ,
58
+ /**
59
+ * Create a Worker and set non-versioned settings like observability
60
+ */
61
+ const worker = await client . workers . create ( workerName , {
62
+ account_id : accountID ,
63
+ subdomain : {
64
+ enabled : subdomain ? true : false ,
65
+ } ,
66
+ observability : {
67
+ enabled : true ,
68
+ } ,
69
+ } ) ;
70
+
71
+ /**
72
+ * Create the first version of the Worker
73
+ * This is where code and bindings are defined and can be different between versions
74
+ */
75
+ const version = await client . workers . versions . create ( worker . id , {
76
+ account_id : accountID ,
77
+ main_module : scriptFileName ,
78
+ compatibility_date : new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ,
79
+ bindings : [
80
+ {
81
+ type : 'plain_text' ,
82
+ name : 'MESSAGE' ,
83
+ text : 'Hello World!' ,
84
+ } ,
85
+ ] ,
86
+ modules : [
87
+ {
88
+ name : scriptFileName ,
89
+ content_type : 'application/javascript+module' ,
90
+ content_base64 : Buffer . from ( scriptContent ) . toString ( 'base64' ) ,
67
91
} ,
68
- files : {
69
- // Add main_module file
70
- [ scriptFileName ] : await toFile ( Buffer . from ( scriptContent ) , scriptFileName , {
71
- type : 'application/javascript+module' ,
72
- } ) ,
73
- // Can add other files, such as more modules or source maps
74
- // [sourceMapFileName]: await toFile(Buffer.from(sourceMapContent), sourceMapFileName, {
75
- // type: 'application/source-map',
76
- // }),
92
+ ] ,
93
+ } ) ;
94
+
95
+ /**
96
+ * Create a deployment and point all traffic to the version we created
97
+ * Triggers that hit fetch() in the Worker (ie. HTTP requests from workers.dev, routes, and custom domains)
98
+ * split requests between one or multiple versions by deployments
99
+ */
100
+ const deployment = await client . workers . scripts . deployments . create ( worker . name , {
101
+ account_id : accountID ,
102
+ strategy : 'percentage' ,
103
+ versions : [
104
+ {
105
+ percentage : 100 ,
106
+ version_id : version . id ,
77
107
} ,
78
- } ) ;
79
- console . log ( 'Script Upload success!' ) ;
80
- console . log ( JSON . stringify ( script , null , 2 ) ) ;
81
- } catch ( error ) {
82
- console . error ( 'Script Upload failure!' ) ;
83
- console . error ( error ) ;
108
+ ] ,
109
+ } ) ;
110
+
111
+ console . log ( JSON . stringify ( deployment , null , 2 ) ) ;
112
+ if ( subdomain ) {
113
+ console . log ( `${ workerName } is live at: ${ workerName } .${ subdomain } .workers.dev` ) ;
114
+ }
115
+ else {
116
+ console . log ( 'Setup a route, custom domain, or workers.dev subdomain to see this Worker live.' ) ;
84
117
}
85
118
}
86
119
0 commit comments