sproutboat 0.4.9 → 0.4.11

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 CHANGED
@@ -1,11 +1,14 @@
1
1
  # sproutboat
2
2
 
3
- The CLI for [Sproutboat](https://github.com/baronunread/sproutboat) a
4
- Wrangler-shaped tool for deploying workers to any Sproutboat control plane.
5
- MIT licensed.
3
+ The CLI for [Sproutboat](https://github.com/baronunread/sproutboat). It is a
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
+
7
+ Full reference: [sproutboat.com/docs](https://sproutboat.com/docs)
8
+ (plain text for agents: [sproutboat.com/llms.txt](https://sproutboat.com/llms.txt)).
6
9
 
7
10
  ```sh
8
- bunx sproutboat login --api-url https://control.example.com
11
+ bunx sproutboat login --api-url https://control.example.com # one browser approval
9
12
  bunx sproutboat init hello
10
13
  cd hello
11
14
  bunx sproutboat deploy
@@ -19,7 +22,11 @@ bun add -g sproutboat # then: sproutboat deploy, sproutboat tail, ...
19
22
 
20
23
  Want it shorter? Alias it yourself: `alias sprout='sproutboat'`.
21
24
 
22
- For CI, skip `login` and set `SPROUTBOAT_API_URL` + `SPROUTBOAT_TOKEN`.
25
+ The `login` browser step is one-time. It writes a long-lived token to
26
+ `~/.config/sproutboat/credentials.json`, keyed by API URL, so you can hold
27
+ logins for several instances at once. For CI or an agent, skip `login`
28
+ entirely and set `SPROUTBOAT_API_URL` + `SPROUTBOAT_TOKEN` (copy the token out
29
+ of that file).
23
30
 
24
31
  ## Commands
25
32
 
@@ -27,20 +34,23 @@ For CI, skip `login` and set `SPROUTBOAT_API_URL` + `SPROUTBOAT_TOKEN`.
27
34
  | --- | --- |
28
35
  | `init [name]` | Scaffold `sproutboat.jsonc` + `src/index.js` |
29
36
  | `check` | Validate the config and entry point |
30
- | `build` | Cross-compile the worker artifact |
31
- | `deploy [--dry-run] [--artifact <dir>]` | Build and upload (`--dry-run` prints the report only) |
32
- | `login [--api-url <url>] [--token <token>]` | Browser device flow, or store a token |
33
- | `tail [name]` | Recent logs |
37
+ | `build` | Cross-compile the sprout binary (Porffor + Zig) |
38
+ | `deploy [--dry-run] [--no-wait] [--no-provision] [--artifact <dir>]` | Build, auto-provision id-less storage bindings, upload, wait until the URL serves |
39
+ | `login [--api-url <url>] [--token <token>]` | Browser device flow, or store a token directly |
40
+ | `tail [name] [--sprout]` | Recent request logs; `--sprout` streams the running sprout + broker output |
34
41
  | `versions list [name]` | Deployed versions |
35
42
  | `rollback <id>` | Activate a previous version |
36
- | `delete --yes` | Delete the project |
43
+ | `secrets [list \| set <NAME> [value] \| rm <NAME>]` | Encrypted project secrets, read as `env.NAME` |
44
+ | `resource [list \| create <kind> <name> \| rename <id> <name> \| delete <id>]` | Account-level KV / D1 / R2 / queue stores |
45
+ | `domains [list \| add <host> \| verify <host> \| rm <host>]` | Attach your own hostname (TXT + A, apex allowed) |
46
+ | `delete --yes` | Delete the project, every version, and its route |
37
47
 
38
- Credentials are keyed by API URL in `~/.config/sproutboat/credentials.json`, so
39
- you can hold logins for several instances at once.
48
+ Run `sproutboat` with no arguments for the grouped list.
49
+ [`SURFACE.md`](SURFACE.md) is the generated inventory of every command and env var.
40
50
 
41
51
  ## Config
42
52
 
43
- `sproutboat.jsonc` the entry point plus Cloudflare-shaped `env.*` bindings:
53
+ `sproutboat.jsonc`: the entry point plus Cloudflare-shaped `env.*` bindings.
44
54
 
45
55
  ```jsonc
46
56
  {
@@ -50,42 +60,54 @@ you can hold logins for several instances at once.
50
60
 
51
61
  "vars": { "SITE": "hi" },
52
62
  "secrets": ["API_KEY"],
53
- "kv_namespaces": ["CACHE"],
63
+ "kv_namespaces": ["CACHE"], // bare name, or { "binding": "CACHE", "id": "kv_..." }
54
64
  "d1_databases": ["DB"],
55
65
  "r2_buckets": ["UPLOADS"],
56
66
  "queues": ["JOBS"],
57
- "analytics_engine_datasets": ["METRICS"],
67
+ "analytics_engine_datasets": ["METRICS"], // bare name only, no id
58
68
  "durable_objects": { "COUNTER": "Counter" },
59
69
  "outbound": ["api.example.com"],
60
70
  "triggers": { "crons": ["*/5 * * * *"] },
61
- "assets": { "directory": "public", "binding": "ASSETS" }
71
+ "assets": { "directory": "public", "binding": "ASSETS", "run_sprout_first": ["/api/*"] }
62
72
  }
63
73
  ```
64
74
 
65
- The handler is one `export default { fetch }`, optionally with `scheduled` /
66
- `queue` handlers and exported Durable Object classes. See
67
- [`examples/kitchen-sink/`](examples/kitchen-sink) for one app that uses every
68
- binding, with an Astro UI and a runnable end-to-end harness.
75
+ A bare `"CACHE"` binding is auto-provisioned on `deploy`: the CLI creates an
76
+ account-level resource, writes its id back into `sproutboat.jsonc`, and the
77
+ store then survives redeploys. Pass `--no-provision` to keep it a throwaway
78
+ per-deploy store instead, or `sproutboat resource create` to make one up front
79
+ and share its id across projects.
80
+
81
+ The handler is one `export default { fetch(request) }`, optionally with
82
+ `scheduled(event)` / `queue(batch)` handlers and Durable Object classes above
83
+ it. `env` is a global (not a parameter), and every binding call is synchronous.
84
+ See [`examples/kitchen-sink/`](examples/kitchen-sink) for one app that uses
85
+ every binding.
69
86
 
70
87
  ## Requirements
71
88
 
72
89
  - [Bun](https://bun.sh) 1.4+
73
90
 
74
91
  `build` / `deploy` cross-compile the handler to a static `linux-x86_64` binary
75
- with Porffor and Zig (Zig is fetched automatically on first use). The package
76
- ships a prebuilt uWebSockets, so nothing else is compiled from source. No Docker,
77
- no root. On Windows, build from WSL.
92
+ with Porffor and Zig (the CLI fetches Zig automatically on first use). The
93
+ package ships a prebuilt uWebSockets and compiles nothing else from source. No
94
+ Docker, no root. On Windows, build from WSL.
78
95
 
79
96
  If that prebuilt is unusable (a `porffor` pin bump before the archive is
80
97
  refreshed), the first build falls back to compiling uWebSockets locally, which
81
98
  needs `git` and `make` on `PATH`. `SPROUTBOAT_UWS_TARBALL=<archive>` overrides
82
99
  the shipped one.
83
100
 
84
- ## Limits (v1)
101
+ ## Limits
85
102
 
86
- Binding values are text/JSON and travel one at a time over a loopback frame; an
87
- upload is capped at 1 MiB by the worker's HTTP server (large-object R2 is
88
- [#56](https://github.com/baronunread/sproutboat/issues/56)). No WebSockets yet.
103
+ Capability profile `http-sync-v0`: one synchronous `fetch` handler, optional
104
+ `scheduled` / `queue` handlers, no streaming, no WebSockets. Binding values are
105
+ text/JSON and travel one at a time over the loopback frame (32 MiB cap);
106
+ large-object R2 is [#56](https://github.com/baronunread/sproutboat/issues/56).
107
+ The sprout upload caps at 16 MiB, assets at 64 MiB / 4096 files. Node
108
+ compatibility is Porffor alpha, so `import`/`require`, `process`, `node:*`, and
109
+ parsing date strings do not work; `sproutboat check` catches most of it. Full
110
+ list at [sproutboat.com/docs](https://sproutboat.com/docs).
89
111
 
90
112
  ---
91
113
 
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.4.9 · runs on Bun (use `bunx`, not `npx`)
6
+ **Package:** `sproutboat` 0.4.11 · runs on Bun (use `bunx`, not `npx`)
7
7
 
8
8
  ## Commands
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sproutboat",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "description": "Wrangler-shaped CLI for Sproutboat. Deploys workers to any control plane via --api-url / SPROUTBOAT_API_URL.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/main.ts CHANGED
@@ -409,21 +409,32 @@ async function tail(args: string[]) {
409
409
  process.stdout.write(await responseText(response, "could not read logs"));
410
410
  }
411
411
 
412
- type DomainView = { hostname: string; verified: boolean; verification: { type: string; name: string; value: string } | null };
412
+ type DomainView = {
413
+ hostname: string;
414
+ verified: boolean;
415
+ verification: { type: string; name: string; value: string } | null;
416
+ serverAddresses: string[];
417
+ warning?: string;
418
+ };
413
419
  function parseDomain(source: string): DomainView | undefined {
414
420
  const record = jsonObject(parseJsonValue(source));
415
421
  if (!record || !isString(record.hostname) || typeof record.verified !== "boolean") return undefined;
416
422
  const v = jsonObject(record.verification ?? null);
417
423
  const verification = v && isString(v.type) && isString(v.name) && isString(v.value) ? { type: v.type, name: v.name, value: v.value } : null;
418
- return { hostname: record.hostname, verified: record.verified, verification };
424
+ const serverAddresses = Array.isArray(record.serverAddresses) ? record.serverAddresses.filter(isString) : [];
425
+ return { hostname: record.hostname, verified: record.verified, verification, serverAddresses, warning: isString(record.warning) ? record.warning : undefined };
419
426
  }
420
427
  function printDomain(domain: DomainView) {
421
428
  const status = domain.verified ? "verified" : "unverified";
422
429
  console.log(`${status.padEnd(10)} ${domain.hostname}`);
423
430
  if (domain.verification) {
424
- console.log(` add this DNS record, then run: sproutboat domains verify ${domain.hostname}`);
431
+ console.log(" add these DNS records, then run: sproutboat domains verify " + domain.hostname);
425
432
  console.log(` ${domain.verification.type} ${domain.verification.name} "${domain.verification.value}"`);
433
+ if (domain.serverAddresses[0]) {
434
+ console.log(` A ${domain.hostname} ${domain.serverAddresses[0]} (point the hostname here, DNS-only / not proxied)`);
435
+ }
426
436
  }
437
+ if (domain.warning) console.log(amber(` ! ${domain.warning}`));
427
438
  }
428
439
 
429
440
  async function domains(args: string[]) {