spfn 0.2.0-beta.65 → 0.2.0-beta.67

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