var p=Object.defineProperty;var d=(a)=>a;function m(a,o){this[a]=d.bind(null,o)}var g=(a,o)=>{for(var i in o)p(a,i,{get:o[i],enumerable:!0,configurable:!0,set:m.bind(o,i)})};var y=(a,o)=>()=>(a&&(o=a(a=0)),o);import u from"@contractspec/lib.ui-link";import{jsx as c,jsxs as h}from"react/jsx-runtime";function r({title:a="Need the operating layer on top of OSS ContractSpec?",body:o="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:i="See what Studio adds",href:l="https://www.contractspec.studio/docs"}){return h("div",{className:"card-subtle space-y-3 p-6",children:[c("h3",{className:"font-semibold text-lg",children:a}),c("p",{className:"text-muted-foreground text-sm",children:o}),c(u,{href:l,className:"btn-primary",children:i})]})}import{CodeBlock as n}from"@contractspec/lib.design-system";import s from"@contractspec/lib.ui-link";import{ChevronRight as f}from"lucide-react";import{jsx as e,jsxs as t}from"react/jsx-runtime";function O(){return t("div",{className:"space-y-8",children:[t("div",{className:"space-y-3",children:[e("h1",{className:"font-bold text-4xl",children:"Spec-driven validation + typing"}),e("p",{className:"text-lg text-muted-foreground",children:"Define a single operation with SchemaModel, generate validation, and keep your existing handler logic."})]}),t("div",{className:"card-subtle space-y-4 p-6",children:[e("h2",{className:"font-bold text-2xl",children:"What you'll build"}),t("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[e("li",{children:"One command spec with explicit input/output models."}),e("li",{children:"Validation + typing without rewriting your service layer."}),e("li",{children:"Clear acceptance scenarios for regression safety."})]})]}),t("div",{className:"space-y-6",children:[t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"1) Define the spec"}),t("p",{className:"text-muted-foreground text-sm",children:["Create ",e("code",{children:"src/contracts/contact-create.operation.ts"}),":"]}),e(n,{language:"typescript",filename:"src/contracts/contact-create.operation.ts",code:`import { defineCommand } from "@contractspec/lib.contracts-spec/operations";
import { SchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";

const ContactInput = new SchemaModel({
  name: "ContactInput",
  fields: {
    email: { type: ScalarTypeEnum.Email(), isOptional: false },
    firstName: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
    lastName: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
  },
});

const ContactOutput = new SchemaModel({
  name: "ContactOutput",
  fields: {
    id: { type: ScalarTypeEnum.String(), isOptional: false },
    email: { type: ScalarTypeEnum.Email(), isOptional: false },
    createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
  },
});

export const ContactCreateCommand = defineCommand({
  meta: {
    key: "contact.create",
    version: "1.0.0",
    description: "Create a CRM contact",
    owners: ["@sales"],
    tags: ["crm", "contacts"],
  },
  io: {
    input: ContactInput,
    output: ContactOutput,
  },
  policy: {
    auth: "user",
  },
  acceptance: {
    scenarios: [
      {
        key: "create-contact",
        given: ["User is authenticated"],
        when: ["ContactCreateCommand executes"],
        then: ["Contact is persisted", "Email is validated"],
      },
    ],
  },
});`})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"2) Wire the handler"}),e("p",{className:"text-muted-foreground text-sm",children:"Keep your existing code. Just ensure the handler returns the output shape defined above."}),e(n,{language:"typescript",filename:"src/handlers/contact-create.ts",code:`import { ContactCreateCommand } from "@/contracts/contact-create.operation";
 
 export async function handleContactCreate(
   input: (typeof ContactCreateCommand)["io"]["input"],
   ctx: { userId: string }
 ) {
   // Your existing persistence logic
   return {
     id: "contact_123",
     email: input.email,
     createdAt: new Date().toISOString(),
   };
 }`})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"3) Validate"}),e(n,{language:"bash",filename:"spec-validation",code:"contractspec validate src/contracts/contact-create.operation.ts"}),t("p",{className:"text-muted-foreground text-sm",children:["Expected output: ",e("code",{children:"Validation passed"}),"."]})]}),t("div",{className:"card-subtle space-y-3 p-6",children:[e("h3",{className:"font-semibold text-lg",children:"Example package"}),e("p",{className:"text-muted-foreground text-sm",children:"The CRM Pipeline example includes real specs, handlers, and presentations for contact + deal flows."}),e(n,{language:"bash",filename:"crm-example",code:`# Build + validate the CRM pipeline example
cd packages/examples/crm-pipeline
bun install
bun run build
bun run validate`})]}),e(r,{title:"Need validation tied to real outcomes?",body:"Studio links checks to evidence, focus decisions, and post-release verification so specs evolve with product truth."})]}),t("div",{className:"flex items-center gap-4 pt-4",children:[t(s,{href:"/docs/guides/contract-driven-forms",className:"btn-primary",children:["Next: Contract-driven forms ",e(f,{size:16})]}),e(s,{href:"/docs/guides",className:"btn-ghost",children:"Back to guides"})]})]})}export{O as GuideSpecValidationTypingPage};
