sproutboat 0.5.0 → 0.6.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/README.md +67 -78
- package/SURFACE.md +1 -1
- package/package.json +25 -20
- package/src/assets.ts +29 -9
- package/src/broker.ts +143 -65
- package/src/build.ts +23 -5
- package/src/bundle.ts +2 -1
- package/src/compile.ts +9 -4
- package/src/config.ts +71 -29
- package/src/dev.ts +33 -16
- package/src/json.ts +9 -1
- package/src/main.ts +274 -77
- package/src/manifest.ts +63 -14
- package/src/native-fetch-prelude.js +256 -127
- package/src/patch-porffor.ts +5 -2
- package/src/report.ts +37 -17
- package/src/source.ts +4 -1
- package/src/style.ts +9 -6
- package/src/surface.ts +150 -42
- package/src/toolchain.ts +15 -4
- package/src/update-check.ts +20 -5
- package/src/wrap.ts +32 -8
package/README.md
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/logo-dark.svg">
|
|
3
|
+
<img src="docs/logo-light.svg" alt="sproutboat" width="220" height="32">
|
|
4
|
+
</picture>
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
Wrangler-shaped tool that compiles a `fetch` handler to a native binary and
|
|
5
|
-
ships it to any Sproutboat control plane. MIT licensed.
|
|
6
|
+
https://sproutboat.com
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
The CLI for [Sproutboat](https://github.com/baronunread/sproutboat). Compiles a
|
|
9
|
+
`fetch` handler to a native binary and ships it to any Sproutboat control plane.
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
Wrangler-shaped, MIT licensed. `build` and `deploy` cross-compile your handler
|
|
14
|
+
to a static `linux-x86_64` binary with [Porffor](https://porffor.dev) and Zig —
|
|
15
|
+
no Docker, no root, nothing to run as a daemon.
|
|
16
|
+
|
|
17
|
+
Full reference: [sproutboat.com/docs](https://sproutboat.com/docs) (plain text
|
|
18
|
+
for agents: [sproutboat.com/llms.txt](https://sproutboat.com/llms.txt)).
|
|
19
|
+
|
|
20
|
+
## Using
|
|
9
21
|
|
|
10
22
|
```sh
|
|
11
23
|
bunx sproutboat init hello
|
|
@@ -26,45 +38,30 @@ Or install it once and drop the `bunx`:
|
|
|
26
38
|
bun add -g sproutboat # then: sproutboat deploy, sproutboat tail, ...
|
|
27
39
|
```
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
The `login` browser step is one-time. It writes a long-lived token to
|
|
41
|
+
`login` is one-time. It writes a long-lived token to
|
|
32
42
|
`~/.config/sproutboat/credentials.json`, keyed by API URL, so you can hold
|
|
33
|
-
logins for several instances at once. For CI or an agent, skip
|
|
34
|
-
|
|
35
|
-
of that file).
|
|
43
|
+
logins for several instances at once. For CI or an agent, skip it and set
|
|
44
|
+
`SPROUTBOAT_API_URL` + `SPROUTBOAT_TOKEN`.
|
|
36
45
|
|
|
37
46
|
## Commands
|
|
38
47
|
|
|
48
|
+
The everyday loop:
|
|
49
|
+
|
|
39
50
|
| Command | What it does |
|
|
40
51
|
| --- | --- |
|
|
41
52
|
| `init [name]` | Scaffold `sproutboat.jsonc` + `src/index.js` |
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
| `logout [--api-url <url>]` | Forget the stored credential |
|
|
51
|
-
| `whoami` | Active endpoint and the account the token belongs to |
|
|
52
|
-
| `kv <list \| create \| info \| rename \| delete>` | KV namespaces |
|
|
53
|
-
| `d1 <list \| create \| info \| rename \| delete>` | D1 databases |
|
|
54
|
-
| `r2 <list \| create \| info \| rename \| delete>` | R2 buckets |
|
|
55
|
-
| `queues <list \| create \| info \| rename \| delete>` | Queues |
|
|
56
|
-
| `secrets <list \| put <NAME> [--value <v>] \| delete <NAME>>` | Encrypted project secrets, read as `env.NAME` |
|
|
57
|
-
| `domains <list \| add <host> \| verify <host> \| delete <host>>` | Attach your own hostname (TXT + A, apex allowed) |
|
|
58
|
-
| `delete --yes` | Delete the project, every version, and its route |
|
|
59
|
-
|
|
60
|
-
Each storage product is its own command with the same five verbs. Wrangler nests
|
|
61
|
-
two of its four (`kv namespace create`, `r2 bucket create`) and leaves the other
|
|
62
|
-
two flat; the nesting separates a container from its contents, which the verb
|
|
63
|
-
already does, so ours are uniform. Contents get their own noun when they arrive
|
|
64
|
-
(`kv key get`, `r2 object put`).
|
|
53
|
+
| `dev [--port <n>]` | Run it here against a real broker, rebuilding on save |
|
|
54
|
+
| `deploy` | Build, provision bindings, upload, wait until the URL serves |
|
|
55
|
+
| `tail [--sprout]` | Recent request logs, or the running sprout's output |
|
|
56
|
+
| `rollback <id>` | Re-activate a previous version |
|
|
57
|
+
|
|
58
|
+
Then `check`, `build`, `versions`, `delete`, `login` / `logout` / `whoami`, and
|
|
59
|
+
one command per storage product — `kv`, `d1`, `r2`, `queues`, `secrets`,
|
|
60
|
+
`domains` — each with the same five verbs.
|
|
65
61
|
|
|
66
62
|
Run `sproutboat` with no arguments for the grouped list.
|
|
67
|
-
[`SURFACE.md`](SURFACE.md) is the generated inventory
|
|
63
|
+
[`SURFACE.md`](SURFACE.md) is the generated inventory: every command, every
|
|
64
|
+
argument, every env var, kept honest by a drift test.
|
|
68
65
|
|
|
69
66
|
## Config
|
|
70
67
|
|
|
@@ -91,55 +88,47 @@ Run `sproutboat` with no arguments for the grouped list.
|
|
|
91
88
|
```
|
|
92
89
|
|
|
93
90
|
A bare `"CACHE"` binding is auto-provisioned on `deploy`: the CLI creates an
|
|
94
|
-
account-level resource
|
|
95
|
-
store
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
`
|
|
103
|
-
See [`examples/kitchen-sink/`](examples/kitchen-sink) for one app that uses
|
|
104
|
-
every binding.
|
|
91
|
+
account-level resource and writes its id back into `sproutboat.jsonc`, so the
|
|
92
|
+
store survives redeploys. `--no-provision` keeps it a throwaway per-deploy
|
|
93
|
+
store instead.
|
|
94
|
+
|
|
95
|
+
The handler is `export default { fetch(request) }`. It may import from other
|
|
96
|
+
files in the project and from its own `node_modules`, and may also export
|
|
97
|
+
`scheduled(event)` / `queue(batch)` handlers and Durable Object classes. `env`
|
|
98
|
+
is a global, not a parameter, and every binding call is synchronous.
|
|
99
|
+
[`examples/kitchen-sink/`](examples/kitchen-sink) uses every binding.
|
|
105
100
|
|
|
106
101
|
`sproutboat dev` runs against a real local broker, so bindings behave like
|
|
107
|
-
production without a deploy — except `secrets`, which live only in the
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
`
|
|
102
|
+
production without a deploy — except `secrets`, which live only in the control
|
|
103
|
+
plane. Put values in a `.dev.vars` file next to `sproutboat.jsonc`
|
|
104
|
+
(`API_KEY=whatever`, one per line, gitignored) and `env.API_KEY` resolves under
|
|
105
|
+
`dev` only.
|
|
111
106
|
|
|
112
107
|
## Requirements
|
|
113
108
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
with Porffor and Zig (the CLI fetches Zig automatically on first use). The
|
|
118
|
-
package ships a prebuilt uWebSockets and compiles nothing else from source. No
|
|
119
|
-
Docker, no root. On Windows, build from WSL.
|
|
120
|
-
|
|
121
|
-
If that prebuilt is unusable (a `porffor` pin bump before the archive is
|
|
122
|
-
refreshed), the first build falls back to compiling uWebSockets locally, which
|
|
123
|
-
needs `git` and `make` on `PATH`. `SPROUTBOAT_UWS_TARBALL=<archive>` overrides
|
|
124
|
-
the shipped one.
|
|
109
|
+
[Bun](https://bun.sh) 1.4+. The CLI fetches Zig automatically on first use and
|
|
110
|
+
ships a prebuilt uWebSockets, so it compiles nothing else from source. On
|
|
111
|
+
Windows, build from WSL.
|
|
125
112
|
|
|
126
113
|
## Limits
|
|
127
114
|
|
|
128
115
|
Capability profile `http-sync-v0`: one synchronous `fetch` handler, optional
|
|
129
116
|
`scheduled` / `queue` handlers, no streaming, no WebSockets. Binding values are
|
|
130
|
-
text/JSON
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
117
|
+
text/JSON, one at a time over a 32 MiB loopback frame. Sprout uploads cap at
|
|
118
|
+
16 MiB, assets at 64 MiB / 4096 files.
|
|
119
|
+
|
|
120
|
+
Porffor is pre-1.0, so some JavaScript does not survive the compile — CommonJS
|
|
121
|
+
`require`, dynamic `import()`, anything reaching `process`/`Bun`/`Deno`/`node:*`,
|
|
122
|
+
and `new Proxy(...)` (it compiles, then silently ignores every trap).
|
|
123
|
+
`sproutboat check` catches most of it before a build. The full list, and the
|
|
124
|
+
current sharp edges, are at [sproutboat.com/docs](https://sproutboat.com/docs).
|
|
125
|
+
|
|
126
|
+
## Bugs
|
|
127
|
+
|
|
128
|
+
File issues at
|
|
129
|
+
[baronunread/sproutboat/issues](https://github.com/baronunread/sproutboat/issues).
|
|
130
|
+
|
|
131
|
+
## Contributing
|
|
132
|
+
|
|
133
|
+
PRs welcome. [`MIGRATION.md`](MIGRATION.md) maps this repo back to the
|
|
134
|
+
monorepo it was extracted from.
|
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.6.0 · runs on Bun (use `bunx`, not `npx`)
|
|
7
7
|
|
|
8
8
|
## Commands
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sproutboat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Wrangler-shaped CLI for Sproutboat. Deploys workers to any control plane via --api-url / SPROUTBOAT_API_URL.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"homepage": "https://github.com/baronunread/sproutboat-cli",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/baronunread/sproutboat-cli.git"
|
|
11
|
-
},
|
|
12
|
-
"bugs": "https://github.com/baronunread/sproutboat-cli/issues",
|
|
13
5
|
"keywords": [
|
|
14
|
-
"sproutboat",
|
|
15
6
|
"cli",
|
|
16
7
|
"deploy",
|
|
8
|
+
"edge",
|
|
17
9
|
"porffor",
|
|
18
10
|
"serverless",
|
|
19
|
-
"
|
|
11
|
+
"sproutboat",
|
|
20
12
|
"wrangler"
|
|
21
13
|
],
|
|
14
|
+
"homepage": "https://github.com/baronunread/sproutboat-cli",
|
|
15
|
+
"bugs": "https://github.com/baronunread/sproutboat-cli/issues",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/baronunread/sproutboat-cli.git"
|
|
20
|
+
},
|
|
22
21
|
"bin": {
|
|
23
22
|
"sproutboat": "src/main.ts"
|
|
24
23
|
},
|
|
24
|
+
"files": [
|
|
25
|
+
"src",
|
|
26
|
+
"!src/*.test.ts",
|
|
27
|
+
"vendor",
|
|
28
|
+
"SURFACE.md"
|
|
29
|
+
],
|
|
30
|
+
"type": "module",
|
|
25
31
|
"exports": {
|
|
26
32
|
"./runtime/config": "./src/config.ts",
|
|
27
33
|
"./runtime/source": "./src/source.ts",
|
|
@@ -32,18 +38,12 @@
|
|
|
32
38
|
"./runtime/prelude": "./src/native-fetch-prelude.js",
|
|
33
39
|
"./package.json": "./package.json"
|
|
34
40
|
},
|
|
35
|
-
"files": [
|
|
36
|
-
"src",
|
|
37
|
-
"!src/*.test.ts",
|
|
38
|
-
"vendor",
|
|
39
|
-
"SURFACE.md"
|
|
40
|
-
],
|
|
41
|
-
"engines": {
|
|
42
|
-
"bun": ">=1.4.0"
|
|
43
|
-
},
|
|
44
41
|
"scripts": {
|
|
42
|
+
"prepare": "lefthook install || true",
|
|
45
43
|
"typecheck": "tsc --noEmit",
|
|
46
44
|
"lint": "oxlint .",
|
|
45
|
+
"fmt": "oxfmt .",
|
|
46
|
+
"fmt:check": "oxfmt --check .",
|
|
47
47
|
"test": "bun test",
|
|
48
48
|
"example:kitchen-sink": "bun examples/kitchen-sink/harness.ts",
|
|
49
49
|
"surface": "UPDATE_SURFACE=1 bun test src/surface.test.ts",
|
|
@@ -58,7 +58,12 @@
|
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@oxlint/plugins": "1.81.0",
|
|
60
60
|
"@types/bun": "1.4.0",
|
|
61
|
+
"lefthook": "2.1.12",
|
|
62
|
+
"oxfmt": "0.66.0",
|
|
61
63
|
"oxlint": "1.81.0",
|
|
62
64
|
"typescript": "5.9.2"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"bun": ">=1.4.0"
|
|
63
68
|
}
|
|
64
69
|
}
|
package/src/assets.ts
CHANGED
|
@@ -21,13 +21,26 @@ export type AssetManifest = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const TYPES = new Map<string, string>([
|
|
24
|
-
["html", "text/html; charset=utf-8"],
|
|
25
|
-
["
|
|
26
|
-
["
|
|
27
|
-
["
|
|
28
|
-
["
|
|
29
|
-
["
|
|
30
|
-
["
|
|
24
|
+
["html", "text/html; charset=utf-8"],
|
|
25
|
+
["css", "text/css; charset=utf-8"],
|
|
26
|
+
["js", "text/javascript; charset=utf-8"],
|
|
27
|
+
["mjs", "text/javascript; charset=utf-8"],
|
|
28
|
+
["json", "application/json; charset=utf-8"],
|
|
29
|
+
["map", "application/json; charset=utf-8"],
|
|
30
|
+
["txt", "text/plain; charset=utf-8"],
|
|
31
|
+
["xml", "application/xml; charset=utf-8"],
|
|
32
|
+
["svg", "image/svg+xml"],
|
|
33
|
+
["png", "image/png"],
|
|
34
|
+
["jpg", "image/jpeg"],
|
|
35
|
+
["jpeg", "image/jpeg"],
|
|
36
|
+
["gif", "image/gif"],
|
|
37
|
+
["webp", "image/webp"],
|
|
38
|
+
["avif", "image/avif"],
|
|
39
|
+
["ico", "image/x-icon"],
|
|
40
|
+
["woff2", "font/woff2"],
|
|
41
|
+
["woff", "font/woff"],
|
|
42
|
+
["ttf", "font/ttf"],
|
|
43
|
+
["wasm", "application/wasm"],
|
|
31
44
|
["webmanifest", "application/manifest+json"],
|
|
32
45
|
]);
|
|
33
46
|
|
|
@@ -68,10 +81,17 @@ export function walkAssets(dir: string) {
|
|
|
68
81
|
if (ent.name.startsWith(".")) continue;
|
|
69
82
|
const childAbs = join(abs, ent.name);
|
|
70
83
|
const childRel = posix.join(rel, ent.name);
|
|
71
|
-
if (ent.isDirectory()) {
|
|
84
|
+
if (ent.isDirectory()) {
|
|
85
|
+
recurse(childAbs, childRel);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
72
88
|
if (!ent.isFile()) continue;
|
|
73
89
|
const body = readFileSync(childAbs);
|
|
74
|
-
out[`/${childRel}`] = {
|
|
90
|
+
out[`/${childRel}`] = {
|
|
91
|
+
hash: createHash("sha256").update(body).digest("hex"),
|
|
92
|
+
size: body.byteLength,
|
|
93
|
+
type: contentType(ent.name),
|
|
94
|
+
};
|
|
75
95
|
}
|
|
76
96
|
};
|
|
77
97
|
recurse(dir, "");
|