sproutboat 0.36.0 → 0.37.0
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 +21 -0
- package/README.md +3 -1
- package/SURFACE.md +1 -1
- package/package.json +7 -7
- package/src/types-gen.ts +14 -5
- package/types/sproutboat.d.ts +134 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,27 @@ maintained going forward by the `release` skill.
|
|
|
10
10
|
|
|
11
11
|
## Unreleased
|
|
12
12
|
|
|
13
|
+
## [0.37.0] - 2026-10-27
|
|
14
|
+
|
|
15
|
+
Built on `@sproutboat/runtime` 0.34.1, `@sproutboat/toolchain` 0.19.1 and
|
|
16
|
+
`@sproutboat/wire` 0.20.2.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **A failed binding call you do not await no longer ends the process.** An un-awaited
|
|
21
|
+
`db.prepare("INSERT ...").run()` that broke a foreign key used to take the whole binary down, even
|
|
22
|
+
with a `try` / `catch` around the call. As on Workers, an unhandled rejection is now logged
|
|
23
|
+
(`Uncaught (in promise) ...`), fires `unhandledrejection` when the app has a listener
|
|
24
|
+
(`addEventListener("unhandledrejection", ...)`), and the process and other requests keep going. An
|
|
25
|
+
un-awaited `async function` that throws is reported the same way. At every compatibility date.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **Types for the Promise bindings.** `sproutboat types` gives D1 (from compatibility date 2026-10-24),
|
|
30
|
+
KV (2026-10-25) and R2 (2026-10-26) bindings the Promise types (`D1DatabaseAsync`,
|
|
31
|
+
`KVNamespaceAsync`, `R2BucketAsync`); earlier dates keep the synchronous ones.
|
|
32
|
+
- Docs, examples and type comments no longer say binding calls are synchronous at every date.
|
|
33
|
+
|
|
13
34
|
## [0.36.0] - 2026-10-26
|
|
14
35
|
|
|
15
36
|
Built on `@sproutboat/runtime` 0.34.0, `@sproutboat/toolchain` 0.19.0 and
|
package/README.md
CHANGED
|
@@ -146,7 +146,9 @@ store instead.
|
|
|
146
146
|
The handler is `export default { fetch(request) }`. It may import from other
|
|
147
147
|
files in the project and from its own `node_modules`, and may also export
|
|
148
148
|
`scheduled(event)` / `queue(batch)` handlers and Durable Object classes. `env`
|
|
149
|
-
is a global, not a parameter
|
|
149
|
+
is a global, not a parameter. Binding calls are synchronous until the compatibility
|
|
150
|
+
date that makes each one return a Promise, as on Workers (D1 from 2026-10-24, KV from
|
|
151
|
+
2026-10-25, R2 from 2026-10-26); `await` works at every date, so always await them.
|
|
150
152
|
[`examples/kitchen-sink/`](examples/kitchen-sink) uses every binding.
|
|
151
153
|
|
|
152
154
|
For objects larger than one request, use resumable R2 multipart uploads. The
|
package/SURFACE.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sproutboat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "Wrangler-shaped CLI for Sproutboat. Deploys workers to any control plane via --api-url / SPROUTBOAT_API_URL.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"@sproutboat/artifact": "^0.3.0",
|
|
65
65
|
"@sproutboat/assets": "^0.3.0",
|
|
66
66
|
"@sproutboat/config": "^0.6.0",
|
|
67
|
-
"@sproutboat/runtime": "^0.34.
|
|
68
|
-
"@sproutboat/toolchain": "^0.19.
|
|
67
|
+
"@sproutboat/runtime": "^0.34.1",
|
|
68
|
+
"@sproutboat/toolchain": "^0.19.1",
|
|
69
69
|
"@sproutboat/wire": "^0.20.2"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
@@ -78,10 +78,10 @@
|
|
|
78
78
|
"typescript": "7.0.2"
|
|
79
79
|
},
|
|
80
80
|
"optionalDependencies": {
|
|
81
|
-
"@sproutboat/cli-darwin-arm64": "0.
|
|
82
|
-
"@sproutboat/cli-darwin-x64": "0.
|
|
83
|
-
"@sproutboat/cli-linux-arm64": "0.
|
|
84
|
-
"@sproutboat/cli-linux-x64": "0.
|
|
81
|
+
"@sproutboat/cli-darwin-arm64": "0.37.0",
|
|
82
|
+
"@sproutboat/cli-darwin-x64": "0.37.0",
|
|
83
|
+
"@sproutboat/cli-linux-arm64": "0.37.0",
|
|
84
|
+
"@sproutboat/cli-linux-x64": "0.37.0"
|
|
85
85
|
},
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": ">=18"
|
package/src/types-gen.ts
CHANGED
|
@@ -26,6 +26,11 @@ const HEADER = `// Generated by \`sproutboat types\`. Do not edit.
|
|
|
26
26
|
|
|
27
27
|
type Entry = { name: string; type: string; note?: string };
|
|
28
28
|
|
|
29
|
+
/** Whether the binding's calls return Promises at the project's compatibility date. */
|
|
30
|
+
function asyncAt(config: SproutboatConfig, date: string): boolean {
|
|
31
|
+
return config.compatibility_date >= date;
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
function entries(config: SproutboatConfig): Entry[] {
|
|
30
35
|
const out: Entry[] = [];
|
|
31
36
|
|
|
@@ -35,9 +40,12 @@ function entries(config: SproutboatConfig): Entry[] {
|
|
|
35
40
|
for (const name of config.secrets ?? []) {
|
|
36
41
|
out.push({ name, type: "string", note: "secret, set with `sproutboat secrets put`" });
|
|
37
42
|
}
|
|
38
|
-
for (const { binding } of resourceRefs(config.kv_namespaces))
|
|
39
|
-
|
|
40
|
-
for (const { binding } of resourceRefs(config.
|
|
43
|
+
for (const { binding } of resourceRefs(config.kv_namespaces))
|
|
44
|
+
out.push({ name: binding, type: asyncAt(config, "2026-10-25") ? "KVNamespaceAsync" : "KVNamespace" });
|
|
45
|
+
for (const { binding } of resourceRefs(config.d1_databases))
|
|
46
|
+
out.push({ name: binding, type: asyncAt(config, "2026-10-24") ? "D1DatabaseAsync" : "D1Database" });
|
|
47
|
+
for (const { binding } of resourceRefs(config.r2_buckets))
|
|
48
|
+
out.push({ name: binding, type: asyncAt(config, "2026-10-26") ? "R2BucketAsync" : "R2Bucket" });
|
|
41
49
|
for (const { binding } of resourceRefs(config.queues)) out.push({ name: binding, type: "Queue" });
|
|
42
50
|
for (const name of config.analytics_engine_datasets ?? []) {
|
|
43
51
|
out.push({ name, type: "AnalyticsEngineDataset" });
|
|
@@ -87,8 +95,9 @@ declare global {
|
|
|
87
95
|
* Bindings from sproutboat.jsonc, for project "${config.name}".
|
|
88
96
|
*
|
|
89
97
|
* ${handlerNote}
|
|
90
|
-
*
|
|
91
|
-
*
|
|
98
|
+
* D1 (from 2026-10-24), KV (2026-10-25) and R2 (2026-10-26) return Promises, as on
|
|
99
|
+
* Workers, so a project at or after those dates gets the *Async types; before them
|
|
100
|
+
* the calls are synchronous. \`await\` works at every date.
|
|
92
101
|
*/
|
|
93
102
|
const env: {
|
|
94
103
|
${body}
|
package/types/sproutboat.d.ts
CHANGED
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
* generates a project's `sproutboat-env.d.ts`, which references this file and
|
|
7
7
|
* declares `env` with that project's bindings.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* KV, D1 and R2 are synchronous before the compatibility date that makes each one return a
|
|
10
|
+
* Promise (D1 2026-10-24, KV 2026-10-25, R2 2026-10-26): `KVNamespace`, `D1Database` and
|
|
11
|
+
* `R2Bucket` are the synchronous types, `KVNamespaceAsync`, `D1DatabaseAsync` and
|
|
12
|
+
* `R2BucketAsync` the Promise types, and `sproutboat types` gives each binding the one for the
|
|
13
|
+
* project's date. `await` works at every date. Before compatibility date 2026-09-28, `env` is a
|
|
10
14
|
* global only and `ctx` is the second handler argument. From that date, `env`
|
|
11
15
|
* is also passed as the second argument and `ctx` as the third.
|
|
12
16
|
*/
|
|
@@ -22,7 +26,7 @@ declare global {
|
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
interface KVNamespace {
|
|
25
|
-
/** The stored string, or `null`. Synchronous
|
|
29
|
+
/** The stored string, or `null`. Synchronous before 2026-10-25 (a Promise from then). An expired key reads as absent. */
|
|
26
30
|
get(key: string): string | null;
|
|
27
31
|
put(key: string, value: string, options?: KVPutOptions): void;
|
|
28
32
|
delete(key: string): void;
|
|
@@ -30,6 +34,33 @@ declare global {
|
|
|
30
34
|
list(prefix?: string): string[];
|
|
31
35
|
}
|
|
32
36
|
|
|
37
|
+
/**
|
|
38
|
+
* KV from compatibility date 2026-10-25: every method returns a Promise, as on Workers.
|
|
39
|
+
* `sproutboat types` picks this type for a project at or after that date.
|
|
40
|
+
*/
|
|
41
|
+
interface KVNamespaceAsync {
|
|
42
|
+
get(key: string, type?: "text"): Promise<string | null>;
|
|
43
|
+
get<T = unknown>(key: string, type: "json"): Promise<T | null>;
|
|
44
|
+
get(key: string, type: "arrayBuffer"): Promise<ArrayBuffer | null>;
|
|
45
|
+
get(key: string, type: "stream"): Promise<ReadableStream | null>;
|
|
46
|
+
getWithMetadata<M = unknown>(
|
|
47
|
+
key: string,
|
|
48
|
+
type?: "text" | "json" | "arrayBuffer" | "stream",
|
|
49
|
+
): Promise<{ value: unknown; metadata: M | null; cacheStatus: string | null }>;
|
|
50
|
+
put(
|
|
51
|
+
key: string,
|
|
52
|
+
value: string | ArrayBuffer | ArrayBufferView | ReadableStream,
|
|
53
|
+
options?: KVPutOptions & { metadata?: unknown },
|
|
54
|
+
): Promise<void>;
|
|
55
|
+
delete(key: string): Promise<void>;
|
|
56
|
+
list(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<{
|
|
57
|
+
keys: Array<{ name: string; expiration?: number; metadata?: unknown }>;
|
|
58
|
+
list_complete: boolean;
|
|
59
|
+
cursor?: string;
|
|
60
|
+
cacheStatus: string | null;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
|
|
33
64
|
// ---------------------------------------------------------------- D1
|
|
34
65
|
|
|
35
66
|
interface D1Meta {
|
|
@@ -63,6 +94,48 @@ declare global {
|
|
|
63
94
|
exec(sql: string): void;
|
|
64
95
|
}
|
|
65
96
|
|
|
97
|
+
/** D1 from compatibility date 2026-10-24: workerd's meta, with D1's keys. */
|
|
98
|
+
interface D1MetaAsync {
|
|
99
|
+
served_by: string;
|
|
100
|
+
duration: number;
|
|
101
|
+
changes: number;
|
|
102
|
+
last_row_id: number;
|
|
103
|
+
changed_db: boolean;
|
|
104
|
+
size_after: number;
|
|
105
|
+
rows_read: number;
|
|
106
|
+
rows_written: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface D1ResultAsync<T = Record<string, unknown>> {
|
|
110
|
+
results: T[];
|
|
111
|
+
success: boolean;
|
|
112
|
+
meta: D1MetaAsync;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* From compatibility date 2026-10-24 `all()`, `run()`, `first()` and `raw()` return Promises, as
|
|
117
|
+
* on Workers. `sproutboat types` picks this type for a project at or after that date.
|
|
118
|
+
*/
|
|
119
|
+
interface D1PreparedStatementAsync {
|
|
120
|
+
/** Positional `?` parameters, in order. Bytes bind as a BLOB. */
|
|
121
|
+
bind(...values: Array<string | number | boolean | null | ArrayBuffer | ArrayBufferView>): D1PreparedStatementAsync;
|
|
122
|
+
all<T = Record<string, unknown>>(): Promise<D1ResultAsync<T>>;
|
|
123
|
+
run<T = Record<string, unknown>>(): Promise<D1ResultAsync<T>>;
|
|
124
|
+
first<T = Record<string, unknown>>(): Promise<T | null>;
|
|
125
|
+
first<T = unknown>(column: string): Promise<T | null>;
|
|
126
|
+
raw<T = unknown[]>(options?: { columnNames?: false }): Promise<T[]>;
|
|
127
|
+
raw<T = unknown[]>(options: { columnNames: true }): Promise<[string[], ...T[]]>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface D1DatabaseAsync {
|
|
131
|
+
prepare(sql: string): D1PreparedStatementAsync;
|
|
132
|
+
batch<T = Record<string, unknown>>(statements: D1PreparedStatementAsync[]): Promise<D1ResultAsync<T>[]>;
|
|
133
|
+
/** Runs a script line by line and counts the lines. */
|
|
134
|
+
exec(sql: string): Promise<{ count: number; duration: number }>;
|
|
135
|
+
/** A Sproutboat addition: an online, integrity-checked copy of the database. */
|
|
136
|
+
backup(name?: string): Promise<{ path: string; bytes: number }>;
|
|
137
|
+
}
|
|
138
|
+
|
|
66
139
|
// ---------------------------------------------------------------- R2
|
|
67
140
|
|
|
68
141
|
interface R2HttpMetadata {
|
|
@@ -172,6 +245,65 @@ declare global {
|
|
|
172
245
|
list(options?: R2ListOptions): R2Objects;
|
|
173
246
|
}
|
|
174
247
|
|
|
248
|
+
/**
|
|
249
|
+
* R2 from compatibility date 2026-10-26: every method returns a Promise, as on Workers, and
|
|
250
|
+
* `uploaded` is a Date. `sproutboat types` picks these types for a project at or after that date.
|
|
251
|
+
*/
|
|
252
|
+
interface R2ObjectAsync {
|
|
253
|
+
key: string;
|
|
254
|
+
size: number;
|
|
255
|
+
etag: string;
|
|
256
|
+
httpEtag: string;
|
|
257
|
+
checksums: { md5?: ArrayBuffer };
|
|
258
|
+
uploaded: Date;
|
|
259
|
+
httpMetadata?: R2HttpMetadata;
|
|
260
|
+
customMetadata?: Record<string, string>;
|
|
261
|
+
range?: { offset: number; length: number };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
interface R2ObjectBodyAsync extends R2ObjectAsync {
|
|
265
|
+
body: ReadableStream;
|
|
266
|
+
bodyUsed: boolean;
|
|
267
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
268
|
+
text(): Promise<string>;
|
|
269
|
+
json<T = unknown>(): Promise<T>;
|
|
270
|
+
blob(): Promise<Blob>;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
interface R2MultipartUploadAsync {
|
|
274
|
+
key: string;
|
|
275
|
+
uploadId: string;
|
|
276
|
+
uploadPart(
|
|
277
|
+
partNumber: number,
|
|
278
|
+
value: string | ArrayBuffer | ArrayBufferView | ReadableStream | Blob,
|
|
279
|
+
): Promise<R2UploadedPart>;
|
|
280
|
+
complete(parts: R2UploadedPart[]): Promise<R2ObjectAsync>;
|
|
281
|
+
abort(): Promise<void>;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
interface R2BucketAsync extends Pick<R2Bucket, "createUploadUrl" | "createDownloadUrl"> {
|
|
285
|
+
head(key: string): Promise<R2ObjectAsync | null>;
|
|
286
|
+
get(
|
|
287
|
+
key: string,
|
|
288
|
+
options?: { range?: { offset?: number; length?: number; suffix?: number }; onlyIf?: unknown },
|
|
289
|
+
): Promise<R2ObjectBodyAsync | null>;
|
|
290
|
+
put(
|
|
291
|
+
key: string,
|
|
292
|
+
value: string | ArrayBuffer | ArrayBufferView | ReadableStream | Blob | null,
|
|
293
|
+
options?: { httpMetadata?: R2HttpMetadata | Headers; customMetadata?: Record<string, string>; onlyIf?: unknown },
|
|
294
|
+
): Promise<R2ObjectAsync | null>;
|
|
295
|
+
delete(keys: string | string[]): Promise<void>;
|
|
296
|
+
list(options?: {
|
|
297
|
+
prefix?: string;
|
|
298
|
+
limit?: number;
|
|
299
|
+
cursor?: string;
|
|
300
|
+
delimiter?: string;
|
|
301
|
+
include?: Array<"httpMetadata" | "customMetadata">;
|
|
302
|
+
}): Promise<{ objects: R2ObjectAsync[]; truncated: boolean; cursor?: string; delimitedPrefixes: string[] }>;
|
|
303
|
+
createMultipartUpload(key: string, options?: R2PutOptions): Promise<R2MultipartUploadAsync>;
|
|
304
|
+
resumeMultipartUpload(key: string, uploadId: string): R2MultipartUploadAsync;
|
|
305
|
+
}
|
|
306
|
+
|
|
175
307
|
// ------------------------------------------------------------ Queues
|
|
176
308
|
|
|
177
309
|
type QueuesContentType = "json" | "text" | "bytes" | "v8";
|