one 2.6.1 → 2.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assetRange.native.js","names":[],"sources":["esm/server/assetRange.native.js"],"sourcesContent":["async function withRange(request, response) {\n var range = request.headers.get(\"range\");\n if (!range || request.method !== \"GET\" || response.status !== 200 || response.headers.has(\"content-range\") || response.headers.has(\"content-encoding\")) {\n return response;\n }\n var match = /^bytes=(\\d*)-(\\d*)$/.exec(range.trim());\n if (!match || !match[1] && !match[2]) return response;\n var bytes = new Uint8Array(await response.arrayBuffer());\n var size = bytes.byteLength;\n var start;\n var end;\n if (!match[1]) {\n start = Math.max(0, size - Number(match[2]));\n end = size - 1;\n } else {\n start = Number(match[1]);\n end = match[2] ? Math.min(Number(match[2]), size - 1) : size - 1;\n }\n var headers = new Headers(response.headers);\n headers.set(\"accept-ranges\", \"bytes\");\n if (start >= size || start > end) {\n headers.set(\"content-range\", `bytes */${size}`);\n return new Response(null, {\n status: 416,\n headers\n });\n }\n headers.set(\"content-range\", `bytes ${start}-${end}/${size}`);\n headers.set(\"content-length\", String(end - start + 1));\n return new Response(bytes.subarray(start, end + 1), {\n status: 206,\n headers\n });\n}\nexport {\n withRange\n};\n//# sourceMappingURL=assetRange.js.map\n"],"mappings":";AAAA,eAAe,UAAU,SAAS,UAAU;CAC1C,IAAI,QAAQ,QAAQ,QAAQ,IAAI,OAAO;CACvC,IAAI,CAAC,SAAS,QAAQ,WAAW,SAAS,SAAS,WAAW,OAAO,SAAS,QAAQ,IAAI,eAAe,KAAK,SAAS,QAAQ,IAAI,kBAAkB,GAAG;EACtJ,OAAO;CACT;CACA,IAAI,QAAQ,sBAAsB,KAAK,MAAM,KAAK,CAAC;CACnD,IAAI,CAAC,SAAS,CAAC,MAAM,MAAM,CAAC,MAAM,IAAI,OAAO;CAC7C,IAAI,QAAQ,IAAI,WAAW,MAAM,SAAS,YAAY,CAAC;CACvD,IAAI,OAAO,MAAM;CACjB,IAAI;CACJ,IAAI;CACJ,IAAI,CAAC,MAAM,IAAI;EACb,QAAQ,KAAK,IAAI,GAAG,OAAO,OAAO,MAAM,EAAE,CAAC;EAC3C,MAAM,OAAO;CACf,OAAO;EACL,QAAQ,OAAO,MAAM,EAAE;EACvB,MAAM,MAAM,KAAK,KAAK,IAAI,OAAO,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,OAAO;CACjE;CACA,IAAI,UAAU,IAAI,QAAQ,SAAS,OAAO;CAC1C,QAAQ,IAAI,iBAAiB,OAAO;CACpC,IAAI,SAAS,QAAQ,QAAQ,KAAK;EAChC,QAAQ,IAAI,iBAAiB,WAAW,MAAM;EAC9C,OAAO,IAAI,SAAS,MAAM;GACxB,QAAQ;GACR;EACF,CAAC;CACH;CACA,QAAQ,IAAI,iBAAiB,SAAS,MAAM,GAAG,IAAI,GAAG,MAAM;CAC5D,QAAQ,IAAI,kBAAkB,OAAO,MAAM,QAAQ,CAAC,CAAC;CACrD,OAAO,IAAI,SAAS,MAAM,SAAS,OAAO,MAAM,CAAC,GAAG;EAClD,QAAQ;EACR;CACF,CAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one",
3
- "version": "2.6.1",
3
+ "version": "2.6.3",
4
4
  "description": "One is a React framework for web, iOS, and Android apps.",
5
5
  "license": "BSD-3-Clause",
6
6
  "sideEffects": [
@@ -236,18 +236,18 @@
236
236
  "@react-navigation/native-stack": "8.0.0-alpha.58",
237
237
  "@react-navigation/routers": "8.0.0-alpha.20",
238
238
  "@ungap/structured-clone": "^1.2.0",
239
- "@vxrn/color-scheme": "2.6.1",
240
- "@vxrn/compiler": "2.6.1",
241
- "@vxrn/resolve": "2.6.1",
242
- "@vxrn/tslib-lite": "2.6.1",
243
- "@vxrn/use-isomorphic-layout-effect": "2.6.1",
244
- "@vxrn/utils": "2.6.1",
245
- "@vxrn/vite-plugin-metro": "2.6.1",
239
+ "@vxrn/color-scheme": "2.6.3",
240
+ "@vxrn/compiler": "2.6.3",
241
+ "@vxrn/resolve": "2.6.3",
242
+ "@vxrn/tslib-lite": "2.6.3",
243
+ "@vxrn/use-isomorphic-layout-effect": "2.6.3",
244
+ "@vxrn/utils": "2.6.3",
245
+ "@vxrn/vite-plugin-metro": "2.6.3",
246
246
  "babel-dead-code-elimination": "1.0.10",
247
247
  "babel-plugin-module-resolver": "^5.0.2",
248
248
  "citty": "^0.1.6",
249
249
  "core-js": "^3.38.1",
250
- "create-vxrn": "2.6.1",
250
+ "create-vxrn": "2.6.3",
251
251
  "escape-string-regexp": "^5.0.0",
252
252
  "fast-deep-equal": "^3.1.3",
253
253
  "fast-glob": "^3.3.3",
@@ -269,7 +269,7 @@
269
269
  "tsconfig-paths": "^4",
270
270
  "use-latest-callback": "^0.2.3",
271
271
  "vite": "^8.2.2",
272
- "vxrn": "2.6.1",
272
+ "vxrn": "2.6.3",
273
273
  "web-streams-polyfill": "^4.3.0",
274
274
  "ws": "^8.21.0",
275
275
  "xxhashjs": "^0.2.2"
@@ -325,19 +325,19 @@
325
325
  }
326
326
  },
327
327
  "devDependencies": {
328
- "@tamagui/sheet": "3.0.3",
328
+ "@tamagui/sheet": "3.0.5",
329
329
  "@callstack/liquid-glass": "^0.8.1",
330
330
  "@react-native/babel-plugin-codegen": "0.87.1",
331
331
  "@react-native/codegen": "^0.87.1",
332
332
  "@react-navigation/core": "8.0.0-alpha.40",
333
333
  "@react-navigation/drawer": "8.0.0-alpha.57",
334
334
  "@react-navigation/native": "8.0.0-alpha.50",
335
- "@tamagui/build": "3.0.3",
335
+ "@tamagui/build": "3.0.5",
336
336
  "@types/node": "^24.10.0",
337
337
  "@types/react-dom": "^19.2.2",
338
338
  "@types/react-test-renderer": "^19.1.0",
339
339
  "@types/xxhashjs": "^0.2.4",
340
- "@vxrn/emitter": "2.6.1",
340
+ "@vxrn/emitter": "2.6.3",
341
341
  "depcheck": "^1.4.7",
342
342
  "esbuild": "^0.25.12",
343
343
  "immer": "^10.1.1",
@@ -356,7 +356,7 @@
356
356
  "typescript": "7.0.2",
357
357
  "vitest": "^4.1.0",
358
358
  "yoga-layout": "^3.2.1",
359
- "@tamagui/web": "3.0.3"
359
+ "@tamagui/web": "3.0.5"
360
360
  },
361
361
  "publishConfig": {
362
362
  "access": "public"
@@ -513,7 +513,7 @@
513
513
  }
514
514
  }
515
515
  },
516
- "releaseSourceCommit": "0d558b23541f02327d5bb9901fa8f366865feb7c",
516
+ "releaseSourceCommit": "2467826578aa2c794d7594e84873d56025b2fe77",
517
517
  "repository": {
518
518
  "type": "git",
519
519
  "url": "git+https://github.com/onejs/one.git",
package/src/cli/build.ts CHANGED
@@ -1306,7 +1306,7 @@ if (typeof MessageChannel === 'undefined') {
1306
1306
  }
1307
1307
  }
1308
1308
 
1309
- import { serve, setFetchStaticHtml } from 'one/serve-worker'
1309
+ import { serve, setFetchStaticHtml, withRange } from 'one/serve-worker'
1310
1310
 
1311
1311
  // Lazy import map - modules load on-demand when route is matched
1312
1312
  const lazyRoutes = {
@@ -1355,7 +1355,7 @@ export default {
1355
1355
  try {
1356
1356
  const assetResponse = await env.ASSETS.fetch(request)
1357
1357
  if (assetResponse && assetResponse.status !== 404) {
1358
- return assetResponse
1358
+ return await withRange(request, assetResponse)
1359
1359
  }
1360
1360
  } catch (e) {
1361
1361
  // asset not found, continue with original response
@@ -6,6 +6,7 @@ import type { One } from './vite/types'
6
6
 
7
7
  // re-export static HTML fetcher utilities for worker use
8
8
  export { getFetchStaticHtml, setFetchStaticHtml } from './server/staticHtmlFetcher'
9
+ export { withRange } from './server/assetRange'
9
10
 
10
11
  // re-export for use in generated worker code
11
12
  export type { LazyRoutes }
@@ -0,0 +1,75 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { withRange } from './assetRange'
3
+
4
+ const bytes = Uint8Array.from({ length: 100 }, (_, i) => i)
5
+
6
+ // the assets binding streams in chunks; split so ranges cross chunk edges
7
+ function asset(headers: Record<string, string> = {}) {
8
+ const chunks = [bytes.slice(0, 30), bytes.slice(30, 70), bytes.slice(70)]
9
+ const body = new ReadableStream<Uint8Array>({
10
+ start(controller) {
11
+ for (const chunk of chunks) controller.enqueue(chunk)
12
+ controller.close()
13
+ },
14
+ })
15
+ return new Response(body, {
16
+ status: 200,
17
+ // the binding sends no content-length
18
+ headers: { 'content-type': 'video/webm', ...headers },
19
+ })
20
+ }
21
+
22
+ function get(range?: string) {
23
+ return new Request('https://x.test/a.webm', range ? { headers: { range } } : {})
24
+ }
25
+
26
+ async function body(response: Response) {
27
+ return Array.from(new Uint8Array(await response.arrayBuffer()))
28
+ }
29
+
30
+ describe('withRange', () => {
31
+ it('slices a range that crosses chunks', async () => {
32
+ const res = await withRange(get('bytes=25-74'), asset())
33
+ expect(res.status).toBe(206)
34
+ expect(res.headers.get('content-range')).toBe('bytes 25-74/100')
35
+ expect(res.headers.get('content-length')).toBe('50')
36
+ expect(res.headers.get('content-type')).toBe('video/webm')
37
+ expect(await body(res)).toEqual(Array.from(bytes.slice(25, 75)))
38
+ })
39
+
40
+ it('serves the safari probe and open-ended ranges', async () => {
41
+ const probe = await withRange(get('bytes=0-1'), asset())
42
+ expect(probe.headers.get('content-range')).toBe('bytes 0-1/100')
43
+ expect(await body(probe)).toEqual([0, 1])
44
+
45
+ const open = await withRange(get('bytes=90-'), asset())
46
+ expect(open.headers.get('content-range')).toBe('bytes 90-99/100')
47
+ expect(await body(open)).toEqual(Array.from(bytes.slice(90)))
48
+ })
49
+
50
+ it('serves suffix ranges and clamps the end', async () => {
51
+ const suffix = await withRange(get('bytes=-5'), asset())
52
+ expect(suffix.headers.get('content-range')).toBe('bytes 95-99/100')
53
+ expect(await body(suffix)).toEqual([95, 96, 97, 98, 99])
54
+
55
+ const clamped = await withRange(get('bytes=98-500'), asset())
56
+ expect(clamped.headers.get('content-range')).toBe('bytes 98-99/100')
57
+ expect(await body(clamped)).toEqual([98, 99])
58
+ })
59
+
60
+ it('answers 416 past the end', async () => {
61
+ const res = await withRange(get('bytes=100-'), asset())
62
+ expect(res.status).toBe(416)
63
+ expect(res.headers.get('content-range')).toBe('bytes */100')
64
+ })
65
+
66
+ it('keeps the full response without a usable single range', async () => {
67
+ for (const [request, response] of [
68
+ [get(), asset()],
69
+ [get('bytes=0-1,5-6'), asset()],
70
+ [get('bytes=0-1'), asset({ 'content-encoding': 'gzip' })],
71
+ ] as const) {
72
+ expect(await withRange(request, response)).toBe(response)
73
+ }
74
+ })
75
+ })
@@ -0,0 +1,45 @@
1
+ // cloudflare's assets binding ignores Range and always answers 200 with the
2
+ // whole file and no content-length, which safari refuses for <video>. this
3
+ // reads that full response and answers the 206 (or 416) the browser asked
4
+ // for. multi-range requests keep the full 200, which http allows.
5
+ export async function withRange(request: Request, response: Response): Promise<Response> {
6
+ const range = request.headers.get('range')
7
+ if (
8
+ !range ||
9
+ request.method !== 'GET' ||
10
+ response.status !== 200 ||
11
+ response.headers.has('content-range') ||
12
+ response.headers.has('content-encoding')
13
+ ) {
14
+ return response
15
+ }
16
+
17
+ const match = /^bytes=(\d*)-(\d*)$/.exec(range.trim())
18
+ if (!match || (!match[1] && !match[2])) return response
19
+
20
+ const bytes = new Uint8Array(await response.arrayBuffer())
21
+ const size = bytes.byteLength
22
+
23
+ let start: number
24
+ let end: number
25
+ if (!match[1]) {
26
+ // suffix range: the last n bytes
27
+ start = Math.max(0, size - Number(match[2]))
28
+ end = size - 1
29
+ } else {
30
+ start = Number(match[1])
31
+ end = match[2] ? Math.min(Number(match[2]), size - 1) : size - 1
32
+ }
33
+
34
+ const headers = new Headers(response.headers)
35
+ headers.set('accept-ranges', 'bytes')
36
+
37
+ if (start >= size || start > end) {
38
+ headers.set('content-range', `bytes */${size}`)
39
+ return new Response(null, { status: 416, headers })
40
+ }
41
+
42
+ headers.set('content-range', `bytes ${start}-${end}/${size}`)
43
+ headers.set('content-length', String(end - start + 1))
44
+ return new Response(bytes.subarray(start, end + 1), { status: 206, headers })
45
+ }
@@ -1,6 +1,7 @@
1
1
  import { type LazyRoutes } from './server/workerHandler';
2
2
  import type { One } from './vite/types';
3
3
  export { getFetchStaticHtml, setFetchStaticHtml } from './server/staticHtmlFetcher';
4
+ export { withRange } from './server/assetRange';
4
5
  export type { LazyRoutes };
5
6
  /**
6
7
  * Creates a fetch handler for edge/worker environments (Cloudflare Workers, service workers, etc.)
@@ -1 +1 @@
1
- {"version":3,"file":"serve-worker.d.ts","sourceRoot":"","sources":["../src/serve-worker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE7E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAGvC,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAGnF,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,GAAG,CAAC,SAAS,EACxB,UAAU,CAAC,EAAE,UAAU,EACvB,YAAY,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE;;+BAelB,GAAG,CAAC,SAAS,kBAAkB,UAAU;GAKvE"}
1
+ {"version":3,"file":"serve-worker.d.ts","sourceRoot":"","sources":["../src/serve-worker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE7E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAGvC,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AACnF,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAG/C,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,GAAG,CAAC,SAAS,EACxB,UAAU,CAAC,EAAE,UAAU,EACvB,YAAY,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAE;;+BAelB,GAAG,CAAC,SAAS,kBAAkB,UAAU;GAKvE"}
@@ -0,0 +1,2 @@
1
+ export declare function withRange(request: Request, response: Response): Promise<Response>;
2
+ //# sourceMappingURL=assetRange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assetRange.d.ts","sourceRoot":"","sources":["../../src/server/assetRange.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwCvF"}