From c1ac0bf9f3104c7a8dbd2c8f240c76b22d778d9f Mon Sep 17 00:00:00 2001 From: "anirut.k" Date: Fri, 21 Mar 2025 13:45:41 +0700 Subject: [PATCH 1/5] feat: implement link upsert API endpoint - Adds a new API endpoint for creating and retrieving links - Validates link data using LinkSchema - Supports case sensitivity for link slugs - Handles existing links by returning the short link and status - Creates new links with expiration metadata in Cloudflare KV store --- server/api/link/upsert.post.ts | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 server/api/link/upsert.post.ts diff --git a/server/api/link/upsert.post.ts b/server/api/link/upsert.post.ts new file mode 100644 index 0000000..2b7da43 --- /dev/null +++ b/server/api/link/upsert.post.ts @@ -0,0 +1,38 @@ +import { LinkSchema } from '@/schemas/link' + +export default eventHandler(async (event) => { + const link = await readValidatedBody(event, LinkSchema.parse) + const { caseSensitive } = useRuntimeConfig(event) + + if (!caseSensitive) { + link.slug = link.slug.toLowerCase() + } + + const { cloudflare } = event.context + const { KV } = cloudflare.env + + // Check if link exists + const existingLink = await KV.get(`link:${link.slug}`, { type: 'json' }) + + if (existingLink) { + // If link exists, return it along with the short link + const shortLink = `${getRequestProtocol(event)}://${getRequestHost(event)}/${link.slug}` + return { link: existingLink, shortLink, status: 'existing' } + } + + // If link doesn't exist, create it + const expiration = getExpiration(event, link.expiration) + + await KV.put(`link:${link.slug}`, JSON.stringify(link), { + expiration, + metadata: { + expiration, + url: link.url, + comment: link.comment, + }, + }) + + setResponseStatus(event, 201) + const shortLink = `${getRequestProtocol(event)}://${getRequestHost(event)}/${link.slug}` + return { link, shortLink, status: 'created' } +}) From 11fdaeeb19e99c38287191234cd06a69c9f181ec Mon Sep 17 00:00:00 2001 From: wiresslend <332542601@qq.com> Date: Tue, 15 Apr 2025 11:12:53 +0800 Subject: [PATCH 2/5] solve not being able to correctly obtain CF IP --- server/utils/access-log.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/utils/access-log.ts b/server/utils/access-log.ts index d3b60cf..92d362a 100644 --- a/server/utils/access-log.ts +++ b/server/utils/access-log.ts @@ -60,7 +60,7 @@ function blobs2logs(blobs: string[]) { } export function useAccessLog(event: H3Event) { - const ip = getHeader(event, 'x-real-ip') || getRequestIP(event, { xForwardedFor: true }) + const ip = getHeader(event, 'cf-connecting-ip') || getHeader(event, 'x-real-ip') || getRequestIP(event, { xForwardedFor: true }) const { host: referer } = parseURL(getHeader(event, 'referer')) From b07e6e348c30d08d65d34b1a23f646046b35c5cf Mon Sep 17 00:00:00 2001 From: ygnask Date: Thu, 17 Apr 2025 16:40:08 +0900 Subject: [PATCH 3/5] Display creation and expiration dates on a single line --- components/dashboard/links/Link.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/dashboard/links/Link.vue b/components/dashboard/links/Link.vue index 4b36f53..ccec374 100644 --- a/components/dashboard/links/Link.vue +++ b/components/dashboard/links/Link.vue @@ -165,7 +165,7 @@ function copyLink() { - {{ shortDate(link.createdAt) }} + {{ shortDate(link.createdAt) }}

Created At: {{ longDate(link.createdAt) }}

@@ -178,7 +178,7 @@ function copyLink() { - {{ shortDate(link.expiration) }} + {{ shortDate(link.expiration) }}

Expires At: {{ longDate(link.expiration) }}

From 54d689a901c37874efe1ded0d3942ffbec05efcf Mon Sep 17 00:00:00 2001 From: ccbikai Date: Sun, 11 May 2025 13:34:39 +0800 Subject: [PATCH 4/5] docs: add iOS app to supported platforms Adds iOS app link to supported platforms in README Adjusts formatting for KV namespace setup instructions The iOS app is now available on the App Store at id6745417598 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cfe81a9..bcfec92 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,8 @@ We welcome your contributions and PRs. - [Raycast-Sink](https://github.com/foru17/raycast-sink) - [x] Apple Shortcuts - [Sink Shortcuts](https://s.search1api.com/sink001) +- [x] iOS App + - [Sink](https://apps.apple.com/app/id6745417598) - [ ] Enhanced Link Management (with Cloudflare D1) - [ ] Analytics Enhancements (Support for merging filter conditions) - [ ] Dashboard Performance Optimization (Infinite loading) @@ -99,7 +101,7 @@ We welcome your contributions and PRs. 5. Save and deploy the project. 6. Cancel the deployment, then navigate to **Settings** -> **Bindings** -> **Add**: - - **KV Namespace**: Bind the variable name `KV` to a [KV namespace](https://developers.cloudflare.com/kv/) (create a new one under **Storage & Databases** -> **KV**). + - **KV Namespace**: Bind the variable name `KV` to a [KV namespace](https://developers.cloudflare.com/kv/) (create a new one under **Storage & Databases** -> **KV**). - **Workers AI** (_Optional_): Bind the variable name `AI` to the Workers AI Catalog. - **Analytics Engine**: - In **Workers & Pages**, go to **Account details** on the right side, find `Analytics Engine`, and click `Set up` to enable the free version. From f9d76b75622b319ad8d6737eb0c088fa1a8cdf9e Mon Sep 17 00:00:00 2001 From: ccbikai Date: Sun, 11 May 2025 13:35:01 +0800 Subject: [PATCH 5/5] chore: 0.1.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e7d088..0387a28 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sink", "type": "module", - "version": "0.1.10", + "version": "0.1.11", "private": true, "packageManager": "pnpm@9.15.1", "engines": {