diff --git a/.changeset/api-pin-and-next-steps.md b/.changeset/api-pin-and-next-steps.md new file mode 100644 index 0000000..ee95ded --- /dev/null +++ b/.changeset/api-pin-and-next-steps.md @@ -0,0 +1,5 @@ +--- +"seamless-cli": patch +--- + +Scaffold the auth server at v0.18.0, whose OTP and magic-link send routes are POST, as the Go, Rust and Python adapters and the current `@seamless-auth/client` send them. v0.18.0 still serves the deprecated GET routes, so projects on the Express and Fastify starters keep working. The next steps after `seamless init` now give each api starter its own command (`go run .`, `cargo run`, `uv run uvicorn ...`) instead of `npm install && npm run dev`. diff --git a/src/core/images.ts b/src/core/images.ts index 45f142c..80018be 100644 --- a/src/core/images.ts +++ b/src/core/images.ts @@ -3,7 +3,7 @@ // scaffolded with, and never has its data directory pulled out from under it. export const POSTGRES_IMAGE = "postgres:18"; -export const SEAMLESS_AUTH_API_VERSION = "v0.17.0"; +export const SEAMLESS_AUTH_API_VERSION = "v0.18.0"; export const SEAMLESS_AUTH_API_IMAGE = `ghcr.io/fells-code/seamless-auth-api:${SEAMLESS_AUTH_API_VERSION}`; diff --git a/src/core/output.test.ts b/src/core/output.test.ts index 281a8da..72c71e0 100644 --- a/src/core/output.test.ts +++ b/src/core/output.test.ts @@ -1,5 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { + apiDevCommand, maskDatabaseUrl, printManagedSuccessOutput, printSuccessOutput, @@ -351,3 +352,31 @@ describe("output for a full-stack web app", () => { expect(out).not.toContain("# Database"); }); }); + +describe("apiDevCommand", () => { + it("starts each api starter with its own toolchain", () => { + expect(apiDevCommand("express")).toBe("cd api && npm install && npm run dev"); + expect(apiDevCommand("fastify")).toBe("cd api && npm install && npm run dev"); + expect(apiDevCommand("gin")).toBe("cd api && go run ."); + expect(apiDevCommand("axum")).toBe("cd api && cargo run"); + expect(apiDevCommand("fastapi")).toBe( + "cd api && uv run uvicorn app.main:build --factory --reload --port 3000", + ); + }); + + it("prints the api starter's own command in the managed next steps", () => { + printManagedSuccessOutput({ + projectName: "my-app", + webFramework: "react", + apiFramework: "axum", + authServerUrl: "https://auth.example.com", + appName: "Acme App", + }); + + const out = allLogs(); + expect(out).toContain("(Axum)"); + expect(out).toContain("cd api && cargo run"); + expect(out).not.toContain("cd api && npm install"); + }); +}); + diff --git a/src/core/output.ts b/src/core/output.ts index d98b53f..9a02e3e 100644 --- a/src/core/output.ts +++ b/src/core/output.ts @@ -283,7 +283,7 @@ export function printManagedSuccessOutput(config: { if (apiFramework) { console.log(kleur.dim(" # API server")); - console.log(" cd api && npm install && npm run dev\n"); + console.log(` ${apiDevCommand(apiFramework)}\n`); } if (webFramework) { console.log(kleur.dim(" # Web app")); @@ -329,6 +329,21 @@ export function maskDatabaseUrl(url: string): string { return url.replace(/\/\/[^@/]*@/, "//****:****@"); } +// The Go, Rust and Python api starters are not npm projects; each README gives +// the same command for running it on the host. +export function apiDevCommand(framework: string): string { + switch (framework) { + case "gin": + return "cd api && go run ."; + case "axum": + return "cd api && cargo run"; + case "fastapi": + return "cd api && uv run uvicorn app.main:build --factory --reload --port 3000"; + default: + return "cd api && npm install && npm run dev"; + } +} + function formatFramework(name: string) { const map: Record = { react: "React", @@ -338,6 +353,8 @@ function formatFramework(name: string) { nextjs: "Next.js", fastapi: "FastAPI", fastify: "Fastify", + gin: "Gin", + axum: "Axum", vue: "Vue", expo: "Expo", };