- commit
- fd3493db0feca641eb3b8e6eae9b82e97ca93d51
- parent
- ee4e6f4e5f050ee544d210789505bf4d27412732
- author
- Dami <dami.etoile@gmail.com>
| M | diagramzip-render/ | 2 | +- |
| M | diagramzip-render/ | 1 | + |
| A | diagramzip-render/ | 58 | ++++++++++++++++++++++++++++++ |
| M | diagramzip-render/ | 15 | +++++++- |
| M | diagramzip-render/ | 2 | + |
@@ -11,6 +11,7 @@
1111 "check": "tsc --noEmit",1212 "deploy:dry": "wrangler deploy --dry-run",1313 "deploy:compatibility-units": "node scripts/deploy-compatibility-units.mjs",14+ "deploy:worker-units": "node scripts/deploy-worker-units.mjs",1415 "dev": "wrangler dev",1516 "smoke": "node scripts/smoke.mjs",1617 "smoke:units": "node scripts/smoke-units.mjs",@@ -0,0 +1,58 @@
1+import { spawn } from 'node:child_process'2+import { resolve } from 'node:path'3+4+const configs = [5+ 'wrangler.units/bytefield.jsonc',6+ 'wrangler.units/nomnoml.jsonc',7+ 'wrangler.units/vega-family.jsonc',8+ 'wrangler.units/wavedrom.jsonc',9+ 'wrangler.compatibility/plantuml-family.jsonc',10+ 'wrangler.compatibility/graphviz.jsonc',11+ 'wrangler.compatibility/d2.jsonc',12+ 'wrangler.compatibility/blockdiag-family.jsonc',13+ 'wrangler.compatibility/dbml.jsonc',14+ 'wrangler.compatibility/diagramsnet.jsonc',15+ 'wrangler.compatibility/ditaa.jsonc',16+ 'wrangler.compatibility/erd.jsonc',17+ 'wrangler.compatibility/goat.jsonc',18+ 'wrangler.compatibility/pikchr.jsonc',19+ 'wrangler.compatibility/structurizr.jsonc',20+ 'wrangler.compatibility/svgbob.jsonc',21+ 'wrangler.compatibility/symbolator.jsonc',22+ 'wrangler.compatibility/tikz.jsonc',23+ 'wrangler.compatibility/umlet.jsonc',24+ 'wrangler.compatibility/wireviz.jsonc',25+]26+const wrangler = resolve(import.meta.dirname, '../node_modules/.bin/wrangler')27+const pending = [...configs]28+const failures = []29+30+async function deploy(config) {31+ await new Promise((resolvePromise, reject) => {32+ const child = spawn(wrangler, ['deploy', '--config', config], {33+ cwd: resolve(import.meta.dirname, '..'),34+ stdio: 'inherit',35+ })36+ child.on('error', reject)37+ child.on('exit', code => code === 0 ? resolvePromise() : reject(new Error(`${config} deployment exited ${code}`)))38+ })39+}40+41+async function worker() {42+ while (pending.length > 0) {43+ const config = pending.shift()44+ try {45+ await deploy(config)46+ } catch (error) {47+ failures.push(error instanceof Error ? error.message : String(error))48+ }49+ }50+}51+52+await Promise.all(Array.from({ length: 4 }, worker))53+if (failures.length > 0) {54+ for (const failure of failures) console.error(failure)55+ process.exitCode = 156+} else {57+ console.log(`${configs.length}/${configs.length} Worker renderer units deployed`)58+}@@ -4,6 +4,18 @@ import type { EngineId, RendererAdapter, RenderRequest } from './types'
44 import { parseUnitRenderRequest } from './validation'55 66 const CACHE_MAX_AGE = 1_8007+const CACHE_SCHEMA = '2'8+const EXPOSED_RESPONSE_HEADERS = [9+ 'Cache-Control',10+ 'Content-Type',11+ 'X-Diagram-Cache',12+ 'X-Diagram-Engine',13+ 'X-Diagram-Engine-Version',14+ 'X-Diagram-Pipeline',15+ 'X-Diagram-Renderer',16+ 'X-Diagram-Unit',17+ 'X-Renderer-Build',18+].join(', ')719 820 export interface RendererUnitDescriptor {921 readonly id: EngineId@@ -45,7 +57,7 @@ function base64Url(bytes: Uint8Array): string {
4557 4658 async function cacheRequestFor(request: RenderRequest, build: string): Promise<Request> {4759 const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(canonicalRequest(request)))48- return new Request(`https://diagramzip-unit-cache.invalid/${encodeURIComponent(request.engine)}/${encodeURIComponent(build)}/${base64Url(new Uint8Array(digest))}`)60+ return new Request(`https://diagramzip-unit-cache.invalid/${CACHE_SCHEMA}/${encodeURIComponent(request.engine)}/${encodeURIComponent(build)}/${base64Url(new Uint8Array(digest))}`)4961 }5062 5163 function responseWithCacheStatus(response: Response, status: 'HIT' | 'MISS'): Response {@@ -67,6 +79,7 @@ async function render(
6779 return new Response(body, {6880 headers: {6981 'Access-Control-Allow-Origin': '*',82+ 'Access-Control-Expose-Headers': EXPOSED_RESPONSE_HEADERS,7083 'Cache-Control': `public, max-age=${CACHE_MAX_AGE}`,7184 'Content-Security-Policy': "default-src 'none'; style-src 'unsafe-inline'; sandbox",7285 'Content-Type': 'image/svg+xml; charset=utf-8',@@ -39,6 +39,8 @@ describe('renderer unit protocol', () => {
3939 expect(response.status).toBe(200)4040 expect(response.headers.get('X-Diagram-Unit')).toBe('vegalite')4141 expect(response.headers.get('X-Diagram-Pipeline')).toBe('vegalite,vega')42+ expect(response.headers.get('Access-Control-Expose-Headers')).toContain('X-Diagram-Unit')43+ expect(response.headers.get('Access-Control-Expose-Headers')).toContain('X-Renderer-Build')4244 expect(await response.text()).toContain('<text x="1" y="8">ok</text>')4345 })4446