Skip to content

Add workers assets example and update workers example to use new API #2658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 143 additions & 61 deletions examples/workers/script-upload.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,168 @@
#!/usr/bin/env -S npm run tsn -T

/*
* Generate an API token: https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
* (Not Global API Key!)
/**
* Create and deploy a Worker
*

Check failure on line 5 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `·`
* Docs:
* - https://developers.cloudflare.com/workers/configuration/versions-and-deployments/
* - https://developers.cloudflare.com/workers/platform/infrastructure-as-code/
*

Check failure on line 9 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `·`
* Prerequisites:
* 1. Generate an API token: https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
* 2. Find your account ID: https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
* 3. Find your workers.dev subdomain: https://developers.cloudflare.com/workers/configuration/routing/workers-dev/
*
* Find your account id: https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
* Environment variables:
* - CLOUDFLARE_API_TOKEN (required)
* - CLOUDFLARE_ACCOUNT_ID (required)
* - CLOUDFLARE_SUBDOMAIN (optional)
*
* Set these environment variables:
* - CLOUDFLARE_API_TOKEN
* - CLOUDFLARE_ACCOUNT_ID
*
* ### Workers for Platforms ###
*
* For uploading a User Worker to a dispatch namespace:
* https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/
*
* Define a "dispatchNamespaceName" variable and change the entire "const script = " line to the following:
* "const script = await client.workersForPlatforms.dispatch.namespaces.scripts.update(dispatchNamespaceName, scriptName, {"
* Usage:
* Run this script to deploy a simple "Hello World" Worker.
* Access it at: my-hello-world-worker.$subdomain.workers.dev
*/

import { exit } from 'node:process';

import Cloudflare from 'cloudflare';
import { toFile } from 'cloudflare/index';

const apiToken = process.env['CLOUDFLARE_API_TOKEN'] ?? '';
if (!apiToken) {
throw new Error('Please set envar CLOUDFLARE_ACCOUNT_ID');
interface Config {
apiToken: string;
accountId: string;
subdomain: string | undefined;
workerName: string;
}

const accountID = process.env['CLOUDFLARE_ACCOUNT_ID'] ?? '';
if (!accountID) {
throw new Error('Please set envar CLOUDFLARE_API_TOKEN');
const WORKER_NAME = 'my-hello-world-worker';
const SCRIPT_FILENAME = `${WORKER_NAME}.mjs`;

function loadConfig(): Config {
const apiToken = process.env['CLOUDFLARE_API_TOKEN'];
if (!apiToken) {
throw new Error('Missing required environment variable: CLOUDFLARE_API_TOKEN');
}

const accountId = process.env['CLOUDFLARE_ACCOUNT_ID'];
if (!accountId) {
throw new Error('Missing required environment variable: CLOUDFLARE_ACCOUNT_ID');
}

const subdomain = process.env['CLOUDFLARE_SUBDOMAIN'];

return {
apiToken,
accountId,
subdomain: subdomain || undefined,
workerName: WORKER_NAME,
};
}

const config = loadConfig();
const client = new Cloudflare({
apiToken: apiToken,
apiToken: config.apiToken,
});

async function main() {
const scriptName = 'my-hello-world-script';
const scriptFileName = `${scriptName}.mjs`;
async function findWorkerByName(name: string): Promise<Cloudflare.Workers.Worker | null> {
const workers = await client.workers.list({ account_id: config.accountId });
for await (const worker of workers) {
if (worker.name === name) {
return worker

Check failure on line 69 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `;`
}
}
return null;
}

async function main(): Promise<void> {
try {
console.log('🚀 Starting Worker creation and deployment...');

// Workers Scripts prefer Module Syntax
// https://blog.cloudflare.com/workers-javascript-modules/
const scriptContent = `
export default {
async fetch(request, env, ctx) {
return new Response(env.MESSAGE, { status: 200 });
const scriptContent = `
export default {
async fetch(request, env, ctx) {
return new Response(env.MESSAGE, { status: 200 });
},
}`.trim();

// Until name aliasing is support, we need to list all Workers to check if one
// with the name we're trying to use already exists
let workerResult = await findWorkerByName(config.workerName);

Check failure on line 89 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `····`
// Create the Worker entity if it doesn't exist
let worker;
if (!workerResult) {
console.log(`✏️ Creating Worker ${config.workerName}...`);
worker = await client.workers.create({
account_id: config.accountId,
name: config.workerName,
subdomain: {
enabled: config.subdomain !== undefined,
},
observability: {
enabled: true,
},
});
} else {
console.log(`♻️ Worker ${config.workerName} already exists. Using it.`);
worker = {
id: workerResult.id

Check failure on line 107 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `,`
}

Check failure on line 108 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `;`
};
`;
}

try {
// https://developers.cloudflare.com/api/resources/workers/subresources/scripts/methods/update/
const script = await client.workers.scripts.update(scriptName, {
account_id: accountID,
// https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/
metadata: {
main_module: scriptFileName,
bindings: [
{
type: 'plain_text',
name: 'MESSAGE',
text: 'Hello World!',
console.log(`⚙️ Worker id: ${worker.id}`);
console.log('✏️ Creating Worker version...');

Check failure on line 113 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `····`
// Create the first version of the Worker
const version = await client.workers.versions.create(worker.id, {
account_id: config.accountId,
main_module: SCRIPT_FILENAME,
compatibility_date: new Date().toISOString().split('T')[0]!,
bindings: [
{
type: 'plain_text',
name: 'MESSAGE',
text: 'Hello World!',
},
],
modules: [
{
name: SCRIPT_FILENAME,
content_type: 'application/javascript+module',
content_base64: Buffer.from(scriptContent).toString('base64'),
},
],
});

console.log(`⚙️ Version id: ${version.id}`);
console.log('🚚 Creating Worker deployment...');

Check failure on line 137 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `····`
// Create a deployment and point all traffic to the version we created
await client.workers.scripts.deployments.create(config.workerName, {
account_id: config.accountId,
strategy: 'percentage',
versions: [
{
percentage: 100,

Check failure on line 144 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`
version_id: version.id,

Check failure on line 145 in examples/workers/script-upload.ts

View workflow job for this annotation

GitHub Actions / lint

Delete `··`
},
],
},
files: {
// Add main_module file
[scriptFileName]: await toFile(Buffer.from(scriptContent), scriptFileName, {
type: 'application/javascript+module',
}),
// Can add other files, such as more modules or source maps
// [sourceMapFileName]: await toFile(Buffer.from(sourceMapContent), sourceMapFileName, {
// type: 'application/source-map',
// }),
},
});
console.log('Script Upload success!');
console.log(JSON.stringify(script, null, 2));

console.log('✅ Deployment successful!');

if (config.subdomain) {
console.log(`
🌍 Your Worker is live!
📍 URL: https://${config.workerName}.${config.subdomain}.workers.dev/
`);
} else {
console.log(`
⚠️ Set up a route, custom domain, or workers.dev subdomain to access your Worker.
Add CLOUDFLARE_SUBDOMAIN to your environment variables to set one up automatically.
`);
}
} catch (error) {
console.error('Script Upload failure!');
console.error(error);
console.error('❌ Deployment failed:', error);
exit(1);
}
}

Expand Down
Loading
Loading