sproutboat 0.14.0 → 0.16.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 +57 -1
- package/SURFACE.md +2 -2
- package/package.json +12 -12
- package/src/build.ts +32 -18
- package/src/compile.ts +31 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,61 @@ maintained going forward by the `release` skill.
|
|
|
10
10
|
|
|
11
11
|
## Unreleased
|
|
12
12
|
|
|
13
|
+
## [0.16.0] - 2026-10-10
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Proxy and revocable Proxy are accepted in handlers with Porffor alpha-16.
|
|
18
|
+
Native regression checks cover property traps, enumeration, callable and
|
|
19
|
+
constructible proxies, revocation, and frozen-property invariants.
|
|
20
|
+
|
|
21
|
+
- `URLSearchParams` and `FormData` provide live keys, values and entries
|
|
22
|
+
iterators. `itty-router` 5.0.24 `IttyRouter` passes GET parameters, Unicode
|
|
23
|
+
POST bodies and a 404 fallback. A basic tRPC 11.19.0 server caller also works.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Pin Porffor alpha-16 (`43087d4`) through `@sproutboat/toolchain` 0.6.0
|
|
28
|
+
and `@sproutboat/runtime` 0.15.0. Collection iterator methods and `matchAll`
|
|
29
|
+
now return iterators. Typed-array `from`, `set` offset and `join` fixes are
|
|
30
|
+
supplied upstream, so their local source patches are removed.
|
|
31
|
+
- Native output handles Unicode console strings, clamped-array ties round
|
|
32
|
+
to even, and class static initializers use the class as `this`.
|
|
33
|
+
|
|
34
|
+
### Compatibility limits
|
|
35
|
+
|
|
36
|
+
- Proxy support alone does not establish compatibility for every package.
|
|
37
|
+
`qs` 6.16.0 parses and serializes nested query data in a native HTTP probe.
|
|
38
|
+
Standard `itty-router` 5.0.24 `Router` still hits a labelled-break compiler
|
|
39
|
+
error. String iteration still splits astral characters into UTF-16 halves.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## [0.15.0] - 2026-10-05
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Sprouts compile with Porffor alpha-15 (`@sproutboat/toolchain` 0.5.0).
|
|
47
|
+
Async functions now compile to state machines, and `console.log` no longer
|
|
48
|
+
adds colour codes when its output is piped. The compatibility suite is
|
|
49
|
+
unchanged at 30/32, and binary size, compile time, start-up and throughput
|
|
50
|
+
are level with alpha-13.
|
|
51
|
+
|
|
52
|
+
### Performance
|
|
53
|
+
|
|
54
|
+
- Rebuilding after a small change is about 3 times faster: 2.1 to 2.4 s
|
|
55
|
+
instead of 6.8 to 7.7 s for the standalone example app. Builds now compile
|
|
56
|
+
from one path per project, so Porffor reuses the C units that didn't change.
|
|
57
|
+
Porffor's build directories that haven't been used for a week are removed;
|
|
58
|
+
they used to pile up without limit.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- Handlers using marked, or any bundled class whose static methods create
|
|
63
|
+
instances of the class itself, work again. Since 0.12.6 they failed with
|
|
64
|
+
`TypeError: value is not a constructor` (baronunread/sproutboat#256).
|
|
65
|
+
- An ISO date's timezone offset could flip sign, so `-00:30` sometimes parsed
|
|
66
|
+
as `+00:30`, depending on what sat next to the string in memory.
|
|
67
|
+
|
|
13
68
|
## [0.14.0] - 2026-10-04
|
|
14
69
|
|
|
15
70
|
### Changed
|
|
@@ -804,7 +859,8 @@ its own package.
|
|
|
804
859
|
- Renamed the package to `sproutboat` (was `@sproutboat/cli`); dropped the
|
|
805
860
|
`sprout` bin alias in favour of a user-defined shell alias.
|
|
806
861
|
|
|
807
|
-
[Unreleased]: https://github.com/baronunread/sproutboat-cli/compare/v0.
|
|
862
|
+
[Unreleased]: https://github.com/baronunread/sproutboat-cli/compare/v0.15.0...HEAD
|
|
863
|
+
[0.15.0]: https://github.com/baronunread/sproutboat-cli/compare/v0.14.0...v0.15.0
|
|
808
864
|
[0.14.0]: https://github.com/baronunread/sproutboat-cli/compare/v0.13.0...v0.14.0
|
|
809
865
|
[0.13.0]: https://github.com/baronunread/sproutboat-cli/compare/v0.12.7...v0.13.0
|
|
810
866
|
[0.12.7]: https://github.com/baronunread/sproutboat-cli/compare/v0.12.6...v0.12.7
|
package/SURFACE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Generated by `src/surface.test.ts` from `src/surface.ts` + the pinned
|
|
4
4
|
> toolchain constants. Do not edit by hand — run `UPDATE_SURFACE=1 bun test`.
|
|
5
5
|
|
|
6
|
-
**Package:** `sproutboat` 0.
|
|
6
|
+
**Package:** `sproutboat` 0.16.0
|
|
7
7
|
|
|
8
8
|
## Commands
|
|
9
9
|
|
|
@@ -76,7 +76,7 @@ usage: sproutboat <init [name] | check [project-dir] | types [project-dir] | dev
|
|
|
76
76
|
| | |
|
|
77
77
|
| --- | --- |
|
|
78
78
|
| Zig | `0.16.0` (`zig cc -target x86_64-linux-musl`, static) |
|
|
79
|
-
| Provenance stamp | `zig-musl/0.16.0+porffor/
|
|
79
|
+
| Provenance stamp | `zig-musl/0.16.0+porffor/43087d4+uws/360c276d` |
|
|
80
80
|
| Artifact schema | `2` |
|
|
81
81
|
| Runtime | `native-fetch` |
|
|
82
82
|
| Capability profile | `http-sync-v0` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sproutboat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.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,24 +64,24 @@
|
|
|
64
64
|
"@sproutboat/artifact": "^0.3.0",
|
|
65
65
|
"@sproutboat/assets": "^0.3.0",
|
|
66
66
|
"@sproutboat/config": "^0.5.0",
|
|
67
|
-
"@sproutboat/runtime": "^0.
|
|
68
|
-
"@sproutboat/toolchain": "^0.
|
|
67
|
+
"@sproutboat/runtime": "^0.15.0",
|
|
68
|
+
"@sproutboat/toolchain": "^0.6.0",
|
|
69
69
|
"@sproutboat/wire": "^0.11.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@oxlint/plugins": "1.
|
|
73
|
-
"@types/bun": "1.4.
|
|
72
|
+
"@oxlint/plugins": "1.85.0",
|
|
73
|
+
"@types/bun": "1.4.2",
|
|
74
74
|
"cookie": "2.0.1",
|
|
75
|
-
"lefthook": "2.1.
|
|
76
|
-
"oxfmt": "0.
|
|
77
|
-
"oxlint": "1.
|
|
75
|
+
"lefthook": "2.1.14",
|
|
76
|
+
"oxfmt": "0.70.0",
|
|
77
|
+
"oxlint": "1.85.0",
|
|
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.16.0",
|
|
82
|
+
"@sproutboat/cli-darwin-x64": "0.16.0",
|
|
83
|
+
"@sproutboat/cli-linux-arm64": "0.16.0",
|
|
84
|
+
"@sproutboat/cli-linux-x64": "0.16.0"
|
|
85
85
|
},
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": ">=18"
|
package/src/build.ts
CHANGED
|
@@ -248,24 +248,38 @@ export async function buildArtifact(input: BuildInput): Promise<BuildOutput> {
|
|
|
248
248
|
const [sqliteObject, tls] = embedded
|
|
249
249
|
? await Promise.all([ensureSqliteObject({ target, zigBin }), ensureBearssl({ target, zigBin })])
|
|
250
250
|
: [null, null];
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
251
|
+
// Porffor caches compiled C units per entry path, so compile from one
|
|
252
|
+
// path per project and build shape: unchanged units (the uWebSockets
|
|
253
|
+
// server alone is ~1.75 s of clang) are reused instead of rebuilt, and
|
|
254
|
+
// Porffor keeps one build dir per shape instead of one per artifact.
|
|
255
|
+
const unitDir = resolve(
|
|
256
|
+
input.projectDir,
|
|
257
|
+
".sproutboat/porffor-units",
|
|
258
|
+
`${input.target ?? "linux-x86_64"}-${input.transport ?? "broker"}-${input.optimize ?? "release"}`,
|
|
259
|
+
);
|
|
260
|
+
const unitLock = input.generatedPath ? null : await acquireArtifactLock(unitDir);
|
|
261
|
+
try {
|
|
262
|
+
await compileSprout({
|
|
263
|
+
sourcePath: input.sourcePath,
|
|
264
|
+
generatedPath: input.generatedPath ?? resolve(unitDir, "sprout.generated.js"),
|
|
265
|
+
generatedSource,
|
|
266
|
+
outPath,
|
|
267
|
+
vars: input.config.vars ?? {},
|
|
268
|
+
bindings,
|
|
269
|
+
zigBin,
|
|
270
|
+
target: input.target,
|
|
271
|
+
compatibilityDate: input.config.compatibility_date,
|
|
272
|
+
transport: input.transport,
|
|
273
|
+
appName: input.config.name,
|
|
274
|
+
assets: bakedAssets,
|
|
275
|
+
extraLink: [...(sqliteObject ? [sqliteObject] : []), ...(tls ? tls.objects : [])],
|
|
276
|
+
extraCflags: tls ? ["-I", tls.includeDir] : [],
|
|
277
|
+
optimize: input.optimize,
|
|
278
|
+
versionMetadata,
|
|
279
|
+
});
|
|
280
|
+
} finally {
|
|
281
|
+
if (unitLock) await rm(unitLock, { recursive: true, force: true });
|
|
282
|
+
}
|
|
269
283
|
};
|
|
270
284
|
let compileCache: BuildOutput["compileCache"] = "bypass";
|
|
271
285
|
const compileStartedAt = performance.now();
|
package/src/compile.ts
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* unusable it stops with its specific integrity or archive error. Contributors
|
|
11
11
|
* may explicitly opt into Porffor's source fallback.
|
|
12
12
|
*/
|
|
13
|
-
import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
13
|
+
import { chmod, mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
14
|
+
import { homedir } from "node:os";
|
|
14
15
|
import { dirname, resolve } from "node:path";
|
|
15
16
|
import { ensurePorfforPatched } from "./patch-porffor";
|
|
16
17
|
import { ensureUWebSockets, ensureUWebSocketsHost, resolveHostCompiler, UwsUnavailableError } from "./toolchain";
|
|
@@ -113,6 +114,32 @@ export async function loadPrelude(transport: Transport = "broker"): Promise<stri
|
|
|
113
114
|
return core.replace(TRANSPORT_MARKER, chosen);
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
let porfforBuildsPruned = false;
|
|
118
|
+
/**
|
|
119
|
+
* Porffor writes one build dir per entry path under ~/.cache/porffor/build and
|
|
120
|
+
* never removes any (one machine had 1,395 of them, 6.3 GB). Drop the ones not
|
|
121
|
+
* compiled in for a week; the only cost is a recompile. Each dir's `flags`
|
|
122
|
+
* stamp is rewritten on every compile, so its mtime is "last used".
|
|
123
|
+
*/
|
|
124
|
+
export async function prunePorfforBuilds(
|
|
125
|
+
root = resolve(process.env.HOME ?? homedir(), ".cache/porffor/build"),
|
|
126
|
+
now = Date.now(),
|
|
127
|
+
): Promise<number> {
|
|
128
|
+
porfforBuildsPruned = true;
|
|
129
|
+
const cutoff = now - 7 * 24 * 60 * 60 * 1000;
|
|
130
|
+
const entries: string[] = await readdir(root).catch(() => []);
|
|
131
|
+
let removed = 0;
|
|
132
|
+
for (const name of entries) {
|
|
133
|
+
const dir = resolve(root, name);
|
|
134
|
+
const used = (await stat(resolve(dir, "flags")).catch(() => null)) ?? (await stat(dir).catch(() => null));
|
|
135
|
+
if (used && used.mtimeMs < cutoff) {
|
|
136
|
+
await rm(dir, { recursive: true, force: true });
|
|
137
|
+
removed++;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return removed;
|
|
141
|
+
}
|
|
142
|
+
|
|
116
143
|
/** Child env for the Porffor run. `SB_EXTRA_LINK` is read by the patched link
|
|
117
144
|
* step (#15) and is absent entirely for a normal build. `cc`/`cxx` override
|
|
118
145
|
* Porffor's own `CC`/`CXX` read for a **host** build (musl builds hardcode
|
|
@@ -191,6 +218,9 @@ export async function compileSprout(input: CompileInput): Promise<void> {
|
|
|
191
218
|
}
|
|
192
219
|
}
|
|
193
220
|
|
|
221
|
+
// Once per process, in the background: housekeeping must never slow a build.
|
|
222
|
+
if (!porfforBuildsPruned) void prunePorfforBuilds().catch(() => {});
|
|
223
|
+
|
|
194
224
|
const outDir = dirname(input.outPath);
|
|
195
225
|
await mkdir(outDir, { recursive: true });
|
|
196
226
|
// The artifact dir is content-addressed, so rebuilding unchanged source lands
|