spfn 0.2.0-beta.64 → 0.2.0-beta.66

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.
Files changed (3) hide show
  1. package/README.md +109 -5
  2. package/dist/index.js +513 -393
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -20,7 +20,8 @@ Or add it as a project dependency (`spfn init`/`spfn create` do this for you), t
20
20
  call it via `pnpm spfn <command>` / `npm run spfn:<script>`.
21
21
 
22
22
  Requirements: Node.js 18.18+ for bare mode, Node.js 20+ for full mode's MCP server,
23
- Next.js 15+ (App Router, `src/` dir), PostgreSQL (Redis optional).
23
+ Next.js 16.2.11+ (App Router, `src/` dir), PostgreSQL 14+ (Redis optional). Next.js 15
24
+ is not supported — see [the root README](../../README.md#what-do-i-need-installed).
24
25
 
25
26
  ## Usage
26
27
 
@@ -48,7 +49,7 @@ with `--pm`. In a pnpm workspace, `create` installs from the workspace root.
48
49
  ## Commands
49
50
 
50
51
  Registered top-level commands: `create`, `init`, `add`, `dev`, `build`, `start`,
51
- `codegen`, `db`, `env`, `key`, `setup`.
52
+ `provision`, `codegen`, `contract`, `key`, `setup`, `db`, `env`, `secret`.
52
53
 
53
54
  ### `spfn create <name>`
54
55
 
@@ -101,6 +102,23 @@ How it works: if not already present it installs the package, then reads the pac
101
102
  function migrations to `DATABASE_URL`. If `DATABASE_URL` is unset, migration is skipped
102
103
  with a hint to run `spfn db push` later. Works with published and workspace packages.
103
104
 
105
+ ### `spfn add vercel`
106
+
107
+ `vercel` is not a package — it is a built-in target, and the one argument to `add` that is
108
+ not a scoped package name. It scaffolds the three files a Next.js + SPFN app needs to run
109
+ its backend as Vercel Functions:
110
+
111
+ | File | What it is |
112
+ |------|------------|
113
+ | `src/app/api/backend/[[...route]]/route.ts` | `hono/vercel` adapter, mounts the SPFN app under `/api/backend` |
114
+ | `vercel.json` | build config (`pnpm spfn:build`) |
115
+ | `.npmrc` | `@spfn` registry auth, reading `GITEA_NPM_TOKEN` from the environment — never committed |
116
+
117
+ Existing files are never overwritten; they are reported and skipped. The runtime behind
118
+ the adapter is `createServerlessApp()` from `@spfn/core/server`. Afterwards, point
119
+ `SPFN_API_URL` at `https://<your-domain>/api/backend`, and make sure `hono` is a direct
120
+ dependency of the app so `hono/vercel` resolves.
121
+
104
122
  ### `spfn dev`
105
123
 
106
124
  Starts the SPFN server + Next.js (and a codegen watcher). The server must report ready
@@ -176,6 +194,43 @@ export default defineConfig({
176
194
  });
177
195
  ```
178
196
 
197
+ ### `spfn contract`
198
+
199
+ Manages the route contract — what a **separately deployed** client (a mobile app, an external
200
+ API consumer) is promised. A web client needs none of this: it derives its types from
201
+ `AppRouter` in the same build, so a broken response already fails the compile.
202
+
203
+ Requires the `@spfn/core:contract` generator in `.spfnrc.ts`. Every command regenerates the
204
+ contract from the router first, so a stale `contracts/current.json` is never what gets checked
205
+ or released.
206
+
207
+ ```bash
208
+ # Regenerate and compare against the newest released snapshot
209
+ spfn contract check
210
+
211
+ # Cut a release — writes contracts/released/1.3.0.json. Commit it.
212
+ spfn contract release 1.3.0
213
+
214
+ # List released snapshots
215
+ spfn contract list
216
+ ```
217
+
218
+ | Subcommand | Description | Exit code |
219
+ |------------|-------------|-----------|
220
+ | `contract check` | Compares the current contract against the newest released snapshot | 1 when a promise is broken |
221
+ | `contract release <version>` | Writes the snapshot every later build is compared against | 1 when the contract is broken, the version already exists, or it is not newer than the newest one |
222
+ | `contract list` (`ls`) | Lists released snapshots | 0 |
223
+
224
+ `--dir <path>` overrides the contracts directory; by default it comes from the generator's
225
+ `outputDir` in `.spfnrc.ts`.
226
+
227
+ **`spfn build` runs the same gate.** A broken contract fails the build with a non-zero exit
228
+ code — that is the point of hanging the check off codegen rather than leaving it to a
229
+ separate step.
230
+
231
+ See [`@spfn/core` contract docs](../core/src/contract/README.md) for the case table and the
232
+ removal rules.
233
+
179
234
  ### `spfn db`
180
235
 
181
236
  Wraps Drizzle Kit with auto-generated config. Most commands read `DATABASE_URL` from the
@@ -186,6 +241,7 @@ loaded `.env` chain.
186
241
  | `db generate` (`g`) | Generate migrations from schema changes (timestamp-prefixed) |
187
242
  | `db push` | Diff with Drizzle Kit's current PostgreSQL engine and apply the selected DDL atomically. Destructive changes need confirmation; `--force` applies them, `--dry-run` previews |
188
243
  | `db migrate` (`m`) | Run pending migrations. `--with-backup` snapshots first |
244
+ | `db status` | Show which migrations are applied and which are pending, for the project and for each installed function package |
189
245
  | `db studio` | Open Drizzle Studio. `-p, --port` (auto-finds a free port) |
190
246
  | `db check` | Verify the database connection |
191
247
  | `db drop` | Drop all tables — **destructive**, double-prompts (see [Pitfalls](#pitfalls)) |
@@ -396,7 +452,16 @@ the SPFN API with cookie forwarding and interceptors, resolving routes via the g
396
452
 
397
453
  ## Deployment
398
454
 
399
- `spfn build` then `spfn start`, or use the generated Docker files.
455
+ Two targets, both shipping from the same repository.
456
+
457
+ **Vercel — serverless, one origin, no container.** Run `spfn add vercel` (above) and
458
+ deploy. Frontend and backend share a single Vercel origin. One caveat: the in-process job
459
+ worker does not run there, so enqueuing works but nothing drains the queue — schedule a
460
+ route that processes a batch (Vercel Cron), or run jobs on an always-on target.
461
+
462
+ **Always-on — a long-lived process.** `spfn build` then `spfn start`, or the generated
463
+ Docker files. Background jobs, WebSocket events and the periodic database health check all
464
+ need this path.
400
465
 
401
466
  ```bash
402
467
  # Build + run locally
@@ -423,6 +488,42 @@ type ships from `spfn` (`@type {import('spfn').SpfnConfig}`).
423
488
 
424
489
  ---
425
490
 
491
+ ## FAQ
492
+
493
+ **`create` or `init` — which one?**
494
+ `create` starts a new project: it runs `create-next-app` with SPFN's flags and then runs
495
+ `init` inside it. `init` adds SPFN to a Next.js app that already exists. If you built
496
+ something with an AI coding agent and now want a real backend under it, `init` is the one.
497
+
498
+ **`bare` or `full`?**
499
+ `full` is the recommended baseline: core, auth, i18n and MCP wired together, so you get a
500
+ working authenticated app on day one. `bare` is core only — the architecture with nothing
501
+ else decided. Automation should always pass `--mode` explicitly, because a `--yes` run
502
+ without one still produces `bare` for backward compatibility.
503
+
504
+ **Why doesn't my server restart when I edit a file?**
505
+ Because hot reload is off by default. `spfn dev --watch` restarts the server on `src/server`
506
+ changes. Next.js reloads on its own either way.
507
+
508
+ **Do I have to use Docker?**
509
+ No. Vercel is a first-class target and needs no container. Docker is the always-on path,
510
+ and `docker compose up -d` is also the convenient way to get PostgreSQL and Redis locally —
511
+ pointing at your own PostgreSQL works too. PostgreSQL itself is not optional.
512
+
513
+ **Which Node version do I need?**
514
+ 18.18 or later for bare mode, 20 or later for full mode, because full mode includes the
515
+ MCP server.
516
+
517
+ **When do I have to run codegen by hand?**
518
+ Whenever routes change outside `spfn dev`, which runs a codegen watcher for you. A stale or
519
+ missing `src/generated/route-map.ts` makes the RPC proxy answer 404 — run `spfn codegen run`
520
+ and commit the result.
521
+
522
+ **Where do secrets go?**
523
+ `.env.server` (gitignored, server-only) for backend values, `.env.local` for the session
524
+ cookie secret that the Next.js runtime itself needs. Never `spfn.config.js` — that file is
525
+ committed.
526
+
426
527
  ## Pitfalls
427
528
 
428
529
  - **`.env.server` is gitignored and server-only.** Put backend-only DB/secret values there,
@@ -441,7 +542,8 @@ type ships from `spfn` (`@type {import('spfn').SpfnConfig}`).
441
542
  destructive ones unless `--force`/confirmed. Prefer `db generate` + `db migrate` for
442
543
  production; `db push` is dev-only.
443
544
  - **`spfn add` requires a scoped package name** (must contain `/`) and only applies
444
- migrations when `DATABASE_URL` is set — otherwise it skips with a hint.
545
+ migrations when `DATABASE_URL` is set — otherwise it skips with a hint. The single
546
+ exception is `spfn add vercel`, a built-in target rather than a package.
445
547
  - **Package manager is auto-detected from lockfiles.** If detection is wrong (e.g. mixed
446
548
  lockfiles), pass `--pm` to `create`. In a pnpm workspace, `create` installs from the
447
549
  workspace root, not the new project dir.
@@ -456,5 +558,7 @@ type ships from `spfn` (`@type {import('spfn').SpfnConfig}`).
456
558
 
457
559
  ## Related
458
560
 
459
- - `@spfn/core` — server, route DSL, codegen, db, client runtime.
561
+ - [`@spfn/core`](../core/README.md) — server, route DSL, codegen, db, client runtime.
562
+ - [`@spfn/auth`](../auth/README.md) — what `--mode full` wires in for accounts and roles.
563
+ - [`@spfn/mcp`](../mcp/README.md) — what `--mode full` wires in for operating the app.
460
564
  - Project root README — framework overview and getting started.