Skip to content

Commit 4c2208a

Browse files
committed
feat: add SUBLINK_FIXED_SHORT_CODE env var for persistent short links
When SUBLINK_FIXED_SHORT_CODE is set, short links always use that code instead of generating a random one each time, so subscription URLs don't change after config updates. Behaviour: - env var set → fixed short code (KV key overwritten on each save) - env var unset → random short code (unchanged behaviour) Compatible with Cloudflare Workers, Pages, and Vercel deployments.
1 parent 9d936bb commit 4c2208a

6 files changed

Lines changed: 17 additions & 5 deletions

File tree

src/app/createApp.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ const DEFAULT_USER_AGENT = 'curl/7.74.0';
2323
export function createApp(bindings = {}) {
2424
const runtime = normalizeRuntime(bindings);
2525
const services = {
26-
shortLinks: runtime.kv ? new ShortLinkService(runtime.kv, { shortLinkTtlSeconds: runtime.config.shortLinkTtlSeconds }) : null,
26+
shortLinks: runtime.kv ? new ShortLinkService(runtime.kv, {
27+
shortLinkTtlSeconds: runtime.config.shortLinkTtlSeconds,
28+
fixedShortCode: runtime.config.fixedShortCode
29+
}) : null,
2730
configStorage: runtime.kv ? new ConfigStorageService(runtime.kv, { configTtlSeconds: runtime.config.configTtlSeconds }) : null
2831
};
2932

src/runtime/cloudflare.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export function createCloudflareRuntime(env) {
55
kv: env?.SUBLINK_KV ? new CloudflareKVAdapter(env.SUBLINK_KV) : null,
66
assetFetcher: env?.ASSETS ? (request) => env.ASSETS.fetch(request) : null,
77
logger: console,
8-
config: {}
8+
config: {
9+
fixedShortCode: env?.SUBLINK_FIXED_SHORT_CODE || null
10+
}
911
};
1012
}

src/runtime/runtimeConfig.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* @typedef {Object} RuntimeConfig
1414
* @property {number} [configTtlSeconds]
1515
* @property {number} [shortLinkTtlSeconds]
16+
* @property {string} [fixedShortCode]
1617
*/
1718

1819
/**
@@ -40,7 +41,8 @@ export function normalizeRuntime(runtime = {}) {
4041
logger: runtime.logger ?? console,
4142
config: {
4243
configTtlSeconds: runtime.config?.configTtlSeconds ?? DEFAULTS.configTtlSeconds,
43-
shortLinkTtlSeconds: runtime.config?.shortLinkTtlSeconds ?? null
44+
shortLinkTtlSeconds: runtime.config?.shortLinkTtlSeconds ?? null,
45+
fixedShortCode: runtime.config?.fixedShortCode ?? null
4446
}
4547
};
4648
}

src/runtime/vercel.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export function createVercelRuntime(env = process.env) {
1111
logger: console,
1212
config: {
1313
configTtlSeconds: undefined,
14-
shortLinkTtlSeconds: null
14+
shortLinkTtlSeconds: null,
15+
fixedShortCode: env?.SUBLINK_FIXED_SHORT_CODE || null
1516
}
1617
};
1718
}

src/services/shortLinkService.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export class ShortLinkService {
1616

1717
async createShortLink(queryString, providedCode) {
1818
const kv = this.ensureKv();
19-
const shortCode = providedCode || generateWebPath();
19+
// Fixed short code from config takes priority; then API-provided code; then random
20+
const shortCode = this.options.fixedShortCode || providedCode || generateWebPath();
2021
const ttl = this.options.shortLinkTtlSeconds;
2122
const putOptions = ttl ? { expirationTtl: ttl } : undefined;
2223
await kv.put(shortCode, queryString, putOptions);

wrangler.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ kv_namespaces = [
88
{ binding = "SUBLINK_KV", id = "8943789ed0af49659f887fc740d11240" }
99
]
1010

11+
[vars]
12+
SUBLINK_FIXED_SHORT_CODE = ""
13+
1114
[assets]
1215
directory = "./public"

0 commit comments

Comments
 (0)