diff --git a/.github/workflows/build-n-publish.yml b/.github/workflows/build-n-publish.yml index 1524d08..584985e 100644 --- a/.github/workflows/build-n-publish.yml +++ b/.github/workflows/build-n-publish.yml @@ -15,6 +15,7 @@ jobs: outputs: frontend-changed: ${{ steps.changes.outputs.frontend-changed }} data-changed: ${{ steps.changes.outputs.data-changed }} + backend-changed: ${{ steps.changes.outputs.backend-changed }} steps: - name: Checkout uses: actions/checkout@v3.5.0 @@ -24,6 +25,7 @@ jobs: run: | FRONTEND_DIFF=$(git diff --name-only origin/main -- frontend/* | wc -l | xargs) DATA_DIFF=$(git diff --name-only origin/main -- data/* | wc -l | xargs) + BACKEND_DIFF=$(git diff --name-only origin/main -- backend/* | wc -l | xargs) if [[ "$FRONTEND_DIFF" == "1" ]]; then echo "frontend-changed=true" >> $GITHUB_OUTPUT @@ -33,6 +35,10 @@ jobs: echo "data-changed=true" >> $GITHUB_OUTPUT fi + if [[ "$BACKEND_DIFF" == "1" ]]; then + echo "backend-changed=true" >> $GITHUB_OUTPUT + fi + build-frontend: name: Build Frontend @@ -103,3 +109,21 @@ jobs: apiToken: ${{ secrets.CF_API_KEY }} accountId: ${{ secrets.CF_ACCOUNT }} command: r2 object put flinnlab-blog/rss.xml --file ./data/rss.xml + + + deploy-backend: + name: Deploy Backend + if: ${{ needs.setup.outputs.backend-changed == 'true' }} + needs: [setup] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3.5.0 + + - name: Deploy Backend + uses: cloudflare/wrangler-action@2.0.0 + with: + apiToken: ${{ secrets.CF_API_KEY }} + accountId: ${{ secrets.CF_ACCOUNT }} + workingDirectory: backend + command: deploy --env production diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 730d78d..e7fc906 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,24 @@ jobs: run: | npm run build:posts npm run build:rss + + + test-backend: + name: Deploy & Test Backend + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3.5.0 + + - name: Deploy backend + uses: cloudflare/wrangler-action@2.0.0 + with: + apiToken: ${{ secrets.CF_API_KEY }} + accountId: ${{ secrets.CF_ACCOUNT }} + workingDirectory: backend + command: deploy --env staging + + - name: Run Integration Tests + uses: grafana/k6-action@v0.3.0 + with: + filename: backend/test/script.js diff --git a/backend/package-lock.json b/backend/package-lock.json index 4bf2b6a..c6ae59a 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -8,7 +8,7 @@ "name": "blog", "version": "0.0.0", "devDependencies": { - "wrangler": "^3.0.0" + "wrangler": "^3.5.1" } }, "node_modules/@cloudflare/kv-asset-handler": { @@ -21,9 +21,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20230724.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20230724.0.tgz", - "integrity": "sha512-DQmFZWHhs8waQFYRb/Z8QmbitAvBMXnbUMUentp+3lS4eCYI0/iurTaQDiz5+ldUn9FTxD+1XuYZlTHzVNxoHw==", + "version": "1.20230814.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20230814.1.tgz", + "integrity": "sha512-aQUO7q7qXl+SVtOiMMlVKLNOSeL6GX43RKeflwzsD74dGgyHPiSfw5KCvXhkVbyN7u+yYF6HyFdaIvHLfn5jyA==", "cpu": [ "x64" ], @@ -37,9 +37,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20230724.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20230724.0.tgz", - "integrity": "sha512-C7T0v/lMjEX7c4iROSZKgIF1eGw3+sj/gFpBD6xwxfbIcrKBjncMypeLQNpRTCdBQr1W3sNpg9jagwuVX5ByZQ==", + "version": "1.20230814.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20230814.1.tgz", + "integrity": "sha512-U2mcgi+AiuI/4EY5Wk/GmygiNoCNw/V2mcHmxESqe4r6XbJYOzBdEsjnqJ05rqd0JlEM8m64jRtE6/qBnQHygg==", "cpu": [ "arm64" ], @@ -53,9 +53,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20230724.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20230724.0.tgz", - "integrity": "sha512-o0F/hj73UXOQwkPkYqZuIxpjG8gAs2eoAGqxX1HSIYRf7iUhfFcPrupwjqlNqf7Oo1h46M+sClSFjr/ZU/LCjg==", + "version": "1.20230814.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20230814.1.tgz", + "integrity": "sha512-Q4kITXLTCuG2i2Z01fbb5AjVRRIf3+lS4ZVsFbTbIwtcOOG4Ozcw7ee7tKsFES7hFqR4Eg9gMG4/aS0mmi+L2g==", "cpu": [ "x64" ], @@ -69,9 +69,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20230724.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20230724.0.tgz", - "integrity": "sha512-UpzCoo7LOuPWxFPw84TZQTPIawIDQNSb3XnC6ffMjUH/FVwHmHdngIFZxW+xjLHKMIzGNAqSn3eRHekKgO3QqA==", + "version": "1.20230814.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20230814.1.tgz", + "integrity": "sha512-BX5SaksXw+pkREVw3Rw2eSNXplqZw+14CcwW/5x/4oq/C6yn5qCvKxJfM7pukJGMI4wkJPOYops7B3g27FB/HA==", "cpu": [ "arm64" ], @@ -85,9 +85,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20230724.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20230724.0.tgz", - "integrity": "sha512-wVpPNu19fnvgsD8V6NiGPSuET0bzKmgn3wJ6RwAwQA+GQ0hdDIDVYd13aImhgO6jLfQvkduCDxeZluGZ7PPojQ==", + "version": "1.20230814.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20230814.1.tgz", + "integrity": "sha512-GWHqfyhsG/1wm2W8afkYX3q3fWXUWWD8NGtHfAs6ZVTHdW3mmYyMhKR0lc6ptBwz5i5aXRlP2S+CxxxwwDbKpw==", "cpu": [ "x64" ], @@ -1046,9 +1046,9 @@ } }, "node_modules/miniflare": { - "version": "3.20230724.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20230724.0.tgz", - "integrity": "sha512-YU8yUwoVJCiuzY2i9ZBJ+McjL/mqwKnMJfn23QedSCvx82Mys8GAlkHCH69mqSqzlSw8IVcdxec330meRRf9bg==", + "version": "3.20230814.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20230814.1.tgz", + "integrity": "sha512-LMgqd1Ut0+fnlvQepVbbBYQczQnyuuap8bgUwOyPETka0S9NR9NxMQSNaBgVZ0uOaG7xMJ/OVTRlz+TGB86PWA==", "dev": true, "dependencies": { "acorn": "^8.8.0", @@ -1063,7 +1063,7 @@ "source-map-support": "0.5.21", "stoppable": "^1.1.0", "undici": "^5.13.0", - "workerd": "1.20230724.0", + "workerd": "1.20230814.1", "ws": "^8.11.0", "youch": "^3.2.2", "zod": "^3.20.6" @@ -1127,9 +1127,9 @@ "dev": true }, "node_modules/node-abi": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", - "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.46.0.tgz", + "integrity": "sha512-LXvP3AqTIrtvH/jllXjkNVbYifpRbt9ThTtymSMSuHmhugQLAWr99QQFTm+ZRht9ziUvdGOgB+esme1C6iE6Lg==", "dev": true, "dependencies": { "semver": "^7.3.5" @@ -1535,9 +1535,9 @@ } }, "node_modules/undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.23.0.tgz", + "integrity": "sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==", "dev": true, "dependencies": { "busboy": "^1.6.0" @@ -1553,9 +1553,9 @@ "dev": true }, "node_modules/workerd": { - "version": "1.20230724.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20230724.0.tgz", - "integrity": "sha512-++D7JqS4/dk7zvtGpk+i/7G9bZtEl6lTtgAsIoSSGR1qJAxxEu21ktm9+FH0EYh7uKfizuM5H9lrTsR+3u44PA==", + "version": "1.20230814.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20230814.1.tgz", + "integrity": "sha512-zJeSEteXuAD+bpYJT8WvzTAHvIAkKPVxOV+Jy6zCLKz5e08N3OUbAF+wrvGWc8b2aB1sj+IYsdXfkv4puH+qXQ==", "dev": true, "hasInstallScript": true, "bin": { @@ -1565,17 +1565,17 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20230724.0", - "@cloudflare/workerd-darwin-arm64": "1.20230724.0", - "@cloudflare/workerd-linux-64": "1.20230724.0", - "@cloudflare/workerd-linux-arm64": "1.20230724.0", - "@cloudflare/workerd-windows-64": "1.20230724.0" + "@cloudflare/workerd-darwin-64": "1.20230814.1", + "@cloudflare/workerd-darwin-arm64": "1.20230814.1", + "@cloudflare/workerd-linux-64": "1.20230814.1", + "@cloudflare/workerd-linux-arm64": "1.20230814.1", + "@cloudflare/workerd-windows-64": "1.20230814.1" } }, "node_modules/wrangler": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.4.0.tgz", - "integrity": "sha512-sATQ84zH/zFUHSaa4hY3V24TBrad3R9HhGV47U6Ek7XRQDLQHBm0jt84mJD3sSV/hhaq5s+xidIYulhm+m1/Tg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.5.1.tgz", + "integrity": "sha512-CnrKId+pmjTfLSidM9Ut7lUDCFWEtJyY3JT3Dk+TgYHvu2zVmMgUeQQZHZfvpVN5eaEZifNQr90KEvMLy7MhHw==", "dev": true, "dependencies": { "@cloudflare/kv-asset-handler": "^0.2.0", @@ -1584,7 +1584,7 @@ "blake3-wasm": "^2.1.5", "chokidar": "^3.5.3", "esbuild": "0.16.3", - "miniflare": "3.20230724.0", + "miniflare": "3.20230814.1", "nanoid": "^3.3.3", "path-to-regexp": "^6.2.0", "selfsigned": "^2.0.1", @@ -1653,9 +1653,9 @@ } }, "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.1.tgz", + "integrity": "sha512-+qUhAMl414+Elh+fRNtpU+byrwjDFOS1N7NioLY+tSlcADTx4TkCUua/hxJvxwDXcV4397/nZ420jy4n4+3WUg==", "dev": true, "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/backend/package.json b/backend/package.json index 60dac9b..7c23592 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,9 +4,9 @@ "private": true, "scripts": { "deploy": "wrangler deploy", - "start": "wrangler dev" + "start": "wrangler dev --remote" }, "devDependencies": { - "wrangler": "^3.0.0" + "wrangler": "^3.5.1" } -} \ No newline at end of file +} diff --git a/backend/src/worker.js b/backend/src/worker.js index 5053293..0ef8f65 100644 --- a/backend/src/worker.js +++ b/backend/src/worker.js @@ -8,25 +8,129 @@ * Learn more at https://developers.cloudflare.com/workers/ */ +const corsHeaders = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET', + 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept' +} + +const getRSS = async (key, env) => { + console.log(`RSS match found`) + const rssBlob = await env.BLOG_BUCKET.get(key); + + if (rssBlob === null) { + return new Response('Object Not Found', { status: 404 }); + } + + if (env.FLAG_USE_HEADERS) { + return new Response(rssBlob.body, { status: 200, headers: { + ...corsHeaders, + 'etag': rssBlob.httpEtag, + 'Content-type': 'application/xml' + }}); + } else { + return new Response(rssBlob.body, { status: 200 }); + } +}; + +const getPostList = async (key, env) => { + const postBlob = await env.BLOG_BUCKET.get('posts.json'); + + if (postBlob === null) { + return new Response('Object Not Found', { status: 404 }); + } + + return postBlob.json() + .then(posts => ( + Object.entries(posts) + .map(([slug, post]) => { + return { + slug: post.slug, + published: post.published, + title: post.title + } + }) + )) + .then(postList => { + if (env.FLAG_USE_HEADERS) { + return new Response(JSON.stringify({ postList: postList }, null, 4), { + status: 200, + headers: { + ...corsHeaders, + 'etag': postBlob.httpEtag, + 'Content-type': 'application/json' + } + }); + } else { + return new Response(JSON.stringify({ postList: postList }, null, 4), { status: 200, }); + } + }) +} + +const getPost = async (key, env) => { + const postBlob = await env.BLOG_BUCKET.get('posts.json'); + + if (postBlob === null) { + return new Response('Object Not Found', { status: 404 }); + } + + const postSlug = key.split("/")[1]; + + return postBlob.json() + .then(posts => posts[postSlug]) + .then(post => { + if (env.FLAG_USE_HEADERS) { + return new Response(JSON.stringify({ post: post }, null, 4), { + status: 200, + headers: { + ...corsHeaders, + 'etag': postBlob.httpEtag, + 'Content-type': 'application/json' + } + }); + } + return new Response(JSON.stringify({ post: post }, null, 4), { + status: 200, + }); + }) +} + export default { async fetch(request, env) { - // For example, the request URL my-worker.account.workers.dev/image.png const url = new URL(request.url); const key = url.pathname.slice(1); - // Retrieve the key "image.png" - const object = await env.BLOG_BUCKET.get(key); - - if (object === null) { - return new Response('Object Not Found', { status: 404 }); - } + console.log(`key: ${key}`) - const headers = new Headers(); - object.writeHttpMetadata(headers); - headers.set('etag', object.httpEtag); - headers.set('Access-Control-Allow-Origin', '*'); + const routeRSS = /rss.xml/, + routePostList = /posts$/, + routePost = /posts\/*/; - return new Response(object.body, { - headers, - }); + switch (true) { + case routeRSS.test(key): + return getRSS(key, env); + break; + case routePostList.test(key): + return getPostList(key, env); + break; + case routePost.test(key): + return getPost(key, env); + break; + default: + if (env.FLAG_USE_HEADERS) { + return new Response(JSON.stringify({ message: `/${key} not found`}, null, 2), { + status: 404, + headers: { + ...corsHeaders, + 'Content-type': 'application/json', + 'My-Header-test': 'did it come through?' + }, + }); + } else { + return new Response(JSON.stringify({ message: `/${key} not found`}, null, 2), { + status: 404, + }); + } + break; + } }, }; diff --git a/backend/test/script.js b/backend/test/script.js new file mode 100644 index 0000000..77c4e64 --- /dev/null +++ b/backend/test/script.js @@ -0,0 +1,60 @@ +import { check, group, sleep } from 'k6' +import http from 'k6/http' + +/* +export const options = { + duration: '10s', + vus: 1, + thresholds: { + http_req_failed: ['rate==0.00'], + http_req_duration: ['p(95)<1000'], + }, +} +*/ + +//let shortenLink + +const BASE_URL = "https://blog-dev.flinnlab.workers.dev" + +export default function () { + group('rss feed', function () { + const res = http.get(`${BASE_URL}/rss.xml`) + + check(res, { + 'is status 200': (r) => r.status === 200, + 'verify RSS feed': (r) => r.body.includes('flinnlab.com') + }) + + sleep(1) // second + }) + + group('list of posts', function () { + const res = http.get(`${BASE_URL}/posts`) + + check(res, { + 'is status 200': (r) => r.status === 200, + 'is formatted correctly': (r) => 'postList' in r.json(), + 'is not empty': (r) => r.json()['postList'].length != 0 + }) + + sleep(1) // second + }) + + group('post', function () { + const res = http.get(`${BASE_URL}/posts/git-monorepo`) + + check(res, { + 'is status 200': (r) => r.status === 200, + 'is formatted correctly': (r) => 'post' in r.json(), + 'contains all metadata': (r) => { + return ['slug', 'title', 'published', 'description', 'body'] + .map(key => + key in r.json()['post'] + ) + .reduce((allMetaDataExists, metadataExists) => allMetaDataExists && metadataExists, true); + } + }) + + sleep(1) // second + }) +} diff --git a/backend/wrangler.toml b/backend/wrangler.toml index 9030ab4..7c59de7 100644 --- a/backend/wrangler.toml +++ b/backend/wrangler.toml @@ -2,50 +2,40 @@ name = "blog" main = "src/worker.js" compatibility_date = "2023-08-01" -# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables) -# Note: Use secrets to store sensitive data. -# Docs: https://developers.cloudflare.com/workers/platform/environment-variables -# [vars] -# MY_VARIABLE = "production_value" - -# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs. -# Docs: https://developers.cloudflare.com/workers/runtime-apis/kv -# [[kv_namespaces]] -# binding = "MY_KV_NAMESPACE" -# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - -# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files. -# Docs: https://developers.cloudflare.com/r2/api/workers/workers-api-usage/ -[[r2_buckets]] -binding = "BLOG_BUCKET" -bucket_name = "flinnlab-blog" - -# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer. -# Docs: https://developers.cloudflare.com/queues/get-started -# [[queues.producers]] -# binding = "MY_QUEUE" -# queue = "my-queue" - -# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them. -# Docs: https://developers.cloudflare.com/queues/get-started -# [[queues.consumers]] -# queue = "my-queue" - -# Bind another Worker service. Use this binding to call another Worker without network overhead. -# Docs: https://developers.cloudflare.com/workers/platform/services -# [[services]] -# binding = "MY_SERVICE" -# service = "/api/*" - -# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model. -# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps. -# Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects -# [[durable_objects.bindings]] -# name = "MY_DURABLE_OBJECT" -# class_name = "MyDurableObject" - -# Durable Object migrations. -# Docs: https://developers.cloudflare.com/workers/learning/using-durable-objects#configure-durable-object-classes-with-migrations -# [[migrations]] -# tag = "v1" -# new_classes = ["MyDurableObject"] +workers_dev = true +r2_buckets = [ + { binding = "BLOG_BUCKET", bucket_name = "flinnlab-blog-dev", preview_bucket_name = "flinnlab-blog-dev"} +] + +[vars] +FLAG_USE_HEADERS=true + +[dev] +ip = "0.0.0.0" +local_protocol = "http" +port = 8787 +upstream_protocol = "https" + + +[env.staging] +name = "blog-dev" + +workers_dev = true +r2_buckets = [ + { binding = "BLOG_BUCKET", bucket_name = "flinnlab-blog-dev" } +] + +[env.staging.vars] +FLAG_USE_HEADERS=true + + +[env.production] +name = "blog" + +workers_dev = true +r2_buckets = [ + { binding = "BLOG_BUCKET", bucket_name = "flinnlab-blog" } +] + +[env.production.vars] +FLAG_USE_HEADERS=true diff --git a/data/scripts/buildPosts.js b/data/scripts/buildPosts.js index 79d6858..304d8f0 100644 --- a/data/scripts/buildPosts.js +++ b/data/scripts/buildPosts.js @@ -3,6 +3,7 @@ import fs from 'fs'; const POSTS_DIR = './posts'; const OUTPUT_DIR = '.'; +const POSTS_REQUIRED_METADATA = ["title", "published", "slug", "description"]; const assert = (condition, message) => { @@ -28,14 +29,13 @@ const filenames = fs.readdirSync(POSTS_DIR); const posts = filenames.reduce((results, filename) => { if (filename.substring(0, 3) == "wip" ) return results; - const requiredMetaDataKeys = ["title", "published", "slug", "description"]; const fileData = fs.readFileSync(`./${POSTS_DIR}/${filename}`, 'utf8'); const [ data, ...rawBody ] = fileData.split("---\n"); const body = rawBody.join('---\n'); const postMetadata = extractData(data.split("\n")); - requiredMetaDataKeys.map(key => assert( + POSTS_REQUIRED_METADATA.map(key => assert( key in postMetadata, `${filename} - "${key}" is a required post metadata` )); diff --git a/frontend/.env b/frontend/.env index 652907c..182952b 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1,4 +1,4 @@ -PUBLIC_DATASOURCE_TYPE=local -PUBLIC_DATASOURCE=../posts.json +PUBLIC_DATASOURCE_TYPE=network_dynamic +PUBLIC_DATASOURCE=https://blog-dev.flinnlab.workers.dev PUBLIC_LOGGING_ENABLED=true diff --git a/frontend/README.md b/frontend/README.md index d7cc4ef..9c739e2 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -9,7 +9,7 @@ dev` and uses `.env.production` when running `vite build`. | Name | Supported Values | Description | | ---- | ---------------- | ----------- | -| `PUBLIC_DATASOURCE_TYPE` | `local`, `network_static`, `network_dynamic` (not yet implemented) | The datasource type +| `PUBLIC_DATASOURCE_TYPE` | `localfs`, `network_static`, `network_dynamic` (not yet implemented) | The datasource type teslls the `$lib/helper.js:getPosts()` where to load posts from. It is helpful to load posts from the local machine while writing the article to make sure the formatting is as intended | | `PUBLIC_DATASOURCE` | `$string` | Where to load the data from with the given type. For `network_*`, an URL is diff --git a/frontend/src/404.html b/frontend/src/404.html new file mode 100644 index 0000000..12c8604 --- /dev/null +++ b/frontend/src/404.html @@ -0,0 +1 @@ +