From 139d5418bd69ac29ccdd99353105220adcbc91ba Mon Sep 17 00:00:00 2001 From: Cody Olsen Date: Thu, 21 Nov 2024 16:05:33 +0100 Subject: [PATCH] let's goooo --- next-enterprise/.env.local.example | 1 + next-enterprise/.gitignore | 1 + .../expirator-service/.env.local.example | 2 + next-enterprise/expirator-service/.gitignore | 176 ++++++++++++++++++ next-enterprise/expirator-service/bun.lockb | Bin 0 -> 13862 bytes next-enterprise/expirator-service/index.ts | 44 +++++ .../expirator-service/package.json | 17 ++ .../expirator-service/tsconfig.json | 27 +++ next-enterprise/src/app/actions.ts | 5 - .../src/app/api/expire-tags/route.ts | 14 ++ 10 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 next-enterprise/.env.local.example create mode 100644 next-enterprise/expirator-service/.env.local.example create mode 100644 next-enterprise/expirator-service/.gitignore create mode 100755 next-enterprise/expirator-service/bun.lockb create mode 100644 next-enterprise/expirator-service/index.ts create mode 100644 next-enterprise/expirator-service/package.json create mode 100644 next-enterprise/expirator-service/tsconfig.json create mode 100644 next-enterprise/src/app/api/expire-tags/route.ts diff --git a/next-enterprise/.env.local.example b/next-enterprise/.env.local.example new file mode 100644 index 0000000..4bb8d31 --- /dev/null +++ b/next-enterprise/.env.local.example @@ -0,0 +1 @@ +SECRET='your-secret' \ No newline at end of file diff --git a/next-enterprise/.gitignore b/next-enterprise/.gitignore index d32cc78..a285e93 100644 --- a/next-enterprise/.gitignore +++ b/next-enterprise/.gitignore @@ -31,6 +31,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.local.example # vercel .vercel diff --git a/next-enterprise/expirator-service/.env.local.example b/next-enterprise/expirator-service/.env.local.example new file mode 100644 index 0000000..abfeeda --- /dev/null +++ b/next-enterprise/expirator-service/.env.local.example @@ -0,0 +1,2 @@ +SECRET='your-secret' +TOKEN='sk... \ No newline at end of file diff --git a/next-enterprise/expirator-service/.gitignore b/next-enterprise/expirator-service/.gitignore new file mode 100644 index 0000000..1557c42 --- /dev/null +++ b/next-enterprise/expirator-service/.gitignore @@ -0,0 +1,176 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local +!.env.local.example + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/next-enterprise/expirator-service/bun.lockb b/next-enterprise/expirator-service/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..06e8de5a6f5a6dff038a554ca320babada1703ce GIT binary patch literal 13862 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 z z@f{c6NAcYe-}CUD40XqM5`2$RhYuad1hO~&M+BtibVr@l;e$3H7wUnwpiXE5+JZJ= zU#KhUjJl&8Xb;gD?L*zsHq;I8eef;?Z9#oeZ`2>{K%3AuvO zaMXbeBt@I4MrNL&7BJ{$U&q4m`#~phOC&x=SV>o{IV!MI~p*fgfPI4>jPcC=zES4>blHV?!3J0cv1WqDUl` zv<4t767xl3n?M5t&<%V*qRmKD71W>#P($L;NZb|FpaL8-7KvCRky$hbP%IXSZ6h&U zP$TmWiGCwdUb22bIT9~N;=-i;m~c#3B!Z4aipk5#hMh%X>PYOEyxgCr93!(PF(lrO z#Farm#^6%WnncEt2rytnmqHDR!6UI|P=nqv{uYf#qR!|VV{i_O#Osl`G^jBF42%zn z#3K=B-})i3dL$<8TR$Y4k3_9~!;pAC64xfffYv0kk3_IRjVVqZ7K_9TlGr$!jjkb4 zg(P}T)(>EQ!uG>{=y?qo5=%&8=IGI;eNCbYN%S1fQA3Wg39N5eim=9`NIV^AV8H>s z4Sp~W{xkxI8gVRsK0}gaQ>9!czuz&$yr3|ih~ofbB@%cCPLPQB0)Ja|!*34}i?0t6 ziI@v32=;&m)h(h`$*LHbie;UuGHsss2{|kgi+Lho^Q=&hcJ&+k-VyA8XJOO=3)Ay* z5lWv~x-^`%6c-{Sc>cok%J658D;6&zm@o2{2t{n<<#TzG$Y7qBE8+)BhSFd4Aslw7 z*jvDtMCx+``8a8`L=?#p1P9F&bA%#){qGy)hj;A6A~QbvwVKiZI(Q7BWKQ9^%ZOS@wS3j-q|wl|R3tZ`jaI!WE~ zLrS7tV>&jjaN7PRh<}~Y*bpsmf|6;X)Owa|(k%S5ayg;_MKg@(+k&VK`gF^W}?pT#1-3hVL-d*l++7 zhVy)Vd0b&oFb#lT!9szUCo{DXk*u^aU-K?&i~#)`7r~$!!p4E7$hr{-eVd%k(wT#; zfDQ#)`eXqbAPE)t^0|CA-KYr#nazNPnT6E=+fsAG`D0H3RU_ZAadev_`@u*6(+^77 z^wx}a2JwUVTo_O3xHVzv_YHye`vNw-p(0}w9F1oVurw|LJJHgnc^VHs@H8&M`C!Vi zY=)?jlYysE3GH@T9dR&^=PL~2!M4$ah2+!#Oyujgk%PtL>+J)7#~@u-P0-K>3E-e5 z8_y6%%~;Zi8?cQ^Kn-J#1+s93A|5+b!VhHg#b7QMSGs@~A>ngpvAsq9VzIX$kL?rc z=f@L)qOdzo#~I|y6VVu79xQb(9G06<|NDlZ%l8HJ1GqVZzV8}1zAwP>g`cM93BwX3 z_+}TZO~Yng`Xk=}&5w%dF>X#9*?A5qWZ!5%G&k4D`4C~UKkJ}-qn}bui~)0$0n5zN z{TestyKnOy;EdVdBCVO*3BZ|IHvRh1T<_n;3VZ*S!>4Mq{N7yf2+612NlRjIb~9z{r)epTnf7Y literal 0 HcmV?d00001 diff --git a/next-enterprise/expirator-service/index.ts b/next-enterprise/expirator-service/index.ts new file mode 100644 index 0000000..f218553 --- /dev/null +++ b/next-enterprise/expirator-service/index.ts @@ -0,0 +1,44 @@ +import {createClient} from '@sanity/client' + +const client = createClient({ + projectId: 'hiomol4a', + dataset: 'lcapi', + apiVersion: '2024-11-21', + useCdn: false, +}) + +const appOrigin = 'https://lcapi-examples-next-enterprise.sanity.dev' +const appRoute = new URL('/api/expire-tags', appOrigin) +appRoute.searchParams.set('secret', process.env.SECRET!) + +await new Promise((resolve, reject) => { + client.live.events().subscribe({ + next: (event) => { + if (event.type === 'welcome') { + console.info( + `Connected to the Sanity Live Content API, events will be forwarded to ${appOrigin} on a protected route which expires tag entries`, + ) + } else if (event.type === 'message') { + const url = new URL(appRoute) + for (const tag of event.tags) { + url.searchParams.append('tag', tag) + } + fetch(url, {method: 'POST'}) + .then((res) => { + if (!res.ok) { + throw new TypeError('Failed', {cause: res.statusText}) + } + return res.json() + }) + .then((json) => console.info('Forwarded tags to api route', event.tags, json)) + .catch((reason) => + console.error('Failed to forward tags to api route', event, reason, url.toString()), + ) + } + }, + error: (error: unknown) => { + reject(error) + }, + complete: () => resolve(undefined), + }) +}) diff --git a/next-enterprise/expirator-service/package.json b/next-enterprise/expirator-service/package.json new file mode 100644 index 0000000..fdf2efc --- /dev/null +++ b/next-enterprise/expirator-service/package.json @@ -0,0 +1,17 @@ +{ + "name": "expirator-service", + "module": "index.ts", + "type": "module", + "devDependencies": { + "@types/bun": "latest" + }, + "scripts": { + "start": "bun run index.ts" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@sanity/client": "^6.22.5" + } +} \ No newline at end of file diff --git a/next-enterprise/expirator-service/tsconfig.json b/next-enterprise/expirator-service/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/next-enterprise/expirator-service/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/next-enterprise/src/app/actions.ts b/next-enterprise/src/app/actions.ts index 5718f57..278d6ab 100644 --- a/next-enterprise/src/app/actions.ts +++ b/next-enterprise/src/app/actions.ts @@ -3,11 +3,6 @@ import type {SyncTag} from '@sanity/client' import {expireTag} from 'next/cache' -export async function expireTags(tags: SyncTag[]) { - expireTag(...tags) - console.log(` expired tags: ${tags.join(', ')}`) -} - export async function randomColorTheme(tags: SyncTag[]) { const res = await fetch('https://lcapi-examples-api.sanity.dev/api/random-color-theme', { method: 'PUT', diff --git a/next-enterprise/src/app/api/expire-tags/route.ts b/next-enterprise/src/app/api/expire-tags/route.ts new file mode 100644 index 0000000..eb9cd89 --- /dev/null +++ b/next-enterprise/src/app/api/expire-tags/route.ts @@ -0,0 +1,14 @@ +import {expireTag} from 'next/cache' + +export async function POST(request: Request) { + const url = new URL(request.url) + const secret = url.searchParams.get('secret') + if (secret !== process.env.SECRET) { + return Response.json({error: 'Unauthorized'}, {status: 401}) + } + + const tags = url.searchParams.getAll('tag') + console.log('Expiring tags from expirator service', tags) + expireTag(...tags) + return Response.json({tags}) +}