git.fiddlerwoaroof.com
Browse code

feat: working sample

Ed L authored on 28/09/2020 18:42:00
Showing 11 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+/target
2
+/dist
3
+**/*.rs.bk
4
+Cargo.lock
5
+bin/
6
+pkg/
7
+wasm-pack.log
8
+worker/
9
+node_modules/
10
+.cargo-ok
11
+*~
0 12
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+{
2
+  "singleQuote": false,
3
+  "semi": true,
4
+  "trailingComma": "all",
5
+  "tabWidth": 2,
6
+  "printWidth": 80
7
+}
1 9
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+Copyright (c) 2018 Ashley Williams <ashley666ashley@gmail.com>
2
+
3
+Permission is hereby granted, free of charge, to any
4
+person obtaining a copy of this software and associated
5
+documentation files (the "Software"), to deal in the
6
+Software without restriction, including without
7
+limitation the rights to use, copy, modify, merge,
8
+publish, distribute, sublicense, and/or sell copies of
9
+the Software, and to permit persons to whom the Software
10
+is furnished to do so, subject to the following
11
+conditions:
12
+
13
+The above copyright notice and this permission notice
14
+shall be included in all copies or substantial portions
15
+of the Software.
16
+
17
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+DEALINGS IN THE SOFTWARE.
0 26
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+all: index.js
2
+	wrangler publish
0 3
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+# 👷 `worker-template` Hello World
2
+
3
+A template for kick starting a Cloudflare worker project.
4
+
5
+[`index.js`](https://github.com/cloudflare/worker-template/blob/master/index.js) is the content of the Workers script.
6
+
7
+#### Wrangler
8
+
9
+To generate using [wrangler](https://github.com/cloudflare/wrangler)
10
+
11
+```
12
+wrangler generate projectname https://github.com/cloudflare/worker-template
13
+```
14
+
15
+Further documentation for Wrangler can be found [here](https://developers.cloudflare.com/workers/tooling/wrangler).
0 16
new file mode 100644
... ...
@@ -0,0 +1,116 @@
1
+addEventListener("fetch", (event) => {
2
+  event.respondWith(handleRequest(event.request));
3
+});
4
+
5
+function parse_url(url) {
6
+  const theURL = url instanceof URL ? url : new URL(url);
7
+  return [theURL.pathname.split("/"), theURL.searchParams];
8
+}
9
+
10
+function uuidv4() {
11
+  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
12
+    (
13
+      c ^
14
+      (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
15
+    ).toString(16),
16
+  );
17
+}
18
+
19
+function ok(body, init) {
20
+  return new Response(body, { ...init, status: 200 });
21
+}
22
+
23
+function handlePath(path, searchParams) {
24
+  const uuid = path.length >= 2 && path[1];
25
+  const response = path.length === 4 && path[3];
26
+  if (response) {
27
+    return { route: "respond", uuid, response, email: path[2] };
28
+  } else if (uuid) {
29
+    return { route: "summary", uuid };
30
+  } else {
31
+    return { route: "notfound", path, searchParams };
32
+  }
33
+}
34
+
35
+async function get() {}
36
+
37
+const routeHandlers = {
38
+  async notfound({ path }) {
39
+    return new Response(`invalid path ${path}`, { status: 404 });
40
+  },
41
+  async summary({ uuid }) {
42
+    const settings = await RSVPS.get(`${uuid}:settings`);
43
+
44
+    if (settings) {
45
+      const rsvps = {};
46
+      let args = { prefix: `${uuid}:response:` };
47
+      let rawRSVPs;
48
+      do {
49
+        rawRSVPs = await RSVPS.list(args);
50
+        for (let { name } of rawRSVPs.keys) {
51
+          const [_, __, email] = name.split(":");
52
+          const response = await RSVPS.get(name);
53
+          rsvps[email] = response;
54
+        }
55
+        args = { cursor: rawRSVPs.cursor };
56
+      } while (!rawRSVPs.list_complete);
57
+      const responseData = {
58
+        settings: JSON.parse(settings),
59
+        rsvps,
60
+      };
61
+      return ok(JSON.stringify(responseData), {
62
+        headers: { "Content-Type": "application/json" },
63
+      });
64
+    } else {
65
+      return new Response(`invalid invite ${uuid}`, { status: 404 });
66
+    }
67
+  },
68
+
69
+  async respond({ uuid, email, response }) {
70
+    const settings = await RSVPS.get(`${uuid}:settings`);
71
+    if (settings) {
72
+      if (!email.includes("@")) {
73
+        return new Response(`invalid email ${response}`, { status: 404 });
74
+      }
75
+      if (response === "yes" || response === "no" || response === "maybe") {
76
+        await RSVPS.put(`${uuid}:response:${email}`, response);
77
+        return new Response(`${uuid} ${email} ${response}`, { status: 200 });
78
+      } else {
79
+        return new Response(`invalid response ${response}`, { status: 404 });
80
+      }
81
+    } else {
82
+      return new Response(`invalid invite ${uuid}`, { status: 404 });
83
+    }
84
+  },
85
+};
86
+
87
+const methodHandlers = {
88
+  async GET(p, sp) {
89
+    const route = handlePath(p, sp);
90
+    return await routeHandlers[route.route](route);
91
+  },
92
+  async POST() {
93
+    const inviteUUID = uuidv4();
94
+    await RSVPS.put(`${inviteUUID}:settings`, "{}");
95
+    return ok(inviteUUID);
96
+  },
97
+  default() {
98
+    return new Response("405 unsupported", { status: 405 });
99
+  },
100
+};
101
+
102
+/**
103
+ * Respond with hello worker text
104
+ * @param {Request} request
105
+ */
106
+async function handleRequest(request) {
107
+  /** @type {number} */
108
+  const nums = JSON.parse((await RSVPS.get("test:count")) || "0") + 1;
109
+  await RSVPS.put("test:count", JSON.stringify(nums));
110
+  const [p, sp] = parse_url(request.url);
111
+
112
+  return await (methodHandlers[request.method] || methodHandlers.default)(
113
+    p,
114
+    sp,
115
+  );
116
+}
0 117
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+{
2
+  "compilerOptions": {
3
+    "target": "ES2015",
4
+    "module": "commonjs",
5
+    "strict": true,
6
+    "checkJs": true,
7
+    "declaration": true,
8
+    "allowJs": true,
9
+    "esModuleInterop": true,
10
+    "skipLibCheck": true,
11
+    "forceConsistentCasingInFileNames": true
12
+  },
13
+  "$schema": "https://json.schemastore.org/tsconfig",
14
+  "display": "Recommended"
15
+}
0 16
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+{
2
+  "name": "rsvp-app",
3
+  "version": "1.0.0",
4
+  "lockfileVersion": 1,
5
+  "requires": true,
6
+  "dependencies": {
7
+    "js-generic-functions": {
8
+      "version": "1.0.9",
9
+      "resolved": "https://registry.npmjs.org/js-generic-functions/-/js-generic-functions-1.0.9.tgz",
10
+      "integrity": "sha512-HeP+M0CLtu8wHwjXKdBIZr2AH7ZCwvlenpyPbyMh55G7+Q/11vF69VC+kfJcHZvZERvEwp2v4F/FexyNnbugqQ=="
11
+    }
12
+  }
13
+}
0 14
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+{
2
+  "private": true,
3
+  "name": "rsvp-app",
4
+  "version": "1.0.0",
5
+  "description": "A template for kick starting a Cloudflare Workers project",
6
+  "main": "index.js",
7
+  "scripts": {
8
+    "test": "echo \"Error: no test specified\" && exit 1",
9
+    "format": "prettier --write '**/*.{js,css,json,md}'"
10
+  },
11
+  "author": "Ed L <el-github@elangley.org>",
12
+  "license": "MIT",
13
+  "devDependencies": {
14
+    "prettier": "^1.18.2"
15
+  },
16
+  "dependencies": {
17
+    "js-generic-functions": "^1.0.9"
18
+  }
19
+}
0 20
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+name = "rsvp-app"
2
+type = "javascript"
3
+account_id = "0c5cfb800fa787999691af697a46979f"
4
+workers_dev = true
5
+route = ""
6
+zone_id = "b715c3adbc8152a7bbbccc1c49fee5a5"
7
+kv_namespaces = [
8
+	 { binding = "RSVPS", id = "9283a7d54f47456caa8e252779312239" }
9
+]