@crossdelta/platform-sdk 0.17.4 → 0.18.0
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/CHANGELOG.md +407 -0
- package/README.md +22 -17
- package/bin/cli.js +342 -223
- package/bin/templates/workspace/.github/workflows/publish-packages.yml +15 -3
- package/package.json +3 -1
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 Gi=Object.create;var Wr=Object.defineProperty;var Ui=Object.getOwnPropertyDescriptor;var Ji=Object.getOwnPropertyNames;var Ki=Object.getPrototypeOf,zi=Object.prototype.hasOwnProperty;var qi=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Ji(t))!zi.call(e,o)&&o!==n&&Wr(e,o,{get:()=>t[o],enumerable:!(r=Ui(t,o))||r.enumerable});return e};var u=(e,t,n)=>(n=e!=null?Gi(Ki(e)):{},qi(t||!e||!e.__esModule?Wr(n,"default",{value:e,enumerable:!0}):n,e));var Fi=require("node:process"),xe=u(require("chalk")),Oi=require("commander"),_i=u(require("terminal-link"));var Co=u(require("chalk")),xo=require("commander");var ue=require("node:fs"),E=require("node:path"),ge=require("fs-extra");var ad=process.env.npm_package_version||"0.0.0",Gr=["bun.lock","bun.lockb","package-lock.json","yarn.lock","pnpm-lock.yaml"],bn="start:dev";var Xe=u(require("chalk"));function Sn(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=Vi(c.barColor??t?.barColor),p=Zi(c,a,o,l,s,t?.labelColor);i.push(p)}return r&&(i.push(""),i.push(r)),i.join(`
|
|
3
|
+
`)}function Vi(e){return e?Xe.default[e]("\u2587"):"\u2587"}function Zi(e,t,n,r,o,s){let a=Math.round(e.value/t*n),i=e.barColor?Xe.default[e.barColor](r.repeat(a)):r.repeat(a),c=e.color??s;return`${Xe.default.bold(c?Xe.default[c](e.label.padEnd(12)):e.label.padEnd(12))} ${i} ${e.value.toLocaleString()}${o?` ${o}`:""}`}var Pn=u(require("chalk")),Jr=require("commander"),Tn=require("listr2");var Qe=u(require("chalk")),m={logs:[],breakLine:()=>(console.log(),m),success:(e,...t)=>(console.log(Qe.default.green(`\u2714 ${e}`),...t),m),info:(e,...t)=>(console.log(Qe.default.cyan(`\u{1F6C8} ${e}`),...t),m),warn:(e,...t)=>(console.warn(Qe.default.yellow(`\u26A0\uFE0E ${e}`),...t),m),error:(e,...t)=>(console.error(Qe.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 ie(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",()=>`${Pn.default.cyan.bold(`
|
|
4
4
|
Example:`)}
|
|
5
|
-
${
|
|
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=
|
|
5
|
+
${Pn.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=Yi(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 Tn.Listr(Ur(e.prompts,i),{rendererOptions:{lazy:!0,showErrorMessage:!1}}).run(i),await new Tn.Listr(Ur(e.actions,i),{rendererOptions:{lazy:!1,showErrorMessage:!1}}).run(i),await e.onComplete?.(i)}catch(r){let o=r;m.error(o.message)}}),t}function Yi(e,t){let n={};return e.forEach(([r],o)=>{let s=r.replace(/[<>[\]]/g,"");n[s]=t[o]}),n}function Ur(e,t){return e.map(n=>typeof n=="function"?n(t):n)}function At(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 Kr=require("execa");function et(e){try{return(0,Kr.execaSync)(e,["--version"]),!0}catch{return!1}}var we=require("node:path"),zr=require("fs-extra"),qr=require("package-up"),Vr=require("rimraf"),g=e=>(0,we.join)(process.cwd(),e),It=e=>{try{return(0,zr.readdirSync)(e).length===0}catch{return!0}};function Zr(){let e=(0,qr.packageUpSync)({cwd:(0,we.dirname)(__filename)});if(!e)throw new Error("Could not find package.json");return(0,we.dirname)(e)}var Yr=e=>(0,Vr.rimraf)(e);var Xr=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 Nt(e,t,n){for(let r=0;r<t.length;r++){let o=t[r];e.output=Xr.default.dim(`[${r+1}/${t.length}] ${o.title}`),await o.fn(n??{},e)}}var tt={services:"services",apps:"apps",packages:"packages",contracts:"packages/contracts"},Xi={docs:{base:["service.md"],frameworks:{}},serviceTypes:{hono:{commandType:"hono-micro",entryPoint:"src/index.ts",skipFiles:[]},nest:{commandType:"nest-micro",entryPoint:"src/main.ts",skipFiles:[]}}},$n=e=>{if(!(0,ue.existsSync)(e))return null;try{return JSON.parse((0,ue.readFileSync)(e,"utf-8"))}catch{return null}},Rt=(e,t)=>typeof e=="string"?e:typeof e=="object"&&e!==null&&"path"in e?e.path:t,Qi=e=>e.split("/").pop()||"workspace",ec=e=>{let t=e.slice(0,e.lastIndexOf("/"));return t===e?null:t},Qr=e=>e.split("."),tc=(e,t)=>{if(!e.workspaces)return!1;if(e.pf||(0,ue.existsSync)((0,E.join)(t,"turbo.json")))return!0;let n=Gr.some(o=>(0,ue.existsSync)((0,E.join)(t,o))),r=(0,ue.existsSync)((0,E.join)(t,"infra"));return n&&r},nc=e=>{let t=$n((0,E.join)(e,"package.json"));return t?tc(t,e):!1},eo=e=>{let t=e;for(;t;){if(nc(t))return t;t=ec(t)}return null},to=()=>eo(process.cwd())!==null,y=()=>{let e=eo(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,17 +13,17 @@ 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
|
-
`);return e},
|
|
17
|
-
`,encoding:"utf-8"})},
|
|
18
|
-
`).filter(Boolean);for(let s of o)try{process.kill(Number.parseInt(s,10),"SIGKILL")}catch{}}catch{}}var
|
|
16
|
+
`);return e},J=e=>{let t=e??y();return $n((0,E.join)(t,"package.json"))},L=e=>{let t=J(e);if(!t?.pf?.paths)return tt;let{paths:n}=t.pf;return{services:Rt(n.services,tt.services),apps:Rt(n.apps,tt.apps),packages:Rt(n.packages,tt.packages),contracts:Rt(n.contracts,tt.contracts)}},C=e=>{let t=e??y(),n=L(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}},be=()=>{let e=y(),t=$n((0,E.join)(e,"package.json")),n=`@${Qi(e)}`;return t?.name?t.name.startsWith("@")?t.name.split("/")[0]:`@${t.name}`:n},rc=(e,t)=>{let n=Qr(t),r=e;for(let o of n){if(r===null||typeof r!="object"||!(o in r))return;r=r[o]}return r},oc=(e,t,n)=>{let r=Qr(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},no=(e,t=process.cwd())=>{let n=(0,ge.readJsonSync)((0,E.join)(t,"package.json"));return rc(n,e)},te=(e,t,n=process.cwd())=>{let r=(0,E.join)(n,"package.json"),o=(0,ge.readJsonSync)(r);oc(o,e,t),(0,ge.writeJsonSync)(r,o,{spaces:2,EOL:`
|
|
17
|
+
`,encoding:"utf-8"})},Mt=e=>{let t=Zr();return(0,ge.readJSONSync)((0,E.resolve)(t,e),{encoding:"utf-8"})},N=Mt("package.json"),nt=()=>N.generatorConfig??Xi;var mo=require("node:fs"),uo=require("node:path"),Nn=require("node:process"),go=require("execa");var In=require("node:child_process"),io=require("node:path"),co=require("execa");var ro=require("node:fs"),oo=require("node:path"),so=require("dotenv"),En=(e,t)=>{let n=(0,oo.resolve)(t,e);return(0,ro.existsSync)(n)?(0,so.config)({path:n,processEnv:{}}).parsed||{}:{}},ao=(e,t)=>{let n=En(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 An={...process.env,NODE_NO_WARNINGS:"1"},sc=(e,t,n)=>e?"pipe":t||n?["ignore","pipe","pipe"]:"inherit",ac=(e,t,n)=>e?{...An,...e}:t||n?{...An,CI:"true"}:{...An},ic=e=>e.includes("EEXIST")||e.includes("failed to link package");async function ce(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,co.execa)(e,t,{cwd:n,stdio:sc(a,r,i),all:r||i?!0:void 0,shell:o??!0,env:ac(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(ic(p))return;throw new Error(cc(p))}}var cc=e=>{let t=e.match(/error: (.+)/);return t?t[1].trim():e};function lo(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?En(o,r):{},d=(0,io.resolve)(r,"node_modules",".bin"),k=process.env.PATH||"",I=`${d}:${k}`,Ye={...process.env,...p,PATH:I,FORCE_COLOR:"1"},O=(0,In.spawn)(e,t,{cwd:r,env:Ye,stdio:["inherit",a?"pipe":"inherit","pipe"],detached:s});return i&&a&&O.stdout?.on("data",i),c&&O.stderr?.on("data",c),l&&O.on("exit",l),O}function jt(e,t,n={}){let{cwd:r=process.cwd()}=n;(0,In.spawn)(e,t,{cwd:r,stdio:"inherit",shell:!0}).on("exit",s=>process.exit(s||0))}async function po(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 Ft=e=>et(e);function Rn(e=process.cwd()){let t=n=>(0,mo.existsSync)((0,uo.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 Rn(e)??Mn()}function Mn(){return Ft("bun")?"bun":Ft("pnpm")?"pnpm":Ft("yarn")?"yarn":"npm"}function fo(){return["bun","pnpm","yarn","npm"].filter(Ft)}async function H(e,t){let n=pc(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 ce(l,k,{cwd:s,task:i,quiet:c})}async function ho(e){let t=["-g"],n=[...e.flags??[],...t];await H({...e,flags:n,packageManager:e.packageManager??x()})}function yo(e,t,n){let{args:r,mergedOptions:o}=vo(t??[],n),s=o.manager??x(),{command:a,args:i}=ko(s);console.log(`
|
|
19
19
|
Running command: ${a} ${[...i,e,...r].join(" ")}
|
|
20
|
-
`),(0,
|
|
21
|
-
createdAt: z.string(),`:Object.entries(e).map(([t,n])=>` ${t}: ${
|
|
22
|
-
`),
|
|
20
|
+
`),(0,go.execaSync)(a,[...i,e,...r],{cwd:o.cwd??(0,Nn.cwd)(),stdio:"inherit",preferLocal:!0})}async function ne(e,t,n){let{args:r,mergedOptions:o}=vo(t??[],n),s=o.manager??x(),{command:a,args:i}=ko(s);await ce(a,[...i,e,...r],o)}async function rt(e,t){let{script:n,mergedOptions:r}=mc(e,t),o=r.packageManager??x();await ce(o,["run",n,...r.args??[]],{cwd:r.cwd??(0,Nn.cwd)(),task:r.task})}function ko(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 pc(e,t){return Array.isArray(e)?{packages:e,mergedOptions:{...t,packages:e}}:{packages:e.packages??[],mergedOptions:e}}function vo(e,t){return Array.isArray(e)?{args:e,mergedOptions:t??{}}:{args:[],mergedOptions:e}}function mc(e,t){return typeof e=="string"?{script:e,mergedOptions:t??{}}:{script:e.script,mergedOptions:e}}var dc=e=>e==="yarn"?["npm","audit"]:["audit"],wo=new xo.Command("audit").description("Run security audit on dependencies").allowUnknownOption(!0).action((e,t)=>{let n=y(),r=x(),o=dc(r),s=t.args||[];console.log(Co.default.dim(`Running ${r} ${[...o,...s].join(" ")}`)),jt(r,[...o,...s],{cwd:n})});var me=require("@listr2/prompt-adapter-enquirer"),ae=u(require("chalk"));var Pe=require("node:fs"),Ao=require("node:os"),Io=require("node:path");var le=require("node:crypto"),Se=require("node:fs"),fe=require("node:os"),bo=require("node:path"),jn=(0,bo.join)((0,fe.homedir)(),".platform-sdk-keys"),So="aes-256-gcm",Po=()=>{let e=`${(0,fe.hostname)()}:${(0,fe.userInfo)().username}:${(0,fe.homedir)()}`;return(0,le.createHash)("sha256").update(e).digest()},To=()=>{if(!(0,Se.existsSync)(jn))return{};try{return JSON.parse((0,Se.readFileSync)(jn,"utf-8"))}catch{return{}}},uc=e=>{(0,Se.writeFileSync)(jn,JSON.stringify(e,null,2),{mode:384})},gc=e=>{let t=Po(),n=(0,le.randomBytes)(16),r=(0,le.createCipheriv)(So,t,n),o=r.update(e,"utf8","hex");return o+=r.final("hex"),{iv:n.toString("hex"),tag:r.getAuthTag().toString("hex"),data:o}},fc=e=>{let t=Po(),n=Buffer.from(e.iv,"hex"),r=Buffer.from(e.tag,"hex"),o=(0,le.createDecipheriv)(So,t,n);o.setAuthTag(r);let s=o.update(e.data,"hex","utf8");return s+=o.final("utf8"),s};async function $o(e,t){let n=To();n[e]=gc(t),uc(n)}async function Ot(e){let n=To()[e];if(!n)return null;try{return fc(n)}catch{return null}}var ot={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 Eo(){return Object.entries(ot).map(([e,t])=>({name:t.name,value:e}))}function st(e){let t=ot[e];if(!t)throw new Error(`Unknown AI provider: ${e}`);return t}var he=(0,Io.join)((0,Ao.homedir)(),".platform-sdk-ai.json"),hc=()=>{let e="anthropic",t=ot[e];return{provider:e,model:t.defaultModel}},Fn=hc();function at(){return(0,Pe.existsSync)(he)}function _t(){if(!at())throw new Error("AI configuration not found. Please run 'pf ai:setup' to configure your AI provider.");try{let e=(0,Pe.readFileSync)(he,"utf-8"),t=JSON.parse(e);return{...Fn,...t}}catch{throw new Error(`Failed to load AI configuration from ${he}. Please run 'pf setup --ai' again.`)}}function No(e){let t=JSON.stringify(e,null,2);(0,Pe.writeFileSync)(he,t,"utf-8")}async function Ro(e,t){await $o(e,t)}async function Mo(e){let t=await Ot(e.provider);if(t)return t;let n=ot[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 yc=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},kc=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 jo(e,t,n={}){let{system:r,maxTokens:o=4096,temperature:s=.7,onToken:a}=n,i=await Mo(e);switch(e.provider){case"openai":return yc(t,e.model,i,{system:r,maxTokens:o,temperature:s,onToken:a});case"anthropic":return kc(t,e.model,i,{system:r,maxTokens:o,temperature:s,onToken:a});default:throw new Error(`Unsupported AI provider: ${e.provider}`)}}var re=require("node:fs"),Re=require("node:path"),ks=require("@inquirer/prompts"),h=u(require("chalk")),vs=u(require("ora"));var On=require("node:fs"),Lt=require("node:path");var Te=require("node:fs"),it=require("node:path"),Dt=u(require("chokidar"));var ct=".pf-generating",vc=e=>(0,Te.existsSync)((0,it.join)(e,ct)),Cc=e=>{let t=(0,it.join)(e,ct);(0,Te.existsSync)(t)&&(0,Te.unlinkSync)(t)},xc=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"],Fo=(e,t)=>{Cc(e);let n=J(e),r=xc(n?.pf?.paths),o=(0,it.join)(e,ct),s=()=>{vc(e)||t()},a=[];a.push(Dt.default.watch(o,{ignoreInitial:!0}).on("unlink",()=>t()));for(let i of r){let c=(0,it.join)(e,i);(0,Te.existsSync)(c)&&(a.push(Dt.default.watch(c,{ignoreInitial:!0,depth:0}).on("addDir",s).on("unlinkDir",s)),a.push(Dt.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 lt=(e=__dirname)=>{let t=r=>(0,On.existsSync)((0,Lt.join)(r,"package.json")),n=(0,Lt.dirname)(e);if(t(e))return e;if(e==="/")throw new Error("Could not find package.json (package root)");return lt(n)},Oo=(e,t)=>{let n=e.find(On.existsSync);if(!n)throw new Error(t??`Directory not found. Searched in: ${e.join(", ")}`);return n};var Gt=require("node:fs"),Ko=require("node:path"),zo=require("ts-morph");var R=require("node:fs"),$e=require("node:path");var Do=e=>e.replace(/\./g,"-").toLowerCase(),_o=e=>e.split(/[-.]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(""),wc=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}()`,bc=e=>!e||Object.keys(e).length===0?` id: z.string(),
|
|
21
|
+
createdAt: z.string(),`:Object.entries(e).map(([t,n])=>` ${t}: ${wc(n)},`).join(`
|
|
22
|
+
`),_n=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=Do(e),n=_o(e),r=e.split(".")[0],o=e.split(".").slice(1).join("-"),s=_n(r).toUpperCase(),a=_n(r).toLowerCase(),i=_o(`${_n(r)}.${o}`);return{eventName:t,contractName:`${i}Contract`,schemaName:`${n}Schema`,typeName:`${n}Data`,streamName:s,domain:a,event:o}},Dn=e=>{let t=pt(e);if((0,R.existsSync)(t))return!0;let{eventsPath:n}=C(),r=Do(e),o=(0,$e.join)(n,`${r}.ts`);return(0,R.existsSync)(o)},Ln=(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
|
+
${bc(t)}
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
export const ${r} = createContract({
|
|
@@ -33,24 +33,24 @@ export const ${r} = createContract({
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
export type ${s} = z.infer<typeof ${r}.schema>
|
|
36
|
-
`,p=(0
|
|
36
|
+
`,p=(0,$e.join)(n,i),d=(0,$e.join)(p,`${c}.ts`);return(0,R.existsSync)(p)||(0,R.mkdirSync)(p,{recursive:!0}),(0,R.writeFileSync)(d,l,"utf-8"),d},pt=e=>{let{eventsPath:t}=C(),{domain:n,event:r}=B(e);return(0,$e.join)(t,n,`${r}.ts`)},Hn=e=>{let t=pt(e);if(!(0,R.existsSync)(t))return null;let n=(0,R.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},Bn=()=>{let{packagePath:e}=C(),t=(0,$e.join)(e,"package.json");if(!(0,R.existsSync)(t))return"@my-platform";try{return JSON.parse((0,R.readFileSync)(t,"utf-8")).name?.split("/")[0]??"@my-platform"}catch{return"@my-platform"}};var Bt=require("node:fs"),Un=require("node:path");var T=require("node:fs"),Ee=require("node:path");var Ht=e=>{let{streamName:t}=B(e);return t},Lo=(e,t)=>{let n=(0,Ee.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)},Sc=e=>{if(e.includes("@crossdelta/cloudevents"))return e;let t=`import { consumeJetStreams } from '@crossdelta/cloudevents'
|
|
37
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},
|
|
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},Pc=(e,t,n)=>`
|
|
39
39
|
|
|
40
40
|
// Consume from ${e} stream
|
|
41
41
|
consumeJetStreams({
|
|
42
42
|
streams: ['${e}'],
|
|
43
43
|
consumer: '${n}-service',
|
|
44
44
|
discover: './src/events/**/*.handler.ts',
|
|
45
|
-
})`,
|
|
46
|
-
`;return(0,T.writeFileSync)(o,l,"utf-8"),{added:!0,streamName:n}},
|
|
45
|
+
})`,Wn=(e,t)=>{let n=Ht(t),r=t.split(".")[0],o=(0,Ee.join)(e,"src","index.ts"),s=(0,Ee.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(Lo(e,n))return{added:!1,streamName:n};let a=(0,T.readFileSync)(o,"utf-8"),i=e.split("/").pop()||"unknown";a.includes("consumeJetStreams")||(a=Sc(a));let c=Pc(n,r,i),l=`${a.trimEnd()+c}
|
|
46
|
+
`;return(0,T.writeFileSync)(o,l,"utf-8"),{added:!0,streamName:n}},Gn=(e,t)=>{let{eventName:n,contractName:r,typeName:o}=B(e),s=Bn(),a=(0,Ee.join)(t,"src","events"),i=(0,Ee.join)(a,`${n}.handler.ts`);if((0,T.existsSync)(i))return null;let c=`import { handleEvent } from '@crossdelta/cloudevents'
|
|
47
47
|
import { ${r}, type ${o} } from '${s}/contracts'
|
|
48
48
|
|
|
49
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 Ho=e=>{try{return(0,Bt.readdirSync)(e,{withFileTypes:!0}).flatMap(n=>{let r=(0,Un.join)(e,n.name);return n.isDirectory()?Ho(r):n.name.endsWith(".handler.ts")?[r]:[]})}catch{return[]}},Jn=e=>{let t=(0,Un.join)(e,"src","events");return Ho(t).flatMap(r=>{let o=(0,Bt.readFileSync)(r,"utf-8");return Tc(r,o)})},Tc=(e,t)=>{let n=$c(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}]},$c=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},Kn=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])=>Ec(n,r)).sort((n,r)=>n.stream.localeCompare(r.stream))},Ec=(e,t)=>{let n=Ht(t[0]?.eventType??`${e}.event`),r=`${e}.>`;return{stream:n,subjects:[r],handlers:t}},zn=(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
|
|
|
@@ -58,14 +58,14 @@ export default handleEvent(${r}, async (data: ${o}) => {
|
|
|
58
58
|
streams: [${e.map(n=>`'${n.stream}'`).join(", ")}],
|
|
59
59
|
consumer: '${t}',
|
|
60
60
|
discover: './src/events/**/*.handler.ts',
|
|
61
|
-
})`;var v=require("node:fs"),
|
|
62
|
-
* ${(0,
|
|
61
|
+
})`;var v=require("node:fs"),K=require("node:path");var Ac=(e,t)=>{let n=`export * from './${t}'`;if(!(0,v.existsSync)(e)){let s=(0,K.dirname)(e);(0,v.existsSync)(s)||(0,v.mkdirSync)(s,{recursive:!0});let a=`/**
|
|
62
|
+
* ${(0,K.dirname)(e).split("/").pop()} Domain Events
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
65
|
`;return(0,v.writeFileSync)(e,a+n+`
|
|
66
66
|
`,"utf-8"),!0}let r=(0,v.readFileSync)(e,"utf-8");if(r.includes(`'./${t}'`))return!1;let o=r.trimEnd()+`
|
|
67
67
|
`+n+`
|
|
68
|
-
`;return(0,v.writeFileSync)(e,o,"utf-8"),!0},
|
|
68
|
+
`;return(0,v.writeFileSync)(e,o,"utf-8"),!0},Ic=(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.
|
|
@@ -74,14 +74,14 @@ export default handleEvent(${r}, async (data: ${o}) => {
|
|
|
74
74
|
`+n+`
|
|
75
75
|
`,"utf-8"),!0;let o=(0,v.readFileSync)(e,"utf-8").split(`
|
|
76
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},
|
|
77
|
+
`),"utf-8"),!0},Nc=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},qn=e=>{let{packagePath:t}=C(),{domain:n,event:r}=B(e),o=(0,K.join)(t,"src","events"),s=(0,K.join)(o,n),a=(0,K.join)(s,"index.ts"),i=(0,K.join)(o,"index.ts"),c=(0,K.join)(t,"src","index.ts"),l=e.split(".")[0],p=(0,K.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 Ac(a,r)&&(d=!0),Ic(i,n)&&(d=!0),Nc(c)&&(d=!0),d},Vn=(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
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"),
|
|
79
|
+
`),"utf-8"),!0};var b=require("node:fs"),z=require("node:path"),f=require("@faker-js/faker");var Bo=[{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"}],Wo=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(),Go=e=>{let t=e.toLowerCase(),n=Bo.find(r=>t.includes(r.pattern));return n?{value:n.generate(),hint:n.hint}:null},Rc=(e,t)=>{if(e.format)return Wo(e.format);let n=Go(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?[Zn(e.element)]:[];case"object":return Zn(e);default:return null}},Zn=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]=Rc(o,r);return t},Mc=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=Zn(s);if(a&&typeof a=="object"&&Object.keys(a).length>0){let i={};return Yn(a,i,""),{data:a,faker:i}}}}catch{}return null},Yn=(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=Bo.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)?Yn(o,t,s):Array.isArray(o)&&o.length>0&&typeof o[0]=="object"&&Yn(o[0],t,`${s}[0]`)}},jc=e=>({string:()=>f.faker.lorem.word(),number:()=>f.faker.number.int({min:1,max:100}),boolean:()=>f.faker.datatype.boolean()})[e]?.(),Fc=(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=Go(s);if(i)t[s]=i.value,i.hint&&(n[s]=i.hint);else{let c=jc(a);c!==void 0&&(t[s]=c)}}},Oc=(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]=Wo(a),n[s]=a==="datetime"?"date":a},Uo=e=>{let t={},n={};return Fc(e,t,n),Oc(e,t,n),{data:t,faker:n}},Wt=async e=>{let{eventsPath:t}=C(),n=pt(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 Mc(n);if(!a){let k=Hn(e);k&&(a=Uo(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,z.join)(t,c,`${l}.mock.json`),d=(0,z.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},_c=(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=Uo(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},Xn=async(e,t={})=>{let n=(0,z.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,z.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,z.basename)(a)} (Handler does not use contracts)`);continue}let{eventName:l}=B(c),p=t.outputDir??C().eventsPath,d=(0,z.join)(p,`${l}.mock.json`);if((0,b.existsSync)(d)&&!t.overwrite){s.push(`${(0,z.basename)(a)} (Mock already exists)`);continue}if(t.outputDir){let I=(0,z.join)(t.outputDir,`${l}.ts`);_c(I,d,c)&&o.push(d);continue}let k=await Wt(c);k&&o.push(k)}return{mockPaths:o,skippedHandlers:s}};var qo=e=>{let t=e.split("/").pop()||"service",n=(0,Ko.join)(e,"src","events","events.service.ts");if(!(0,Gt.existsSync)(n))return!1;let r=Jn(e);if(r.length===0||(0,Gt.readFileSync)(n,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").includes("consumeJetStreams"))return!1;let i=Kn(r),c=zn(i,t);if(!c)return!1;let l=new zo.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 O=[...c.split(`
|
|
80
80
|
`),""," this.logger.log('Event consumers started successfully')"].join(`
|
|
81
|
-
`);I.setBodyText(
|
|
82
|
-
`));for(let n of e)console.log(
|
|
83
|
-
`));for(let l of i)console.log(
|
|
84
|
-
`));for(let l of c)console.log(
|
|
81
|
+
`);I.setBodyText(O),d=!0;break}return d&&l.saveSync(),d};var Dc=e=>{let t=e.split(/\s+/),n=t[0],r=t.slice(1);return n==="pf"&&(n=process.argv[1]),{executable:n,args:r}},Lc=async(e,t)=>{try{let{executable:n,args:r}=Dc(e.command);return await ce(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)}}},Qn=async(e,t)=>{let n=[];for(let r of e){let o=await Lc(r,t);if(n.push(o),!o.success)break}return n},er=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)))},Vo=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 mt=require("node:fs"),Jt=require("node:path"),q=u(require("chalk"));var ye=require("node:fs"),Ut=require("node:path"),Hc=(e,t)=>{let r=e.path.startsWith("packages/")&&t.workspaceRoot?t.workspaceRoot:t.baseDir,o=(0,Ut.join)(r,e.path);try{if((0,ye.existsSync)(o)&&!t.overwrite)return{status:"skipped",path:e.path};if(t.dryRun)return{status:"written",path:e.path};let s=(0,Ut.dirname)(o);return(0,ye.existsSync)(s)||(0,ye.mkdirSync)(s,{recursive:!0}),(0,ye.writeFileSync)(o,e.content,"utf-8"),{status:"written",path:e.path}}catch(s){return{status:"failed",path:e.path,error:s.message}}},Zo=(e,t)=>{let n=e.map(r=>Hc(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 Bc=(e,t)=>{let n=L(t.workspaceRoot),r=(0,Jt.join)(t.workspaceRoot,n.contracts);if(!(0,mt.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()},Wc=e=>{let t=(0,Jt.join)(e,"packages/contracts/src/index.ts");if(!(0,mt.existsSync)(t))return new Set;try{let n=(0,mt.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}},Gc=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}`},Uc=(e,t,n)=>{let r=Wc(t),o=[],s=[],a=[];for(let i of e)if(r.has(i))o.push(i);else{s.push(i);let c=Gc(i),l=n.replace(`${t}/`,"");a.push(`pf event add ${c} --service ${l}`)}return{existing:o,missing:s,suggestedCommands:a}},Jc=(e,t)=>{if(e.length!==0){console.log(q.default.cyan(`\u{1F4E6} Using existing contracts:
|
|
82
|
+
`));for(let n of e)console.log(q.default.dim(` ${t}/contracts \u2192 ${n}`));console.log()}},Kc=(e,t)=>{let n=/^packages\/contracts\/src\/events\/([^/]+)\.ts$/,r=(0,Jt.join)(t,"packages/contracts/src/index.ts");for(let o of e){let s=o.match(n);s&&s[1]!=="index"&&Vn(r,s[1])}},Yo=async(e,t)=>{t.start("Applying code formatting...");try{await ne("biome",["check","--fix","--unsafe","."],{cwd:e,quiet:!0}),t.succeed("Code formatted!")}catch{t.warn("Code formatting completed with warnings")}},zc=async(e,t)=>{t.start("Scanning for event handlers...");let{mockPaths:n,skippedHandlers:r}=await Xn(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(q.default.dim(` ${a}`))}console.log()}else t.succeed("Event handlers found");if(r.length>0){for(let s of r)console.log(q.default.dim(` \u2139 Skipped: ${s}`));console.log()}},Xo=async(e,t,n,r)=>{r.start("Writing generated files...");let o=Zo(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(q.default.dim(` ${l}`));console.log()}else r.succeed("No files to write");let s=Bc(e,n),{existing:a,missing:i,suggestedCommands:c}=Uc(s,n.workspaceRoot,t);if(a.length>0&&Jc(a,n.scope),i.length>0){console.log(q.default.yellow(`\u26A0\uFE0F Missing contracts (not exported from @${n.scope}/contracts):
|
|
83
|
+
`));for(let l of i)console.log(q.default.yellow(` ${l}`));console.log(),console.log(q.default.cyan(`\u{1F4A1} Run these commands to create the missing contracts:
|
|
84
|
+
`));for(let l of c)console.log(q.default.dim(` ${l}`));console.log()}return Kc(o.written,n.workspaceRoot),o.written.length>0&&await zc(t,r),{missingContractCommands:c}};var Kt=require("node:fs"),Ie=require("node:path");var Ae=require("node:fs"),Qo=require("node:path");var es=e=>{let{eventsPath:t}=C(e);if(!(0,Ae.existsSync)(t))return[];let n=[];try{let r=(0,Ae.readdirSync)(t).filter(o=>o.endsWith(".ts")&&!o.endsWith(".mock.json")&&o!=="index.ts");for(let o of r){let s=(0,Qo.join)(t,o),a=(0,Ae.readFileSync)(s,"utf-8"),i=qc(a,s);i&&n.push(i)}}catch(r){return console.warn("Warning: Could not scan contracts package:",r),[]}return n},qc=(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=Zc(e);return{name:r,typeName:s,eventType:i,fields:c,filePath:t}}catch{return null}},Vc={string:"string",number:"number",boolean:"boolean",array:"array",object:"object",date:"date"},Zc=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=Vc[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]},ts=(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.
|
|
@@ -102,15 +102,15 @@ The following event contracts are available in \`${t}/contracts\`:
|
|
|
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 Yc=(e,t)=>{let n=(0,Ie.join)(__dirname,"docs","generators"),r=nt(),o=[];for(let s of r.docs.base)o.push((0,Ie.join)(n,s));if(e&&r.docs.frameworks[e]){let s=r.docs.frameworks[e];if(typeof s=="string")o.push((0,Ie.join)(n,s));else{let a=t==="bun"?"bun":"node";s[a]&&o.push((0,Ie.join)(n,s[a]))}}return o},ns={copilot:".github/copilot-instructions.md",projectGuidelines:"docs/ai-guidelines.md"},Xc=1500,rs=e=>{try{return(0,Kt.existsSync)(e)?(0,Kt.readFileSync)(e,"utf-8"):null}catch{return null}},Qc=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(),el=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(),tl=e=>Math.ceil(e.length/4),nl=(e,t)=>{let n=e.split(/(?=^## )/m),r="",o=0;for(let s of n){let a=tl(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()},rl=(e,t)=>{let{workspaceRoot:n,scope:r}=t,o=es(n),s=ts(o,r);return e.replace(/\{\{scope\}\}/g,r).replace(/\{\{AVAILABLE_CONTRACTS\}\}/g,s)},os=e=>{let{workspaceRoot:t,scope:n}=e,r=[],o=Yc(e.serviceType,e.packageManager);for(let i of o){let c=rs(i);if(c){let l=rl(c,e),p=Qc(l);r.push(p)}}let s=[ns.copilot,ns.projectGuidelines],a=Math.floor(Xc/s.length);for(let i of s){let c=rs((0,Ie.join)(t,i));if(c){let l=el(c),p=nl(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 ol=`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`,sl=e=>e.replace(/-/g,"_").toUpperCase(),al=e=>e.split("/").pop()||"my-service",ss=(e,t,n)=>{let r=os({...e,serviceType:t,packageManager:n});return`${ol}
|
|
128
128
|
|
|
129
129
|
## Project Guidelines & Patterns
|
|
130
130
|
|
|
131
131
|
Follow these project-specific conventions and patterns when generating code:
|
|
132
132
|
|
|
133
|
-
${r}`},
|
|
133
|
+
${r}`},as=(e,t,n,r)=>{let o=al(e),s=`${sl(o)}_PORT`,a=be();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,277 @@ 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
|
-
`),n=[],r=0;for(let o of t){let s=
|
|
151
|
-
`));return}let o=(await
|
|
152
|
-
\u2717 Scaffolding failed: ${o.command}`)),o.error&&console.log(
|
|
148
|
+
`};var il=()=>!1,is=(e,t)=>{il()&&console.log(`[AI Parser] ${e}`,t??"")},zt={commandsBlock:/```commands\n([\s\S]*?)```/gi,postCommandsBlock:/```post-commands\n([\s\S]*?)```/gi,dependenciesBlock:/```dependencies\n([\s\S]*?)```/gi,fileHeader:/^#{1,4}\s+`([^`]+)`\s*$/},nr=(e,t)=>[...e.matchAll(t)].flatMap(r=>r[1].split(`
|
|
149
|
+
`).map(o=>o.trim()).filter(o=>o.length>0&&!o.startsWith("#"))),cs=e=>({command:e,isPfCommand:e.startsWith("pf ")||e.includes(" pf ")}),cl=e=>nr(e,zt.commandsBlock).map(cs),ll=e=>nr(e,zt.postCommandsBlock).map(cs),pl=e=>nr(e,zt.dependenciesBlock).filter(t=>!t.startsWith("@crossdelta/")&&t!=="zod"),ml=e=>{let t={ts:"typescript",js:"javascript",md:"markdown",yml:"yaml"},n=(e||"typescript").toLowerCase();return t[n]||n},dl=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"},ul=e=>e.replace(/^\s*\/\/ \.{3,}.*$/gm,"").replace(/^\s*\/\/ Lines? \d+.*omitted.*$/gim,"").replace(/^\s*\/\* Lines? \d+.*omitted.*\*\/$/gim,"").trim(),gl=e=>{let t=e.split(`
|
|
150
|
+
`),n=[],r=0;for(let o of t){let s=zt.fileHeader.exec(o);s&&n.push({path:s[1],index:r}),r+=o.length+1}return n},fl=(e,t)=>{let r=e.slice(t).match(/```(\w+)?\n([\s\S]*?)```/);return r?{language:r[1]?ml(r[1]):void 0,content:ul(r[2])}:null},hl=e=>gl(e).map(n=>{let r=fl(e,n.index);return!r||r.content.length===0?null:{path:n.path,language:r.language||dl(n.path),content:r.content,startIndex:n.index}}).filter(n=>n!==null),tr=e=>e.includes("packages/contracts")||e.includes("contracts/src"),yl=e=>{let t=e.filter(r=>tr(r.path)),n=e.filter(r=>!tr(r.path));return[...t,...n]},kl=e=>{let t=e.replace(/^\/+/,"").replace(/\/{2,}/g,"/");if(tr(t))return t;let n=t.match(/^services\/[^/]+\/(.+)$/);return n?n[1]:t},ls=(e,t)=>{is("Parsing AI response",{length:e.length});let n=cl(e),r=ll(e),o=pl(e),s=hl(e),a=yl(s.map(i=>({path:kl(i.path),content:i.content,language:i.language})));return is("Parsed response",{commands:n.length,postCommands:r.length,dependencies:o.length,files:a.length}),{commands:n,files:a,dependencies:o,postCommands:r}},ps=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 ms=require("node:fs"),W=u(require("chalk"));var ds=async(e,t,n)=>{if(e.length===0){(0,ms.mkdirSync)(t,{recursive:!0}),console.log(W.default.yellow(`\u26A0 No scaffolding command found - creating empty directory
|
|
151
|
+
`));return}let o=(await Qn(e,n)).find(s=>!s.success);if(o)throw console.log(W.default.red(`
|
|
152
|
+
\u2717 Scaffolding failed: ${o.command}`)),o.error&&console.log(W.default.red(` Error: ${o.error}`)),new Error(`Command failed: ${o.command}${o.error?` - ${o.error}`:""}`)},us=async(e,t)=>{t.start("Linking workspace dependencies...");try{await H({cwd:e,quiet:!0}),t.succeed("Workspace dependencies linked")}catch{let n=x();t.warn(`Workspace sync skipped (run ${n} install manually)`)}},gs=async(e,t,n)=>{if(e.length===0)return;n.stop();let r=e.length===1?"package":"packages";console.log(W.default.cyan(`
|
|
153
153
|
\u25B6 Installing ${e.length} additional ${r}...
|
|
154
|
-
`));try{await
|
|
155
|
-
`))}catch(o){throw console.log(
|
|
156
|
-
`)),o}},
|
|
154
|
+
`));try{await H({packages:e,cwd:t,flags:["--silent"]}),console.log(W.default.green(`\u2713 Installed ${e.length} ${r}
|
|
155
|
+
`))}catch(o){throw console.log(W.default.red(`\u2717 Package installation failed
|
|
156
|
+
`)),o}},rr=async(e,t)=>{if(e.length===0)return;console.log(W.default.cyan(`
|
|
157
157
|
\u25B6 Running post-generation commands...
|
|
158
|
-
`));let r=(await
|
|
159
|
-
\u26A0 Post-command failed: ${r.command}`)),r.error&&console.log(
|
|
160
|
-
`))};var
|
|
161
|
-
`,
|
|
162
|
-
`),
|
|
158
|
+
`));let r=(await Qn(e,t)).find(o=>!o.success);if(r){console.log(W.default.yellow(`
|
|
159
|
+
\u26A0 Post-command failed: ${r.command}`)),r.error&&console.log(W.default.yellow(` Error: ${r.error}`));return}console.log(W.default.green(`\u2713 Post-generation commands complete
|
|
160
|
+
`))};var dt=u(require("chalk")),vl=e=>`${dt.default.dim(" \u2022 ")+dt.default.cyan(e)}
|
|
161
|
+
`,fs=e=>dt.default.dim(` \u2728 Generated ${dt.default.white.bold(e)} tokens
|
|
162
|
+
`),hs=()=>{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(vl(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 Cl=()=>{let e=y(),t=(0,Re.join)(e,"package.json"),n=(()=>{if(!(0,re.existsSync)(t))throw new Error("No package.json found in workspace root. Run from a valid workspace.");try{let o=JSON.parse((0,re.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()}},xl=async(e,t,n,r,o,s)=>{let a=as(n,r,o,t.workspaceRoot),i=ss(t,o,s),c=hs(),l=await jo(e,a,{system:i,maxTokens:16384,temperature:.7,onToken:c}),p=c.getStats();return console.log(fs(p.tokenCount)),console.log(),l},wl=(e,t)=>{let{serviceTypes:n}=nt(),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})},bl=e=>e.length===0?"":`${[h.default.cyan(`
|
|
163
163
|
\u{1F4C1} Files to create:`),...e.map(t=>` ${h.default.green("\u2022")} ${h.default.white(t.path)} ${h.default.dim(`(${t.language})`)}`)].join(`
|
|
164
164
|
`)}
|
|
165
|
-
`,
|
|
165
|
+
`,ys=(e,t,n)=>e.length===0?"":`${[h.default.cyan(`
|
|
166
166
|
${n} ${t}:`),...e.map(r=>` ${h.default.yellow("$")} ${h.default.white(r.command)}`)].join(`
|
|
167
167
|
`)}
|
|
168
|
-
`,
|
|
168
|
+
`,Sl=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
|
-
`,
|
|
171
|
+
`,Pl=(e,t)=>`${[h.default.yellow(`
|
|
172
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
|
-
`,
|
|
176
|
-
`)},
|
|
175
|
+
`,Ne=e=>{e&&process.stdout.write(e)},Tl=(e,t)=>{let n=ls(e,t),r=er(n.commands),o=er(n.postCommands),s=ps(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`),Ne(Pl(s.errors,e.slice(0,500))),null)},$l=e=>{console.log(`${h.default.green("\u2714")} Extracted ${e.files.length} files`),Ne(bl(e.files)),Ne(ys(e.commands,"Commands to run","\u{1F527}")),Ne(ys(e.postCommands,"Post-generation commands","\u{1F4DD}")),Ne(Sl(e.dependencies)),Ne(`
|
|
176
|
+
`)},El=(e,t,n)=>{let r=Vo(e);return r&&!r.includes("/")&&!r.startsWith(".")&&(r=`${L().services}/${r}`),r?(0,Re.resolve)(n,r):(0,Re.resolve)(n,t)},Al=(e,t)=>{let{serviceTypes:n}=nt(),r=n[t]?.skipFiles||["package.json","tsconfig.json","Dockerfile"];return e.filter(o=>!r.includes(o.path))},Me=()=>{if(!at())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:_t()}}catch(e){return{valid:!1,error:h.default.red.bold(`\u274C ${e.message}
|
|
179
|
+
`)}}},qt=async e=>e||(0,ks.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"}),Vt=(e,t,n)=>{console.log(h.default.cyan.bold(`
|
|
180
180
|
\u{1F916} AI-Powered Generation
|
|
181
181
|
`)),console.log(h.default.dim(`Service: ${e.split("/").pop()}`)),console.log(h.default.dim(`Path: ${e}`)),console.log(h.default.dim(`Model: ${t.model}`)),console.log(h.default.dim(`Description: ${n}
|
|
182
|
-
`))},
|
|
182
|
+
`))},Zt=async(e,t)=>{let{servicePath:n,description:r="",serviceType:o,packageManager:s}=e,a=n.split("/").pop()||n,i=Cl(),c=(0,Re.join)(i.workspaceRoot,ct);(0,re.writeFileSync)(c,`generating:${n}`);let l=()=>{(0,re.existsSync)(c)&&(0,re.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 xl(t,i,n,r,o,s),k=Tl(d,a);if(!k)return!1;$l(k);let I=(0,vs.default)({text:"Processing files...",color:"cyan"}).start(),Ye=wl(k.commands,o),O=El(Ye,n,i.cwd),Hi=Al(k.files,o);await ds(Ye,O,i.workspaceRoot);let{missingContractCommands:Br}=await Xo(Hi,O,i,I);if(k.postCommands.length>0)await rr(k.postCommands,i.workspaceRoot);else if(Br.length>0){console.log(h.default.cyan(`\u{1F527} Auto-creating missing contracts...
|
|
185
|
+
`));let Bi=Br.map(Wi=>({command:Wi,isPfCommand:!0}));await rr(Bi,i.workspaceRoot)}return qo(O),await gs(k.dependencies,O,I),await us(i.workspaceRoot,I),await Yo(O,I),!0}finally{process.off("SIGINT",p),process.off("SIGTERM",p),l()}};var xs=require("node:fs"),ut=require("ts-morph"),Cs=new ut.Project({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0}),or=e=>{if(!(0,xs.existsSync)(e))return null;let t=Cs.getSourceFile(e);return t||Cs.addSourceFileAtPath(e)},sr=e=>{e.saveSync()},ar=(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})},Il=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()===ut.SyntaxKind.ObjectLiteralExpression)return o}return null},ir=(e,t)=>{let n=Il(e);if(!n)return!1;let r=n.getProperty("imports");if(r){let o=r.getFirstChildByKind(ut.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 Yt=require("node:fs"),gt=u(require("node:path")),cr=u(require("chalk"));var ws=async e=>{await ce("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 Nl()},lr=()=>et("bun"),bs=()=>Sn([{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"}),Ss=()=>Sn([{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:cr.default.blackBright("* Installing dependencies from cache for a Remix app."),barColor:"blackBright"}),Nl=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=[gt.default.join(t,".zshrc"),gt.default.join(t,".bashrc"),gt.default.join(t,".bash_profile")];for(let r of n)try{if(await Yt.promises.stat(r).then(()=>!0).catch(()=>!1)){(await Yt.promises.readFile(r,"utf8")).includes(e)||(await Yt.promises.appendFile(r,`
|
|
188
188
|
# Added by platform installer
|
|
189
189
|
${e}
|
|
190
|
-
`),m.log(`Added Bun path to ${
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
`)
|
|
195
|
-
`)
|
|
190
|
+
`),m.log(`Added Bun path to ${gt.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(cr.default.cyan(e))};var M=require("node:fs"),je=require("node:path");var ft=require("node:fs"),Xt=require("node:path"),Rl=e=>e.isDirectory()&&e.name!=="node_modules",Ml=(e,t)=>{let n=t.replace(".ts",""),r=(0,Xt.join)(e,`${n}.mock.json`);return(0,ft.existsSync)(r)},jl=(e,t)=>t.endsWith(".ts")&&t!=="index.ts"&&Ml(e,t),Fl=(e,t)=>{let n=t.replace(".ts","");return`${e.replace(/s$/,"")}.${n}`},Ol=e=>(0,ft.readdirSync)(e,{withFileTypes:!0}).filter(Rl).flatMap(r=>{let o=(0,Xt.join)(e,r.name);return(0,ft.readdirSync)(o).filter(a=>jl(o,a)).map(a=>Fl(r.name,a))}),pr=()=>{try{let e=(0,Xt.join)(process.cwd(),"packages","contracts","src","events");return Ol(e).sort()}catch{return[]}},Ps=()=>pr();var Ts=require("node:fs"),$s=require("node:path"),ht=u(require("chalk"));var Qt=u(require("chalk")),pe=e=>{let t=Math.max(...e.commands.map(o=>o.name.length)),n=e.commands.map(o=>{let s=" ".repeat(t-o.name.length+3);return` ${Qt.default.cyan(o.name)}${s}${o.description}`}),r=e.footer||'Run "<command> --help" for more information';return[Qt.default.cyan.bold(`
|
|
191
|
+
${e.title}
|
|
192
|
+
`),`Available commands:
|
|
193
|
+
`,...n,"",Qt.default.dim(`${r}
|
|
194
|
+
`)].join(`
|
|
195
|
+
`)};var _l=(e,t)=>t.some(n=>n.name()===e),Dl=(e,t)=>t.pf?.commands?.[e]??null,Ll=(e,t)=>!!t.scripts?.[e],Hl=(e,t)=>t.cwd?(0,$s.join)(e,t.cwd):e,Bl=(e,t)=>t.command||e,Wl=(e,t,n,r)=>{let o=Hl(r,n),s=Bl(e,n);if(n.cwd&&!(0,Ts.existsSync)(o))return console.error(ht.default.red(`
|
|
196
|
+
\u2716 Directory not found: ${o}
|
|
197
|
+
`)),!0;let a=n.cwd?ht.default.dim(` in ${n.cwd}/`):"";return console.log(ht.default.dim(`Running ${s}${a}`)),jt(s,t,{cwd:o}),!0},Gl=(e,t,n)=>(console.log(ht.default.dim(`Running workspace script: ${e}`)),rt(e,{args:t,cwd:n}),!0);async function Ul(e,t,n){if(_l(e,n))return!1;let r;try{r=y()}catch{return!1}let o=J(r);if(!o)return!1;let s=Dl(e,o);return s?Wl(e,t,s,r):Ll(e,o)?Gl(e,t,r):!1}function Es(){let e;try{e=J()}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 mr(){let{configured:e,scripts:t}=Es();return[...e,...t]}function As(){let{configured:e,scripts:t}=Es(),n=[...e,...t];if(n.length===0)return"";let o=J()?.pf?.commands||{},s=n.map(a=>({name:a,description:o[a]?.description||en[a]||""}));return pe({title:"Workspace Commands",commands:s,footer:""})}function Is(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=mr();for(let i of a)console.log(i);return}Ul(o,s,n).then(a=>{a||e.parse(t)})}else e.parse(t)}var Ns={setup:"Configure platform settings",new:"Create a new project",dev:"Start development mode",event:"Event management commands",token:"Token management commands",audit:"Run security audit"},en={build:"Build all packages",test:"Run tests",lint:"Lint codebase",format:"Format code",preview:"Preview application",prepare:"Prepare workspace",pulumi:"Run Pulumi commands","pub-sdk":"Publish platform SDK","pub-cloudevents":"Publish cloudevents package","check-versions":"Check internal version consistency","sync-versions":"Sync internal package versions","sync-templates":"Sync service templates","generate-env":"Generate environment files",dev:"Start development environment"},Rs=(e,t)=>t?`${e}:${t}`:e,Jl=()=>Object.entries(Ns).map(([e,t])=>Rs(e,t)),Kl=()=>{try{let e=mr(),n=J()?.pf?.commands||{},r=Object.keys(Ns);return e.filter(o=>!r.includes(o)).map(o=>{let s=n[o]?.description||en[o]||"";return Rs(o,s)})}catch{return[]}},zl=()=>{try{return Ps()}catch{return[]}},dr=()=>({commands:[...Jl(),...Kl()],events:zl()});var yt="node_modules/.cache/pf",kt="completion-cache";var ql=e=>{let t=N.version||"0.0.0",n=e.commands.join("|"),r=e.events.join("|");return`${t} ${n} ${r}`},Vl=e=>{let t=e.split(" ");if(t.length===3){let[o,s,a]=t;return{version:o,commands:s?s.split("|"):[],events:a?a.split("|"):[]}}let[n,r]=t;return{commands:n?n.split("|"):[],events:r?r.split("|"):[]}},Zl=e=>{let t=(0,je.join)(e,yt);return(0,je.join)(t,kt)},Yl=(e,t=!1)=>{if(t)return!0;let n=Zl(e);if(!(0,M.existsSync)(n))return!0;let r=(0,M.readFileSync)(n,"utf-8").trim(),o=Vl(r),s=N.version||"0.0.0";if(o.version!==s)return!0;let a=(0,je.join)(e,"package.json");if(!(0,M.existsSync)(a))return!1;let i=(0,M.statSync)(n).mtimeMs;return(0,M.statSync)(a).mtimeMs>i};var Xl=(e,t)=>{let n=(0,je.join)(e,yt),r=(0,je.join)(n,kt);(0,M.existsSync)(n)||(0,M.mkdirSync)(n,{recursive:!0});let o=ql(t);(0,M.writeFileSync)(r,o,"utf-8")},tn=(e={})=>{let t;try{t=y()}catch{return!1}if(!t)return!1;if(!Yl(t,e.force))return e.verbose&&console.log("[completion] Cache is up to date"),!1;let n=dr();return Xl(t,n),e.verbose&&console.log(`[completion] Cache regenerated: ${n.commands.length} commands, ${n.events.length} events`),!0},ke=(e={})=>{tn({...e,force:!0})};var V=require("node:fs"),ur=require("node:os"),nn=require("node:path"),ve=u(require("chalk"));var Ms=`${yt}/${kt}`,js=e=>`# ${e} completion (workspace-local cache)
|
|
198
|
+
# Generated: ${new Date().toISOString()}
|
|
199
|
+
|
|
200
|
+
# Cache file path (relative to workspace root)
|
|
201
|
+
_${e}_cache_path="${Ms}"
|
|
202
|
+
|
|
203
|
+
# Find workspace root (walk up to find monorepo package.json)
|
|
204
|
+
_${e}_find_workspace() {
|
|
205
|
+
local dir="$PWD"
|
|
206
|
+
while [[ "$dir" != "/" ]]; do
|
|
207
|
+
if [[ -f "$dir/package.json" ]] && grep -q '"workspaces"' "$dir/package.json" 2>/dev/null; then
|
|
208
|
+
echo "$dir"
|
|
209
|
+
return
|
|
210
|
+
fi
|
|
211
|
+
dir="\${dir:h}"
|
|
212
|
+
done
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
# Read cache file from workspace
|
|
216
|
+
_${e}_read_cache() {
|
|
217
|
+
local ws="$1"
|
|
218
|
+
local cache="$ws/$_${e}_cache_path"
|
|
219
|
+
[[ -f "$cache" ]] && cat "$cache"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# Main completion function
|
|
223
|
+
_${e}_completions() {
|
|
224
|
+
local line state
|
|
225
|
+
|
|
226
|
+
_arguments -C \\
|
|
227
|
+
"1: :->cmds" \\
|
|
228
|
+
"*::arg:->args"
|
|
229
|
+
|
|
230
|
+
# Find workspace and read cache
|
|
231
|
+
local ws_root=$(_${e}_find_workspace)
|
|
232
|
+
local cache_data=""
|
|
233
|
+
local in_workspace=0
|
|
234
|
+
|
|
235
|
+
if [[ -n "$ws_root" ]]; then
|
|
236
|
+
in_workspace=1
|
|
237
|
+
cache_data=$(_${e}_read_cache "$ws_root")
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
# Parse data: "version cmd1:desc1|cmd2:desc2 events"
|
|
241
|
+
# Split by tabs, skip first field (version)
|
|
242
|
+
local -a parts
|
|
243
|
+
parts=("\${(@s: :)cache_data}")
|
|
244
|
+
|
|
245
|
+
local commands_str=""
|
|
246
|
+
local events_str=""
|
|
247
|
+
|
|
248
|
+
if [[ \${#parts[@]} -eq 3 ]]; then
|
|
249
|
+
# New format: version commands events
|
|
250
|
+
commands_str="\${parts[2]}"
|
|
251
|
+
events_str="\${parts[3]}"
|
|
252
|
+
elif [[ \${#parts[@]} -eq 2 ]]; then
|
|
253
|
+
# Legacy format: commands events
|
|
254
|
+
commands_str="\${parts[1]}"
|
|
255
|
+
events_str="\${parts[2]}"
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
case "$state" in
|
|
259
|
+
cmds)
|
|
260
|
+
if [[ -n "$commands_str" ]]; then
|
|
261
|
+
# Cache exists \u2192 all commands
|
|
262
|
+
local -a subcmds
|
|
263
|
+
subcmds=("\${(@s:|:)commands_str}")
|
|
264
|
+
_describe 'command' subcmds
|
|
265
|
+
elif [[ $in_workspace -eq 1 ]]; then
|
|
266
|
+
# Workspace but no cache \u2192 main commands
|
|
267
|
+
local -a main_cmds
|
|
268
|
+
main_cmds=(
|
|
269
|
+
"setup:Configure platform settings"
|
|
270
|
+
"new:Create a new project"
|
|
271
|
+
"dev:Start development mode"
|
|
272
|
+
"event:Event management commands"
|
|
273
|
+
"token:Token management commands"
|
|
274
|
+
"audit:Run security audit"
|
|
275
|
+
)
|
|
276
|
+
_describe 'command' main_cmds
|
|
277
|
+
else
|
|
278
|
+
# No workspace \u2192 only new
|
|
279
|
+
local -a fallback_cmds
|
|
280
|
+
fallback_cmds=(
|
|
281
|
+
"new:Create a new project"
|
|
282
|
+
)
|
|
283
|
+
_describe 'command' fallback_cmds
|
|
284
|
+
fi
|
|
285
|
+
;;
|
|
286
|
+
args)
|
|
287
|
+
case $line[1] in
|
|
288
|
+
new)
|
|
289
|
+
local -a new_commands
|
|
290
|
+
new_commands=(
|
|
291
|
+
"workspace:Create a new workspace"
|
|
292
|
+
"hono-micro:Create a Hono microservice"
|
|
293
|
+
"nest-micro:Create a NestJS microservice"
|
|
294
|
+
)
|
|
295
|
+
_describe 'new commands' new_commands
|
|
296
|
+
;;
|
|
297
|
+
event)
|
|
298
|
+
case $line[2] in
|
|
299
|
+
publish)
|
|
300
|
+
if [[ -n "$events_str" ]]; then
|
|
301
|
+
local -a events
|
|
302
|
+
events=("\${(@s:|:)events_str}")
|
|
303
|
+
_describe 'event type' events
|
|
304
|
+
fi
|
|
305
|
+
;;
|
|
306
|
+
*)
|
|
307
|
+
local -a event_commands
|
|
308
|
+
event_commands=(
|
|
309
|
+
"add:Add event contract and handler"
|
|
310
|
+
"list:List all event mocks"
|
|
311
|
+
"publish:Publish to NATS JetStream"
|
|
312
|
+
)
|
|
313
|
+
_describe 'event commands' event_commands
|
|
314
|
+
;;
|
|
315
|
+
esac
|
|
316
|
+
;;
|
|
317
|
+
esac
|
|
318
|
+
;;
|
|
319
|
+
esac
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
compdef _${e}_completions ${e}`,Fs=e=>`# ${e} completion (workspace-local cache)
|
|
323
|
+
# Generated: ${new Date().toISOString()}
|
|
324
|
+
|
|
325
|
+
# Cache file path (relative to workspace root)
|
|
326
|
+
_${e}_cache_path="${Ms}"
|
|
327
|
+
|
|
328
|
+
# Find workspace root
|
|
329
|
+
_${e}_find_workspace() {
|
|
330
|
+
local dir="$PWD"
|
|
331
|
+
while [[ "$dir" != "/" ]]; do
|
|
332
|
+
if [[ -f "$dir/package.json" ]] && grep -q '"workspaces"' "$dir/package.json" 2>/dev/null; then
|
|
333
|
+
echo "$dir"
|
|
334
|
+
return
|
|
335
|
+
fi
|
|
336
|
+
dir="$(dirname "$dir")"
|
|
337
|
+
done
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
# Read cache file
|
|
341
|
+
_${e}_read_cache() {
|
|
342
|
+
local ws="$1"
|
|
343
|
+
local cache="$ws/$_${e}_cache_path"
|
|
344
|
+
[[ -f "$cache" ]] && cat "$cache"
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
# Main completion function
|
|
348
|
+
_${e}_completions() {
|
|
349
|
+
local cur prev opts
|
|
350
|
+
COMPREPLY=()
|
|
351
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
352
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
353
|
+
|
|
354
|
+
# Find workspace and read cache
|
|
355
|
+
local ws_root=$(_${e}_find_workspace)
|
|
356
|
+
local cache_data=""
|
|
357
|
+
local commands_str=""
|
|
358
|
+
local events_str=""
|
|
359
|
+
local in_workspace=0
|
|
360
|
+
|
|
361
|
+
if [[ -n "$ws_root" ]]; then
|
|
362
|
+
in_workspace=1
|
|
363
|
+
cache_data=$(_${e}_read_cache "$ws_root")
|
|
364
|
+
|
|
365
|
+
# Parse data: "version cmd1:desc1|cmd2:desc2 events"
|
|
366
|
+
IFS=$'\\t' read -ra parts <<< "$cache_data"
|
|
367
|
+
|
|
368
|
+
if [[ \${#parts[@]} -eq 3 ]]; then
|
|
369
|
+
# New format: version commands events
|
|
370
|
+
commands_str="\${parts[1]}"
|
|
371
|
+
events_str="\${parts[2]}"
|
|
372
|
+
elif [[ \${#parts[@]} -eq 2 ]]; then
|
|
373
|
+
# Legacy format: commands events
|
|
374
|
+
commands_str="\${parts[0]}"
|
|
375
|
+
events_str="\${parts[1]}"
|
|
376
|
+
fi
|
|
377
|
+
fi
|
|
378
|
+
|
|
379
|
+
# Extract command names
|
|
380
|
+
local cmd_names=""
|
|
381
|
+
if [[ -n "$commands_str" ]]; then
|
|
382
|
+
cmd_names=$(echo "$commands_str" | tr '|' '\\n' | cut -d: -f1 | tr '\\n' ' ')
|
|
383
|
+
elif [[ $in_workspace -eq 1 ]]; then
|
|
384
|
+
cmd_names="setup new dev event token audit"
|
|
385
|
+
else
|
|
386
|
+
cmd_names="new"
|
|
387
|
+
fi
|
|
388
|
+
|
|
389
|
+
opts="$cmd_names"
|
|
390
|
+
|
|
391
|
+
# Subcommand completion
|
|
392
|
+
case "\${COMP_WORDS[1]}" in
|
|
393
|
+
new)
|
|
394
|
+
opts="workspace hono-micro nest-micro"
|
|
395
|
+
;;
|
|
396
|
+
event)
|
|
397
|
+
case "\${COMP_WORDS[2]}" in
|
|
398
|
+
publish)
|
|
399
|
+
if [[ -n "$events_str" ]]; then
|
|
400
|
+
opts=$(echo "$events_str" | tr '|' ' ')
|
|
401
|
+
fi
|
|
402
|
+
;;
|
|
403
|
+
*)
|
|
404
|
+
opts="add list publish"
|
|
405
|
+
;;
|
|
406
|
+
esac
|
|
407
|
+
;;
|
|
408
|
+
esac
|
|
409
|
+
|
|
410
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
411
|
+
return 0
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
complete -F _${e}_completions ${e}`;var Ql=(e,t)=>(0,nn.join)((0,ur.homedir)(),`.${t}-completion.${e}`),_s=e=>{let t=(0,ur.homedir)();return e==="zsh"?(0,nn.join)(t,".zshrc"):(0,nn.join)(t,".bashrc")},ep=e=>`[[ -f "${e}" ]] && source "${e}"`,tp=(e,t)=>(0,V.existsSync)(e)?(0,V.readFileSync)(e,"utf-8").includes(t):!1,np=(e,t)=>{let n=(0,V.existsSync)(e)?(0,V.readFileSync)(e,"utf-8"):"",r=n.endsWith(`
|
|
415
|
+
`)?`${n}${t}
|
|
416
|
+
`:`${n}
|
|
417
|
+
${t}
|
|
418
|
+
`;(0,V.writeFileSync)(e,r,"utf-8")},rp=(e,t)=>{let n=Ql(e,t),r=e==="zsh"?js(t):Fs(t);return(0,V.writeFileSync)(n,r,"utf-8"),n},Os=(e,t,n)=>{let r=rp(e,t),o=_s(e),s=ep(r);return tp(o,s)?(n&&console.log(ve.default.dim(`[${e}] Already configured in ${o}`)),!1):(np(o,s),n&&console.log(ve.default.green(`[${e}] Added source line to ${o}`)),!0)},op=()=>(process.env.SHELL||"").includes("zsh")?"zsh":"bash",gr=(e,t=!1)=>{let n=op();t&&console.log(ve.default.cyan(`Installing ${n} completion...`)),Os(n,e,t);let r=n==="zsh"?"bash":"zsh",o=_s(r);(0,V.existsSync)(o)&&Os(r,e,t),t&&(console.log(ve.default.green("\u2713 Shell completion installed")),console.log(ve.default.dim(` Run: ${ve.default.cyan("exec $SHELL")} to reload`)))};var $=u(require("chalk")),Ds=require("execa"),Ls=require("jiti");var vt=async e=>{let{stdout:t}=await(0,Ds.execa)("sh",["-c",e]);return t.trim()},fr="pf-local-nats",sp="2.10-alpine",ap=4222,ip=8222,cp=e=>({clientPort:e.clientPort??ap,monitoringPort:e.monitoringPort??ip,containerName:e.containerName??fr,version:e.version??sp}),lp=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"],pp=e=>({containerName:e.containerName,clientUrl:`nats://localhost:${e.clientPort}`,monitoringUrl:`http://localhost:${e.monitoringPort}`}),mp=async()=>{try{return await vt("docker info"),!0}catch{return!1}},Hs=async e=>{try{return(await vt(`docker ps -q -f name=${e}`)).length>0}catch{return!1}},dp=async e=>{try{await vt(`docker stop ${e} 2>/dev/null || true`),await vt(`docker rm ${e} 2>/dev/null || true`)}catch{}},up=async e=>{let t=lp(e);try{return await vt(`docker ${t.join(" ")}`),{success:!0,value:pp(e)}}catch{return{success:!1}}},gp=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("")},Bs=async(e={})=>{let t=cp(e);if(!await mp())return console.log($.default.yellow("\u26A0\uFE0F Docker not available - skipping NATS (services may fail)")),!1;if(await Hs(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 up(t);return n.success?(gp(n.value),!0):(console.error($.default.red("\u2717 Failed to start NATS")),!1)},fp=e=>e.map(t=>({stream:t,subjects:[`${t.toLowerCase()}.*`],config:{storage:"memory",retention:"limits",maxAge:36e5}})),hp=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))),Ws=async e=>{try{let{ensureJetStreams:t}=await import("@crossdelta/cloudevents"),{indexPath:n}=C(e),o=await(0,Ls.createJiti)(e).import(n,{default:!0}),s=hp(o);if(s.length===0){console.log($.default.dim(" No streams found in contracts"));return}let a=fp(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"))}},yp=async(e=fr)=>{await Hs(e)&&(console.log($.default.dim("Stopping NATS...")),await dp(e))},Gs=async(e=fr)=>{await yp(e)};function Us(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
196
419
|
import { ports } from '@crossdelta/infrastructure'
|
|
197
420
|
|
|
198
421
|
/**
|
|
@@ -213,7 +436,7 @@ const config: K8sServiceConfig = {
|
|
|
213
436
|
}
|
|
214
437
|
|
|
215
438
|
export default config
|
|
216
|
-
`}function
|
|
439
|
+
`}function Js(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
217
440
|
import { ports } from '@crossdelta/infrastructure'
|
|
218
441
|
|
|
219
442
|
/**
|
|
@@ -234,182 +457,78 @@ const config: K8sServiceConfig = {
|
|
|
234
457
|
}
|
|
235
458
|
|
|
236
459
|
export default config
|
|
237
|
-
`}var
|
|
238
|
-
`)
|
|
239
|
-
|
|
240
|
-
|
|
460
|
+
`}var Z=u(require("chalk")),qs=u(require("terminal-link"));var rn="integrations-run";var P=require("zod"),kp=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()}),Ks=P.z.array(kp);var zs=e=>{try{return Ks.parse(e)}catch(t){throw new Error(t.issues.map(n=>` - Path ${n.path.join(". ")} : ${n.message}`).join(`
|
|
461
|
+
`))}};var G=()=>{try{let e=Mt("bin/integration.collection.json");return zs(e)}catch(e){throw new Error(`Failed to load integrations!
|
|
462
|
+
Check your integration.collection.json:
|
|
463
|
+
${e.message}`)}},Fe=()=>G().reduce((t,n)=>(n.initial&&t.push(n.name),t),[]),vp=e=>!!e?.name&&!!e?.link&&!!e?.description,on=e=>{let t=G();if(!t?.length||!e?.length)return;let n=e.map(r=>t.find(o=>o.name===r)).filter(vp);n.length&&(m.breakLine().log("\u{1F50C} Installed Integrations:"),n.forEach(({name:r,link:o,description:s})=>{let a=m.getStoredLogs(`${rn}:${r}`);o&&m.log(`${(0,qs.default)(Z.default.cyan(r),o)} - ${s}`),a.length&&m.log(a.map(i=>` \u203A ${Z.default.dim(i.message)}`).join(`
|
|
464
|
+
`))}))},Cp=e=>e.toUpperCase().replace(/-/g,"_"),Vs=(e,t)=>{let n=Cp(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 hr=u(require("chalk"));var xp=e=>{let t=e.match(/^(@?[^@]+)@(.+)$/);return t?{name:t[1],version:t[2]}:{name:e,version:"latest"}},Zs=async e=>{let{selectedIntegrations:t,cwd:n,packageManager:r=x(),task:o}=e;if(!t?.length||!o)return;let s=wp(t,n,r,o);await Nt(o,s)},wp=(e,t,n,r)=>{let s=G()?.filter(i=>e.includes(i.name))?.flatMap(i=>i.install.map(c=>{let{name:l,version:p}=xp(c);return{title:hr.default.cyanBright(`Adding ${c} (${i.name})`),fn:async()=>{te(`dependencies.${l}`,p,t)}}})),a={title:hr.default.cyanBright("Installing packages..."),fn:async()=>{await H({cwd:t,packageManager:n,task:r})}};return[...s??[],a]};var Ys=u(require("chalk"));var Xs=async e=>{let{selectedIntegrations:t,cwd:n,task:r}=e;if(!t?.length||!r)return;let o=bp(t,n,r,e.packageManager);await Nt(r,o)},bp=(e,t,n,r)=>G().filter(s=>e.includes(s.name)&&s.run?.length).flatMap(s=>(s.run||[]).map(a=>({title:Ys.default.cyanBright(`Running "${a}" for ${s.name}
|
|
465
|
+
`),fn:()=>Sp(s,a,t,n,r)}))),Sp=async(e,t,n,r,o)=>{let s=`${rn}:${e.name}`;try{if(e.interactive)return yo(t,[],{cwd:n,context:s,task:r,manager:o});await ne(t,[],{cwd:n,task:r,context:s})}catch(a){m.error(`Failed to run command "${t}" for ${e.name}: ${a.message}`)}};var sn=require("node:fs"),Ct=require("node:path");var an=(e,t)=>{try{let n=(0,sn.readFileSync)(e,"utf-8"),r=JSON.parse(n);t(r),(0,sn.writeFileSync)(e,JSON.stringify(r,null,2),"utf-8")}catch{}},Pp=e=>{let t=(0,Ct.join)(g(e),"tsconfig.json");an(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"]})},Tp=e=>{let t=(0,Ct.join)(g(e),"tsconfig.build.json");an(t,n=>{n.exclude=["node_modules","test","dist","**/*.spec.ts","**/*.test.ts"]})},$p=e=>{let t=(0,Ct.join)(g(e),"nest-cli.json");an(t,n=>{n.compilerOptions=n.compilerOptions||{},n.compilerOptions.tsConfigPath="tsconfig.build.json"})},Ep=e=>{let t=(0,Ct.join)(g(e),"package.json");an(t,n=>{delete n.jest})},Qs=e=>{Pp(e),Tp(e),$p(e),Ep(e)};var ea=require("node:path");var Ap=(e,t)=>{let n=or(e);if(n){for(let{className:r,importPath:o}of t)ar(n,o,[r]),ir(n,r);sr(n)}},ta=e=>{let t=(0,ea.join)(g(e),"src","app.module.ts");Ap(t,[{className:"EventsModule",importPath:"./events/events.module"}])};var Ip=require("fs-extra");var Rp=u(require("chalk")),Mp=u(require("cli-table3"));var na=require("node:fs"),ra=require("node:path"),oa=u(require("handlebars"));var Oe=(e,t)=>Oo(e,t??`Templates directory not found. Searched in: ${e.join(", ")}`),yr=(e,t={})=>{let n=(0,na.readFileSync)(e,"utf-8");return oa.default.compile(n)(t)},cn=e=>(t,n={})=>{let r=(0,ra.join)(e,t);return yr(r,n)};var xt=e=>e.toUpperCase().replace(/-/g,"_");var sa=e=>e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ");function ln(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}async function aa(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?`--${ln(String(l))}`:`--${ln(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?`--${ln(l)}`:`--${ln(l)}=${String(p)}`}).filter(l=>l!==void 0),c=[...s,...a,...i].map(String);await e.parseAsync(c,{from:"user"})}var $a=require("node:path"),oe=u(require("chalk"));var ia=require("@listr2/prompt-adapter-enquirer"),_e={title:"Confirm creation",enabled:e=>!e.userConfirmed,task:async(e,t)=>{if(e.userConfirmed=await t.prompt(ia.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 Y=require("node:fs"),De=require("node:path");var jp=4001,Fp=4e3;function Op(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 _p(e,t){let n=t?jp:Fp,r=new Set;if(!(0,Y.existsSync)(e))return n;let o=(0,Y.readdirSync)(e).filter(a=>a.endsWith(".ts"));for(let a of o){let i=(0,De.join)(e,a);try{let c=(0,Y.readFileSync)(i,"utf-8"),l=Op(c);for(let p of l)r.add(p)}catch{}}let s=n;for(;r.has(s);)s++;return s}function Dp(e){return(0,De.basename)(e)}var pn={title:"Creating infrastructure service config",task:async(e,t)=>{let n=Dp(e.projectName),r=y(),o=(0,De.join)(r,"infra","services");if(!(0,Y.existsSync)(o)){t.title="Skipping infra config (no infra/services directory found)";return}let s=(0,De.join)(o,`${n}.ts`);if((0,Y.existsSync)(s)){t.title=`Service config already exists: infra/services/${n}.ts`;return}let a=_p(o,!0);e.assignedPort=a;let i=e.serviceType==="hono"?Us(n,a):Js(n,a);(0,Y.writeFileSync)(s,i),t.title=`Created infra/services/${n}.ts (port: ${a})`}};var wt=require("node:child_process"),ca=require("node:fs"),la=require("node:path"),Lp=()=>{try{return(0,wt.execSync)("git --version",{stdio:"ignore"}),!0}catch{return!1}},Hp=e=>(0,ca.existsSync)((0,la.join)(e,".git")),pa={title:"Initializing git repository",enabled:()=>Lp(),skip:e=>Hp(e.cwd)?"Already a git repository":!1,task:async(e,t)=>{try{(0,wt.execSync)("git init",{cwd:e.cwd,stdio:"ignore"}),(0,wt.execSync)("git add -A",{cwd:e.cwd,stdio:"ignore"}),(0,wt.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 ma=require("@listr2/prompt-adapter-enquirer"),kr=u(require("chalk"));var Le={title:"Installing Bun",enabled:e=>!!e.shouldInstallBun&&!lr(),task:async(e,t)=>S(t,async n=>{await ws(t),e.elapsedTime+=n(),t.title=`Bun installed successfully. (${e.elapsedTime}s)`})},He={enabled:e=>!lr()&&!e.shouldInstallBun&&!e.packageManager,task:async(e,t)=>{e.shouldInstallBun=await t.prompt(ma.ListrEnquirerPromptAdapter).run({type:"Toggle",message:"Would you like to use Bun? (recommended)",initial:!0,footer:["",`${kr.default.magenta.bold("Bun")} is a fast JavaScript runtime, package manager, bundler, and test runner: ${kr.default.underline("https://bun.sh")}`,bs(),Ss()].join(`
|
|
466
|
+
`)}),e.shouldInstallBun&&(e.packageManager="bun")}};var da=require("@listr2/prompt-adapter-enquirer"),vr=u(require("chalk"));var mn={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 Zs({selectedIntegrations:r,packageManager:s,cwd:o,task:t}),e.elapsedTime+=n()}),rendererOptions:{outputBar:1e3}},dn={title:"Select integrations",enabled:e=>e.selectedIntegrations.length===0,task:async(e,t)=>{e.selectedIntegrations=await t.prompt(da.ListrEnquirerPromptAdapter).run({type:"MultiSelect",hint:`
|
|
467
|
+
Press <space> to select/deselect, <enter> to confirm, <i> to invert selection`,message:"Which integrations would you like to include?",initial:Fe().map((n,r)=>r),choices:e.availableIntegrations.map(({name:n,description:r})=>({name:n,message:[vr.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=>vr.default.bold(`\u2022 ${n}`))].join(`
|
|
468
|
+
`)}};var ua={title:"Install Nest CLI",task:async(e,t)=>S(t,async n=>{await ho({packages:["@nestjs/cli"],task:t,cwd:e.cwd}),e.elapsedTime+=n()}),rendererOptions:{outputBar:1e3}};var un={title:"Install dependencies",task:async(e,t)=>S(t,async n=>{await H({cwd:e.cwd,task:t,packageManager:e.packageManager}),e.elapsedTime+=n()})};var ga=require("@listr2/prompt-adapter-enquirer"),fa=u(require("chalk"));var Be={enabled:e=>!e.removeDir&&!It(e.cwd),task:async(e,t)=>{if(e.removeDir=await t.prompt(ga.ListrEnquirerPromptAdapter).run({type:"Toggle",message:fa.default.bold("\u26A0\uFE0F Overwrite existing directory?"),initial:!1}),!e.removeDir)throw new Error("Project creation was canceled by the user.")}},We={enabled:e=>!!e.removeDir,task:async e=>Yr(e.cwd)};var gn={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 Xs({selectedIntegrations:r,cwd:o,task:t,packageManager:e.packageManager}),e.elapsedTime+=n()}),rendererOptions:{outputBar:1}};var ha=require("@listr2/prompt-adapter-enquirer");var Bp=["services/my-hono-service","services/my-nest-service","my-platform"],Ge={enabled:e=>e.skipInputPrompts||e.userConfirmed?!1:e.projectName?Bp.includes(e.projectName):!0,task:async(e,t)=>{e.projectName=await t.prompt(ha.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 ya=require("@listr2/prompt-adapter-enquirer"),Cr=u(require("chalk"));var Ue={title:"Select Package manager",task:async(e,t)=>{if(e.packageManager??=Rn(),e.packageManager){t.title=`Using ${Cr.default.bold(e.packageManager)} as package manager.`;return}e.packageManager=await t.prompt(ya.ListrEnquirerPromptAdapter).run({type:"Select",message:"Which package manager would you like to use?",initial:Mn(),choices:fo}),t.title=`Using ${Cr.default.bold(e.packageManager)} as package manager.`}};var fn=require("@listr2/prompt-adapter-enquirer"),bt=u(require("chalk")),ka={title:"GitHub repository owner",task:async(e,t)=>{if(e.githubOwner){t.title=`GitHub owner: ${bt.default.bold(e.githubOwner)}`;return}e.githubOwner=await t.prompt(fn.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: ${bt.default.bold(e.githubOwner)}`}},va={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(fn.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 Ca={title:"Pulumi stack name",task:async(e,t)=>{if(e.pulumiStackBase){t.title=`Pulumi stack: ${bt.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(fn.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: ${bt.default.bold(e.pulumiStackBase)}`}};var _=require("node:fs"),j=require("node:path");var hn=require("node:path");var Wp=()=>{let e=lt();return Oe([(0,hn.join)(__dirname,"templates","hono-microservice"),(0,hn.join)(__dirname,"..","hono-microservice","templates"),(0,hn.join)(e,"bin","templates","hono-microservice")],"Hono templates directory not found.")},St=(e,t={})=>cn(Wp())(e,t);function xa(){return St("tsconfig.json.hbs")}function wa(e="1.2.23"){return St("Dockerfile.hbs",{bunVersion:e})}function ba(){return St("biome.json.hbs")}function Sa(e){return St("src/index.ts.hbs",{envKey:xt(e)})}function Pa(e){return St("src/config/env.ts.hbs",{envKey:xt(e)})}var Gp=async({projectName:e,packageManager:t},n)=>{let r=t==="bun"?"bun":"nodejs";try{await ne("create-hono@latest",[e,"--pm",t,"--template",r,"--install"],{task:n})}catch(s){let a=(0,j.join)(g(e),"package.json");if(!(0,_.existsSync)(a))throw new Error(`Failed to scaffold: ${s instanceof Error?s.message:String(s)}`)}let o=(0,j.join)(g(e),"package.json");if(!(0,_.existsSync)(o))throw new Error("Failed to scaffold Hono app structure - package.json not created")},Up=({projectName:e,packageManager:t})=>{let n=(0,j.basename)(e),r=be(),o=t==="npm"?"*":"workspace:*",s=g(e),a=no("scripts.dev",s);a&&te("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})=>te(c,l,e))},Jp=({projectName:e})=>{let t=(0,j.basename)(e),n=(0,j.join)(g(e),"src","index.ts"),r=Sa(t);(0,_.writeFileSync)(n,r)},Kp=({projectName:e})=>{let t=(0,j.basename)(e),n=g(e),r=(0,j.join)(n,"src","config");(0,_.existsSync)(r)||(0,_.mkdirSync)(r,{recursive:!0});let o=(0,j.join)(r,"env.ts"),s=Pa(t);(0,_.writeFileSync)(o,s)},zp=({projectName:e})=>{let t=g(e),n=(0,j.join)(t,"tsconfig.json");(0,_.writeFileSync)(n,xa());let r=(0,j.join)(t,"Dockerfile");(0,_.writeFileSync)(r,wa());let o=(0,j.join)(t,"biome.json");(0,_.writeFileSync)(o,ba())},Ta={title:"Create Hono app structure",rendererOptions:{outputBar:1e3},task:async(e,t)=>S(t,async n=>{await Gp(e,t),Up(e),Jp(e),Kp(e),zp(e),e.elapsedTime+=n()})};var qp=e=>{let t=(e||"my-hono-service").trim();return t.includes("/")||t.startsWith(".")?t:`${L().services}/${t}`},Vp=async(e,t)=>{let{valid:n,config:r,error:o}=Me();if(!n||!r){console.log(o);return}let s=qp(e.name),a=t.packageManager||x(),i=await qt(t.description);if(Vt(s,r,i),await Zt({servicePath:s,description:i,serviceType:"hono",packageManager:a},r))console.log(oe.default.green.bold(`
|
|
241
469
|
\u2705 Service generated successfully!
|
|
242
|
-
`)),console.log(
|
|
243
|
-
${
|
|
470
|
+
`)),console.log(oe.default.dim("Next steps:")),console.log(oe.default.dim(` ${oe.default.cyan("pf dev")} - Start all services`)),console.log(oe.default.dim(` ${oe.default.cyan(`cd ${s} && bun dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},Ea=ie({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:Vp,buildContext:async(e,t)=>{let n=(e.name??"my-hono-service").trim();!n.includes("/")&&!n.startsWith(".")&&(n=`${L().services}/${n}`);let r=g(n),o=t.packageManager??(t.yes&&x()),s=G(),a=t.yes?Fe():[],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:[Ge,Be,He,Ue,dn,_e],actions:[We,Le,Ta,pn,mn,gn],onComplete:({projectName:e,packageManager:t,selectedIntegrations:n,assignedPort:r})=>{m.breakLine().log(oe.default.bold.green("Hono Microservice created successfully!")),on(n),Vs((0,$a.basename)(e),r??8080);let o=t??x();m.breakLine().log(`To start the project, run:
|
|
471
|
+
${oe.default.bold(`cd ${e} && ${o} run dev`)}`).breakLine().log("Happy shipping with Hono! \u26A1\uFE0F").breakLine()}});var se=u(require("chalk"));var U=require("node:fs"),F=require("node:path");var wr=require("node:path");var Zp=()=>Oe([(0,wr.join)(__dirname,"templates","nest-microservice"),(0,wr.join)(__dirname,"..","nest-microservice","templates")],"NestJS templates directory not found."),Je=(e,t={})=>cn(Zp())(e,t);function yn(e,t=3e3){return Je("src/main.ts.hbs",{serviceName:e,envKey:xt(e),displayName:sa(e),defaultPort:t})}function Aa(){return Je("src/app.context.ts.hbs",{})}function Ia(){return Je("src/events/events.module.ts.hbs",{})}function Na(e){return Je("src/events/events.service.ts.hbs",{serviceName:e})}function Ra(e="24",t="1.2.23"){return Je("Dockerfile.hbs",{nodeVersion:e,bunVersion:t})}function Ma(){return Je("biome.json.hbs",{})}var Yp=async(e,t)=>{await ne("@nestjs/cli",["new",e.projectName,"--skip-install","--skip-git","--package-manager",e.packageManager],{task:t})},Xp=({projectName:e,packageManager:t})=>{let n=(0,F.basename)(e),r=be(),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})=>te(i,c,e)),["jest","@types/jest","ts-jest","@nestjs/testing","supertest","@types/supertest","ts-node","tsconfig-paths","@nestjs/schematics","@nestjs/cli"].map(i=>te(`devDependencies.${i}`,void 0,e))},Qp=({projectName:e})=>{let t=["eslint.config.mjs","src/app.controller.spec.ts"];for(let n of t)try{(0,U.unlinkSync)((0,F.join)(g(e),n))}catch{}},em=({projectName:e})=>{let t=g(e),n=(0,F.join)(t,"Dockerfile");(0,U.writeFileSync)(n,Ra());let r=(0,F.join)(t,"biome.json");(0,U.writeFileSync)(r,Ma())},tm=({projectName:e})=>{let t=(0,F.join)(g(e),"src","app.context.ts");(0,U.writeFileSync)(t,Aa())},nm=({projectName:e})=>{let t=(0,F.basename)(e),n=(0,F.join)(g(e),"src","events");(0,U.mkdirSync)(n,{recursive:!0}),(0,U.writeFileSync)((0,F.join)(n,"events.module.ts"),Ia()),(0,U.writeFileSync)((0,F.join)(n,"events.service.ts"),Na(t)),ta(e)},rm=({projectName:e})=>{let t=(0,F.basename)(e),n=(0,F.join)(g(e),"src","main.ts");(0,U.writeFileSync)(n,yn(t))},ja={title:"Create NestJS app structure",rendererOptions:{outputBar:1e3},task:async(e,t)=>S(t,async n=>{await Yp(e,t),Xp(e),Qs(e.projectName),Qp(e),em(e),tm(e),nm(e),rm(e),e.elapsedTime+=n()})};var Fa=require("node:fs"),kn=require("node:path");var Oa={title:"Patch main.ts with PORT pattern",task:async(e,t)=>S(t,async n=>{let r=(0,kn.basename)(e.projectName),o=e.assignedPort??3e3,s=(0,kn.join)(g(e.projectName),"src","main.ts");(0,Fa.writeFileSync)(s,yn(r,o)),t.title=`Patched main.ts with PORT || ${r.toUpperCase().replace(/-/g,"_")}_PORT`,e.elapsedTime+=n()})};var om=e=>{let t=(e||"my-nest-service").trim();return t.includes("/")||t.startsWith(".")?t:`${L().services}/${t}`},sm=async(e,t)=>{let{valid:n,config:r,error:o}=Me();if(!n||!r){console.log(o);return}let s=om(e.name),a=t.packageManager||x(),i=await qt(t.description);if(Vt(s,r,i),await Zt({servicePath:s,description:i,serviceType:"nest",packageManager:a},r))console.log(se.default.green.bold(`
|
|
244
472
|
\u2705 Service generated successfully!
|
|
245
|
-
`)),console.log(
|
|
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
|
-
|
|
248
|
-
`)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
473
|
+
`)),console.log(se.default.dim("Next steps:")),console.log(se.default.dim(` ${se.default.cyan("pf dev")} - Start all services`)),console.log(se.default.dim(` ${se.default.cyan(`cd ${s} && bun run start:dev`)} - Start this service only`)),console.log();else throw new Error("Service generation failed")},_a=ie({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:sm,buildContext:async(e,t)=>{let n=(e.name??"my-nest-service").trim();!n.includes("/")&&!n.startsWith(".")&&(n=`${L().services}/${n}`);let r=g(n),o=t.packageManager??(t.yes&&x()),s=t.packageManager==="bun",a=G(),i=t.yes?Fe():[],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:[Ge,Be,He,Ue,dn,_e],actions:[We,Le,ja,pn,Oa,un,ua,mn,gn],onComplete:({projectName:e,packageManager:t,selectedIntegrations:n})=>{m.breakLine().log(se.default.bold.green("NestJS Microservice created successfully!")),on(n),m.breakLine().log(`To start the project, run:
|
|
474
|
+
${se.default.bold(`cd ${e} && ${t} run start:dev`)}`).breakLine().log("Happy coding! \u{1F389}").breakLine()}});var za=require("@listr2/prompt-adapter-enquirer"),D=u(require("chalk"));var Ba=require("node:child_process"),A=require("node:fs"),Ke=require("node:path");var Da=require("node:fs"),Pt=require("node:path");var br=()=>{let e=lt();return Oe([(0,Pt.join)(__dirname,"templates","workspace"),(0,Pt.join)(__dirname,"..","..","..","..","templates","workspace"),(0,Pt.join)(e,"bin","templates","workspace")],"Workspace templates directory not found.")},La=()=>{let e=br(),t=(0,Pt.join)(e,"packages","contracts");if(!(0,Da.existsSync)(t))throw new Error(`Contracts templates directory not found at: ${t}`);return t},vn=(e,t)=>yr(e,t);var Ha=e=>{e.endsWith(".sh")&&(0,A.chmodSync)(e,493)},am=[{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}],Wa={title:"Creating workspace structure",task:async(e,t)=>{if((0,A.existsSync)(e.cwd)){t.title="Workspace directory already exists, skipping...";return}let n=br(),r=e.includeGitHubCI??!0,o=e.packageManager||"bun",s=c=>{try{let d=(0,Ba.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=am.filter(c=>!(c.isGitHubCI&&!r||c.forPackageManager&&c.forPackageManager!==o));for(let c of i){let l=(0,Ke.join)(e.cwd,c.output),p=(0,Ke.dirname)(l);if((0,A.existsSync)(p)||(0,A.mkdirSync)(p,{recursive:!0}),c.isStatic){let d=(0,Ke.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,Ke.join)(n,c.template),k=vn(d,a);(0,A.writeFileSync)(l,k),Ha(l)}}t.title="Workspace structure created"}};var X=require("node:fs"),Tt=require("node:path"),Ga=u(require("chalk"));var im=()=>{let e=(0,Tt.join)(process.cwd(),"package.json");if(!(0,X.existsSync)(e))throw new Error("Root package.json not found. Please run this command from the workspace root.");let n=JSON.parse((0,X.readFileSync)(e,"utf-8")).name;if(!n)throw new Error('package.json must have a "name" field');return n.startsWith("@")?n:`@${n}`},cm=()=>{let e=im(),{relativePath:t,packagePath:n}=C();if((0,X.existsSync)(n))throw new Error(`${t} already exists. Remove it first if you want to regenerate.`);let r=La(),o={scope:e,workspaceName:e.replace("@","").replace("/","-")};(0,X.mkdirSync)(n,{recursive:!0}),(0,X.mkdirSync)((0,Tt.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,Tt.join)(r,a.template),c=(0,Tt.join)(n,a.output),l=vn(i,o);(0,X.writeFileSync)(c,l,"utf-8")}},Ua={title:"Initializing contracts package",task:(e,t)=>{let n=process.cwd();try{process.chdir(e.cwd),cm(),t.title="Contracts package initialized"}catch(r){throw t.title=Ga.default.red(`Contracts package failed: ${r.message}`),r}finally{process.chdir(n)}}};var Ja=u(require("chalk"));var Ka={title:"Registering shell completion",task:(e,t)=>{let n=process.cwd();try{process.chdir(e.cwd),ke(),t.title="Shell completion registered"}catch{t.title=Ja.default.dim("Shell completion skipped")}finally{process.chdir(n)}}};var qa=ie({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(za.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=D.default.yellow("Warning: Creating nested workspace")}catch(n){if(n.message?.includes("cancelled"))throw n;t.title="No existing workspace detected"}}},Ge,Be,ka,va,Ca,He,Ue,_e],actions:[We,Le,Wa,Ua,un,pa,Ka],onComplete:({projectName:e,includeGitHubCI:t})=>{m.breakLine().log(D.default.bold.green("Workspace created successfully!")),m.breakLine().log(D.default.bold("Next steps:")).log(` 1. ${D.default.cyan(`cd ${e}`)}`).log(` 2. ${D.default.cyan("exec $SHELL")} ${D.default.dim("(enable tab completion)")}`),t&&m.breakLine().log(D.default.bold("GitHub Setup:")).log(" Configure these secrets in your GitHub repository:").log(` \u2022 ${D.default.yellow("PULUMI_ACCESS_TOKEN")} - Pulumi Cloud access token`).log(` \u2022 ${D.default.yellow("DIGITALOCEAN_TOKEN")} - DigitalOcean API token`).log(` \u2022 ${D.default.yellow("NPM_TOKEN")} - (optional) NPM token for private packages`),m.breakLine().log(D.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 $t=[{name:"Hono Microservice",value:"hono-micro",command:Ea,supportsAi:!0},{name:"Nest Microservice",value:"nest-micro",command:_a,supportsAi:!0},{name:"Workspace (Infrastructure)",value:"workspace",command:qa,supportsAi:!1}],Va=()=>{let e=ie({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(me.ListrEnquirerPromptAdapter).run({type:"select",message:"Select Project type",choices:$t});t.projectType=$t.find(o=>o.name===r)?.value||"",n.title=`Using ${ae.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(`
|
|
475
|
+
`);throw new Error(r)}}},{enabled:t=>t.projectType==="workspace",task:async(t,n)=>{try{let r=y();if(!await n.prompt(me.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=ae.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(me.ListrEnquirerPromptAdapter).run({type:"input",message:s,initial:o});t.servicePath=a.trim(),n.title=`Path: ${ae.default.dim(a)}`}},{enabled:t=>!!$t.find(r=>r.value===t.projectType)?.supportsAi&&Me().valid,task:async(t,n)=>{let r=await n.prompt(me.ListrEnquirerPromptAdapter).run({type:"toggle",message:"Use AI to generate service code?",enabled:"Yes",disabled:"No",initial:!1});t.useAi=r,n.title=r?ae.default.cyan("\u{1F916} AI-powered generation"):"Standard scaffolding"}},{enabled:t=>t.useAi,task:async(t,n)=>{let r=await n.prompt(me.ListrEnquirerPromptAdapter).run({type:"input",message:"Describe what this service should do:"});t.aiDescription=r,n.title=`Description: ${ae.default.dim(r.slice(0,50))}${r.length>50?"...":""}`}},{enabled:t=>{if(!t.servicePath)return!1;let n=g(t.servicePath);return!It(n)},task:async(t,n)=>{if(!await n.prompt(me.ListrEnquirerPromptAdapter).run({type:"toggle",message:ae.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=ae.default.yellow("Will overwrite existing directory")}},{title:"Confirm creation",enabled:t=>t.projectType!=="workspace",task:async(t,n)=>{if(!await n.prompt(me.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=>{$t.find(s=>s.value===t.projectType)||e.error(ae.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 aa(n,t,r,o)}});for(let t of $t)e.addCommand(t.command);return e};var Qa=require("commander");var Ce=u(require("chalk"));var Sr=e=>new Promise(t=>setTimeout(t,e)),ze=e=>process.stdout.write(`${e}
|
|
476
|
+
`),lm=()=>{process.stdout.write("\x1B[2J\x1B[3J\x1B[H"),process.stdout.isTTY&&process.stdout.write("\x1Bc")},Za=()=>({turboProcess:null,isRestarting:!1,isShuttingDown:!1}),Ya=async(e,t)=>{let n=ao(".env.local",t);n.length>0&&(await po(n),await Sr(50)),ze(Ce.default.cyan("\u{1F525} Starting services...")),ze(Ce.default.dim(` Command: turbo run ${bn} --continue`)),e.isShuttingDown=!1,e.isRestarting=!1,e.turboProcess=lo("turbo",["run",bn,"--continue","--no-daemon"],{cwd:t,envFile:".env.local",onExit:r=>{e.isRestarting||e.isShuttingDown||(r===1&&process.exit(0),r!==null&&r!==0&&(ze(`
|
|
477
|
+
${Ce.default.yellow("\u26A0\uFE0F A service has crashed")} (exit code: ${r})`),ze(Ce.default.dim("Check the logs above to see which service failed.")),ze(Ce.default.dim("Fix the error and save the file to restart automatically.")),ze(Ce.default.dim("Press Ctrl+C to exit dev mode."))))}})},Xa=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 Sr(200);try{process.kill(-n,"SIGKILL")}catch{}await Sr(30)}catch{}e.turboProcess=null,lm()}};var ei=new Qa.Command("dev").description("Start development mode with auto-reload").action(async()=>{let e=y(),t=Za(),n=i=>rt("generate-env",{cwd:i}),r=()=>H({cwd:e,quiet:!0}),o=async()=>{await r(),await n(e),await Bs()&&await Ws(e),await Ya(t,e)},s=async()=>{t.isRestarting||t.isShuttingDown||(t.isRestarting=!0,console.log(`
|
|
478
|
+
\u{1F504} Change detected, restarting...
|
|
479
|
+
`),await Xa(t),await o(),t.isRestarting=!1)},a=()=>{if(t.isShuttingDown)return;t.isShuttingDown=!0,console.log(`
|
|
480
|
+
\u{1F6D1} Shutting down...`);let i=t.turboProcess?.pid;if(i)try{process.kill(-i,"SIGKILL")}catch{try{t.turboProcess?.kill("SIGKILL")}catch{}}Gs().finally(()=>{process.exit(0)}),setTimeout(()=>{process.exit(0)},2e3)};process.removeAllListeners("SIGINT"),process.removeAllListeners("SIGTERM"),process.on("SIGINT",a),process.on("SIGTERM",a),await o(),Fo(e,s),console.log(`
|
|
481
|
+
\u{1F440} Watching for changes... (Ctrl+C to stop)
|
|
482
|
+
`)});var ki=require("commander");var ti=require("node:fs"),ni=require("node:path"),Q=u(require("chalk")),ri=require("commander");var pm=e=>{if(e)try{return JSON.parse(e)}catch{return}},mm=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},dm=(e,t)=>{if(!t)return;let n=t.startsWith("/")?t:(0,ni.resolve)(e,t);return(0,ti.existsSync)(n)?n:void 0},um=async(e,t)=>{let n=[],r=[],o=[];if(Dn(e)&&!t.force)r.push("Contract (already exists)");else{let a=Ln(e,t.schema);n.push(`Contract: ${a}`)}qn(e)&&n.push("Export: packages/contracts/src/index.ts");let s=await Wt(e);if(s&&n.push(`Mock: ${s}`),t.servicePath){let a=Gn(e,t.servicePath);a?n.push(`Handler: ${a}`):r.push("Handler (already exists)");let i=Wn(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}},gm=(e,t,n=[])=>{if(e.length>0){console.log(Q.default.green(`\u2713 Created:
|
|
483
|
+
`));for(let r of e)console.log(Q.default.dim(` ${r}`))}if(t.length>0){console.log(Q.default.yellow(`
|
|
253
484
|
\u2139 Skipped:
|
|
254
|
-
`));for(let r of t)console.log(
|
|
485
|
+
`));for(let r of t)console.log(Q.default.dim(` ${r}`))}if(n.length>0){console.log(Q.default.yellow(`
|
|
255
486
|
\u26A0 Warning:
|
|
256
|
-
`));for(let r of n)console.log(
|
|
487
|
+
`));for(let r of n)console.log(Q.default.dim(` ${r}`))}},Pr=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=mm(t.fields)||pm(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=dm(n,t.service);if(t.service&&!o){m.error(`Service directory not found: ${t.service}`);return}console.log(Q.default.cyan(`
|
|
257
488
|
\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
|
|
489
|
+
`));let{created:s,skipped:a,warnings:i}=await um(e,{schema:r,servicePath:o,force:t.force});gm(s,a,i),console.log(),s.length>0&&ke({force:!0}),t.service||(console.log(Q.default.yellow(`\u{1F4A1} Tip: Use --service to also create an event handler:
|
|
490
|
+
`)),console.log(Q.default.dim(` pf event add ${e} --service services/my-service
|
|
491
|
+
`)))},kk=new ri.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(Pr);var ai=require("commander");var oi=require("fs-extra"),si=require("globby"),de=require("zod");var fm=["**/node_modules/**","**/.nats-data/**","**/dist/**","**/build/**","**/.git/**","**/coverage/**"],hm=de.z.record(de.z.string()),ym=de.z.object({description:de.z.string().optional(),eventName:de.z.string(),faker:hm.optional(),data:de.z.record(de.z.any())}),qe=(e=process.cwd())=>(0,si.globbySync)("**/*.mock.json",{cwd:e,absolute:!0,gitignore:!0,ignore:fm}).map(n=>{try{let r=(0,oi.readJSONSync)(n,{encoding:"utf8"}),o=ym.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 Tr=null,ii=async()=>{if(!Tr){let{faker:e}=await import("@faker-js/faker");Tr=e}return Tr},$r=async(e,t)=>{let n=await ii(),o=qe().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 km(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.")},Sk=new ai.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($r),km=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([n,r])=>{let o=await vm(r);At(t,n,o)})),t},vm=async e=>{let t=await ii();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 gi=require("commander");var Er=require("node:fs"),ci=require("node:path"),Ar=require("globby");var Cm=["**/node_modules/**","**/.nats-data/**","**/dist/**","**/build/**","**/.git/**","**/coverage/**"],xm=e=>{let t=e.split("/"),n=t.indexOf("services");return n!==-1&&n+1<t.length?t[n+1]:"unknown"},wm=(e,t)=>{try{let{eventsPath:n}=C(t),o=(0,Ar.globbySync)("**/*.ts",{cwd:n,absolute:!0}).map(a=>({file:a,content:(0,Er.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}},bm=e=>e.replace(/Contract$/,"").replace(/([A-Z])/g,(t,n,r)=>(r>0?".":"")+n.toLowerCase()),Sm=(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 wm(s,t)||bm(s)},Pm=(e,t)=>{try{let n=(0,Er.readFileSync)(e,"utf-8"),r=Sm(n,t);return r?{serviceName:xm(e),handlerPath:(0,ci.relative)(t,e),eventType:r}:null}catch{return null}},li=(e=process.cwd())=>(0,Ar.globbySync)("services/**/src/events/*.handler.ts",{cwd:e,absolute:!0,gitignore:!0,ignore:Cm}).map(n=>Pm(n,e)).filter(n=>n!==null),pi=e=>e.reduce((t,n)=>{let r=t.get(n.eventType)||[];return t.set(n.eventType,[...r,n]),t},new Map);var di=u(require("cli-table3"));var mi=(e,t)=>{let n=t.get(e)||[],r=[...new Set(n.map(o=>o.serviceName))];return r.length>0?r.join(", "):"-"};var ui=(e,t)=>{let n=new di.default({head:["name","description","consumers"],style:{head:["dim","bold"],compact:!0}});for(let{eventName:r,schema:o}of e)n.push([r,o.description||"-",mi(r,t)]);return n.toString()};var Tm=e=>{for(let t of e)console.log(t)},$m=()=>{let e=pr();Tm(e)},Em=()=>{let e=qe();if(e.length===0){m.error("No event schemas found.");return}let t=li(),n=pi(t),r=ui(e,n);console.log(r)},Ir=e=>{if(!to()){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)}e.namesOnly?$m():Em()},_k=new gi.Command("event:list").description("List all available event mocks").option("--names-only","Output only event names (for completion)").action(Ir);var fi=require("node:path"),hi=require("commander");var Rm={},Nr=null,Rr=null,yi=async()=>{if(!Nr){let{faker:e}=await import("@faker-js/faker");Nr=e}return Nr},Am=async()=>{if(!Rr)try{let{createJiti:e}=await import("jiti"),t=e(Rm.url),n=y(),r=C(n),o=(0,fi.join)(r.packagePath,"node_modules","@crossdelta","cloudevents");Rr=(await t.import(o)).publish}catch{throw new Error(`@crossdelta/cloudevents is required for event:publish.
|
|
492
|
+
Install it in your contracts package with: cd packages/contracts && bun add @crossdelta/cloudevents`)}return Rr},Mr=async(e,t)=>{let n=await yi(),o=qe().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 Im(s):s.data;if(t.print){console.log(`
|
|
493
|
+
\u{1F4E6} Event Type:`,s.eventName),console.log("\u{1F4C4} Payload:"),console.dir(a,{colors:!0,depth:null});return}try{let i=await Am();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)}},Wk=new hi.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(Mr),Im=async e=>{let t=structuredClone(e.data);return e.faker&&await Promise.all(Object.entries(e.faker).map(async([n,r])=>{let o=await Nm(r);At(t,n,o)})),t},Nm=async e=>{let t=await yi();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 Ve=new ki.Command("event").description("Event management commands");Ve.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(Pr);Ve.command("list").description("List all available event mocks").option("--names-only","Output only event names (for completion)").action(Ir);Ve.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(Mr);Ve.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($r);Ve.action(()=>{let e=pe({title:"\u{1F4EC} Event Management",commands:[{name:"add",description:"Add event contract, handler, and mock"},{name:"list",description:"List all available event mocks"},{name:"publish",description:"Publish to NATS JetStream"},{name:"http",description:"Send via HTTP Pub/Sub endpoint"}],footer:'Run "pf event <command> --help" for more information'});console.log(e)});var vi=Ve;var Or=u(require("chalk")),Si=require("commander");var Ze=require("node:fs"),Fr=u(require("node:path")),Cn=u(require("chalk")),Ci=require("commander"),xi=u(require("os"));var{name:Mm,publishConfig:jm}=N,Fm=jm?.registry,Om=Mm?.split("/")[0],Xk=new Ci.Command("token:set").description(Cn.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)",Om).option("--registry <registry>","Registry URL",Fm).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)=>wi(e,t.scope||"",t.registry||"",t.local,t.force)).addHelpText("after",()=>`${Cn.default.cyan(`
|
|
263
494
|
Example:`)}
|
|
264
|
-
${
|
|
265
|
-
`),
|
|
266
|
-
//${r}/:_authToken=${e}`:`//${r}/:_authToken=${e}`},
|
|
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),
|
|
495
|
+
${Cn.default.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
496
|
+
`),_m=e=>e?Fr.default.join(process.cwd(),".npmrc"):Fr.default.join(xi.default.homedir(),".npmrc"),Dm=(e,t,n)=>{let r=new URL(n).host;return t?`${t}:registry=https://${r}
|
|
497
|
+
//${r}/:_authToken=${e}`:`//${r}/:_authToken=${e}`},Lm=e=>(0,Ze.existsSync)(e)?(0,Ze.readFileSync)(e,"utf8"):"",jr=(e,t)=>(0,Ze.writeFileSync)(e,t),wi=(e,t,n,r=!1,o=!1)=>{let s=_m(r),a=Dm(e,t,n),i=new URL(n).host,c=Lm(s),l=new RegExp(`//${i}/:_authToken=\\S+`);if(!c){jr(s,`${a}
|
|
498
|
+
`),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),jr(s,c),m.success(`Overwrote existing token for ${i} in ${s}`);return}c+=`
|
|
268
499
|
${a}
|
|
269
|
-
`,
|
|
500
|
+
`,jr(s,c),m.success(`Appended token for ${i} to ${s}`)},bi=(e,t)=>wi(e,t.scope||"",t.registry||"",t.local,t.force);var{name:Hm,publishConfig:Bm}=N,Wm=Bm?.registry,Gm=Hm?.split("/")[0],_r=new Si.Command("token").description("Token management commands");_r.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)",Gm).option("--registry <registry>","Registry URL",Wm).option("--local","Write token to a local .npmrc in the current directory",!1).option("--force","Force overwrite existing token if already present",!1).action(bi).addHelpText("after",()=>`${Or.default.cyan(`
|
|
270
501
|
Example:`)}
|
|
271
|
-
${
|
|
272
|
-
`);var
|
|
502
|
+
${Or.default.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
503
|
+
`);_r.action(()=>{let e=pe({title:"\u{1F511} Token Management",commands:[{name:"set",description:"Set a registry auth token in a .npmrc file"}],footer:'Run "pf token <command> --help" for more information'});console.log(e)});var Pi=_r;var xn=u(require("chalk")),Ai=require("commander");var sv={AI_GENERATION:!0,DEBUG:process.env.PF_DEBUG==="true"};var ee=require("@inquirer/prompts"),w=u(require("chalk"));var Um=[/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],Jm=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)}},Km=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(),zm=async(e,t)=>{let n=st(e),r=await Jm(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=Um.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:Km(i.id),value:i.id}));if(a.length===0)throw new Error(`No chat models found from ${n.name} API`);return a};async function Ti(e,t){if(!t)throw new Error("API key is required to fetch available models");return{models:await zm(e,t),fromApi:!0}}function qm(){if(!at())return null;try{let e=_t();return console.log(w.default.dim(`Found existing configuration at ${he}
|
|
273
504
|
`)),e}catch{return console.log(w.default.yellow(`Found corrupted configuration, starting fresh.
|
|
274
|
-
`)),null}}async function
|
|
505
|
+
`)),null}}async function Vm(e,t){return console.log(w.default.dim(`
|
|
275
506
|
\u{1F4CB} Get your ${e} API key here:`)),console.log(w.default.cyan(` ${t}
|
|
276
|
-
`)),(0,
|
|
507
|
+
`)),(0,ee.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 Zm(e,t,n){let r=await(0,ee.select)({message:"Select model:",choices:e,default:t?.provider===n?t.model:void 0});return await(0,ee.confirm)({message:"Enter a custom model ID instead?",default:!1})?(0,ee.input)({message:"Enter custom model ID:",default:r,validate:s=>s.trim()?!0:"Model ID cannot be empty"}):r}function $i(e){return e.length<=12?"****":`${e.slice(0,4)}...${e.slice(-4)}`}function Ym(e,t){console.log(w.default.green.bold(`
|
|
277
508
|
\u2705 AI configuration saved successfully!
|
|
278
|
-
`)),console.log(w.default.dim(`Configuration file: ${
|
|
509
|
+
`)),console.log(w.default.dim(`Configuration file: ${he}`)),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: ${$i(t)}
|
|
279
510
|
`)),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
|
|
511
|
+
`))}async function Xm(e){let t=await Ot(e);if(t)return t;let n=st(e);return process.env[n.defaultApiKeyEnvVar]??null}async function Ei(){console.log(w.default.cyan.bold(`
|
|
281
512
|
\u{1F916} AI Configuration Setup
|
|
282
|
-
`));let e=
|
|
283
|
-
\u2713 Found existing API key: ${
|
|
284
|
-
Fetching available models...`));let s;try{s=(await
|
|
513
|
+
`));let e=qm();try{let t=await(0,ee.select)({message:"Select AI provider:",choices:Eo(),default:e?.provider??Fn.provider}),n=st(t),r,o=await Xm(t);o&&(console.log(w.default.green(`
|
|
514
|
+
\u2713 Found existing API key: ${$i(o)}`)),await(0,ee.confirm)({message:"Use this existing API key?",default:!0})&&(r=o)),r||(r=await Vm(n.name,n.apiKeyUrl)),console.log(w.default.dim(`
|
|
515
|
+
Fetching available models...`));let s;try{s=(await Ti(t,r)).models,console.log(w.default.green(`\u2713 Loaded ${s.length} models from ${n.name} API
|
|
285
516
|
`))}catch(c){console.error(w.default.red(`
|
|
286
517
|
\u274C Failed to fetch models: ${c.message}`)),console.log(w.default.yellow(`
|
|
287
518
|
Please check your API key and try again.
|
|
288
|
-
`)),process.exit(1)}let a=await
|
|
519
|
+
`)),process.exit(1)}let a=await Zm(s,e,t),i={provider:t,model:a.trim()};No(i),await Ro(t,r),Ym(i,r)}catch(t){throw t.name==="ExitPromptError"&&(console.log(w.default.yellow(`
|
|
289
520
|
Setup cancelled.
|
|
290
|
-
`)),process.exit(0)),t}}var
|
|
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",`
|
|
521
|
+
`)),process.exit(0)),t}}var Dr=(e,t=!1)=>{try{return gr(e,t),ke({verbose:t}),!0}catch{return!1}};var wn=e=>{let t=new Ai.Command("setup").description("Configure platform settings");return t.command("completion").description("Install shell autocompletion").option("--verbose","Enable verbose logging").addHelpText("after",`
|
|
400
522
|
Examples:
|
|
401
|
-
$ pf setup
|
|
402
|
-
$ pf setup --
|
|
403
|
-
`).action(
|
|
404
|
-
\u2714 Shell autocompletion installed!`)),console.log(
|
|
405
|
-
`))
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
\
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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),`
|
|
414
|
-
|
|
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);
|
|
523
|
+
$ pf setup completion
|
|
524
|
+
$ pf setup completion --verbose
|
|
525
|
+
`).action(n=>{Dr(e,n.verbose),n.verbose||(console.log(xn.default.green(`
|
|
526
|
+
\u2714 Shell autocompletion installed!`)),console.log(xn.default.dim(` Restart your shell:
|
|
527
|
+
`)),console.log(xn.default.cyan(` exec $SHELL
|
|
528
|
+
`)))}),t.command("ai").description("Configure AI provider and API key for code generation").addHelpText("after",`
|
|
529
|
+
Example:
|
|
530
|
+
$ pf setup ai
|
|
531
|
+
`).action(async()=>{await Ei()}),t.action(()=>{let n=pe({title:"\u2699\uFE0F Platform Setup",commands:[{name:"completion",description:"Install shell autocompletion"},{name:"ai",description:"Configure AI provider"}],footer:'Run "pf setup <command> --help" for more information'});console.log(n)}),t},ed=wn("pf");tn();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(xe.default.red(`
|
|
532
|
+
\u2716 An unexpected error occurred:`)),console.error(e),process.exit(1)});var Et=new Oi.Command,Ii=Object.keys(N.bin||{}),[Hr="pf",Lr]=Ii.length>0?Ii:["pf"],{description:Ni,version:td,repository:Ri,homepage:nd}=N,Mi=Ni?.split(/ —|,|\./)[0]||Ni||"Platform CLI",Di=Ri?.url?`https://${Ri.url.replace(/^(git\+|git@)/,"").replace(/\.git$/,"").replace(":","/")}`:null,ji=Di||nd,rd=Di?"GitHub":"README",od=ji?[xe.default.bold(Mi),`
|
|
533
|
+
|
|
534
|
+
`,xe.default.cyan("See more at: "),xe.default.bold((0,_i.default)(rd,String(ji)))].join(""):xe.default.bold(Mi),Li=[wn(Hr),Va(),ei,vi,Pi,wo];Et.name(Hr).description(od).version(td||"0.0.1").helpCommand(!1).configureHelp({subcommandTerm:e=>xe.default.cyan(e.name())}).addHelpText("after",As);Lr&&Lr!==Hr&&Et.alias(Lr);Li.forEach(e=>{Et.addCommand(e)});Et.command("__workspace-hash",{hidden:!0}).action(()=>{let e=process.cwd(),t=Math.abs(e.split("").reduce((n,r)=>(n<<5)-n+r.charCodeAt(0)|0,0));console.log(t)});Is(Et,Fi.argv,Li);
|