Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/api-pin-and-next-steps.md
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion src/core/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;

Expand Down
29 changes: 29 additions & 0 deletions src/core/output.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
apiDevCommand,
maskDatabaseUrl,
printManagedSuccessOutput,
printSuccessOutput,
Expand Down Expand Up @@ -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");
});
});

19 changes: 18 additions & 1 deletion src/core/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down Expand Up @@ -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<string, string> = {
react: "React",
Expand All @@ -338,6 +353,8 @@ function formatFramework(name: string) {
nextjs: "Next.js",
fastapi: "FastAPI",
fastify: "Fastify",
gin: "Gin",
axum: "Axum",
vue: "Vue",
expo: "Expo",
};
Expand Down
Loading