// @bun
var y=Object.defineProperty;var g=(p)=>p;function i(p,a){this[p]=g.bind(null,a)}var q=(p,a)=>{for(var h in a)y(p,h,{get:a[h],enumerable:!0,configurable:!0,set:i.bind(a,h)})};var z=(p,a)=>()=>(p&&(a=p(p=0)),a);import v from"@contractspec/lib.ui-link";import{jsx as d,jsxs as N}from"react/jsx-runtime";function m({title:p="Need the operating layer on top of OSS ContractSpec?",body:a="ContractSpec Studio helps teams turn evidence into proposed spec changes, governed delivery loops, and execution-ready task packs while keeping the open contract system as the source of truth.",ctaLabel:h="See what Studio adds",href:o="https://www.contractspec.studio/docs"}){return N("div",{className:"card-subtle space-y-3 p-6",children:[d("h3",{className:"font-semibold text-lg",children:p}),d("p",{className:"text-muted-foreground text-sm",children:a}),d(v,{href:o,className:"btn-primary",children:h})]})}import{CodeBlock as r}from"@contractspec/lib.design-system";import u from"@contractspec/lib.ui-link";import{AlertCircle as P,ChevronRight as b,FileCode as c,Scan as n,Settings as f}from"lucide-react";import{jsx as t,jsxs as e}from"react/jsx-runtime";var L=[{name:"NestJS",flag:"nestjs",description:"Controllers, decorators, DTOs"},{name:"Express",flag:"express",description:"Router methods, middleware"},{name:"Fastify",flag:"fastify",description:"Route definitions, schemas"},{name:"Hono",flag:"hono",description:"Route handlers, validators"},{name:"Elysia",flag:"elysia",description:"Type-safe routes, schemas"},{name:"tRPC",flag:"trpc",description:"Procedure definitions"},{name:"Next.js",flag:"next-api",description:"API routes (app/api, pages/api)"}];function O(){return e("div",{className:"space-y-8",children:[e("div",{className:"space-y-3",children:[t("h1",{className:"font-bold text-4xl",children:"Import Existing Codebases"}),t("p",{className:"text-lg text-muted-foreground",children:"Convert your existing API endpoints into ContractSpec contracts. Auto-detect frameworks, extract schemas, and generate explicit contract definitions from your code."})]}),e("div",{className:"card-subtle space-y-4 p-6",children:[t("h2",{className:"font-bold text-2xl",children:"What you'll learn"}),e("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[t("li",{children:"How to import existing API endpoints as ContractSpec contracts."}),t("li",{children:"Framework-specific patterns and auto-detection."}),t("li",{children:"Customizing imports with scopes, dry-run, and output options."}),t("li",{children:"Registering imported contracts and adding handlers."})]})]}),e("div",{className:"space-y-6",children:[e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"Why import existing code?"}),t("p",{className:"text-muted-foreground text-sm",children:"Instead of writing contracts from scratch, the import command extracts endpoint patterns from your existing codebase. This gives you:"}),e("ul",{className:"list-disc space-y-1 pl-5 text-muted-foreground text-sm",children:[t("li",{children:"Instant spec coverage for existing APIs"}),t("li",{children:"Type-safe schemas derived from your existing types"}),t("li",{children:"A foundation to iterate and refine contracts"}),t("li",{children:"Gradual adoption without rewriting code"})]})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"Supported frameworks"}),t("div",{className:"grid gap-3 md:grid-cols-2 lg:grid-cols-3",children:L.map((p)=>e("div",{className:"flex items-start gap-3 rounded-lg border border-white/10 p-4",children:[t(c,{className:"text-violet-400",size:18}),e("div",{className:"space-y-1",children:[t("h3",{className:"font-semibold",children:p.name}),t("p",{className:"text-muted-foreground text-xs",children:p.description}),e("code",{className:"text-violet-400 text-xs",children:["--framework ",p.flag]})]})]},p.flag))})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"1) Quick start"}),t("p",{className:"text-muted-foreground text-sm",children:"Run the import command to auto-detect your framework and extract endpoints:"}),t(r,{language:"bash",filename:"import-quickstart",code:`# Auto-detect framework and import all endpoints
contractspec import ./src

# Preview what would be imported (dry-run)
contractspec import ./src --dry-run

# Force a specific framework
contractspec import ./src --framework nestjs`}),t("p",{className:"text-muted-foreground text-sm",children:"Expected output: A summary of endpoints found, schemas extracted, and files generated."})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"2) Framework-specific patterns"}),t("p",{className:"text-muted-foreground text-sm",children:"The import command recognizes these patterns in each framework:"})]}),e("div",{className:"space-y-3",children:[e("h3",{className:"flex items-center gap-2 font-semibold text-xl",children:[t(n,{size:18,className:"text-blue-400"}),"NestJS"]}),t(r,{language:"typescript",filename:"src/users/users.controller.ts (before)",code:`@Controller('users')
export class UsersController {
  @Get(':id')
  async getUser(@Param('id') id: string): Promise<UserDto> {
    return this.usersService.findOne(id);
  }

  @Post()
  @UseGuards(AuthGuard)
  async createUser(@Body() dto: CreateUserDto): Promise<UserDto> {
    return this.usersService.create(dto);
  }
}`}),e("p",{className:"text-muted-foreground text-sm",children:["Detected: ",t("code",{children:"@Controller"}),", ",t("code",{children:"@Get"}),","," ",t("code",{children:"@Post"}),", ",t("code",{children:"@Body"}),", ",t("code",{children:"@Param"}),","," ",t("code",{children:"@UseGuards"})," decorators."]})]}),e("div",{className:"space-y-3",children:[e("h3",{className:"flex items-center gap-2 font-semibold text-xl",children:[t(n,{size:18,className:"text-green-400"}),"Express"]}),t(r,{language:"typescript",filename:"src/routes/users.ts (before)",code:`const router = express.Router();

router.get('/users/:id', async (req, res) => {
  const user = await getUserById(req.params.id);
  res.json(user);
});

router.post('/users', validateBody(CreateUserSchema), async (req, res) => {
  const user = await createUser(req.body);
  res.status(201).json(user);
});`}),e("p",{className:"text-muted-foreground text-sm",children:["Detected: ",t("code",{children:"router.get"}),", ",t("code",{children:"router.post"}),", validation middleware, Zod schemas."]})]}),e("div",{className:"space-y-3",children:[e("h3",{className:"flex items-center gap-2 font-semibold text-xl",children:[t(n,{size:18,className:"text-purple-400"}),"Next.js API Routes"]}),t(r,{language:"typescript",filename:"app/api/users/[id]/route.ts (before)",code:`export async function GET(
  request: Request,
  { params }: { params: { id: string } }
) {
  const user = await getUserById(params.id);
  return Response.json(user);
}

export async function POST(request: Request) {
  const body = await request.json();
  const user = await createUser(body);
  return Response.json(user, { status: 201 });
}`}),e("p",{className:"text-muted-foreground text-sm",children:["Detected: ",t("code",{children:"GET"}),", ",t("code",{children:"POST"})," exports in"," ",t("code",{children:"app/api/**/route.ts"})," and ",t("code",{children:"pages/api/**/*.ts"}),"."]})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"3) Understanding generated contracts"}),t("p",{className:"text-muted-foreground text-sm",children:"The import command generates ContractSpec operations with TODO placeholders for fields it cannot infer:"}),t(r,{language:"typescript",filename:".contractspec/generated/users.operation.ts",code:`import { defineQuery, defineCommand } from "@contractspec/lib.contracts-spec";
import { SchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";

export const GetUserQuery = defineQuery({
  meta: {
    key: "users.get",
    version: "1.0.0",
    description: "TODO: Add description",
    stability: "draft",
    owners: ["TODO"],
    tags: ["users"],
  },
  io: {
    input: new SchemaModel({
      name: "GetUserInput",
      fields: {
        id: { type: ScalarTypeEnum.String(), isOptional: false },
      },
    }),
    output: new SchemaModel({
      name: "GetUserOutput",
      fields: {
        // TODO: Add output fields based on your UserDto
        id: { type: ScalarTypeEnum.String(), isOptional: false },
      },
    }),
  },
  policy: { auth: "user" }, // Inferred from @UseGuards
  transport: {
    rest: { method: "GET", path: "/users/:id" },
  },
});

export const CreateUserCommand = defineCommand({
  meta: {
    key: "users.create",
    version: "1.0.0",
    description: "TODO: Add description",
    stability: "draft",
    owners: ["TODO"],
    tags: ["users"],
  },
  io: {
    input: new SchemaModel({
      name: "CreateUserInput",
      fields: {
        // TODO: Add fields from CreateUserDto
      },
    }),
    output: new SchemaModel({
      name: "CreateUserOutput",
      fields: {
        id: { type: ScalarTypeEnum.String(), isOptional: false },
      },
    }),
  },
  policy: { auth: "admin" },
  transport: {
    rest: { method: "POST", path: "/users" },
  },
});`})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"4) Customizing imports"}),e("div",{className:"flex items-center gap-2",children:[t(f,{size:18,className:"text-violet-400"}),t("h3",{className:"font-semibold text-lg",children:"Available options"})]}),t("div",{className:"overflow-x-auto",children:e("table",{className:"w-full text-sm",children:[t("thead",{children:e("tr",{className:"border-white/10 border-b",children:[t("th",{className:"py-2 pr-4 text-left",children:"Option"}),t("th",{className:"py-2 pr-4 text-left",children:"Description"}),t("th",{className:"py-2 text-left",children:"Example"})]})}),e("tbody",{className:"text-muted-foreground",children:[e("tr",{className:"border-white/5 border-b",children:[t("td",{className:"py-2 pr-4",children:t("code",{children:"--scope"})}),t("td",{className:"py-2 pr-4",children:"Limit to specific directories"}),t("td",{className:"py-2",children:t("code",{children:"--scope src/users src/auth"})})]}),e("tr",{className:"border-white/5 border-b",children:[t("td",{className:"py-2 pr-4",children:t("code",{children:"--framework"})}),t("td",{className:"py-2 pr-4",children:"Force a specific framework"}),t("td",{className:"py-2",children:t("code",{children:"--framework express"})})]}),e("tr",{className:"border-white/5 border-b",children:[t("td",{className:"py-2 pr-4",children:t("code",{children:"--output"})}),t("td",{className:"py-2 pr-4",children:"Output directory"}),t("td",{className:"py-2",children:t("code",{children:"--output ./contracts"})})]}),e("tr",{className:"border-white/5 border-b",children:[t("td",{className:"py-2 pr-4",children:t("code",{children:"--dry-run"})}),t("td",{className:"py-2 pr-4",children:"Preview without writing files"}),t("td",{className:"py-2",children:t("code",{children:"--dry-run"})})]}),e("tr",{className:"border-white/5 border-b",children:[t("td",{className:"py-2 pr-4",children:t("code",{children:"--analyze"})}),t("td",{className:"py-2 pr-4",children:"Analysis only, no code generation"}),t("td",{className:"py-2",children:t("code",{children:"--analyze"})})]}),e("tr",{children:[t("td",{className:"py-2 pr-4",children:t("code",{children:"--json"})}),t("td",{className:"py-2 pr-4",children:"Output as JSON for scripting"}),t("td",{className:"py-2",children:t("code",{children:"--json"})})]})]})]})}),t(r,{language:"bash",filename:"import-options",code:`# Import only specific modules
contractspec import ./src --scope src/users src/orders

# Preview with analysis
contractspec import ./src --dry-run --analyze

# Output to custom directory
contractspec import ./src --output ./src/contracts/generated

# Get JSON for CI/scripting
contractspec import ./src --json > import-result.json`})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"5) Registering imported contracts"}),t("p",{className:"text-muted-foreground text-sm",children:"After import, register contracts and add handlers:"}),t(r,{language:"typescript",filename:"src/contracts/registry.ts",code:`import {
  OperationSpecRegistry,
  installOp,
} from "@contractspec/lib.contracts-spec/operations";
import {
  GetUserQuery,
  CreateUserCommand,
} from "./.contractspec/generated/users.operation";

export const registry = new OperationSpecRegistry();

// Add handlers to imported operations
installOp(registry, GetUserQuery, async (input) => {
  const user = await db.user.findUnique({ where: { id: input.id } });
  return user;
});

installOp(registry, CreateUserCommand, async (input) => {
  const user = await db.user.create({ data: input });
  return { id: user.id };
});`})]}),e("div",{className:"space-y-3",children:[t("h2",{className:"font-bold text-2xl",children:"6) After importing"}),e("ol",{className:"list-decimal space-y-2 pl-5 text-muted-foreground text-sm",children:[e("li",{children:[t("strong",{children:"Review generated contracts"})," \u2014 Check the TODO placeholders and fill in descriptions, owners, and tags."]}),e("li",{children:[t("strong",{children:"Refine schemas"})," \u2014 Add proper types, validation rules, and error definitions."]}),e("li",{children:[t("strong",{children:"Run validation"})," \u2014"," ",t("code",{children:"contractspec validate"})," to ensure contracts are valid."]}),e("li",{children:[t("strong",{children:"Register and wire handlers"})," \u2014 Connect contracts to your existing business logic."]}),e("li",{children:[t("strong",{children:"Iterate"})," \u2014 The imported contracts are a starting point. Refine them as your spec matures."]})]})]}),e("div",{className:"space-y-3",children:[e("h2",{className:"flex items-center gap-2 font-bold text-2xl",children:[t(P,{size:20,className:"text-yellow-400"}),"Troubleshooting"]}),e("div",{className:"space-y-4",children:[e("div",{className:"card-subtle space-y-2 p-4",children:[t("h3",{className:"font-semibold",children:"Framework not detected"}),e("p",{className:"text-muted-foreground text-sm",children:["Use ",t("code",{children:"--framework <name>"})," to force a specific framework. Check that your entry files follow standard patterns."]})]}),e("div",{className:"card-subtle space-y-2 p-4",children:[t("h3",{className:"font-semibold",children:"Missing schemas"}),e("p",{className:"text-muted-foreground text-sm",children:["Schema inference works best with explicit types. If using"," ",t("code",{children:"any"})," or dynamic types, you'll see TODO placeholders. Fill them in manually."]})]}),e("div",{className:"card-subtle space-y-2 p-4",children:[t("h3",{className:"font-semibold",children:"Partial imports"}),e("p",{className:"text-muted-foreground text-sm",children:["Some endpoints may not be detected if they use unconventional patterns. Use ",t("code",{children:"--analyze"})," to see what was found, then add missing contracts manually."]})]})]})]}),t(m,{title:"Want evidence-driven migration priorities?",body:"Studio clusters product signals into scored patterns, then proposes contract changes and execution-ready work for the highest-impact areas."})]}),e("div",{className:"flex items-center gap-4 pt-4",children:[e(u,{href:"/docs/guides/spec-validation-and-typing",className:"btn-primary",children:["Next: Spec validation + typing ",t(b,{size:16})]}),t(u,{href:"/docs/guides",className:"btn-ghost",children:"Back to guides"})]})]})}export{O as GuideImportExistingCodebasesPage};
