Worker migration (#5072)

* Worker migration

* Deploy on pnpm changes

* Specify package manager

* Manually bump Wrangler to 4.54

* Get rid of useless Wranglers worker

* I take it back

* Set account ID

* Fix preview alias

* feat: use workers api key

* feat: try fix

* fix: missing imports

* fix: again

* fix: only run push workflow on main or prod

* feat: remove store id?

* Populate secret store IDs

* Use correct key name

* Fix setting PREVIEW variable

* Inject variables from wrangler into shell

* Inject variables from wrangler into shell

* Add git- prefix to preview-alias

* No need to use environments now

* fix: remove test as it's covered by staging deploy

---------

Co-authored-by: Michael H. <michael@iptables.sh>
This commit is contained in:
Calum H.
2026-01-08 11:25:45 -05:00
committed by GitHub
parent 8175120c4c
commit 62e56eb27e
9 changed files with 739 additions and 47 deletions

View File

@@ -1,8 +1,7 @@
import { GenericModrinthClient, type Labrinth } from '@modrinth/api-client'
// Import directly from utils to avoid loading .vue files at config time
import { LOCALES } from '@modrinth/ui/src/composables/i18n.ts'
import serverSidedVue from '@vitejs/plugin-vue'
import { promises as fs } from 'fs'
import fs from 'fs/promises'
import { defineNuxtConfig } from 'nuxt/config'
import svgLoader from 'vite-svg-loader'
@@ -96,6 +95,11 @@ export default defineNuxtConfig({
},
}),
],
build: {
rollupOptions: {
external: ['cloudflare:workers'],
},
},
},
hooks: {
async 'nitro:config'(nitroConfig) {
@@ -183,7 +187,7 @@ export default defineNuxtConfig({
process.env.CF_PAGES_BRANCH ||
// @ts-ignore
globalThis.CF_PAGES_BRANCH ||
'master',
'main',
hash:
process.env.VERCEL_GIT_COMMIT_SHA ||
process.env.CF_PAGES_COMMIT_SHA ||
@@ -246,6 +250,11 @@ export default defineNuxtConfig({
rollupConfig: {
// @ts-expect-error because of rolldown-vite - completely fine though
plugins: [serverSidedVue()],
external: ['cloudflare:workers'],
},
preset: 'cloudflare_module',
cloudflare: {
nodeCompat: true,
},
},
devtools: {
@@ -308,11 +317,8 @@ function getFeatureFlagOverrides() {
function getDomain() {
if (process.env.NODE_ENV === 'production') {
if (process.env.SITE_URL) {
return process.env.SITE_URL
}
// @ts-ignore
else if (process.env.CF_PAGES_URL || globalThis.CF_PAGES_URL) {
if (process.env.CF_PAGES_URL || globalThis.CF_PAGES_URL) {
// @ts-ignore
return process.env.CF_PAGES_URL ?? globalThis.CF_PAGES_URL
} else if (process.env.HEROKU_APP_NAME) {

View File

@@ -11,7 +11,9 @@
"lint": "eslint . && prettier --check .",
"fix": "eslint . --fix && prettier --write .",
"intl:extract": "formatjs extract \"src/{components,composables,layouts,middleware,modules,pages,plugins,utils}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" \"src/error.vue\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
"test": "pnpm build"
"cf-deploy": "pnpm run build && wrangler deploy --env preview",
"cf-dev": "pnpm run build && wrangler dev --env preview",
"cf-typegen": "wrangler types"
},
"devDependencies": {
"@formatjs/cli": "^6.2.12",
@@ -30,7 +32,8 @@
"typescript": "^5.4.5",
"vite-svg-loader": "^5.1.0",
"vue-component-type-helpers": "^3.1.8",
"vue-tsc": "^2.0.24"
"vue-tsc": "^2.0.24",
"wrangler": "^4.54.0"
},
"dependencies": {
"@formatjs/intl-localematcher": "^0.5.4",

View File

@@ -1,3 +1,25 @@
let cachedRateLimitKey = undefined
let rateLimitKeyPromise = undefined
async function getRateLimitKey(config) {
if (config.rateLimitKey) return config.rateLimitKey
if (cachedRateLimitKey !== undefined) return cachedRateLimitKey
if (!rateLimitKeyPromise) {
rateLimitKeyPromise = (async () => {
try {
const { env } = await import('cloudflare:workers')
return await env.RATE_LIMIT_IGNORE_KEY?.get()
} catch {
return undefined
}
})()
}
cachedRateLimitKey = await rateLimitKeyPromise
return cachedRateLimitKey
}
export const useBaseFetch = async (url, options = {}, skipAuth = false) => {
const config = useRuntimeConfig()
let base = import.meta.server ? config.apiBaseUrl : config.public.apiBaseUrl
@@ -7,7 +29,7 @@ export const useBaseFetch = async (url, options = {}, skipAuth = false) => {
}
if (import.meta.server) {
options.headers['x-ratelimit-key'] = config.rateLimitKey
options.headers['x-ratelimit-key'] = await getRateLimitKey(config)
}
if (!skipAuth) {

View File

@@ -13,6 +13,17 @@ import {
} from '@modrinth/api-client'
import type { Ref } from 'vue'
async function getRateLimitKeyFromSecretsStore(): Promise<string | undefined> {
try {
// @ts-expect-error only avail in workers env
const { env } = await import('cloudflare:workers')
return await env.RATE_LIMIT_IGNORE_KEY?.get()
} catch {
// Not running in Cloudflare Workers environment
return undefined
}
}
export function createModrinthClient(
auth: Ref<{ token: string | undefined }>,
config: { apiBaseUrl: string; archonBaseUrl: string; rateLimitKey?: string },
@@ -24,7 +35,7 @@ export function createModrinthClient(
const clientConfig: NuxtClientConfig = {
labrinthBaseUrl: config.apiBaseUrl,
archonBaseUrl: config.archonBaseUrl,
rateLimitKey: config.rateLimitKey,
rateLimitKey: config.rateLimitKey || getRateLimitKeyFromSecretsStore,
features: [
// for modrinth hosting
// is skipped for normal reqs

View File

@@ -0,0 +1,59 @@
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "frontend",
"compatibility_date": "2025-12-10",
"main": "./.output/server/index.mjs",
"assets": {
"binding": "ASSETS",
"directory": "./.output/public/"
},
"compatibility_flags": ["nodejs_compat", "no_nodejs_compat_v2"],
"preview_urls": true,
"workers_dev": true,
"limits": {
"cpu_ms": 2000
},
"observability": {
"enabled": true,
"head_sampling_rate": 0.001
},
"keep_vars": false,
"secrets_store_secrets": [
{
"binding": "RATE_LIMIT_IGNORE_KEY",
"store_id": "c9024fef252d4a53adf513feca64417d",
"secret_name": "labrinth-production-ratelimit-key"
}
],
"vars": {
"ENVIRONMENT": "production",
"BASE_URL": "https://api.modrinth.com/v2/",
"BROWSER_BASE_URL": "https://api.modrinth.com/v2/",
"PYRO_BASE_URL": "https://archon.modrinth.com/",
"STRIPE_PUBLISHABLE_KEY": "pk_live_51JbFxJJygY5LJFfKLVVldb10HlLt24p421OWRsTOWc5sXYFOnFUXWieSc6HD3PHo25ktx8db1WcHr36XGFvZFVUz00V9ixrCs5"
},
"env": {
"staging": {
"observability": {
"enabled": true,
"head_sampling_rate": 0.1
},
"routes": ["staging.modrinth.com/*"],
"vars": {
"ENVIRONMENT": "staging",
"BASE_URL": "https://staging-api.modrinth.com/v2/",
"BROWSER_BASE_URL": "https://staging-api.modrinth.com/v2/",
"PYRO_BASE_URL": "https://staging-archon.modrinth.com/",
"STRIPE_PUBLISHABLE_KEY": "pk_test_51JbFxJJygY5LJFfKV50mnXzz3YLvBVe2Gd1jn7ljWAkaBlRz3VQdxN9mXcPSrFbSqxwAb0svte9yhnsmm7qHfcWn00R611Ce7b"
},
"secrets_store_secrets": [
{
"binding": "RATE_LIMIT_IGNORE_KEY",
"store_id": "c9024fef252d4a53adf513feca64417d",
"secret_name": "labrinth-staging-ratelimit-key"
}
],
"preview_urls": true
}
}
}