11#!/usr/bin/env -S npm run tsn -T
22
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!)
613 *
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/
819 *
920 * 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
2024 */
2125
2226import Cloudflare from 'cloudflare' ;
23- import { toFile } from 'cloudflare/index' ;
2427
2528const apiToken = process . env [ 'CLOUDFLARE_API_TOKEN' ] ?? '' ;
2629if ( ! apiToken ) {
27- throw new Error ( 'Please set envar CLOUDFLARE_ACCOUNT_ID ' ) ;
30+ throw new Error ( 'Please set envar CLOUDFLARE_API_TOKEN ' ) ;
2831}
2932
3033const accountID = process . env [ 'CLOUDFLARE_ACCOUNT_ID' ] ?? '' ;
3134if ( ! accountID ) {
32- throw new Error ( 'Please set envar CLOUDFLARE_API_TOKEN ' ) ;
35+ throw new Error ( 'Please set envar CLOUDFLARE_ACCOUNT_ID ' ) ;
3336}
3437
38+ const subdomain = process . env [ 'CLOUDFLARE_SUBDOMAIN' ] ?? '' ;
39+
3540const client = new Cloudflare ( {
36- apiToken : apiToken ,
41+ apiToken,
3742} ) ;
3843
3944async 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` ;
4247
43- // Workers Scripts prefer Module Syntax
48+ // Workers Scripts use ES Module Syntax
4449 // https://blog.cloudflare.com/workers-javascript-modules/
4550 const scriptContent = `
4651 export default {
@@ -50,37 +55,65 @@ async function main() {
5055 };
5156 ` ;
5257
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' ) ,
6791 } ,
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 ,
77107 } ,
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.' ) ;
84117 }
85118}
86119
0 commit comments