From 598afe2e32a764bd4e8f384e7c60379a4f6b859f Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Sun, 12 Feb 2023 20:00:56 +0300 Subject: [PATCH] copied netlify files --- .env.example | 4 ++++ netlify.toml | 10 ++++++++++ netlify/functions/views.ts | 35 +++++++++++++++++++++++++++++++++++ package-lock.json | 30 ++++++++++++++++++++++++++++++ package.json | 1 + redis.ts | 9 +++++++++ 6 files changed, 89 insertions(+) create mode 100644 .env.example create mode 100644 netlify.toml create mode 100644 netlify/functions/views.ts create mode 100644 redis.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c64313f --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +IS_SITE_UNDER_CONSTRUCTION=false +REDIS_HOST=redis-1234.p124.eu-central-5-5.ec2.cloud.redislabs.com +REDIS_PASSWORD=superpassword +REDIS_PORT=1234 \ No newline at end of file diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..9a237f2 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,10 @@ +[build] + command = "npm run build" + publish = "dist" + functions = "netlify/functions" + +[[redirects]] + from = "/api/*" # simplify all calls to serverless functions + to = "/.netlify/functions/:splat" # all function calls will go to this path + status = 200 # ok code + force = true # ensure to always redirect \ No newline at end of file diff --git a/netlify/functions/views.ts b/netlify/functions/views.ts new file mode 100644 index 0000000..506b427 --- /dev/null +++ b/netlify/functions/views.ts @@ -0,0 +1,35 @@ +import { Handler } from "@netlify/functions"; +import { redisClient } from "../../redis"; + +const getViewsBySlug = async (slug: string): Promise => { + let views = 1; + const data = await redisClient.get(`views:${slug}`); + if (data) views = Number.parseInt(data, 10); + if (Number.isNaN(views)) views = 1; + return views; +}; + +const handler: Handler = async (event) => { + const slug = event.queryStringParameters?.slug; + + switch (event.httpMethod) { + case "GET": { + if (!slug) return { statusCode: 400, body: "Bad request." }; + const views = await getViewsBySlug(slug); + return { statusCode: 200, body: views.toString() }; + } + case "POST": { + if (!slug) return { statusCode: 400, body: "Bad request." }; + const views = await redisClient.incr(`views:${slug}`); + return { statusCode: 200, body: views.toString() }; + } + default: { + return { + statusCode: 500, + body: "Unrecognized HTTP Method, must be one of GET/POST", + }; + } + } +}; + +export { handler }; diff --git a/package-lock.json b/package-lock.json index 9ca9c08..d098528 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@astrojs/rss": "^2.1.0", "@astrojs/sitemap": "^1.0.1", "@astrojs/solid-js": "^2.0.2", + "@netlify/functions": "^1.4.0", "astro": "^2.0.10", "astro-icon": "^0.8.0", "astro-netlify-cms": "^0.5.3", @@ -1471,6 +1472,17 @@ "rollup": ">=2" } }, + "node_modules/@netlify/functions": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.4.0.tgz", + "integrity": "sha512-gy7ULTIRroc2/jyFVGx1djCmmBMVisIwrvkqggq5B6iDcInRSy2Tpkm+V5C63hKJVkNRskKWtLQKm9ecCaQTjA==", + "dependencies": { + "is-promise": "^4.0.0" + }, + "engines": { + "node": ">=8.3.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5304,6 +5316,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, "node_modules/is-reference": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz", @@ -14302,6 +14319,14 @@ "vfile": "^5.0.0" } }, + "@netlify/functions": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-1.4.0.tgz", + "integrity": "sha512-gy7ULTIRroc2/jyFVGx1djCmmBMVisIwrvkqggq5B6iDcInRSy2Tpkm+V5C63hKJVkNRskKWtLQKm9ecCaQTjA==", + "requires": { + "is-promise": "^4.0.0" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -17193,6 +17218,11 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, "is-reference": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz", diff --git a/package.json b/package.json index 3e64965..2051707 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@astrojs/rss": "^2.1.0", "@astrojs/sitemap": "^1.0.1", "@astrojs/solid-js": "^2.0.2", + "@netlify/functions": "^1.4.0", "astro": "^2.0.10", "astro-icon": "^0.8.0", "astro-netlify-cms": "^0.5.3", diff --git a/redis.ts b/redis.ts new file mode 100644 index 0000000..52f4e9f --- /dev/null +++ b/redis.ts @@ -0,0 +1,9 @@ +import Redis from "ioredis"; + +const redisClient = new Redis({ + host: process.env.REDIS_HOST, + port: Number.parseInt(process.env.REDIS_PORT || "6379", 10), + password: process.env.REDIS_PASSWORD, +}); + +export { redisClient };