@crossdelta/platform-sdk 0.17.1 → 0.17.3
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/README.md +21 -1
- package/bin/cli.js +246 -135
- package/bin/docs/generators/nest.md +1 -1
- package/bin/docs/generators/service.md +19 -15
- package/bin/templates/workspace/infra/package.json.hbs +1 -1
- package/bin/templates/workspace/packages/contracts/README.md.hbs +5 -5
- package/bin/templates/workspace/packages/contracts/package.json.hbs +1 -1
- package/package.json +2 -2
package/bin/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var
|
|
3
|
-
`)}function
|
|
2
|
+
"use strict";var $i=Object.create;var Ir=Object.defineProperty;var Ei=Object.getOwnPropertyDescriptor;var Ai=Object.getOwnPropertyNames;var Ii=Object.getPrototypeOf,Ni=Object.prototype.hasOwnProperty;var Ri=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Ai(t))!Ni.call(e,o)&&o!==n&&Ir(e,o,{get:()=>t[o],enumerable:!(r=Ei(t,o))||r.enumerable});return e};var u=(e,t,n)=>(n=e!=null?$i(Ii(e)):{},Ri(t||!e||!e.__esModule?Ir(n,"default",{value:e,enumerable:!0}):n,e));var vi=require("node:process"),ye=u(require("chalk")),Ci=require("commander"),xi=u(require("terminal-link"));var io=u(require("chalk")),co=require("commander");var me=require("node:fs"),E=require("node:path"),de=require("fs-extra");var Nr=["bun.lock","bun.lockb","package-lock.json","yarn.lock","pnpm-lock.yaml"],gn="start:dev";var Ve=u(require("chalk"));function fn(e,t){if(e.length===0)return"No entries to display.";let n=t?.title||"Benchmark Results",r=t?.footer||"",o=t?.maxBarWidth||50,s=t?.unit||"",a=Math.max(...e.map(c=>c.value)),i=[];i.push(""),i.push(n),i.push("");for(let c of e){let l=ji(c.barColor??t?.barColor),p=Mi(c,a,o,l,s,t?.labelColor);i.push(p)}return r&&(i.push(""),i.push(r)),i.join(`
|
|
3
|
+
`)}function ji(e){return e?Ve.default[e]("\u2587"):"\u2587"}function Mi(e,t,n,r,o,s){let a=Math.round(e.value/t*n),i=e.barColor?Ve.default[e.barColor](r.repeat(a)):r.repeat(a),c=e.color??s;return`${Ve.default.bold(c?Ve.default[c](e.label.padEnd(12)):e.label.padEnd(12))} ${i} ${e.value.toLocaleString()}${o?` ${o}`:""}`}var hn=u(require("chalk")),jr=require("commander"),yn=require("listr2");var Ze=u(require("chalk")),m={logs:[],breakLine:()=>(console.log(),m),success:(e,...t)=>(console.log(Ze.default.green(`\u2714 ${e}`),...t),m),info:(e,...t)=>(console.log(Ze.default.cyan(`\u{1F6C8} ${e}`),...t),m),warn:(e,...t)=>(console.warn(Ze.default.yellow(`\u26A0\uFE0E ${e}`),...t),m),error:(e,...t)=>(console.error(Ze.default.red(`\u2716 ${e}`),...t),m),log:(e,...t)=>(console.log(e,...t),m.logs.push({message:e,context:t.join()}),m),getStoredLogs:e=>e?m.logs.filter(t=>t.context?.includes(e)):m.logs,storeLog:(e,t)=>m.logs.push({message:e,context:t})};function oe(e){let t=new jr.Command(e.name).description(e.description).showHelpAfterError();return e.arguments?.map(([n,r])=>t.argument(n,r)),e.options?.map(([n,r])=>t.option(n,r)),e.exampleUsage&&t.addHelpText("after",()=>`${hn.default.cyan.bold(`
|
|
4
4
|
Example:`)}
|
|
5
|
-
${
|
|
6
|
-
`),e.additionalInfo&&t.addHelpText("after",()=>(typeof e.additionalInfo=="function"?e.additionalInfo():e.additionalInfo)??""),t.action(async(...
|
|
5
|
+
${hn.default.bold(e.exampleUsage)}
|
|
6
|
+
`),e.additionalInfo&&t.addHelpText("after",()=>(typeof e.additionalInfo=="function"?e.additionalInfo():e.additionalInfo)??""),t.action(async(...n)=>{try{let r=n.at(-1),o=r.args,s=r.opts(),a=Fi(e.arguments??[],o);if(e.shouldSkipWorkflow?.(a,s)){await e.onSkipWorkflow?.(a,s);return}let i=await e.buildContext(a,s);e.prompts?.length&&await new yn.Listr(Rr(e.prompts,i),{rendererOptions:{lazy:!0,showErrorMessage:!1}}).run(i),await new yn.Listr(Rr(e.actions,i),{rendererOptions:{lazy:!1,showErrorMessage:!1,clearOutput:!0}}).run(i),await e.onComplete?.(i)}catch(r){let o=r;m.error(o.message)}}),t}function Fi(e,t){let n={};return e.forEach(([r],o)=>{let s=r.replace(/[<>[\]]/g,"");n[s]=t[o]}),n}function Rr(e,t){return e.map(n=>typeof n=="function"?n(t):n)}function St(e,t,n){let r=t.split("."),o=e;for(;r.length>1;){let s=r.shift();s in o||(o[s]={}),o=o[s]}o[r[0]]=n}var Mr=require("execa");function Ye(e){try{return(0,Mr.execaSync)(e,["--version"]),!0}catch{return!1}}var ke=require("node:path"),Fr=require("fs-extra"),Or=require("package-up"),Dr=require("rimraf"),g=e=>(0,ke.join)(process.cwd(),e),Pt=e=>{try{return(0,Fr.readdirSync)(e).length===0}catch{return!0}};function _r(){let e=(0,Or.packageUpSync)({cwd:(0,ke.dirname)(__filename)});if(!e)throw new Error("Could not find package.json");return(0,ke.dirname)(e)}var Br=e=>(0,Dr.rimraf)(e);var Hr=u(require("chalk"));async function S(e,t){let n=Date.now(),r=e.title,o=()=>Math.floor((Date.now()-n)/1e3),s=setInterval(()=>{o()>1&&(e.title=`${r} (${o()}s)`)},1e3);try{return await t(o)}finally{clearInterval(s)}}async function Tt(e,t,n){for(let r=0;r<t.length;r++){let o=t[r];e.output=Hr.default.dim(`[${r+1}/${t.length}] ${o.title}`),await o.fn(n??{},e)}}var Xe={services:"services",apps:"apps",packages:"packages",contracts:"packages/contracts"},Oi={docs:{base:["service.md"],frameworks:{}},serviceTypes:{hono:{commandType:"hono-micro",entryPoint:"src/index.ts",skipFiles:[]},nest:{commandType:"nest-micro",entryPoint:"src/main.ts",skipFiles:[]}}},kn=e=>{if(!(0,me.existsSync)(e))return null;try{return JSON.parse((0,me.readFileSync)(e,"utf-8"))}catch{return null}},$t=(e,t)=>typeof e=="string"?e:typeof e=="object"&&e!==null&&"path"in e?e.path:t,Di=e=>e.split("/").pop()||"workspace",_i=e=>{let t=e.slice(0,e.lastIndexOf("/"));return t===e?null:t},Lr=e=>e.split("."),Bi=(e,t)=>{if(!e.workspaces)return!1;if(e.pf||(0,me.existsSync)((0,E.join)(t,"turbo.json")))return!0;let n=Nr.some(o=>(0,me.existsSync)((0,E.join)(t,o))),r=(0,me.existsSync)((0,E.join)(t,"infra"));return n&&r},Hi=e=>{let t=kn((0,E.join)(e,"package.json"));return t?Bi(t,e):!1},Wr=e=>{let t=e;for(;t;){if(Hi(t))return t;t=_i(t)}return null},Gr=()=>Wr(process.cwd())!==null,y=()=>{let e=Wr(process.cwd());if(!e)throw new Error(`
|
|
7
7
|
\x1B[31m\u2716\x1B[0m Not in a workspace directory
|
|
8
8
|
|
|
9
9
|
Current directory: ${process.cwd()}
|
|
@@ -13,85 +13,85 @@ This command must be run from within a workspace created with \x1B[36mpf new wor
|
|
|
13
13
|
To create a new workspace, run:
|
|
14
14
|
|
|
15
15
|
\x1B[36mpf new workspace my-platform\x1B[0m
|
|
16
|
-
`);
|
|
17
|
-
`,encoding:"utf-8"})}
|
|
18
|
-
`).filter(Boolean);for(let s of o)try{process.kill(Number.parseInt(s,10),"SIGKILL")}catch{}}catch{}}var
|
|
19
|
-
Running command: ${a} ${[...i,e,...
|
|
20
|
-
`),(0,
|
|
21
|
-
createdAt: z.string(),`:Object.entries(e).map(([t,
|
|
22
|
-
`),
|
|
16
|
+
`);return e},ve=e=>{let t=e??y();return kn((0,E.join)(t,"package.json"))},D=e=>{let t=ve(e);if(!t?.pf?.paths)return Xe;let{paths:n}=t.pf;return{services:$t(n.services,Xe.services),apps:$t(n.apps,Xe.apps),packages:$t(n.packages,Xe.packages),contracts:$t(n.contracts,Xe.contracts)}},C=e=>{let t=e??y(),n=D(t),r=(0,E.join)(t,n.contracts);return{packagePath:r,eventsPath:(0,E.join)(r,"src","events"),indexPath:(0,E.join)(r,"src","index.ts"),relativePath:n.contracts}},Ce=()=>{let e=y(),t=kn((0,E.join)(e,"package.json")),n=`@${Di(e)}`;return t?.name?t.name.startsWith("@")?t.name.split("/")[0]:`@${t.name}`:n},Li=(e,t)=>{let n=Lr(t),r=e;for(let o of n){if(r===null||typeof r!="object"||!(o in r))return;r=r[o]}return r},Wi=(e,t,n)=>{let r=Lr(t),o=r[r.length-1],s=e;for(let a of r.slice(0,-1))(!(a in s)||typeof s[a]!="object"||s[a]===null)&&(s[a]={}),s=s[a];s[o]=n},Ur=(e,t=process.cwd())=>{let n=(0,de.readJsonSync)((0,E.join)(t,"package.json"));return Li(n,e)},X=(e,t,n=process.cwd())=>{let r=(0,E.join)(n,"package.json"),o=(0,de.readJsonSync)(r);Wi(o,e,t),(0,de.writeJsonSync)(r,o,{spaces:2,EOL:`
|
|
17
|
+
`,encoding:"utf-8"})},Et=e=>{let t=_r();return(0,de.readJSONSync)((0,E.resolve)(t,e),{encoding:"utf-8"})},G=Et("package.json"),Qe=()=>G.generatorConfig??Oi;var Qr=require("node:fs"),eo=require("node:path"),wn=require("node:process"),to=require("execa");var xn=require("node:child_process"),Vr=require("node:path"),Zr=require("execa");var Jr=require("node:fs"),Kr=require("node:path"),zr=require("dotenv"),vn=(e,t)=>{let n=(0,Kr.resolve)(t,e);return(0,Jr.existsSync)(n)?(0,zr.config)({path:n,processEnv:{}}).parsed||{}:{}},qr=(e,t)=>{let n=vn(e,t),r=[];for(let[o,s]of Object.entries(n))if(o.endsWith("_PORT")&&s){let a=Number.parseInt(s,10);!Number.isNaN(a)&&a>0&&r.push(a)}return r};var Cn={...process.env,NODE_NO_WARNINGS:"1"},Gi=(e,t,n)=>e?"pipe":t||n?["ignore","pipe","pipe"]:"inherit",Ui=(e,t,n)=>e?{...Cn,...e}:t||n?{...Cn,CI:"true"}:{...Cn},Ji=e=>e.includes("EEXIST")||e.includes("failed to link package");async function se(e,t,{cwd:n=process.cwd(),task:r,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,Zr.execa)(e,t,{cwd:n,stdio:Gi(a,r,i),all:r||i?!0:void 0,shell:o??!0,env:Ui(c,r,i)});l.all&&l.all.on("data",p=>{let d=p.toString().trim();r?(r.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(Ji(p))return;throw new Error(Ki(p))}}var Ki=e=>{let t=e.match(/error: (.+)/);return t?t[1].trim():e};function Yr(e,t,n={}){let{cwd:r=process.cwd(),envFile:o,detached:s=!0,pipeStdout:a=!1,onStdout:i,onStderr:c,onExit:l}=n,p=o?vn(o,r):{},d=(0,Vr.resolve)(r,"node_modules",".bin"),k=process.env.PATH||"",I=`${d}:${k}`,qe={...process.env,...p,PATH:I,FORCE_COLOR:"1"},F=(0,xn.spawn)(e,t,{cwd:r,env:qe,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 At(e,t,n={}){let{cwd:r=process.cwd()}=n;(0,xn.spawn)(e,t,{cwd:r,stdio:"inherit",shell:!0}).on("exit",s=>process.exit(s||0))}async function Xr(e){let{execSync:t}=await import("node:child_process");for(let n of e)try{let o=t(`lsof -ti:${n}`,{encoding:"utf8",stdio:"pipe"}).trim().split(`
|
|
18
|
+
`).filter(Boolean);for(let s of o)try{process.kill(Number.parseInt(s,10),"SIGKILL")}catch{}}catch{}}var It=e=>Ye(e);function bn(e=process.cwd()){let t=n=>(0,Qr.existsSync)((0,eo.join)(e,n));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 x(e){return bn(e)??Sn()}function Sn(){return It("bun")?"bun":It("pnpm")?"pnpm":It("yarn")?"yarn":"npm"}function no(){return["bun","pnpm","yarn","npm"].filter(It)}async function _(e,t){let n=qi(e,t),{mergedOptions:r,packages:o}=n,{cwd:s=process.cwd(),flags:a=[],task:i,quiet:c}=r,l=r.packageManager??x(),p=[],d=Array.isArray(o)?o:[o];l==="bun"&&(d=d.map(I=>I.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 k=d.length?l==="npm"?["install",...a,...p,...d]:["add",...a,...p,...d]:["install",...a,...p];await se(l,k,{cwd:s,task:i,quiet:c})}async function ro(e){let t=["-g"],n=[...e.flags??[],...t];await _({...e,flags:n,packageManager:e.packageManager??x()})}function oo(e,t,n){let{args:r,mergedOptions:o}=ao(t??[],n),s=o.manager??x(),{command:a,args:i}=so(s);console.log(`
|
|
19
|
+
Running command: ${a} ${[...i,e,...r].join(" ")}
|
|
20
|
+
`),(0,to.execaSync)(a,[...i,e,...r],{cwd:o.cwd??(0,wn.cwd)(),stdio:"inherit",preferLocal:!0})}async function Q(e,t,n){let{args:r,mergedOptions:o}=ao(t??[],n),s=o.manager??x(),{command:a,args:i}=so(s);await se(a,[...i,e,...r],o)}async function et(e,t){let{script:n,mergedOptions:r}=Vi(e,t),o=r.packageManager??x();await se(o,["run",n,...r.args??[]],{cwd:r.cwd??(0,wn.cwd)(),task:r.task})}function so(e){let n={bun:"bunx",pnpm:"npx",yarn:"npx",npm:"npx"}[e];if(!n)throw new Error(`No executor found for the detected package manager: ${e}`);let[r,...o]=n.split(" ");return{command:r,args:o}}function qi(e,t){return Array.isArray(e)?{packages:e,mergedOptions:{...t,packages:e}}:{packages:e.packages??[],mergedOptions:e}}function ao(e,t){return Array.isArray(e)?{args:e,mergedOptions:t??{}}:{args:[],mergedOptions:e}}function Vi(e,t){return typeof e=="string"?{script:e,mergedOptions:t??{}}:{script:e.script,mergedOptions:e}}var Zi=e=>e==="yarn"?["npm","audit"]:["audit"],lo=new co.Command("audit").description("Run security audit on dependencies").allowUnknownOption(!0).action((e,t)=>{let n=y(),r=x(),o=Zi(r),s=t.args||[];console.log(io.default.dim(`Running ${r} ${[...o,...s].join(" ")}`)),At(r,[...o,...s],{cwd:n})});var ie=require("@listr2/prompt-adapter-enquirer"),re=u(require("chalk"));var we=require("node:fs"),yo=require("node:os"),ko=require("node:path");var ae=require("node:crypto"),xe=require("node:fs"),ue=require("node:os"),po=require("node:path"),Pn=(0,po.join)((0,ue.homedir)(),".platform-sdk-keys"),mo="aes-256-gcm",uo=()=>{let e=`${(0,ue.hostname)()}:${(0,ue.userInfo)().username}:${(0,ue.homedir)()}`;return(0,ae.createHash)("sha256").update(e).digest()},go=()=>{if(!(0,xe.existsSync)(Pn))return{};try{return JSON.parse((0,xe.readFileSync)(Pn,"utf-8"))}catch{return{}}},Yi=e=>{(0,xe.writeFileSync)(Pn,JSON.stringify(e,null,2),{mode:384})},Xi=e=>{let t=uo(),n=(0,ae.randomBytes)(16),r=(0,ae.createCipheriv)(mo,t,n),o=r.update(e,"utf8","hex");return o+=r.final("hex"),{iv:n.toString("hex"),tag:r.getAuthTag().toString("hex"),data:o}},Qi=e=>{let t=uo(),n=Buffer.from(e.iv,"hex"),r=Buffer.from(e.tag,"hex"),o=(0,ae.createDecipheriv)(mo,t,n);o.setAuthTag(r);let s=o.update(e.data,"hex","utf8");return s+=o.final("utf8"),s};async function fo(e,t){let n=go();n[e]=Xi(t),Yi(n)}async function Nt(e){let n=go()[e];if(!n)return null;try{return Qi(n)}catch{return null}}var tt={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(n=>({id:n.id,created:new Date(n.created_at).getTime()})),modelFilters:[/^claude-/]}};function ho(){return Object.entries(tt).map(([e,t])=>({name:t.name,value:e}))}function nt(e){let t=tt[e];if(!t)throw new Error(`Unknown AI provider: ${e}`);return t}var ge=(0,ko.join)((0,yo.homedir)(),".platform-sdk-ai.json"),ec=()=>{let e="anthropic",t=tt[e];return{provider:e,model:t.defaultModel}},Tn=ec();function rt(){return(0,we.existsSync)(ge)}function Rt(){if(!rt())throw new Error("AI configuration not found. Please run 'pf ai:setup' to configure your AI provider.");try{let e=(0,we.readFileSync)(ge,"utf-8"),t=JSON.parse(e);return{...Tn,...t}}catch{throw new Error(`Failed to load AI configuration from ${ge}. Please run 'pf setup --ai' again.`)}}function vo(e){let t=JSON.stringify(e,null,2);(0,we.writeFileSync)(ge,t,"utf-8")}async function Co(e,t){await fo(e,t)}async function xo(e){let t=await Nt(e.provider);if(t)return t;let n=tt[e.provider],r=process.env[n.defaultApiKeyEnvVar];if(r)return r;throw new Error("API key not found. Please run 'pf setup --ai' to configure your API key.")}var tc=async(e,t,n,r)=>{let{createOpenAI:o}=await import("@ai-sdk/openai"),s=o({apiKey:n});if(r.onToken){let{streamText:c}=await import("ai"),l=c({model:s(t),prompt:e,system:r.system,maxOutputTokens:r.maxTokens,temperature:r.temperature}),p="";for await(let d of(await l).textStream)p+=d,r.onToken(d);return p}let{generateText:a}=await import("ai"),{text:i}=await a({model:s(t),prompt:e,system:r.system,maxOutputTokens:r.maxTokens,temperature:r.temperature});return i},nc=async(e,t,n,r)=>{let{createAnthropic:o}=await import("@ai-sdk/anthropic"),s=o({apiKey:n});if(r.onToken){let{streamText:c}=await import("ai"),l=c({model:s(t),prompt:e,system:r.system,maxOutputTokens:r.maxTokens,temperature:r.temperature}),p="";for await(let d of(await l).textStream)p+=d,r.onToken(d);return p}let{generateText:a}=await import("ai"),{text:i}=await a({model:s(t),prompt:e,system:r.system,maxOutputTokens:r.maxTokens,temperature:r.temperature});return i};async function wo(e,t,n={}){let{system:r,maxTokens:o=4096,temperature:s=.7,onToken:a}=n,i=await xo(e);switch(e.provider){case"openai":return tc(t,e.model,i,{system:r,maxTokens:o,temperature:s,onToken:a});case"anthropic":return nc(t,e.model,i,{system:r,maxTokens:o,temperature:s,onToken:a});default:throw new Error(`Unsupported AI provider: ${e.provider}`)}}var ee=require("node:fs"),Ae=require("node:path"),as=require("@inquirer/prompts"),h=u(require("chalk")),is=u(require("ora"));var $n=require("node:fs"),Mt=require("node:path");var be=require("node:fs"),ot=require("node:path"),jt=u(require("chokidar"));var st=".pf-generating",rc=e=>(0,be.existsSync)((0,ot.join)(e,st)),oc=e=>{let t=(0,ot.join)(e,st);(0,be.existsSync)(t)&&(0,be.unlinkSync)(t)},sc=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"],bo=(e,t)=>{oc(e);let n=ve(e),r=sc(n?.pf?.paths),o=(0,ot.join)(e,st),s=()=>{rc(e)||t()},a=[];a.push(jt.default.watch(o,{ignoreInitial:!0}).on("unlink",()=>t()));for(let i of r){let c=(0,ot.join)(e,i);(0,be.existsSync)(c)&&(a.push(jt.default.watch(c,{ignoreInitial:!0,depth:0}).on("addDir",s).on("unlinkDir",s)),a.push(jt.default.watch(`${c}/*/package.json`,{ignoreInitial:!0}).on("add",s).on("change",s).on("unlink",s)))}return async()=>{await Promise.all(a.map(i=>i.close()))}};var at=(e=__dirname)=>{let t=r=>(0,$n.existsSync)((0,Mt.join)(r,"package.json")),n=(0,Mt.dirname)(e);if(t(e))return e;if(e==="/")throw new Error("Could not find package.json (package root)");return at(n)},So=(e,t)=>{let n=e.find($n.existsSync);if(!n)throw new Error(t??`Directory not found. Searched in: ${e.join(", ")}`);return n};var _t=require("node:fs"),Mo=require("node:path"),Fo=require("ts-morph");var N=require("node:fs"),Se=require("node:path");var To=e=>e.replace(/\./g,"-").toLowerCase(),Po=e=>e.split(/[-.]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(""),ac=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}()`,ic=e=>!e||Object.keys(e).length===0?` id: z.string(),
|
|
21
|
+
createdAt: z.string(),`:Object.entries(e).map(([t,n])=>` ${t}: ${ac(n)},`).join(`
|
|
22
|
+
`),En=e=>e.endsWith("s")?e:e.endsWith("y")?`${e.slice(0,-1)}ies`:e.endsWith("ch")||e.endsWith("sh")?`${e}es`:`${e}s`,B=e=>{let t=To(e),n=Po(e),r=e.split(".")[0],o=e.split(".").slice(1).join("-"),s=En(r).toUpperCase(),a=En(r).toLowerCase(),i=Po(`${En(r)}.${o}`);return{eventName:t,contractName:`${i}Contract`,schemaName:`${n}Schema`,typeName:`${n}Data`,streamName:s,domain:a,event:o}},An=e=>{let t=it(e);if((0,N.existsSync)(t))return!0;let{eventsPath:n}=C(),r=To(e),o=(0,Se.join)(n,`${r}.ts`);return(0,N.existsSync)(o)},In=(e,t)=>{let{eventsPath:n}=C(),{contractName:r,schemaName:o,typeName:s,streamName:a,domain:i,event:c}=B(e),l=`import { createContract } from '@crossdelta/cloudevents'
|
|
23
23
|
import { z } from 'zod'
|
|
24
24
|
|
|
25
25
|
export const ${o} = z.object({
|
|
26
|
-
${
|
|
26
|
+
${ic(t)}
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
export const ${
|
|
29
|
+
export const ${r} = createContract({
|
|
30
30
|
type: '${e}',
|
|
31
31
|
channel: { stream: '${a}' },
|
|
32
32
|
schema: ${o},
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
export type ${s} = z.infer<typeof ${
|
|
36
|
-
`,p=(0,
|
|
37
|
-
`,
|
|
38
|
-
${t}${e.slice(o)}`}let
|
|
35
|
+
export type ${s} = z.infer<typeof ${r}.schema>
|
|
36
|
+
`,p=(0,Se.join)(n,i),d=(0,Se.join)(p,`${c}.ts`);return(0,N.existsSync)(p)||(0,N.mkdirSync)(p,{recursive:!0}),(0,N.writeFileSync)(d,l,"utf-8"),d},it=e=>{let{eventsPath:t}=C(),{domain:n,event:r}=B(e);return(0,Se.join)(t,n,`${r}.ts`)},Nn=e=>{let t=it(e);if(!(0,N.existsSync)(t))return null;let n=(0,N.readFileSync)(t,"utf-8"),r=n.match(/export const \w+Schema\s*=\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m);if(r)return r[1];let o=n.match(/schema:\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m);return o?o[1]:null},Rn=()=>{let{packagePath:e}=C(),t=(0,Se.join)(e,"package.json");if(!(0,N.existsSync)(t))return"@my-platform";try{return JSON.parse((0,N.readFileSync)(t,"utf-8")).name?.split("/")[0]??"@my-platform"}catch{return"@my-platform"}};var Ot=require("node:fs"),Fn=require("node:path");var T=require("node:fs"),Pe=require("node:path");var Ft=e=>{let{streamName:t}=B(e);return t},$o=(e,t)=>{let n=(0,Pe.join)(e,"src","index.ts");if(!(0,T.existsSync)(n))return!1;let r=(0,T.readFileSync)(n,"utf-8"),o=t.toLowerCase();return new RegExp(`streams:\\s*\\[[^\\]]*['"]${t}['"]`).test(r)||r.includes(`stream: '${t}'`)?!0:new RegExp(`subjects:\\s*\\[.*['"]${o}\\.[*>]`).test(r)},cc=e=>{if(e.includes("@crossdelta/cloudevents"))return e;let t=`import { consumeJetStreams } from '@crossdelta/cloudevents'
|
|
37
|
+
`,n=e.match(/import\s+['"]@crossdelta\/telemetry['"]\s*\n/);if(n){let o=(n.index??0)+n[0].length;return`${e.slice(0,o)}
|
|
38
|
+
${t}${e.slice(o)}`}let r=e.match(/import\s+.*\n/);if(r){let o=(r.index??0)+r[0].length;return e.slice(0,o)+t+e.slice(o)}return e},lc=(e,t,n)=>`
|
|
39
39
|
|
|
40
40
|
// Consume from ${e} stream
|
|
41
41
|
consumeJetStreams({
|
|
42
42
|
streams: ['${e}'],
|
|
43
|
-
consumer: '${
|
|
43
|
+
consumer: '${n}-service',
|
|
44
44
|
discover: './src/events/**/*.handler.ts',
|
|
45
|
-
})`,
|
|
46
|
-
`;return(0,T.writeFileSync)(o,l,"utf-8"),{added:!0,streamName:
|
|
47
|
-
import { ${
|
|
45
|
+
})`,jn=(e,t)=>{let n=Ft(t),r=t.split(".")[0],o=(0,Pe.join)(e,"src","index.ts"),s=(0,Pe.join)(e,"src","main.ts");if(!(0,T.existsSync)(o)&&(0,T.existsSync)(s))return{added:!1,streamName:n};if(!(0,T.existsSync)(o))return{added:!1,streamName:n,warning:"Entry point not found (index.ts or main.ts)"};if($o(e,n))return{added:!1,streamName:n};let a=(0,T.readFileSync)(o,"utf-8"),i=e.split("/").pop()||"unknown";a.includes("consumeJetStreams")||(a=cc(a));let c=lc(n,r,i),l=`${a.trimEnd()+c}
|
|
46
|
+
`;return(0,T.writeFileSync)(o,l,"utf-8"),{added:!0,streamName:n}},Mn=(e,t)=>{let{eventName:n,contractName:r,typeName:o}=B(e),s=Rn(),a=(0,Pe.join)(t,"src","events"),i=(0,Pe.join)(a,`${n}.handler.ts`);if((0,T.existsSync)(i))return null;let c=`import { handleEvent } from '@crossdelta/cloudevents'
|
|
47
|
+
import { ${r}, type ${o} } from '${s}/contracts'
|
|
48
48
|
|
|
49
|
-
export default handleEvent(${
|
|
49
|
+
export default handleEvent(${r}, async (data: ${o}) => {
|
|
50
50
|
// TODO: Implement event handling logic
|
|
51
51
|
console.log('Received ${e}:', data)
|
|
52
52
|
})
|
|
53
|
-
`;return(0,T.existsSync)(a)||(0,T.mkdirSync)(a,{recursive:!0}),(0,T.writeFileSync)(i,c,"utf-8"),i};var
|
|
53
|
+
`;return(0,T.existsSync)(a)||(0,T.mkdirSync)(a,{recursive:!0}),(0,T.writeFileSync)(i,c,"utf-8"),i};var Eo=e=>{try{return(0,Ot.readdirSync)(e,{withFileTypes:!0}).flatMap(n=>{let r=(0,Fn.join)(e,n.name);return n.isDirectory()?Eo(r):n.name.endsWith(".handler.ts")?[r]:[]})}catch{return[]}},On=e=>{let t=(0,Fn.join)(e,"src","events");return Eo(t).flatMap(r=>{let o=(0,Ot.readFileSync)(r,"utf-8");return pc(r,o)})},pc=(e,t)=>{let n=mc(t);if(!n)return[];let s=(n.replace(/Contract$/,"").match(/[A-Z][a-z]*/g)??[]).map(a=>a.toLowerCase()).join(".");return[{filePath:e,eventType:s,contractName:n}]},mc=e=>{let n=/import\s+{([^}]+)}\s+from\s+['"]@[\w-]+\/contracts['"]/.exec(e);return n?n[1].split(",").map(s=>s.trim()).filter(s=>s.endsWith("Contract")).map(s=>s.replace(/\s+as\s+.+$/,"").trim()).at(0)??null:null},Dn=e=>{let t=e.reduce((n,r)=>{let o=r.eventType.split(".")[0],s=n.get(o)??[];return n.set(o,[...s,r]),n},new Map);return Array.from(t.entries()).map(([n,r])=>dc(n,r)).sort((n,r)=>n.stream.localeCompare(r.stream))},dc=(e,t)=>{let n=Ft(t[0]?.eventType??`${e}.event`),r=`${e}.>`;return{stream:n,subjects:[r],handlers:t}},_n=(e,t)=>e.length===0?"":` // Services NEVER create streams!
|
|
54
54
|
// - Development: pf dev auto-creates ephemeral streams from contracts
|
|
55
55
|
// - Production: Pulumi materializes persistent streams
|
|
56
56
|
|
|
57
57
|
consumeJetStreams({
|
|
58
|
-
streams: [${e.map(
|
|
58
|
+
streams: [${e.map(n=>`'${n.stream}'`).join(", ")}],
|
|
59
59
|
consumer: '${t}',
|
|
60
60
|
discover: './src/events/**/*.handler.ts',
|
|
61
|
-
})`;var
|
|
62
|
-
* ${(0,
|
|
61
|
+
})`;var v=require("node:fs"),U=require("node:path");var uc=(e,t)=>{let n=`export * from './${t}'`;if(!(0,v.existsSync)(e)){let s=(0,U.dirname)(e);(0,v.existsSync)(s)||(0,v.mkdirSync)(s,{recursive:!0});let a=`/**
|
|
62
|
+
* ${(0,U.dirname)(e).split("/").pop()} Domain Events
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
|
-
`;return(0,
|
|
66
|
-
`,"utf-8"),!0}let
|
|
67
|
-
`+
|
|
68
|
-
`;return(0,
|
|
65
|
+
`;return(0,v.writeFileSync)(e,a+n+`
|
|
66
|
+
`,"utf-8"),!0}let r=(0,v.readFileSync)(e,"utf-8");if(r.includes(`'./${t}'`))return!1;let o=r.trimEnd()+`
|
|
67
|
+
`+n+`
|
|
68
|
+
`;return(0,v.writeFileSync)(e,o,"utf-8"),!0},gc=(e,t)=>{let n=`export * from './${t}'`;if(!(0,v.existsSync)(e))return(0,v.writeFileSync)(e,`/**
|
|
69
69
|
* Event Contracts Index
|
|
70
70
|
*
|
|
71
71
|
* Re-exports all event contracts for convenient importing.
|
|
72
72
|
*/
|
|
73
73
|
|
|
74
|
-
`+
|
|
75
|
-
`,"utf-8"),!0;let o=(0,
|
|
76
|
-
`);if(o.some(a=>a.trim()===
|
|
77
|
-
`),"utf-8"),!0},
|
|
78
|
-
`),s=o.findLastIndex(a=>a.startsWith("export"));return s>=0?o.splice(s+1,0,
|
|
79
|
-
`),"utf-8"),!0};var b=require("node:fs"),
|
|
74
|
+
`+n+`
|
|
75
|
+
`,"utf-8"),!0;let o=(0,v.readFileSync)(e,"utf-8").split(`
|
|
76
|
+
`);if(o.some(a=>a.trim()===n))return!1;let s=o.findLastIndex(a=>a.startsWith("export"));return s>=0?o.splice(s+1,0,n):o.push(n),(0,v.writeFileSync)(e,o.join(`
|
|
77
|
+
`),"utf-8"),!0},fc=e=>{if(!(0,v.existsSync)(e))return!1;let t=(0,v.readFileSync)(e,"utf-8"),n=t;return n=n.replace(/\/\/ export \* from '\.\/events'/,"export * from './events'"),n=n.replace(/\/\/ export \* from '\.\/stream-policies'/,"export * from './stream-policies'"),n!==t?((0,v.writeFileSync)(e,n,"utf-8"),!0):!1},Bn=e=>{let{packagePath:t}=C(),{domain:n,event:r}=B(e),o=(0,U.join)(t,"src","events"),s=(0,U.join)(o,n),a=(0,U.join)(s,"index.ts"),i=(0,U.join)(o,"index.ts"),c=(0,U.join)(t,"src","index.ts"),l=e.split(".")[0],p=(0,U.join)(o,l);l!==n&&(0,v.existsSync)(p)&&(console.warn(`\u26A0\uFE0F Warning: Legacy folder '${l}/' found. Please migrate to '${n}/' to avoid conflicts.`),console.warn(` Run: mv ${p} ${s}`));let d=!1;return uc(a,r)&&(d=!0),gc(i,n)&&(d=!0),fc(c)&&(d=!0),d},Hn=(e,t)=>{if(!(0,v.existsSync)(e))return!1;let n=`export * from './events/${t}'`,r=(0,v.readFileSync)(e,"utf-8");if(r.includes(`'./events/${t}'`))return!1;let o=r.split(`
|
|
78
|
+
`),s=o.findLastIndex(a=>a.startsWith("export"));return s>=0?o.splice(s+1,0,n):o.push("",n),(0,v.writeFileSync)(e,o.join(`
|
|
79
|
+
`),"utf-8"),!0};var b=require("node:fs"),J=require("node:path"),f=require("@faker-js/faker");var Ao=[{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"}],Io=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(),No=e=>{let t=e.toLowerCase(),n=Ao.find(r=>t.includes(r.pattern));return n?{value:n.generate(),hint:n.hint}:null},hc=(e,t)=>{if(e.format)return Io(e.format);let n=No(t);if(n)return n.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?[Ln(e.element)]:[];case"object":return Ln(e);default:return null}},Ln=e=>{let t={},n=e.shape??(typeof e.def?.shape=="function"?e.def.shape():void 0);if(!n)return t;for(let[r,o]of Object.entries(n))t[r]=hc(o,r);return t},yc=async e=>{try{let{createJiti:t}=await import("jiti"),r=t(process.cwd(),{interopDefault:!0})(e),o=Object.entries(r).find(([s])=>s.endsWith("Schema")||s==="schema");if(o?.[1]){let s=o[1],a=Ln(s);if(a&&typeof a=="object"&&Object.keys(a).length>0){let i={};return Wn(a,i,""),{data:a,faker:i}}}}catch{}return null},Wn=(e,t,n)=>{if(!(!e||typeof e!="object"))for(let[r,o]of Object.entries(e)){let s=n?`${n}.${r}`:r,a=r.toLowerCase(),i=Ao.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)?Wn(o,t,s):Array.isArray(o)&&o.length>0&&typeof o[0]=="object"&&Wn(o[0],t,`${s}[0]`)}},kc=e=>({string:()=>f.faker.lorem.word(),number:()=>f.faker.number.int({min:1,max:100}),boolean:()=>f.faker.datatype.boolean()})[e]?.(),vc=(e,t,n)=>{let r=/(\w+):\s*z\.(\w+)\(/g,o=Array.from(e.matchAll(r));for(let[,s,a]of o){if(a==="array"||a==="object")continue;let i=No(s);if(i)t[s]=i.value,i.hint&&(n[s]=i.hint);else{let c=kc(a);c!==void 0&&(t[s]=c)}}},Cc=(e,t,n)=>{let r=/(\w+):\s*z\.string\(\)\.(datetime|email|url|uuid)\(\)/g,o=Array.from(e.matchAll(r));for(let[,s,a]of o)t[s]=Io(a),n[s]=a==="datetime"?"date":a},Ro=e=>{let t={},n={};return vc(e,t,n),Cc(e,t,n),{data:t,faker:n}},Dt=async e=>{let{eventsPath:t}=C(),n=it(e);if(!(0,b.existsSync)(n))return null;let o=(0,b.readFileSync)(n,"utf-8").match(/type:\s*['"]([^'"]+)['"]/),s=o?o[1]:e,a=await yc(n);if(!a){let k=Nn(e);k&&(a=Ro(k))}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}=B(e),p=(0,J.join)(t,c,`${l}.mock.json`),d=(0,J.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 jo=e=>{let t=e.match(/import\s+\{[^}]*?(\w+Contract)[^}]*?\}\s+from\s+['"][^'"]+\/contracts['"]/);return t?t[1].replace("Contract","").replace(/([A-Z])/g,(r,o,s)=>(s>0?".":"")+o.toLowerCase()):null},xc=(e,t,n)=>{if(!(0,b.existsSync)(e))return!1;let r=(0,b.readFileSync)(e,"utf-8"),o=r.match(/export const \w+(?:Schema|Data)\s*=\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m)??r.match(/schema:\s*z\.object\(\s*\{([\s\S]*?)\}\s*\)/m);if(!o)return!1;let s=Ro(o[1]),a={eventName:n,description:`Mock data for ${n} 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},Gn=async(e,t={})=>{let n=(0,J.join)(e,"src","events");if(!(0,b.existsSync)(n))return{mockPaths:[],skippedHandlers:[]};let r=(0,b.readdirSync)(n).filter(a=>a.endsWith(".event.ts")).map(a=>(0,J.join)(n,a)),o=[],s=[];for(let a of r){let i=(0,b.readFileSync)(a,"utf-8"),c=jo(i);if(!c){s.push(`${(0,J.basename)(a)} (Handler does not use contracts)`);continue}let{eventName:l}=B(c),p=t.outputDir??C().eventsPath,d=(0,J.join)(p,`${l}.mock.json`);if((0,b.existsSync)(d)&&!t.overwrite){s.push(`${(0,J.basename)(a)} (Mock already exists)`);continue}if(t.outputDir){let I=(0,J.join)(t.outputDir,`${l}.ts`);xc(I,d,c)&&o.push(d);continue}let k=await Dt(c);k&&o.push(k)}return{mockPaths:o,skippedHandlers:s}};var Oo=e=>{let t=e.split("/").pop()||"service",n=(0,Mo.join)(e,"src","events","events.service.ts");if(!(0,_t.existsSync)(n))return!1;let r=On(e);if(r.length===0||(0,_t.readFileSync)(n,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").includes("consumeJetStreams"))return!1;let i=Dn(r),c=_n(i,t);if(!c)return!1;let l=new Fo.Project({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0}),p=l.addSourceFileAtPath(n),d=!1;for(let k of p.getClasses()){let I=k.getMethod("startConsumers");if(!I)continue;let F=[...c.split(`
|
|
80
80
|
`),""," this.logger.log('Event consumers started successfully')"].join(`
|
|
81
|
-
`)
|
|
82
|
-
`));for(let
|
|
83
|
-
`));for(let l of i)console.log(
|
|
84
|
-
`));for(let l of c)console.log(
|
|
81
|
+
`);I.setBodyText(F),d=!0;break}return d&&l.saveSync(),d};var wc=e=>{let t=e.split(/\s+/),n=t[0],r=t.slice(1);return n==="pf"&&(n=process.argv[1]),{executable:n,args:r}},bc=async(e,t)=>{try{let{executable:n,args:r}=wc(e.command);return await se(n,r,{cwd:t,shell:!1}),{command:e.command,success:!0}}catch(n){return{command:e.command,success:!1,error:n instanceof Error?n.message:String(n)}}},Un=async(e,t)=>{let n=[];for(let r of e){let o=await bc(r,t);if(n.push(o),!o.success)break}return n},Jn=e=>{let t=[/^pf\s+/,/^bun\s+pf\s+/,/^npx\s+pf\s+/,/^bunx\s+pf\s+/];return e.filter(n=>t.some(r=>r.test(n.command)))},Do=e=>{for(let t of e){let n=t.command.match(/(?:bun\s+)?pf\s+new\s+\S+\s+(\S+)/);if(n)return n[1]}return null};var ct=require("node:fs"),Ht=require("node:path"),K=u(require("chalk"));var fe=require("node:fs"),Bt=require("node:path"),Sc=(e,t)=>{let r=e.path.startsWith("packages/")&&t.workspaceRoot?t.workspaceRoot:t.baseDir,o=(0,Bt.join)(r,e.path);try{if((0,fe.existsSync)(o)&&!t.overwrite)return{status:"skipped",path:e.path};if(t.dryRun)return{status:"written",path:e.path};let s=(0,Bt.dirname)(o);return(0,fe.existsSync)(s)||(0,fe.mkdirSync)(s,{recursive:!0}),(0,fe.writeFileSync)(o,e.content,"utf-8"),{status:"written",path:e.path}}catch(s){return{status:"failed",path:e.path,error:s.message}}},_o=(e,t)=>{let n=e.map(r=>Sc(r,t));return{written:n.filter(r=>r.status==="written").map(r=>r.path),skipped:n.filter(r=>r.status==="skipped").map(r=>r.path),failed:n.filter(r=>r.status==="failed").map(r=>({path:r.path,error:r.error}))}};var Pc=(e,t)=>{let n=D(t.workspaceRoot),r=(0,Ht.join)(t.workspaceRoot,n.contracts);if(!(0,ct.existsSync)(r))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()},Tc=e=>{let t=(0,Ht.join)(e,"packages/contracts/src/index.ts");if(!(0,ct.existsSync)(t))return new Set;try{let n=(0,ct.readFileSync)(t,"utf-8"),r=new Set,o=/export\s+(?:\*|{[^}]*Contract[^}]*})\s+from\s+['"]\.\/events\/([^'"]+)['"]/g,s=n.matchAll(o);for(let a of s){let i=a[0],c=/(\w+Contract)/g,l=i.matchAll(c);for(let p of l)r.add(p[1])}return r}catch{return new Set}},$c=e=>{let t=e.replace(/Contract$/,""),n=t.split(/(?=[A-Z])/).filter(Boolean);if(n.length<2)return t.toLowerCase();let r=n[0].toLowerCase(),o=n.slice(1).join("").toLowerCase();return`${r}.${o}`},Ec=(e,t,n)=>{let r=Tc(t),o=[],s=[],a=[];for(let i of e)if(r.has(i))o.push(i);else{s.push(i);let c=$c(i),l=n.replace(`${t}/`,"");a.push(`pf event add ${c} --service ${l}`)}return{existing:o,missing:s,suggestedCommands:a}},Ac=(e,t)=>{if(e.length!==0){console.log(K.default.cyan(`\u{1F4E6} Using existing contracts:
|
|
82
|
+
`));for(let n of e)console.log(K.default.dim(` ${t}/contracts \u2192 ${n}`));console.log()}},Ic=(e,t)=>{let n=/^packages\/contracts\/src\/events\/([^/]+)\.ts$/,r=(0,Ht.join)(t,"packages/contracts/src/index.ts");for(let o of e){let s=o.match(n);s&&s[1]!=="index"&&Hn(r,s[1])}},Bo=async(e,t)=>{t.start("Applying code formatting...");try{await Q("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:n,skippedHandlers:r}=await Gn(e);if(n.length+r.length===0){t.info("No event handlers found");return}if(n.length>0){t.succeed(`Generated ${n.length} event ${n.length===1?"mock":"mocks"}`),console.log();for(let s of n){let a=s.replace(`${e}/`,"");console.log(K.default.dim(` ${a}`))}console.log()}else t.succeed("Event handlers found");if(r.length>0){for(let s of r)console.log(K.default.dim(` \u2139 Skipped: ${s}`));console.log()}},Ho=async(e,t,n,r)=>{r.start("Writing generated files...");let o=_o(e,{baseDir:t,workspaceRoot:n.workspaceRoot,overwrite:!0});if(o.written.length>0){r.succeed(`Created ${o.written.length} files`),console.log();for(let l of o.written)console.log(K.default.dim(` ${l}`));console.log()}else r.succeed("No files to write");let s=Pc(e,n),{existing:a,missing:i,suggestedCommands:c}=Ec(s,n.workspaceRoot,t);if(a.length>0&&Ac(a,n.scope),i.length>0){console.log(K.default.yellow(`\u26A0\uFE0F Missing contracts (not exported from @${n.scope}/contracts):
|
|
83
|
+
`));for(let l of i)console.log(K.default.yellow(` ${l}`));console.log(),console.log(K.default.cyan(`\u{1F4A1} Run these commands to create the missing contracts:
|
|
84
|
+
`));for(let l of c)console.log(K.default.dim(` ${l}`));console.log()}return Ic(o.written,n.workspaceRoot),o.written.length>0&&await Nc(t,r),{missingContractCommands:c}};var Lt=require("node:fs"),$e=require("node:path");var Te=require("node:fs"),Lo=require("node:path");var Wo=e=>{let{eventsPath:t}=C(e);if(!(0,Te.existsSync)(t))return[];let n=[];try{let r=(0,Te.readdirSync)(t).filter(o=>o.endsWith(".ts")&&!o.endsWith(".mock.json")&&o!=="index.ts");for(let o of r){let s=(0,Lo.join)(t,o),a=(0,Te.readFileSync)(s,"utf-8"),i=Rc(a,s);i&&n.push(i)}}catch(r){return console.warn("Warning: Could not scan contracts package:",r),[]}return n},Rc=(e,t)=>{try{let n=e.match(/export const (\w+Contract) = createContract/);if(!n)return null;let r=n[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=Mc(e);return{name:r,typeName:s,eventType:i,fields:c,filePath:t}}catch{return null}},jc={string:"string",number:"number",boolean:"boolean",array:"array",object:"object",date:"date"},Mc=e=>{let t=e.match(/z\.object\({([^}]+)\}/);if(!t)return[];let n=t[1],r=/(\w+):\s*z\.(\w+)\([^)]*\)/g,o=[...n.matchAll(r)].map(([,i,c])=>{let l=jc[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]},Go=(e,t)=>{if(e.length===0)return`
|
|
85
85
|
**Available Contracts:**
|
|
86
86
|
|
|
87
87
|
No contracts are currently defined. Use Basic Mode with inline schemas for all events.
|
|
88
|
-
`.trim();let
|
|
88
|
+
`.trim();let n=e.map((r,o)=>{let s=r.fields.length>0?r.fields.map(a=>` - ${a}`).join(`
|
|
89
89
|
`):" - (no fields detected)";return`
|
|
90
|
-
${o+1}. **${
|
|
91
|
-
- Type: \`${
|
|
90
|
+
${o+1}. **${r.name}** (\`${r.eventType}\`)
|
|
91
|
+
- Type: \`${r.typeName}\`
|
|
92
92
|
- Fields:
|
|
93
93
|
${s}
|
|
94
|
-
- **USE THIS** when consuming ${
|
|
94
|
+
- **USE THIS** when consuming ${r.eventType} or similar event names
|
|
95
95
|
`.trim()}).join(`
|
|
96
96
|
|
|
97
97
|
`);return`
|
|
@@ -99,18 +99,18 @@ ${s}
|
|
|
99
99
|
|
|
100
100
|
The following event contracts are available in \`${t}/contracts\`:
|
|
101
101
|
|
|
102
|
-
${
|
|
102
|
+
${n}
|
|
103
103
|
|
|
104
104
|
If the event type your service consumes matches one of these, **you MUST use Advanced Mode**.
|
|
105
|
-
`.trim()};var
|
|
105
|
+
`.trim()};var Fc=(e,t)=>{let n=(0,$e.join)(__dirname,"docs","generators"),r=Qe(),o=[];for(let s of r.docs.base)o.push((0,$e.join)(n,s));if(e&&r.docs.frameworks[e]){let s=r.docs.frameworks[e];if(typeof s=="string")o.push((0,$e.join)(n,s));else{let a=t==="bun"?"bun":"node";s[a]&&o.push((0,$e.join)(n,s[a]))}}return o},Uo={copilot:".github/copilot-instructions.md",projectGuidelines:"docs/ai-guidelines.md"},Oc=1500,Jo=e=>{try{return(0,Lt.existsSync)(e)?(0,Lt.readFileSync)(e,"utf-8"):null}catch{return null}},Dc=e=>e.replace(/<!--[\s\S]*?-->/g,"").replace(/^\[.+\]:\s*.+$/gm,"").replace(/\n{3,}/g,`
|
|
106
106
|
|
|
107
|
-
`).replace(/[ \t]+$/gm,"").trim(),
|
|
107
|
+
`).replace(/[ \t]+$/gm,"").trim(),_c=e=>e.replace(/<!--[\s\S]*?-->/g,"").replace(/^\[.+\]:\s*.+$/gm,"").replace(/```[\s\S]*?```/g,"").replace(/`[^`]{50,}`/g,"`...`").replace(/\n{3,}/g,`
|
|
108
108
|
|
|
109
|
-
`).replace(/[ \t]+$/gm,"").trim(),
|
|
109
|
+
`).replace(/[ \t]+$/gm,"").trim(),Bc=e=>Math.ceil(e.length/4),Hc=(e,t)=>{let n=e.split(/(?=^## )/m),r="",o=0;for(let s of n){let a=Bc(s);if(o+a<=t)r+=s,o+=a;else if(o===0){r=s.slice(0,t*4);break}else break}return r.trim()},Lc=(e,t)=>{let{workspaceRoot:n,scope:r}=t,o=Wo(n),s=Go(o,r);return e.replace(/\{\{scope\}\}/g,r).replace(/\{\{AVAILABLE_CONTRACTS\}\}/g,s)},Ko=e=>{let{workspaceRoot:t,scope:n}=e,r=[],o=Fc(e.serviceType,e.packageManager);for(let i of o){let c=Jo(i);if(c){let l=Lc(c,e),p=Dc(l);r.push(p)}}let s=[Uo.copilot,Uo.projectGuidelines],a=Math.floor(Oc/s.length);for(let i of s){let c=Jo((0,$e.join)(t,i));if(c){let l=_c(c),p=Hc(l,a);p.length>50&&r.push(p)}}return r.length===0?(console.warn("\u26A0\uFE0F No instruction files found."),`Use ${n}/contracts for shared types.`):r.join(`
|
|
110
110
|
|
|
111
111
|
---
|
|
112
112
|
|
|
113
|
-
`)};var
|
|
113
|
+
`)};var Wc=`You are an expert code generator. Generate clean, production-ready code.
|
|
114
114
|
|
|
115
115
|
## Output Format
|
|
116
116
|
|
|
@@ -124,13 +124,13 @@ Format your code blocks with the file path on the line before the code block:
|
|
|
124
124
|
**IMPORTANT:** Always generate:
|
|
125
125
|
- Source code files (src/**)
|
|
126
126
|
- Test files (src/**/*.test.ts) for all business logic
|
|
127
|
-
- README.md with service documentation`,
|
|
127
|
+
- README.md with service documentation`,Gc=e=>e.replace(/-/g,"_").toUpperCase(),Uc=e=>e.split("/").pop()||"my-service",zo=(e,t,n)=>{let r=Ko({...e,serviceType:t,packageManager:n});return`${Wc}
|
|
128
128
|
|
|
129
129
|
## Project Guidelines & Patterns
|
|
130
130
|
|
|
131
131
|
Follow these project-specific conventions and patterns when generating code:
|
|
132
132
|
|
|
133
|
-
${
|
|
133
|
+
${r}`},qo=(e,t,n,r)=>{let o=Uc(e),s=`${Gc(o)}_PORT`,a=Ce();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,54 +145,54 @@ 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
|
|
149
|
-
`).map(o=>o.trim()).filter(o=>o.length>0&&!o.startsWith("#"))),
|
|
150
|
-
`),
|
|
151
|
-
`));return}let o=(await
|
|
152
|
-
\u2717 Scaffolding failed: ${o.command}`)),o.error&&console.log(
|
|
153
|
-
\u25B6 Installing ${e.length} additional ${
|
|
154
|
-
`));try{await
|
|
155
|
-
`))}catch(o){throw console.log(
|
|
156
|
-
`)),o}},
|
|
148
|
+
`};var Jc=()=>!1,Vo=(e,t)=>{Jc()&&console.log(`[AI Parser] ${e}`,t??"")},Wt={commandsBlock:/```commands\n([\s\S]*?)```/gi,postCommandsBlock:/```post-commands\n([\s\S]*?)```/gi,dependenciesBlock:/```dependencies\n([\s\S]*?)```/gi,fileHeader:/^#{1,4}\s+`([^`]+)`\s*$/},zn=(e,t)=>[...e.matchAll(t)].flatMap(r=>r[1].split(`
|
|
149
|
+
`).map(o=>o.trim()).filter(o=>o.length>0&&!o.startsWith("#"))),Zo=e=>({command:e,isPfCommand:e.startsWith("pf ")||e.includes(" pf ")}),Kc=e=>zn(e,Wt.commandsBlock).map(Zo),zc=e=>zn(e,Wt.postCommandsBlock).map(Zo),qc=e=>zn(e,Wt.dependenciesBlock).filter(t=>!t.startsWith("@crossdelta/")&&t!=="zod"),Vc=e=>{let t={ts:"typescript",js:"javascript",md:"markdown",yml:"yaml"},n=(e||"typescript").toLowerCase();return t[n]||n},Zc=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"},Yc=e=>e.replace(/^\s*\/\/ \.{3,}.*$/gm,"").replace(/^\s*\/\/ Lines? \d+.*omitted.*$/gim,"").replace(/^\s*\/\* Lines? \d+.*omitted.*\*\/$/gim,"").trim(),Xc=e=>{let t=e.split(`
|
|
150
|
+
`),n=[],r=0;for(let o of t){let s=Wt.fileHeader.exec(o);s&&n.push({path:s[1],index:r}),r+=o.length+1}return n},Qc=(e,t)=>{let r=e.slice(t).match(/```(\w+)?\n([\s\S]*?)```/);return r?{language:r[1]?Vc(r[1]):void 0,content:Yc(r[2])}:null},el=e=>Xc(e).map(n=>{let r=Qc(e,n.index);return!r||r.content.length===0?null:{path:n.path,language:r.language||Zc(n.path),content:r.content,startIndex:n.index}}).filter(n=>n!==null),Kn=e=>e.includes("packages/contracts")||e.includes("contracts/src"),tl=e=>{let t=e.filter(r=>Kn(r.path)),n=e.filter(r=>!Kn(r.path));return[...t,...n]},nl=e=>{let t=e.replace(/^\/+/,"").replace(/\/{2,}/g,"/");if(Kn(t))return t;let n=t.match(/^services\/[^/]+\/(.+)$/);return n?n[1]:t},Yo=(e,t)=>{Vo("Parsing AI response",{length:e.length});let n=Kc(e),r=zc(e),o=qc(e),s=el(e),a=tl(s.map(i=>({path:nl(i.path),content:i.content,language:i.language})));return Vo("Parsed response",{commands:n.length,postCommands:r.length,dependencies:o.length,files:a.length}),{commands:n,files:a,dependencies:o,postCommands:r}},Xo=e=>{let t=e.filter(s=>!s.content||s.content.trim().length===0),n=e.length===0?["No files could be extracted from the AI response"]:t.map(s=>`File ${s.path} is empty`),r=e.some(s=>["src/index.ts","src/main.ts","index.ts"].includes(s.path)),o=e.length>0&&!r?["No entry point file (src/index.ts or src/main.ts) found - assuming it exists from scaffolding"]:[];return{valid:n.length===0,errors:n,warnings:o}};var Qo=require("node:fs"),H=u(require("chalk"));var es=async(e,t,n)=>{if(e.length===0){(0,Qo.mkdirSync)(t,{recursive:!0}),console.log(H.default.yellow(`\u26A0 No scaffolding command found - creating empty directory
|
|
151
|
+
`));return}let o=(await Un(e,n)).find(s=>!s.success);if(o)throw console.log(H.default.red(`
|
|
152
|
+
\u2717 Scaffolding failed: ${o.command}`)),o.error&&console.log(H.default.red(` Error: ${o.error}`)),new Error(`Command failed: ${o.command}${o.error?` - ${o.error}`:""}`)},ts=async(e,t)=>{t.start("Linking workspace dependencies...");try{await _({cwd:e,quiet:!0}),t.succeed("Workspace dependencies linked")}catch{let n=x();t.warn(`Workspace sync skipped (run ${n} install manually)`)}},ns=async(e,t,n)=>{if(e.length===0)return;n.stop();let r=e.length===1?"package":"packages";console.log(H.default.cyan(`
|
|
153
|
+
\u25B6 Installing ${e.length} additional ${r}...
|
|
154
|
+
`));try{await _({packages:e,cwd:t,flags:["--silent"]}),console.log(H.default.green(`\u2713 Installed ${e.length} ${r}
|
|
155
|
+
`))}catch(o){throw console.log(H.default.red(`\u2717 Package installation failed
|
|
156
|
+
`)),o}},qn=async(e,t)=>{if(e.length===0)return;console.log(H.default.cyan(`
|
|
157
157
|
\u25B6 Running post-generation commands...
|
|
158
|
-
`));let
|
|
159
|
-
\u26A0 Post-command failed: ${
|
|
160
|
-
`))};var
|
|
161
|
-
`,
|
|
162
|
-
`),
|
|
158
|
+
`));let r=(await Un(e,t)).find(o=>!o.success);if(r){console.log(H.default.yellow(`
|
|
159
|
+
\u26A0 Post-command failed: ${r.command}`)),r.error&&console.log(H.default.yellow(` Error: ${r.error}`));return}console.log(H.default.green(`\u2713 Post-generation commands complete
|
|
160
|
+
`))};var lt=u(require("chalk")),rl=e=>`${lt.default.dim(" \u2022 ")+lt.default.cyan(e)}
|
|
161
|
+
`,rs=e=>lt.default.dim(` \u2728 Generated ${lt.default.white.bold(e)} tokens
|
|
162
|
+
`),os=()=>{let e="",t=0,n=Date.now(),r=[],o=()=>{let a=e.match(/####\s+`([^`]+)`/);if(!a)return!1;r.push(a[1]),process.stdout.write(rl(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()-n)/1e3).toFixed(2),i=(t/Number.parseFloat(a)).toFixed(0);return{tokenCount:t,duration:a,tokensPerSec:i}},s.getFiles=()=>r,s};var ol=()=>{let e=y(),t=(0,Ae.join)(e,"package.json"),n=(()=>{if(!(0,ee.existsSync)(t))throw new Error("No package.json found in workspace root. Run from a valid workspace.");try{let o=JSON.parse((0,ee.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(r){throw r instanceof SyntaxError?new Error("Invalid JSON in package.json"):r}})();return{workspaceRoot:e,scope:n,cwd:process.cwd()}},sl=async(e,t,n,r,o,s)=>{let a=qo(n,r,o,t.workspaceRoot),i=zo(t,o,s),c=os(),l=await wo(e,a,{system:i,maxTokens:16384,temperature:.7,onToken:c}),p=c.getStats();return console.log(rs(p.tokenCount)),console.log(),l},al=(e,t)=>{let{serviceTypes:n}=Qe(),r=n[t]?.commandType;if(!r)return e;let o=Object.values(n).map(s=>s.commandType);return e.map(s=>{for(let a of o)if(a!==r&&s.command.includes(`pf new ${a}`))return{...s,command:s.command.replace(`pf new ${a}`,`pf new ${r}`)};return s})},il=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
|
-
`,
|
|
166
|
-
${
|
|
165
|
+
`,ss=(e,t,n)=>e.length===0?"":`${[h.default.cyan(`
|
|
166
|
+
${n} ${t}:`),...e.map(r=>` ${h.default.yellow("$")} ${h.default.white(r.command)}`)].join(`
|
|
167
167
|
`)}
|
|
168
|
-
`,
|
|
168
|
+
`,cl=e=>e.length===0?"":`${[h.default.cyan(`
|
|
169
169
|
\u{1F4E6} Dependencies to install:`),...e.map(t=>` ${h.default.magenta("+")} ${h.default.white(t)}`)].join(`
|
|
170
170
|
`)}
|
|
171
|
-
`,
|
|
172
|
-
Validation errors:`),...e.map(
|
|
171
|
+
`,ll=(e,t)=>`${[h.default.yellow(`
|
|
172
|
+
Validation errors:`),...e.map(n=>h.default.yellow(` \u26A0 ${n}`)),h.default.dim(`
|
|
173
173
|
Response preview:`),h.default.dim(t)].join(`
|
|
174
174
|
`)}
|
|
175
|
-
`,Ee=e=>{e&&process.stdout.write(e)},
|
|
176
|
-
`)},
|
|
175
|
+
`,Ee=e=>{e&&process.stdout.write(e)},pl=(e,t)=>{let n=Yo(e,t),r=Jn(n.commands),o=Jn(n.postCommands),s=Xo(n.files);return s.valid?{files:n.files,commands:r,dependencies:n.dependencies,postCommands:o}:(console.log(`${h.default.yellow("\u26A0")} Could not extract structured files from AI response`),Ee(ll(s.errors,e.slice(0,500))),null)},ml=e=>{console.log(`${h.default.green("\u2714")} Extracted ${e.files.length} files`),Ee(il(e.files)),Ee(ss(e.commands,"Commands to run","\u{1F527}")),Ee(ss(e.postCommands,"Post-generation commands","\u{1F4DD}")),Ee(cl(e.dependencies)),Ee(`
|
|
176
|
+
`)},dl=(e,t,n)=>{let r=Do(e);return r&&!r.includes("/")&&!r.startsWith(".")&&(r=`${D().services}/${r}`),r?(0,Ae.resolve)(n,r):(0,Ae.resolve)(n,t)},ul=(e,t)=>{let{serviceTypes:n}=Qe(),r=n[t]?.skipFiles||["package.json","tsconfig.json","Dockerfile"];return e.filter(o=>!r.includes(o.path))},Ie=()=>{if(!rt())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
|
-
`)};try{return{valid:!0,config:
|
|
179
|
-
`)}}},
|
|
178
|
+
`)};try{return{valid:!0,config:Rt()}}catch(e){return{valid:!1,error:h.default.red.bold(`\u274C ${e.message}
|
|
179
|
+
`)}}},Gt=async e=>e||(0,as.input)({message:"\u{1F4DD} Describe what this service should do:",validate:t=>t.trim().length>0||"Please provide a description for the AI to generate code"}),Ut=(e,t,n)=>{console.log(h.default.cyan.bold(`
|
|
180
180
|
\u{1F916} AI-Powered Generation
|
|
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: ${
|
|
182
|
-
`))},
|
|
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: ${n}
|
|
182
|
+
`))},Jt=async(e,t)=>{let{servicePath:n,description:r="",serviceType:o,packageManager:s}=e,a=n.split("/").pop()||n,i=ol(),c=(0,Ae.join)(i.workspaceRoot,st);(0,ee.writeFileSync)(c,`generating:${n}`);let l=()=>{(0,ee.existsSync)(c)&&(0,ee.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
|
|
185
|
-
`));let
|
|
184
|
+
`));let d=await sl(t,i,n,r,o,s),k=pl(d,a);if(!k)return!1;ml(k);let I=(0,is.default)({text:"Processing files...",color:"cyan"}).start(),qe=al(k.commands,o),F=dl(qe,n,i.cwd),Si=ul(k.files,o);await es(qe,F,i.workspaceRoot);let{missingContractCommands:Ar}=await Ho(Si,F,i,I);if(k.postCommands.length>0)await qn(k.postCommands,i.workspaceRoot);else if(Ar.length>0){console.log(h.default.cyan(`\u{1F527} Auto-creating missing contracts...
|
|
185
|
+
`));let Pi=Ar.map(Ti=>({command:Ti,isPfCommand:!0}));await qn(Pi,i.workspaceRoot)}return Oo(F),await ns(k.dependencies,F,I),await ts(i.workspaceRoot,I),await Bo(F,I),!0}finally{process.off("SIGINT",p),process.off("SIGTERM",p),l()}};var ls=require("node:fs"),pt=require("ts-morph"),cs=new pt.Project({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0}),Vn=e=>{if(!(0,ls.existsSync)(e))return null;let t=cs.getSourceFile(e);return t||cs.addSourceFileAtPath(e)},Zn=e=>{e.saveSync()},Yn=(e,t,n)=>{let r=e.getImportDeclaration(t);if(r){let o=r.getNamedImports().map(a=>a.getName()),s=n.filter(a=>!o.includes(a));for(let a of s)r.addNamedImport(a);return}e.addImportDeclaration({moduleSpecifier:t,namedImports:n})},gl=e=>{for(let t of e.getClasses()){let n=t.getDecorator("Module");if(!n)continue;let r=n.getArguments();if(r.length===0)continue;let o=r[0];if(o.getKind()===pt.SyntaxKind.ObjectLiteralExpression)return o}return null},Xn=(e,t)=>{let n=gl(e);if(!n)return!1;let r=n.getProperty("imports");if(r){let o=r.getFirstChildByKind(pt.SyntaxKind.ArrayLiteralExpression);return o?(o.getElements().map(a=>a.getText()).includes(t)||o.addElement(t),!0):!1}return n.addPropertyAssignment({name:"imports",initializer:`[${t}]`}),!0};var Kt=require("node:fs"),mt=u(require("node:path")),Qn=u(require("chalk"));var ps=async e=>{await se("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
|
-
`],{task:e,shell:!0}),await
|
|
187
|
+
`],{task:e,shell:!0}),await fl()},er=()=>Ye("bun"),ms=()=>fn([{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"}),ds=()=>fn([{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:Qn.default.blackBright("* Installing dependencies from cache for a Remix app."),barColor:"blackBright"}),fl=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 n=[mt.default.join(t,".zshrc"),mt.default.join(t,".bashrc"),mt.default.join(t,".bash_profile")];for(let r of n)try{if(await Kt.promises.stat(r).then(()=>!0).catch(()=>!1)){(await Kt.promises.readFile(r,"utf8")).includes(e)||(await Kt.promises.appendFile(r,`
|
|
188
188
|
# Added by platform installer
|
|
189
189
|
${e}
|
|
190
|
-
`),m.log(`Added Bun path to ${
|
|
191
|
-
`))}};var
|
|
190
|
+
`),m.log(`Added Bun path to ${mt.default.basename(r)}`));return}}catch(o){m.error(`Failed to update ${r}: ${o.message}`)}m.warn("No shell config file (.zshrc, .bashrc, .bash_profile) found. Please add the following manually:"),m.log(Qn.default.cyan(e))};var $=u(require("chalk")),us=require("execa"),gs=require("jiti");var dt=async e=>{let{stdout:t}=await(0,us.execa)("sh",["-c",e]);return t.trim()},tr="pf-local-nats",hl="2.10-alpine",yl=4222,kl=8222,vl=e=>({clientPort:e.clientPort??yl,monitoringPort:e.monitoringPort??kl,containerName:e.containerName??tr,version:e.version??hl}),Cl=e=>["run","--rm","--detach",`--name=${e.containerName}`,`-p=${e.clientPort}:4222`,`-p=${e.monitoringPort}:8222`,`nats:${e.version}`,"--jetstream","--store_dir=/data","--http_port=8222"],xl=e=>({containerName:e.containerName,clientUrl:`nats://localhost:${e.clientPort}`,monitoringUrl:`http://localhost:${e.monitoringPort}`}),wl=async()=>{try{return await dt("docker info"),!0}catch{return!1}},fs=async e=>{try{return(await dt(`docker ps -q -f name=${e}`)).length>0}catch{return!1}},bl=async e=>{try{await dt(`docker stop ${e} 2>/dev/null || true`),await dt(`docker rm ${e} 2>/dev/null || true`)}catch{}},Sl=async e=>{let t=Cl(e);try{return await dt(`docker ${t.join(" ")}`),{success:!0,value:xl(e)}}catch{return{success:!1}}},Pl=e=>{console.log($.default.green("\u2713 NATS started")),console.log($.default.dim(` Client: ${e.clientUrl}`)),console.log($.default.dim(` Monitoring: ${e.monitoringUrl}`)),console.log($.default.dim(" Streams: ephemeral, auto-created by services")),console.log("")},hs=async(e={})=>{let t=vl(e);if(!await wl())return console.log($.default.yellow("\u26A0\uFE0F Docker not available - skipping NATS (services may fail)")),!1;if(await fs(t.containerName))return console.log($.default.dim("\u2713 NATS already running")),!0;console.log($.default.cyan("\u{1F680} Starting development infrastructure...")),console.log($.default.dim(" NATS with JetStream (ephemeral)"));let n=await Sl(t);return n.success?(Pl(n.value),!0):(console.error($.default.red("\u2717 Failed to start NATS")),!1)},Tl=e=>e.map(t=>({stream:t,subjects:[`${t.toLowerCase()}.*`],config:{storage:"memory",retention:"limits",maxAge:36e5}})),$l=e=>Array.from(new Set(Object.values(e).filter(t=>t!==null&&typeof t=="object"&&"channel"in t).map(t=>t.channel?.stream).filter(t=>!!t))),ys=async e=>{try{let{ensureJetStreams:t}=await import("@crossdelta/cloudevents"),{indexPath:n}=C(e),o=await(0,gs.createJiti)(e).import(n,{default:!0}),s=$l(o);if(s.length===0){console.log($.default.dim(" No streams found in contracts"));return}let a=Tl(s);await t({streams:a}),console.log($.default.dim(` Created ${s.length} ephemeral stream(s): ${s.join(", ")}`))}catch(t){console.log($.default.yellow(` \u26A0\uFE0F Stream creation failed: ${t instanceof Error?t.message:"Unknown error"}`)),console.log($.default.dim(" Stream auto-creation will happen on first publish"))}},El=async(e=tr)=>{await fs(e)&&(console.log($.default.dim("Stopping NATS...")),await bl(e))},ks=async(e=tr)=>{await El(e)};var z=u(require("chalk")),xs=u(require("terminal-link"));var zt="integrations-run";var P=require("zod"),Al=P.z.object({name:P.z.string(),description:P.z.string(),link:P.z.string().url().optional(),install:P.z.union([P.z.string(),P.z.array(P.z.string())]).transform(e=>Array.isArray(e)?e:[e]),installFlags:P.z.array(P.z.string()).optional(),run:P.z.array(P.z.string()).optional(),initial:P.z.boolean().optional(),interactive:P.z.boolean().optional()}),vs=P.z.array(Al);var Cs=e=>{try{return vs.parse(e)}catch(t){throw new Error(t.issues.map(n=>` - Path ${n.path.join(". ")} : ${n.message}`).join(`
|
|
191
|
+
`))}};var L=()=>{try{let e=Et("bin/integration.collection.json");return Cs(e)}catch(e){throw new Error(`Failed to load integrations!
|
|
192
192
|
Check your integration.collection.json:
|
|
193
|
-
${e.message}`)}}
|
|
194
|
-
`))}))},
|
|
195
|
-
`),fn:()=>
|
|
193
|
+
${e.message}`)}},Ne=()=>L().reduce((t,n)=>(n.initial&&t.push(n.name),t),[]),Il=e=>!!e?.name&&!!e?.link&&!!e?.description,qt=e=>{let t=L();if(!t?.length||!e?.length)return;let n=e.map(r=>t.find(o=>o.name===r)).filter(Il);n.length&&(m.breakLine().log("\u{1F50C} Installed Integrations:"),n.forEach(({name:r,link:o,description:s})=>{let a=m.getStoredLogs(`${zt}:${r}`);o&&m.log(`${(0,xs.default)(z.default.cyan(r),o)} - ${s}`),a.length&&m.log(a.map(i=>` \u203A ${z.default.dim(i.message)}`).join(`
|
|
194
|
+
`))}))},Nl=e=>e.toUpperCase().replace(/-/g,"_"),ws=(e,t)=>{let n=Nl(e);m.breakLine().log(z.default.bold("Environment variables:")).log(z.default.dim(" Local:")).log(z.default.cyan(` ${n}_PORT=${t}`)).log(z.default.cyan(` ${n}_URL=http://localhost:${t}`)).breakLine().log(z.default.dim(" Production (auto-configured):")).log(z.default.cyan(` ${n}_PORT=${t}`)).log(z.default.cyan(` ${n}_URL=http://${e}:${t}`))};var nr=u(require("chalk"));var Rl=e=>{let t=e.match(/^(@?[^@]+)@(.+)$/);return t?{name:t[1],version:t[2]}:{name:e,version:"latest"}},bs=async e=>{let{selectedIntegrations:t,cwd:n,packageManager:r=x(),task:o}=e;if(!t?.length||!o)return;let s=jl(t,n,r,o);await Tt(o,s)},jl=(e,t,n,r)=>{let s=L()?.filter(i=>e.includes(i.name))?.flatMap(i=>i.install.map(c=>{let{name:l,version:p}=Rl(c);return{title:nr.default.cyanBright(`Adding ${c} (${i.name})`),fn:async()=>{X(`dependencies.${l}`,p,t)}}})),a={title:nr.default.cyanBright("Installing packages..."),fn:async()=>{await _({cwd:t,packageManager:n,task:r})}};return[...s??[],a]};var Ss=u(require("chalk"));var Ps=async e=>{let{selectedIntegrations:t,cwd:n,task:r}=e;if(!t?.length||!r)return;let o=Ml(t,n,r,e.packageManager);await Tt(r,o)},Ml=(e,t,n,r)=>L().filter(s=>e.includes(s.name)&&s.run?.length).flatMap(s=>(s.run||[]).map(a=>({title:Ss.default.cyanBright(`Running "${a}" for ${s.name}
|
|
195
|
+
`),fn:()=>Fl(s,a,t,n,r)}))),Fl=async(e,t,n,r,o)=>{let s=`${zt}:${e.name}`;try{if(e.interactive)return oo(t,[],{cwd:n,context:s,task:r,manager:o});await Q(t,[],{cwd:n,task:r,context:s})}catch(a){m.error(`Failed to run command "${t}" for ${e.name}: ${a.message}`)}};var Vt=require("node:fs"),ut=require("node:path");var Zt=(e,t)=>{try{let n=(0,Vt.readFileSync)(e,"utf-8"),r=JSON.parse(n);t(r),(0,Vt.writeFileSync)(e,JSON.stringify(r,null,2),"utf-8")}catch{}},Ol=e=>{let t=(0,ut.join)(g(e),"tsconfig.json");Zt(t,n=>{n.compilerOptions.module="ESNext",n.compilerOptions.moduleResolution="bundler",n.compilerOptions.resolvePackageJsonExports=!0,n.compilerOptions.types=n.compilerOptions.types||[],n.compilerOptions.types.includes("bun-types")||n.compilerOptions.types.push("bun-types"),n.exclude=["node_modules","dist"]})},Dl=e=>{let t=(0,ut.join)(g(e),"tsconfig.build.json");Zt(t,n=>{n.exclude=["node_modules","test","dist","**/*.spec.ts","**/*.test.ts"]})},_l=e=>{let t=(0,ut.join)(g(e),"nest-cli.json");Zt(t,n=>{n.compilerOptions=n.compilerOptions||{},n.compilerOptions.tsConfigPath="tsconfig.build.json"})},Bl=e=>{let t=(0,ut.join)(g(e),"package.json");Zt(t,n=>{delete n.jest})},Ts=e=>{Ol(e),Dl(e),_l(e),Bl(e)};var $s=require("node:path");var Hl=(e,t)=>{let n=Vn(e);if(n){for(let{className:r,importPath:o}of t)Yn(n,o,[r]),Xn(n,r);Zn(n)}},Es=e=>{let t=(0,$s.join)(g(e),"src","app.module.ts");Hl(t,[{className:"EventsModule",importPath:"./events/events.module"}])};var Ll=require("fs-extra");var Gl=u(require("chalk")),Ul=u(require("cli-table3"));var As=require("node:fs"),Is=require("node:path"),Ns=u(require("handlebars"));var Re=(e,t)=>So(e,t??`Templates directory not found. Searched in: ${e.join(", ")}`),rr=(e,t={})=>{let n=(0,As.readFileSync)(e,"utf-8");return Ns.default.compile(n)(t)},Yt=e=>(t,n={})=>{let r=(0,Is.join)(e,t);return rr(r,n)};var gt=e=>e.toUpperCase().replace(/-/g,"_");var Rs=e=>e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ");function Xt(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}async function js(e,t,n={},r=[],o=[]){if(!e){console.error("Subcommand is not defined.");return}let s=r.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?`--${Xt(String(l))}`:`--${Xt(String(l))}=${String(p)}`}).filter(l=>l!==void 0),i=Object.entries(n).map(([l,p])=>{if(!(p===!1||p===void 0))return p===!0?`--${Xt(l)}`:`--${Xt(l)}=${String(p)}`}).filter(l=>l!==void 0),c=[...s,...a,...i].map(String);await e.parseAsync(c,{from:"user"})}var na=require("node:path"),te=u(require("chalk"));var Ms=require("@listr2/prompt-adapter-enquirer"),je={title:"Confirm creation",enabled:e=>!e.userConfirmed,task:async(e,t)=>{if(e.userConfirmed=await t.prompt(Ms.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 q=require("node:fs"),Me=require("node:path");function Fs(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
196
196
|
import { ports } from '@crossdelta/infrastructure'
|
|
197
197
|
|
|
198
198
|
/**
|
|
@@ -213,7 +213,7 @@ const config: K8sServiceConfig = {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
export default config
|
|
216
|
-
`}function
|
|
216
|
+
`}function Os(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
217
217
|
import { ports } from '@crossdelta/infrastructure'
|
|
218
218
|
|
|
219
219
|
/**
|
|
@@ -234,71 +234,182 @@ const config: K8sServiceConfig = {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
export default config
|
|
237
|
-
`}var
|
|
238
|
-
`)}),e.shouldInstallBun&&(e.packageManager="bun")}};var
|
|
239
|
-
Press <space> to select/deselect, <enter> to confirm, <i> to invert selection`,message:"Which integrations would you like to include?",initial
|
|
240
|
-
`)}};var
|
|
237
|
+
`}var Jl=4001,Kl=4e3;function zl(e){let t=[],n=e.matchAll(/ports\(\)\.(?:http|https|grpc|primary)\((\d+)\)/g);for(let c of n)t.push(Number(c[1]));let r=e.matchAll(/\.add(?:Http|Grpc)?\((\d+)/g);for(let c of r)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 ql(e,t){let n=t?Jl:Kl,r=new Set;if(!(0,q.existsSync)(e))return n;let o=(0,q.readdirSync)(e).filter(a=>a.endsWith(".ts"));for(let a of o){let i=(0,Me.join)(e,a);try{let c=(0,q.readFileSync)(i,"utf-8"),l=zl(c);for(let p of l)r.add(p)}catch{}}let s=n;for(;r.has(s);)s++;return s}function Vl(e){return(0,Me.basename)(e)}var Qt={title:"Creating infrastructure service config",task:async(e,t)=>{let n=Vl(e.projectName),r=y(),o=(0,Me.join)(r,"infra","services");if(!(0,q.existsSync)(o)){t.title="Skipping infra config (no infra/services directory found)";return}let s=(0,Me.join)(o,`${n}.ts`);if((0,q.existsSync)(s)){t.title=`Service config already exists: infra/services/${n}.ts`;return}let a=ql(o,!0);e.assignedPort=a;let i=e.serviceType==="hono"?Fs(n,a):Os(n,a);(0,q.writeFileSync)(s,i),t.title=`Created infra/services/${n}.ts (port: ${a})`}};var ft=require("node:child_process"),Ds=require("node:fs"),_s=require("node:path"),Zl=()=>{try{return(0,ft.execSync)("git --version",{stdio:"ignore"}),!0}catch{return!1}},Yl=e=>(0,Ds.existsSync)((0,_s.join)(e,".git")),Bs={title:"Initializing git repository",enabled:()=>Zl(),skip:e=>Yl(e.cwd)?"Already a git repository":!1,task:async(e,t)=>{try{(0,ft.execSync)("git init",{cwd:e.cwd,stdio:"ignore"}),(0,ft.execSync)("git add -A",{cwd:e.cwd,stdio:"ignore"}),(0,ft.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 Hs=require("@listr2/prompt-adapter-enquirer"),or=u(require("chalk"));var Fe={title:"Installing Bun",enabled:e=>!!e.shouldInstallBun&&!er(),task:async(e,t)=>S(t,async n=>{await ps(t),e.elapsedTime+=n(),t.title=`Bun installed successfully. (${e.elapsedTime}s)`})},Oe={enabled:e=>!er()&&!e.shouldInstallBun&&!e.packageManager,task:async(e,t)=>{e.shouldInstallBun=await t.prompt(Hs.ListrEnquirerPromptAdapter).run({type:"Toggle",message:"Would you like to use Bun? (recommended)",initial:!0,footer:["",`${or.default.magenta.bold("Bun")} is a fast JavaScript runtime, package manager, bundler, and test runner: ${or.default.underline("https://bun.sh")}`,ms(),ds()].join(`
|
|
238
|
+
`)}),e.shouldInstallBun&&(e.packageManager="bun")}};var Ls=require("@listr2/prompt-adapter-enquirer"),sr=u(require("chalk"));var en={title:"Install integrations",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>S(t,async n=>{let{selectedIntegrations:r,cwd:o,packageManager:s}=e;await bs({selectedIntegrations:r,packageManager:s,cwd:o,task:t}),e.elapsedTime+=n()}),rendererOptions:{outputBar:1e3}},tn={title:"Select integrations",enabled:e=>e.selectedIntegrations.length===0,task:async(e,t)=>{e.selectedIntegrations=await t.prompt(Ls.ListrEnquirerPromptAdapter).run({type:"MultiSelect",hint:`
|
|
239
|
+
Press <space> to select/deselect, <enter> to confirm, <i> to invert selection`,message:"Which integrations would you like to include?",initial:Ne().map((n,r)=>r),choices:e.availableIntegrations.map(({name:n,description:r})=>({name:n,message:[sr.default.bold(n),r].join(" - "),value:n}))}),!e.selectedIntegrations||e.selectedIntegrations.length===0?t.title="No integrations selected.":t.title=["Selected integrations:",...e.selectedIntegrations.map(n=>sr.default.bold(`\u2022 ${n}`))].join(`
|
|
240
|
+
`)}};var Ws={title:"Install Nest CLI",task:async(e,t)=>S(t,async n=>{await ro({packages:["@nestjs/cli"],task:t,cwd:e.cwd}),e.elapsedTime+=n()}),rendererOptions:{outputBar:1e3}};var nn={title:"Install dependencies",task:async(e,t)=>S(t,async n=>{await _({cwd:e.cwd,task:t,packageManager:e.packageManager}),e.elapsedTime+=n()})};var Gs=require("@listr2/prompt-adapter-enquirer"),Us=u(require("chalk"));var De={enabled:e=>!e.removeDir&&!Pt(e.cwd),task:async(e,t)=>{if(e.removeDir=await t.prompt(Gs.ListrEnquirerPromptAdapter).run({type:"Toggle",message:Us.default.bold("\u26A0\uFE0F Overwrite existing directory?"),initial:!1}),!e.removeDir)throw new Error("Project creation was canceled by the user.")}},_e={enabled:e=>!!e.removeDir,task:async e=>Br(e.cwd)};var rn={title:"Run integration commands",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>S(t,async n=>{let{selectedIntegrations:r,cwd:o}=e;await Ps({selectedIntegrations:r,cwd:o,task:t,packageManager:e.packageManager}),e.elapsedTime+=n()}),rendererOptions:{outputBar:1}};var Js=require("@listr2/prompt-adapter-enquirer");var Xl=["services/my-hono-service","services/my-nest-service","my-platform"],Be={enabled:e=>e.skipInputPrompts||e.userConfirmed?!1:e.projectName?Xl.includes(e.projectName):!0,task:async(e,t)=>{e.projectName=await t.prompt(Js.ListrEnquirerPromptAdapter).run({type:"Input",initial:e.projectName,message:"Enter project name",validate:n=>n?!0:"Project name is required."}),e.cwd&&(e.cwd=g(e.projectName))}};var Ks=require("@listr2/prompt-adapter-enquirer"),ar=u(require("chalk"));var He={title:"Select Package manager",task:async(e,t)=>{if(e.packageManager??=bn(),e.packageManager){t.title=`Using ${ar.default.bold(e.packageManager)} as package manager.`;return}e.packageManager=await t.prompt(Ks.ListrEnquirerPromptAdapter).run({type:"Select",message:"Which package manager would you like to use?",initial:Sn(),choices:no}),t.title=`Using ${ar.default.bold(e.packageManager)} as package manager.`}};var on=require("@listr2/prompt-adapter-enquirer"),ht=u(require("chalk")),zs={title:"GitHub repository owner",task:async(e,t)=>{if(e.githubOwner){t.title=`GitHub owner: ${ht.default.bold(e.githubOwner)}`;return}e.githubOwner=await t.prompt(on.ListrEnquirerPromptAdapter).run({type:"Input",message:"Enter GitHub organization or username",initial:"my-org",validate:n=>n?.trim()?!0:"GitHub owner is required."}),t.title=`GitHub owner: ${ht.default.bold(e.githubOwner)}`}},qs={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(on.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 Vs={title:"Pulumi stack name",task:async(e,t)=>{if(e.pulumiStackBase){t.title=`Pulumi stack: ${ht.default.bold(e.pulumiStackBase)}`;return}let n=e.githubOwner||"myorg",r=e.projectName?.replace(/[^a-zA-Z0-9-]/g,"-")||"myproject",o=`${n}/${r}`;e.pulumiStackBase=await t.prompt(on.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: ${ht.default.bold(e.pulumiStackBase)}`}};var O=require("node:fs"),R=require("node:path");var sn=require("node:path");var Ql=()=>{let e=at();return Re([(0,sn.join)(__dirname,"templates","hono-microservice"),(0,sn.join)(__dirname,"..","hono-microservice","templates"),(0,sn.join)(e,"bin","templates","hono-microservice")],"Hono templates directory not found.")},yt=(e,t={})=>Yt(Ql())(e,t);function Zs(){return yt("tsconfig.json.hbs")}function Ys(e="1.2.23"){return yt("Dockerfile.hbs",{bunVersion:e})}function Xs(){return yt("biome.json.hbs")}function Qs(e){return yt("src/index.ts.hbs",{envKey:gt(e)})}function ea(e){return yt("src/config/env.ts.hbs",{envKey:gt(e)})}var ep=async({projectName:e,packageManager:t},n)=>{let r=t==="bun"?"bun":"nodejs";try{await Q("create-hono@latest",[e,"--pm",t,"--template",r,"--install"],{task:n})}catch(s){let a=(0,R.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,R.join)(g(e),"package.json");if(!(0,O.existsSync)(o))throw new Error("Failed to scaffold Hono app structure - package.json not created")},tp=({projectName:e,packageManager:t})=>{let n=(0,R.basename)(e),r=Ce(),o=t==="npm"?"*":"workspace:*",s=g(e),a=Ur("scripts.dev",s);a&&X("scripts.start:dev",a,e),[{field:"name",value:`${r}/${n}`},{field:"scripts.test",value:"bun test"},{field:"scripts.lint",value:"biome lint --write ./src"},{field:`dependencies.${r}/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})=>X(c,l,e))},np=({projectName:e})=>{let t=(0,R.basename)(e),n=(0,R.join)(g(e),"src","index.ts"),r=Qs(t);(0,O.writeFileSync)(n,r)},rp=({projectName:e})=>{let t=(0,R.basename)(e),n=g(e),r=(0,R.join)(n,"src","config");(0,O.existsSync)(r)||(0,O.mkdirSync)(r,{recursive:!0});let o=(0,R.join)(r,"env.ts"),s=ea(t);(0,O.writeFileSync)(o,s)},op=({projectName:e})=>{let t=g(e),n=(0,R.join)(t,"tsconfig.json");(0,O.writeFileSync)(n,Zs());let r=(0,R.join)(t,"Dockerfile");(0,O.writeFileSync)(r,Ys());let o=(0,R.join)(t,"biome.json");(0,O.writeFileSync)(o,Xs())},ta={title:"Create Hono app structure",rendererOptions:{outputBar:1e3},task:async(e,t)=>S(t,async n=>{await ep(e,t),tp(e),np(e),rp(e),op(e),e.elapsedTime+=n()})};var sp=e=>{let t=(e||"my-hono-service").trim();return t.includes("/")||t.startsWith(".")?t:`${D().services}/${t}`},ap=async(e,t)=>{let{valid:n,config:r,error:o}=Ie();if(!n||!r){console.log(o);return}let s=sp(e.name),a=t.packageManager||x(),i=await Gt(t.description);if(Ut(s,r,i),await Jt({servicePath:s,description:i,serviceType:"hono",packageManager:a},r))console.log(te.default.green.bold(`
|
|
241
241
|
\u2705 Service generated successfully!
|
|
242
|
-
`)),console.log(
|
|
243
|
-
${
|
|
242
|
+
`)),console.log(te.default.dim("Next steps:")),console.log(te.default.dim(` ${te.default.cyan("pf dev")} - Start all services`)),console.log(te.default.dim(` ${te.default.cyan(`cd ${s} && bun dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},ra=oe({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:ap,buildContext:async(e,t)=>{let n=(e.name??"my-hono-service").trim();!n.includes("/")&&!n.startsWith(".")&&(n=`${D().services}/${n}`);let r=g(n),o=t.packageManager??(t.yes&&x()),s=L(),a=t.yes?Ne():[],i=t.packageManager==="bun",c=!!t.yes||!!e.name&&e.name!=="my-hono-service";return{cwd:r,projectName:n,packageManager:o,shouldInstallBun:i,availableIntegrations:s,selectedIntegrations:a,serviceType:"hono",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[Be,De,Oe,He,tn,je],actions:[_e,Fe,ta,Qt,en,rn],onComplete:({projectName:e,packageManager:t,selectedIntegrations:n,assignedPort:r})=>{m.breakLine().log(te.default.bold.green("Hono Microservice created successfully!")),qt(n),ws((0,na.basename)(e),r??8080);let o=t??x();m.breakLine().log(`To start the project, run:
|
|
243
|
+
${te.default.bold(`cd ${e} && ${o} run dev`)}`).breakLine().log("Happy shipping with Hono! \u26A1\uFE0F").breakLine()}});var ne=u(require("chalk"));var W=require("node:fs"),j=require("node:path");var cr=require("node:path");var ip=()=>Re([(0,cr.join)(__dirname,"templates","nest-microservice"),(0,cr.join)(__dirname,"..","nest-microservice","templates")],"NestJS templates directory not found."),Le=(e,t={})=>Yt(ip())(e,t);function an(e,t=3e3){return Le("src/main.ts.hbs",{serviceName:e,envKey:gt(e),displayName:Rs(e),defaultPort:t})}function oa(){return Le("src/app.context.ts.hbs",{})}function sa(){return Le("src/events/events.module.ts.hbs",{})}function aa(e){return Le("src/events/events.service.ts.hbs",{serviceName:e})}function ia(e="24",t="1.2.23"){return Le("Dockerfile.hbs",{nodeVersion:e,bunVersion:t})}function ca(){return Le("biome.json.hbs",{})}var cp=async(e,t)=>{await Q("@nestjs/cli",["new",e.projectName,"--skip-install","--skip-git","--package-manager",e.packageManager],{task:t})},lp=({projectName:e,packageManager:t})=>{let n=(0,j.basename)(e),r=Ce(),o=t==="npm"?"*":"workspace:*";[{field:"name",value:`${r}/${n}`},{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.${r}/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})=>X(i,c,e)),["jest","@types/jest","ts-jest","@nestjs/testing","supertest","@types/supertest","ts-node","tsconfig-paths","@nestjs/schematics","@nestjs/cli"].map(i=>X(`devDependencies.${i}`,void 0,e))},pp=({projectName:e})=>{let t=["eslint.config.mjs","src/app.controller.spec.ts"];for(let n of t)try{(0,W.unlinkSync)((0,j.join)(g(e),n))}catch{}},mp=({projectName:e})=>{let t=g(e),n=(0,j.join)(t,"Dockerfile");(0,W.writeFileSync)(n,ia());let r=(0,j.join)(t,"biome.json");(0,W.writeFileSync)(r,ca())},dp=({projectName:e})=>{let t=(0,j.join)(g(e),"src","app.context.ts");(0,W.writeFileSync)(t,oa())},up=({projectName:e})=>{let t=(0,j.basename)(e),n=(0,j.join)(g(e),"src","events");(0,W.mkdirSync)(n,{recursive:!0}),(0,W.writeFileSync)((0,j.join)(n,"events.module.ts"),sa()),(0,W.writeFileSync)((0,j.join)(n,"events.service.ts"),aa(t)),Es(e)},gp=({projectName:e})=>{let t=(0,j.basename)(e),n=(0,j.join)(g(e),"src","main.ts");(0,W.writeFileSync)(n,an(t))},la={title:"Create NestJS app structure",rendererOptions:{outputBar:1e3},task:async(e,t)=>S(t,async n=>{await cp(e,t),lp(e),Ts(e.projectName),pp(e),mp(e),dp(e),up(e),gp(e),e.elapsedTime+=n()})};var pa=require("node:fs"),cn=require("node:path");var ma={title:"Patch main.ts with PORT pattern",task:async(e,t)=>S(t,async n=>{let r=(0,cn.basename)(e.projectName),o=e.assignedPort??3e3,s=(0,cn.join)(g(e.projectName),"src","main.ts");(0,pa.writeFileSync)(s,an(r,o)),t.title=`Patched main.ts with PORT || ${r.toUpperCase().replace(/-/g,"_")}_PORT`,e.elapsedTime+=n()})};var fp=e=>{let t=(e||"my-nest-service").trim();return t.includes("/")||t.startsWith(".")?t:`${D().services}/${t}`},hp=async(e,t)=>{let{valid:n,config:r,error:o}=Ie();if(!n||!r){console.log(o);return}let s=fp(e.name),a=t.packageManager||x(),i=await Gt(t.description);if(Ut(s,r,i),await Jt({servicePath:s,description:i,serviceType:"nest",packageManager:a},r))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")},
|
|
246
|
-
${ne.default.bold(`cd ${e} && ${t} run start:dev`)}`).breakLine().log("Happy coding! \u{1F389}").breakLine()}});var
|
|
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
|
|
248
|
-
`);throw new Error(
|
|
249
|
-
`),
|
|
250
|
-
${
|
|
251
|
-
${
|
|
252
|
-
`));for(let
|
|
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")},da=oe({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:hp,buildContext:async(e,t)=>{let n=(e.name??"my-nest-service").trim();!n.includes("/")&&!n.startsWith(".")&&(n=`${D().services}/${n}`);let r=g(n),o=t.packageManager??(t.yes&&x()),s=t.packageManager==="bun",a=L(),i=t.yes?Ne():[],c=!!t.yes||!!e.name;return{cwd:r,projectName:n,shouldInstallBun:s,packageManager:o,availableIntegrations:a,selectedIntegrations:i,serviceType:"nest",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[Be,De,Oe,He,tn,je],actions:[_e,Fe,la,Qt,ma,nn,Ws,en,rn],onComplete:({projectName:e,packageManager:t,selectedIntegrations:n})=>{m.breakLine().log(ne.default.bold.green("NestJS Microservice created successfully!")),qt(n),m.breakLine().log(`To start the project, run:
|
|
246
|
+
${ne.default.bold(`cd ${e} && ${t} run start:dev`)}`).breakLine().log("Happy coding! \u{1F389}").breakLine()}});var va=require("@listr2/prompt-adapter-enquirer"),M=u(require("chalk"));var V=require("node:fs"),vt=require("node:path");var ua=require("node:fs"),kt=require("node:path");var lr=()=>{let e=at();return Re([(0,kt.join)(__dirname,"templates","workspace"),(0,kt.join)(__dirname,"..","..","..","..","templates","workspace"),(0,kt.join)(e,"bin","templates","workspace")],"Workspace templates directory not found.")},ga=()=>{let e=lr(),t=(0,kt.join)(e,"packages","contracts");if(!(0,ua.existsSync)(t))throw new Error(`Contracts templates directory not found at: ${t}`);return t},ln=(e,t)=>rr(e,t);var yp=()=>{let e=(0,vt.join)(process.cwd(),"package.json");if(!(0,V.existsSync)(e))throw new Error("Root package.json not found. Please run this command from the workspace root.");let n=JSON.parse((0,V.readFileSync)(e,"utf-8")).name;if(!n)throw new Error('package.json must have a "name" field');return n.startsWith("@")?n:`@${n}`},fa=()=>{let e=yp(),{relativePath:t,packagePath:n}=C();if((0,V.existsSync)(n))throw new Error(`${t} already exists. Remove it first if you want to regenerate.`);console.log(`Creating contracts package with scope: ${e}`);let r=ga(),o={scope:e,workspaceName:e.replace("@","").replace("/","-")};(0,V.mkdirSync)(n,{recursive:!0}),(0,V.mkdirSync)((0,vt.join)(n,"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,vt.join)(r,a.template),c=(0,vt.join)(n,a.output),l=ln(i,o);(0,V.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 ya=require("node:child_process"),A=require("node:fs"),We=require("node:path");var ha=e=>{e.endsWith(".sh")&&(0,A.chmodSync)(e,493)},kp=[{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}],ka={title:"Creating workspace structure",task:async(e,t)=>{if((0,A.existsSync)(e.cwd)){t.title="Workspace directory already exists, skipping...";return}let n=lr(),r=e.includeGitHubCI??!0,o=e.packageManager||"bun",s=c=>{try{let d=(0,ya.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=kp.filter(c=>!(c.isGitHubCI&&!r||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,A.existsSync)(p)||(0,A.mkdirSync)(p,{recursive:!0}),c.isStatic){let d=(0,We.join)(n,c.template);(0,A.existsSync)(d)?(0,A.writeFileSync)(l,(0,A.readFileSync)(d)):(0,A.writeFileSync)(l,""),ha(l)}else{let d=(0,We.join)(n,c.template),k=ln(d,a);(0,A.writeFileSync)(l,k),ha(l)}}t.title="Workspace structure created"}};var Ca=oe({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 n=(e.name??"my-platform").trim(),r=g(n),o=!!t.yes,s=t.packageManager??(o?x():void 0),a=t.packageManager==="bun",i=t.githubOwner??(o?"my-org":void 0),c=t.pulumiStack??(o?`${i}/${n}`:void 0),l=t.github===!1?!1:o?!0:void 0,p=!!e.name,d=t.removeDir||o;return{cwd:r,projectName:n,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 n=y();if(!await t.prompt(va.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");t.title=M.default.yellow("Warning: Creating nested workspace")}catch(n){if(n.message?.includes("cancelled"))throw n;t.title="No existing workspace detected"}}},Be,De,zs,qs,Vs,Oe,He,je],actions:[_e,Fe,ka,{title:"Initializing contracts package",task:(e,t)=>{let n=process.cwd();try{process.chdir(e.cwd),fa(),t.title="Contracts package initialized"}catch(r){throw t.title=M.default.red(`Contracts package failed: ${r.message}`),r}finally{process.chdir(n)}}},nn,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 Ct=[{name:"Hono Microservice",value:"hono-micro",command:ra,supportsAi:!0},{name:"Nest Microservice",value:"nest-micro",command:da,supportsAi:!0},{name:"Workspace (Infrastructure)",value:"workspace",command:Ca,supportsAi:!1}],xa=()=>{let e=oe({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,n)=>{let r=await n.prompt(ie.ListrEnquirerPromptAdapter).run({type:"select",message:"Select Project type",choices:Ct});t.projectType=Ct.find(o=>o.name===r)?.value||"",n.title=`Using ${re.default.bold(r)}`}},{enabled:t=>t.projectType!=="workspace"&&t.projectType!=="",task:async(t,n)=>{try{y(),n.title="Workspace detected"}catch{let r=["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
|
+
`);throw new Error(r)}}},{enabled:t=>t.projectType==="workspace",task:async(t,n)=>{try{let r=y();if(!await n.prompt(ie.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");n.title=re.default.yellow("Warning: Creating nested workspace")}catch(r){if(r.message?.includes("cancelled"))throw r;n.title="No existing workspace detected"}}},{enabled:t=>!!t.projectType,task:async(t,n)=>{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 n.prompt(ie.ListrEnquirerPromptAdapter).run({type:"input",message:s,initial:o});t.servicePath=a.trim(),n.title=`Path: ${re.default.dim(a)}`}},{enabled:t=>!!Ct.find(r=>r.value===t.projectType)?.supportsAi&&Ie().valid,task:async(t,n)=>{let r=await n.prompt(ie.ListrEnquirerPromptAdapter).run({type:"toggle",message:"Use AI to generate service code?",enabled:"Yes",disabled:"No",initial:!1});t.useAi=r,n.title=r?re.default.cyan("\u{1F916} AI-powered generation"):"Standard scaffolding"}},{enabled:t=>t.useAi,task:async(t,n)=>{let r=await n.prompt(ie.ListrEnquirerPromptAdapter).run({type:"input",message:"Describe what this service should do:"});t.aiDescription=r,n.title=`Description: ${re.default.dim(r.slice(0,50))}${r.length>50?"...":""}`}},{enabled:t=>{if(!t.servicePath)return!1;let n=g(t.servicePath);return!Pt(n)},task:async(t,n)=>{if(!await n.prompt(ie.ListrEnquirerPromptAdapter).run({type:"toggle",message:re.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,n.title=re.default.yellow("Will overwrite existing directory")}},{title:"Confirm creation",enabled:t=>t.projectType!=="workspace",task:async(t,n)=>{if(!await n.prompt(ie.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=>{Ct.find(s=>s.value===t.projectType)||e.error(re.default.red(`Project type ${t.projectType} is not supported.`));let n=e.commands.find(s=>s.name()===t.projectType),r={};t.projectType!=="workspace"&&(r.yes=!0);let o=[];t.servicePath&&o.push("servicePath"),t.shouldRemoveDir&&(r.removeDir=!0),t.useAi&&(r.ai=!0,r.description=t.aiDescription),await js(n,t,r,o)}});for(let t of Ct)e.addCommand(t.command);return e};var Sa=require("commander");var ce=u(require("chalk"));var pr=e=>new Promise(t=>setTimeout(t,e)),he=e=>process.stdout.write(`${e}
|
|
249
|
+
`),vp=()=>{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")},wa=()=>({turboProcess:null,isRestarting:!1,isShuttingDown:!1}),ba=async(e,t)=>{let n=qr(".env.local",t);n.length>0&&(await Xr(n),await pr(50)),he(ce.default.cyan("\u{1F525} Starting services...")),he(ce.default.dim(` Command: turbo run ${gn} --continue`)),e.isShuttingDown=!1,e.isRestarting=!1,e.turboProcess=Yr("turbo",["run",gn,"--continue","--no-daemon"],{cwd:t,envFile:".env.local",onExit:r=>{!e.isRestarting&&!e.isShuttingDown&&(r===0?he(`
|
|
250
|
+
${ce.default.cyan("\u{1F440} Dev mode ready. Waiting for file changes...")}`):(he(`
|
|
251
|
+
${ce.default.yellow("\u26A0\uFE0F A service has crashed")} (exit code: ${r})`),he(ce.default.dim("Check the logs above to see which service failed.")),he(ce.default.dim("Fix the error and save the file to restart automatically."))),he(ce.default.dim("Press Ctrl+C to exit dev mode.")))}})},mr=async(e,t=!1)=>{let n=e.turboProcess?.pid;if(n){t?e.isRestarting=!0:e.isShuttingDown=!0;try{try{process.kill(-n,"SIGTERM")}catch{e.turboProcess?.kill("SIGTERM")}await pr(200);try{process.kill(-n,"SIGKILL")}catch{}await pr(30)}catch{}e.turboProcess=null,vp()}};var Cp=300,Pa=new Sa.Command("dev").description("Start development mode with auto-reload").action(async()=>{let e=y(),t=wa(),n=l=>et("generate-env",{cwd:l}),r=()=>_({cwd:e,quiet:!0}),o=null,s=async()=>{await r(),await n(e),await hs()&&await ys(e),await ba(t,e)},a=async()=>{if(!(t.isRestarting||t.isShuttingDown)){t.isRestarting=!0;try{await mr(t,!0),await s()}catch{}finally{t.isRestarting=!1}}},i=(()=>{let l=null;return async()=>{t.isRestarting||t.isShuttingDown||(l&&clearTimeout(l),l=setTimeout(()=>a(),Cp))}})(),c=async()=>{await mr(t,!1),await ks(),o&&await o(),process.exit(0)};await s(),o=bo(e,i),process.on("SIGINT",c),process.on("SIGTERM",c)});var Ga=require("commander");var Ta=require("node:fs"),$a=require("node:path"),Z=u(require("chalk")),Ea=require("commander");var xp=e=>{if(e)try{return JSON.parse(e)}catch{return}},wp=e=>{if(!e)return;let t={},n=e.split(",").map(r=>r.trim()).filter(Boolean);for(let r of n){let[o,s]=r.split(":").map(a=>a.trim());o&&s&&(t[o]=s)}return Object.keys(t).length>0?t:void 0},bp=(e,t)=>{if(!t)return;let n=t.startsWith("/")?t:(0,$a.resolve)(e,t);return(0,Ta.existsSync)(n)?n:void 0},Sp=async(e,t)=>{let n=[],r=[],o=[];if(An(e)&&!t.force)r.push("Contract (already exists)");else{let a=In(e,t.schema);n.push(`Contract: ${a}`)}Bn(e)&&n.push("Export: packages/contracts/src/index.ts");let s=await Dt(e);if(s&&n.push(`Mock: ${s}`),t.servicePath){let a=Mn(e,t.servicePath);a?n.push(`Handler: ${a}`):r.push("Handler (already exists)");let i=jn(t.servicePath,e);i.added?n.push(`Stream: ${i.streamName} added to index.ts`):i.warning&&o.push(i.warning)}return{created:n,skipped:r,warnings:o}},Pp=(e,t,n=[])=>{if(e.length>0){console.log(Z.default.green(`\u2713 Created:
|
|
252
|
+
`));for(let r of e)console.log(Z.default.dim(` ${r}`))}if(t.length>0){console.log(Z.default.yellow(`
|
|
253
253
|
\u2139 Skipped:
|
|
254
|
-
`));for(let
|
|
254
|
+
`));for(let r of t)console.log(Z.default.dim(` ${r}`))}if(n.length>0){console.log(Z.default.yellow(`
|
|
255
255
|
\u26A0 Warning:
|
|
256
|
-
`));for(let
|
|
256
|
+
`));for(let r of n)console.log(Z.default.dim(` ${r}`))}},dr=async(e,t)=>{let n=y();if(!n){m.error("Not in a pf workspace. Run this command from your workspace root.");return}if(!e.includes(".")){m.error("Event type must include a namespace (e.g., orders.created)");return}let r=wp(t.fields)||xp(t.schema);if(t.schema&&!r&&!t.fields){m.error(`Invalid schema JSON. Example: '{"orderId":"string","total":"number"}'`);return}if(t.fields&&!r){m.error("Invalid fields format. Example: orderId:string,total:number");return}let o=bp(n,t.service);if(t.service&&!o){m.error(`Service directory not found: ${t.service}`);return}console.log(Z.default.cyan(`
|
|
257
257
|
\u{1F4E6} Adding event: ${e}
|
|
258
|
-
`));let{created:s,skipped:a,warnings:i}=await
|
|
259
|
-
`)),console.log(
|
|
260
|
-
`)))}
|
|
261
|
-
Install it in your contracts package with: cd packages/contracts && bun add @crossdelta/cloudevents`)}return
|
|
262
|
-
\u{1F4E6} Event Type:`,s.eventName),console.log("\u{1F4C4} Payload:"),console.dir(a,{colors:!0,depth:null});return}try{let i=await
|
|
258
|
+
`));let{created:s,skipped:a,warnings:i}=await Sp(e,{schema:r,servicePath:o,force:t.force});Pp(s,a,i),console.log(),t.service||(console.log(Z.default.yellow(`\u{1F4A1} Tip: Use --service to also create an event handler:
|
|
259
|
+
`)),console.log(Z.default.dim(` pf event add ${e} --service services/my-service
|
|
260
|
+
`)))},ay=new Ea.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(dr);var Na=require("commander");var Aa=require("fs-extra"),Ia=require("globby"),le=require("zod");var Tp=["**/node_modules/**","**/.nats-data/**","**/dist/**","**/build/**","**/.git/**","**/coverage/**"],$p=le.z.record(le.z.string()),Ep=le.z.object({description:le.z.string().optional(),eventName:le.z.string(),faker:$p.optional(),data:le.z.record(le.z.any())}),Ge=(e=process.cwd())=>(0,Ia.globbySync)("**/*.mock.json",{cwd:e,absolute:!0,gitignore:!0,ignore:Tp}).map(n=>{try{let r=(0,Aa.readJSONSync)(n,{encoding:"utf8"}),o=Ep.safeParse(r);return o.success?{eventName:o.data.eventName,path:n,schema:o.data}:(m.warn(`\u26A0\uFE0F Invalid schema in ${n}`),console.log(o.error.format()),null)}catch{return m.warn(`\u26A0\uFE0F Failed to read or parse ${n}`),null}}).filter(n=>n!==null);var ur=null,Ra=async()=>{if(!ur){let{faker:e}=await import("@faker-js/faker");ur=e}return ur},gr=async(e,t)=>{let n=await Ra(),o=Ge().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 Ap(s):s.data,c={message:{data:Buffer.from(JSON.stringify({...a,type:s.eventName})).toString("base64"),messageId:n.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.")},dy=new Na.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(gr),Ap=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([n,r])=>{let o=await Ip(r);St(t,n,o)})),t},Ip=async e=>{let t=await Ra();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 fr=require("node:fs"),ja=require("node:path"),hr=require("globby");var Np=["**/node_modules/**","**/.nats-data/**","**/dist/**","**/build/**","**/.git/**","**/coverage/**"],Rp=e=>{let t=e.split("/"),n=t.indexOf("services");return n!==-1&&n+1<t.length?t[n+1]:"unknown"},jp=(e,t)=>{try{let{eventsPath:n}=C(t),o=(0,hr.globbySync)("**/*.ts",{cwd:n,absolute:!0}).map(a=>({file:a,content:(0,fr.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}},Mp=e=>e.replace(/Contract$/,"").replace(/([A-Z])/g,(t,n,r)=>(r>0?".":"")+n.toLowerCase()),Fp=(e,t)=>{let n=e.match(/handleEvent\s*\(\s*\{\s*[^}]*type:\s*['"]([^'"]+)['"]/s);if(n)return n[1];let r=e.match(/handleEvent\s*\(\s*['"]([^'"]+)['"]/s);if(r)return r[1];let o=e.match(/import\s+(?:type\s+)?{[^}]*?(\w+Contract)[^}]*?}\s+from/);if(!o)return null;let s=o[1];return jp(s,t)||Mp(s)},Op=(e,t)=>{try{let n=(0,fr.readFileSync)(e,"utf-8"),r=Fp(n,t);return r?{serviceName:Rp(e),handlerPath:(0,ja.relative)(t,e),eventType:r}:null}catch{return null}},Ma=(e=process.cwd())=>(0,hr.globbySync)("services/**/src/events/*.handler.ts",{cwd:e,absolute:!0,gitignore:!0,ignore:Np}).map(n=>Op(n,e)).filter(n=>n!==null),Fa=e=>e.reduce((t,n)=>{let r=t.get(n.eventType)||[];return t.set(n.eventType,[...r,n]),t},new Map);var Da=u(require("cli-table3"));var Oa=(e,t)=>{let n=t.get(e)||[],r=[...new Set(n.map(o=>o.serviceName))];return r.length>0?r.join(", "):"-"};var _a=(e,t)=>{let n=new Da.default({head:["name","description","consumers"],style:{head:["dim","bold"],compact:!0}});for(let{eventName:r,schema:o}of e)n.push([r,o.description||"-",Oa(r,t)]);return n.toString()};var yr=e=>{if(!Gr()){if(e.namesOnly)return;m.error("This command must be run from within a workspace."),m.info("To create a new workspace, run: pf new workspace my-platform"),process.exit(1)}let t=Ge();if(t.length===0){m.error("No event schemas found.");return}if(e.namesOnly){for(let s of t)console.log(s.eventName);return}let n=Ma(),r=Fa(n),o=_a(t,r);console.log(o)},Sy=new Ba.Command("event:list").description("List all available event mocks").option("--names-only","Output only event names (for completion)").action(yr);var Ha=require("node:path"),La=require("commander");var Hp={},kr=null,vr=null,Wa=async()=>{if(!kr){let{faker:e}=await import("@faker-js/faker");kr=e}return kr},Dp=async()=>{if(!vr)try{let{createJiti:e}=await import("jiti"),t=e(Hp.url),n=y(),r=C(n),o=(0,Ha.join)(r.packagePath,"node_modules","@crossdelta","cloudevents");vr=(await t.import(o)).publish}catch{throw new Error(`@crossdelta/cloudevents is required for event:publish.
|
|
261
|
+
Install it in your contracts package with: cd packages/contracts && bun add @crossdelta/cloudevents`)}return vr},Cr=async(e,t)=>{let n=await Wa(),o=Ge().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 _p(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 Dp();if(!i)throw new Error("Failed to load publish function from cloudevents");await i(s.eventName,a,{source:"platform-sdk-cli",subject:n.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)}},Ay=new La.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(Cr),_p=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([n,r])=>{let o=await Bp(r);St(t,n,o)})),t},Bp=async e=>{let t=await Wa();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 xt=new Ga.Command("event").description("Event management commands");xt.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(dr);xt.command("list").description("List all available event mocks").option("--names-only","Output only event names (for completion)").action(yr);xt.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(Cr);xt.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(gr);var Ua=xt;var br=u(require("chalk")),Va=require("commander");var Ue=require("node:fs"),wr=u(require("node:path")),pn=u(require("chalk")),Ja=require("commander"),Ka=u(require("os"));var{name:Lp,publishConfig:Wp}=G,Gp=Wp?.registry,Up=Lp?.split("/")[0],_y=new Ja.Command("token:set").description(pn.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)",Up).option("--registry <registry>","Registry URL",Gp).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)=>za(e,t.scope||"",t.registry||"",t.local,t.force)).addHelpText("after",()=>`${pn.default.cyan(`
|
|
263
263
|
Example:`)}
|
|
264
|
-
${
|
|
265
|
-
`),
|
|
266
|
-
//${
|
|
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),
|
|
264
|
+
${pn.default.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
265
|
+
`),Jp=e=>e?wr.default.join(process.cwd(),".npmrc"):wr.default.join(Ka.default.homedir(),".npmrc"),Kp=(e,t,n)=>{let r=new URL(n).host;return t?`${t}:registry=https://${r}
|
|
266
|
+
//${r}/:_authToken=${e}`:`//${r}/:_authToken=${e}`},zp=e=>(0,Ue.existsSync)(e)?(0,Ue.readFileSync)(e,"utf8"):"",xr=(e,t)=>(0,Ue.writeFileSync)(e,t),za=(e,t,n,r=!1,o=!1)=>{let s=Jp(r),a=Kp(e,t,n),i=new URL(n).host,c=zp(s),l=new RegExp(`//${i}/:_authToken=\\S+`);if(!c){xr(s,`${a}
|
|
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),xr(s,c),m.success(`Overwrote existing token for ${i} in ${s}`);return}c+=`
|
|
268
268
|
${a}
|
|
269
|
-
`,
|
|
269
|
+
`,xr(s,c),m.success(`Appended token for ${i} to ${s}`)},qa=(e,t)=>za(e,t.scope||"",t.registry||"",t.local,t.force);var{name:qp,publishConfig:Vp}=G,Zp=Vp?.registry,Yp=qp?.split("/")[0],Za=new Va.Command("token").description("Token management commands");Za.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)",Yp).option("--registry <registry>","Registry URL",Zp).option("--local","Write token to a local .npmrc in the current directory",!1).option("--force","Force overwrite existing token if already present",!1).action(qa).addHelpText("after",()=>`${br.default.cyan(`
|
|
270
270
|
Example:`)}
|
|
271
|
-
${
|
|
272
|
-
`);var
|
|
273
|
-
`)),e}catch{return console.log(
|
|
274
|
-
`)),null}}async function
|
|
275
|
-
\u{1F4CB} Get your ${e} API key here:`)),console.log(
|
|
276
|
-
`)),(0,
|
|
271
|
+
${br.default.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
272
|
+
`);var Ya=Za;var Ke=u(require("chalk")),Tr=require("commander");var Y=require("@inquirer/prompts"),w=u(require("chalk"));var Xp=[/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],Qp=async(e,t,n=1e4)=>{let r=new AbortController,o=setTimeout(()=>r.abort(),n);try{return await fetch(e,{...t,signal:r.signal})}finally{clearTimeout(o)}},em=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(),tm=async(e,t)=>{let n=nt(e),r=await Qp(n.modelsApiUrl,{headers:n.buildHeaders(t)});if(!r.ok)throw new Error(`${n.name} API error: ${r.status}`);let o=await r.json(),s=n.parseModelsResponse(o);if(!Array.isArray(s)||s.length===0)throw new Error(`No models returned from ${n.name} API`);let a=s.filter(i=>{let c=n.modelFilters.some(p=>p.test(i.id)),l=Xp.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:em(i.id),value:i.id}));if(a.length===0)throw new Error(`No chat models found from ${n.name} API`);return a};async function Xa(e,t){if(!t)throw new Error("API key is required to fetch available models");return{models:await tm(e,t),fromApi:!0}}function nm(){if(!rt())return null;try{let e=Rt();return console.log(w.default.dim(`Found existing configuration at ${ge}
|
|
273
|
+
`)),e}catch{return console.log(w.default.yellow(`Found corrupted configuration, starting fresh.
|
|
274
|
+
`)),null}}async function rm(e,t){return console.log(w.default.dim(`
|
|
275
|
+
\u{1F4CB} Get your ${e} API key here:`)),console.log(w.default.cyan(` ${t}
|
|
276
|
+
`)),(0,Y.password)({message:`Enter your ${e} API key:`,mask:"*",validate:n=>n.trim()?n.length<10?"API key seems too short":!0:"API key cannot be empty"})}async function om(e,t,n){let r=await(0,Y.select)({message:"Select model:",choices:e,default:t?.provider===n?t.model:void 0});return await(0,Y.confirm)({message:"Enter a custom model ID instead?",default:!1})?(0,Y.input)({message:"Enter custom model ID:",default:r,validate:s=>s.trim()?!0:"Model ID cannot be empty"}):r}function Qa(e){return e.length<=12?"****":`${e.slice(0,4)}...${e.slice(-4)}`}function sm(e,t){console.log(w.default.green.bold(`
|
|
277
277
|
\u2705 AI configuration saved successfully!
|
|
278
|
-
`)),console.log(
|
|
279
|
-
`)),console.log(
|
|
280
|
-
`))}async function
|
|
278
|
+
`)),console.log(w.default.dim(`Configuration file: ${ge}`)),console.log(w.default.dim("API Key: Stored securely in system keychain")),console.log(w.default.dim(`Provider: ${e.provider}`)),console.log(w.default.dim(`Model: ${e.model}`)),console.log(w.default.dim(`API Key: ${Qa(t)}
|
|
279
|
+
`)),console.log(w.default.cyan("You can now use AI-powered service generation:")),console.log(w.default.dim(` pf new hono-micro services/my-service --ai
|
|
280
|
+
`))}async function am(e){let t=await Nt(e);if(t)return t;let n=nt(e);return process.env[n.defaultApiKeyEnvVar]??null}async function ei(){console.log(w.default.cyan.bold(`
|
|
281
281
|
\u{1F916} AI Configuration Setup
|
|
282
|
-
`));let e=
|
|
283
|
-
\u2713 Found existing API key: ${
|
|
284
|
-
Fetching available models...`));let s;try{s=(await
|
|
285
|
-
`))}catch(c){console.error(
|
|
286
|
-
\u274C Failed to fetch models: ${c.message}`)),console.log(
|
|
282
|
+
`));let e=nm();try{let t=await(0,Y.select)({message:"Select AI provider:",choices:ho(),default:e?.provider??Tn.provider}),n=nt(t),r,o=await am(t);o&&(console.log(w.default.green(`
|
|
283
|
+
\u2713 Found existing API key: ${Qa(o)}`)),await(0,Y.confirm)({message:"Use this existing API key?",default:!0})&&(r=o)),r||(r=await rm(n.name,n.apiKeyUrl)),console.log(w.default.dim(`
|
|
284
|
+
Fetching available models...`));let s;try{s=(await Xa(t,r)).models,console.log(w.default.green(`\u2713 Loaded ${s.length} models from ${n.name} API
|
|
285
|
+
`))}catch(c){console.error(w.default.red(`
|
|
286
|
+
\u274C Failed to fetch models: ${c.message}`)),console.log(w.default.yellow(`
|
|
287
287
|
Please check your API key and try again.
|
|
288
|
-
`)),process.exit(1)}let a=await
|
|
288
|
+
`)),process.exit(1)}let a=await om(s,e,t),i={provider:t,model:a.trim()};vo(i),await Co(t,r),sm(i,r)}catch(t){throw t.name==="ExitPromptError"&&(console.log(w.default.yellow(`
|
|
289
289
|
Setup cancelled.
|
|
290
|
-
`)),process.exit(0)),t}}var
|
|
290
|
+
`)),process.exit(0)),t}}var pe=require("node:fs"),Sr=require("node:os"),Je=require("node:path"),wt=u(require("chalk"));var ti=e=>e.commands.map(t=>({name:t.name(),description:t.description()||t.name()})),mn=(e,t)=>{let n=e.commands.find(r=>r.name()===t);return n?.commands.length?n.commands.map(r=>({name:r.name(),description:r.description()||r.name()})):[]},dn=(e,t)=>{let n=e.commands.find(r=>r.name()===t);return n?n.options.map(r=>({flag:r.long||r.short||"",description:r.description||""})).filter(r=>r.flag):[]};var ni=(e,t,n)=>t.map(r=>{let o=mn(n,r.name),s=dn(n,r.name);if(o.length>0){let a=o.map(i=>` '${i.name}:${i.description}'`).join(`
|
|
291
|
+
`);return r.name==="event"?` ${r.name})
|
|
292
|
+
case $line[2] in
|
|
293
|
+
publish)
|
|
294
|
+
local -a events
|
|
295
|
+
events=(\${(f)"$(${e} event list --names-only 2>/dev/null)"})
|
|
296
|
+
_describe 'available events' events
|
|
297
|
+
;;
|
|
298
|
+
*)
|
|
299
|
+
local -a ${r.name}_commands
|
|
300
|
+
${r.name}_commands=(
|
|
301
|
+
${a}
|
|
302
|
+
)
|
|
303
|
+
_describe '${r.name} commands' ${r.name}_commands
|
|
304
|
+
;;
|
|
305
|
+
esac
|
|
306
|
+
;;`:` ${r.name})
|
|
307
|
+
local -a ${r.name}_commands
|
|
308
|
+
${r.name}_commands=(
|
|
309
|
+
${a}
|
|
310
|
+
)
|
|
311
|
+
_describe '${r.name} commands' ${r.name}_commands
|
|
312
|
+
;;`}if(s.length>0){let a=s.map(i=>` '${i.flag}[${i.description}]'`).join(` \\
|
|
313
|
+
`);return` ${r.name})
|
|
314
|
+
_arguments \\
|
|
315
|
+
${a}
|
|
316
|
+
;;`}return null}).filter(Boolean).join(`
|
|
317
|
+
`),ri=(e,t,n)=>t.map(r=>{let o=mn(n,r.name),s=dn(n,r.name);if(o.length>0){let a=o.map(i=>i.name).join(" ");return r.name==="event"?` ${r.name})
|
|
318
|
+
case "\${COMP_WORDS[2]}" in
|
|
319
|
+
publish)
|
|
320
|
+
opts="$(${e} event list --names-only 2>/dev/null)"
|
|
321
|
+
;;
|
|
322
|
+
*)
|
|
323
|
+
opts="${a}"
|
|
324
|
+
;;
|
|
325
|
+
esac
|
|
326
|
+
;;`:` ${r.name})
|
|
327
|
+
opts="${a}"
|
|
328
|
+
;;`}if(s.length>0){let a=s.map(i=>i.flag).join(" ");return` ${r.name})
|
|
329
|
+
opts="${a}"
|
|
330
|
+
;;`}return null}).filter(Boolean).join(`
|
|
331
|
+
`),oi=(e,t,n)=>{let r=[];for(let o of t){let s=mn(n,o.name),a=dn(n,o.name);s.length>0&&(r.push(`
|
|
332
|
+
# ${o.name} subcommands`),r.push(...s.map(i=>`complete -c ${e} -f -n "__fish_seen_subcommand_from ${o.name}" -a "${i.name}" -d "${i.description}"`)),o.name==="event"&&(r.push(`
|
|
333
|
+
# Dynamic event completion for 'event publish'`),r.push(`complete -c ${e} -f -n "__fish_seen_subcommand_from event; and __fish_seen_subcommand_from publish" -a "(${e} event list --names-only 2>/dev/null)"`))),a.length>0&&(r.push(`
|
|
334
|
+
# ${o.name} options`),r.push(...a.map(i=>`complete -c ${e} -f -n "__fish_seen_subcommand_from ${o.name}" -l ${i.flag.replace(/^--/,"")} -d "${i.description}"`)))}return r};var si=({binName:e,mainCommands:t,subcommandCases:n})=>`# ${e} completion
|
|
335
|
+
_${e}_completions() {
|
|
336
|
+
local line state
|
|
337
|
+
|
|
338
|
+
_arguments -C \\
|
|
339
|
+
"1: :->cmds" \\
|
|
340
|
+
"*::arg:->args"
|
|
341
|
+
|
|
342
|
+
case "$state" in
|
|
343
|
+
cmds)
|
|
344
|
+
local -a subcmds
|
|
345
|
+
subcmds=(
|
|
346
|
+
${t}
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
# Add dynamic workspace commands if in workspace
|
|
350
|
+
local -a workspace_cmds
|
|
351
|
+
workspace_cmds=(\${(f)"$(${e} __workspace-commands --names-only 2>/dev/null)"})
|
|
352
|
+
if [[ \${#workspace_cmds[@]} -gt 0 ]]; then
|
|
353
|
+
subcmds+=(\${workspace_cmds[@]})
|
|
354
|
+
fi
|
|
355
|
+
|
|
356
|
+
_describe 'command' subcmds
|
|
357
|
+
;;
|
|
358
|
+
args)
|
|
359
|
+
case $line[1] in
|
|
360
|
+
${n}
|
|
361
|
+
esac
|
|
362
|
+
;;
|
|
363
|
+
esac
|
|
364
|
+
}
|
|
365
|
+
compdef _${e}_completions ${e}`,ai=({binName:e,mainCommands:t,subcommandCases:n})=>`# ${e} completion
|
|
366
|
+
_${e}_completions() {
|
|
367
|
+
local cur prev opts base
|
|
368
|
+
COMPREPLY=()
|
|
369
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
370
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
371
|
+
|
|
372
|
+
# Top-level commands (including dynamic workspace commands)
|
|
373
|
+
opts="${t}"
|
|
374
|
+
|
|
375
|
+
# Add workspace commands if available
|
|
376
|
+
local workspace_cmds
|
|
377
|
+
workspace_cmds="$(${e} __workspace-commands --names-only 2>/dev/null)"
|
|
378
|
+
if [[ -n "$workspace_cmds" ]]; then
|
|
379
|
+
opts="$opts $workspace_cmds"
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
# Subcommands
|
|
383
|
+
case "\${COMP_WORDS[1]}" in
|
|
384
|
+
${n}
|
|
385
|
+
esac
|
|
386
|
+
|
|
387
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
388
|
+
return 0
|
|
389
|
+
}
|
|
390
|
+
complete -F _${e}_completions ${e}`,ii=(e,t,n)=>{let r=`
|
|
391
|
+
# Dynamic workspace commands
|
|
392
|
+
complete -c ${e} -f -n "__fish_use_subcommand" -a "(${e} __workspace-commands --names-only 2>/dev/null)"`;return`# ${e} completion
|
|
393
|
+
${t}${n.join(`
|
|
394
|
+
`)}${r}`};var ci=()=>{let e=process.env.SHELL||"";return e.includes("zsh")?"zsh":e.includes("bash")?"bash":e.includes("fish")?"fish":null},im=e=>{let t=(0,Sr.homedir)();switch(e){case"zsh":return(0,Je.join)(t,".zshrc");case"bash":return(0,Je.join)(t,".bashrc");case"fish":return(0,Je.join)(t,".config","fish","config.fish");default:return(0,Je.join)(t,".profile")}};var cm=(e,t)=>{let n=ci(),r=ti(t);switch(n){case"zsh":{let o=r.map(a=>` '${a.name}:${a.description}'`).join(`
|
|
395
|
+
`),s=ni(e,r,t);return si({binName:e,mainCommands:o,subcommandCases:s})}case"bash":{let o=r.map(a=>a.name).join(" "),s=ri(e,r,t);return ai({binName:e,mainCommands:o,subcommandCases:s})}case"fish":{let o=r.map(a=>`complete -c ${e} -f -n "__fish_use_subcommand" -a "${a.name}" -d "${a.description}"`).join(`
|
|
396
|
+
`),s=oi(e,r,t);return ii(e,o,s)}default:return null}},Pr=(e,t)=>{let n=ci();if(!n)return console.log(wt.default.yellow("\u26A0\uFE0F Could not detect shell (bash, zsh, fish supported)")),!1;let r=(0,Sr.homedir)(),o=(0,Je.join)(r,`.${e}-completion.${n}`),s=im(n),a=cm(e,t);if(!a)return console.log(wt.default.yellow("\u26A0\uFE0F Could not generate completion script")),!1;try{(0,pe.writeFileSync)(o,a);let i=`
|
|
397
|
+
# ${e} completion
|
|
398
|
+
[ -f "${o}" ] && source "${o}"
|
|
399
|
+
`;return(0,pe.existsSync)(s)&&(0,pe.readFileSync)(s,"utf-8").includes(o)?(console.log(wt.default.dim(`Already installed to ${s}`)),!0):((0,pe.appendFileSync)(s,i),!0)}catch{return console.log(wt.default.red("\u2716 Failed to install completion")),!1}};var un=(e,t)=>new Tr.Command("setup").description("Configure platform settings").option("--ai","Configure AI provider and API key for code generation").option("--completion","Install shell autocompletion").addHelpText("after",`
|
|
291
400
|
Examples:
|
|
292
|
-
# Configure AI provider (OpenAI, Anthropic)
|
|
293
401
|
$ pf setup --ai
|
|
294
|
-
|
|
402
|
+
$ pf setup --completion
|
|
403
|
+
`).action(async n=>{if(n.ai){await ei();return}if(n.completion){Pr(t,e)&&(console.log(Ke.default.green(`
|
|
404
|
+
\u2714 Shell autocompletion installed!`)),console.log(Ke.default.dim(` Restart your shell to activate
|
|
405
|
+
`)));return}console.log(Ke.default.cyan.bold(`
|
|
295
406
|
\u2699\uFE0F Platform Setup
|
|
296
407
|
`)),console.log(`Available setup options:
|
|
297
|
-
`),console.log(
|
|
408
|
+
`),console.log(Ke.default.dim(" --ai Configure AI provider")),console.log(Ke.default.dim(" --completion Install shell autocompletion")),console.log()}),lm=un(new Tr.Command,"pf");var li=require("node:fs"),pi=require("node:path"),ze=u(require("chalk"));var pm=(e,t)=>t.some(n=>n.name()===e),mm=(e,t)=>t.pf?.commands?.[e]??null,dm=(e,t)=>!!t.scripts?.[e],um=(e,t)=>t.cwd?(0,pi.join)(e,t.cwd):e,gm=(e,t)=>t.command||e,fm=(e,t,n,r)=>{let o=um(r,n),s=gm(e,n);if(n.cwd&&!(0,li.existsSync)(o))return console.error(ze.default.red(`
|
|
298
409
|
\u2716 Directory not found: ${o}
|
|
299
|
-
`)),!0;let a=
|
|
300
|
-
Workspace Commands:`,...
|
|
301
|
-
`)}function
|
|
302
|
-
\u2716 An unexpected error occurred:`)),console.error(e),process.exit(1)});var
|
|
410
|
+
`)),!0;let a=n.cwd?ze.default.dim(` in ${n.cwd}/`):"";return console.log(ze.default.dim(`Running ${s}${a}`)),At(s,t,{cwd:o}),!0},hm=(e,t,n)=>(console.log(ze.default.dim(`Running workspace script: ${e}`)),et(e,{args:t,cwd:n}),!0);async function ym(e,t,n){if(pm(e,n))return!1;let r;try{r=y()}catch{return!1}let o=ve(r);if(!o)return!1;let s=mm(e,o);return s?fm(e,t,s,r):dm(e,o)?hm(e,t,r):!1}function mi(){let e;try{e=ve()}catch{return{configured:[],scripts:[]}}if(!e)return{configured:[],scripts:[]};let t=Object.keys(e.pf?.commands??{}),r=Object.keys(e.scripts??{}).filter(o=>!t.includes(o));return{configured:t,scripts:r}}function km(){let{configured:e,scripts:t}=mi();return[...e,...t]}function di(){let{configured:e,scripts:t}=mi(),n=[...e,...t];return n.length===0?"":["",`
|
|
411
|
+
Workspace Commands:`,...n.map(o=>` ${ze.default.cyan(o)}`)].join(`
|
|
412
|
+
`)}function ui(e,t,n){let r=t.slice(2);if(r.length>0&&!r[0].startsWith("-")){let o=r[0],s=r.slice(1);if(o==="__workspace-commands"&&s.includes("--names-only")){let a=km();for(let i of a)console.log(i);return}ym(o,s,n).then(a=>{a||e.parse(t)})}else e.parse(t)}process.on("SIGINT",()=>{process.exit(0)});process.on("unhandledRejection",e=>{throw(e.name==="ExitPromptError"||e.message?.includes("ERR_USE_AFTER_CLOSE")||e.message?.includes("Cancelled prompt"))&&process.exit(0),e});process.on("uncaughtException",e=>{(e.name==="ExitPromptError"||e.message?.includes("ERR_USE_AFTER_CLOSE")||e.message?.includes("Cancelled prompt"))&&process.exit(0),(e.message?.includes("Not in a workspace directory")||e.message?.includes("Could not locate workspace root"))&&(console.error(e.message),process.exit(1)),console.error(ye.default.red(`
|
|
413
|
+
\u2716 An unexpected error occurred:`)),console.error(e),process.exit(1)});var bt=new Ci.Command,gi=Object.keys(G.bin||{}),[Er="pf",$r]=gi.length>0?gi:["pf"],{description:fi,version:vm,repository:hi,homepage:Cm}=G,yi=fi?.split(/ —|,|\./)[0]||fi||"Platform CLI",wi=hi?.url?`https://${hi.url.replace(/^(git\+|git@)/,"").replace(/\.git$/,"").replace(":","/")}`:null,ki=wi||Cm,xm=wi?"GitHub":"README",wm=ki?[ye.default.bold(yi),`
|
|
303
414
|
|
|
304
|
-
`,
|
|
415
|
+
`,ye.default.cyan("See more at: "),ye.default.bold((0,xi.default)(xm,ki))].join(""):ye.default.bold(yi),bi=[un(bt,Er),xa(),Pa,Ua,Ya,lo];bt.name(Er).description(wm).version(vm||"0.0.1").helpCommand(!1).configureHelp({subcommandTerm:e=>ye.default.cyan(e.name())}).addHelpText("after",di);$r&&$r!==Er&&bt.alias($r);bi.forEach(e=>{bt.addCommand(e)});ui(bt,vi.argv,bi);
|