@sproutboat/toolchain 0.10.0 → 0.10.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @sproutboat/toolchain
2
2
 
3
+ ## 0.10.2
4
+
5
+ ### Patch Changes
6
+
7
+ - bc3fd25: `Response.body` and `Request.body` are `ReadableStream`s only from compatibility date `2026-10-21`. 0.19.0 changed this for every app, which broke handlers that read `request.body` as a string, such as `JSON.parse(request.body)` in the CLI's own D1 example. An app with an earlier `compatibility_date` keeps the raw body, as before. To opt in, move `compatibility_date` to `2026-10-21` or later and rebuild.
8
+
9
+ ## 0.10.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 6676ead: `env.BUCKET.put(key, request.body)`, `env.KV.put(key, request.body)` and `fetch(url, { body: request.body })` store and send the request body again. Since 0.19.0, `body` is a `ReadableStream`, and these took its string form. Incoming request bodies are also read as the bytes they are, so `arrayBuffer()`, `blob()`, `body` and KV `put` no longer UTF-8 encode a non-ASCII upload twice. R2 `put` accepts bytes as well.
14
+
3
15
  ## 0.10.0
4
16
 
5
17
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutboat/toolchain",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -72,13 +72,19 @@ export const REQUEST_CLASS_SOURCE = String.raw`class Request {
72
72
  // body is a ReadableStream, as in Fetch: a stream body itself, else a stream made once over
73
73
  // the bytes. The value as given stays in _bodyInit, which the native writer, streaming and
74
74
  // the prelude read; assigning body (the native ingress does) sets it.
75
+ // From compatibility date 2026-10-21. Before it, body is the value as given, as it always
76
+ // was here (apps read request.body as a string); a deployed handler keeps its behaviour.
75
77
  static _bodyAsStream(message) {
76
78
  const init = message._bodyInit;
79
+ if (!(globalThis.__sbCompat >= '2026-10-21')) return init;
77
80
  if (init == null) return null;
78
81
  if (Request._isStream(init)) return init;
79
82
  if (message._bodyStream == null) {
80
- const bytes = Request._bodyBytes(init);
83
+ const bytes = Request._messageBytes(message, init);
81
84
  message._bodyStream = new globalThis.ReadableStream({ start(c) { if (bytes.length) c.enqueue(bytes); c.close(); } });
85
+ // The value the stream was made from, for the bindings that take a body at once
86
+ // (R2 and KV put, outbound fetch): put(key, request.body) is the Workers idiom.
87
+ message._bodyStream._sbBody = message._bodyLatin1 === true ? bytes : init;
82
88
  }
83
89
  return message._bodyStream;
84
90
  }
@@ -120,7 +126,17 @@ export const REQUEST_CLASS_SOURCE = String.raw`class Request {
120
126
  static _read(message, finish) {
121
127
  const body = Request._consume(message);
122
128
  if (Request._isStream(body)) return Request._streamBytes(body).then(finish);
123
- return finish(Request._bodyBytes(body));
129
+ return finish(Request._messageBytes(message, body));
130
+ }
131
+ // A body the native ingress delivered is its raw bytes, one character each
132
+ // (_bodyLatin1): those bytes, not the string UTF-8 encoded again.
133
+ static _messageBytes(message, body) {
134
+ if (message._bodyLatin1 === true && typeof body == 'string') {
135
+ const out = new Uint8Array(body.length);
136
+ for (let i = 0; i < body.length; i++) out[i] = body.charCodeAt(i) & 255;
137
+ return out;
138
+ }
139
+ return Request._bodyBytes(body);
124
140
  }
125
141
 
126
142
  constructor(input, init = undefined) {
@@ -21,7 +21,7 @@ export const PATCH_SOURCES = [
21
21
  * patch.ts as the module patch.ts is everywhere else. Kept current by fingerprint.test.ts
22
22
  * (UPDATE_FINGERPRINT=1 bun test packages/toolchain/src/fingerprint.test.ts).
23
23
  */
24
- export const RELEASED_FINGERPRINT = "405c8f04fb7d";
24
+ export const RELEASED_FINGERPRINT = "300297573305";
25
25
 
26
26
  /** The fingerprint of the sources in dir, or null where they are not on disk. */
27
27
  export function sourceFingerprint(dir: string): string | null {