Ctrl K
ComunidadGuías…

scripts/generate-plugin-route-hosts.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bun
/**
 * Generates the list of hostnames / zones the plugin worker is routed on from
 * cloudflare_workers/plugin/wrangler.jsonc. The /updates edge cache purge uses
 * it to purge only the zones that can hold plugin cache entries.
 *
 * Run `bun run generate:plugin-route-hosts` after changing plugin routes;
 * tests/plugin-route-hosts.unit.test.ts fails while the file is stale.
 */
import { readFileSync, writeFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'

const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
export const WRANGLER_PATH = resolve(ROOT, 'cloudflare_workers/plugin/wrangler.jsonc')
export const GENERATED_PATH = resolve(ROOT, 'supabase/functions/_backend/plugin_runtime/utils/pluginRouteHosts.generated.ts')

/** Strips // and /* *\/ comments and trailing commas outside of strings. */
export function parseJsonc(text: string): unknown {
  let out = ''
  let inString = false
  for (let i = 0; i < text.length; i++) {
    const char = text[i]
    if (inString) {
      out += char
      if (char === '\\') {
        out += text[++i] ?? ''
        continue
      }
      if (char === '"')
        inString = false
      continue
    }
    if (char === '"') {
      inString = true
      out += char
      continue
    }
    if (char === '/' && text[i + 1] === '/') {
      while (i < text.length && text[i] !== '\n')
        i++
      out += '\n'
      continue
    }
    if (char === '/' && text[i + 1] === '*') {
      i += 2
      while (i < text.length && !(text[i] === '*' && text[i + 1] === '/'))
        i++
      i++
      continue
    }
    out += char
  }
  return JSON.parse(stripTrailingCommas(out))
}

/** Drops commas before `}` / `]`, outside strings only (string values stay intact). */
function stripTrailingCommas(text: string) {
  let out = ''
  let inString = false
  for (let i = 0; i < text.length; i++) {
    const char = text[i]
    if (inString) {
      out += char
      if (char === '\\') {
        out += text[++i] ?? ''
        continue
      }
      if (char === '"')
        inString = false
      continue
    }
    if (char === '"') {
      inString = true
      out += char
      continue
    }
    if (char === ',') {
      let next = i + 1
      while (next < text.length && /\s/.test(text[next]))
        next++
      if (text[next] === '}' || text[next] === ']')
        continue
    }
    out += char
  }
  return out
}

interface Route { pattern?: string, zone_name?: string }

export function collectPluginRouteHosts(config: unknown) {
  const hosts = new Set<string>()
  const zoneNames = new Set<string>()
  const envs = Object.values((config as { env?: Record<string, { routes?: Route[] }> }).env ?? {})
  for (const env of envs) {
    for (const route of env.routes ?? []) {
      if (route.pattern)
        hosts.add(route.pattern.split('/')[0].toLowerCase())
      if (route.zone_name)
        zoneNames.add(route.zone_name.toLowerCase())
    }
  }
  return { hosts: [...hosts].sort(), zoneNames: [...zoneNames].sort() }
}

function renderList(values: string[]) {
  return `[\n${values.map(value => `  '${value}',\n`).join('')}]`
}

export function renderGenerated(config: unknown) {
  const { hosts, zoneNames } = collectPluginRouteHosts(config)
  return `// Generated by scripts/generate-plugin-route-hosts.ts from
// cloudflare_workers/plugin/wrangler.jsonc. Do not edit by hand.

/** Hostnames the plugin worker is routed on (custom domains and route patterns). */
export const PLUGIN_ROUTE_HOSTS: readonly string[] = ${renderList(hosts)}

/** Zones named explicitly by plugin routes (custom hostnames resolve through them). */
export const PLUGIN_ROUTE_ZONE_NAMES: readonly string[] = ${renderList(zoneNames)}
`
}

if (import.meta.main) {
  writeFileSync(GENERATED_PATH, renderGenerated(parseJsonc(readFileSync(WRANGLER_PATH, 'utf8'))))
  console.log(`wrote ${GENERATED_PATH}`)
}