Skip to content

Commit bfe3880

Browse files
author
Cody Koeninger
committed
restore publish durable object script that was deleted in the move
1 parent 0bc0a92 commit bfe3880

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#! /bin/bash
2+
#
3+
# This script configures a Durable Object namespace on your Cloudflare Workers account.
4+
#
5+
# This is a temporary hack needed until we add Durable Objects support to Wrangler. Once Wrangler
6+
# support exists, this script can probably go away.
7+
#
8+
# On first run, this script will ask for configuration, create the Durable Object namespace bindings,
9+
# and generate metadata.json. On subsequent runs it will just update the script from source code.
10+
11+
set -euo pipefail
12+
13+
if ! which curl >/dev/null; then
14+
echo "$0: please install curl" >&2
15+
exit 1
16+
fi
17+
18+
if ! which jq >/dev/null; then
19+
echo "$0: please install jq" >&2
20+
exit 1
21+
fi
22+
23+
# If credentials.conf doesn't exist, prompt for the values and generate it.
24+
if [ -e credentials.conf ]; then
25+
source credentials.conf
26+
else
27+
echo -n "Cloudflare account ID (32 hex digits): "
28+
read ACCOUNT_ID
29+
echo "Please create a Cloudflare API Token with Workers Scripts Edit permission on your account (can be created using the Edit Cloudflare Workers API Token template)."
30+
echo -n "API Token: "
31+
read API_TOKEN
32+
echo -n "JavaScript module file (e.g. counter.mjs): "
33+
read SCRIPT_FILE
34+
echo -n "script name: (e.g counter-worker): "
35+
read SCRIPT_NAME
36+
echo -n "class name: (e.g. Counter): "
37+
read CLASS_NAME
38+
39+
cat > credentials.conf << __EOF__
40+
ACCOUNT_ID=$ACCOUNT_ID
41+
API_TOKEN=$API_TOKEN
42+
SCRIPT_FILE=$SCRIPT_FILE
43+
SCRIPT_NAME=$SCRIPT_NAME
44+
CLASS_NAME=$CLASS_NAME
45+
__EOF__
46+
47+
chmod 600 credentials.conf
48+
49+
echo "Wrote credentials.conf with these values."
50+
fi
51+
52+
# curl_api performs a curl command passing the appropriate authorization headers, and parses the
53+
# JSON response for errors. In case of errors, exit. Otherwise, write just the result part to
54+
# stdout.
55+
curl_api() {
56+
RESULT=$(curl -s -H "Authorization: Bearer $API_TOKEN" "$@")
57+
if [ $(echo "$RESULT" | jq .success) = true ]; then
58+
echo "$RESULT" | jq .result
59+
return 0
60+
else
61+
echo "API ERROR:" >&2
62+
echo "$RESULT" >&2
63+
return 1
64+
fi
65+
}
66+
67+
# Let's verify the credentials work by listing Workers scripts and Durable Object namespaces. If
68+
# either of these requests error then we're certainly not going to be able to continue.
69+
echo "Checking credentials..."
70+
curl_api https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts >/dev/null
71+
curl_api https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/durable_objects/namespaces >/dev/null
72+
73+
# upload_script uploads our Worker code with the appropriate metadata.
74+
upload_script() {
75+
curl_api https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts/$SCRIPT_NAME \
76+
-X PUT \
77+
-F "[email protected];type=application/json" \
78+
-F "script=@$SCRIPT_FILE;type=application/javascript+module" \
79+
> /dev/null
80+
}
81+
82+
# upload_bootstrap_script is a temporary hack to work around a chicken-and-egg problem: in order
83+
# to define a Durable Object namespace, we must tell it a script and class name. But when we upload our
84+
# script, we need to configure the environment to bind to our durable object namespaces. This function
85+
# uploads a version of our script with an empty environment (no bindings). The script won't be able
86+
# to run correctly, but this gets us far enough to define the namespaces, and then we can upload the
87+
# script with full environment later.
88+
#
89+
# This is obviously dumb and we (Cloudflare) will come up with something better soon.
90+
upload_bootstrap_script() {
91+
echo '{"main_module": "'$SCRIPT_FILE'"}' > bootstrap-metadata.json
92+
curl_api https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts/$SCRIPT_NAME \
93+
-X PUT \
94+
-F "[email protected];type=application/json" \
95+
-F "script=@$SCRIPT_FILE;type=application/javascript+module" \
96+
> /dev/null
97+
rm bootstrap-metadata.json
98+
}
99+
100+
# upsert_namespace configures a Durable Object namespace so that instances of it can be created and called
101+
# from other scripts (or from the same script). This function checks if the namespace already exists,
102+
# creates it if it doesn't, and either way writes the namespace ID to stdout.
103+
#
104+
# The namespace ID can be used to configure environment bindings in other scripts (or even the same
105+
# script) such that they can send messages to instances of this namespace.
106+
upsert_namespace() {
107+
# Check if the namespace exists already.
108+
EXISTING_ID=$(\
109+
curl_api https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/durable_objects/namespaces | \
110+
jq -r ".[] | select(.script == \"$SCRIPT_NAME\" and .class == \"$1\") | .id")
111+
112+
if [ "$EXISTING_ID" != "" ]; then
113+
echo $EXISTING_ID
114+
return
115+
fi
116+
117+
# No. Create it.
118+
curl_api https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/durable_objects/namespaces \
119+
-X POST --data "{\"name\": \"$SCRIPT_NAME-$1\", \"script\": \"$SCRIPT_NAME\", \"class\": \"$1\"}" | \
120+
jq -r .id
121+
}
122+
123+
if [ ! -e metadata.json ]; then
124+
# If metadata.json doesn't exist we assume this is first-time setup and we need to create the
125+
# namespaces.
126+
127+
upload_bootstrap_script
128+
NAMESPACE_ID=$(upsert_namespace $CLASS_NAME)
129+
130+
cat > metadata.json << __EOF__
131+
{
132+
"main_module": "$SCRIPT_FILE",
133+
"bindings": [
134+
{
135+
"type": "durable_object_namespace",
136+
"name": "$CLASS_NAME",
137+
"namespace_id": "$NAMESPACE_ID"
138+
}
139+
]
140+
}
141+
__EOF__
142+
fi
143+
144+
upload_script
145+
146+
echo "App uploaded to your account under the name: $SCRIPT_NAME"
147+
echo "You may deploy it to a specific host in the Cloudflare Dashboard."

0 commit comments

Comments
 (0)