Add Go vanity scripts

This commit is contained in:
Andrew Ying 2025-07-29 16:31:16 +01:00
parent d86b9e38de
commit 5afd1a236c
11 changed files with 3113 additions and 97 deletions

21
global.d.ts vendored Normal file
View file

@ -0,0 +1,21 @@
import { Data, EscapeCallback, IncludeCallback, RethrowCallback } from "ejs";
declare module "*.ejs" {
/**
* Generates HTML markup from an EJS template.
*
* @param locals an object of data to be passed into the template.
* @param escape callback used to escape variables
* @param include callback used to include files at runtime with `include()`
* @param rethrow callback used to handle and rethrow errors
*
* @return Return type depends on `Options.async`.
*/
const fn: (
locals?: Data,
escape?: EscapeCallback,
include?: IncludeCallback,
rethrow?: RethrowCallback,
) => string;
export default fn;
}

2977
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,17 +2,25 @@
"name": "witos-go",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"deploy": "wrangler deploy",
"dev": "wrangler dev",
"start": "wrangler dev",
"deploy": "npm run build && wrangler deploy",
"dev": "vite dev",
"build": "vite build",
"test": "vitest",
"cf-typegen": "wrangler types"
"typegen": "wrangler types"
},
"devDependencies": {
"@cloudflare/vite-plugin": "^1.9.6",
"@cloudflare/vitest-pool-workers": "^0.8.19",
"@types/ejs": "^3.1.5",
"@types/node": "^24.1.0",
"ejs": "^3.1.10",
"typescript": "^5.5.2",
"vitest": "~3.2.0",
"wrangler": "^4.25.0"
"wrangler": "^4.26.1"
},
"dependencies": {
"ejs-lint": "^2.0.1"
}
}

View file

@ -1,18 +1,41 @@
/**
* Welcome to Cloudflare Workers! This is your first worker.
*
* - Run `npm run dev` in your terminal to start a development server
* - Open a browser tab at http://localhost:8787/ to see your worker in action
* - Run `npm run deploy` to publish your worker
*
* Bind resources to your worker in `wrangler.jsonc`. After adding bindings, a type definition for the
* `Env` object can be regenerated with `npm run cf-typegen`.
*
* Learn more at https://developers.cloudflare.com/workers/
*/
import vanity from "../templates/vanity.ejs";
export interface Env {
CACHE_MAXAGE: number;
PACKAGES: object;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
return new Response('Hello World!');
const url = new URL(request.url);
// Construct the cache key from the cache URL
const cacheKey = new Request(
`${url.protocol}//${url.host}${url.pathname}`,
request
);
const cache = caches.default;
// Check whether the value is already available in the cache
// if not, you will need to fetch it from origin, and store it in the cache
let response = await cache.match(cacheKey);
if (!response) {
const packages = env.PACKAGES;
let slug = url.pathname;
slug = slug.replace(/^\//, '');
console.log(slug);
if (packages.hasOwnProperty(slug)) {
const html = vanity(packages[slug]);
response = new Response(html, {headers: {'Content-Type': 'text/html'}});
} else {
response = new Response(null, {status: 404});
}
response.headers.append("Cache-Control", `public,max-age=${env.CACHE_MAXAGE}`);
ctx.waitUntil(cache.put(cacheKey, response.clone()));
}
return response;
},
} satisfies ExportedHandler<Env>;

11
templates/vanity.ejs Normal file
View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="<%= data.import_name %> <%= data.vcs %> <%= data.repository %>">
<meta http-equiv="refresh" content="0; url=<%= data.url %>">
</head>
<body>
<a href="<%= data.url %>">See the package</a>.
</body>
</html>

View file

@ -41,5 +41,5 @@
]
},
"exclude": ["test"],
"include": ["worker-configuration.d.ts", "src/**/*.ts"]
"include": ["worker-configuration.d.ts", "src/**/*.ts", "templates/**/*.ejs"]
}

27
vite.config.ts Normal file
View file

@ -0,0 +1,27 @@
import { defineConfig } from 'vite';
import { compile } from "ejs";
import { readFile } from "node:fs/promises";
import { relative, resolve } from "node:path";
import { cloudflare } from '@cloudflare/vite-plugin';
export default defineConfig({
plugins: [
{
name: 'ejs',
async transform(_, id) {
if (id.endsWith('.ejs')) {
const src = await readFile(id, 'utf-8');
const code = compile(src, {
client: true,
strict: true,
localsName: 'data',
views: [resolve(__dirname, 'templates')],
filename: relative(__dirname, id),
}).toString();
return `export default ${code}`;
}
},
},
cloudflare(),
],
});

View file

@ -1,11 +0,0 @@
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: './wrangler.jsonc' },
},
},
},
});

32
vitest.config.ts Normal file
View file

@ -0,0 +1,32 @@
import { compile } from "ejs";
import { readFile } from "node:fs/promises";
import { relative, resolve } from "node:path";
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';
export default defineWorkersConfig({
plugins: [
{
name: "ejs",
async transform(_, id) {
if (id.endsWith(".ejs")) {
const src = await readFile(id, "utf-8");
const code = compile(src, {
client: true,
strict: true,
localsName: "env",
views: [resolve(__dirname, "templates")],
filename: relative(__dirname, id),
}).toString();
return `export default ${code}`;
}
},
}
],
test: {
poolOptions: {
workers: {
wrangler: { configPath: './wrangler.jsonc' },
},
},
},
});

View file

@ -1,8 +1,10 @@
/* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: 869ac3b4ce0f52ba3b2e0bc70c49089e)
// Generated by Wrangler by running `wrangler types` (hash: 8d05098abb964f413acb938487d4548b)
// Runtime types generated with workerd@1.20250712.0 2025-07-19
declare namespace Cloudflare {
interface Env {
CACHE_MAXAGE: 86400;
PACKAGES: {"logger":""};
}
}
interface Env extends Cloudflare.Env {}

View file

@ -1,47 +1,23 @@
/**
* For more details on how to configure Wrangler, refer to:
* https://developers.cloudflare.com/workers/wrangler/configuration/
*/
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "witos-go",
"main": "src/index.ts",
"compatibility_date": "2025-07-19",
"observability": {
"enabled": true
"compatibility_date": "2025-07-12",
"routes": [
{
"pattern": "go.witos.dev",
"custom_domain": true
}
],
"vars": {
"CACHE_MAXAGE": 86400,
"PACKAGES": {
"logger": {
"import_name": "go.witos.dev/logger",
"vcs": "git",
"repository": "https://git.witine.com/witos/logger",
"url": "https://git.witine.com/witos/logger"
}
}
}
/**
* Smart Placement
* Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
*/
// "placement": { "mode": "smart" },
/**
* Bindings
* Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
* databases, object storage, AI inference, real-time communication and more.
* https://developers.cloudflare.com/workers/runtime-apis/bindings/
*/
/**
* Environment Variables
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
*/
// "vars": { "MY_VARIABLE": "production_value" },
/**
* Note: Use secrets to store sensitive data.
* https://developers.cloudflare.com/workers/configuration/secrets/
*/
/**
* Static Assets
* https://developers.cloudflare.com/workers/static-assets/binding/
*/
// "assets": { "directory": "./public/", "binding": "ASSETS" },
/**
* Service Bindings (communicate between multiple Workers)
* https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
*/
// "services": [{ "binding": "MY_SERVICE", "service": "my-service" }]
}