diff --git a/.changeset/grumpy-cooks-design.md b/.changeset/grumpy-cooks-design.md new file mode 100644 index 00000000..a481de13 --- /dev/null +++ b/.changeset/grumpy-cooks-design.md @@ -0,0 +1,5 @@ +--- +'nxjs-runtime': patch +--- + +Make `data:` scheme URLs work with `fetch()` diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 623958a1..e4f23e6f 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -20,6 +20,7 @@ "@ungap/event-target": "^0.2.4", "color-rgba": "^2.4.0", "core-js": "^3.32.1", + "data-uri-to-buffer": "^6.0.1", "dts-bundle-generator": "^8.0.1", "esbuild": "^0.17.19", "kleur": "github:TooTallNate/kleur#rgb", diff --git a/packages/runtime/src/fetch/fetch.ts b/packages/runtime/src/fetch/fetch.ts index 6981630c..a62d6bb6 100644 --- a/packages/runtime/src/fetch/fetch.ts +++ b/packages/runtime/src/fetch/fetch.ts @@ -1,3 +1,4 @@ +import { dataUriToBuffer } from 'data-uri-to-buffer'; import { def } from '../utils'; import { objectUrls } from '../polyfills/url'; import { decoder } from '../polyfills/text-decoder'; @@ -217,6 +218,21 @@ async function fetchBlob(req: Request, url: URL) { }); } +async function fetchData(req: Request, url: URL) { + if (req.method !== 'GET') { + throw new Error( + `GET method must be used when fetching "${url.protocol}" protocol (got "${req.method}")` + ); + } + const parsed = dataUriToBuffer(url); + return new Response(parsed.buffer, { + headers: { + 'content-length': String(parsed.buffer.byteLength), + 'content-type': parsed.typeFull, + }, + }); +} + async function fetchFile(req: Request, url: URL) { if (req.method !== 'GET') { throw new Error( @@ -236,6 +252,7 @@ const fetchers = new Map Promise>( [ ['http:', fetchHttp], ['blob:', fetchBlob], + ['data:', fetchData], ['file:', fetchFile], ['sdmc:', fetchFile], ['romfs:', fetchFile], @@ -249,6 +266,7 @@ const fetchers = new Map Promise>( * * - `http:` - Fetch data from the network using the HTTP protocol * - `blob:` - Fetch data from a URL constructed by {@link URL.createObjectURL | `URL.createObjectURL()`} + * - `data:` - Fetch data from a Data URI (possibly base64-encoded) * - `sdmc:` - Fetch data from a local file on the SD card * - `romfs:` - Fetch data from the RomFS partition of the nx.js application * - `file:` - Same as `sdmc:` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70f3374b..f36ee673 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -323,6 +323,9 @@ importers: core-js: specifier: ^3.32.1 version: 3.32.1 + data-uri-to-buffer: + specifier: ^6.0.1 + version: 6.0.1 dts-bundle-generator: specifier: ^8.0.1 version: 8.0.1 @@ -1239,6 +1242,11 @@ packages: stream-transform: 2.1.3 dev: true + /data-uri-to-buffer@6.0.1: + resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==} + engines: {node: '>= 14'} + dev: true + /dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} dev: true