@crossdelta/platform-sdk 0.16.6 → 0.17.1
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.
package/bin/cli.js
CHANGED
|
@@ -14,16 +14,16 @@ To create a new workspace, run:
|
|
|
14
14
|
|
|
15
15
|
\x1B[36mpf new workspace my-platform\x1B[0m
|
|
16
16
|
`);e=t}return e}function ve(){let e=k(),t=(0,A.join)(e,"package.json");if(!(0,D.existsSync)(t))return`@${e.split("/").pop()||"workspace"}`;try{let n=JSON.parse((0,D.readFileSync)(t,"utf-8")).name;return n?n.startsWith("@")?n.split("/")[0]:`@${n}`:`@${e.split("/").pop()||"workspace"}`}catch{return`@${e.split("/").pop()||"workspace"}`}}function Q(e,t,r=process.cwd()){let n=(0,A.join)(r,"package.json"),o=(0,me.readJsonSync)(n);ui(o,e,t),(0,me.writeJsonSync)(n,o,{spaces:2,EOL:`
|
|
17
|
-
`,encoding:"utf-8"})}function An(e,t=process.cwd()){let r=(0,A.join)(t,"package.json"),n=(0,me.readJsonSync)(r),o=e.split("."),s=n;for(let a of o){if(s===null||typeof s!="object"||!(a in s))return;s=s[a]}return s}function ui(e,t,r){let n=t.split("."),o=e;for(let s=0;s<n.length-1;s++){let a=n[s];(!(a in o)||typeof o[a]!="object"||o[a]===null)&&(o[a]={}),o=o[a]}o[n[n.length-1]]=r}var Ct=e=>{let t=Pn();return(0,me.readJSONSync)((0,A.resolve)(t,e),{encoding:"utf-8"})},U=Ct("package.json"),gi={docs:{base:["service.md"],frameworks:{}},serviceTypes:{hono:{commandType:"hono-micro",entryPoint:"src/index.ts",skipFiles:[]},nest:{commandType:"nest-micro",entryPoint:"src/main.ts",skipFiles:[]}}},Ve=()=>U.generatorConfig??gi;var Dn=require("node:fs"),Bn=require("node:path"),mr=require("node:process"),Hn=require("execa");var pr=require("node:child_process"),
|
|
17
|
+
`,encoding:"utf-8"})}function An(e,t=process.cwd()){let r=(0,A.join)(t,"package.json"),n=(0,me.readJsonSync)(r),o=e.split("."),s=n;for(let a of o){if(s===null||typeof s!="object"||!(a in s))return;s=s[a]}return s}function ui(e,t,r){let n=t.split("."),o=e;for(let s=0;s<n.length-1;s++){let a=n[s];(!(a in o)||typeof o[a]!="object"||o[a]===null)&&(o[a]={}),o=o[a]}o[n[n.length-1]]=r}var Ct=e=>{let t=Pn();return(0,me.readJSONSync)((0,A.resolve)(t,e),{encoding:"utf-8"})},U=Ct("package.json"),gi={docs:{base:["service.md"],frameworks:{}},serviceTypes:{hono:{commandType:"hono-micro",entryPoint:"src/index.ts",skipFiles:[]},nest:{commandType:"nest-micro",entryPoint:"src/main.ts",skipFiles:[]}}},Ve=()=>U.generatorConfig??gi;var Dn=require("node:fs"),Bn=require("node:path"),mr=require("node:process"),Hn=require("execa");var pr=require("node:child_process"),Rn=require("node:path"),Mn=require("execa");var In=require("node:fs"),$n=require("node:path"),Nn=require("dotenv"),cr=(e,t)=>{let r=(0,$n.resolve)(t,e);return(0,In.existsSync)(r)?(0,Nn.config)({path:r,processEnv:{}}).parsed||{}:{}},jn=(e,t)=>{let r=cr(e,t),n=[];for(let[o,s]of Object.entries(r))if(o.endsWith("_PORT")&&s){let a=Number.parseInt(s,10);!Number.isNaN(a)&&a>0&&n.push(a)}return n};var lr={...process.env,NODE_NO_WARNINGS:"1"},fi=(e,t,r)=>e?"pipe":t||r?["ignore","pipe","pipe"]:"inherit",hi=(e,t,r)=>e?{...lr,...e}:t||r?{...lr,CI:"true"}:{...lr},yi=e=>e.includes("EEXIST")||e.includes("failed to link package");async function ae(e,t,{cwd:r=process.cwd(),task:n,shell:o,context:s=e,quiet:a=!1,nonInteractive:i=!1,env:c}={}){try{t.length===0&&(t=e.split(" ").slice(1));let l=(0,Mn.execa)(e,t,{cwd:r,stdio:fi(a,n,i),all:n||i?!0:void 0,shell:o??!0,env:hi(c,n,i)});l.all&&l.all.on("data",p=>{let d=p.toString().trim();n?(n.output=d,d.length&&m.storeLog(d,s)):i&&d.length&&console.log(d)}),await l}catch(l){let p=l instanceof Error?l.message:String(l);if(yi(p))return;throw new Error(ki(p))}}var ki=e=>{let t=e.match(/error: (.+)/);return t?t[1].trim():e};function Fn(e,t,r={}){let{cwd:n=process.cwd(),envFile:o,detached:s=!0,pipeStdout:a=!1,onStdout:i,onStderr:c,onExit:l}=r,p=o?cr(o,n):{},d=(0,Rn.resolve)(n,"node_modules",".bin"),v=process.env.PATH||"",$=`${d}:${v}`,Je={...process.env,...p,PATH:$,FORCE_COLOR:"1"},F=(0,pr.spawn)(e,t,{cwd:n,env:Je,stdio:["inherit",a?"pipe":"inherit","pipe"],detached:s});return i&&a&&F.stdout?.on("data",i),c&&F.stderr?.on("data",c),l&&F.on("exit",l),F}function wt(e,t,r={}){let{cwd:n=process.cwd()}=r;(0,pr.spawn)(e,t,{cwd:n,stdio:"inherit",shell:!0}).on("exit",s=>process.exit(s||0))}async function On(e){let{execSync:t}=await import("node:child_process");for(let r of e)try{let o=t(`lsof -ti:${r}`,{encoding:"utf8",stdio:"pipe"}).trim().split(`
|
|
18
18
|
`).filter(Boolean);for(let s of o)try{process.kill(Number.parseInt(s,10),"SIGKILL")}catch{}}catch{}}var bt=e=>qe(e);function dr(e=process.cwd()){let t=r=>(0,Dn.existsSync)((0,Bn.join)(e,r));if(t("bun.lock")||t("bun.lockb"))return"bun";if(t("pnpm-lock.yaml"))return"pnpm";if(t("yarn.lock"))return"yarn";if(t("package-lock.json"))return"npm"}function w(e){return dr(e)??ur()}function ur(){return bt("bun")?"bun":bt("pnpm")?"pnpm":bt("yarn")?"yarn":"npm"}function Ln(){return["bun","pnpm","yarn","npm"].filter(bt)}async function H(e,t){let r=xi(e,t),{mergedOptions:n,packages:o}=r,{cwd:s=process.cwd(),flags:a=[],task:i,quiet:c}=n,l=n.packageManager??w(),p=[],d=Array.isArray(o)?o:[o];l==="bun"&&(d=d.map($=>$.replace("git+ssh://",""))),l==="pnpm"&&(p.push("--config.engine-strict=false"),p.push("--no-frozen-lockfile")),["yarn","npm"].includes(l)&&p.push("--ignore-engines");let v=d.length?l==="npm"?["install",...a,...p,...d]:["add",...a,...p,...d]:["install",...a,...p];await ae(l,v,{cwd:s,task:i,quiet:c})}async function Wn(e){let t=["-g"],r=[...e.flags??[],...t];await H({...e,flags:r,packageManager:e.packageManager??w()})}function _n(e,t,r){let{args:n,mergedOptions:o}=Un(t??[],r),s=o.manager??w(),{command:a,args:i}=Gn(s);console.log(`
|
|
19
19
|
Running command: ${a} ${[...i,e,...n].join(" ")}
|
|
20
|
-
`),(0,Hn.execaSync)(a,[...i,e,...n],{cwd:o.cwd??(0,mr.cwd)(),stdio:"inherit",preferLocal:!0})}async function ee(e,t,r){let{args:n,mergedOptions:o}=Un(t??[],r),s=o.manager??w(),{command:a,args:i}=Gn(s);await ae(a,[...i,e,...n],o)}async function Ze(e,t){let{script:r,mergedOptions:n}=Ci(e,t),o=n.packageManager??w();await ae(o,["run",r,...n.args??[]],{cwd:n.cwd??(0,mr.cwd)(),task:n.task})}function Gn(e){let r={bun:"bunx",pnpm:"npx",yarn:"npx",npm:"npx"}[e];if(!r)throw new Error(`No executor found for the detected package manager: ${e}`);let[n,...o]=r.split(" ");return{command:n,args:o}}function xi(e,t){return Array.isArray(e)?{packages:e,mergedOptions:{...t,packages:e}}:{packages:e.packages??[],mergedOptions:e}}function Un(e,t){return Array.isArray(e)?{args:e,mergedOptions:t??{}}:{args:[],mergedOptions:e}}function Ci(e,t){return typeof e=="string"?{script:e,mergedOptions:t??{}}:{script:e.script,mergedOptions:e}}var wi=e=>e==="yarn"?["npm","audit"]:["audit"],zn=new Kn.Command("audit").description("Run security audit on dependencies").allowUnknownOption(!0).action((e,t)=>{let r=k(),n=w(),o=wi(n),s=t.args||[];console.log(Jn.default.dim(`Running ${n} ${[...o,...s].join(" ")}`)),wt(n,[...o,...s],{cwd:r})});var ce=require("@listr2/prompt-adapter-enquirer"),oe=u(require("chalk"));var Ce=require("node:fs"),eo=require("node:os"),to=require("node:path");var ie=require("node:crypto"),xe=require("node:fs"),de=require("node:os"),qn=require("node:path"),gr=(0,qn.join)((0,de.homedir)(),".platform-sdk-keys"),Vn="aes-256-gcm",Zn=()=>{let e=`${(0,de.hostname)()}:${(0,de.userInfo)().username}:${(0,de.homedir)()}`;return(0,ie.createHash)("sha256").update(e).digest()},Yn=()=>{if(!(0,xe.existsSync)(gr))return{};try{return JSON.parse((0,xe.readFileSync)(gr,"utf-8"))}catch{return{}}},bi=e=>{(0,xe.writeFileSync)(gr,JSON.stringify(e,null,2),{mode:384})},Si=e=>{let t=Zn(),r=(0,ie.randomBytes)(16),n=(0,ie.createCipheriv)(Vn,t,r),o=n.update(e,"utf8","hex");return o+=n.final("hex"),{iv:r.toString("hex"),tag:n.getAuthTag().toString("hex"),data:o}},Pi=e=>{let t=Zn(),r=Buffer.from(e.iv,"hex"),n=Buffer.from(e.tag,"hex"),o=(0,ie.createDecipheriv)(Vn,t,r);o.setAuthTag(n);let s=o.update(e.data,"hex","utf8");return s+=o.final("utf8"),s};async function Xn(e,t){let r=Yn();r[e]=Si(t),bi(r)}async function St(e){let r=Yn()[e];if(!r)return null;try{return Pi(r)}catch{return null}}var Ye={openai:{id:"openai",name:"OpenAI",defaultApiKeyEnvVar:"OPENAI_API_KEY",defaultModel:"gpt-4o-mini",modelsApiUrl:"https://api.openai.com/v1/models",apiKeyUrl:"https://platform.openai.com/api-keys",buildHeaders:e=>({Authorization:`Bearer ${e}`}),parseModelsResponse:e=>e.data??[],modelFilters:[/^gpt-4/,/^gpt-3\.5/,/^o1/,/^o3/]},anthropic:{id:"anthropic",name:"Anthropic (Claude)",defaultApiKeyEnvVar:"ANTHROPIC_API_KEY",defaultModel:"claude-sonnet-4-20250514",modelsApiUrl:"https://api.anthropic.com/v1/models",apiKeyUrl:"https://console.anthropic.com/settings/keys",buildHeaders:e=>({"x-api-key":e,"anthropic-version":"2023-06-01"}),parseModelsResponse:e=>(e.data??[]).map(r=>({id:r.id,created:new Date(r.created_at).getTime()})),modelFilters:[/^claude-/]}};function Qn(){return Object.entries(Ye).map(([e,t])=>({name:t.name,value:e}))}function Xe(e){let t=Ye[e];if(!t)throw new Error(`Unknown AI provider: ${e}`);return t}var ue=(0,to.join)((0,eo.homedir)(),".platform-sdk-ai.json"),Ti=()=>{let e="anthropic",t=Ye[e];return{provider:e,model:t.defaultModel}},fr=Ti();function Qe(){return(0,Ce.existsSync)(ue)}function Pt(){if(!Qe())throw new Error("AI configuration not found. Please run 'pf ai:setup' to configure your AI provider.");try{let e=(0,Ce.readFileSync)(ue,"utf-8"),t=JSON.parse(e);return{...fr,...t}}catch{throw new Error(`Failed to load AI configuration from ${ue}. Please run 'pf setup --ai' again.`)}}function ro(e){let t=JSON.stringify(e,null,2);(0,Ce.writeFileSync)(ue,t,"utf-8")}async function no(e,t){await Xn(e,t)}async function oo(e){let t=await St(e.provider);if(t)return t;let r=Ye[e.provider],n=process.env[r.defaultApiKeyEnvVar];if(n)return n;throw new Error("API key not found. Please run 'pf setup --ai' to configure your API key.")}var Ei=async(e,t,r,n)=>{let{createOpenAI:o}=await import("@ai-sdk/openai"),s=o({apiKey:r});if(n.onToken){let{streamText:c}=await import("ai"),l=c({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature}),p="";for await(let d of(await l).textStream)p+=d,n.onToken(d);return p}let{generateText:a}=await import("ai"),{text:i}=await a({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature});return i},Ai=async(e,t,r,n)=>{let{createAnthropic:o}=await import("@ai-sdk/anthropic"),s=o({apiKey:r});if(n.onToken){let{streamText:c}=await import("ai"),l=c({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature}),p="";for await(let d of(await l).textStream)p+=d,n.onToken(d);return p}let{generateText:a}=await import("ai"),{text:i}=await a({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature});return i};async function so(e,t,r={}){let{system:n,maxTokens:o=4096,temperature:s=.7,onToken:a}=r,i=await oo(e);switch(e.provider){case"openai":return Ei(t,e.model,i,{system:n,maxTokens:o,temperature:s,onToken:a});case"anthropic":return Ai(t,e.model,i,{system:n,maxTokens:o,temperature:s,onToken:a});default:throw new Error(`Unsupported AI provider: ${e.provider}`)}}var te=require("node:fs"),Ae=require("node:path"),Uo=require("@inquirer/prompts"),h=u(require("chalk")),Jo=u(require("ora"));var hr=require("node:fs"),Et=require("node:path");var we=require("node:fs"),et=require("node:path"),Tt=u(require("chokidar"));var tt=".pf-generating",Ii=e=>(0,we.existsSync)((0,et.join)(e,tt)),$i=e=>{let t=(0,et.join)(e,tt);(0,we.existsSync)(t)&&(0,we.unlinkSync)(t)},Ni=e=>e?Object.values(e).filter(t=>typeof t=="object"&&t!==null&&t.watch===!0&&typeof t.path=="string").map(t=>t.path):["services","apps"],ao=(e,t)=>{$i(e);let r=ke(e),n=Ni(r?.pf?.paths),o=(0,et.join)(e,tt),s=()=>{Ii(e)||t()};Tt.default.watch(o,{ignoreInitial:!0}).on("unlink",()=>t());for(let a of n){let i=(0,et.join)(e,a);(0,we.existsSync)(i)&&(Tt.default.watch(i,{ignoreInitial:!0,depth:0}).on("addDir",s).on("unlinkDir",s),Tt.default.watch(`${i}/*/package.json`,{ignoreInitial:!0}).on("add",s).on("change",s).on("unlink",s))}};var rt=(e=__dirname)=>{let t=n=>(0,hr.existsSync)((0,Et.join)(n,"package.json")),r=(0,Et.dirname)(e);if(t(e))return e;if(e==="/")throw new Error("Could not find package.json (package root)");return rt(r)},io=(e,t)=>{let r=e.find(hr.existsSync);if(!r)throw new Error(t??`Directory not found. Searched in: ${e.join(", ")}`);return r};var Nt=require("node:fs"),ko=require("node:path"),vo=require("ts-morph");var N=require("node:fs"),be=require("node:path");var lo=e=>e.replace(/\./g,"-").toLowerCase(),co=e=>e.split(/[-.]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(""),
|
|
21
|
-
createdAt: z.string(),`:Object.entries(e).map(([t,r])=>` ${t}: ${
|
|
20
|
+
`),(0,Hn.execaSync)(a,[...i,e,...n],{cwd:o.cwd??(0,mr.cwd)(),stdio:"inherit",preferLocal:!0})}async function ee(e,t,r){let{args:n,mergedOptions:o}=Un(t??[],r),s=o.manager??w(),{command:a,args:i}=Gn(s);await ae(a,[...i,e,...n],o)}async function Ze(e,t){let{script:r,mergedOptions:n}=Ci(e,t),o=n.packageManager??w();await ae(o,["run",r,...n.args??[]],{cwd:n.cwd??(0,mr.cwd)(),task:n.task})}function Gn(e){let r={bun:"bunx",pnpm:"npx",yarn:"npx",npm:"npx"}[e];if(!r)throw new Error(`No executor found for the detected package manager: ${e}`);let[n,...o]=r.split(" ");return{command:n,args:o}}function xi(e,t){return Array.isArray(e)?{packages:e,mergedOptions:{...t,packages:e}}:{packages:e.packages??[],mergedOptions:e}}function Un(e,t){return Array.isArray(e)?{args:e,mergedOptions:t??{}}:{args:[],mergedOptions:e}}function Ci(e,t){return typeof e=="string"?{script:e,mergedOptions:t??{}}:{script:e.script,mergedOptions:e}}var wi=e=>e==="yarn"?["npm","audit"]:["audit"],zn=new Kn.Command("audit").description("Run security audit on dependencies").allowUnknownOption(!0).action((e,t)=>{let r=k(),n=w(),o=wi(n),s=t.args||[];console.log(Jn.default.dim(`Running ${n} ${[...o,...s].join(" ")}`)),wt(n,[...o,...s],{cwd:r})});var ce=require("@listr2/prompt-adapter-enquirer"),oe=u(require("chalk"));var Ce=require("node:fs"),eo=require("node:os"),to=require("node:path");var ie=require("node:crypto"),xe=require("node:fs"),de=require("node:os"),qn=require("node:path"),gr=(0,qn.join)((0,de.homedir)(),".platform-sdk-keys"),Vn="aes-256-gcm",Zn=()=>{let e=`${(0,de.hostname)()}:${(0,de.userInfo)().username}:${(0,de.homedir)()}`;return(0,ie.createHash)("sha256").update(e).digest()},Yn=()=>{if(!(0,xe.existsSync)(gr))return{};try{return JSON.parse((0,xe.readFileSync)(gr,"utf-8"))}catch{return{}}},bi=e=>{(0,xe.writeFileSync)(gr,JSON.stringify(e,null,2),{mode:384})},Si=e=>{let t=Zn(),r=(0,ie.randomBytes)(16),n=(0,ie.createCipheriv)(Vn,t,r),o=n.update(e,"utf8","hex");return o+=n.final("hex"),{iv:r.toString("hex"),tag:n.getAuthTag().toString("hex"),data:o}},Pi=e=>{let t=Zn(),r=Buffer.from(e.iv,"hex"),n=Buffer.from(e.tag,"hex"),o=(0,ie.createDecipheriv)(Vn,t,r);o.setAuthTag(n);let s=o.update(e.data,"hex","utf8");return s+=o.final("utf8"),s};async function Xn(e,t){let r=Yn();r[e]=Si(t),bi(r)}async function St(e){let r=Yn()[e];if(!r)return null;try{return Pi(r)}catch{return null}}var Ye={openai:{id:"openai",name:"OpenAI",defaultApiKeyEnvVar:"OPENAI_API_KEY",defaultModel:"gpt-4o-mini",modelsApiUrl:"https://api.openai.com/v1/models",apiKeyUrl:"https://platform.openai.com/api-keys",buildHeaders:e=>({Authorization:`Bearer ${e}`}),parseModelsResponse:e=>e.data??[],modelFilters:[/^gpt-4/,/^gpt-3\.5/,/^o1/,/^o3/]},anthropic:{id:"anthropic",name:"Anthropic (Claude)",defaultApiKeyEnvVar:"ANTHROPIC_API_KEY",defaultModel:"claude-sonnet-4-20250514",modelsApiUrl:"https://api.anthropic.com/v1/models",apiKeyUrl:"https://console.anthropic.com/settings/keys",buildHeaders:e=>({"x-api-key":e,"anthropic-version":"2023-06-01"}),parseModelsResponse:e=>(e.data??[]).map(r=>({id:r.id,created:new Date(r.created_at).getTime()})),modelFilters:[/^claude-/]}};function Qn(){return Object.entries(Ye).map(([e,t])=>({name:t.name,value:e}))}function Xe(e){let t=Ye[e];if(!t)throw new Error(`Unknown AI provider: ${e}`);return t}var ue=(0,to.join)((0,eo.homedir)(),".platform-sdk-ai.json"),Ti=()=>{let e="anthropic",t=Ye[e];return{provider:e,model:t.defaultModel}},fr=Ti();function Qe(){return(0,Ce.existsSync)(ue)}function Pt(){if(!Qe())throw new Error("AI configuration not found. Please run 'pf ai:setup' to configure your AI provider.");try{let e=(0,Ce.readFileSync)(ue,"utf-8"),t=JSON.parse(e);return{...fr,...t}}catch{throw new Error(`Failed to load AI configuration from ${ue}. Please run 'pf setup --ai' again.`)}}function ro(e){let t=JSON.stringify(e,null,2);(0,Ce.writeFileSync)(ue,t,"utf-8")}async function no(e,t){await Xn(e,t)}async function oo(e){let t=await St(e.provider);if(t)return t;let r=Ye[e.provider],n=process.env[r.defaultApiKeyEnvVar];if(n)return n;throw new Error("API key not found. Please run 'pf setup --ai' to configure your API key.")}var Ei=async(e,t,r,n)=>{let{createOpenAI:o}=await import("@ai-sdk/openai"),s=o({apiKey:r});if(n.onToken){let{streamText:c}=await import("ai"),l=c({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature}),p="";for await(let d of(await l).textStream)p+=d,n.onToken(d);return p}let{generateText:a}=await import("ai"),{text:i}=await a({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature});return i},Ai=async(e,t,r,n)=>{let{createAnthropic:o}=await import("@ai-sdk/anthropic"),s=o({apiKey:r});if(n.onToken){let{streamText:c}=await import("ai"),l=c({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature}),p="";for await(let d of(await l).textStream)p+=d,n.onToken(d);return p}let{generateText:a}=await import("ai"),{text:i}=await a({model:s(t),prompt:e,system:n.system,maxOutputTokens:n.maxTokens,temperature:n.temperature});return i};async function so(e,t,r={}){let{system:n,maxTokens:o=4096,temperature:s=.7,onToken:a}=r,i=await oo(e);switch(e.provider){case"openai":return Ei(t,e.model,i,{system:n,maxTokens:o,temperature:s,onToken:a});case"anthropic":return Ai(t,e.model,i,{system:n,maxTokens:o,temperature:s,onToken:a});default:throw new Error(`Unsupported AI provider: ${e.provider}`)}}var te=require("node:fs"),Ae=require("node:path"),Uo=require("@inquirer/prompts"),h=u(require("chalk")),Jo=u(require("ora"));var hr=require("node:fs"),Et=require("node:path");var we=require("node:fs"),et=require("node:path"),Tt=u(require("chokidar"));var tt=".pf-generating",Ii=e=>(0,we.existsSync)((0,et.join)(e,tt)),$i=e=>{let t=(0,et.join)(e,tt);(0,we.existsSync)(t)&&(0,we.unlinkSync)(t)},Ni=e=>e?Object.values(e).filter(t=>typeof t=="object"&&t!==null&&t.watch===!0&&typeof t.path=="string").map(t=>t.path):["services","apps"],ao=(e,t)=>{$i(e);let r=ke(e),n=Ni(r?.pf?.paths),o=(0,et.join)(e,tt),s=()=>{Ii(e)||t()};Tt.default.watch(o,{ignoreInitial:!0}).on("unlink",()=>t());for(let a of n){let i=(0,et.join)(e,a);(0,we.existsSync)(i)&&(Tt.default.watch(i,{ignoreInitial:!0,depth:0}).on("addDir",s).on("unlinkDir",s),Tt.default.watch(`${i}/*/package.json`,{ignoreInitial:!0}).on("add",s).on("change",s).on("unlink",s))}};var rt=(e=__dirname)=>{let t=n=>(0,hr.existsSync)((0,Et.join)(n,"package.json")),r=(0,Et.dirname)(e);if(t(e))return e;if(e==="/")throw new Error("Could not find package.json (package root)");return rt(r)},io=(e,t)=>{let r=e.find(hr.existsSync);if(!r)throw new Error(t??`Directory not found. Searched in: ${e.join(", ")}`);return r};var Nt=require("node:fs"),ko=require("node:path"),vo=require("ts-morph");var N=require("node:fs"),be=require("node:path");var lo=e=>e.replace(/\./g,"-").toLowerCase(),co=e=>e.split(/[-.]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(""),ji=e=>({string:"z.string()",number:"z.number()",boolean:"z.boolean()",date:"z.string().datetime()",array:"z.array(z.unknown())",object:"z.record(z.unknown())","string?":"z.string().optional()","number?":"z.number().optional()","boolean?":"z.boolean().optional()"})[e.toLowerCase()]||`z.${e}()`,Ri=e=>!e||Object.keys(e).length===0?` id: z.string(),
|
|
21
|
+
createdAt: z.string(),`:Object.entries(e).map(([t,r])=>` ${t}: ${ji(r)},`).join(`
|
|
22
22
|
`),yr=e=>e.endsWith("s")?e:e.endsWith("y")?`${e.slice(0,-1)}ies`:e.endsWith("ch")||e.endsWith("sh")?`${e}es`:`${e}s`,L=e=>{let t=lo(e),r=co(e),n=e.split(".")[0],o=e.split(".").slice(1).join("-"),s=yr(n).toUpperCase(),a=yr(n).toLowerCase(),i=co(`${yr(n)}.${o}`);return{eventName:t,contractName:`${i}Contract`,schemaName:`${r}Schema`,typeName:`${r}Data`,streamName:s,domain:a,event:o}},kr=e=>{let t=nt(e);if((0,N.existsSync)(t))return!0;let{eventsPath:r}=C(),n=lo(e),o=(0,be.join)(r,`${n}.ts`);return(0,N.existsSync)(o)},vr=(e,t)=>{let{eventsPath:r}=C(),{contractName:n,schemaName:o,typeName:s,streamName:a,domain:i,event:c}=L(e),l=`import { createContract } from '@crossdelta/cloudevents'
|
|
23
23
|
import { z } from 'zod'
|
|
24
24
|
|
|
25
25
|
export const ${o} = z.object({
|
|
26
|
-
${
|
|
26
|
+
${Ri(t)}
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
export const ${n} = createContract({
|
|
@@ -76,10 +76,10 @@ export default handleEvent(${n}, async (data: ${o}) => {
|
|
|
76
76
|
`);if(o.some(a=>a.trim()===r))return!1;let s=o.findLastIndex(a=>a.startsWith("export"));return s>=0?o.splice(s+1,0,r):o.push(r),(0,x.writeFileSync)(e,o.join(`
|
|
77
77
|
`),"utf-8"),!0},Wi=e=>{if(!(0,x.existsSync)(e))return!1;let t=(0,x.readFileSync)(e,"utf-8"),r=t;return r=r.replace(/\/\/ export \* from '\.\/events'/,"export * from './events'"),r=r.replace(/\/\/ export \* from '\.\/stream-policies'/,"export * from './stream-policies'"),r!==t?((0,x.writeFileSync)(e,r,"utf-8"),!0):!1},Ar=e=>{let{packagePath:t}=C(),{domain:r,event:n}=L(e),o=(0,J.join)(t,"src","events"),s=(0,J.join)(o,r),a=(0,J.join)(s,"index.ts"),i=(0,J.join)(o,"index.ts"),c=(0,J.join)(t,"src","index.ts"),l=e.split(".")[0],p=(0,J.join)(o,l);l!==r&&(0,x.existsSync)(p)&&(console.warn(`\u26A0\uFE0F Warning: Legacy folder '${l}/' found. Please migrate to '${r}/' to avoid conflicts.`),console.warn(` Run: mv ${p} ${s}`));let d=!1;return Hi(a,n)&&(d=!0),Li(i,r)&&(d=!0),Wi(c)&&(d=!0),d},Ir=(e,t)=>{if(!(0,x.existsSync)(e))return!1;let r=`export * from './events/${t}'`,n=(0,x.readFileSync)(e,"utf-8");if(n.includes(`'./events/${t}'`))return!1;let o=n.split(`
|
|
78
78
|
`),s=o.findLastIndex(a=>a.startsWith("export"));return s>=0?o.splice(s+1,0,r):o.push("",r),(0,x.writeFileSync)(e,o.join(`
|
|
79
|
-
`),"utf-8"),!0};var b=require("node:fs"),K=require("node:path"),f=require("@faker-js/faker");var uo=[{pattern:"email",generate:()=>f.faker.internet.email(),hint:"email"},{pattern:"id",generate:()=>f.faker.string.uuid(),hint:"uuid"},{pattern:"firstname",generate:()=>f.faker.person.firstName(),hint:"firstName"},{pattern:"lastname",generate:()=>f.faker.person.lastName(),hint:"lastName"},{pattern:"name",generate:()=>f.faker.person.fullName(),hint:"fullName"},{pattern:"phone",generate:()=>f.faker.phone.number(),hint:"phoneNumber"},{pattern:"address",generate:()=>f.faker.location.streetAddress(),hint:"streetAddress"},{pattern:"street",generate:()=>f.faker.location.streetAddress(),hint:"streetAddress"},{pattern:"city",generate:()=>f.faker.location.city(),hint:"city"},{pattern:"country",generate:()=>f.faker.location.country(),hint:"country"},{pattern:"price",generate:()=>f.faker.number.float({min:10,max:1e3,fractionDigits:2}),hint:"price"},{pattern:"amount",generate:()=>f.faker.number.float({min:10,max:1e3,fractionDigits:2}),hint:"price"},{pattern:"total",generate:()=>f.faker.number.float({min:10,max:1e3,fractionDigits:2}),hint:"price"},{pattern:"quantity",generate:()=>f.faker.number.int({min:1,max:10}),hint:"quantity"},{pattern:"date",generate:()=>f.faker.date.recent().toISOString(),hint:"date"},{pattern:"createdat",generate:()=>f.faker.date.recent().toISOString(),hint:"date"},{pattern:"updatedat",generate:()=>f.faker.date.recent().toISOString(),hint:"date"}],go=e=>({email:()=>f.faker.internet.email(),datetime:()=>f.faker.date.recent().toISOString(),url:()=>f.faker.internet.url(),uuid:()=>f.faker.string.uuid(),date:()=>f.faker.date.recent().toISOString().split("T")[0],time:()=>f.faker.date.recent().toISOString().split("T")[1]?.split(".")[0]})[e]?.()??f.faker.lorem.word(),fo=e=>{let t=e.toLowerCase(),r=uo.find(n=>t.includes(n.pattern));return r?{value:r.generate(),hint:r.hint}:null},_i=(e,t)=>{if(e.format)return go(e.format);let r=fo(t);if(r)return r.value;switch(e.type){case"string":return f.faker.lorem.word();case"number":return f.faker.number.int({min:1,max:100});case"boolean":return f.faker.datatype.boolean();case"array":return e.element?[$r(e.element)]:[];case"object":return $r(e);default:return null}},$r=e=>{let t={},r=e.shape??(typeof e.def?.shape=="function"?e.def.shape():void 0);if(!r)return t;for(let[n,o]of Object.entries(r))t[n]=_i(o,n);return t},Gi=async e=>{try{let{createJiti:t}=await import("jiti"),n=t(process.cwd(),{interopDefault:!0})(e),o=Object.entries(n).find(([s])=>s.endsWith("Schema")||s==="schema");if(o?.[1]){let s=o[1],a=$r(s);if(a&&typeof a=="object"&&Object.keys(a).length>0){let i={};return Nr(a,i,""),{data:a,faker:i}}}}catch{}return null},Nr=(e,t,r)=>{if(!(!e||typeof e!="object"))for(let[n,o]of Object.entries(e)){let s=r?`${r}.${n}`:n,a=n.toLowerCase(),i=uo.find(c=>a.includes(c.pattern));i&&(i.hint!=="uuid"||typeof o=="string")&&(t[s]=i.hint),typeof o=="object"&&o!==null&&!Array.isArray(o)?Nr(o,t,s):Array.isArray(o)&&o.length>0&&typeof o[0]=="object"&&Nr(o[0],t,`${s}[0]`)}},Ui=e=>({string:()=>f.faker.lorem.word(),number:()=>f.faker.number.int({min:1,max:100}),boolean:()=>f.faker.datatype.boolean()})[e]?.(),Ji=(e,t,r)=>{let n=/(\w+):\s*z\.(\w+)\(/g,o=Array.from(e.matchAll(n));for(let[,s,a]of o){if(a==="array"||a==="object")continue;let i=fo(s);if(i)t[s]=i.value,i.hint&&(r[s]=i.hint);else{let c=Ui(a);c!==void 0&&(t[s]=c)}}},Ki=(e,t,r)=>{let n=/(\w+):\s*z\.string\(\)\.(datetime|email|url|uuid)\(\)/g,o=Array.from(e.matchAll(n));for(let[,s,a]of o)t[s]=go(a),r[s]=a==="datetime"?"date":a},ho=e=>{let t={},r={};return Ji(e,t,r),Ki(e,t,r),{data:t,faker:r}},$t=async e=>{let{eventsPath:t}=C(),r=nt(e);if(!(0,b.existsSync)(r))return null;let o=(0,b.readFileSync)(r,"utf-8").match(/type:\s*['"]([^'"]+)['"]/),s=o?o[1]:e,a=await Gi(r);if(!a){let v=xr(e);v&&(a=ho(v))}if(!a)return null;let i={eventName:s,description:`Mock data for ${s} event`,data:a.data};Object.keys(a.faker).length>0&&(i.faker=a.faker);let{domain:c,event:l}=L(e),p=(0,K.join)(t,c,`${l}.mock.json`),d=(0,K.join)(t,c);return(0,b.existsSync)(d)||(0,b.mkdirSync)(d,{recursive:!0}),(0,b.writeFileSync)(p,JSON.stringify(i,null,2),"utf-8"),p};var yo=e=>{let t=e.match(/import\s+\{[^}]*?(\w+Contract)[^}]*?\}\s+from\s+['"][^'"]+\/contracts['"]/);return t?t[1].replace("Contract","").replace(/([A-Z])/g,(n,o,s)=>(s>0?".":"")+o.toLowerCase()):null},zi=(e,t,r)=>{if(!(0,b.existsSync)(e))return!1;let n=(0,b.readFileSync)(e,"utf-8"),o=n.match(/export const \w+(?:Schema|Data)\s*=\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m)??n.match(/schema:\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m);if(!o)return!1;let s=ho(o[1]),a={eventName:r,description:`Mock data for ${r} event`,data:s.data};return Object.keys(s.faker).length>0&&(a.faker=s.faker),(0,b.writeFileSync)(t,JSON.stringify(a,null,2)),!0},
|
|
79
|
+
`),"utf-8"),!0};var b=require("node:fs"),K=require("node:path"),f=require("@faker-js/faker");var uo=[{pattern:"email",generate:()=>f.faker.internet.email(),hint:"email"},{pattern:"id",generate:()=>f.faker.string.uuid(),hint:"uuid"},{pattern:"firstname",generate:()=>f.faker.person.firstName(),hint:"firstName"},{pattern:"lastname",generate:()=>f.faker.person.lastName(),hint:"lastName"},{pattern:"name",generate:()=>f.faker.person.fullName(),hint:"fullName"},{pattern:"phone",generate:()=>f.faker.phone.number(),hint:"phoneNumber"},{pattern:"address",generate:()=>f.faker.location.streetAddress(),hint:"streetAddress"},{pattern:"street",generate:()=>f.faker.location.streetAddress(),hint:"streetAddress"},{pattern:"city",generate:()=>f.faker.location.city(),hint:"city"},{pattern:"country",generate:()=>f.faker.location.country(),hint:"country"},{pattern:"price",generate:()=>f.faker.number.float({min:10,max:1e3,fractionDigits:2}),hint:"price"},{pattern:"amount",generate:()=>f.faker.number.float({min:10,max:1e3,fractionDigits:2}),hint:"price"},{pattern:"total",generate:()=>f.faker.number.float({min:10,max:1e3,fractionDigits:2}),hint:"price"},{pattern:"quantity",generate:()=>f.faker.number.int({min:1,max:10}),hint:"quantity"},{pattern:"date",generate:()=>f.faker.date.recent().toISOString(),hint:"date"},{pattern:"createdat",generate:()=>f.faker.date.recent().toISOString(),hint:"date"},{pattern:"updatedat",generate:()=>f.faker.date.recent().toISOString(),hint:"date"}],go=e=>({email:()=>f.faker.internet.email(),datetime:()=>f.faker.date.recent().toISOString(),url:()=>f.faker.internet.url(),uuid:()=>f.faker.string.uuid(),date:()=>f.faker.date.recent().toISOString().split("T")[0],time:()=>f.faker.date.recent().toISOString().split("T")[1]?.split(".")[0]})[e]?.()??f.faker.lorem.word(),fo=e=>{let t=e.toLowerCase(),r=uo.find(n=>t.includes(n.pattern));return r?{value:r.generate(),hint:r.hint}:null},_i=(e,t)=>{if(e.format)return go(e.format);let r=fo(t);if(r)return r.value;switch(e.type){case"string":return f.faker.lorem.word();case"number":return f.faker.number.int({min:1,max:100});case"boolean":return f.faker.datatype.boolean();case"array":return e.element?[$r(e.element)]:[];case"object":return $r(e);default:return null}},$r=e=>{let t={},r=e.shape??(typeof e.def?.shape=="function"?e.def.shape():void 0);if(!r)return t;for(let[n,o]of Object.entries(r))t[n]=_i(o,n);return t},Gi=async e=>{try{let{createJiti:t}=await import("jiti"),n=t(process.cwd(),{interopDefault:!0})(e),o=Object.entries(n).find(([s])=>s.endsWith("Schema")||s==="schema");if(o?.[1]){let s=o[1],a=$r(s);if(a&&typeof a=="object"&&Object.keys(a).length>0){let i={};return Nr(a,i,""),{data:a,faker:i}}}}catch{}return null},Nr=(e,t,r)=>{if(!(!e||typeof e!="object"))for(let[n,o]of Object.entries(e)){let s=r?`${r}.${n}`:n,a=n.toLowerCase(),i=uo.find(c=>a.includes(c.pattern));i&&(i.hint!=="uuid"||typeof o=="string")&&(t[s]=i.hint),typeof o=="object"&&o!==null&&!Array.isArray(o)?Nr(o,t,s):Array.isArray(o)&&o.length>0&&typeof o[0]=="object"&&Nr(o[0],t,`${s}[0]`)}},Ui=e=>({string:()=>f.faker.lorem.word(),number:()=>f.faker.number.int({min:1,max:100}),boolean:()=>f.faker.datatype.boolean()})[e]?.(),Ji=(e,t,r)=>{let n=/(\w+):\s*z\.(\w+)\(/g,o=Array.from(e.matchAll(n));for(let[,s,a]of o){if(a==="array"||a==="object")continue;let i=fo(s);if(i)t[s]=i.value,i.hint&&(r[s]=i.hint);else{let c=Ui(a);c!==void 0&&(t[s]=c)}}},Ki=(e,t,r)=>{let n=/(\w+):\s*z\.string\(\)\.(datetime|email|url|uuid)\(\)/g,o=Array.from(e.matchAll(n));for(let[,s,a]of o)t[s]=go(a),r[s]=a==="datetime"?"date":a},ho=e=>{let t={},r={};return Ji(e,t,r),Ki(e,t,r),{data:t,faker:r}},$t=async e=>{let{eventsPath:t}=C(),r=nt(e);if(!(0,b.existsSync)(r))return null;let o=(0,b.readFileSync)(r,"utf-8").match(/type:\s*['"]([^'"]+)['"]/),s=o?o[1]:e,a=await Gi(r);if(!a){let v=xr(e);v&&(a=ho(v))}if(!a)return null;let i={eventName:s,description:`Mock data for ${s} event`,data:a.data};Object.keys(a.faker).length>0&&(i.faker=a.faker);let{domain:c,event:l}=L(e),p=(0,K.join)(t,c,`${l}.mock.json`),d=(0,K.join)(t,c);return(0,b.existsSync)(d)||(0,b.mkdirSync)(d,{recursive:!0}),(0,b.writeFileSync)(p,JSON.stringify(i,null,2),"utf-8"),p};var yo=e=>{let t=e.match(/import\s+\{[^}]*?(\w+Contract)[^}]*?\}\s+from\s+['"][^'"]+\/contracts['"]/);return t?t[1].replace("Contract","").replace(/([A-Z])/g,(n,o,s)=>(s>0?".":"")+o.toLowerCase()):null},zi=(e,t,r)=>{if(!(0,b.existsSync)(e))return!1;let n=(0,b.readFileSync)(e,"utf-8"),o=n.match(/export const \w+(?:Schema|Data)\s*=\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m)??n.match(/schema:\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m);if(!o)return!1;let s=ho(o[1]),a={eventName:r,description:`Mock data for ${r} event`,data:s.data};return Object.keys(s.faker).length>0&&(a.faker=s.faker),(0,b.writeFileSync)(t,JSON.stringify(a,null,2)),!0},jr=async(e,t={})=>{let r=(0,K.join)(e,"src","events");if(!(0,b.existsSync)(r))return{mockPaths:[],skippedHandlers:[]};let n=(0,b.readdirSync)(r).filter(a=>a.endsWith(".event.ts")).map(a=>(0,K.join)(r,a)),o=[],s=[];for(let a of n){let i=(0,b.readFileSync)(a,"utf-8"),c=yo(i);if(!c){s.push(`${(0,K.basename)(a)} (Handler does not use contracts)`);continue}let{eventName:l}=L(c),p=t.outputDir??C().eventsPath,d=(0,K.join)(p,`${l}.mock.json`);if((0,b.existsSync)(d)&&!t.overwrite){s.push(`${(0,K.basename)(a)} (Mock already exists)`);continue}if(t.outputDir){let $=(0,K.join)(t.outputDir,`${l}.ts`);zi($,d,c)&&o.push(d);continue}let v=await $t(c);v&&o.push(v)}return{mockPaths:o,skippedHandlers:s}};var xo=e=>{let t=e.split("/").pop()||"service",r=(0,ko.join)(e,"src","events","events.service.ts");if(!(0,Nt.existsSync)(r))return!1;let n=Pr(e);if(n.length===0||(0,Nt.readFileSync)(r,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").includes("consumeJetStreams"))return!1;let i=Tr(n),c=Er(i,t);if(!c)return!1;let l=new vo.Project({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0}),p=l.addSourceFileAtPath(r),d=!1;for(let v of p.getClasses()){let $=v.getMethod("startConsumers");if(!$)continue;let F=[...c.split(`
|
|
80
80
|
`),""," this.logger.log('Event consumers started successfully')"].join(`
|
|
81
|
-
`);$.setBodyText(F),d=!0;break}return d&&l.saveSync(),d};var qi=e=>{let t=e.split(/\s+/),r=t[0],n=t.slice(1);return r==="pf"&&(r=process.argv[1]),{executable:r,args:n}},Vi=async(e,t)=>{try{let{executable:r,args:n}=qi(e.command);return await ae(r,n,{cwd:t,shell:!1}),{command:e.command,success:!0}}catch(r){return{command:e.command,success:!1,error:r instanceof Error?r.message:String(r)}}},
|
|
82
|
-
`));for(let r of e)console.log(z.default.dim(` ${t}/contracts \u2192 ${r}`));console.log()}},rc=(e,t)=>{let r=/^packages\/contracts\/src\/events\/([^/]+)\.ts$/,n=(0,
|
|
81
|
+
`);$.setBodyText(F),d=!0;break}return d&&l.saveSync(),d};var qi=e=>{let t=e.split(/\s+/),r=t[0],n=t.slice(1);return r==="pf"&&(r=process.argv[1]),{executable:r,args:n}},Vi=async(e,t)=>{try{let{executable:r,args:n}=qi(e.command);return await ae(r,n,{cwd:t,shell:!1}),{command:e.command,success:!0}}catch(r){return{command:e.command,success:!1,error:r instanceof Error?r.message:String(r)}}},Rr=async(e,t)=>{let r=[];for(let n of e){let o=await Vi(n,t);if(r.push(o),!o.success)break}return r},Mr=e=>{let t=[/^pf\s+/,/^bun\s+pf\s+/,/^npx\s+pf\s+/,/^bunx\s+pf\s+/];return e.filter(r=>t.some(n=>n.test(r.command)))},Co=e=>{for(let t of e){let r=t.command.match(/(?:bun\s+)?pf\s+new\s+\S+\s+(\S+)/);if(r)return r[1]}return null};var ot=require("node:fs"),Rt=require("node:path"),z=u(require("chalk"));var ge=require("node:fs"),jt=require("node:path"),Zi=(e,t)=>{let n=e.path.startsWith("packages/")&&t.workspaceRoot?t.workspaceRoot:t.baseDir,o=(0,jt.join)(n,e.path);try{if((0,ge.existsSync)(o)&&!t.overwrite)return{status:"skipped",path:e.path};if(t.dryRun)return{status:"written",path:e.path};let s=(0,jt.dirname)(o);return(0,ge.existsSync)(s)||(0,ge.mkdirSync)(s,{recursive:!0}),(0,ge.writeFileSync)(o,e.content,"utf-8"),{status:"written",path:e.path}}catch(s){return{status:"failed",path:e.path,error:s.message}}},wo=(e,t)=>{let r=e.map(n=>Zi(n,t));return{written:r.filter(n=>n.status==="written").map(n=>n.path),skipped:r.filter(n=>n.status==="skipped").map(n=>n.path),failed:r.filter(n=>n.status==="failed").map(n=>({path:n.path,error:n.error}))}};var Yi=(e,t)=>{let r=B(t.workspaceRoot),n=(0,Rt.join)(t.workspaceRoot,r.contracts);if(!(0,ot.existsSync)(n))return[];let o=/import\s+(?:type\s+)?{([^}]+)}\s+from\s+['"]@\w+\/contracts['"]/g,s=new Set;for(let a of e){let i=a.content.matchAll(o);for(let c of i){let p=c[1].split(",").map(d=>d.trim()).map(d=>d.replace(/^type\s+/,"").replace(/\s+as\s+.+$/,"").trim()).filter(d=>d.endsWith("Contract"));for(let d of p)s.add(d)}}return Array.from(s).sort()},Xi=e=>{let t=(0,Rt.join)(e,"packages/contracts/src/index.ts");if(!(0,ot.existsSync)(t))return new Set;try{let r=(0,ot.readFileSync)(t,"utf-8"),n=new Set,o=/export\s+(?:\*|{[^}]*Contract[^}]*})\s+from\s+['"]\.\/events\/([^'"]+)['"]/g,s=r.matchAll(o);for(let a of s){let i=a[0],c=/(\w+Contract)/g,l=i.matchAll(c);for(let p of l)n.add(p[1])}return n}catch{return new Set}},Qi=e=>{let t=e.replace(/Contract$/,""),r=t.split(/(?=[A-Z])/).filter(Boolean);if(r.length<2)return t.toLowerCase();let n=r[0].toLowerCase(),o=r.slice(1).join("").toLowerCase();return`${n}.${o}`},ec=(e,t,r)=>{let n=Xi(t),o=[],s=[],a=[];for(let i of e)if(n.has(i))o.push(i);else{s.push(i);let c=Qi(i),l=r.replace(`${t}/`,"");a.push(`pf event add ${c} --service ${l}`)}return{existing:o,missing:s,suggestedCommands:a}},tc=(e,t)=>{if(e.length!==0){console.log(z.default.cyan(`\u{1F4E6} Using existing contracts:
|
|
82
|
+
`));for(let r of e)console.log(z.default.dim(` ${t}/contracts \u2192 ${r}`));console.log()}},rc=(e,t)=>{let r=/^packages\/contracts\/src\/events\/([^/]+)\.ts$/,n=(0,Rt.join)(t,"packages/contracts/src/index.ts");for(let o of e){let s=o.match(r);s&&s[1]!=="index"&&Ir(n,s[1])}},bo=async(e,t)=>{t.start("Applying code formatting...");try{await ee("biome",["check","--fix","--unsafe","."],{cwd:e,quiet:!0}),t.succeed("Code formatted!")}catch{t.warn("Code formatting completed with warnings")}},nc=async(e,t)=>{t.start("Scanning for event handlers...");let{mockPaths:r,skippedHandlers:n}=await jr(e);if(r.length+n.length===0){t.info("No event handlers found");return}if(r.length>0){t.succeed(`Generated ${r.length} event ${r.length===1?"mock":"mocks"}`),console.log();for(let s of r){let a=s.replace(`${e}/`,"");console.log(z.default.dim(` ${a}`))}console.log()}else t.succeed("Event handlers found");if(n.length>0){for(let s of n)console.log(z.default.dim(` \u2139 Skipped: ${s}`));console.log()}},So=async(e,t,r,n)=>{n.start("Writing generated files...");let o=wo(e,{baseDir:t,workspaceRoot:r.workspaceRoot,overwrite:!0});if(o.written.length>0){n.succeed(`Created ${o.written.length} files`),console.log();for(let l of o.written)console.log(z.default.dim(` ${l}`));console.log()}else n.succeed("No files to write");let s=Yi(e,r),{existing:a,missing:i,suggestedCommands:c}=ec(s,r.workspaceRoot,t);if(a.length>0&&tc(a,r.scope),i.length>0){console.log(z.default.yellow(`\u26A0\uFE0F Missing contracts (not exported from @${r.scope}/contracts):
|
|
83
83
|
`));for(let l of i)console.log(z.default.yellow(` ${l}`));console.log(),console.log(z.default.cyan(`\u{1F4A1} Run these commands to create the missing contracts:
|
|
84
84
|
`));for(let l of c)console.log(z.default.dim(` ${l}`));console.log()}return rc(o.written,r.workspaceRoot),o.written.length>0&&await nc(t,n),{missingContractCommands:c}};var Mt=require("node:fs"),Te=require("node:path");var Pe=require("node:fs"),Po=require("node:path");var To=e=>{let{eventsPath:t}=C(e);if(!(0,Pe.existsSync)(t))return[];let r=[];try{let n=(0,Pe.readdirSync)(t).filter(o=>o.endsWith(".ts")&&!o.endsWith(".mock.json")&&o!=="index.ts");for(let o of n){let s=(0,Po.join)(t,o),a=(0,Pe.readFileSync)(s,"utf-8"),i=oc(a,s);i&&r.push(i)}}catch(n){return console.warn("Warning: Could not scan contracts package:",n),[]}return r},oc=(e,t)=>{try{let r=e.match(/export const (\w+Contract) = createContract/);if(!r)return null;let n=r[1],o=e.match(/export type (\w+(?:Data|Event)) = z\.infer/);if(!o)return null;let s=o[1],a=e.match(/type:\s*['"]([^'"]+)['"]/);if(!a)return null;let i=a[1],c=ac(e);return{name:n,typeName:s,eventType:i,fields:c,filePath:t}}catch{return null}},sc={string:"string",number:"number",boolean:"boolean",array:"array",object:"object",date:"date"},ac=e=>{let t=e.match(/z\.object\({([^}]+)\}/);if(!t)return[];let r=t[1],n=/(\w+):\s*z\.(\w+)\([^)]*\)/g,o=[...r.matchAll(n)].map(([,i,c])=>{let l=sc[c]||c;return`${i}: ${l}`});if(!e.includes("z.array("))return o;let s=/(\w+):\s*z\.array\(/g,a=[...e.matchAll(s)].map(([,i])=>i).filter(i=>!o.some(c=>c.startsWith(i))).map(i=>`${i}: array`);return[...o,...a]},Eo=(e,t)=>{if(e.length===0)return`
|
|
85
85
|
**Available Contracts:**
|
|
@@ -130,7 +130,7 @@ Format your code blocks with the file path on the line before the code block:
|
|
|
130
130
|
|
|
131
131
|
Follow these project-specific conventions and patterns when generating code:
|
|
132
132
|
|
|
133
|
-
${n}`},
|
|
133
|
+
${n}`},jo=(e,t,r,n)=>{let o=hc(e),s=`${fc(o)}_PORT`,a=ve();return`Generate source code for a microservice at path "${e}".
|
|
134
134
|
|
|
135
135
|
Use the patterns and conventions from the Project Guidelines above.
|
|
136
136
|
|
|
@@ -145,21 +145,21 @@ Service purpose: ${t}
|
|
|
145
145
|
- BUT you MUST keep the existing port configuration line unchanged!
|
|
146
146
|
|
|
147
147
|
Do NOT include the service path in file headers (use \`src/...\`, NOT \`${e}/src/...\`).
|
|
148
|
-
`};var yc=()=>!1,
|
|
148
|
+
`};var yc=()=>!1,Ro=(e,t)=>{yc()&&console.log(`[AI Parser] ${e}`,t??"")},Ft={commandsBlock:/```commands\n([\s\S]*?)```/gi,postCommandsBlock:/```post-commands\n([\s\S]*?)```/gi,dependenciesBlock:/```dependencies\n([\s\S]*?)```/gi,fileHeader:/^#{1,4}\s+`([^`]+)`\s*$/},Or=(e,t)=>[...e.matchAll(t)].flatMap(n=>n[1].split(`
|
|
149
149
|
`).map(o=>o.trim()).filter(o=>o.length>0&&!o.startsWith("#"))),Mo=e=>({command:e,isPfCommand:e.startsWith("pf ")||e.includes(" pf ")}),kc=e=>Or(e,Ft.commandsBlock).map(Mo),vc=e=>Or(e,Ft.postCommandsBlock).map(Mo),xc=e=>Or(e,Ft.dependenciesBlock).filter(t=>!t.startsWith("@crossdelta/")&&t!=="zod"),Cc=e=>{let t={ts:"typescript",js:"javascript",md:"markdown",yml:"yaml"},r=(e||"typescript").toLowerCase();return t[r]||r},wc=e=>{let t=e.split(".").pop()?.toLowerCase();return{ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",json:"json",yaml:"yaml",yml:"yaml",md:"markdown"}[t||""]||"plaintext"},bc=e=>e.replace(/^\s*\/\/ \.{3,}.*$/gm,"").replace(/^\s*\/\/ Lines? \d+.*omitted.*$/gim,"").replace(/^\s*\/\* Lines? \d+.*omitted.*\*\/$/gim,"").trim(),Sc=e=>{let t=e.split(`
|
|
150
|
-
`),r=[],n=0;for(let o of t){let s=Ft.fileHeader.exec(o);s&&r.push({path:s[1],index:n}),n+=o.length+1}return r},Pc=(e,t)=>{let n=e.slice(t).match(/```(\w+)?\n([\s\S]*?)```/);return n?{language:n[1]?Cc(n[1]):void 0,content:bc(n[2])}:null},Tc=e=>Sc(e).map(r=>{let n=Pc(e,r.index);return!n||n.content.length===0?null:{path:r.path,language:n.language||wc(r.path),content:n.content,startIndex:r.index}}).filter(r=>r!==null),Fr=e=>e.includes("packages/contracts")||e.includes("contracts/src"),Ec=e=>{let t=e.filter(n=>Fr(n.path)),r=e.filter(n=>!Fr(n.path));return[...t,...r]},Ac=e=>{let t=e.replace(/^\/+/,"").replace(/\/{2,}/g,"/");if(Fr(t))return t;let r=t.match(/^services\/[^/]+\/(.+)$/);return r?r[1]:t},Fo=(e,t)=>{
|
|
151
|
-
`));return}let o=(await
|
|
150
|
+
`),r=[],n=0;for(let o of t){let s=Ft.fileHeader.exec(o);s&&r.push({path:s[1],index:n}),n+=o.length+1}return r},Pc=(e,t)=>{let n=e.slice(t).match(/```(\w+)?\n([\s\S]*?)```/);return n?{language:n[1]?Cc(n[1]):void 0,content:bc(n[2])}:null},Tc=e=>Sc(e).map(r=>{let n=Pc(e,r.index);return!n||n.content.length===0?null:{path:r.path,language:n.language||wc(r.path),content:n.content,startIndex:r.index}}).filter(r=>r!==null),Fr=e=>e.includes("packages/contracts")||e.includes("contracts/src"),Ec=e=>{let t=e.filter(n=>Fr(n.path)),r=e.filter(n=>!Fr(n.path));return[...t,...r]},Ac=e=>{let t=e.replace(/^\/+/,"").replace(/\/{2,}/g,"/");if(Fr(t))return t;let r=t.match(/^services\/[^/]+\/(.+)$/);return r?r[1]:t},Fo=(e,t)=>{Ro("Parsing AI response",{length:e.length});let r=kc(e),n=vc(e),o=xc(e),s=Tc(e),a=Ec(s.map(i=>({path:Ac(i.path),content:i.content,language:i.language})));return Ro("Parsed response",{commands:r.length,postCommands:n.length,dependencies:o.length,files:a.length}),{commands:r,files:a,dependencies:o,postCommands:n}},Oo=e=>{let t=e.filter(s=>!s.content||s.content.trim().length===0),r=e.length===0?["No files could be extracted from the AI response"]:t.map(s=>`File ${s.path} is empty`),n=e.some(s=>["src/index.ts","src/main.ts","index.ts"].includes(s.path)),o=e.length>0&&!n?["No entry point file (src/index.ts or src/main.ts) found - assuming it exists from scaffolding"]:[];return{valid:r.length===0,errors:r,warnings:o}};var Do=require("node:fs"),W=u(require("chalk"));var Bo=async(e,t,r)=>{if(e.length===0){(0,Do.mkdirSync)(t,{recursive:!0}),console.log(W.default.yellow(`\u26A0 No scaffolding command found - creating empty directory
|
|
151
|
+
`));return}let o=(await Rr(e,r)).find(s=>!s.success);if(o)throw console.log(W.default.red(`
|
|
152
152
|
\u2717 Scaffolding failed: ${o.command}`)),o.error&&console.log(W.default.red(` Error: ${o.error}`)),new Error(`Command failed: ${o.command}${o.error?` - ${o.error}`:""}`)},Ho=async(e,t)=>{t.start("Linking workspace dependencies...");try{await H({cwd:e,quiet:!0}),t.succeed("Workspace dependencies linked")}catch{let r=w();t.warn(`Workspace sync skipped (run ${r} install manually)`)}},Lo=async(e,t,r)=>{if(e.length===0)return;r.stop();let n=e.length===1?"package":"packages";console.log(W.default.cyan(`
|
|
153
153
|
\u25B6 Installing ${e.length} additional ${n}...
|
|
154
154
|
`));try{await H({packages:e,cwd:t,flags:["--silent"]}),console.log(W.default.green(`\u2713 Installed ${e.length} ${n}
|
|
155
155
|
`))}catch(o){throw console.log(W.default.red(`\u2717 Package installation failed
|
|
156
156
|
`)),o}},Dr=async(e,t)=>{if(e.length===0)return;console.log(W.default.cyan(`
|
|
157
157
|
\u25B6 Running post-generation commands...
|
|
158
|
-
`));let n=(await
|
|
158
|
+
`));let n=(await Rr(e,t)).find(o=>!o.success);if(n){console.log(W.default.yellow(`
|
|
159
159
|
\u26A0 Post-command failed: ${n.command}`)),n.error&&console.log(W.default.yellow(` Error: ${n.error}`));return}console.log(W.default.green(`\u2713 Post-generation commands complete
|
|
160
160
|
`))};var st=u(require("chalk")),Ic=e=>`${st.default.dim(" \u2022 ")+st.default.cyan(e)}
|
|
161
161
|
`,Wo=e=>st.default.dim(` \u2728 Generated ${st.default.white.bold(e)} tokens
|
|
162
|
-
`),_o=()=>{let e="",t=0,r=Date.now(),n=[],o=()=>{let a=e.match(/####\s+`([^`]+)`/);if(!a)return!1;n.push(a[1]),process.stdout.write(Ic(a[1]));let i=e.indexOf(a[0])+a[0].length;return e=e.slice(i),!0},s=a=>{e+=a,t++,o(),e.length>500&&(e=e.slice(-200))};return s.getStats=()=>{let a=((Date.now()-r)/1e3).toFixed(2),i=(t/Number.parseFloat(a)).toFixed(0);return{tokenCount:t,duration:a,tokensPerSec:i}},s.getFiles=()=>n,s};var $c=()=>{let e=k(),t=(0,Ae.join)(e,"package.json"),r=(()=>{if(!(0,te.existsSync)(t))throw new Error("No package.json found in workspace root. Run from a valid workspace.");try{let o=JSON.parse((0,te.readFileSync)(t,"utf-8")).name;if(!o)throw new Error('package.json has no "name" field. Please add a name to your root package.json.');return o.startsWith("@")?o:`@${o}`}catch(n){throw n instanceof SyntaxError?new Error("Invalid JSON in package.json"):n}})();return{workspaceRoot:e,scope:r,cwd:process.cwd()}},Nc=async(e,t,r,n,o,s)=>{let a=
|
|
162
|
+
`),_o=()=>{let e="",t=0,r=Date.now(),n=[],o=()=>{let a=e.match(/####\s+`([^`]+)`/);if(!a)return!1;n.push(a[1]),process.stdout.write(Ic(a[1]));let i=e.indexOf(a[0])+a[0].length;return e=e.slice(i),!0},s=a=>{e+=a,t++,o(),e.length>500&&(e=e.slice(-200))};return s.getStats=()=>{let a=((Date.now()-r)/1e3).toFixed(2),i=(t/Number.parseFloat(a)).toFixed(0);return{tokenCount:t,duration:a,tokensPerSec:i}},s.getFiles=()=>n,s};var $c=()=>{let e=k(),t=(0,Ae.join)(e,"package.json"),r=(()=>{if(!(0,te.existsSync)(t))throw new Error("No package.json found in workspace root. Run from a valid workspace.");try{let o=JSON.parse((0,te.readFileSync)(t,"utf-8")).name;if(!o)throw new Error('package.json has no "name" field. Please add a name to your root package.json.');return o.startsWith("@")?o:`@${o}`}catch(n){throw n instanceof SyntaxError?new Error("Invalid JSON in package.json"):n}})();return{workspaceRoot:e,scope:r,cwd:process.cwd()}},Nc=async(e,t,r,n,o,s)=>{let a=jo(r,n,o,t.workspaceRoot),i=No(t,o,s),c=_o(),l=await so(e,a,{system:i,maxTokens:16384,temperature:.7,onToken:c}),p=c.getStats();return console.log(Wo(p.tokenCount)),console.log(),l},jc=(e,t)=>{let{serviceTypes:r}=Ve(),n=r[t]?.commandType;if(!n)return e;let o=Object.values(r).map(s=>s.commandType);return e.map(s=>{for(let a of o)if(a!==n&&s.command.includes(`pf new ${a}`))return{...s,command:s.command.replace(`pf new ${a}`,`pf new ${n}`)};return s})},Rc=e=>e.length===0?"":`${[h.default.cyan(`
|
|
163
163
|
\u{1F4C1} Files to create:`),...e.map(t=>` ${h.default.green("\u2022")} ${h.default.white(t.path)} ${h.default.dim(`(${t.language})`)}`)].join(`
|
|
164
164
|
`)}
|
|
165
165
|
`,Go=(e,t,r)=>e.length===0?"":`${[h.default.cyan(`
|
|
@@ -172,7 +172,7 @@ Do NOT include the service path in file headers (use \`src/...\`, NOT \`${e}/src
|
|
|
172
172
|
Validation errors:`),...e.map(r=>h.default.yellow(` \u26A0 ${r}`)),h.default.dim(`
|
|
173
173
|
Response preview:`),h.default.dim(t)].join(`
|
|
174
174
|
`)}
|
|
175
|
-
`,Ee=e=>{e&&process.stdout.write(e)},Oc=(e,t)=>{let r=Fo(e,t),n=Mr(r.commands),o=Mr(r.postCommands),s=Oo(r.files);return s.valid?{files:r.files,commands:n,dependencies:r.dependencies,postCommands:o}:(console.log(`${h.default.yellow("\u26A0")} Could not extract structured files from AI response`),Ee(Fc(s.errors,e.slice(0,500))),null)},Dc=e=>{console.log(`${h.default.green("\u2714")} Extracted ${e.files.length} files`),Ee(
|
|
175
|
+
`,Ee=e=>{e&&process.stdout.write(e)},Oc=(e,t)=>{let r=Fo(e,t),n=Mr(r.commands),o=Mr(r.postCommands),s=Oo(r.files);return s.valid?{files:r.files,commands:n,dependencies:r.dependencies,postCommands:o}:(console.log(`${h.default.yellow("\u26A0")} Could not extract structured files from AI response`),Ee(Fc(s.errors,e.slice(0,500))),null)},Dc=e=>{console.log(`${h.default.green("\u2714")} Extracted ${e.files.length} files`),Ee(Rc(e.files)),Ee(Go(e.commands,"Commands to run","\u{1F527}")),Ee(Go(e.postCommands,"Post-generation commands","\u{1F4DD}")),Ee(Mc(e.dependencies)),Ee(`
|
|
176
176
|
`)},Bc=(e,t,r)=>{let n=Co(e);return n&&!n.includes("/")&&!n.startsWith(".")&&(n=`${B().services}/${n}`),n?(0,Ae.resolve)(r,n):(0,Ae.resolve)(r,t)},Hc=(e,t)=>{let{serviceTypes:r}=Ve(),n=r[t]?.skipFiles||["package.json","tsconfig.json","Dockerfile"];return e.filter(o=>!n.includes(o.path))},Ie=()=>{if(!Qe())return{valid:!1,error:h.default.red.bold(`\u274C AI configuration not found.
|
|
177
177
|
`)+h.default.yellow("Please run ")+h.default.cyan.bold("pf setup --ai")+h.default.yellow(` first to configure your AI provider.
|
|
178
178
|
`)};try{return{valid:!0,config:Pt()}}catch(e){return{valid:!1,error:h.default.red.bold(`\u274C ${e.message}
|
|
@@ -181,7 +181,7 @@ Response preview:`),h.default.dim(t)].join(`
|
|
|
181
181
|
`)),console.log(h.default.dim(`Service: ${e.split("/").pop()}`)),console.log(h.default.dim(`Path: ${e}`)),console.log(h.default.dim(`Model: ${t.model}`)),console.log(h.default.dim(`Description: ${r}
|
|
182
182
|
`))},Bt=async(e,t)=>{let{servicePath:r,description:n="",serviceType:o,packageManager:s}=e,a=r.split("/").pop()||r,i=$c(),c=(0,Ae.join)(i.workspaceRoot,tt);(0,te.writeFileSync)(c,`generating:${r}`);let l=()=>{(0,te.existsSync)(c)&&(0,te.unlinkSync)(c)},p=()=>{l(),process.exit(130)};process.on("SIGINT",p),process.on("SIGTERM",p);try{console.log(h.default.cyan.bold(`
|
|
183
183
|
\u{1F916} AI Generation
|
|
184
|
-
`));let d=await Nc(t,i,r,n,o,s),v=Oc(d,a);if(!v)return!1;Dc(v);let $=(0,Jo.default)({text:"Processing files...",color:"cyan"}).start(),Je=
|
|
184
|
+
`));let d=await Nc(t,i,r,n,o,s),v=Oc(d,a);if(!v)return!1;Dc(v);let $=(0,Jo.default)({text:"Processing files...",color:"cyan"}).start(),Je=jc(v.commands,o),F=Bc(Je,r,i.cwd),ei=Hc(v.files,o);await Bo(Je,F,i.workspaceRoot);let{missingContractCommands:hn}=await So(ei,F,i,$);if(v.postCommands.length>0)await Dr(v.postCommands,i.workspaceRoot);else if(hn.length>0){console.log(h.default.cyan(`\u{1F527} Auto-creating missing contracts...
|
|
185
185
|
`));let ti=hn.map(ri=>({command:ri,isPfCommand:!0}));await Dr(ti,i.workspaceRoot)}return xo(F),await Lo(v.dependencies,F,$),await Ho(i.workspaceRoot,$),await bo(F,$),!0}finally{process.off("SIGINT",p),process.off("SIGTERM",p),l()}};var zo=require("node:fs"),at=require("ts-morph"),Ko=new at.Project({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0}),Br=e=>{if(!(0,zo.existsSync)(e))return null;let t=Ko.getSourceFile(e);return t||Ko.addSourceFileAtPath(e)},Hr=e=>{e.saveSync()},Lr=(e,t,r)=>{let n=e.getImportDeclaration(t);if(n){let o=n.getNamedImports().map(a=>a.getName()),s=r.filter(a=>!o.includes(a));for(let a of s)n.addNamedImport(a);return}e.addImportDeclaration({moduleSpecifier:t,namedImports:r})},Lc=e=>{for(let t of e.getClasses()){let r=t.getDecorator("Module");if(!r)continue;let n=r.getArguments();if(n.length===0)continue;let o=n[0];if(o.getKind()===at.SyntaxKind.ObjectLiteralExpression)return o}return null},Wr=(e,t)=>{let r=Lc(e);if(!r)return!1;let n=r.getProperty("imports");if(n){let o=n.getFirstChildByKind(at.SyntaxKind.ArrayLiteralExpression);return o?(o.getElements().map(a=>a.getText()).includes(t)||o.addElement(t),!0):!1}return r.addPropertyAssignment({name:"imports",initializer:`[${t}]`}),!0};var Ht=require("node:fs"),it=u(require("node:path")),_r=u(require("chalk"));var qo=async e=>{await ae("bash",["-c",`
|
|
186
186
|
curl -fsSL https://bun.sh/install | bash && if [ -f "$HOME/.bun/bin/bun" ]; then export PATH="$HOME/.bun/bin:$PATH"; fi
|
|
187
187
|
`],{task:e,shell:!0}),await Wc()},Gr=()=>qe("bun"),Vo=()=>sr([{label:"Bun",value:59026,color:"magenta",barColor:"magenta"},{label:"Deno",value:25335},{label:"Node.js",value:19039}],{title:'Express.js "hello world" HTTP requests per second (Linux x64)',barColor:"blackBright"}),Zo=()=>sr([{label:"Bun",value:.36,color:"magenta",barColor:"magenta"},{label:"pnpm",value:6.44},{label:"npm",value:10.58},{label:"yarn",value:12.08}],{title:"Bun is an npm-compatible package manager.",unit:"s",footer:_r.default.blackBright("* Installing dependencies from cache for a Remix app."),barColor:"blackBright"}),Wc=async()=>{let e='export PATH="$HOME/.bun/bin:$PATH"',t=process.env.HOME;if(!t){m.error("Could not detect $HOME environment variable. Cannot update shell config.");return}let r=[it.default.join(t,".zshrc"),it.default.join(t,".bashrc"),it.default.join(t,".bash_profile")];for(let n of r)try{if(await Ht.promises.stat(n).then(()=>!0).catch(()=>!1)){(await Ht.promises.readFile(n,"utf8")).includes(e)||(await Ht.promises.appendFile(n,`
|
|
@@ -192,7 +192,7 @@ ${e}
|
|
|
192
192
|
Check your integration.collection.json:
|
|
193
193
|
${e.message}`)}},$e=()=>_().reduce((t,r)=>(r.initial&&t.push(r.name),t),[]),rl=e=>!!e?.name&&!!e?.link&&!!e?.description,Wt=e=>{let t=_();if(!t?.length||!e?.length)return;let r=e.map(n=>t.find(o=>o.name===n)).filter(rl);r.length&&(m.breakLine().log("\u{1F50C} Installed Integrations:"),r.forEach(({name:n,link:o,description:s})=>{let a=m.getStoredLogs(`${Lt}:${n}`);o&&m.log(`${(0,ss.default)(q.default.cyan(n),o)} - ${s}`),a.length&&m.log(a.map(i=>` \u203A ${q.default.dim(i.message)}`).join(`
|
|
194
194
|
`))}))},nl=e=>e.toUpperCase().replace(/-/g,"_"),as=(e,t)=>{let r=nl(e);m.breakLine().log(q.default.bold("Environment variables:")).log(q.default.dim(" Local:")).log(q.default.cyan(` ${r}_PORT=${t}`)).log(q.default.cyan(` ${r}_URL=http://localhost:${t}`)).breakLine().log(q.default.dim(" Production (auto-configured):")).log(q.default.cyan(` ${r}_PORT=${t}`)).log(q.default.cyan(` ${r}_URL=http://${e}:${t}`))};var Jr=u(require("chalk"));var ol=e=>{let t=e.match(/^(@?[^@]+)@(.+)$/);return t?{name:t[1],version:t[2]}:{name:e,version:"latest"}},is=async e=>{let{selectedIntegrations:t,cwd:r,packageManager:n=w(),task:o}=e;if(!t?.length||!o)return;let s=sl(t,r,n,o);await xt(o,s)},sl=(e,t,r,n)=>{let s=_()?.filter(i=>e.includes(i.name))?.flatMap(i=>i.install.map(c=>{let{name:l,version:p}=ol(c);return{title:Jr.default.cyanBright(`Adding ${c} (${i.name})`),fn:async()=>{Q(`dependencies.${l}`,p,t)}}})),a={title:Jr.default.cyanBright("Installing packages..."),fn:async()=>{await H({cwd:t,packageManager:r,task:n})}};return[...s??[],a]};var cs=u(require("chalk"));var ls=async e=>{let{selectedIntegrations:t,cwd:r,task:n}=e;if(!t?.length||!n)return;let o=al(t,r,n,e.packageManager);await xt(n,o)},al=(e,t,r,n)=>_().filter(s=>e.includes(s.name)&&s.run?.length).flatMap(s=>(s.run||[]).map(a=>({title:cs.default.cyanBright(`Running "${a}" for ${s.name}
|
|
195
|
-
`),fn:()=>il(s,a,t,r,n)}))),il=async(e,t,r,n,o)=>{let s=`${Lt}:${e.name}`;try{if(e.interactive)return _n(t,[],{cwd:r,context:s,task:n,manager:o});await ee(t,[],{cwd:r,task:n,context:s})}catch(a){m.error(`Failed to run command "${t}" for ${e.name}: ${a.message}`)}};var _t=require("node:fs"),lt=require("node:path");var Gt=(e,t)=>{try{let r=(0,_t.readFileSync)(e,"utf-8"),n=JSON.parse(r);t(n),(0,_t.writeFileSync)(e,JSON.stringify(n,null,2),"utf-8")}catch{}},cl=e=>{let t=(0,lt.join)(g(e),"tsconfig.json");Gt(t,r=>{r.compilerOptions.module="ESNext",r.compilerOptions.moduleResolution="bundler",r.compilerOptions.resolvePackageJsonExports=!0,r.compilerOptions.types=r.compilerOptions.types||[],r.compilerOptions.types.includes("bun-types")||r.compilerOptions.types.push("bun-types"),r.exclude=["node_modules","dist"]})},ll=e=>{let t=(0,lt.join)(g(e),"tsconfig.build.json");Gt(t,r=>{r.exclude=["node_modules","test","dist","**/*.spec.ts","**/*.test.ts"]})},pl=e=>{let t=(0,lt.join)(g(e),"nest-cli.json");Gt(t,r=>{r.compilerOptions=r.compilerOptions||{},r.compilerOptions.tsConfigPath="tsconfig.build.json"})},ml=e=>{let t=(0,lt.join)(g(e),"package.json");Gt(t,r=>{delete r.jest})},ps=e=>{cl(e),ll(e),pl(e),ml(e)};var ms=require("node:path");var dl=(e,t)=>{let r=Br(e);if(r){for(let{className:n,importPath:o}of t)Lr(r,o,[n]),Wr(r,n);Hr(r)}},ds=e=>{let t=(0,ms.join)(g(e),"src","app.module.ts");dl(t,[{className:"EventsModule",importPath:"./events/events.module"}])};var ul=require("fs-extra");var fl=u(require("chalk")),hl=u(require("cli-table3"));var us=require("node:fs"),gs=require("node:path"),fs=u(require("handlebars"));var Ne=(e,t)=>io(e,t??`Templates directory not found. Searched in: ${e.join(", ")}`),Kr=(e,t={})=>{let r=(0,us.readFileSync)(e,"utf-8");return fs.default.compile(r)(t)},Ut=e=>(t,r={})=>{let n=(0,gs.join)(e,t);return Kr(n,r)};var pt=e=>e.toUpperCase().replace(/-/g,"_");var hs=e=>e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ");function Jt(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}async function ys(e,t,r={},n=[],o=[]){if(!e){console.error("Subcommand is not defined.");return}let s=n.map(l=>t[l]).filter(l=>l!==void 0),a=o.map(l=>{let p=t[l];if(!(p===!1||p===void 0))return p===!0?`--${Jt(String(l))}`:`--${Jt(String(l))}=${String(p)}`}).filter(l=>l!==void 0),i=Object.entries(r).map(([l,p])=>{if(!(p===!1||p===void 0))return p===!0?`--${Jt(l)}`:`--${Jt(l)}=${String(p)}`}).filter(l=>l!==void 0),c=[...s,...a,...i].map(String);await e.parseAsync(c,{from:"user"})}var Ls=require("node:path"),re=u(require("chalk"));var ks=require("@listr2/prompt-adapter-enquirer"),
|
|
195
|
+
`),fn:()=>il(s,a,t,r,n)}))),il=async(e,t,r,n,o)=>{let s=`${Lt}:${e.name}`;try{if(e.interactive)return _n(t,[],{cwd:r,context:s,task:n,manager:o});await ee(t,[],{cwd:r,task:n,context:s})}catch(a){m.error(`Failed to run command "${t}" for ${e.name}: ${a.message}`)}};var _t=require("node:fs"),lt=require("node:path");var Gt=(e,t)=>{try{let r=(0,_t.readFileSync)(e,"utf-8"),n=JSON.parse(r);t(n),(0,_t.writeFileSync)(e,JSON.stringify(n,null,2),"utf-8")}catch{}},cl=e=>{let t=(0,lt.join)(g(e),"tsconfig.json");Gt(t,r=>{r.compilerOptions.module="ESNext",r.compilerOptions.moduleResolution="bundler",r.compilerOptions.resolvePackageJsonExports=!0,r.compilerOptions.types=r.compilerOptions.types||[],r.compilerOptions.types.includes("bun-types")||r.compilerOptions.types.push("bun-types"),r.exclude=["node_modules","dist"]})},ll=e=>{let t=(0,lt.join)(g(e),"tsconfig.build.json");Gt(t,r=>{r.exclude=["node_modules","test","dist","**/*.spec.ts","**/*.test.ts"]})},pl=e=>{let t=(0,lt.join)(g(e),"nest-cli.json");Gt(t,r=>{r.compilerOptions=r.compilerOptions||{},r.compilerOptions.tsConfigPath="tsconfig.build.json"})},ml=e=>{let t=(0,lt.join)(g(e),"package.json");Gt(t,r=>{delete r.jest})},ps=e=>{cl(e),ll(e),pl(e),ml(e)};var ms=require("node:path");var dl=(e,t)=>{let r=Br(e);if(r){for(let{className:n,importPath:o}of t)Lr(r,o,[n]),Wr(r,n);Hr(r)}},ds=e=>{let t=(0,ms.join)(g(e),"src","app.module.ts");dl(t,[{className:"EventsModule",importPath:"./events/events.module"}])};var ul=require("fs-extra");var fl=u(require("chalk")),hl=u(require("cli-table3"));var us=require("node:fs"),gs=require("node:path"),fs=u(require("handlebars"));var Ne=(e,t)=>io(e,t??`Templates directory not found. Searched in: ${e.join(", ")}`),Kr=(e,t={})=>{let r=(0,us.readFileSync)(e,"utf-8");return fs.default.compile(r)(t)},Ut=e=>(t,r={})=>{let n=(0,gs.join)(e,t);return Kr(n,r)};var pt=e=>e.toUpperCase().replace(/-/g,"_");var hs=e=>e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ");function Jt(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}async function ys(e,t,r={},n=[],o=[]){if(!e){console.error("Subcommand is not defined.");return}let s=n.map(l=>t[l]).filter(l=>l!==void 0),a=o.map(l=>{let p=t[l];if(!(p===!1||p===void 0))return p===!0?`--${Jt(String(l))}`:`--${Jt(String(l))}=${String(p)}`}).filter(l=>l!==void 0),i=Object.entries(r).map(([l,p])=>{if(!(p===!1||p===void 0))return p===!0?`--${Jt(l)}`:`--${Jt(l)}=${String(p)}`}).filter(l=>l!==void 0),c=[...s,...a,...i].map(String);await e.parseAsync(c,{from:"user"})}var Ls=require("node:path"),re=u(require("chalk"));var ks=require("@listr2/prompt-adapter-enquirer"),je={title:"Confirm creation",enabled:e=>!e.userConfirmed,task:async(e,t)=>{if(e.userConfirmed=await t.prompt(ks.ListrEnquirerPromptAdapter).run({type:"Toggle",initial:!0,message:"\u{1F680} Ready to launch your project?"}),!e.userConfirmed)throw new Error("Project creation was canceled by the user.")}};var V=require("node:fs"),Re=require("node:path");function vs(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
196
196
|
import { ports } from '@crossdelta/infrastructure'
|
|
197
197
|
|
|
198
198
|
/**
|
|
@@ -234,19 +234,19 @@ const config: K8sServiceConfig = {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
export default config
|
|
237
|
-
`}var yl=4001,kl=4e3;function vl(e){let t=[],r=e.matchAll(/ports\(\)\.(?:http|https|grpc|primary)\((\d+)\)/g);for(let c of r)t.push(Number(c[1]));let n=e.matchAll(/\.add(?:Http|Grpc)?\((\d+)/g);for(let c of n)t.push(Number(c[1]));let o=e.match(/containerPort\s*:\s*(\d+)/);o&&t.push(Number(o[1]));let s=e.match(/internalPorts\s*:\s*\[([^\]]+)\]/);if(s){let c=s[1].match(/\d+/g);c&&t.push(...c.map(Number))}let a=e.match(/httpPort\s*:\s*(\d+)/);a&&t.push(Number(a[1]));let i=e.matchAll(/const\s+\w*[pP]ort\w*\s*=\s*(\d+)/g);for(let c of i)t.push(Number(c[1]));return t}function xl(e,t){let r=t?yl:kl,n=new Set;if(!(0,V.existsSync)(e))return r;let o=(0,V.readdirSync)(e).filter(a=>a.endsWith(".ts"));for(let a of o){let i=(0,
|
|
237
|
+
`}var yl=4001,kl=4e3;function vl(e){let t=[],r=e.matchAll(/ports\(\)\.(?:http|https|grpc|primary)\((\d+)\)/g);for(let c of r)t.push(Number(c[1]));let n=e.matchAll(/\.add(?:Http|Grpc)?\((\d+)/g);for(let c of n)t.push(Number(c[1]));let o=e.match(/containerPort\s*:\s*(\d+)/);o&&t.push(Number(o[1]));let s=e.match(/internalPorts\s*:\s*\[([^\]]+)\]/);if(s){let c=s[1].match(/\d+/g);c&&t.push(...c.map(Number))}let a=e.match(/httpPort\s*:\s*(\d+)/);a&&t.push(Number(a[1]));let i=e.matchAll(/const\s+\w*[pP]ort\w*\s*=\s*(\d+)/g);for(let c of i)t.push(Number(c[1]));return t}function xl(e,t){let r=t?yl:kl,n=new Set;if(!(0,V.existsSync)(e))return r;let o=(0,V.readdirSync)(e).filter(a=>a.endsWith(".ts"));for(let a of o){let i=(0,Re.join)(e,a);try{let c=(0,V.readFileSync)(i,"utf-8"),l=vl(c);for(let p of l)n.add(p)}catch{}}let s=r;for(;n.has(s);)s++;return s}function Cl(e){return(0,Re.basename)(e)}var Kt={title:"Creating infrastructure service config",task:async(e,t)=>{let r=Cl(e.projectName),n=k(),o=(0,Re.join)(n,"infra","services");if(!(0,V.existsSync)(o)){t.title="Skipping infra config (no infra/services directory found)";return}let s=(0,Re.join)(o,`${r}.ts`);if((0,V.existsSync)(s)){t.title=`Service config already exists: infra/services/${r}.ts`;return}let a=xl(o,!0);e.assignedPort=a;let i=e.serviceType==="hono"?vs(r,a):xs(r,a);(0,V.writeFileSync)(s,i),t.title=`Created infra/services/${r}.ts (port: ${a})`}};var mt=require("node:child_process"),Cs=require("node:fs"),ws=require("node:path"),wl=()=>{try{return(0,mt.execSync)("git --version",{stdio:"ignore"}),!0}catch{return!1}},bl=e=>(0,Cs.existsSync)((0,ws.join)(e,".git")),bs={title:"Initializing git repository",enabled:()=>wl(),skip:e=>bl(e.cwd)?"Already a git repository":!1,task:async(e,t)=>{try{(0,mt.execSync)("git init",{cwd:e.cwd,stdio:"ignore"}),(0,mt.execSync)("git add -A",{cwd:e.cwd,stdio:"ignore"}),(0,mt.execSync)('git commit -m "chore: initial commit"',{cwd:e.cwd,stdio:"ignore",env:{...process.env,GIT_AUTHOR_NAME:process.env.GIT_AUTHOR_NAME||"Platform SDK",GIT_AUTHOR_EMAIL:process.env.GIT_AUTHOR_EMAIL||"platform-sdk@localhost",GIT_COMMITTER_NAME:process.env.GIT_COMMITTER_NAME||"Platform SDK",GIT_COMMITTER_EMAIL:process.env.GIT_COMMITTER_EMAIL||"platform-sdk@localhost"}}),t.title="Git repository initialized with initial commit"}catch{t.title="Git initialization skipped (git error)"}}};var Ss=require("@listr2/prompt-adapter-enquirer"),zr=u(require("chalk"));var Me={title:"Installing Bun",enabled:e=>!!e.shouldInstallBun&&!Gr(),task:async(e,t)=>S(t,async r=>{await qo(t),e.elapsedTime+=r(),t.title=`Bun installed successfully. (${e.elapsedTime}s)`})},Fe={enabled:e=>!Gr()&&!e.shouldInstallBun&&!e.packageManager,task:async(e,t)=>{e.shouldInstallBun=await t.prompt(Ss.ListrEnquirerPromptAdapter).run({type:"Toggle",message:"Would you like to use Bun? (recommended)",initial:!0,footer:["",`${zr.default.magenta.bold("Bun")} is a fast JavaScript runtime, package manager, bundler, and test runner: ${zr.default.underline("https://bun.sh")}`,Vo(),Zo()].join(`
|
|
238
238
|
`)}),e.shouldInstallBun&&(e.packageManager="bun")}};var Ps=require("@listr2/prompt-adapter-enquirer"),qr=u(require("chalk"));var zt={title:"Install integrations",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>S(t,async r=>{let{selectedIntegrations:n,cwd:o,packageManager:s}=e;await is({selectedIntegrations:n,packageManager:s,cwd:o,task:t}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1e3}},qt={title:"Select integrations",enabled:e=>e.selectedIntegrations.length===0,task:async(e,t)=>{e.selectedIntegrations=await t.prompt(Ps.ListrEnquirerPromptAdapter).run({type:"MultiSelect",hint:`
|
|
239
239
|
Press <space> to select/deselect, <enter> to confirm, <i> to invert selection`,message:"Which integrations would you like to include?",initial:$e().map((r,n)=>n),choices:e.availableIntegrations.map(({name:r,description:n})=>({name:r,message:[qr.default.bold(r),n].join(" - "),value:r}))}),!e.selectedIntegrations||e.selectedIntegrations.length===0?t.title="No integrations selected.":t.title=["Selected integrations:",...e.selectedIntegrations.map(r=>qr.default.bold(`\u2022 ${r}`))].join(`
|
|
240
|
-
`)}};var Ts={title:"Install Nest CLI",task:async(e,t)=>S(t,async r=>{await Wn({packages:["@nestjs/cli"],task:t,cwd:e.cwd}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1e3}};var Vt={title:"Install dependencies",task:async(e,t)=>S(t,async r=>{await H({cwd:e.cwd,task:t,packageManager:e.packageManager}),e.elapsedTime+=r()})};var Es=require("@listr2/prompt-adapter-enquirer"),As=u(require("chalk"));var Oe={enabled:e=>!e.removeDir&&!vt(e.cwd),task:async(e,t)=>{if(e.removeDir=await t.prompt(Es.ListrEnquirerPromptAdapter).run({type:"Toggle",message:As.default.bold("\u26A0\uFE0F Overwrite existing directory?"),initial:!1}),!e.removeDir)throw new Error("Project creation was canceled by the user.")}},De={enabled:e=>!!e.removeDir,task:async e=>Tn(e.cwd)};var Zt={title:"Run integration commands",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>S(t,async r=>{let{selectedIntegrations:n,cwd:o}=e;await ls({selectedIntegrations:n,cwd:o,task:t,packageManager:e.packageManager}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1}};var Is=require("@listr2/prompt-adapter-enquirer");var Sl=["services/my-hono-service","services/my-nest-service","my-platform"],Be={enabled:e=>e.skipInputPrompts||e.userConfirmed?!1:e.projectName?Sl.includes(e.projectName):!0,task:async(e,t)=>{e.projectName=await t.prompt(Is.ListrEnquirerPromptAdapter).run({type:"Input",initial:e.projectName,message:"Enter project name",validate:r=>r?!0:"Project name is required."}),e.cwd&&(e.cwd=g(e.projectName))}};var $s=require("@listr2/prompt-adapter-enquirer"),Vr=u(require("chalk"));var He={title:"Select Package manager",task:async(e,t)=>{if(e.packageManager??=dr(),e.packageManager){t.title=`Using ${Vr.default.bold(e.packageManager)} as package manager.`;return}e.packageManager=await t.prompt($s.ListrEnquirerPromptAdapter).run({type:"Select",message:"Which package manager would you like to use?",initial:ur(),choices:Ln}),t.title=`Using ${Vr.default.bold(e.packageManager)} as package manager.`}};var Yt=require("@listr2/prompt-adapter-enquirer"),dt=u(require("chalk")),Ns={title:"GitHub repository owner",task:async(e,t)=>{if(e.githubOwner){t.title=`GitHub owner: ${dt.default.bold(e.githubOwner)}`;return}e.githubOwner=await t.prompt(Yt.ListrEnquirerPromptAdapter).run({type:"Input",message:"Enter GitHub organization or username",initial:"my-org",validate:r=>r?.trim()?!0:"GitHub owner is required."}),t.title=`GitHub owner: ${dt.default.bold(e.githubOwner)}`}},
|
|
240
|
+
`)}};var Ts={title:"Install Nest CLI",task:async(e,t)=>S(t,async r=>{await Wn({packages:["@nestjs/cli"],task:t,cwd:e.cwd}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1e3}};var Vt={title:"Install dependencies",task:async(e,t)=>S(t,async r=>{await H({cwd:e.cwd,task:t,packageManager:e.packageManager}),e.elapsedTime+=r()})};var Es=require("@listr2/prompt-adapter-enquirer"),As=u(require("chalk"));var Oe={enabled:e=>!e.removeDir&&!vt(e.cwd),task:async(e,t)=>{if(e.removeDir=await t.prompt(Es.ListrEnquirerPromptAdapter).run({type:"Toggle",message:As.default.bold("\u26A0\uFE0F Overwrite existing directory?"),initial:!1}),!e.removeDir)throw new Error("Project creation was canceled by the user.")}},De={enabled:e=>!!e.removeDir,task:async e=>Tn(e.cwd)};var Zt={title:"Run integration commands",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>S(t,async r=>{let{selectedIntegrations:n,cwd:o}=e;await ls({selectedIntegrations:n,cwd:o,task:t,packageManager:e.packageManager}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1}};var Is=require("@listr2/prompt-adapter-enquirer");var Sl=["services/my-hono-service","services/my-nest-service","my-platform"],Be={enabled:e=>e.skipInputPrompts||e.userConfirmed?!1:e.projectName?Sl.includes(e.projectName):!0,task:async(e,t)=>{e.projectName=await t.prompt(Is.ListrEnquirerPromptAdapter).run({type:"Input",initial:e.projectName,message:"Enter project name",validate:r=>r?!0:"Project name is required."}),e.cwd&&(e.cwd=g(e.projectName))}};var $s=require("@listr2/prompt-adapter-enquirer"),Vr=u(require("chalk"));var He={title:"Select Package manager",task:async(e,t)=>{if(e.packageManager??=dr(),e.packageManager){t.title=`Using ${Vr.default.bold(e.packageManager)} as package manager.`;return}e.packageManager=await t.prompt($s.ListrEnquirerPromptAdapter).run({type:"Select",message:"Which package manager would you like to use?",initial:ur(),choices:Ln}),t.title=`Using ${Vr.default.bold(e.packageManager)} as package manager.`}};var Yt=require("@listr2/prompt-adapter-enquirer"),dt=u(require("chalk")),Ns={title:"GitHub repository owner",task:async(e,t)=>{if(e.githubOwner){t.title=`GitHub owner: ${dt.default.bold(e.githubOwner)}`;return}e.githubOwner=await t.prompt(Yt.ListrEnquirerPromptAdapter).run({type:"Input",message:"Enter GitHub organization or username",initial:"my-org",validate:r=>r?.trim()?!0:"GitHub owner is required."}),t.title=`GitHub owner: ${dt.default.bold(e.githubOwner)}`}},js={title:"Include GitHub CI/CD",task:async(e,t)=>{if(e.includeGitHubCI!==void 0){t.title=e.includeGitHubCI?"Including GitHub CI/CD workflows":"Skipping GitHub CI/CD";return}e.includeGitHubCI=await t.prompt(Yt.ListrEnquirerPromptAdapter).run({type:"Toggle",message:"Include GitHub Actions workflows and CI/CD?",initial:!0,enabled:"Yes",disabled:"No"}),t.title=e.includeGitHubCI?"Including GitHub CI/CD workflows":"Skipping GitHub CI/CD"}};var Rs={title:"Pulumi stack name",task:async(e,t)=>{if(e.pulumiStackBase){t.title=`Pulumi stack: ${dt.default.bold(e.pulumiStackBase)}`;return}let r=e.githubOwner||"myorg",n=e.projectName?.replace(/[^a-zA-Z0-9-]/g,"-")||"myproject",o=`${r}/${n}`;e.pulumiStackBase=await t.prompt(Yt.ListrEnquirerPromptAdapter).run({type:"Input",message:"Enter Pulumi stack base name (org/project)",initial:o,validate:s=>s?.trim()?s.includes("/")?!0:"Format should be org/project (e.g., myorg/myproject)":"Pulumi stack name is required."}),t.title=`Pulumi stack: ${dt.default.bold(e.pulumiStackBase)}`}};var O=require("node:fs"),j=require("node:path");var Xt=require("node:path");var Pl=()=>{let e=rt();return Ne([(0,Xt.join)(__dirname,"templates","hono-microservice"),(0,Xt.join)(__dirname,"..","hono-microservice","templates"),(0,Xt.join)(e,"bin","templates","hono-microservice")],"Hono templates directory not found.")},ut=(e,t={})=>Ut(Pl())(e,t);function Ms(){return ut("tsconfig.json.hbs")}function Fs(e="1.2.23"){return ut("Dockerfile.hbs",{bunVersion:e})}function Os(){return ut("biome.json.hbs")}function Ds(e){return ut("src/index.ts.hbs",{envKey:pt(e)})}function Bs(e){return ut("src/config/env.ts.hbs",{envKey:pt(e)})}var Tl=async({projectName:e,packageManager:t},r)=>{let n=t==="bun"?"bun":"nodejs";try{await ee("create-hono@latest",[e,"--pm",t,"--template",n,"--install"],{task:r})}catch(s){let a=(0,j.join)(g(e),"package.json");if(!(0,O.existsSync)(a))throw new Error(`Failed to scaffold: ${s instanceof Error?s.message:String(s)}`)}let o=(0,j.join)(g(e),"package.json");if(!(0,O.existsSync)(o))throw new Error("Failed to scaffold Hono app structure - package.json not created")},El=({projectName:e,packageManager:t})=>{let r=(0,j.basename)(e),n=ve(),o=t==="npm"?"*":"workspace:*",s=g(e),a=An("scripts.dev",s);a&&Q("scripts.start:dev",a,e),[{field:"name",value:`${n}/${r}`},{field:"scripts.test",value:"bun test"},{field:"scripts.lint",value:"biome lint --write ./src"},{field:`dependencies.${n}/contracts`,value:o},{field:"dependencies.@crossdelta/telemetry",value:"*"},{field:"dependencies.zod",value:"^4.0.0"},{field:"devDependencies.bun-types",value:"latest",condition:t!=="bun"},{field:"devDependencies.@biomejs/biome",value:"latest"}].filter(({condition:c})=>c??!0).map(({field:c,value:l})=>Q(c,l,e))},Al=({projectName:e})=>{let t=(0,j.basename)(e),r=(0,j.join)(g(e),"src","index.ts"),n=Ds(t);(0,O.writeFileSync)(r,n)},Il=({projectName:e})=>{let t=(0,j.basename)(e),r=g(e),n=(0,j.join)(r,"src","config");(0,O.existsSync)(n)||(0,O.mkdirSync)(n,{recursive:!0});let o=(0,j.join)(n,"env.ts"),s=Bs(t);(0,O.writeFileSync)(o,s)},$l=({projectName:e})=>{let t=g(e),r=(0,j.join)(t,"tsconfig.json");(0,O.writeFileSync)(r,Ms());let n=(0,j.join)(t,"Dockerfile");(0,O.writeFileSync)(n,Fs());let o=(0,j.join)(t,"biome.json");(0,O.writeFileSync)(o,Os())},Hs={title:"Create Hono app structure",rendererOptions:{outputBar:1e3},task:async(e,t)=>S(t,async r=>{await Tl(e,t),El(e),Al(e),Il(e),$l(e),e.elapsedTime+=r()})};var Nl=e=>{let t=(e||"my-hono-service").trim();return t.includes("/")||t.startsWith(".")?t:`${B().services}/${t}`},jl=async(e,t)=>{let{valid:r,config:n,error:o}=Ie();if(!r||!n){console.log(o);return}let s=Nl(e.name),a=t.packageManager||w(),i=await Ot(t.description);if(Dt(s,n,i),await Bt({servicePath:s,description:i,serviceType:"hono",packageManager:a},n))console.log(re.default.green.bold(`
|
|
241
241
|
\u2705 Service generated successfully!
|
|
242
|
-
`)),console.log(re.default.dim("Next steps:")),console.log(re.default.dim(` ${re.default.cyan("pf dev")} - Start all services`)),console.log(re.default.dim(` ${re.default.cyan(`cd ${s} && bun dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},Ws=se({name:"hono-micro",description:"Create a new Hono microservice with the Crossdelta setup. Use --ai for AI-powered generation.",arguments:[["[name]","Name or path of the service"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["--ai","Use AI to generate service code based on a description"],["-d, --description <description>","Service description for AI generation (requires --ai)"],["--remove-dir","Remove existing directory before creating (used internally)"]],exampleUsage:'platform new hono-micro my-service --ai -d "Payment processing service"',shouldSkipWorkflow:(e,t)=>!!t.ai,onSkipWorkflow:
|
|
243
|
-
${re.default.bold(`cd ${e} && ${o} run dev`)}`).breakLine().log("Happy shipping with Hono! \u26A1\uFE0F").breakLine()}});var ne=u(require("chalk"));var G=require("node:fs"),
|
|
242
|
+
`)),console.log(re.default.dim("Next steps:")),console.log(re.default.dim(` ${re.default.cyan("pf dev")} - Start all services`)),console.log(re.default.dim(` ${re.default.cyan(`cd ${s} && bun dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},Ws=se({name:"hono-micro",description:"Create a new Hono microservice with the Crossdelta setup. Use --ai for AI-powered generation.",arguments:[["[name]","Name or path of the service"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["--ai","Use AI to generate service code based on a description"],["-d, --description <description>","Service description for AI generation (requires --ai)"],["--remove-dir","Remove existing directory before creating (used internally)"]],exampleUsage:'platform new hono-micro my-service --ai -d "Payment processing service"',shouldSkipWorkflow:(e,t)=>!!t.ai,onSkipWorkflow:jl,buildContext:async(e,t)=>{let r=(e.name??"my-hono-service").trim();!r.includes("/")&&!r.startsWith(".")&&(r=`${B().services}/${r}`);let n=g(r),o=t.packageManager??(t.yes&&w()),s=_(),a=t.yes?$e():[],i=t.packageManager==="bun",c=!!t.yes||!!e.name&&e.name!=="my-hono-service";return{cwd:n,projectName:r,packageManager:o,shouldInstallBun:i,availableIntegrations:s,selectedIntegrations:a,serviceType:"hono",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[Be,Oe,Fe,He,qt,je],actions:[De,Me,Hs,Kt,zt,Zt],onComplete:({projectName:e,packageManager:t,selectedIntegrations:r,assignedPort:n})=>{m.breakLine().log(re.default.bold.green("Hono Microservice created successfully!")),Wt(r),as((0,Ls.basename)(e),n??8080);let o=t??w();m.breakLine().log(`To start the project, run:
|
|
243
|
+
${re.default.bold(`cd ${e} && ${o} run dev`)}`).breakLine().log("Happy shipping with Hono! \u26A1\uFE0F").breakLine()}});var ne=u(require("chalk"));var G=require("node:fs"),R=require("node:path");var Yr=require("node:path");var Rl=()=>Ne([(0,Yr.join)(__dirname,"templates","nest-microservice"),(0,Yr.join)(__dirname,"..","nest-microservice","templates")],"NestJS templates directory not found."),Le=(e,t={})=>Ut(Rl())(e,t);function Qt(e,t=3e3){return Le("src/main.ts.hbs",{serviceName:e,envKey:pt(e),displayName:hs(e),defaultPort:t})}function _s(){return Le("src/app.context.ts.hbs",{})}function Gs(){return Le("src/events/events.module.ts.hbs",{})}function Us(e){return Le("src/events/events.service.ts.hbs",{serviceName:e})}function Js(e="24",t="1.2.23"){return Le("Dockerfile.hbs",{nodeVersion:e,bunVersion:t})}function Ks(){return Le("biome.json.hbs",{})}var Ml=async(e,t)=>{await ee("@nestjs/cli",["new",e.projectName,"--skip-install","--skip-git","--package-manager",e.packageManager],{task:t})},Fl=({projectName:e,packageManager:t})=>{let r=(0,R.basename)(e),n=ve(),o=t==="npm"?"*":"workspace:*";[{field:"name",value:`${n}/${r}`},{field:"type",value:"module"},{field:"scripts.start",value:"bun src/main.ts"},{field:"scripts.start:dev",value:"bun --hot src/main.ts"},{field:"scripts.start:prod",value:"node dist/main.js"},{field:"scripts.test",value:"bun test"},{field:"scripts.lint",value:"biome lint --write ./src"},{field:`dependencies.${n}/contracts`,value:o},{field:"dependencies.@crossdelta/telemetry",value:"*"},{field:"dependencies.@nestjs/config",value:"^4"},{field:"devDependencies.bun-types",value:"latest"},{field:"devDependencies.@biomejs/biome",value:"latest"}].map(({field:i,value:c})=>Q(i,c,e)),["jest","@types/jest","ts-jest","@nestjs/testing","supertest","@types/supertest","ts-node","tsconfig-paths","@nestjs/schematics","@nestjs/cli"].map(i=>Q(`devDependencies.${i}`,void 0,e))},Ol=({projectName:e})=>{let t=["eslint.config.mjs","src/app.controller.spec.ts"];for(let r of t)try{(0,G.unlinkSync)((0,R.join)(g(e),r))}catch{}},Dl=({projectName:e})=>{let t=g(e),r=(0,R.join)(t,"Dockerfile");(0,G.writeFileSync)(r,Js());let n=(0,R.join)(t,"biome.json");(0,G.writeFileSync)(n,Ks())},Bl=({projectName:e})=>{let t=(0,R.join)(g(e),"src","app.context.ts");(0,G.writeFileSync)(t,_s())},Hl=({projectName:e})=>{let t=(0,R.basename)(e),r=(0,R.join)(g(e),"src","events");(0,G.mkdirSync)(r,{recursive:!0}),(0,G.writeFileSync)((0,R.join)(r,"events.module.ts"),Gs()),(0,G.writeFileSync)((0,R.join)(r,"events.service.ts"),Us(t)),ds(e)},Ll=({projectName:e})=>{let t=(0,R.basename)(e),r=(0,R.join)(g(e),"src","main.ts");(0,G.writeFileSync)(r,Qt(t))},zs={title:"Create NestJS app structure",rendererOptions:{outputBar:1e3},task:async(e,t)=>S(t,async r=>{await Ml(e,t),Fl(e),ps(e.projectName),Ol(e),Dl(e),Bl(e),Hl(e),Ll(e),e.elapsedTime+=r()})};var qs=require("node:fs"),er=require("node:path");var Vs={title:"Patch main.ts with PORT pattern",task:async(e,t)=>S(t,async r=>{let n=(0,er.basename)(e.projectName),o=e.assignedPort??3e3,s=(0,er.join)(g(e.projectName),"src","main.ts");(0,qs.writeFileSync)(s,Qt(n,o)),t.title=`Patched main.ts with PORT || ${n.toUpperCase().replace(/-/g,"_")}_PORT`,e.elapsedTime+=r()})};var Wl=e=>{let t=(e||"my-nest-service").trim();return t.includes("/")||t.startsWith(".")?t:`${B().services}/${t}`},_l=async(e,t)=>{let{valid:r,config:n,error:o}=Ie();if(!r||!n){console.log(o);return}let s=Wl(e.name),a=t.packageManager||w(),i=await Ot(t.description);if(Dt(s,n,i),await Bt({servicePath:s,description:i,serviceType:"nest",packageManager:a},n))console.log(ne.default.green.bold(`
|
|
244
244
|
\u2705 Service generated successfully!
|
|
245
|
-
`)),console.log(ne.default.dim("Next steps:")),console.log(ne.default.dim(` ${ne.default.cyan("pf dev")} - Start all services`)),console.log(ne.default.dim(` ${ne.default.cyan(`cd ${s} && bun run start:dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},Zs=se({name:"nest-micro",description:"Create a new NestJS microservice with the Crossdelta setup. Use --ai for AI-powered generation.",arguments:[["[name]","Name or path of the service"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["--ai","Use AI to generate service code based on a description"],["-d, --description <description>","Service description for AI generation (requires --ai)"],["--remove-dir","Remove existing directory before creating (used internally)"]],exampleUsage:'platform new nest-micro my-service --ai -d "User authentication service"',shouldSkipWorkflow:(e,t)=>!!t.ai,onSkipWorkflow:_l,buildContext:async(e,t)=>{let r=(e.name??"my-nest-service").trim();!r.includes("/")&&!r.startsWith(".")&&(r=`${B().services}/${r}`);let n=g(r),o=t.packageManager??(t.yes&&w()),s=t.packageManager==="bun",a=_(),i=t.yes?$e():[],c=!!t.yes||!!e.name;return{cwd:n,projectName:r,shouldInstallBun:s,packageManager:o,availableIntegrations:a,selectedIntegrations:i,serviceType:"nest",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[Be,Oe,Fe,He,qt,
|
|
245
|
+
`)),console.log(ne.default.dim("Next steps:")),console.log(ne.default.dim(` ${ne.default.cyan("pf dev")} - Start all services`)),console.log(ne.default.dim(` ${ne.default.cyan(`cd ${s} && bun run start:dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},Zs=se({name:"nest-micro",description:"Create a new NestJS microservice with the Crossdelta setup. Use --ai for AI-powered generation.",arguments:[["[name]","Name or path of the service"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["--ai","Use AI to generate service code based on a description"],["-d, --description <description>","Service description for AI generation (requires --ai)"],["--remove-dir","Remove existing directory before creating (used internally)"]],exampleUsage:'platform new nest-micro my-service --ai -d "User authentication service"',shouldSkipWorkflow:(e,t)=>!!t.ai,onSkipWorkflow:_l,buildContext:async(e,t)=>{let r=(e.name??"my-nest-service").trim();!r.includes("/")&&!r.startsWith(".")&&(r=`${B().services}/${r}`);let n=g(r),o=t.packageManager??(t.yes&&w()),s=t.packageManager==="bun",a=_(),i=t.yes?$e():[],c=!!t.yes||!!e.name;return{cwd:n,projectName:r,shouldInstallBun:s,packageManager:o,availableIntegrations:a,selectedIntegrations:i,serviceType:"nest",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[Be,Oe,Fe,He,qt,je],actions:[De,Me,zs,Kt,Vs,Vt,Ts,zt,Zt],onComplete:({projectName:e,packageManager:t,selectedIntegrations:r})=>{m.breakLine().log(ne.default.bold.green("NestJS Microservice created successfully!")),Wt(r),m.breakLine().log(`To start the project, run:
|
|
246
246
|
${ne.default.bold(`cd ${e} && ${t} run start:dev`)}`).breakLine().log("Happy coding! \u{1F389}").breakLine()}});var na=require("@listr2/prompt-adapter-enquirer"),M=u(require("chalk"));var Z=require("node:fs"),ft=require("node:path");var Ys=require("node:fs"),gt=require("node:path");var Xr=()=>{let e=rt();return Ne([(0,gt.join)(__dirname,"templates","workspace"),(0,gt.join)(__dirname,"..","..","..","..","templates","workspace"),(0,gt.join)(e,"bin","templates","workspace")],"Workspace templates directory not found.")},Xs=()=>{let e=Xr(),t=(0,gt.join)(e,"packages","contracts");if(!(0,Ys.existsSync)(t))throw new Error(`Contracts templates directory not found at: ${t}`);return t},tr=(e,t)=>Kr(e,t);var Gl=()=>{let e=(0,ft.join)(process.cwd(),"package.json");if(!(0,Z.existsSync)(e))throw new Error("Root package.json not found. Please run this command from the workspace root.");let r=JSON.parse((0,Z.readFileSync)(e,"utf-8")).name;if(!r)throw new Error('package.json must have a "name" field');return r.startsWith("@")?r:`@${r}`},Qs=()=>{let e=Gl(),{relativePath:t,packagePath:r}=C();if((0,Z.existsSync)(r))throw new Error(`${t} already exists. Remove it first if you want to regenerate.`);console.log(`Creating contracts package with scope: ${e}`);let n=Xs(),o={scope:e,workspaceName:e.replace("@","").replace("/","-")};(0,Z.mkdirSync)(r,{recursive:!0}),(0,Z.mkdirSync)((0,ft.join)(r,"src","events"),{recursive:!0});let s=[{template:"package.json.hbs",output:"package.json"},{template:"tsconfig.json.hbs",output:"tsconfig.json"},{template:"README.md.hbs",output:"README.md"},{template:"src/index.ts",output:"src/index.ts"},{template:"src/stream-policies.ts.hbs",output:"src/stream-policies.ts"},{template:"src/events/index.ts",output:"src/events/index.ts"}];for(let a of s){let i=(0,ft.join)(n,a.template),c=(0,ft.join)(r,a.output),l=tr(i,o);(0,Z.writeFileSync)(c,l,"utf-8")}console.log(`\u2705 Created ${e}/contracts at ${t}`),console.log(`
|
|
247
|
-
Next steps:`),console.log("1. Run: bun install"),console.log("2. Define your first event schema in src/events/"),console.log('3. Add contracts to services: "@scope/contracts": "workspace:*"')};var ta=require("node:child_process"),I=require("node:fs"),We=require("node:path");var ea=e=>{e.endsWith(".sh")&&(0,I.chmodSync)(e,493)},Ul=[{template:"package.json.hbs",output:"package.json"},{template:"pnpm-workspace.yaml.hbs",output:"pnpm-workspace.yaml",forPackageManager:"pnpm"},{template:"biome.json.hbs",output:"biome.json"},{template:"turbo.json.hbs",output:"turbo.json"},{template:"bunfig.toml.hbs",output:"bunfig.toml"},{template:"gitignore.hbs",output:".gitignore"},{template:"editorconfig.hbs",output:".editorconfig"},{template:"npmrc.hbs",output:".npmrc"},{template:".vscode/settings.json",output:".vscode/settings.json",isStatic:!0},{template:".vscode/extensions.json",output:".vscode/extensions.json",isStatic:!0},{template:"infra/package.json.hbs",output:"infra/package.json"},{template:"infra/index.ts.hbs",output:"infra/index.ts"},{template:"infra/tsconfig.json.hbs",output:"infra/tsconfig.json"},{template:"infra/Pulumi.yaml.hbs",output:"infra/Pulumi.yaml"},{template:"infra/Pulumi.dev.yaml.hbs",output:"infra/Pulumi.dev.yaml"},{template:"apps/.gitkeep",output:"apps/.gitkeep",isStatic:!0},{template:"packages/.gitkeep",output:"packages/.gitkeep",isStatic:!0},{template:"docs/.gitkeep",output:"docs/.gitkeep",isStatic:!0},{template:"infra/services/.gitkeep",output:"infra/services/.gitkeep",isStatic:!0},{template:".github/README.md",output:".github/README.md",isStatic:!0,isGitHubCI:!0},{template:".github/dependabot.yml",output:".github/dependabot.yml",isStatic:!0,isGitHubCI:!0},{template:".github/workflows/lint-and-tests.yml.hbs",output:".github/workflows/lint-and-tests.yml",isGitHubCI:!0},{template:".github/workflows/build-and-deploy.yml.hbs",output:".github/workflows/build-and-deploy.yml",isGitHubCI:!0},{template:".github/workflows/publish-packages.yml",output:".github/workflows/publish-packages.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/setup-bun-install/action.yml.hbs",output:".github/actions/setup-bun-install/action.yml",isGitHubCI:!0},{template:".github/actions/check-image-tag-exists/action.yml",output:".github/actions/check-image-tag-exists/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/check-image-tag-exists/index.js",output:".github/actions/check-image-tag-exists/index.js",isStatic:!0,isGitHubCI:!0},{template:".github/actions/check-path-changes/action.yml",output:".github/actions/check-path-changes/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/check-path-changes/index.js",output:".github/actions/check-path-changes/index.js",isStatic:!0,isGitHubCI:!0},{template:".github/actions/detect-skipped-services/action.yml",output:".github/actions/detect-skipped-services/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/generate-scope-matrix/action.yml",output:".github/actions/generate-scope-matrix/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/generate-scope-matrix/index.js",output:".github/actions/generate-scope-matrix/index.js",isStatic:!0,isGitHubCI:!0},{template:".github/actions/prepare-build-context/action.yml",output:".github/actions/prepare-build-context/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/resolve-scope-tags/action.yml",output:".github/actions/resolve-scope-tags/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/resolve-scope-tags/index.js",output:".github/actions/resolve-scope-tags/index.js",isStatic:!0,isGitHubCI:!0}],ra={title:"Creating workspace structure",task:async(e,t)=>{if((0,I.existsSync)(e.cwd)){t.title="Workspace directory already exists, skipping...";return}let r=Xr(),n=e.includeGitHubCI??!0,o=e.packageManager||"bun",s=c=>{try{let d=(0,ta.spawnSync)(c,["--version"],{encoding:"utf-8",timeout:5e3}).stdout?.trim();if(d&&/^\d+\.\d+/.test(d))return`${c}@${d}`}catch{}return{bun:"bun@1.2.7",npm:"npm@10.9.2",yarn:"yarn@4.6.0",pnpm:"pnpm@9.15.2"}[c]||`${c}@latest`},a={projectName:e.projectName,scope:`@${e.projectName}`,githubOwner:e.githubOwner||"",pulumiStackBase:e.pulumiStackBase||e.projectName,packageManager:o,packageManagerVersion:s(o)},i=Ul.filter(c=>!(c.isGitHubCI&&!n||c.forPackageManager&&c.forPackageManager!==o));for(let c of i){let l=(0,We.join)(e.cwd,c.output),p=(0,We.dirname)(l);if((0,I.existsSync)(p)||(0,I.mkdirSync)(p,{recursive:!0}),c.isStatic){let d=(0,We.join)(r,c.template);(0,I.existsSync)(d)?(0,I.writeFileSync)(l,(0,I.readFileSync)(d)):(0,I.writeFileSync)(l,""),ea(l)}else{let d=(0,We.join)(r,c.template),v=tr(d,a);(0,I.writeFileSync)(l,v),ea(l)}}t.title="Workspace structure created"}};var oa=se({name:"workspace",description:"Create a new workspace with infrastructure setup",arguments:[["[name]","Name or path of the workspace"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["-o, --github-owner <owner>","GitHub organization or username"],["-s, --pulumi-stack <name>","Pulumi stack base name (org/project)"],["--no-github","Skip GitHub CI/CD workflows"],["--remove-dir","Remove existing directory before creating (internal use)"]],exampleUsage:"pf new workspace my-platform -o my-org",buildContext:(e,t)=>{let r=(e.name??"my-platform").trim(),n=g(r),o=!!t.yes,s=t.packageManager??(o?w():void 0),a=t.packageManager==="bun",i=t.githubOwner??(o?"my-org":void 0),c=t.pulumiStack??(o?`${i}/${r}`:void 0),l=t.github===!1?!1:o?!0:void 0,p=!!e.name,d=t.removeDir||o;return{cwd:n,projectName:r,shouldInstallBun:a,packageManager:s,elapsedTime:0,userConfirmed:o,skipInputPrompts:p&&!o,removeDir:d,githubOwner:i,pulumiStackBase:c,includeGitHubCI:l}},prompts:[{enabled:e=>!e.userConfirmed,task:async(e,t)=>{try{let r=k();if(!await t.prompt(na.ListrEnquirerPromptAdapter).run({type:"toggle",message:`\u26A0\uFE0F You are inside an existing workspace (${r}). Create a nested workspace anyway?`,enabled:"Yes",disabled:"No",initial:!1}))throw new Error("Workspace creation cancelled - already inside a workspace");t.title=M.default.yellow("Warning: Creating nested workspace")}catch(r){if(r.message?.includes("cancelled"))throw r;t.title="No existing workspace detected"}}},Be,Oe,Ns,Rs,
|
|
247
|
+
Next steps:`),console.log("1. Run: bun install"),console.log("2. Define your first event schema in src/events/"),console.log('3. Add contracts to services: "@scope/contracts": "workspace:*"')};var ta=require("node:child_process"),I=require("node:fs"),We=require("node:path");var ea=e=>{e.endsWith(".sh")&&(0,I.chmodSync)(e,493)},Ul=[{template:"package.json.hbs",output:"package.json"},{template:"tsconfig.json.hbs",output:"tsconfig.json"},{template:"pnpm-workspace.yaml.hbs",output:"pnpm-workspace.yaml",forPackageManager:"pnpm"},{template:"biome.json.hbs",output:"biome.json"},{template:"turbo.json.hbs",output:"turbo.json"},{template:"bunfig.toml.hbs",output:"bunfig.toml"},{template:"gitignore.hbs",output:".gitignore"},{template:"editorconfig.hbs",output:".editorconfig"},{template:"npmrc.hbs",output:".npmrc"},{template:".vscode/settings.json",output:".vscode/settings.json",isStatic:!0},{template:".vscode/extensions.json",output:".vscode/extensions.json",isStatic:!0},{template:"infra/package.json.hbs",output:"infra/package.json"},{template:"infra/index.ts.hbs",output:"infra/index.ts"},{template:"infra/tsconfig.json.hbs",output:"infra/tsconfig.json"},{template:"infra/Pulumi.yaml.hbs",output:"infra/Pulumi.yaml"},{template:"infra/Pulumi.dev.yaml.hbs",output:"infra/Pulumi.dev.yaml"},{template:"apps/.gitkeep",output:"apps/.gitkeep",isStatic:!0},{template:"packages/.gitkeep",output:"packages/.gitkeep",isStatic:!0},{template:"docs/.gitkeep",output:"docs/.gitkeep",isStatic:!0},{template:"infra/services/.gitkeep",output:"infra/services/.gitkeep",isStatic:!0},{template:".github/README.md",output:".github/README.md",isStatic:!0,isGitHubCI:!0},{template:".github/dependabot.yml",output:".github/dependabot.yml",isStatic:!0,isGitHubCI:!0},{template:".github/workflows/lint-and-tests.yml.hbs",output:".github/workflows/lint-and-tests.yml",isGitHubCI:!0},{template:".github/workflows/build-and-deploy.yml.hbs",output:".github/workflows/build-and-deploy.yml",isGitHubCI:!0},{template:".github/workflows/publish-packages.yml",output:".github/workflows/publish-packages.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/setup-bun-install/action.yml.hbs",output:".github/actions/setup-bun-install/action.yml",isGitHubCI:!0},{template:".github/actions/check-image-tag-exists/action.yml",output:".github/actions/check-image-tag-exists/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/check-image-tag-exists/index.js",output:".github/actions/check-image-tag-exists/index.js",isStatic:!0,isGitHubCI:!0},{template:".github/actions/check-path-changes/action.yml",output:".github/actions/check-path-changes/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/check-path-changes/index.js",output:".github/actions/check-path-changes/index.js",isStatic:!0,isGitHubCI:!0},{template:".github/actions/detect-skipped-services/action.yml",output:".github/actions/detect-skipped-services/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/generate-scope-matrix/action.yml",output:".github/actions/generate-scope-matrix/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/generate-scope-matrix/index.js",output:".github/actions/generate-scope-matrix/index.js",isStatic:!0,isGitHubCI:!0},{template:".github/actions/prepare-build-context/action.yml",output:".github/actions/prepare-build-context/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/resolve-scope-tags/action.yml",output:".github/actions/resolve-scope-tags/action.yml",isStatic:!0,isGitHubCI:!0},{template:".github/actions/resolve-scope-tags/index.js",output:".github/actions/resolve-scope-tags/index.js",isStatic:!0,isGitHubCI:!0}],ra={title:"Creating workspace structure",task:async(e,t)=>{if((0,I.existsSync)(e.cwd)){t.title="Workspace directory already exists, skipping...";return}let r=Xr(),n=e.includeGitHubCI??!0,o=e.packageManager||"bun",s=c=>{try{let d=(0,ta.spawnSync)(c,["--version"],{encoding:"utf-8",timeout:5e3}).stdout?.trim();if(d&&/^\d+\.\d+/.test(d))return`${c}@${d}`}catch{}return{bun:"bun@1.2.7",npm:"npm@10.9.2",yarn:"yarn@4.6.0",pnpm:"pnpm@9.15.2"}[c]||`${c}@latest`},a={projectName:e.projectName,scope:`@${e.projectName}`,githubOwner:e.githubOwner||"",pulumiStackBase:e.pulumiStackBase||e.projectName,packageManager:o,packageManagerVersion:s(o)},i=Ul.filter(c=>!(c.isGitHubCI&&!n||c.forPackageManager&&c.forPackageManager!==o));for(let c of i){let l=(0,We.join)(e.cwd,c.output),p=(0,We.dirname)(l);if((0,I.existsSync)(p)||(0,I.mkdirSync)(p,{recursive:!0}),c.isStatic){let d=(0,We.join)(r,c.template);(0,I.existsSync)(d)?(0,I.writeFileSync)(l,(0,I.readFileSync)(d)):(0,I.writeFileSync)(l,""),ea(l)}else{let d=(0,We.join)(r,c.template),v=tr(d,a);(0,I.writeFileSync)(l,v),ea(l)}}t.title="Workspace structure created"}};var oa=se({name:"workspace",description:"Create a new workspace with infrastructure setup",arguments:[["[name]","Name or path of the workspace"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["-o, --github-owner <owner>","GitHub organization or username"],["-s, --pulumi-stack <name>","Pulumi stack base name (org/project)"],["--no-github","Skip GitHub CI/CD workflows"],["--remove-dir","Remove existing directory before creating (internal use)"]],exampleUsage:"pf new workspace my-platform -o my-org",buildContext:(e,t)=>{let r=(e.name??"my-platform").trim(),n=g(r),o=!!t.yes,s=t.packageManager??(o?w():void 0),a=t.packageManager==="bun",i=t.githubOwner??(o?"my-org":void 0),c=t.pulumiStack??(o?`${i}/${r}`:void 0),l=t.github===!1?!1:o?!0:void 0,p=!!e.name,d=t.removeDir||o;return{cwd:n,projectName:r,shouldInstallBun:a,packageManager:s,elapsedTime:0,userConfirmed:o,skipInputPrompts:p&&!o,removeDir:d,githubOwner:i,pulumiStackBase:c,includeGitHubCI:l}},prompts:[{enabled:e=>!e.userConfirmed,task:async(e,t)=>{try{let r=k();if(!await t.prompt(na.ListrEnquirerPromptAdapter).run({type:"toggle",message:`\u26A0\uFE0F You are inside an existing workspace (${r}). Create a nested workspace anyway?`,enabled:"Yes",disabled:"No",initial:!1}))throw new Error("Workspace creation cancelled - already inside a workspace");t.title=M.default.yellow("Warning: Creating nested workspace")}catch(r){if(r.message?.includes("cancelled"))throw r;t.title="No existing workspace detected"}}},Be,Oe,Ns,js,Rs,Fe,He,je],actions:[De,Me,ra,{title:"Initializing contracts package",task:(e,t)=>{let r=process.cwd();try{process.chdir(e.cwd),Qs(),t.title="Contracts package initialized"}catch(n){throw t.title=M.default.red(`Contracts package failed: ${n.message}`),n}finally{process.chdir(r)}}},Vt,bs],onComplete:({projectName:e,includeGitHubCI:t})=>{m.breakLine().log(M.default.bold.green("Workspace created successfully!")),m.breakLine().log(M.default.bold("Next steps:")).log(` 1. ${M.default.cyan(`cd ${e}`)}`).log(` 2. ${M.default.cyan("bun pulumi login")}`).log(` 3. ${M.default.cyan("bun pulumi up --stack dev")}`),t&&m.breakLine().log(M.default.bold("GitHub Setup:")).log(" Configure these secrets in your GitHub repository:").log(` \u2022 ${M.default.yellow("PULUMI_ACCESS_TOKEN")} - Pulumi Cloud access token`).log(` \u2022 ${M.default.yellow("DIGITALOCEAN_TOKEN")} - DigitalOcean API token`).log(` \u2022 ${M.default.yellow("NPM_TOKEN")} - (optional) NPM token for private packages`),m.breakLine().log(M.default.bold("Structure created:")).log(" apps/ # Frontend applications").log(" services/ # Backend microservices").log(" packages/").log(" \u2514\u2500\u2500 contracts/ # Shared event contracts").log(" infra/").log(" \u251C\u2500\u2500 index.ts # Pulumi entry point").log(" \u251C\u2500\u2500 services/ # Service configs").log(" \u251C\u2500\u2500 Pulumi.yaml # Pulumi project config").log(" \u2514\u2500\u2500 Pulumi.dev.yaml # Dev stack config"),t&&m.log(" .github/").log(" \u251C\u2500\u2500 workflows/ # CI/CD workflows").log(" \u2514\u2500\u2500 actions/ # Custom actions"),m.breakLine().log("Happy coding! \u{1F389}").breakLine()}});var ht=[{name:"Hono Microservice",value:"hono-micro",command:Ws,supportsAi:!0},{name:"Nest Microservice",value:"nest-micro",command:Zs,supportsAi:!0},{name:"Workspace (Infrastructure)",value:"workspace",command:oa,supportsAi:!1}],sa=()=>{let e=se({name:"new",description:"Create a new project",arguments:[["[type]","Type of the project (e.g., nest-micro, hono-micro, workspace)"]],exampleUsage:"platform new hono-micro test-service",buildContext:t=>({projectType:t.type??"",useAi:!1,aiDescription:"",elapsedTime:0,cwd:process.cwd()}),prompts:[{enabled:t=>!t.projectType,task:async(t,r)=>{let n=await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"select",message:"Select Project type",choices:ht});t.projectType=ht.find(o=>o.name===n)?.value||"",r.title=`Using ${oe.default.bold(n)}`}},{enabled:t=>t.projectType!=="workspace"&&t.projectType!=="",task:async(t,r)=>{try{k(),r.title="Workspace detected"}catch{let n=["Not in a workspace directory","",`Current directory: ${process.cwd()}`,"","This command must be run from within a workspace created with pf new workspace","","To create a new workspace, run:",""," pf new workspace my-platform"].join(`
|
|
248
248
|
`);throw new Error(n)}}},{enabled:t=>t.projectType==="workspace",task:async(t,r)=>{try{let n=k();if(!await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"toggle",message:`\u26A0\uFE0F You are inside an existing workspace (${n}). Create a nested workspace anyway?`,enabled:"Yes",disabled:"No",initial:!1}))throw new Error("Workspace creation cancelled - already inside a workspace");r.title=oe.default.yellow("Warning: Creating nested workspace")}catch(n){if(n.message?.includes("cancelled"))throw n;r.title="No existing workspace detected"}}},{enabled:t=>!!t.projectType,task:async(t,r)=>{let o={"hono-micro":"services/my-hono-service","nest-micro":"services/my-nest-service",workspace:"my-platform"}[t.projectType]||"my-project",s=t.projectType==="workspace"?"\u{1F4E6} Workspace name:":"\u{1F4E6} Service path (e.g., services/my-service):",a=await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"input",message:s,initial:o});t.servicePath=a.trim(),r.title=`Path: ${oe.default.dim(a)}`}},{enabled:t=>!!ht.find(n=>n.value===t.projectType)?.supportsAi&&Ie().valid,task:async(t,r)=>{let n=await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"toggle",message:"Use AI to generate service code?",enabled:"Yes",disabled:"No",initial:!1});t.useAi=n,r.title=n?oe.default.cyan("\u{1F916} AI-powered generation"):"Standard scaffolding"}},{enabled:t=>t.useAi,task:async(t,r)=>{let n=await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"input",message:"Describe what this service should do:"});t.aiDescription=n,r.title=`Description: ${oe.default.dim(n.slice(0,50))}${n.length>50?"...":""}`}},{enabled:t=>{if(!t.servicePath)return!1;let r=g(t.servicePath);return!vt(r)},task:async(t,r)=>{if(!await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"toggle",message:oe.default.bold("\u26A0\uFE0F Overwrite existing directory?"),enabled:"Yes",disabled:"No",initial:!1}))throw new Error("Project creation was canceled by the user.");t.shouldRemoveDir=!0,r.title=oe.default.yellow("Will overwrite existing directory")}},{title:"Confirm creation",enabled:t=>t.projectType!=="workspace",task:async(t,r)=>{if(!await r.prompt(ce.ListrEnquirerPromptAdapter).run({type:"Toggle",initial:!0,message:"\u{1F680} Ready to launch your project?"}))throw new Error("Project creation was canceled by the user.")}}],actions:[],onComplete:async t=>{ht.find(s=>s.value===t.projectType)||e.error(oe.default.red(`Project type ${t.projectType} is not supported.`));let r=e.commands.find(s=>s.name()===t.projectType),n={};t.projectType!=="workspace"&&(n.yes=!0);let o=[];t.servicePath&&o.push("servicePath"),t.shouldRemoveDir&&(n.removeDir=!0),t.useAi&&(n.ai=!0,n.description=t.aiDescription),await ys(r,t,n,o)}});for(let t of ht)e.addCommand(t.command);return e};var ca=require("commander");var le=u(require("chalk"));var Qr=e=>new Promise(t=>setTimeout(t,e)),fe=e=>process.stdout.write(`${e}
|
|
249
|
-
`),Jl=()=>{process.stdout.write("\x1B[?1049l"),process.stdout.write("\x1B[2J"),process.stdout.write("\x1B[3J"),process.stdout.write("\x1B[H"),process.stdout.write("\x1B[?25h"),process.stdout.isTTY&&process.stdout.write("\x1Bc")},aa=()=>({turboProcess:null,isRestarting:!1,isShuttingDown:!1}),ia=async(e,t)=>{let r=
|
|
249
|
+
`),Jl=()=>{process.stdout.write("\x1B[?1049l"),process.stdout.write("\x1B[2J"),process.stdout.write("\x1B[3J"),process.stdout.write("\x1B[H"),process.stdout.write("\x1B[?25h"),process.stdout.isTTY&&process.stdout.write("\x1Bc")},aa=()=>({turboProcess:null,isRestarting:!1,isShuttingDown:!1}),ia=async(e,t)=>{let r=jn(".env.local",t);r.length>0&&(await On(r),await Qr(50)),fe(le.default.cyan("\u{1F525} Starting services...")),fe(le.default.dim(` Command: turbo run ${or} --continue`)),e.isShuttingDown=!1,e.isRestarting=!1,e.turboProcess=Fn("turbo",["run",or,"--continue","--no-daemon"],{cwd:t,envFile:".env.local",onExit:n=>{!e.isRestarting&&!e.isShuttingDown&&(n===0?fe(`
|
|
250
250
|
${le.default.cyan("\u{1F440} Dev mode ready. Waiting for file changes...")}`):(fe(`
|
|
251
251
|
${le.default.yellow("\u26A0\uFE0F A service has crashed")} (exit code: ${n})`),fe(le.default.dim("Check the logs above to see which service failed.")),fe(le.default.dim("Fix the error and save the file to restart automatically."))),fe(le.default.dim("Press Ctrl+C to exit dev mode.")))}})},en=async(e,t=!1)=>{let r=e.turboProcess?.pid;if(r){t?e.isRestarting=!0:e.isShuttingDown=!0;try{try{process.kill(-r,"SIGTERM")}catch{e.turboProcess?.kill("SIGTERM")}await Qr(200);try{process.kill(-r,"SIGKILL")}catch{}await Qr(30)}catch{}e.turboProcess=null,Jl()}};var Kl=300,la=new ca.Command("dev").description("Start development mode with auto-reload").action(async()=>{let e=k(),t=aa(),r=c=>Ze("generate-env",{cwd:c}),n=()=>H({cwd:e,quiet:!0}),o=async()=>{await n(),await r(e),await es()&&await ts(e),await ia(t,e)},s=async()=>{if(!(t.isRestarting||t.isShuttingDown)){t.isRestarting=!0;try{await en(t,!0),await o()}catch{}finally{t.isRestarting=!1}}},a=(()=>{let c=null;return async()=>{t.isRestarting||t.isShuttingDown||(c&&clearTimeout(c),c=setTimeout(()=>s(),Kl))}})(),i=async()=>{await en(t,!1),await rs(),process.exit(0)};await o(),ao(e,a),process.on("SIGINT",i),process.on("SIGTERM",i)});var Ea=require("commander");var pa=require("node:fs"),ma=require("node:path"),Y=u(require("chalk")),da=require("commander");var zl=e=>{if(e)try{return JSON.parse(e)}catch{return}},ql=e=>{if(!e)return;let t={},r=e.split(",").map(n=>n.trim()).filter(Boolean);for(let n of r){let[o,s]=n.split(":").map(a=>a.trim());o&&s&&(t[o]=s)}return Object.keys(t).length>0?t:void 0},Vl=(e,t)=>{if(!t)return;let r=t.startsWith("/")?t:(0,ma.resolve)(e,t);return(0,pa.existsSync)(r)?r:void 0},Zl=async(e,t)=>{let r=[],n=[],o=[];if(kr(e)&&!t.force)n.push("Contract (already exists)");else{let a=vr(e,t.schema);r.push(`Contract: ${a}`)}Ar(e)&&r.push("Export: packages/contracts/src/index.ts");let s=await $t(e);if(s&&r.push(`Mock: ${s}`),t.servicePath){let a=br(e,t.servicePath);a?r.push(`Handler: ${a}`):n.push("Handler (already exists)");let i=wr(t.servicePath,e);i.added?r.push(`Stream: ${i.streamName} added to index.ts`):i.warning&&o.push(i.warning)}return{created:r,skipped:n,warnings:o}},Yl=(e,t,r=[])=>{if(e.length>0){console.log(Y.default.green(`\u2713 Created:
|
|
252
252
|
`));for(let n of e)console.log(Y.default.dim(` ${n}`))}if(t.length>0){console.log(Y.default.yellow(`
|
|
@@ -259,14 +259,14 @@ ${le.default.yellow("\u26A0\uFE0F A service has crashed")} (exit code: ${n})`),
|
|
|
259
259
|
`)),console.log(Y.default.dim(` pf event add ${e} --service services/my-service
|
|
260
260
|
`)))},$h=new da.Command("event:add").description("Add event contract, handler, and mock").argument("<event-type>","Event type (e.g., orders.created)").option("-s, --service <path>","Service path to create handler in (e.g., services/orders)").option("-f, --fields <fields>","Schema fields (e.g., orderId:string,total:number,customerId:string)").option("--schema <json>",`Schema fields as JSON (e.g., '{"orderId":"string","total":"number"}')`).option("--force","Overwrite existing files",!1).action(tn);var fa=require("commander");var ua=require("fs-extra"),ga=require("globby"),pe=require("zod");var Xl=["**/node_modules/**","**/.nats-data/**","**/dist/**","**/build/**","**/.git/**","**/coverage/**"],Ql=pe.z.record(pe.z.string()),ep=pe.z.object({description:pe.z.string().optional(),eventName:pe.z.string(),faker:Ql.optional(),data:pe.z.record(pe.z.any())}),_e=(e=process.cwd())=>(0,ga.globbySync)("**/*.mock.json",{cwd:e,absolute:!0,gitignore:!0,ignore:Xl}).map(r=>{try{let n=(0,ua.readJSONSync)(r,{encoding:"utf8"}),o=ep.safeParse(n);return o.success?{eventName:o.data.eventName,path:r,schema:o.data}:(m.warn(`\u26A0\uFE0F Invalid schema in ${r}`),console.log(o.error.format()),null)}catch{return m.warn(`\u26A0\uFE0F Failed to read or parse ${r}`),null}}).filter(r=>r!==null);var rn=null,ha=async()=>{if(!rn){let{faker:e}=await import("@faker-js/faker");rn=e}return rn},nn=async(e,t)=>{let r=await ha(),o=_e().find(p=>p.eventName===e);if(!o){m.error(`Event "${e}" not found. Use "pf event list" to see available events.`);return}let s=o.schema,a=t.fake?await tp(s):s.data,c={message:{data:Buffer.from(JSON.stringify({...a,type:s.eventName})).toString("base64"),messageId:r.string.uuid(),attributes:{source:"platform-sdk"}}};if(t.print){console.dir(c,{colors:!0});return}let l=await fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)});if(!l.ok){let p=await l.text();throw new Error(`Request failed: ${l.status} \u2013 ${p}`)}m.success("Event sent successfully.")},Oh=new fa.Command("event:http").description("Send via HTTP Pub/Sub endpoint").argument("<eventName>","The name of the event").option("--endpoint <url>","Target HTTP endpoint","http://localhost:3000").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated Pub/Sub event without sending").action(nn),tp=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([r,n])=>{let o=await rp(n);kt(t,r,o)})),t},rp=async e=>{let t=await ha();switch(e){case"uuid":return t.string.uuid();case"email":return t.internet.email();case"string":return t.lorem.word();case"number":return t.number.int();case"boolean":return t.datatype.boolean();case"date":return new Date().toISOString();case"productName":return t.commerce.productName();case"productDescription":return t.commerce.productDescription();case"firstName":return t.person.firstName();case"lastName":return t.person.lastName();case"url":return t.internet.url();case"phoneNumber":return t.phone.number();case"streetAddress":return t.location.streetAddress();case"city":return t.location.city();case"state":return t.location.state();case"country":return t.location.country();case"companyName":return t.company.name();case"zipCode":return t.location.zipCode();case"password":return t.internet.password();default:return null}};var ba=require("commander");var on=require("node:fs"),ya=require("node:path"),sn=require("globby");var np=["**/node_modules/**","**/.nats-data/**","**/dist/**","**/build/**","**/.git/**","**/coverage/**"],op=e=>{let t=e.split("/"),r=t.indexOf("services");return r!==-1&&r+1<t.length?t[r+1]:"unknown"},sp=(e,t)=>{try{let{eventsPath:r}=C(t),o=(0,sn.globbySync)("**/*.ts",{cwd:r,absolute:!0}).map(a=>({file:a,content:(0,on.readFileSync)(a,"utf-8")})).find(({content:a})=>a.includes(`export const ${e}`));if(!o)return null;let s=o.content.match(/type:\s*['"]([^'"]+)['"]/);return s?s[1]:null}catch{return null}},ap=e=>e.replace(/Contract$/,"").replace(/([A-Z])/g,(t,r,n)=>(n>0?".":"")+r.toLowerCase()),ip=(e,t)=>{let r=e.match(/handleEvent\s*\(\s*\{\s*[^}]*type:\s*['"]([^'"]+)['"]/s);if(r)return r[1];let n=e.match(/handleEvent\s*\(\s*['"]([^'"]+)['"]/s);if(n)return n[1];let o=e.match(/import\s+(?:type\s+)?{[^}]*?(\w+Contract)[^}]*?}\s+from/);if(!o)return null;let s=o[1];return sp(s,t)||ap(s)},cp=(e,t)=>{try{let r=(0,on.readFileSync)(e,"utf-8"),n=ip(r,t);return n?{serviceName:op(e),handlerPath:(0,ya.relative)(t,e),eventType:n}:null}catch{return null}},ka=(e=process.cwd())=>(0,sn.globbySync)("services/**/src/events/*.handler.ts",{cwd:e,absolute:!0,gitignore:!0,ignore:np}).map(r=>cp(r,e)).filter(r=>r!==null),va=e=>e.reduce((t,r)=>{let n=t.get(r.eventType)||[];return t.set(r.eventType,[...n,r]),t},new Map);var Ca=u(require("cli-table3"));var xa=(e,t)=>{let r=t.get(e)||[],n=[...new Set(r.map(o=>o.serviceName))];return n.length>0?n.join(", "):"-"};var wa=(e,t)=>{let r=new Ca.default({head:["name","description","consumers"],style:{head:["dim","bold"],compact:!0}});for(let{eventName:n,schema:o}of e)r.push([n,o.description||"-",xa(n,t)]);return r.toString()};var an=()=>{let e=_e();if(e.length===0){m.error("No event schemas found.");return}let t=ka(),r=va(t),n=wa(e,r);console.log(n)},zh=new ba.Command("event:list").description("List all available event mocks").action(an);var Sa=require("node:path"),Pa=require("commander");var dp={},cn=null,ln=null,Ta=async()=>{if(!cn){let{faker:e}=await import("@faker-js/faker");cn=e}return cn},lp=async()=>{if(!ln)try{let{createJiti:e}=await import("jiti"),t=e(dp.url),r=k(),n=C(r),o=(0,Sa.join)(n.packagePath,"node_modules","@crossdelta","cloudevents");ln=(await t.import(o)).publish}catch{throw new Error(`@crossdelta/cloudevents is required for event:publish.
|
|
261
261
|
Install it in your contracts package with: cd packages/contracts && bun add @crossdelta/cloudevents`)}return ln},pn=async(e,t)=>{let r=await Ta(),o=_e().find(i=>i.eventName===e||i.path.includes(`${e}.mock.json`));if(!o){m.error(`Event "${e}" not found. Use "pf event list" to see available events.`);return}let s=o.schema,a=t.fake?await pp(s):s.data;if(t.print){console.log(`
|
|
262
|
-
\u{1F4E6} Event Type:`,s.eventName),console.log("\u{1F4C4} Payload:"),console.dir(a,{colors:!0,depth:null});return}try{let i=await lp();if(!i)throw new Error("Failed to load publish function from cloudevents");await i(s.eventName,a,{source:"platform-sdk-cli",subject:r.string.uuid()}),m.success(`Event "${s.eventName}" published successfully to NATS JetStream.`),await new Promise(c=>setTimeout(c,100)),process.exit(0)}catch(i){m.error(`Failed to publish event: ${i instanceof Error?i.message:String(i)}`),m.info("Make sure NATS is running and NATS_URL is configured."),process.exit(1)}},Xh=new Pa.Command("event:publish").description("Publish to NATS JetStream").argument("<eventName>","The name of the event (e.g., order-created)").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated event data without publishing").action(pn),pp=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([r,n])=>{let o=await mp(n);kt(t,r,o)})),t},mp=async e=>{let t=await Ta();switch(e.toLowerCase()){case"uuid":return t.string.uuid();case"email":return t.internet.email();case"firstname":return t.person.firstName();case"lastname":return t.person.lastName();case"name":return t.person.fullName();case"url":return t.internet.url();case"phone":return t.phone.number();case"date":return t.date.recent().toISOString();case"boolean":return t.datatype.boolean();case"number":return t.number.int({min:1,max:1e3});case"string":return t.lorem.word();case"text":return t.lorem.sentence();default:return e}};var yt=new Ea.Command("event").description("Event management commands");yt.command("add").description("Add event contract, handler, and mock").argument("<event-type>","Event type (e.g., orders.created)").option("-s, --service <path>","Service path to create handler in (e.g., services/orders)").option("--schema <fields>",`Schema fields as JSON (e.g., '{"orderId":"string","total":"number"}')`).option("--force","Overwrite existing files",!1).action(tn);yt.command("list").description("List all available event mocks").action(an);yt.command("publish").description("Publish to NATS JetStream").argument("<eventName>","Event name to publish").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated event data without publishing").action(pn);yt.command("http").description("Send via HTTP Pub/Sub endpoint").argument("<eventName>","Event name to send").option("--endpoint <url>","Target HTTP endpoint","http://localhost:3000").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated Pub/Sub event without sending").action(nn);var Aa=yt;var un=u(require("chalk")),
|
|
262
|
+
\u{1F4E6} Event Type:`,s.eventName),console.log("\u{1F4C4} Payload:"),console.dir(a,{colors:!0,depth:null});return}try{let i=await lp();if(!i)throw new Error("Failed to load publish function from cloudevents");await i(s.eventName,a,{source:"platform-sdk-cli",subject:r.string.uuid()}),m.success(`Event "${s.eventName}" published successfully to NATS JetStream.`),await new Promise(c=>setTimeout(c,100)),process.exit(0)}catch(i){m.error(`Failed to publish event: ${i instanceof Error?i.message:String(i)}`),m.info("Make sure NATS is running and NATS_URL is configured."),process.exit(1)}},Xh=new Pa.Command("event:publish").description("Publish to NATS JetStream").argument("<eventName>","The name of the event (e.g., order-created)").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated event data without publishing").action(pn),pp=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([r,n])=>{let o=await mp(n);kt(t,r,o)})),t},mp=async e=>{let t=await Ta();switch(e.toLowerCase()){case"uuid":return t.string.uuid();case"email":return t.internet.email();case"firstname":return t.person.firstName();case"lastname":return t.person.lastName();case"name":return t.person.fullName();case"url":return t.internet.url();case"phone":return t.phone.number();case"date":return t.date.recent().toISOString();case"boolean":return t.datatype.boolean();case"number":return t.number.int({min:1,max:1e3});case"string":return t.lorem.word();case"text":return t.lorem.sentence();default:return e}};var yt=new Ea.Command("event").description("Event management commands");yt.command("add").description("Add event contract, handler, and mock").argument("<event-type>","Event type (e.g., orders.created)").option("-s, --service <path>","Service path to create handler in (e.g., services/orders)").option("--schema <fields>",`Schema fields as JSON (e.g., '{"orderId":"string","total":"number"}')`).option("--force","Overwrite existing files",!1).action(tn);yt.command("list").description("List all available event mocks").action(an);yt.command("publish").description("Publish to NATS JetStream").argument("<eventName>","Event name to publish").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated event data without publishing").action(pn);yt.command("http").description("Send via HTTP Pub/Sub endpoint").argument("<eventName>","Event name to send").option("--endpoint <url>","Target HTTP endpoint","http://localhost:3000").option("--fake","Apply fake values to fakeable fields").option("--print","Print the generated Pub/Sub event without sending").action(nn);var Aa=yt;var un=u(require("chalk")),Ra=require("commander");var Ge=require("node:fs"),dn=u(require("node:path")),rr=u(require("chalk")),Ia=require("commander"),$a=u(require("os"));var{name:up,publishConfig:gp}=U,fp=gp?.registry,hp=up?.split("/")[0],iy=new Ia.Command("token:set").description(rr.default.bold("Set a registry auth token in a .npmrc file")).argument("<token>","Authentication token (e.g. GitHub or npm token)").option("--scope <scope>","Package scope (e.g. @my-workspace)",hp).option("--registry <registry>","Registry URL",fp).option("--local","Write token to a local .npmrc in the current directory",!1).option("--force","Force overwrite existing token if already present",!1).action((e,t)=>Na(e,t.scope||"",t.registry||"",t.local,t.force)).addHelpText("after",()=>`${rr.default.cyan(`
|
|
263
263
|
Example:`)}
|
|
264
264
|
${rr.default.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
265
265
|
`),yp=e=>e?dn.default.join(process.cwd(),".npmrc"):dn.default.join($a.default.homedir(),".npmrc"),kp=(e,t,r)=>{let n=new URL(r).host;return t?`${t}:registry=https://${n}
|
|
266
266
|
//${n}/:_authToken=${e}`:`//${n}/:_authToken=${e}`},vp=e=>(0,Ge.existsSync)(e)?(0,Ge.readFileSync)(e,"utf8"):"",mn=(e,t)=>(0,Ge.writeFileSync)(e,t),Na=(e,t,r,n=!1,o=!1)=>{let s=yp(n),a=kp(e,t,r),i=new URL(r).host,c=vp(s),l=new RegExp(`//${i}/:_authToken=\\S+`);if(!c){mn(s,`${a}
|
|
267
267
|
`),m.success(`Created new .npmrc and set token for ${i}`);return}if(l.test(c)){if(!o){m.warn(`Token for ${i} already exists in ${s}. Use --force to overwrite.`);return}c=c.replace(l,a),mn(s,c),m.success(`Overwrote existing token for ${i} in ${s}`);return}c+=`
|
|
268
268
|
${a}
|
|
269
|
-
`,mn(s,c),m.success(`Appended token for ${i} to ${s}`)},
|
|
269
|
+
`,mn(s,c),m.success(`Appended token for ${i} to ${s}`)},ja=(e,t)=>Na(e,t.scope||"",t.registry||"",t.local,t.force);var{name:xp,publishConfig:Cp}=U,wp=Cp?.registry,bp=xp?.split("/")[0],Ma=new Ra.Command("token").description("Token management commands");Ma.command("set").description("Set a registry auth token in a .npmrc file").argument("<token>","Authentication token (e.g. GitHub or npm token)").option("--scope <scope>","Package scope (e.g. @my-workspace)",bp).option("--registry <registry>","Registry URL",wp).option("--local","Write token to a local .npmrc in the current directory",!1).option("--force","Force overwrite existing token if already present",!1).action(ja).addHelpText("after",()=>`${un.default.cyan(`
|
|
270
270
|
Example:`)}
|
|
271
271
|
${un.default.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
272
272
|
`);var Fa=Ma;var X=require("@inquirer/prompts"),y=u(require("chalk")),Da=require("commander");var Sp=[/embed/i,/whisper/i,/tts/i,/dall-e/i,/davinci/i,/babbage/i,/curie/i,/ada(?!-)/i,/moderation/i,/realtime/i,/audio/i,/transcription/i,/search/i],Pp=async(e,t,r=1e4)=>{let n=new AbortController,o=setTimeout(()=>n.abort(),r);try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(o)}},Tp=e=>e.replace(/-(\d{8})$/," ($1)").replace(/^claude-/,"Claude ").replace(/^gpt-/,"GPT-").replace(/-/g," ").replace(/(\d)\.(\d)/g,"$1.$2").replace(/\s+/g," ").split(" ").map(t=>/^\d/.test(t)||/^\(\d+\)$/.test(t)?t:t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join(" ").trim(),Ep=async(e,t)=>{let r=Xe(e),n=await Pp(r.modelsApiUrl,{headers:r.buildHeaders(t)});if(!n.ok)throw new Error(`${r.name} API error: ${n.status}`);let o=await n.json(),s=r.parseModelsResponse(o);if(!Array.isArray(s)||s.length===0)throw new Error(`No models returned from ${r.name} API`);let a=s.filter(i=>{let c=r.modelFilters.some(p=>p.test(i.id)),l=Sp.some(p=>p.test(i.id));return c&&!l}).sort((i,c)=>{let l=typeof i.created=="number"?i.created:new Date(i.created).getTime();return(typeof c.created=="number"?c.created:new Date(c.created).getTime())-l}).map(i=>({name:Tp(i.id),value:i.id}));if(a.length===0)throw new Error(`No chat models found from ${r.name} API`);return a};async function Oa(e,t){if(!t)throw new Error("API key is required to fetch available models");return{models:await Ep(e,t),fromApi:!0}}function Ap(){if(!Qe())return null;try{let e=Pt();return console.log(y.default.dim(`Found existing configuration at ${ue}
|
|
@@ -277,9 +277,9 @@ ${un.default.bold("pf token set <token> --scope @my-workspace --registry https:/
|
|
|
277
277
|
\u2705 AI configuration saved successfully!
|
|
278
278
|
`)),console.log(y.default.dim(`Configuration file: ${ue}`)),console.log(y.default.dim("API Key: Stored securely in system keychain")),console.log(y.default.dim(`Provider: ${e.provider}`)),console.log(y.default.dim(`Model: ${e.model}`)),console.log(y.default.dim(`API Key: ${Ba(t)}
|
|
279
279
|
`)),console.log(y.default.cyan("You can now use AI-powered service generation:")),console.log(y.default.dim(` pf new hono-micro services/my-service --ai
|
|
280
|
-
`))}async function
|
|
280
|
+
`))}async function jp(e){let t=await St(e);if(t)return t;let r=Xe(e);return process.env[r.defaultApiKeyEnvVar]??null}async function Rp(){console.log(y.default.cyan.bold(`
|
|
281
281
|
\u{1F916} AI Configuration Setup
|
|
282
|
-
`));let e=Ap();try{let t=await(0,X.select)({message:"Select AI provider:",choices:Qn(),default:e?.provider??fr.provider}),r=Xe(t),n,o=await
|
|
282
|
+
`));let e=Ap();try{let t=await(0,X.select)({message:"Select AI provider:",choices:Qn(),default:e?.provider??fr.provider}),r=Xe(t),n,o=await jp(t);o&&(console.log(y.default.green(`
|
|
283
283
|
\u2713 Found existing API key: ${Ba(o)}`)),await(0,X.confirm)({message:"Use this existing API key?",default:!0})&&(n=o)),n||(n=await Ip(r.name,r.apiKeyUrl)),console.log(y.default.dim(`
|
|
284
284
|
Fetching available models...`));let s;try{s=(await Oa(t,n)).models,console.log(y.default.green(`\u2713 Loaded ${s.length} models from ${r.name} API
|
|
285
285
|
`))}catch(c){console.error(y.default.red(`
|
|
@@ -291,7 +291,7 @@ Setup cancelled.
|
|
|
291
291
|
Examples:
|
|
292
292
|
# Configure AI provider (OpenAI, Anthropic)
|
|
293
293
|
$ pf setup --ai
|
|
294
|
-
`).action(async e=>{if(e.ai){await
|
|
294
|
+
`).action(async e=>{if(e.ai){await Rp();return}console.log(y.default.cyan.bold(`
|
|
295
295
|
\u2699\uFE0F Platform Setup
|
|
296
296
|
`)),console.log(`Available setup options:
|
|
297
297
|
`),console.log(y.default.dim(" --ai Configure AI provider for code generation")),console.log(),console.log(y.default.dim("Example: pf setup --ai")),console.log()});var Ha=require("node:fs"),La=require("node:path"),Ue=u(require("chalk"));var Mp=(e,t)=>t.some(r=>r.name()===e),Fp=(e,t)=>t.pf?.commands?.[e]??null,Op=(e,t)=>!!t.scripts?.[e],Dp=(e,t)=>t.cwd?(0,La.join)(e,t.cwd):e,Bp=(e,t)=>t.command||e,Hp=(e,t,r,n)=>{let o=Dp(n,r),s=Bp(e,r);if(r.cwd&&!(0,Ha.existsSync)(o))return console.error(Ue.default.red(`
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
// Type Checking
|
|
5
|
+
"strict": true,
|
|
6
|
+
"noUncheckedIndexedAccess": true,
|
|
7
|
+
"noImplicitOverride": true,
|
|
8
|
+
"noFallthroughCasesInSwitch": true,
|
|
9
|
+
|
|
10
|
+
// Modules
|
|
11
|
+
"module": "ESNext",
|
|
12
|
+
"moduleResolution": "Bundler",
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"allowImportingTsExtensions": true,
|
|
15
|
+
"verbatimModuleSyntax": true,
|
|
16
|
+
|
|
17
|
+
// Emit
|
|
18
|
+
"noEmit": true,
|
|
19
|
+
"sourceMap": true,
|
|
20
|
+
|
|
21
|
+
// Interop Constraints
|
|
22
|
+
"isolatedModules": true,
|
|
23
|
+
"esModuleInterop": true,
|
|
24
|
+
"allowSyntheticDefaultImports": true,
|
|
25
|
+
"forceConsistentCasingInFileNames": true,
|
|
26
|
+
"skipLibCheck": true,
|
|
27
|
+
|
|
28
|
+
// Language and Environment
|
|
29
|
+
"target": "ES2022",
|
|
30
|
+
"lib": ["ES2022"],
|
|
31
|
+
"useDefineForClassFields": true,
|
|
32
|
+
|
|
33
|
+
// Projects
|
|
34
|
+
"incremental": true
|
|
35
|
+
},
|
|
36
|
+
"exclude": [
|
|
37
|
+
"node_modules",
|
|
38
|
+
"dist",
|
|
39
|
+
"build",
|
|
40
|
+
"coverage",
|
|
41
|
+
".turbo",
|
|
42
|
+
"tmp"
|
|
43
|
+
]
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossdelta/platform-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "Platform toolkit for event-driven microservices — keeping code and infrastructure in lockstep.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
"@ai-sdk/anthropic": "^2.0.53",
|
|
98
98
|
"@ai-sdk/openai": "^2.0.79",
|
|
99
99
|
"@angular-devkit/core": "^21.0.0",
|
|
100
|
+
"@crossdelta/cloudevents": "0.6.0",
|
|
100
101
|
"@faker-js/faker": "^9.8.0",
|
|
101
102
|
"@inquirer/prompts": "^7.5.0",
|
|
102
103
|
"@listr2/prompt-adapter-enquirer": "^2.0.15",
|
|
@@ -121,8 +122,7 @@
|
|
|
121
122
|
"zod": "^3.24.3"
|
|
122
123
|
},
|
|
123
124
|
"peerDependencies": {
|
|
124
|
-
"@crossdelta/
|
|
125
|
-
"@crossdelta/infrastructure": "*",
|
|
125
|
+
"@crossdelta/infrastructure": "0.5.3",
|
|
126
126
|
"@nestjs/schematics": "^11.0.5",
|
|
127
127
|
"turbo": "^2.0.0"
|
|
128
128
|
},
|