@crossdelta/platform-sdk 0.25.6 → 0.26.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 +25 -0
- package/README.md +19 -46
- package/bin/cli.mjs +101 -237
- package/bin/docs/generators/README.md +4 -32
- package/bin/templates/workspace/.claude/rules/cloudevents.md +1 -2
- package/bin/templates/workspace/CLAUDE.md +5 -1
- package/bin/templates/workspace/package.json.hbs +9 -0
- package/bin/templates/workspace/packages/contracts/README.md.hbs +1 -1
- package/package.json +1 -43
- package/schemas/service-types.schema.json +0 -33
package/bin/cli.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
Hint: ${this.hint}`),t.join("")}},
|
|
4
|
-
Hint: ${e.hint}`)),n&&process.exit(
|
|
5
|
-
`)}function
|
|
2
|
+
var $s=Object.defineProperty;var xt=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var C=(e,t)=>()=>(e&&(t=e(e=0)),t);var Rs=(e,t)=>{for(var r in t)$s(e,r,{get:t[r],enumerable:!0})};var k,le=C(()=>{"use strict";k={SUCCESS:0,GENERAL_ERROR:1,USAGE_ERROR:2,WORKSPACE_ERROR:64,VALIDATION_ERROR:65,CONFIG_ERROR:66,IO_ERROR:74,PERMISSION_ERROR:77,CANCELLED:130}});var W,Re,wt=C(()=>{"use strict";le();W=class extends Error{exitCode;category;hint;cause;constructor(t,r=k.GENERAL_ERROR,n={}){super(t),this.name="CliError",this.exitCode=r,this.category=n.category??"process",this.hint=n.hint,this.cause=n.cause}toUserMessage(){let t=[this.message];return this.hint&&t.push(`
|
|
3
|
+
Hint: ${this.hint}`),t.join("")}},Re=class extends W{constructor(t="Operation cancelled",r={}){super(t,k.CANCELLED,{...r,category:"user"}),this.name="CancelledError"}}});import H from"chalk";var Ie,Rr,Ir,Is,Ns,Ne,As,Os,O,Nr=C(()=>{"use strict";wt();le();Ie=e=>e instanceof Error,Rr=["ExitPromptError"],Ir=["Cancelled prompt","User force closed"],Is=["ERR_USE_AFTER_CLOSE"],Ns=e=>Rr.some(t=>e.name?.includes(t))||Ir.some(t=>e.message?.includes(t)),Ne=e=>{if(e instanceof Re)return!0;if(!(e instanceof Error))return!1;if(Rr.some(r=>e.name?.includes(r))||Ir.some(r=>e.message?.includes(r)))return!0;let t=e.code;return t&&Is.includes(t)?Ns(e):!1},As=e=>{if(e instanceof W){let r=e.toUserMessage();return H.red(`\u2716 ${r||"Unexpected error (re-run with DEBUG=true for details)"}`)}if(e instanceof Error){let r=e.message?.trim();return r?H.red(`\u2716 ${r}`):H.red("\u2716 Unexpected error (re-run with DEBUG=true for details)")}let t=String(e);return!t||t==="undefined"||t==="null"?H.red("\u2716 Unexpected error (re-run with DEBUG=true for details)"):H.red(`\u2716 ${t}`)},Os=e=>e instanceof W?e.exitCode:Ne(e)?k.CANCELLED:k.GENERAL_ERROR,O=(e,t={})=>{let{debug:r=process.env.DEBUG==="true",exit:n=!0,logger:o=console.error}=t;if(Ne(e)){n&&process.exit(k.CANCELLED);return}o(As(e)),r&&e instanceof Error&&e.stack&&o(H.dim(e.stack)),e instanceof W&&e.hint&&o(H.dim(`
|
|
4
|
+
Hint: ${e.hint}`)),n&&process.exit(Os(e))}});var z=C(()=>{"use strict";wt();Nr();le()});var fm,Ar,Pt,Ae=C(()=>{"use strict";fm=process.env.npm_package_version||"0.0.0",Ar=["bun.lock","bun.lockb","package-lock.json","yarn.lock","pnpm-lock.yaml"],Pt="start:dev"});import Oe from"chalk";function bt(e,t){if(e.length===0)return"No entries to display.";let r=t?.title||"Benchmark Results",n=t?.footer||"",o=t?.maxBarWidth||50,s=t?.unit||"",i=Math.max(...e.map(c=>c.value)),a=[];a.push(""),a.push(r),a.push("");for(let c of e){let p=_s(c.barColor??t?.barColor),l=Ds(c,i,o,p,s,t?.labelColor);a.push(l)}return n&&(a.push(""),a.push(n)),a.join(`
|
|
5
|
+
`)}function _s(e){return e?Oe[e]("\u2587"):"\u2587"}function Ds(e,t,r,n,o,s){let i=Math.round(e.value/t*r),a=e.barColor?Oe[e.barColor](n.repeat(i)):n.repeat(i),c=e.color??s;return`${Oe.bold(c?Oe[c](e.label.padEnd(12)):e.label.padEnd(12))} ${a} ${e.value.toLocaleString()}${o?` ${o}`:""}`}var Or=C(()=>{"use strict"});import{existsSync as Tt,unlinkSync as Ls,writeFileSync as Ms}from"fs";import{join as Et}from"path";import St from"chokidar";var js,_e,Fs,_r,$t,Ws,Dr,Rt=C(()=>{"use strict";h();v();js=".pf-generating",_e=e=>Et(e,js),Fs=e=>Tt(_e(e)),_r=e=>{Ms(_e(e),"","utf-8")},$t=e=>{let t=_e(e);Tt(t)&&Ls(t)},Ws=e=>{let r=$(e)?.pf?.paths;return r?Object.values(r).filter(n=>typeof n=="object"&&n!==null&&n.watch===!0&&typeof n.path=="string"):[{path:"services"},{path:"apps"}]},Dr=(e,t)=>{$t(e);let r=Ws(e),n=_e(e),s=J(async()=>{Fs(e)||await t()},300),i=[];i.push(St.watch(n,{ignoreInitial:!0}).on("unlink",()=>t()));for(let a of r){let c=Et(e,a.path);if(!Tt(c))continue;let p=a.ignorePatterns?.map(l=>Et(c,l));i.push(St.watch(c,{ignoreInitial:!0,depth:0,ignored:p,usePolling:!0,interval:1e3}).on("addDir",l=>l!==c&&s()).on("unlinkDir",l=>l!==c&&s())),i.push(St.watch(`${c}/*/package.json`,{ignoreInitial:!0,ignored:p}).on("add",s).on("change",s))}return async()=>{await Promise.all(i.map(a=>a.close()))}}});import Lr from"chalk";import{Command as Hs}from"commander";import{Listr as Mr}from"listr2";var L,Gs,jr,Fr=C(()=>{"use strict";z();Rt();v();L=e=>{let t=new Hs(e.name).description(e.description).showHelpAfterError();e.arguments?.forEach(([o,s])=>{t.argument(o,s)}),e.options?.forEach(([o,s])=>{t.option(o,s)}),e.exampleUsage&&t.addHelpText("after",()=>`${Lr.cyan.bold(`
|
|
6
6
|
Example:`)}
|
|
7
|
-
${
|
|
8
|
-
`),e.additionalInfo&&t.addHelpText("after",()=>(typeof e.additionalInfo=="function"?e.additionalInfo():e.additionalInfo)??"");let r=async o=>{e.prompts?.length&&await new
|
|
9
|
-
`,"utf-8"),
|
|
7
|
+
${Lr.bold(e.exampleUsage)}
|
|
8
|
+
`),e.additionalInfo&&t.addHelpText("after",()=>(typeof e.additionalInfo=="function"?e.additionalInfo():e.additionalInfo)??"");let r=async o=>{e.prompts?.length&&await new Mr(jr(e.prompts,o),{rendererOptions:{lazy:!0,showErrorMessage:!1}}).run(o),await new Mr(jr(e.actions,o),{rendererOptions:{lazy:!1,showErrorMessage:!1}}).run(o),await e.onComplete?.(o)},n=()=>{try{let o=d();return _r(o),o}catch{return null}};return t.action(async(...o)=>{let s=null;try{let i=o.at(-1),a=i.args,c=i.opts(),p=Gs(e.arguments??[],a),l=await e.buildContext(p,c);s=n(),await r(l)}catch(i){O(i,{exit:!1})}finally{s&&$t(s)}}),t},Gs=(e,t)=>{let r=e.map(([n],o)=>[n.replace(/[<>[\]]/g,""),t[o]]);return Object.fromEntries(r)},jr=(e,t)=>e.map(r=>typeof r=="function"?r(t):r)});var J,Wr=C(()=>{"use strict";J=(e,t)=>{let r=null;return(...n)=>(r&&clearTimeout(r),new Promise(o=>{r=setTimeout(async()=>{r=null,await e(...n),o()},t)}))}});var Hr=C(()=>{"use strict"});import{execaSync as Bs}from"execa";function me(e){try{return Bs(e,["--version"]),!0}catch{return!1}}var It=C(()=>{"use strict"});var Gr=C(()=>{"use strict";It()});import{readdirSync as Us}from"fs";import{dirname as Br,isAbsolute as Hm,join as Vs,normalize as Gm,resolve as Bm,sep as Um}from"path";import{fileURLToPath as zs}from"url";import{packageUpSync as Js}from"package-up";import{rimraf as Ks}from"rimraf";function Ur(){let e=Js({cwd:Br(qs())});if(!e)throw new Error("Could not find package.json");return Br(e)}var qs,_,De,Vr,zr=C(()=>{"use strict";z();v();qs=()=>typeof import.meta?.url=="string"?zs(import.meta.url):process.cwd(),_=e=>{let t=Nt()?d():process.cwd();return Vs(t,e)},De=e=>{try{return Us(e).length===0}catch{return!0}};Vr=e=>Ks(e)});import ue from"chalk";var Jr,Ys,Zs,Le,m,Kr=C(()=>{"use strict";Jr={debug:0,info:1,warn:2,error:3,silent:4},Ys=e=>e==="debug"||e==="info"||e==="warn"||e==="error"||e==="silent",Zs=()=>{let e=process.env.LOG_LEVEL;return Ys(e)?e:process.env.DEBUG==="true"||process.env.VERBOSE==="true"?"debug":"info"},Le=e=>{let t=Zs();return Jr[e]>=Jr[t]},m={logs:[],breakLine:()=>(console.log(),m),success:(e,...t)=>(console.log(ue.green(`\u2714 ${e}`),...t),m),info:(e,...t)=>(Le("info")&&console.log(ue.cyan(`\u{1F6C8} ${e}`),...t),m),warn:(e,...t)=>(Le("warn")&&console.warn(ue.yellow(`\u26A0\uFE0E ${e}`),...t),m),error:(e,...t)=>(Le("error")&&console.error(ue.red(`\u2716 ${e}`),...t),m),debug:(e,...t)=>(Le("debug")&&console.log(ue.dim(`[debug] ${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})}});var qr=C(()=>{"use strict"});import Xs from"chalk";async function R(e,t){let r=Date.now(),n=e.title,o=()=>Math.floor((Date.now()-r)/1e3),s=setInterval(()=>{o()>1&&(e.title=`${n} (${o()}s)`)},1e3);try{return await t(o)}finally{clearInterval(s)}}async function Me(e,t,r){for(let n=0;n<t.length;n++){let o=t[n];e.output=Xs.dim(`[${n+1}/${t.length}] ${o.title}`),await o.fn(r??{},e)}}var Yr=C(()=>{"use strict"});var h=C(()=>{"use strict";Or();Fr();Wr();Hr();Gr();zr();Kr();qr();It();Yr()});var rn={};Rs(rn,{discoverAvailableServices:()=>He,findWorkspaceRoot:()=>d,getContractsConfig:()=>x,getPackageJsonField:()=>mi,getPfConfig:()=>fe,getPkgJson:()=>tn,getRootPackageScope:()=>en,getWorkspacePackageJson:()=>$,getWorkspacePathsConfig:()=>I,isInWorkspace:()=>Nt,pkgJson:()=>E,readPackageConfig:()=>he,updatePackageJsonField:()=>We});import{existsSync as ge,readdirSync as Qs,readFileSync as Zr,writeFileSync as ei}from"fs";import{join as S,resolve as ti}from"path";var Ot,ri,ni,oi,de,Fe,je,si,ii,Xr,ai,ci,Qr,Nt,d,$,I,fe,x,en,pi,li,mi,We,he,At,tn,E,He,v=C(()=>{"use strict";Ae();h();Ot=e=>JSON.parse(Zr(e,"utf-8")),ri=Ot,ni=(e,t,r)=>ei(e,`${JSON.stringify(t,null,2)}
|
|
9
|
+
`,"utf-8"),oi=["@crossdelta/cloudevents"],de={services:"services",apps:"apps",packages:"packages",contracts:"packages/contracts"},Fe=e=>{if(!ge(e))return null;try{return JSON.parse(Zr(e,"utf-8"))}catch{return null}},je=(e,t)=>typeof e=="string"?e:typeof e=="object"&&e!==null&&"path"in e?e.path:t,si=e=>e.split("/").pop()||"workspace",ii=e=>{let t=e.slice(0,e.lastIndexOf("/"));return t===e?null:t},Xr=e=>e.split("."),ai=(e,t)=>{if(!e.workspaces)return!1;if(e.pf||ge(S(t,"turbo.json")))return!0;let r=Ar.some(o=>ge(S(t,o))),n=ge(S(t,"infra"));return r&&n},ci=e=>{let t=Fe(S(e,"package.json"));return t?ai(t,e):!1},Qr=e=>{let t=e;for(;t;){if(ci(t))return t;t=ii(t)}return null},Nt=()=>Qr(process.cwd())!==null,d=()=>{let e=Qr(process.cwd());if(!e)throw new Error(`
|
|
10
10
|
\x1B[31m\u2716\x1B[0m Not in a workspace directory
|
|
11
11
|
|
|
12
12
|
Current directory: ${process.cwd()}
|
|
@@ -16,171 +16,27 @@ This command must be run from within a workspace created with \x1B[36mpf new wor
|
|
|
16
16
|
To create a new workspace, run:
|
|
17
17
|
|
|
18
18
|
\x1B[36mpf new workspace my-platform\x1B[0m
|
|
19
|
-
`);return e}
|
|
20
|
-
`,encoding:"utf-8"})},
|
|
21
|
-
`).filter(Boolean);for(let s of o)try{process.kill(Number.parseInt(s,10),"SIGKILL")}catch{}}catch{}}
|
|
19
|
+
`);return e},$=e=>{let t=e??d();return Fe(S(t,"package.json"))},I=e=>{let t=$(e);if(!t?.pf?.paths)return de;let{paths:r}=t.pf;return{services:je(r.services,de.services),apps:je(r.apps,de.apps),packages:je(r.packages,de.packages),contracts:je(r.contracts,de.contracts)}},fe=e=>{let t=$(e);return{plugins:t?.pf?.plugins??oi,dev:{filter:t?.pf?.dev?.filter??[]}}},x=e=>{let t=e??d(),r=I(t),n=S(t,r.contracts),s=Fe(S(n,"package.json"))?.name??`${en()}/contracts`;return{packagePath:n,eventsPath:S(n,"src","events"),indexPath:S(n,"src","index.ts"),relativePath:r.contracts,packageName:s}},en=()=>{let e=d(),t=Fe(S(e,"package.json")),r=`@${si(e)}`;return t?.name?t.name.startsWith("@")?t.name.split("/")[0]:`@${t.name}`:r},pi=(e,t)=>{let r=Xr(t),n=e;for(let o of r){if(n===null||typeof n!="object"||!(o in n))return;n=n[o]}return n},li=(e,t,r)=>{let n=Xr(t),o=n[n.length-1],s=e;for(let i of n.slice(0,-1))(!(i in s)||typeof s[i]!="object"||s[i]===null)&&(s[i]={}),s=s[i];s[o]=r},mi=(e,t=process.cwd())=>{let r=Ot(S(t,"package.json"));return pi(r,e)},We=(e,t,r=process.cwd())=>{let n=S(r,"package.json"),o=Ot(n);li(o,e,t),ni(n,o,{spaces:2,EOL:`
|
|
20
|
+
`,encoding:"utf-8"})},he=e=>{let t=Ur();return ri(ti(t,e))},At=null,tn=()=>(At||(At=he("package.json")),At),E=new Proxy({},{get:(e,t)=>tn()[t]}),He=e=>{let t=e??d(),r=I(t),n=S(t,r.services);if(!ge(n))return[];try{return Qs(n,{withFileTypes:!0}).filter(s=>s.isDirectory()&&!s.name.startsWith(".")).map(s=>`${r.services}/${s.name}`).sort()}catch{return[]}}});import{argv as Jl}from"process";import Te from"chalk";import{Command as Kl}from"commander";import ql from"terminal-link";z();v();import Ni from"chalk";import{Command as Ai}from"commander";h();import{existsSync as Si}from"fs";import{join as Ei}from"path";import{cwd as ln}from"process";import{execaSync as Ti}from"execa";h();import{spawn as Lt}from"child_process";import{resolve as vi}from"path";import{execa as ki}from"execa";import{existsSync as ui}from"fs";import{resolve as di}from"path";import{config as gi}from"dotenv";var _t=(e,t)=>{let r=di(t,e);return ui(r)?gi({path:r,processEnv:{}}).parsed||{}:{}},fi=e=>`${(e.includes("/")?e.split("/").pop()??e:e).toUpperCase().replace(/-/g,"_")}_PORT`,nn=(e,t)=>{let r=_t(e,t),n=[];for(let[o,s]of Object.entries(r))if(o.endsWith("_PORT")&&s){let i=Number.parseInt(s,10);!Number.isNaN(i)&&i>0&&n.push({key:o,port:i})}return n},hi=65535,yi=e=>{if(!e||!/^\d+$/.test(e))return;let t=Number.parseInt(e,10);return t>0&&t<=hi?t:void 0},on=(e,t,r)=>{let n=t.filter(i=>!i.startsWith("!"));if(n.length===0)return e.map(i=>i.port);let o=yi(r);if(o!==void 0&&n.length===1)return[o];let s=new Set(n.map(fi));return[...new Set(e.filter(i=>s.has(i.key)).map(i=>i.port))]};var Dt={...process.env,NODE_NO_WARNINGS:"1"},Ci=(e,t,r)=>e?"pipe":t||r?["ignore","pipe","pipe"]:"inherit",xi=(e,t,r)=>e?{...Dt,...e}:t||r?{...Dt,CI:"true"}:{...Dt},wi=e=>e.includes("EEXIST")||e.includes("failed to link package");async function K(e,t,{cwd:r=process.cwd(),task:n,shell:o,context:s=e,quiet:i=!1,nonInteractive:a=!1,env:c}={}){try{t.length===0&&(t=e.split(" ").slice(1));let p=ki(e,t,{cwd:r,stdio:Ci(i,n,a),all:n||a?!0:void 0,shell:o??!0,env:xi(c,n,a)});p.all&&p.all.on("data",l=>{let u=l.toString().trim();n?(n.output=u,u.length&&m.storeLog(u,s)):a&&u.length&&console.log(u)}),await p}catch(p){let l=p instanceof Error?p.message:String(p);if(wi(l))return;throw new Error(Pi(l))}}var Pi=e=>{let t=e.match(/error: (.+)/);return t?t[1].trim():e};function sn(e,t,r={}){let{cwd:n=process.cwd(),envFile:o,detached:s=!0,pipeStdout:i=!1,onStdout:a,onStderr:c,onExit:p}=r,l=o?_t(o,n):{},u=vi(n,"node_modules",".bin"),T=process.env.PATH||"",Ct=`${u}:${T}`,Ts={...process.env,...l,PATH:Ct,FORCE_COLOR:"1"},$e=Lt(e,t,{cwd:n,env:Ts,stdio:["inherit",i?"pipe":"inherit","pipe"],detached:s});return a&&i&&$e.stdout?.on("data",a),c&&$e.stderr?.on("data",c),p&&$e.on("exit",p),$e}function an(e,t,r={}){let{cwd:n=process.cwd()}=r;Lt(e,t,{cwd:n,stdio:"inherit"}).on("exit",s=>process.exit(s||0))}function cn(e,t,r={}){let{cwd:n=process.cwd()}=r,o=t.length>0?`${e} ${t.join(" ")}`:e;Lt(o,[],{cwd:n,env:process.env,stdio:"inherit",shell:!0}).on("exit",i=>process.exit(i||0))}async function pn(e){let{execSync:t}=await import("child_process");for(let r of e)try{let o=t(`lsof -ti:${r}`,{encoding:"utf8",stdio:"pipe"}).trim().split(`
|
|
21
|
+
`).filter(Boolean);for(let s of o)try{process.kill(Number.parseInt(s,10),"SIGKILL")}catch{}}catch{}}v();var Ge=e=>me(e);function Mt(e=process.cwd()){let t=r=>Si(Ei(e,r));if(t("bun.lock")||t("bun.lockb"))return"bun";if(t("pnpm-lock.yaml"))return"pnpm";if(t("yarn.lock"))return"yarn";if(t("package-lock.json"))return"npm"}function w(e){return Mt(e)??$i()}function $i(){return Ge("bun")?"bun":Ge("pnpm")?"pnpm":Ge("yarn")?"yarn":"npm"}function mn(){return["bun","pnpm","yarn","npm"].filter(Ge)}async function M(e,t){let r=Ri(e,t),{mergedOptions:n,packages:o}=r,{cwd:s=process.cwd(),flags:i=[],task:a,quiet:c}=n,p=n.packageManager??w(),l=[],u=Array.isArray(o)?o:[o];p==="bun"&&(u=u.map(Ct=>Ct.replace("git+ssh://",""))),p==="pnpm"&&(l.push("--config.engine-strict=false"),l.push("--no-frozen-lockfile")),["yarn","npm"].includes(p)&&l.push("--ignore-engines");let T=u.length?p==="npm"?["install",...i,...l,...u]:["add",...i,...l,...u]:["install",...i,...l];await K(p,T,{cwd:s,task:a,quiet:c})}async function un(e){let t=["-g"],r=[...e.flags??[],...t];await M({...e,flags:r,packageManager:e.packageManager??w()})}function dn(e,t,r){let{args:n,mergedOptions:o}=fn(t??[],r),s=o.manager??w(),{command:i,args:a}=gn(s);console.log(`
|
|
22
22
|
Running command: ${i} ${[...a,e,...n].join(" ")}
|
|
23
|
-
`),
|
|
24
|
-
`,r=e.match(/import\s+['"]@crossdelta\/telemetry['"]\s*\n/);if(r){let o=(r.index??0)+r[0].length;return`${e.slice(0,o)}
|
|
25
|
-
${t}${e.slice(o)}`}let n=e.match(/import\s+.*\n/);if(n){let o=(n.index??0)+n[0].length;return e.slice(0,o)+t+e.slice(o)}return e},Vc=(e,t)=>`
|
|
26
|
-
|
|
27
|
-
// Consume from ${e} stream
|
|
28
|
-
consumeJetStreams({
|
|
29
|
-
streams: ['${e}'],
|
|
30
|
-
consumer: '${t}-service',
|
|
31
|
-
discover: './src/events/**/*.handler.ts',
|
|
32
|
-
})`,yr=(e,t)=>{let r=Bc(t),n=hr(e,"src","index.ts"),o=hr(e,"src","main.ts");if(!mt(n)&&mt(o))return{added:!1,streamName:r};if(!mt(n))return{added:!1,streamName:r,warning:"Entry point not found (index.ts or main.ts)"};if(wo(e,r))return{added:!1,streamName:r};let s=xo(n,"utf-8"),i=e.split("/").pop()||"unknown";s.includes("consumeJetStreams")||(s=Uc(s));let a=Vc(r,i),c=`${s.trimEnd()+a}
|
|
33
|
-
`;return Gc(n,c,"utf-8"),{added:!0,streamName:r}};f();import{existsSync as oy,readFileSync as sy}from"fs";import{join as ay}from"path";import{contractCreated as ly,deriveEventNames as py,generateContract as my,getContractFilePath as dy}from"@crossdelta/cloudevents";import{readdirSync as zc,readFileSync as Jc}from"fs";import{join as Po}from"path";import{getStreamName as Kc,singularize as qc}from"@crossdelta/cloudevents";var So=e=>{try{return zc(e,{withFileTypes:!0}).flatMap(r=>{let n=Po(e,r.name);return r.isDirectory()?So(n):r.name.endsWith(".handler.ts")?[n]:[]})}catch{return[]}},vr=e=>{let t=Po(e,"src","events");return So(t).flatMap(n=>{let o=Jc(n,"utf-8");return Yc(n,o)})},Yc=(e,t)=>{let r=Xc(t);if(!r)return[];let n=Zc(r);return n?[{filePath:e,eventType:n,contractName:r}]:[]},Zc=e=>{let r=e.replace(/Contract$/,"").match(/[A-Z][a-z]*/g);if(!r||r.length<2)return null;let n=r[0].toLowerCase(),o=qc(n),i=r.slice(1).map(a=>a.toLowerCase()).join("-");return`${o}.${i}`},Xc=e=>{let r=/import\s+{([^}]+)}\s+from\s+['"]@[\w-]+\/contracts['"]/.exec(e);return r?r[1].split(",").map(s=>s.trim()).filter(s=>s.endsWith("Contract")).map(s=>s.replace(/\s+as\s+.+$/,"").trim()).at(0)??null:null},Cr=e=>{let t=e.reduce((r,n)=>{let o=n.eventType.split(".")[0],s=r.get(o)??[];return r.set(o,[...s,n]),r},new Map);return Array.from(t.entries()).map(([r,n])=>Qc(r,n)).sort((r,n)=>r.stream.localeCompare(n.stream))},Qc=(e,t)=>{let r=Kc(t[0]?.eventType??`${e}.event`),n=`${e}.>`;return{stream:r,subjects:[n],handlers:t}},kr=(e,t)=>e.length===0?"":` // Development: pf dev auto-creates ephemeral streams from contracts
|
|
34
|
-
// Production: Pulumi materializes persistent streams
|
|
35
|
-
|
|
36
|
-
consumeJetStreams({
|
|
37
|
-
streams: [${e.map(r=>`'${r.stream}'`).join(", ")}],
|
|
38
|
-
consumer: '${t}',
|
|
39
|
-
discover: './src/events/**/*.handler.ts',
|
|
40
|
-
})`;f();import{existsSync as te,mkdirSync as el,readFileSync as dt,writeFileSync as pe}from"fs";import{dirname as bo,join as le}from"path";import{deriveEventNames as tl}from"@crossdelta/cloudevents";var rl=(e,t)=>{let r=`export * from './${t}'`;if(!te(e)){let s=bo(e);te(s)||el(s,{recursive:!0});let i=`/**
|
|
41
|
-
* ${bo(e).split("/").pop()} Domain Events
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
`;return pe(e,`${i+r}
|
|
45
|
-
`,"utf-8"),!0}let n=dt(e,"utf-8");if(n.includes(`'./${t}'`))return!1;let o=`${n.trimEnd()}
|
|
46
|
-
${r}
|
|
47
|
-
`;return pe(e,o,"utf-8"),!0},nl=(e,t)=>{let r=`export * from './${t}'`;if(!te(e))return pe(e,`/**
|
|
48
|
-
* Event Contracts Index
|
|
49
|
-
*
|
|
50
|
-
* Re-exports all event contracts for convenient importing.
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
${r}
|
|
54
|
-
`,"utf-8"),!0;let o=dt(e,"utf-8").split(`
|
|
55
|
-
`);if(o.some(i=>i.trim()===r))return!1;let s=o.findLastIndex(i=>i.startsWith("export"));return s>=0?o.splice(s+1,0,r):o.push(r),pe(e,o.join(`
|
|
56
|
-
`),"utf-8"),!0},ol=e=>{if(!te(e))return!1;let t=dt(e,"utf-8"),r="export * from './events'";if(t.split(`
|
|
57
|
-
`).some(s=>s.trim()===r||s.trim().startsWith(r)))return!1;let o=t;return o=o.replace(/\/\/\s*export \* from '\.\/events'/,r),o=o.replace(/\/\/\s*export \* from '\.\/stream-policies'/,"export * from './stream-policies'"),/export \* from '\.\/events\/\w+\/\w+'/.test(o)&&(o=o.replace(/export \* from '\.\/events\/\w+\/\w+'\n?/g,"")),o.includes(r)||(o=`${o.trimEnd()}
|
|
58
|
-
${r}
|
|
59
|
-
`),o!==t?(pe(e,o,"utf-8"),!0):!1},xr=(e,t)=>{let{packagePath:r}=x(t),{domain:n,action:o}=tl(e),s=le(r,"src","events");if(!te(s))return!1;let i=le(s,n),a=le(i,"index.ts"),c=le(s,"index.ts"),l=le(r,"src","index.ts"),p=e.split(".")[0],m=le(s,p);p!==n&&te(m)&&(console.warn(`\u26A0\uFE0F Warning: Legacy folder '${p}/' found. Please migrate to '${n}/' to avoid conflicts.`),console.warn(` Run: mv ${m} ${i}`));let y=!1;return rl(a,o)&&(y=!0),nl(c,n)&&(y=!0),ol(l)&&(y=!0),y},wr=(e,t)=>{if(!te(e))return!1;let r=`export * from './events/${t}'`,n=dt(e,"utf-8");if(n.includes(`'./events/${t}'`))return!1;let o=n.split(`
|
|
60
|
-
`),s=o.findLastIndex(i=>i.startsWith("export"));return s>=0?o.splice(s+1,0,r):o.push("",r),pe(e,o.join(`
|
|
61
|
-
`),"utf-8"),!0};f();import{existsSync as Eo,readdirSync as il,readFileSync as al}from"fs";import{join as To}from"path";import{generateJsonMockFromContract as cl,getJsonMockPath as ll,initFaker as pl}from"@crossdelta/cloudevents";var $o=e=>{let t=e.match(/handleEvent\s*\(\s*(\w+Contract)/m);if(t){let n=e.match(/type:\s*['"]([^'"]+)['"]/m);if(n)return n[1]}let r=e.match(/handleEvent\s*\(\s*\{[^}]*type:\s*['"]([^'"]+)['"]/m);if(r)return r[1];if(t){let s=t[1].replace(/Contract$/,"").split(/(?=[A-Z])/).filter(Boolean);if(s.length>=2){let i=s[0].toLowerCase(),a=s.slice(1).join("").toLowerCase();return`${i}.${a}`}}return null};var Pr=async(e,t={})=>{let r=To(e,"src","events");if(!Eo(r))return{mockPaths:[],skippedHandlers:[]};await pl();let n=il(r).filter(i=>i.endsWith(".handler.ts")||i.endsWith(".event.ts")),o=[],s=[];for(let i of n){let a=To(r,i),c=al(a,"utf-8"),l=$o(c);if(!l){s.push(`${i} (Could not extract event type)`);continue}let p=t.outputDir??x().packagePath,m=ll(l,p);if(Eo(m)&&!t.overwrite){s.push(`${i} (Mock already exists)`);continue}let y=cl(l,p,{useFaker:!0});y&&y.status!=="skipped"&&"ref"in y?o.push(y.ref):s.push(`${i} (Contract not found or generation failed)`)}return{mockPaths:o,skippedHandlers:s}};var Ao=e=>{let t=e.split("/").pop()||"service",r=gl(e,"src","events","events.service.ts");if(!ml(r))return!1;let n=vr(e);if(n.length===0||dl(r,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").includes("consumeJetStreams"))return!1;let a=Cr(n),c=kr(a,t);if(!c)return!1;let l=new ul({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0}),p=l.addSourceFileAtPath(r),m=!1;for(let y of p.getClasses()){let j=y.getMethod("startConsumers");if(!j)continue;let N=[...c.split(`
|
|
62
|
-
`),""," this.logger.log('Event consumers started successfully')"].join(`
|
|
63
|
-
`);j.setBodyText(N),m=!0;break}return m&&l.saveSync(),m};f();var fl=e=>{let t=e.split(/\s+/),r=t[0],n=t.slice(1);return r==="pf"&&(r=process.argv[1]),{executable:r,args:n}},hl=async(e,t)=>{try{let{executable:r,args:n}=fl(e.command);return await K(r,n,{cwd:t,shell:!1}),{command:e.command,success:!0}}catch(r){return{command:e.command,success:!1,error:r instanceof Error?r.message:String(r)}}},Sr=async(e,t)=>{let r=[];for(let n of e){let o=await hl(n,t);if(r.push(o),!o.success)break}return r},br=e=>{let t=[/^pf\s+/,/^bun\s+pf\s+/,/^npx\s+pf\s+/,/^bunx\s+pf\s+/];return e.filter(r=>t.some(n=>n.test(r.command)))},Io=e=>{for(let t of e){let r=t.command.match(/(?:bun\s+)?pf\s+new\s+\S+\s+(\S+)/);if(r)return r[1]}return null};import{existsSync as Fo,readFileSync as xl}from"fs";import{join as Er}from"path";import G from"chalk";f();or();import{existsSync as Ro,mkdirSync as yl,writeFileSync as vl}from"fs";import{dirname as Cl}from"path";var kl=(e,t)=>{let n=e.path.startsWith("packages/")&&t.workspaceRoot?t.workspaceRoot:t.baseDir,o;try{o=_n(e.path,n)}catch(s){return{status:"failed",path:e.path,error:s.message}}try{if(Ro(o)&&!t.overwrite)return{status:"skipped",path:e.path};if(t.dryRun)return{status:"written",path:e.path};let s=Cl(o);return Ro(s)||yl(s,{recursive:!0}),vl(o,e.content,"utf-8"),{status:"written",path:e.path}}catch(s){return{status:"failed",path:e.path,error:s.message}}},No=(e,t)=>{let r=e.map(n=>kl(n,t));return{written:r.filter(n=>n.status==="written").map(n=>n.path),skipped:r.filter(n=>n.status==="skipped").map(n=>n.path),failed:r.filter(n=>n.status==="failed").map(n=>({path:n.path,error:n.error}))}};var wl=(e,t)=>{let r=E(t.workspaceRoot),n=Er(t.workspaceRoot,r.contracts);if(!Fo(n))return[];let o=/import\s+(?:type\s+)?{([^}]+)}\s+from\s+['"]@\w+\/contracts['"]/g,s=new Set;for(let i of e){let a=i.content.matchAll(o);for(let c of a){let p=c[1].split(",").map(m=>m.trim()).map(m=>m.replace(/^type\s+/,"").replace(/\s+as\s+.+$/,"").trim()).filter(m=>m.endsWith("Contract"));for(let m of p)s.add(m)}}return Array.from(s).sort()},Pl=e=>{let t=Er(e,"packages/contracts/src/index.ts");if(!Fo(t))return new Set;try{let r=xl(t,"utf-8"),n=new Set,o=/export\s+(?:\*|{[^}]*Contract[^}]*})\s+from\s+['"]\.\/events\/([^'"]+)['"]/g,s=r.matchAll(o);for(let i of s){let a=i[0],c=/(\w+Contract)/g,l=a.matchAll(c);for(let p of l)n.add(p[1])}return n}catch{return new Set}},Sl=e=>{let t=e.replace(/Contract$/,""),r=t.split(/(?=[A-Z])/).filter(Boolean);if(r.length<2)return t.toLowerCase();let n=r[0].toLowerCase(),o=r.slice(1).join("").toLowerCase();return`${n}.${o}`},bl=(e,t,r)=>{let n=Pl(t),o=[],s=[],i=[];for(let a of e)if(n.has(a))o.push(a);else{s.push(a);let c=Sl(a),l=r.replace(`${t}/`,"");i.push(`pf cloudevents add ${c} --service ${l}`)}return{existing:o,missing:s,suggestedCommands:i}},El=(e,t)=>{if(e.length!==0){console.log(G.cyan(`\u{1F4E6} Using existing contracts:
|
|
64
|
-
`));for(let r of e)console.log(G.dim(` ${t}/contracts \u2192 ${r}`));console.log()}},Tl=(e,t)=>{let r=/^packages\/contracts\/src\/events\/([^/]+)\.ts$/,n=Er(t,"packages/contracts/src/index.ts");for(let o of e){let s=o.match(r);s&&s[1]!=="index"&&wr(n,s[1])}},Oo=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")}},$l=async(e,t)=>{t.start("Scanning for event handlers...");let{mockPaths:r,skippedHandlers:n}=await Pr(e);if(r.length+n.length===0){t.info("No event handlers found");return}if(r.length>0){t.succeed(`Generated ${r.length} event ${r.length===1?"mock":"mocks"}`),console.log();for(let s of r){let i=s.replace(`${e}/`,"");console.log(G.dim(` ${i}`))}console.log()}else t.succeed("Event handlers found");if(n.length>0){for(let s of n)console.log(G.dim(` \u2139 Skipped: ${s}`));console.log()}},Mo=async(e,t,r,n)=>{n.start("Writing generated files...");let o=No(e,{baseDir:t,workspaceRoot:r.workspaceRoot,overwrite:!0});if(o.written.length>0){n.succeed(`Created ${o.written.length} files`),console.log();for(let l of o.written)console.log(G.dim(` ${l}`));console.log()}else n.succeed("No files to write");let s=wl(e,r),{existing:i,missing:a,suggestedCommands:c}=bl(s,r.workspaceRoot,t);if(i.length>0&&El(i,r.scope),a.length>0){console.log(G.yellow(`\u26A0\uFE0F Missing contracts (not exported from @${r.scope}/contracts):
|
|
65
|
-
`));for(let l of a)console.log(G.yellow(` ${l}`));console.log(),console.log(G.cyan(`\u{1F4A1} Run these commands to create the missing contracts:
|
|
66
|
-
`));for(let l of c)console.log(G.dim(` ${l}`));console.log()}return Tl(o.written,r.workspaceRoot),o.written.length>0&&await $l(t,n),{missingContractCommands:c}};f();import{existsSync as Dl,readFileSync as _l}from"fs";import{join as _e}from"path";f();f();import{existsSync as Al,readdirSync as Il,readFileSync as Rl}from"fs";import{join as Nl}from"path";var Do=e=>{let{eventsPath:t}=x(e);if(!Al(t))return[];let r=[];try{let n=Il(t).filter(o=>o.endsWith(".ts")&&!o.endsWith(".mock.json")&&o!=="index.ts");for(let o of n){let s=Nl(t,o),i=Rl(s,"utf-8"),a=Fl(i,s);a&&r.push(a)}}catch(n){return console.warn("Warning: Could not scan contracts package:",n),[]}return r},Fl=(e,t)=>{try{let r=e.match(/export const (\w+Contract) = createContract/);if(!r)return null;let n=r[1],o=e.match(/export type (\w+(?:Data|Event)) = z\.infer/);if(!o)return null;let s=o[1],i=e.match(/type:\s*['"]([^'"]+)['"]/);if(!i)return null;let a=i[1],c=Ml(e);return{name:n,typeName:s,eventType:a,fields:c,filePath:t}}catch{return null}},Ol={string:"string",number:"number",boolean:"boolean",array:"array",object:"object",date:"date"},Ml=e=>{let t=e.match(/z\.object\({([^}]+)\}/);if(!t)return[];let r=t[1],n=/(\w+):\s*z\.(\w+)\([^)]*\)/g,o=[...r.matchAll(n)].map(([,a,c])=>{let l=Ol[c]||c;return`${a}: ${l}`});if(!e.includes("z.array("))return o;let s=/(\w+):\s*z\.array\(/g,i=[...e.matchAll(s)].map(([,a])=>a).filter(a=>!o.some(c=>c.startsWith(a))).map(a=>`${a}: array`);return[...o,...i]},_o=(e,t)=>{if(e.length===0)return`
|
|
67
|
-
**Available Contracts:**
|
|
68
|
-
|
|
69
|
-
No contracts are currently defined. Use Basic Mode with inline schemas for all events.
|
|
70
|
-
`.trim();let r=e.map((n,o)=>{let s=n.fields.length>0?n.fields.map(i=>` - ${i}`).join(`
|
|
71
|
-
`):" - (no fields detected)";return`
|
|
72
|
-
${o+1}. **${n.name}** (\`${n.eventType}\`)
|
|
73
|
-
- Type: \`${n.typeName}\`
|
|
74
|
-
- Fields:
|
|
75
|
-
${s}
|
|
76
|
-
- **USE THIS** when consuming ${n.eventType} or similar event names
|
|
77
|
-
`.trim()}).join(`
|
|
78
|
-
|
|
79
|
-
`);return`
|
|
80
|
-
**Available Contracts** (ALWAYS check this list first!):
|
|
81
|
-
|
|
82
|
-
The following event contracts are available in \`${t}/contracts\`:
|
|
83
|
-
|
|
84
|
-
${r}
|
|
85
|
-
|
|
86
|
-
If the event type your service consumes matches one of these, **you MUST use Advanced Mode**.
|
|
87
|
-
`.trim()};var jl=()=>typeof import.meta?.url=="string"?W(import.meta.url):typeof __dirname=="string"?__dirname:process.cwd(),Ll=(e,t)=>{let r=_e(jl(),"docs","generators"),n=ce(),o=[];for(let s of n.docs.base)o.push(_e(r,s));if(e&&n.docs.frameworks[e]){let s=n.docs.frameworks[e];if(typeof s=="string")o.push(_e(r,s));else{let i=t==="bun"?"bun":"node";s[i]&&o.push(_e(r,s[i]))}}return o},Wl=["CLAUDE.md","AGENTS.md",".github/copilot-instructions.md","docs/ai-guidelines.md"],jo=1500,Lo=50,Wo=e=>{try{return Dl(e)?_l(e,"utf-8"):null}catch{return null}},Hl=e=>e.replace(/<!--[\s\S]*?-->/g,"").replace(/^\[.+\]:\s*.+$/gm,"").replace(/\n{3,}/g,`
|
|
88
|
-
|
|
89
|
-
`).replace(/[ \t]+$/gm,"").trim(),Gl=e=>e.replace(/<!--[\s\S]*?-->/g,"").replace(/^\[.+\]:\s*.+$/gm,"").replace(/```[\s\S]*?```/g,"").replace(/`[^`]{50,}`/g,"`...`").replace(/\n{3,}/g,`
|
|
90
|
-
|
|
91
|
-
`).replace(/[ \t]+$/gm,"").trim(),Bl=e=>Math.ceil(e.length/4),Ul=(e,t)=>{let r=e.split(/(?=^## )/m),n="",o=0;for(let s of r){let i=Bl(s);if(o+i<=t)n+=s,o+=i;else if(o===0){n=s.slice(0,t*4);break}else break}return n.trim()},Vl=(e,t)=>{let{workspaceRoot:r,scope:n}=t,o=Do(r),s=_o(o,n);return e.replace(/\{\{scope\}\}/g,n).replace(/\{\{AVAILABLE_CONTRACTS\}\}/g,s)},Ho=e=>{let{workspaceRoot:t,scope:r}=e,n=[],o=Ll(e.serviceType,e.packageManager);for(let a of o){let c=Wo(a);if(c){let l=Vl(c,e),p=Hl(l);n.push(p)}}let s=[...new Set(Wl.map(a=>Wo(_e(t,a))).filter(a=>a!==null).map(Gl).filter(a=>a.length>Lo))],i=s.length?Math.floor(jo/s.length):jo;for(let a of s){let c=Ul(a,i);c.length>Lo&&n.push(c)}return n.length===0?(console.warn("\u26A0\uFE0F No instruction files found."),`Use ${r}/contracts for shared types.`):n.join(`
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
`)};var zl=`You are an expert code generator. Generate clean, production-ready code.
|
|
96
|
-
|
|
97
|
-
## Output Format
|
|
98
|
-
|
|
99
|
-
Format your code blocks with the file path on the line before the code block:
|
|
100
|
-
|
|
101
|
-
#### \`src/index.ts\`
|
|
102
|
-
\`\`\`typescript
|
|
103
|
-
// code here
|
|
104
|
-
\`\`\`
|
|
105
|
-
|
|
106
|
-
**IMPORTANT:** Always generate:
|
|
107
|
-
- Source code files (src/**)
|
|
108
|
-
- Test files (src/**/*.test.ts) for all business logic
|
|
109
|
-
- README.md with service documentation`,Jl=e=>e.replace(/-/g,"_").toUpperCase(),Kl=e=>e.split("/").pop()||"my-service",Go=(e,t,r)=>{let n=Ho({...e,serviceType:t,packageManager:r});return`${zl}
|
|
110
|
-
|
|
111
|
-
## Project Guidelines & Patterns
|
|
112
|
-
|
|
113
|
-
Follow these project-specific conventions and patterns when generating code:
|
|
114
|
-
|
|
115
|
-
${n}`},Bo=(e,t,r,n)=>{let o=Kl(e),s=`${Jl(o)}_PORT`,i=st();return`Generate source code for a microservice at path "${e}".
|
|
116
|
-
|
|
117
|
-
Use the patterns and conventions from the Project Guidelines above.
|
|
118
|
-
|
|
119
|
-
Service purpose: ${t}
|
|
120
|
-
|
|
121
|
-
**CRITICAL:**
|
|
122
|
-
- Service name: "${o}"
|
|
123
|
-
- Workspace scope: "${i}" (use this for imports like \`${i}/contracts\`)
|
|
124
|
-
- Port env var: Use \`process.env.${s}\` (NOT SERVICE_NAME_PORT)
|
|
125
|
-
- Consumer name: Use "${o}" as the consumer name in consumeJetStreams
|
|
126
|
-
- You MAY modify \`src/index.ts\` or \`src/main.ts\` to add consumeJetStreams, env validation, or middleware
|
|
127
|
-
- BUT you MUST keep the existing port configuration line unchanged!
|
|
128
|
-
|
|
129
|
-
Do NOT include the service path in file headers (use \`src/...\`, NOT \`${e}/src/...\`).
|
|
130
|
-
`};var ql=()=>!!process.env.DEBUG,Uo=(e,t)=>{ql()&&console.log(`[AI Parser] ${e}`,t??"")},gt={commandsBlock:/```commands\n([\s\S]*?)```/gi,postCommandsBlock:/```post-commands\n([\s\S]*?)```/gi,dependenciesBlock:/```dependencies\n([\s\S]*?)```/gi,fileHeader:/^#{1,4}\s+`([^`]+)`\s*$/},$r=(e,t)=>[...e.matchAll(t)].flatMap(n=>n[1].split(`
|
|
131
|
-
`).map(o=>o.trim()).filter(o=>o.length>0&&!o.startsWith("#"))),Vo=e=>({command:e,isPfCommand:e.startsWith("pf ")||e.includes(" pf ")}),Yl=e=>$r(e,gt.commandsBlock).map(Vo),Zl=e=>$r(e,gt.postCommandsBlock).map(Vo),Xl=e=>$r(e,gt.dependenciesBlock).filter(t=>!t.startsWith("@crossdelta/")&&t!=="zod"),Ql=e=>{let t={ts:"typescript",js:"javascript",md:"markdown",yml:"yaml"},r=(e||"typescript").toLowerCase();return t[r]||r},ep=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"},tp=e=>e.replace(/^\s*\/\/ \.{3,}.*$/gm,"").replace(/^\s*\/\/ Lines? \d+.*omitted.*$/gim,"").replace(/^\s*\/\* Lines? \d+.*omitted.*\*\/$/gim,"").trim(),rp=e=>{let t=e.split(`
|
|
132
|
-
`),r=[],n=0;for(let o of t){let s=gt.fileHeader.exec(o);s&&r.push({path:s[1],index:n}),n+=o.length+1}return r},np=(e,t)=>{let n=e.slice(t).match(/```(\w+)?\n([\s\S]*?)```/);return n?{language:n[1]?Ql(n[1]):void 0,content:tp(n[2])}:null},op=e=>rp(e).map(r=>{let n=np(e,r.index);return!n||n.content.length===0?null:{path:r.path,language:n.language||ep(r.path),content:n.content,startIndex:r.index}}).filter(r=>r!==null),Tr=e=>e.includes("packages/contracts")||e.includes("contracts/src"),sp=e=>{let t=e.filter(n=>Tr(n.path)),r=e.filter(n=>!Tr(n.path));return[...t,...r]},ip=e=>{let t=e.replace(/^\/+/,"").replace(/\/{2,}/g,"/");if(Tr(t))return t;let r=t.match(/^services\/[^/]+\/(.+)$/);return r?r[1]:t},zo=(e,t)=>{Uo("Parsing AI response",{length:e.length});let r=Yl(e),n=Zl(e),o=Xl(e),s=op(e),i=sp(s.map(a=>({path:ip(a.path),content:a.content,language:a.language})));return Uo("Parsed response",{commands:r.length,postCommands:n.length,dependencies:o.length,files:i.length}),{commands:r,files:i,dependencies:o,postCommands:n}},Jo=e=>{let t=e.filter(s=>!s.content||s.content.trim().length===0),r=e.length===0?["No files could be extracted from the AI response"]:t.map(s=>`File ${s.path} is empty`),n=e.some(s=>["src/index.ts","src/main.ts","index.ts"].includes(s.path)),o=e.length>0&&!n?["No entry point file (src/index.ts or src/main.ts) found - assuming it exists from scaffolding"]:[];return{valid:r.length===0,errors:r,warnings:o}};import{mkdirSync as ap}from"fs";import H from"chalk";var Ko=async(e,t,r)=>{if(e.length===0){ap(t,{recursive:!0}),console.log(H.yellow(`\u26A0 No scaffolding command found - creating empty directory
|
|
133
|
-
`));return}let o=(await Sr(e,r)).find(s=>!s.success);if(o)throw console.log(H.red(`
|
|
134
|
-
\u2717 Scaffolding failed: ${o.command}`)),o.error&&console.log(H.red(` Error: ${o.error}`)),new Error(`Command failed: ${o.command}${o.error?` - ${o.error}`:""}`)},qo=async(e,t,r)=>{if(e.length===0)return;r.stop();let n=e.length===1?"package":"packages";console.log(H.cyan(`
|
|
135
|
-
\u25B6 Installing ${e.length} additional ${n}...
|
|
136
|
-
`));try{await L({packages:e,cwd:t,flags:["--silent"]}),console.log(H.green(`\u2713 Installed ${e.length} ${n}
|
|
137
|
-
`))}catch(o){throw console.log(H.red(`\u2717 Package installation failed
|
|
138
|
-
`)),o}},Ar=async(e,t)=>{if(e.length===0)return;console.log(H.cyan(`
|
|
139
|
-
\u25B6 Running post-generation commands...
|
|
140
|
-
`));let n=(await Sr(e,t)).find(o=>!o.success);if(n){console.log(H.yellow(`
|
|
141
|
-
\u26A0 Post-command failed: ${n.command}`)),n.error&&console.log(H.yellow(` Error: ${n.error}`));return}console.log(H.green(`\u2713 Post-generation commands complete
|
|
142
|
-
`))};import ut from"chalk";var cp=e=>`${ut.dim(" \u2022 ")+ut.cyan(e)}
|
|
143
|
-
`,Yo=e=>ut.dim(` \u2728 Generated ${ut.white.bold(e)} tokens
|
|
144
|
-
`),Zo=()=>{let e="",t=0,r=Date.now(),n=[],o=()=>{let i=e.match(/####\s+`([^`]+)`/);if(!i)return!1;n.push(i[1]),process.stdout.write(cp(i[1]));let a=e.indexOf(i[0])+i[0].length;return e=e.slice(a),!0},s=i=>{e+=i,t++,o(),e.length>500&&(e=e.slice(-200))};return s.getStats=()=>{let i=((Date.now()-r)/1e3).toFixed(2),a=(t/Number.parseFloat(i)).toFixed(0);return{tokenCount:t,duration:i,tokensPerSec:a}},s.getFiles=()=>n,s};var up=()=>{let e=g(),t=ts(e,"package.json"),r=(()=>{if(!es(t))throw new Error("No package.json found in workspace root. Run from a valid workspace.");try{let o=JSON.parse(lp(t,"utf-8")).name;if(!o)throw new Error('package.json has no "name" field. Please add a name to your root package.json.');return o.startsWith("@")?o:`@${o}`}catch(n){throw n instanceof SyntaxError?new Error("Invalid JSON in package.json"):n}})();return{workspaceRoot:e,scope:r,cwd:process.cwd()}},fp=async(e,t,r,n,o,s)=>{let i=Bo(r,n,o,t.workspaceRoot),a=Go(t,o,s),c=Zo(),l=await yo(e,i,{system:a,maxTokens:16384,temperature:.7,onToken:c}),p=c.getStats();return console.log(Yo(p.tokenCount)),console.log(),l},hp=(e,t)=>{let{serviceTypes:r}=ce(),n=r[t]?.commandType;if(!n)return e;let o=Object.values(r).map(s=>s.commandType);return e.map(s=>{for(let i of o)if(i!==n&&s.command.includes(`pf new ${i}`))return{...s,command:s.command.replace(`pf new ${i}`,`pf new ${n}`)};return s})},yp=e=>e.length===0?"":`${[h.cyan(`
|
|
145
|
-
\u{1F4C1} Files to create:`),...e.map(t=>` ${h.green("\u2022")} ${h.white(t.path)} ${h.dim(`(${t.language})`)}`)].join(`
|
|
146
|
-
`)}
|
|
147
|
-
`,Qo=(e,t,r)=>e.length===0?"":`${[h.cyan(`
|
|
148
|
-
${r} ${t}:`),...e.map(n=>` ${h.yellow("$")} ${h.white(n.command)}`)].join(`
|
|
149
|
-
`)}
|
|
150
|
-
`,vp=e=>e.length===0?"":`${[h.cyan(`
|
|
151
|
-
\u{1F4E6} Dependencies to install:`),...e.map(t=>` ${h.magenta("+")} ${h.white(t)}`)].join(`
|
|
152
|
-
`)}
|
|
153
|
-
`,Cp=(e,t)=>`${[h.yellow(`
|
|
154
|
-
Validation errors:`),...e.map(r=>h.yellow(` \u26A0 ${r}`)),h.dim(`
|
|
155
|
-
Response preview:`),h.dim(t)].join(`
|
|
156
|
-
`)}
|
|
157
|
-
`,me=e=>{e&&process.stdout.write(e)},kp=(e,t)=>{let r=zo(e,t),n=br(r.commands),o=br(r.postCommands),s=Jo(r.files);return s.valid?{files:r.files,commands:n,dependencies:r.dependencies,postCommands:o}:(console.log(`${h.yellow("\u26A0")} Could not extract structured files from AI response`),me(Cp(s.errors,e.slice(0,500))),null)},xp=e=>{console.log(`${h.green("\u2714")} Extracted ${e.files.length} files`),me(yp(e.files)),me(Qo(e.commands,"Commands to run","\u{1F527}")),me(Qo(e.postCommands,"Post-generation commands","\u{1F4DD}")),me(vp(e.dependencies)),me(`
|
|
158
|
-
`)},wp=(e,t,r)=>{let n=Io(e);return n&&!n.includes("/")&&!n.startsWith(".")&&(n=`${E().services}/${n}`),n?Xo(r,n):Xo(r,t)},Pp=(e,t)=>{let{serviceTypes:r}=ce(),n=r[t]?.skipFiles||["package.json","tsconfig.json","Dockerfile"];return e.filter(o=>!n.includes(o.path))},de=()=>{if(!De())return{valid:!1,error:h.red.bold(`\u274C AI configuration not found.
|
|
159
|
-
`)+h.yellow("Please run ")+h.cyan.bold("pf setup --ai")+h.yellow(` first to configure your AI provider.
|
|
160
|
-
`)};try{return{valid:!0,config:pt()}}catch(e){return{valid:!1,error:h.red.bold(`\u274C ${e.message}
|
|
161
|
-
`)}}},ft=async e=>e||dp({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"}),ht=(e,t,r)=>{console.log(h.cyan.bold(`
|
|
162
|
-
\u{1F916} AI-Powered Generation
|
|
163
|
-
`)),console.log(h.dim(`Service: ${e.split("/").pop()}`)),console.log(h.dim(`Path: ${e}`)),console.log(h.dim(`Model: ${t.model}`)),console.log(h.dim(`Description: ${r}
|
|
164
|
-
`))},yt=async(e,t)=>{let{servicePath:r,description:n="",serviceType:o,packageManager:s}=e,i=r.split("/").pop()||r,a=up(),c=ts(a.workspaceRoot,er);mp(c,`generating:${r}`);let l=()=>{es(c)&&pp(c)},p=()=>{l(),process.exit(w.CANCELLED)};process.on("SIGINT",p),process.on("SIGTERM",p);try{console.log(h.cyan.bold(`
|
|
165
|
-
\u{1F916} AI Generation
|
|
166
|
-
`));let m=await fp(t,a,r,n,o,s),y=kp(m,i);if(!y)return!1;xp(y);let j=gp({text:"Processing files...",color:"cyan"}).start(),be=hp(y.commands,o),N=wp(be,r,a.cwd),oa=Pp(y.files,o);await Ko(be,N,a.workspaceRoot);let{missingContractCommands:Cn}=await Mo(oa,N,a,j);if(y.postCommands.length>0)await Ar(y.postCommands,a.workspaceRoot);else if(Cn.length>0){console.log(h.cyan(`\u{1F527} Auto-creating missing contracts...
|
|
167
|
-
`));let sa=Cn.map(ia=>({command:ia,isPfCommand:!0}));await Ar(sa,a.workspaceRoot)}return Ao(N),await qo(y.dependencies,N,j),await Oo(N,j),!0}finally{process.off("SIGINT",p),process.off("SIGTERM",p),l()}};import{existsSync as aC}from"fs";import{Project as Sp,SyntaxKind as lC}from"ts-morph";var pC=new Sp({skipAddingFilesFromTsConfig:!0,skipFileDependencyResolution:!0});v();import{promises as Ir}from"fs";import vt from"path";import rs from"chalk";var ns=async e=>{await K("bash",["-c",`
|
|
23
|
+
`),Ti(i,[...a,e,...n],{cwd:o.cwd??ln(),stdio:"inherit",preferLocal:!0})}async function jt(e,t,r){let{args:n,mergedOptions:o}=fn(t??[],r),s=o.manager??w(),{command:i,args:a}=gn(s);await K(i,[...a,e,...n],o)}async function ye(e,t){let{script:r,mergedOptions:n}=Ii(e,t),o=n.packageManager??w();await K(o,["run",r,...n.args??[]],{cwd:n.cwd??ln(),task:n.task})}function gn(e){let r={bun:"bunx",pnpm:"npx",yarn:"npx",npm:"npx"}[e];if(!r)throw new Error(`No executor found for the detected package manager: ${e}`);let[n,...o]=r.split(" ");return{command:n,args:o}}function Ri(e,t){return Array.isArray(e)?{packages:e,mergedOptions:{...t,packages:e}}:{packages:e.packages??[],mergedOptions:e}}function fn(e,t){return Array.isArray(e)?{args:e,mergedOptions:t??{}}:{args:[],mergedOptions:e}}function Ii(e,t){return typeof e=="string"?{script:e,mergedOptions:t??{}}:{script:e.script,mergedOptions:e}}var Oi=e=>e==="yarn"?["npm","audit"]:["audit"],hn=new Ai("audit").description("Run security audit on dependencies").allowUnknownOption(!0).action((e,t)=>{try{let r=d(),n=w(),o=Oi(n),s=t.args||[];console.log(Ni.dim(`Running ${n} ${[...o,...s].join(" ")}`)),an(n,[...o,...s],{cwd:r})}catch(r){O(r)}});import pe from"chalk";h();import{promises as Ft}from"fs";import Be from"path";import yn from"chalk";var vn=async e=>{await K("bash",["-c",`
|
|
168
24
|
curl -fsSL https://bun.sh/install | bash && if [ -f "$HOME/.bun/bin/bun" ]; then export PATH="$HOME/.bun/bin:$PATH"; fi
|
|
169
|
-
`],{task:e,shell:!0}),await
|
|
25
|
+
`],{task:e,shell:!0}),await _i()},Wt=()=>me("bun"),kn=()=>bt([{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"}),Cn=()=>bt([{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:yn.blackBright("* Installing dependencies from cache for a Remix app."),barColor:"blackBright"}),_i=async()=>{let e='export PATH="$HOME/.bun/bin:$PATH"',t=process.env.HOME;if(!t){m.error("Could not detect $HOME environment variable. Cannot update shell config.");return}let r=[Be.join(t,".zshrc"),Be.join(t,".bashrc"),Be.join(t,".bash_profile")];for(let n of r)try{if(await Ft.stat(n).then(()=>!0).catch(()=>!1)){(await Ft.readFile(n,"utf8")).includes(e)||(await Ft.appendFile(n,`
|
|
170
26
|
# Added by platform installer
|
|
171
27
|
${e}
|
|
172
|
-
`),
|
|
28
|
+
`),m.log(`Added Bun path to ${Be.basename(n)}`));return}}catch(o){m.error(`Failed to update ${n}: ${o.message}`)}m.warn("No shell config file (.zshrc, .bashrc, .bash_profile) found. Please add the following manually:"),m.log(yn.cyan(e))};v();import{existsSync as ze,mkdirSync as ea,readFileSync as ta,renameSync as ra,statSync as Rn,unlinkSync as na,writeFileSync as oa}from"fs";import{join as Ce}from"path";import{existsSync as Di}from"fs";import{join as Li}from"path";import Ue from"chalk";v();import Ht from"chalk";var q=e=>{let t=Math.max(...e.commands.map(o=>o.name.length)),r=e.commands.map(o=>{let s=" ".repeat(t-o.name.length+3);return` ${Ht.cyan(o.name)}${s}${o.description}`}),n=e.footer||'Run "<command> --help" for more information';return[Ht.cyan.bold(`
|
|
173
29
|
${e.title}
|
|
174
30
|
`),`Available commands:
|
|
175
|
-
`,...r,"",
|
|
31
|
+
`,...r,"",Ht.dim(`${n}
|
|
176
32
|
`)].join(`
|
|
177
|
-
`)};var
|
|
33
|
+
`)};var Mi=(e,t)=>t.some(r=>r.name()===e),ji=(e,t)=>t.pf?.commands?.[e]??null,Fi=(e,t)=>!!t.scripts?.[e],Wi=(e,t)=>t.cwd?Li(e,t.cwd):e,Hi=(e,t)=>t.command||e,Gi=(e,t,r,n)=>{let o=Wi(n,r),s=Hi(e,r);if(r.cwd&&!Di(o))return console.error(Ue.red(`
|
|
178
34
|
\u2716 Directory not found: ${o}
|
|
179
|
-
`)),!0;let i=r.cwd?
|
|
35
|
+
`)),!0;let i=r.cwd?Ue.dim(` in ${r.cwd}/`):"";return console.log(Ue.dim(`Running ${s}${i}`)),cn(s,t,{cwd:o}),!0},Bi=(e,t,r)=>(console.log(Ue.dim(`Running workspace script: ${e}`)),ye(e,{args:t,cwd:r}),!0);async function Ui(e,t,r){if(Mi(e,r))return!1;let n;try{n=d()}catch{return!1}let o=$(n);if(!o)return!1;let s=ji(e,o);return s?Gi(e,t,s,n):Fi(e,o)?Bi(e,t,n):!1}function xn(){let e;try{e=$()}catch{return{configured:[],scripts:[]}}if(!e)return{configured:[],scripts:[]};let t=Object.keys(e.pf?.commands??{}),n=Object.keys(e.scripts??{}).filter(o=>!t.includes(o));return{configured:t,scripts:n}}function Gt(){let{configured:e,scripts:t}=xn();return[...e,...t]}function wn(){let{configured:e,scripts:t}=xn(),r=[...e,...t];if(r.length===0)return"";let o=$()?.pf?.commands||{},s=r.map(i=>({name:i,description:o[i]?.description||Ve[i]||""}));return q({title:"Workspace Commands",commands:s,footer:""})}function Pn(e,t,r){let n=t.slice(2);if(n.length>0&&!n[0].startsWith("-")){let o=n[0],s=n.slice(1);if(o==="__workspace-commands"&&s.includes("--names-only")){let i=Gt();for(let a of i)console.log(a);return}Ui(o,s,r).then(i=>{i||e.parse(t)})}else e.parse(t)}import{existsSync as Bt,readdirSync as Ji}from"fs";import{dirname as Ki,join as bn}from"path";import{dirname as Vi}from"path";import{fileURLToPath as zi}from"url";var j=e=>Vi(zi(e));Rt();var qi=()=>typeof import.meta?.url=="string"?j(import.meta.url):typeof __dirname=="string"?__dirname:process.cwd(),G=e=>{let t=e??qi(),r=o=>Bt(bn(o,"package.json")),n=Ki(t);if(r(t))return t;if(t==="/")throw new Error("Could not find package.json (package root)");return G(n)},Sn=(e,t)=>{let r=e.find(Bt);if(!r)throw new Error(t??`Directory not found. Searched in: ${e.join(", ")}`);return r},En=async e=>{let{getWorkspacePathsConfig:t}=await Promise.resolve().then(()=>(v(),rn)),r=t(e);return[r.services,r.apps].flatMap(o=>{let s=bn(e,o);if(!Bt(s))return[];try{return Ji(s,{withFileTypes:!0}).filter(i=>i.isDirectory()&&i.name!==".gitkeep").map(i=>`${o}/${i.name}`)}catch{return[]}})};v();var Tn={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"},Ve={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"},$n=(e,t)=>t?`${e}:${t}`:e,Yi=()=>Object.entries(Tn).map(([e,t])=>$n(e,t)),Zi=()=>{try{let e=Gt(),r=$()?.pf?.commands||{},n=Object.keys(Tn);return e.filter(o=>!n.includes(o)).map(o=>{let s=r[o]?.description||Ve[o]||"";return $n(o,s)})}catch{return[]}},Xi=()=>{try{let e=d(),t=x(e),r=`${e}/${t.relativePath}/src`,{discoverEventTypes:n}=xt("@crossdelta/cloudevents");return n(r)}catch{return[]}},Qi=async()=>{try{let e=d();return await En(e)}catch{return[]}},Ut=async()=>({commands:[...Yi(),...Zi()],events:Xi(),services:await Qi()});var ve="node_modules/.cache/pf",ke="completion-cache";var sa=e=>{let t=E.version||"0.0.0",r=e.commands.join("|"),n=e.events.join("|"),o=e.services.join("|");return`${t} ${r} ${n} ${o}`},ia=e=>{let t=e.split(" ");if(t.length===4){let[o,s,i,a]=t;return{version:o,commands:s?s.split("|"):[],events:i?i.split("|"):[],services:a?a.split("|"):[]}}if(t.length===3){let[o,s,i]=t;return{version:o,commands:s?s.split("|"):[],events:i?i.split("|"):[],services:[]}}let[r,n]=t;return{commands:r?r.split("|"):[],events:n?n.split("|"):[],services:[]}},aa=e=>{let t=Ce(e,ve);return Ce(t,ke)},ca=(e,t=!1)=>{if(t)return!0;let r=aa(e);if(!ze(r))return!0;let n=ta(r,"utf-8").trim(),o=ia(n),s=E.version||"0.0.0";if(o.version!==s)return!0;let i=Ce(e,"package.json");if(!ze(i))return!1;let a=Rn(r).mtimeMs;return Rn(i).mtimeMs>a};var pa=(e,t)=>{let r=Ce(e,ve),n=Ce(r,ke),o=`${n}.tmp.${process.pid}`;ze(r)||ea(r,{recursive:!0});let s=sa(t);try{oa(o,s,"utf-8"),ra(o,n)}catch(i){try{ze(o)&&na(o)}catch{}throw i}},Je=async(e={})=>{let t;try{t=d()}catch{return!1}if(!t)return!1;if(!ca(t,e.force))return e.verbose&&console.log("[completion] Cache is up to date"),!1;let r=await Ut();return pa(t,r),e.verbose&&console.log(`[completion] Cache regenerated: ${r.commands.length} commands, ${r.events.length} events`),!0},xe=async(e={})=>{await Je({...e,force:!0})};import{existsSync as zt,readFileSync as _n,writeFileSync as Dn}from"fs";import{homedir as Ln}from"os";import{join as Vt}from"path";import Y from"chalk";var In=`${ve}/${ke}`,Nn=e=>`# ${e} completion (workspace-local cache)
|
|
180
36
|
# Generated: ${new Date().toISOString()}
|
|
181
37
|
|
|
182
38
|
# Cache file path (relative to workspace root)
|
|
183
|
-
_${e}_cache_path="${
|
|
39
|
+
_${e}_cache_path="${In}"
|
|
184
40
|
|
|
185
41
|
# Find workspace root (walk up to find monorepo package.json)
|
|
186
42
|
_${e}_find_workspace() {
|
|
@@ -307,11 +163,11 @@ _${e}_completions() {
|
|
|
307
163
|
esac
|
|
308
164
|
}
|
|
309
165
|
|
|
310
|
-
compdef _${e}_completions ${e}`,
|
|
166
|
+
compdef _${e}_completions ${e}`,An=e=>`# ${e} completion (workspace-local cache)
|
|
311
167
|
# Generated: ${new Date().toISOString()}
|
|
312
168
|
|
|
313
169
|
# Cache file path (relative to workspace root)
|
|
314
|
-
_${e}_cache_path="${
|
|
170
|
+
_${e}_cache_path="${In}"
|
|
315
171
|
|
|
316
172
|
# Find workspace root
|
|
317
173
|
_${e}_find_workspace() {
|
|
@@ -405,31 +261,60 @@ _${e}_completions() {
|
|
|
405
261
|
return 0
|
|
406
262
|
}
|
|
407
263
|
|
|
408
|
-
complete -F _${e}_completions ${e}`;var
|
|
264
|
+
complete -F _${e}_completions ${e}`;var la=(e,t)=>Vt(Ln(),`.${t}-completion.${e}`),Mn=e=>{let t=Ln();return e==="zsh"?Vt(t,".zshrc"):Vt(t,".bashrc")},ma=e=>`[[ -f "${e}" ]] && source "${e}"`,ua=(e,t)=>zt(e)?_n(e,"utf-8").includes(t):!1,da=(e,t)=>{let r=zt(e)?_n(e,"utf-8"):"",n=r.endsWith(`
|
|
409
265
|
`)?`${r}${t}
|
|
410
266
|
`:`${r}
|
|
411
267
|
${t}
|
|
412
|
-
`;
|
|
268
|
+
`;Dn(e,n,"utf-8")},ga=(e,t)=>{let r=la(e,t),n=e==="zsh"?Nn(t):An(t);return Dn(r,n,"utf-8"),r},On=(e,t,r)=>{let n=ga(e,t),o=Mn(e),s=ma(n);return ua(o,s)?(r&&console.log(Y.dim(`[${e}] Already configured in ${o}`)),!1):(da(o,s),r&&console.log(Y.green(`[${e}] Added source line to ${o}`)),!0)},fa=()=>(process.env.SHELL||"").includes("zsh")?"zsh":"bash",Jt=(e,t=!1)=>{let r=fa();t&&console.log(Y.cyan(`Installing ${r} completion...`)),On(r,e,t);let n=r==="zsh"?"bash":"zsh",o=Mn(n);zt(o)&&On(n,e,t),t&&(console.log(Y.green("\u2713 Shell completion installed")),console.log(Y.dim(` Run: ${Y.cyan("exec $SHELL")} to reload`)))};z();import{readdir as Jf}from"fs/promises";import{dirname as qf,join as Yf}from"path";import{fileURLToPath as Xf}from"url";import{runFlow as eh}from"@crossdelta/flowcore";var ha={debug:()=>{},info:console.log,warn:console.warn,error:console.error},jn=e=>e!==null&&typeof e=="object",Fn=e=>typeof e=="string"&&e.length>0,Wn=e=>typeof e=="string",Kt=e=>typeof e=="function",ya=(e,t)=>jn(e)?[!Fn(e.name)&&`commands[${t}]: missing or invalid 'name'`,!Wn(e.description)&&`commands[${t}]: missing or invalid 'description'`,!Array.isArray(e.args)&&`commands[${t}]: missing 'args' array`,!Array.isArray(e.options)&&`commands[${t}]: missing 'options' array`,!Kt(e.run)&&`commands[${t}]: missing 'run' function`].filter(r=>r!==!1):[`commands[${t}]: must be an object`];var Hn=e=>{if(!jn(e))return["Plugin must be an object"];let t=[!Fn(e.name)&&"Missing or invalid 'name'",!Wn(e.version)&&"Missing or invalid 'version'",!Array.isArray(e.commands)&&"Missing 'commands' array",!Array.isArray(e.flows)&&"Missing 'flows' array",!Kt(e.setup)&&"Missing 'setup' function"].filter(n=>n!==!1),r=Array.isArray(e.commands)?e.commands.flatMap((n,o)=>ya(n,o)):[];return[...t,...r]},Ke=(e,t=ha)=>({workspace:e,logger:t}),qe=async(e,t)=>{let{logger:r}=t;r.debug(`Loading plugin from module: ${e}`);let n=await import(e),o=n.createPfPlugin||n.default?.createPfPlugin;if(!Kt(o))throw new Error(`Module ${e} does not export createPfPlugin`);let s=o({contractsPath:t.workspace.contracts.path,contractsPackage:t.workspace.contracts.packageName,availableServices:t.workspace.availableServices}),i=Hn(s);if(i.length>0)throw new Error(`Plugin from ${e} does not conform to PfPlugin interface:
|
|
413
269
|
- ${i.join(`
|
|
414
|
-
- `)}`);let a=s;return r.debug(`Loaded plugin: ${a.name} v${a.version}`),await a.setup(t),{plugin:a,source:e}};import{deriveEventNames as
|
|
270
|
+
- `)}`);let a=s;return r.debug(`Loaded plugin: ${a.name} v${a.version}`),await a.setup(t),{plugin:a,source:e}};import{deriveEventNames as oh}from"@crossdelta/cloudevents";import{z as f}from"zod";var Ye=f.object({dependencies:f.record(f.string(),f.string()).default({}),envVars:f.array(f.object({key:f.string(),description:f.string(),required:f.boolean().default(!0)})).default([]),adapterFile:f.string().optional()}),va=f.object({push:f.string().optional(),email:f.string().optional(),slack:f.string().optional(),sms:f.string().optional()}).optional(),ka=f.object({defaults:va,providers:f.object({push:f.record(f.string(),Ye).optional(),email:f.record(f.string(),Ye).optional(),slack:f.record(f.string(),Ye).optional(),sms:f.record(f.string(),Ye).optional()}).optional()}),qd=f.object({notifier:ka.optional()});import{z as g}from"zod";var Ca=g.object({type:g.literal("event"),eventType:g.string(),stream:g.string().optional()}),xa=g.object({type:g.literal("http"),method:g.enum(["GET","POST","PUT","DELETE","PATCH"]).optional(),path:g.string().optional()}),Gn=g.discriminatedUnion("type",[Ca,xa]),wa=g.object({type:g.literal("emit.event"),eventType:g.string()}),Pa=g.object({type:g.literal("notify"),channel:g.enum(["push","email","slack","sms"]),provider:g.string().optional()}),ba=g.object({type:g.literal("call.http"),name:g.string().optional(),baseUrl:g.string().optional()}),Sa=g.object({type:g.literal("persist"),store:g.enum(["db","kv","cache"]),entity:g.string().optional()}),Bn=g.discriminatedUnion("type",[wa,Pa,ba,Sa]),Un=g.object({serviceName:g.string().regex(/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/),framework:g.enum(["hono","nest"]).default("hono"),triggers:g.array(Gn).min(1),actions:g.array(Bn).default([])});v();import{existsSync as X,mkdirSync as Da,readFileSync as qt,writeFileSync as we}from"fs";import{dirname as zn,join as Z}from"path";import{deriveEventNames as La}from"@crossdelta/cloudevents";var Ma=(e,t)=>{let r=`export * from './${t}'`;if(!X(e)){let s=zn(e);X(s)||Da(s,{recursive:!0});let i=`/**
|
|
271
|
+
* ${zn(e).split("/").pop()} Domain Events
|
|
272
|
+
*/
|
|
273
|
+
|
|
274
|
+
`;return we(e,`${i+r}
|
|
275
|
+
`,"utf-8"),!0}let n=qt(e,"utf-8");if(n.includes(`'./${t}'`))return!1;let o=`${n.trimEnd()}
|
|
276
|
+
${r}
|
|
277
|
+
`;return we(e,o,"utf-8"),!0},ja=(e,t)=>{let r=`export * from './${t}'`;if(!X(e))return we(e,`/**
|
|
278
|
+
* Event Contracts Index
|
|
279
|
+
*
|
|
280
|
+
* Re-exports all event contracts for convenient importing.
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
${r}
|
|
284
|
+
`,"utf-8"),!0;let o=qt(e,"utf-8").split(`
|
|
285
|
+
`);if(o.some(i=>i.trim()===r))return!1;let s=o.findLastIndex(i=>i.startsWith("export"));return s>=0?o.splice(s+1,0,r):o.push(r),we(e,o.join(`
|
|
286
|
+
`),"utf-8"),!0},Fa=e=>{if(!X(e))return!1;let t=qt(e,"utf-8"),r="export * from './events'";if(t.split(`
|
|
287
|
+
`).some(s=>s.trim()===r||s.trim().startsWith(r)))return!1;let o=t;return o=o.replace(/\/\/\s*export \* from '\.\/events'/,r),o=o.replace(/\/\/\s*export \* from '\.\/stream-policies'/,"export * from './stream-policies'"),/export \* from '\.\/events\/\w+\/\w+'/.test(o)&&(o=o.replace(/export \* from '\.\/events\/\w+\/\w+'\n?/g,"")),o.includes(r)||(o=`${o.trimEnd()}
|
|
288
|
+
${r}
|
|
289
|
+
`),o!==t?(we(e,o,"utf-8"),!0):!1},Jn=(e,t)=>{let{packagePath:r}=x(t),{domain:n,action:o}=La(e),s=Z(r,"src","events");if(!X(s))return!1;let i=Z(s,n),a=Z(i,"index.ts"),c=Z(s,"index.ts"),p=Z(r,"src","index.ts"),l=e.split(".")[0],u=Z(s,l);l!==n&&X(u)&&(console.warn(`\u26A0\uFE0F Warning: Legacy folder '${l}/' found. Please migrate to '${n}/' to avoid conflicts.`),console.warn(` Run: mv ${u} ${i}`));let T=!1;return Ma(a,o)&&(T=!0),ja(c,n)&&(T=!0),Fa(p)&&(T=!0),T};import{existsSync as Ze,readFileSync as Kn,writeFileSync as Wa}from"fs";import{join as Yt}from"path";import{getStreamName as Ha}from"@crossdelta/cloudevents";var Ga=(e,t)=>{let r=Yt(e,"src","index.ts");if(!Ze(r))return!1;let n=Kn(r,"utf-8"),o=t.toLowerCase();return new RegExp(`streams:\\s*\\[[^\\]]*['"]${t}['"]`).test(n)||n.includes(`stream: '${t}'`)?!0:new RegExp(`subjects:\\s*\\[.*['"]${o}\\.[*>]`).test(n)},Ba=e=>{if(e.includes("@crossdelta/cloudevents"))return e;let t=`import { consumeJetStreams } from '@crossdelta/cloudevents'
|
|
290
|
+
`,r=e.match(/import\s+['"]@crossdelta\/telemetry['"]\s*\n/);if(r){let o=(r.index??0)+r[0].length;return`${e.slice(0,o)}
|
|
291
|
+
${t}${e.slice(o)}`}let n=e.match(/import\s+.*\n/);if(n){let o=(n.index??0)+n[0].length;return e.slice(0,o)+t+e.slice(o)}return e},Ua=(e,t)=>`
|
|
292
|
+
|
|
293
|
+
// Consume from ${e} stream
|
|
294
|
+
consumeJetStreams({
|
|
295
|
+
streams: ['${e}'],
|
|
296
|
+
consumer: '${t}-service',
|
|
297
|
+
discover: './src/events/**/*.handler.ts',
|
|
298
|
+
})`,qn=(e,t)=>{let r=Ha(t),n=Yt(e,"src","index.ts"),o=Yt(e,"src","main.ts");if(!Ze(n)&&Ze(o))return{added:!1,streamName:r};if(!Ze(n))return{added:!1,streamName:r,warning:"Entry point not found (index.ts or main.ts)"};if(Ga(e,r))return{added:!1,streamName:r};let s=Kn(n,"utf-8"),i=e.split("/").pop()||"unknown";s.includes("consumeJetStreams")||(s=Ba(s));let a=Ua(r,i),c=`${s.trimEnd()+a}
|
|
299
|
+
`;return Wa(n,c,"utf-8"),{added:!0,streamName:r}};var Va=(e,t,r)=>{let{stream:n,servicePath:o}=e,s=o.startsWith("/")?o:`${t.workspace.workspaceRoot}/${o}`;if(r?.dryRun)return{success:!0,message:`Would wire stream ${n} to ${o}`,changes:[{type:"update",path:s,description:`Wire ${n} stream to service`,preview:`consumeJetStreams({ streams: ['${n.toUpperCase()}'], ... })`}]};let i=qn(s,`${n.toLowerCase()}.event`);return i.warning?(t.logger.warn(i.warning),{success:!1,message:i.warning}):i.added?(t.logger.info(`Wired stream ${i.streamName} to service`),{success:!0,message:`Wired stream ${i.streamName}`}):(t.logger.debug(`Stream ${i.streamName} already wired`),{success:!0,message:`Stream ${i.streamName} already configured`})},za=(e,t,r)=>{let{path:n,eventType:o}=e;if(r?.dryRun){let i=`
|
|
415
300
|
import { createContract } from '@crossdelta/cloudevents'
|
|
416
301
|
import { z } from 'zod'
|
|
417
302
|
|
|
418
|
-
export const ${
|
|
303
|
+
export const ${Zt(o)}Contract = createContract({
|
|
419
304
|
type: '${o}',
|
|
420
305
|
schema: z.object({ ... }),
|
|
421
306
|
})
|
|
422
|
-
`.trim();return{success:!0,message:`Would create contract ${o}`,changes:[{type:"create",path:n,description:`Create event contract for ${o}`,preview:i.slice(0,500)}]}}let s=
|
|
307
|
+
`.trim();return{success:!0,message:`Would create contract ${o}`,changes:[{type:"create",path:n,description:`Create event contract for ${o}`,preview:i.slice(0,500)}]}}let s=Jn(o,t.workspace.workspaceRoot);return s&&t.logger.debug(`Added export for ${o} to contracts index`),t.logger.debug(`Contract created: ${o} at ${n}`),{success:!0,message:s?`Contract ${o} created with exports`:`Contract ${o} created`}},Zt=e=>e.split(".").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(""),Ja=(e,t,r)=>{let{path:n,eventType:o,servicePath:s}=e;if(r?.dryRun){let i=`
|
|
423
308
|
import { handleEvent } from '@crossdelta/cloudevents'
|
|
424
|
-
import { ${
|
|
309
|
+
import { ${Zt(o)}Contract } from '@your-scope/contracts'
|
|
425
310
|
|
|
426
|
-
export default handleEvent(${
|
|
311
|
+
export default handleEvent(${Zt(o)}Contract, async (data) => {
|
|
427
312
|
console.log('Processing ${o}:', data)
|
|
428
313
|
// TODO: Implement handler logic
|
|
429
314
|
})
|
|
430
|
-
`.trim();return{success:!0,message:`Would create handler for ${o}`,changes:[{type:"create",path:n,description:`Create event handler for ${o}`,preview:i.slice(0,500)}]}}return t.logger.debug(`Handler created: ${o} at ${n} (service: ${s})`),{success:!0}}
|
|
315
|
+
`.trim();return{success:!0,message:`Would create handler for ${o}`,changes:[{type:"create",path:n,description:`Create event handler for ${o}`,preview:i.slice(0,500)}]}}return t.logger.debug(`Handler created: ${o} at ${n} (service: ${s})`),{success:!0}},Ka={"stream.wired":Va,"contract.created":za,"handler.created":Ja},Xt=(e,t,r)=>e.map(n=>{let o=Ka[n.kind];return o?o(n,t,r):(t.logger.warn(`Unknown effect kind: ${n.kind}`),{success:!1,message:`Unknown effect kind: ${n.kind}`})});import{join as rt}from"path";import{deriveEventNames as Mc}from"@crossdelta/cloudevents";var Qt=(e,t,r={})=>({ok:!0,operation:e,summary:t,artifacts:r.artifacts??[],changes:r.changes??[],diagnostics:r.diagnostics??[],next:r.next,data:r.data});v();import{join as tr}from"path";import{readFileSync as qa}from"fs";import{join as Ya}from"path";import Za from"handlebars";var Q=(e,t)=>Sn(e,t??`Templates directory not found. Searched in: ${e.join(", ")}`),er=(e,t={})=>{let r=qa(e,"utf-8");return Za.compile(r)(t)},Xe=e=>(t,r={})=>{let n=Ya(e,t);return er(n,r)};var D=e=>e.toUpperCase().replace(/-/g,"_");var Yn=e=>e.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ");var Xa=()=>typeof import.meta?.url=="string"?j(import.meta.url):typeof __dirname=="string"?__dirname:process.cwd(),Qa=()=>{let e=Xa(),t=G();return Q([tr(e,"templates","hono-microservice"),tr(e,"..","hono-microservice","templates"),tr(t,"bin","templates","hono-microservice")],"Hono templates directory not found.")},Qe=(e,t={})=>Xe(Qa())(e,t);function Zn(){return Qe("tsconfig.json.hbs")}function Xn(e="1.2.23"){return Qe("Dockerfile.hbs",{bunVersion:e})}function Qn(){return Qe("biome.json.hbs")}function eo(e,t=[]){return Qe("src/config/env.ts.hbs",{envKey:D(e),envVars:t})}var ec=e=>{let t=["import './config/env'","import '@crossdelta/telemetry'",""];return e&&t.push("import { consumeJetStreams, isConsumerConnected } from '@crossdelta/cloudevents'"),t.push("import { Hono } from 'hono'"),t},tc=(e,t)=>{let r=[`const port = Number(process.env.${e}_PORT) || 8080`,"const app = new Hono()","","app.get('/health', (c) => {"," return c.json({ status: 'ok' })","})"];return t&&r.push("","app.get('/health/ready', (c) => {"," const ready = isConsumerConnected()"," return c.json({ status: ready ? 'ok' : 'not-ready' }, ready ? 200 : 503)","})"),r},rc=(e,t)=>["","// Start NATS JetStream consumer","consumeJetStreams({",` streams: [${t.map(r=>`'${r}'`).join(", ")}],`,` consumer: '${e}',`," discover: './src/events/**/*.handler.ts',","})"],nc=()=>["","Bun.serve({"," port,"," fetch: app.fetch,","})","","console.log(`\u{1F680} Service ready at http://localhost:${port}`)"],oc=e=>{let t=D(e.serviceName);return`${[...ec(e.hasEvents),"",...tc(t,e.hasEvents),...e.hasEvents?rc(e.serviceName,e.streams):[],...nc()].join(`
|
|
431
316
|
`)}
|
|
432
|
-
`},
|
|
317
|
+
`},sc=e=>{let t={hono:"^4.6.14","@crossdelta/telemetry":"workspace:*",zod:"^4.1.0",[`${e.workspaceScope}/contracts`]:"workspace:*"};e.hasEvents&&(t["@crossdelta/cloudevents"]="workspace:*");let r={name:e.packageName,version:"0.0.1",type:"module",scripts:{"start:dev":"bun --watch src/index.ts",start:"bun src/index.ts",test:"bun test"},dependencies:t,devDependencies:{"@types/bun":"^1.2.23"}};return JSON.stringify(r,null,2)},ic=e=>`# ${e.serviceName}
|
|
433
318
|
|
|
434
319
|
## Development
|
|
435
320
|
|
|
@@ -449,7 +334,7 @@ ${e.hasEvents?`
|
|
|
449
334
|
This service consumes from:
|
|
450
335
|
${e.streams.map(t=>`- ${t}`).join(`
|
|
451
336
|
`)}`:""}
|
|
452
|
-
`,
|
|
337
|
+
`,ac=()=>"",to={name:"hono-bun",runtime:"bun",framework:"hono",files:[{path:"src/index.ts",content:oc},{path:"src/config/env.ts",content:e=>eo(e.serviceName,e.envVars)},{path:"package.json",content:sc},{path:"tsconfig.json",content:()=>Zn()},{path:"Dockerfile",content:()=>Xn()},{path:"biome.json",content:()=>Qn()},{path:"README.md",content:ic},{path:"src/events/.gitkeep",content:ac,skip:e=>!e.hasEvents}]};import{join as rr}from"path";var cc=()=>typeof import.meta?.url=="string"?j(import.meta.url):typeof __dirname=="string"?__dirname:process.cwd(),pc=()=>{let e=cc(),t=G();return Q([rr(e,"templates","nest-microservice"),rr(e,"..","nest-microservice","templates"),rr(t,"bin","templates","nest-microservice")],"NestJS templates directory not found.")},B=(e,t={})=>Xe(pc())(e,t);function ro(e,t=3e3){return B("src/main.ts.hbs",{serviceName:e,envKey:D(e),displayName:Yn(e),defaultPort:t})}function no(){return B("src/app.context.ts.hbs",{})}function oo(){return B("src/events/events.module.ts.hbs",{})}function so(e){return B("src/events/events.service.ts.hbs",{serviceName:e})}function io(e="24",t="1.2.23"){return B("Dockerfile.hbs",{nodeVersion:e,bunVersion:t})}function ao(){return B("biome.json.hbs",{})}function co(e,t=[]){return B("src/config/env.ts.hbs",{envKey:D(e),envVars:t})}var lc=e=>{let t={"@nestjs/common":"^11.0.0","@nestjs/core":"^11.0.0","@nestjs/platform-express":"^11.0.0","@crossdelta/telemetry":"workspace:*","reflect-metadata":"^0.2.0",rxjs:"^7.8.0",zod:"^4.1.0",[`${e.workspaceScope}/contracts`]:"workspace:*"};e.hasEvents&&(t["@crossdelta/cloudevents"]="workspace:*");let r={name:e.packageName,version:"0.0.1",scripts:{"start:dev":"bun --watch src/main.ts",start:"node dist/main.js",build:"tsc",test:"bun test"},dependencies:t,devDependencies:{"@nestjs/cli":"^11.0.0","@types/node":"^24.0.0",typescript:"^5.7.0"}};return JSON.stringify(r,null,2)},mc=()=>JSON.stringify({extends:"../../../../tsconfig.json",compilerOptions:{outDir:"./dist",rootDir:"./src",experimentalDecorators:!0,emitDecoratorMetadata:!0},include:["src/**/*"],exclude:["node_modules","dist","**/*.test.ts"]},null,2),uc=e=>{let t=["Module","HttpModule"],r=["HttpModule"];return e.hasEvents&&(t.push("OnModuleInit"),r.push("EventsModule")),`import { ${t.join(", ")} } from '@nestjs/common'
|
|
453
338
|
${e.hasEvents?"import { EventsModule } from './events/events.module'":""}
|
|
454
339
|
|
|
455
340
|
@Module({
|
|
@@ -462,7 +347,7 @@ export class AppModule${e.hasEvents?" implements OnModuleInit":""} {
|
|
|
462
347
|
// Events module initializes NATS consumer
|
|
463
348
|
}`:""}
|
|
464
349
|
}
|
|
465
|
-
`},
|
|
350
|
+
`},dc=()=>`import { Controller, Get } from '@nestjs/common'
|
|
466
351
|
|
|
467
352
|
@Controller()
|
|
468
353
|
export class AppController {
|
|
@@ -471,7 +356,7 @@ export class AppController {
|
|
|
471
356
|
return { status: 'ok' }
|
|
472
357
|
}
|
|
473
358
|
}
|
|
474
|
-
`,
|
|
359
|
+
`,gc=e=>`# ${e.serviceName}
|
|
475
360
|
|
|
476
361
|
## Development
|
|
477
362
|
|
|
@@ -491,8 +376,8 @@ ${e.hasEvents?`
|
|
|
491
376
|
This service consumes from:
|
|
492
377
|
${e.streams.map(t=>`- ${t}`).join(`
|
|
493
378
|
`)}`:""}
|
|
494
|
-
`,
|
|
495
|
-
`);for(let{pattern:s,description:i,code:a}of t){let c=new RegExp(s,"g");for(let
|
|
379
|
+
`,fc=()=>"",po={name:"nest",runtime:"node",framework:"nest",files:[{path:"src/config/env.ts",content:e=>co(e.serviceName,e.envVars)},{path:"src/main.ts",content:e=>ro(e.serviceName,e.port)},{path:"src/app.module.ts",content:uc},{path:"src/app.controller.ts",content:()=>dc()},{path:"src/app.context.ts",content:()=>no()},{path:"package.json",content:lc},{path:"tsconfig.json",content:()=>mc()},{path:"Dockerfile",content:()=>io()},{path:"biome.json",content:()=>ao()},{path:"README.md",content:gc},{path:"src/events/events.module.ts",content:()=>oo(),skip:e=>!e.hasEvents},{path:"src/events/events.service.ts",content:e=>so(e.serviceName),skip:e=>!e.hasEvents},{path:"src/events/handlers/.gitkeep",content:fc,skip:e=>!e.hasEvents}]};var lo=[to,po],mo=e=>{let t=hc(e),r=lo.find(n=>n.name===t);if(!r)throw new Error(`Template '${e}' not found. Available: ${lo.map(n=>n.name).join(", ")}`);return r},hc=e=>({"hono-micro":"hono-bun","nest-micro":"nest"})[e]||e;import{join as or}from"path";import{deriveEventNames as sr}from"@crossdelta/cloudevents";var uo={appliesTo:["src/domain","src/use-cases"],forbiddenPatterns:[{pattern:"console\\.(log|error|warn|info|debug)\\s*\\(",description:"console.* is forbidden in business logic (use structured logging)",code:"CONSOLE_IN_DOMAIN"},{pattern:"process\\.env\\b",description:"process.env is forbidden in business logic (use dependency injection)",code:"PROCESS_ENV_IN_DOMAIN"},{pattern:"\\bfetch\\s*\\(",description:"fetch() is forbidden in business logic (use adapters/services)",code:"FETCH_IN_DOMAIN"}]},Pe={hono:{businessLogicDir:"use-cases",eventsDir:"events",filePattern:"{name}.use-case.ts",suffix:"use-case",handlerDelegatesToBusinessLogic:!0,pathGuards:{forbidDirs:["src/services"]},codingConstraints:uo},nestjs:{businessLogicDir:"",eventsDir:"events",filePattern:"{name}.service.ts",suffix:"service",handlerDelegatesToBusinessLogic:!1,pathGuards:{forbidDirs:[]},codingConstraints:{appliesTo:["src/domain"],forbiddenPatterns:uo.forbiddenPatterns}}},yc=e=>e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase()),vc=(e,t)=>`../${e}/${t}`,ee=(e,t)=>{let r=Pe[e],n=r.filePattern.replace("{name}",t),o=n.replace(/\.ts$/,""),s=r.businessLogicDir?`src/${r.businessLogicDir}`:"src";return{filePath:s?`${s}/${n}`:`src/${n}`,dirPath:s,fileName:n,functionName:yc(t),delegateFromHandler:r.handlerDelegatesToBusinessLogic,importFromEvents:r.businessLogicDir?vc(r.businessLogicDir,o):`./${o}`}},nr=(e,t)=>{let n=`src/${Pe[e].eventsDir}`,o=`${t}.handler.ts`;return{filePath:`${n}/${o}`,dirPath:n,fileName:o}},be=e=>`handle-${e.replace(/\./g,"-")}`,et=e=>{let t=e.replace(/\\/g,"/");t=t.replace(/^\.\//,"").replace(/^\//,"");let r=t.split("/"),n=[];for(let o of r)o===".."?n.pop():o!=="."&&o!==""&&n.push(o);return n.join("/")},kc=(e,t)=>{let r=et(e);for(let n of t){let o=et(n);if(r.startsWith(`${o}/`)||r===o)return n}return null},Cc=(e,t)=>{let r=et(e);return t.some(n=>{let o=et(n);return r.startsWith(`${o}/`)||r===o})},xc=(e,t,r)=>{let n=[],o=e.split(`
|
|
380
|
+
`);for(let{pattern:s,description:i,code:a}of t){let c=new RegExp(s,"g");for(let p=0;p<o.length;p++)c.test(o[p])&&n.push({code:a,message:i,path:r,line:p+1}),c.lastIndex=0}return n},wc=(e,t)=>{let r=[],n=kc(e.path,t.pathGuards.forbidDirs);if(n&&r.push({code:"FORBIDDEN_DIR",message:`Path '${e.path}' is in forbidden directory '${n}'`,path:e.path}),Cc(e.path,t.codingConstraints.appliesTo)){let o=xc(e.content,t.codingConstraints.forbiddenPatterns,e.path);r.push(...o)}return r},tt=(e,t)=>{let r=Pe[e],n=[];for(let o of t)n.push(...wc(o,r));return{valid:n.length===0,violations:n}};var Sc=(e,t)=>t.map(r=>({kind:"file:write",path:or(e,r.path),content:r.content})),Ec=(e,t,r)=>({kind:"infra:add",serviceName:e,port:t,framework:r.framework,runtime:r.runtime}),Tc=(e,t)=>({kind:"env:add",key:`${e}_PORT`,value:t.toString()}),$c=(e,t)=>{let{typeName:r}=sr(e),n=be(e),o=ee("hono",n);return`import type { ${r} } from '${t}/contracts'
|
|
496
381
|
|
|
497
382
|
/**
|
|
498
383
|
* Handle ${e} event
|
|
@@ -504,7 +389,7 @@ export const ${o.functionName} = async (data: ${r}): Promise<void> => {
|
|
|
504
389
|
// TODO: Implement business logic
|
|
505
390
|
// Example: validate data, transform, call external services
|
|
506
391
|
}
|
|
507
|
-
`},
|
|
392
|
+
`},Rc=(e,t,r)=>{let{contractName:n,typeName:o}=sr(e),s=be(e),i=ee(r,s);return i.delegateFromHandler?`import { handleEvent } from '@crossdelta/cloudevents'
|
|
508
393
|
import { ${n}, type ${o} } from '${t}/contracts'
|
|
509
394
|
import { ${i.functionName} } from '${i.importFromEvents}'
|
|
510
395
|
|
|
@@ -519,13 +404,13 @@ export default handleEvent(${n}, async (data: ${o}) => {
|
|
|
519
404
|
console.log('\u{1F4E6} [${e}] Event received:', data)
|
|
520
405
|
// TODO: Inject and call service
|
|
521
406
|
})
|
|
522
|
-
`},
|
|
523
|
-
`):r.includes("connection refused")?"Cannot connect to NATS \u2014 is the container running?":
|
|
524
|
-
`):t},
|
|
525
|
-
\u2717 ${
|
|
526
|
-
`)),t;console.log(
|
|
407
|
+
`},Ic=(e,t,r)=>!t.hasEvents||t.events.length===0?[]:ee(r,"stub").delegateFromHandler?t.events.map(o=>{let s=be(o),i=ee(r,s);return{kind:"file:write",path:or(e,i.filePath),content:$c(o,t.workspaceScope)}}):[],Nc=(e,t,r)=>!t.hasEvents||t.events.length===0?[]:t.events.map(n=>{let{kebab:o}=sr(n),s=nr(r,o);return{kind:"file:write",path:or(e,s.filePath),content:Rc(n,t.workspaceScope,r)}}),Ac=e=>e==="hono"?"hono":e==="nest"?"nestjs":"hono",go=(e,t,r,n)=>{let o=Ac(n.framework),s=Sc(e,t),i=Ic(e,r,o),a=Nc(e,r,o),c=Ec(r.serviceName,r.port,n),p=Tc(r.envVarName,r.port);return[...s,...i,...a,c,p]};import{existsSync as Oc,readdirSync as _c,readFileSync as Dc}from"fs";import{join as fo}from"path";var ho=4001,Lc=e=>{let t=e.match(/ports\(\)\.(?:http|https|grpc|primary)\((\d+)\)/);if(t)return Number.parseInt(t[1],10);let r=e.match(/containerPort:\s*(\d+)/);return r?Number.parseInt(r[1],10):null},yo=e=>{try{let t=fo(e,"infra","services");return Oc(t)?_c(t).filter(n=>n.endsWith(".ts")).reduce((n,o)=>{let s=Dc(fo(t,o),"utf-8"),i=Lc(s);return i!==null&&n.add(i),n},new Set):new Set}catch(t){return console.warn("Failed to scan ports:",t),new Set}},ir=(e,t)=>e.has(t)?ir(e,t+1):t;var jc=e=>{if(!e||e.trim().length===0)throw new Error("Service name cannot be empty");if(!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e))throw new Error(`Service name '${e}' must be kebab-case (lowercase, alphanumeric, hyphens only)`)},Fc=(e,t,r)=>{if(t){if(t.startsWith("/"))return t;if(t.startsWith("."))return rt(r,t);if(t.includes("/"))return rt(r,t)}let n=I(r);return rt(r,n.services,e)},Wc=e=>[...new Set(e.map(t=>Mc(t).streamName))],Hc=(e,t,r,n)=>{let s=x(t).packageName.split("/")[0],i=e.events??[],a=i.length>0||e.hasEvents||!1,c=i.length>0?Wc(i):e.streams??[];return{serviceName:e.name,packageName:`${s}/${e.name}`,servicePath:r.replace(`${t}/`,""),port:n,envVarName:D(e.name),hasEvents:a,streams:c,events:i,workspaceScope:s,envVars:e.envVars}},Gc=(e,t)=>e.files.filter(r=>!r.skip?.(t)).map(r=>({path:r.path,content:r.content(t)})),Bc=(e,t,r)=>[...e.map(o=>({type:"file",path:rt(r,o.path),description:`Service file: ${o.path}`})),{type:"config",path:`infra/services/${t}.ts`,description:"Infrastructure configuration"},{type:"env",path:".env.local",description:"Environment variables"}],Uc=e=>[{command:`cd ${e} && bun dev`,description:"Start this service"},{command:"pf dev",description:"Start all services"}],vo=e=>{jc(e.name);let t=e.workspaceRoot??d(),r=Fc(e.name,e.path,t),n=e.port??ir(yo(t),ho),o=Hc(e,t,r,n),s=mo(e.type),i=Gc(s,o),a=go(r,i,o,s),c=Bc(i,e.name,r),p=Uc(r);return Qt("service.generate",`Generated ${e.name} service (port ${n})`,{artifacts:c,changes:a,next:p,data:{serviceName:e.name,servicePath:r,port:n,vars:o}})},ko=e=>{let t=vo(e);if(!t.ok||!t.data)throw new Error(t.summary);return{serviceName:t.data.serviceName,servicePath:t.data.servicePath,port:t.data.port,effects:t.changes,vars:t.data.vars}};v();v();v();import b from"chalk";import{execa as zc}from"execa";import{createJiti as Jc}from"jiti";var cr=async e=>{let{stdout:t}=await zc("sh",["-c",e]);return t.trim()},Co="pf-local-nats",Kc="2.10-alpine",qc=4222,Yc=8222,Zc=64*1024*1024,Xc={storage:"memory",retention:"limits",maxAge:36e5,maxBytes:Zc},Qc=e=>({clientPort:e.clientPort??qc,monitoringPort:e.monitoringPort??Yc,containerName:e.containerName??Co,version:e.version??Kc}),ep=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"],tp=e=>({containerName:e.containerName,clientUrl:`nats://localhost:${e.clientPort}`,monitoringUrl:`http://localhost:${e.monitoringPort}`}),rp=async()=>{try{return await cr("docker info"),!0}catch{return!1}},np=async e=>{try{return(await cr(`docker ps -q -f name=${e}`)).length>0}catch{return!1}};var op=async e=>{let t=ep(e);try{return await cr(`docker ${t.join(" ")}`),{success:!0,value:tp(e)}}catch{return{success:!1}}},sp=e=>{console.log(b.green("\u2713 NATS started")),console.log(b.dim(` Client: ${e.clientUrl}`)),console.log(b.dim(` Monitoring: ${e.monitoringUrl}`)),console.log(b.dim(" Streams: ephemeral, auto-created by services")),console.log("")},xo=async(e={})=>{let t=Qc(e);if(!await rp())return console.log(b.yellow("\u26A0\uFE0F Docker not available - skipping NATS (services may fail)")),!1;if(await np(t.containerName))return console.log(b.dim("\u2713 NATS already running")),!0;console.log(b.cyan("\u{1F680} Starting development infrastructure...")),console.log(b.dim(" NATS with JetStream (ephemeral)"));let r=await op(t);return r.success?(sp(r.value),!0):(console.error(b.red("\u2717 Failed to start NATS")),!1)},ip=e=>e.map(({stream:t,subjects:r})=>({stream:t,subjects:r,config:Xc})),ar="@crossdelta/infrastructure",wo=e=>e.includes(ar)&&(e.includes("is not defined by")||e.includes("Cannot find module")||e.includes("Cannot find package")),Po=e=>{if(typeof e!="object"||e===null)return null;let{message:t}=e;return typeof t=="string"?t:null},ap=e=>{let t=Po(e);if(t===null)return!0;if(wo(t))return!1;let r=t.toLowerCase();return!r.includes("insufficient storage")&&!r.includes("connection refused")},cp=e=>{let t=Po(e);if(t===null)return"Unknown error";let r=t.toLowerCase();return r.includes("insufficient storage")?["NATS has insufficient storage to create streams."," JetStream fixes its storage limit when the server starts, at 75% of the free space it"," sees then, and never recomputes it. So a disk that was full when the container started"," keeps the old limit even after you free space. Restart the container first:","",` docker restart ${Co}`," pf dev",""," If it still fails, the disk is full now as well:",""," docker system prune -af"].join(`
|
|
408
|
+
`):r.includes("connection refused")?"Cannot connect to NATS \u2014 is the container running?":wo(t)?[`${ar} is missing or too old to provide its /streams entry point.`,""," It is a peer dependency of this CLI, so neither `bun add -g` nor `npm i -g` installs it"," alongside pf, and bun reports nothing when it is absent. Install it explicitly:","",` bun add -g ${ar}`,""," Not continuing without it: letting the services create the streams instead leaves them in"," whatever shape they already had, so a corrected contract subject never takes effect and"," its events are dropped without an error."].join(`
|
|
409
|
+
`):t},pr=async e=>{try{let{ensureJetStreams:t}=await import("@crossdelta/cloudevents"),{indexPath:r}=x(e),o=await Jc(e,{moduleCache:!1}).import(r,{default:!0}),{collectStreamDefinitions:s}=await import("@crossdelta/infrastructure/streams"),i=s(o);if(i.length===0){console.log(b.dim(" No streams found in contracts"));return}let a=ip(i);await t({streams:a});let c=i.map(p=>p.stream);console.log(b.dim(` Ensured ${i.length} ephemeral stream(s): ${c.join(", ")}`))}catch(t){if(!ap(t))throw console.error(b.red(`
|
|
410
|
+
\u2717 ${cp(t)}
|
|
411
|
+
`)),t;console.log(b.yellow(` \u26A0\uFE0F Stream creation failed: ${t instanceof Error?t.message:"Unknown error"}`)),console.log(b.dim(" Streams will be created when services connect"))}};var bo=`// env: string literals \u2192 written to .env.local by generate-env (use for values meaningful locally)
|
|
527
412
|
// containerEnv: \u2192 only applied in the K8s container, never in .env.local
|
|
528
|
-
// (use for deployment-specific values like ORIGIN or NODE_OPTIONS)`;function
|
|
413
|
+
// (use for deployment-specific values like ORIGIN or NODE_OPTIONS)`;function So(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
529
414
|
import { ports } from '@crossdelta/infrastructure'
|
|
530
415
|
|
|
531
416
|
/**
|
|
@@ -534,7 +419,7 @@ import { ports } from '@crossdelta/infrastructure'
|
|
|
534
419
|
* Internal-only service - accessed via cluster DNS:
|
|
535
420
|
* http://${e}.{namespace}.svc.cluster.local:${t}
|
|
536
421
|
*/
|
|
537
|
-
${
|
|
422
|
+
${bo}
|
|
538
423
|
const config: K8sServiceConfig = {
|
|
539
424
|
name: '${e}',
|
|
540
425
|
ports: ports().http(${t}).build(),
|
|
@@ -547,7 +432,7 @@ const config: K8sServiceConfig = {
|
|
|
547
432
|
}
|
|
548
433
|
|
|
549
434
|
export default config
|
|
550
|
-
`}function
|
|
435
|
+
`}function Eo(e,t){return`import type { K8sServiceConfig } from '@crossdelta/infrastructure'
|
|
551
436
|
import { ports } from '@crossdelta/infrastructure'
|
|
552
437
|
|
|
553
438
|
/**
|
|
@@ -556,7 +441,7 @@ import { ports } from '@crossdelta/infrastructure'
|
|
|
556
441
|
* Internal-only service - accessed via cluster DNS:
|
|
557
442
|
* http://${e}.{namespace}.svc.cluster.local:${t}
|
|
558
443
|
*/
|
|
559
|
-
${
|
|
444
|
+
${bo}
|
|
560
445
|
const config: K8sServiceConfig = {
|
|
561
446
|
name: '${e}',
|
|
562
447
|
ports: ports().http(${t}).build(),
|
|
@@ -569,62 +454,41 @@ const config: K8sServiceConfig = {
|
|
|
569
454
|
}
|
|
570
455
|
|
|
571
456
|
export default config
|
|
572
|
-
`}
|
|
573
|
-
`))}};var
|
|
457
|
+
`}h();import U from"chalk";import lp from"terminal-link";var nt="integrations-run";import{z as P}from"zod";var pp=P.object({name:P.string(),description:P.string(),link:P.url().optional(),install:P.union([P.string(),P.array(P.string())]).transform(e=>Array.isArray(e)?e:[e]),installFlags:P.array(P.string()).optional(),run:P.array(P.string()).optional(),initial:P.boolean().optional(),interactive:P.boolean().optional()}),To=P.array(pp);var $o=e=>{try{return To.parse(e)}catch(t){throw new Error(t.issues.map(r=>` - Path ${r.path.join(". ")} : ${r.message}`).join(`
|
|
458
|
+
`))}};var N=()=>{try{let e=he("bin/integration.collection.json");return $o(e)}catch(e){throw new Error(`Failed to load integrations!
|
|
574
459
|
Check your integration.collection.json:
|
|
575
|
-
${e.message}`)}},
|
|
576
|
-
`))}))},
|
|
577
|
-
`),fn:()=>
|
|
578
|
-
`)),e.shouldInstallBun=await r.toggle({message:"Would you like to use Bun? (recommended)",initial:!0}),e.shouldInstallBun&&(e.packageManager="bun")}};import
|
|
460
|
+
${e.message}`)}},te=()=>N().reduce((t,r)=>(r.initial&&t.push(r.name),t),[]),mp=e=>!!e?.name&&!!e?.link&&!!e?.description,ot=e=>{let t=N();if(!t?.length||!e?.length)return;let r=e.map(n=>t.find(o=>o.name===n)).filter(mp);r.length&&(m.breakLine().log("\u{1F50C} Installed Integrations:"),r.forEach(({name:n,link:o,description:s})=>{let i=m.getStoredLogs(`${nt}:${n}`);o&&m.log(`${lp(U.cyan(n),o)} - ${s}`),i.length&&m.log(i.map(a=>` \u203A ${U.dim(a.message)}`).join(`
|
|
461
|
+
`))}))},up=e=>e.toUpperCase().replace(/-/g,"_"),Ro=(e,t)=>{let r=up(e);m.breakLine().log(U.bold("Environment variables:")).log(U.dim(" Local (.env.local):")).log(U.cyan(` ${r}_PORT=${t}`)).breakLine().log(U.dim(" Production (auto-injected by infra):")).log(U.cyan(` PORT=${t}`))};h();import Io from"chalk";var dp=e=>{let t=e.match(/^(@?[^@]+)@(.+)$/);return t?{name:t[1],version:t[2]}:{name:e,version:"latest"}},No=async e=>{let{selectedIntegrations:t,cwd:r,packageManager:n=w(),task:o}=e;if(!t?.length||!o)return;let s=gp(t,r,n,o);await Me(o,s)},gp=(e,t,r,n)=>{let s=N()?.filter(a=>e.includes(a.name))?.flatMap(a=>a.install.map(c=>{let{name:p,version:l}=dp(c);return{title:Io.cyanBright(`Adding ${c} (${a.name})`),fn:async()=>{We(`dependencies.${p}`,l,t)}}})),i={title:Io.cyanBright("Installing packages..."),fn:async()=>{await M({cwd:t,packageManager:r,task:n})}};return[...s??[],i]};h();import fp from"chalk";var Ao=async e=>{let{selectedIntegrations:t,cwd:r,task:n}=e;if(!t?.length||!n)return;let o=hp(t,r,n,e.packageManager);await Me(n,o)},hp=(e,t,r,n)=>N().filter(s=>e.includes(s.name)&&s.run?.length).flatMap(s=>(s.run||[]).map(i=>({title:fp.cyanBright(`Running "${i}" for ${s.name}
|
|
462
|
+
`),fn:()=>yp(s,i,t,r,n)}))),yp=async(e,t,r,n,o)=>{let s=`${nt}:${e.name}`;try{if(e.interactive)return dn(t,[],{cwd:r,context:s,task:n,manager:o});await jt(t,[],{cwd:r,task:n,context:s})}catch(i){m.error(`Failed to run command "${t}" for ${e.name}: ${i.message}`)}};import{ListrEnquirerPromptAdapter as Se}from"@listr2/prompt-adapter-enquirer";var y=e=>({select:async t=>e.prompt(Se).run({type:"select",message:t.message,choices:t.choices}),confirm:async t=>e.prompt(Se).run({type:"confirm",message:t.message,initial:t.initial??!1}),toggle:async t=>e.prompt(Se).run({type:"toggle",message:t.message,enabled:t.enabled??"Yes",disabled:t.disabled??"No",initial:t.initial??!1}),input:async t=>e.prompt(Se).run({type:"input",message:t.message,initial:t.initial,validate:t.validate}),multiSelect:async t=>e.prompt(Se).run({type:"MultiSelect",message:t.message,hint:t.hint,initial:t.initial,choices:t.choices})});h();import{readFileSync as oy}from"fs";import{join as iy}from"path";import hy from"chalk";import vy from"cli-table3";h();function st(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}async function Oo(e,t,r={},n=[],o=[]){if(!e){console.error("Subcommand is not defined.");return}let s=n.map(p=>t[p]).filter(p=>p!==void 0),i=o.map(p=>{let l=t[p];if(!(l===!1||l===void 0))return l===!0?`--${st(String(p))}`:`--${st(String(p))}=${String(l)}`}).filter(p=>p!==void 0),a=Object.entries(r).map(([p,l])=>{if(!(l===!1||l===void 0))return l===!0?`--${st(p)}`:`--${st(p)}=${String(l)}`}).filter(p=>p!==void 0),c=[...s,...i,...a].map(String);await e.parseAsync(c,{from:"user"})}import{basename as Hp}from"path";import Go from"chalk";v();var re={title:"Confirm creation",enabled:e=>!e.userConfirmed,task:async(e,t)=>{let r=y(t);if(e.userConfirmed=await r.toggle({initial:!0,message:"\u{1F680} Ready to launch your project?"}),!e.userConfirmed)throw new Error("Project creation was canceled by the user.")}};import{existsSync as lr,readdirSync as kp,readFileSync as Cp,writeFileSync as xp}from"fs";import{basename as wp,join as mr}from"path";var Pp=4001,bp=4e3;function Sp(e){let t=[],r=e.matchAll(/ports\(\)\.(?:http|https|grpc|primary)\((\d+)\)/g);for(let c of r)t.push(Number(c[1]));let n=e.matchAll(/\.add(?:Http|Grpc)?\((\d+)/g);for(let c of n)t.push(Number(c[1]));let o=e.match(/containerPort\s*:\s*(\d+)/);o&&t.push(Number(o[1]));let s=e.match(/internalPorts\s*:\s*\[([^\]]+)\]/);if(s){let c=s[1].match(/\d+/g);c&&t.push(...c.map(Number))}let i=e.match(/httpPort\s*:\s*(\d+)/);i&&t.push(Number(i[1]));let a=e.matchAll(/const\s+\w*[pP]ort\w*\s*=\s*(\d+)/g);for(let c of a)t.push(Number(c[1]));return t}function Ep(e,t){let r=t?Pp:bp,n=new Set;if(!lr(e))return r;let o=kp(e).filter(i=>i.endsWith(".ts"));for(let i of o){let a=mr(e,i);try{let c=Cp(a,"utf-8"),p=Sp(c);for(let l of p)n.add(l)}catch{}}let s=r;for(;n.has(s);)s++;return s}function Tp(e){return wp(e)}var it={title:"Creating infrastructure service config",task:async(e,t)=>{let r=Tp(e.projectName),n=d(),o=mr(n,"infra","services");if(!lr(o)){t.title="Skipping infra config (no infra/services directory found)";return}let s=mr(o,`${r}.ts`);if(lr(s)){t.title=`Service config already exists: infra/services/${r}.ts`;return}let i=Ep(o,!0);e.assignedPort=i;let a=e.serviceType==="hono"?So(r,i):Eo(r,i);xp(s,a),t.title=`Created infra/services/${r}.ts (port: ${i})`}};import{execSync as at}from"child_process";import{existsSync as $p}from"fs";import{join as Rp}from"path";var Ip=()=>{try{return at("git --version",{stdio:"ignore"}),!0}catch{return!1}},Np=e=>$p(Rp(e,".git")),_o={title:"Initializing git repository",enabled:()=>Ip(),skip:e=>Np(e.cwd)?"Already a git repository":!1,task:async(e,t)=>{try{at("git init",{cwd:e.cwd,stdio:"ignore"}),at("git add -A",{cwd:e.cwd,stdio:"ignore"}),at('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)"}}};import Do from"chalk";h();var ne={title:"Installing Bun",enabled:e=>!!e.shouldInstallBun&&!Wt(),task:async(e,t)=>R(t,async r=>{await vn(t),e.elapsedTime+=r(),t.title=`Bun installed successfully. (${e.elapsedTime}s)`})},oe={enabled:e=>!Wt()&&!e.shouldInstallBun&&!e.packageManager,task:async(e,t)=>{let r=y(t);console.log(["",`${Do.magenta.bold("Bun")} is a fast JavaScript runtime, package manager, bundler, and test runner: ${Do.underline("https://bun.sh")}`,kn(),Cn()].join(`
|
|
463
|
+
`)),e.shouldInstallBun=await r.toggle({message:"Would you like to use Bun? (recommended)",initial:!0}),e.shouldInstallBun&&(e.packageManager="bun")}};import Lo from"chalk";h();var ct={title:"Install integrations",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>R(t,async r=>{let{selectedIntegrations:n,cwd:o,packageManager:s}=e;await No({selectedIntegrations:n,packageManager:s,cwd:o,task:t}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1e3}},pt={title:"Select integrations",enabled:e=>e.selectedIntegrations.length===0,task:async(e,t)=>{let r=y(t);e.selectedIntegrations=await r.multiSelect({hint:"\\nPress <space> to select/deselect, <enter> to confirm, <i> to invert selection",message:"Which integrations would you like to include?",initial:te().map((n,o)=>o),choices:e.availableIntegrations.map(({name:n,description:o})=>({name:n,message:[Lo.bold(n),o].join(" - "),value:n}))}),!e.selectedIntegrations||e.selectedIntegrations.length===0?t.title="No integrations selected.":t.title=["Selected integrations:",...e.selectedIntegrations.map(n=>Lo.bold(`\u2022 ${n}`))].join("\\n")}};h();var Mo={title:"Install Nest CLI",task:async(e,t)=>R(t,async r=>{await un({packages:["@nestjs/cli"],task:t,cwd:e.cwd}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1e3}};h();var lt={title:"Install dependencies",task:async(e,t)=>R(t,async r=>{await M({cwd:e.cwd,task:t,packageManager:e.packageManager}),e.elapsedTime+=r()})};import Ap from"chalk";h();var se={enabled:e=>!e.removeDir&&!De(e.cwd),task:async(e,t)=>{let r=y(t);if(e.removeDir=await r.toggle({message:Ap.bold("\u26A0\uFE0F Overwrite existing directory?"),initial:!1}),!e.removeDir)throw new Error("Project creation was canceled by the user.")}},ie={enabled:e=>!!e.removeDir,task:async e=>Vr(e.cwd)};h();var mt={title:"Run integration commands",enabled:e=>e.selectedIntegrations.length>0,task:async(e,t)=>R(t,async r=>{let{selectedIntegrations:n,cwd:o}=e;await Ao({selectedIntegrations:n,cwd:o,task:t,packageManager:e.packageManager}),e.elapsedTime+=r()}),rendererOptions:{outputBar:1}};h();var Op=["services/my-hono-service","services/my-nest-service","my-platform"],ae={enabled:e=>e.skipInputPrompts||e.userConfirmed?!1:e.projectName?Op.includes(e.projectName):!0,task:async(e,t)=>{let r=y(t);e.projectName=await r.input({initial:e.projectName,message:"Enter project name",validate:n=>n?!0:"Project name is required."}),e.cwd&&(e.cwd=_(e.projectName))}};import jo from"chalk";var ce={title:"Select Package manager",task:async(e,t)=>{if(e.packageManager??=Mt(),e.packageManager){t.title=`Using ${jo.bold(e.packageManager)} as package manager.`;return}let r=y(t);e.packageManager=await r.select({message:"Which package manager would you like to use?",choices:mn().map(n=>({name:n,value:n}))}),t.title=`Using ${jo.bold(e.packageManager)} as package manager.`}};import ut from"chalk";var Fo={title:"GitHub repository owner",task:async(e,t)=>{if(e.githubOwner){t.title=`GitHub owner: ${ut.bold(e.githubOwner)}`;return}let r=y(t);e.githubOwner=await r.input({message:"Enter GitHub organization or username",initial:"my-org",validate:n=>n?.trim()?!0:"GitHub owner is required."}),t.title=`GitHub owner: ${ut.bold(e.githubOwner)}`}},Wo={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}let r=y(t);e.includeGitHubCI=await r.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 Ho={title:"Pulumi stack name",task:async(e,t)=>{if(e.pulumiStackBase){t.title=`Pulumi stack: ${ut.bold(e.pulumiStackBase)}`;return}let r=e.githubOwner||"myorg",n=e.projectName?.replace(/[^a-zA-Z0-9-]/g,"-")||"myproject",o=`${r}/${n}`,s=y(t);e.pulumiStackBase=await s.input({message:"Enter Pulumi stack base name (org/project)",initial:o,validate:i=>i?.trim()?i.includes("/")?!0:"Format should be org/project (e.g., myorg/myproject)":"Pulumi stack name is required."}),t.title=`Pulumi stack: ${ut.bold(e.pulumiStackBase)}`}};h();import{mkdirSync as _p,writeFileSync as Dp}from"fs";import{dirname as Lp}from"path";h();var Mp=e=>e==="hono"?"hono":"nestjs",jp=e=>{let t=Lp(e.path);_p(t,{recursive:!0}),Dp(e.path,e.content,"utf-8")},Fp=(e,t)=>{let r=e.map(o=>{let s=o.path.match(/services\/[^/]+\/(.+)$/);return{path:s?s[1]:o.path,content:o.content}}),n=tt(t,r);if(!n.valid){let o=n.violations.map(s=>` - ${s.code}: ${s.message} (${s.path})`).join(`
|
|
579
464
|
`);throw new Error(`Policy violation(s) detected:
|
|
580
|
-
${o}`)}e.forEach(
|
|
581
|
-
${
|
|
582
|
-
${se.bold(`cd ${e} && ${t} run start:dev`)}`).breakLine().log("Happy coding! \u{1F389}").breakLine()}});import _ from"chalk";v();import{spawnSync as $g}from"child_process";import{chmodSync as Ag,existsSync as rn,mkdirSync as Ig,readFileSync as Rg,writeFileSync as nn}from"fs";import{dirname as Ng,join as on}from"path";import{existsSync as Eg}from"fs";import{join as Gt}from"path";var Tg=()=>typeof import.meta?.url=="string"?W(import.meta.url):typeof __dirname=="string"?__dirname:process.cwd(),tn=()=>{let e=Tg(),t=ee();return fe([Gt(e,"templates","workspace"),Gt(e,"..","..","..","..","templates","workspace"),Gt(t,"bin","templates","workspace")],"Workspace templates directory not found.")},xi=()=>{let e=tn(),t=Gt(e,"packages","contracts");if(!Eg(t))throw new Error(`Contracts templates directory not found at: ${t}`);return t},Bt=(e,t)=>Gr(e,t);var wi=e=>{e.endsWith(".sh")&&Ag(e,493)},Fg=[{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:"services/.gitkeep",output:"services/.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/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:"CLAUDE.md",output:"CLAUDE.md",isStatic:!0},{template:".claude/rules/cloudevents.md",output:".claude/rules/cloudevents.md",isStatic:!0}],Pi={title:"Creating workspace structure",task:async(e,t)=>{if(rn(e.cwd)){t.title="Workspace directory already exists, skipping...";return}let r=tn(),n=e.includeGitHubCI??!0,o=e.packageManager||"bun",s=c=>{try{let m=$g(c,["--version"],{encoding:"utf-8",timeout:5e3}).stdout?.trim();if(m&&/^\d+\.\d+/.test(m))return`${c}@${m}`}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`},i={projectName:e.projectName,scope:`@${e.projectName}`,githubOwner:e.githubOwner||"",pulumiStackBase:e.pulumiStackBase||e.projectName,packageManager:o,packageManagerVersion:s(o)},a=Fg.filter(c=>!(c.isGitHubCI&&!n||c.forPackageManager&&c.forPackageManager!==o));for(let c of a){let l=on(e.cwd,c.output),p=Ng(l);if(rn(p)||Ig(p,{recursive:!0}),c.isStatic){let m=on(r,c.template);rn(m)?nn(l,Rg(m)):nn(l,""),wi(l)}else{let m=on(r,c.template),y=Bt(m,i);nn(l,y),wi(l)}}t.title="Workspace structure created"}};f();import{existsSync as bi,mkdirSync as Si,readFileSync as Og,writeFileSync as Mg}from"fs";import{join as Ut}from"path";import Dg from"chalk";var _g=()=>{let e=Ut(process.cwd(),"package.json");if(!bi(e))throw new Error("Root package.json not found. Please run this command from the workspace root.");let r=JSON.parse(Og(e,"utf-8")).name;if(!r)throw new Error('package.json must have a "name" field');return r.startsWith("@")?r:`@${r}`},jg=()=>{let e=_g(),{relativePath:t,packagePath:r}=x();if(bi(r))throw new Error(`${t} already exists. Remove it first if you want to regenerate.`);let n=xi(),o={scope:e,workspaceName:e.replace("@","").replace("/","-")};Si(r,{recursive:!0}),Si(Ut(r,"src","events"),{recursive:!0});let s=[{template:"package.json.hbs",output:"package.json"},{template:"tsconfig.json.hbs",output:"tsconfig.json"},{template:"tsup.config.ts",output:"tsup.config.ts"},{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 i of s){let a=Ut(n,i.template),c=Ut(r,i.output),l=Bt(a,o);Mg(c,l,"utf-8")}},Ei={title:"Initializing contracts package",task:(e,t)=>{let r=process.cwd();try{process.chdir(e.cwd),jg(),t.title="Contracts package initialized"}catch(n){throw t.title=Dg.red(`Contracts package failed: ${n.message}`),n}finally{process.chdir(r)}}};import Lg from"chalk";var Ti={title:"Registering shell completion",task:async(e,t)=>{let r=process.cwd();try{process.chdir(e.cwd),await He(),t.title="Shell completion registered"}catch{t.title=Lg.dim("Shell completion skipped")}finally{process.chdir(r)}}};var $i=J({name:"workspace",description:"Create a new workspace with infrastructure setup",arguments:[["[name]","Name or path of the workspace"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["-o, --github-owner <owner>","GitHub organization or username"],["-s, --pulumi-stack <name>","Pulumi stack base name (org/project)"],["--no-github","Skip GitHub CI/CD workflows"],["--remove-dir","Remove existing directory before creating (internal use)"]],exampleUsage:"pf new workspace my-platform -o my-org",buildContext:(e,t)=>{let r=(e.name??"my-platform").trim(),n=O(r),o=!!t.yes,s=t.packageManager??(o?b():void 0),i=t.packageManager==="bun",a=t.githubOwner??(o?"my-org":void 0),c=t.pulumiStack??(o?`${a}/${r}`:void 0),l=t.github===!1?!1:o?!0:void 0,p=!!e.name,m=t.removeDir||o;return{cwd:n,projectName:r,shouldInstallBun:i,packageManager:s,elapsedTime:0,userConfirmed:o,skipInputPrompts:p&&!o,removeDir:m,githubOwner:a,pulumiStackBase:c,includeGitHubCI:l}},prompts:[{enabled:e=>!e.userConfirmed,task:async(e,t)=>{try{let r=g();if(!await k(t).toggle({message:`\u26A0\uFE0F You are inside an existing workspace (${r}). Create a nested workspace anyway?`,initial:!1}))throw new Error("Workspace creation cancelled - already inside a workspace");t.title=_.yellow("Warning: Creating nested workspace")}catch(r){if(X(r)&&r.message?.includes("cancelled"))throw r;t.title="No existing workspace detected"}}},Pe,xe,hi,yi,vi,ke,Se,ve],actions:[we,Ce,Pi,Ei,jt,mi,Ti],onComplete:({projectName:e,includeGitHubCI:t})=>{d.breakLine().log(_.bold.green("Workspace created successfully!")),d.breakLine().log(_.bold("Next steps:")).log(` 1. ${_.cyan(`cd ${e}`)}`).log(` 2. ${_.cyan("exec $SHELL")} ${_.dim("(enable tab completion)")}`),t&&d.breakLine().log(_.bold("GitHub Setup:")).log(" Configure these secrets in your GitHub repository:").log(` \u2022 ${_.yellow("PULUMI_ACCESS_TOKEN")} - Pulumi Cloud access token`).log(` \u2022 ${_.yellow("DIGITALOCEAN_TOKEN")} - DigitalOcean API token`).log(` \u2022 ${_.yellow("NPM_TOKEN")} - (optional) NPM token for private packages`),d.breakLine().log(_.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&&d.log(" .github/").log(" \u251C\u2500\u2500 workflows/ # CI/CD workflows").log(" \u2514\u2500\u2500 actions/ # Custom actions"),d.breakLine().log("Happy coding! \u{1F389}").breakLine()}});var Ve=[{name:"Hono Microservice",value:"hono-micro",command:Ci,supportsAi:!0},{name:"Nest Microservice",value:"nest-micro",command:ki,supportsAi:!0},{name:"Workspace (Infrastructure)",value:"workspace",command:$i,supportsAi:!1}],Ai=()=>{let e=J({name:"new",description:"Create a new project",arguments:[["[type]","Type of the project (e.g., nest-micro, hono-micro, workspace)"]],exampleUsage:"platform new hono-micro test-service",buildContext:t=>({projectType:t.type??"",useAi:!1,aiDescription:"",elapsedTime:0,cwd:process.cwd()}),prompts:[{enabled:t=>!t.projectType,task:async(t,r)=>{let o=await k(r).select({message:"Select Project type",choices:Ve});t.projectType=Ve.find(s=>s.name===o)?.value||"",r.title=`Using ${q.bold(o)}`}},{enabled:t=>t.projectType!=="workspace"&&t.projectType!=="",task:async(t,r)=>{try{g(),r.title="Workspace detected"}catch{let n=["Not in a workspace directory","",`Current directory: ${process.cwd()}`,"","This command must be run from within a workspace created with pf new workspace","","To create a new workspace, run:",""," pf new workspace my-platform"].join(`
|
|
583
|
-
`);throw new Error(n)}}},{enabled:t=>t.projectType==="workspace",task:async(t,r)=>{try{let n=
|
|
584
|
-
\u{1F4E6} Contracts changed, updating streams...`),await
|
|
585
|
-
`),
|
|
465
|
+
${o}`)}e.forEach(jp)},Wp=async(e,t,r)=>{let{projectName:n,serviceType:o,hasEvents:s,streams:i}=e,a=n.split("/").pop()||n,p=ko({type:o==="hono"?"hono-micro":"nest",name:a,path:n,hasEvents:s,streams:i}),l=p.effects.filter(T=>T.kind==="file:write"),u=Mp(o);Fp(l,u),e.assignedPort=p.port,e.elapsedTime+=r(),t.title=`Generated ${a} (port ${p.port}, ${e.elapsedTime}s)`},dt={title:"Generating service",task:async(e,t)=>R(t,async r=>{await Wp(e,t,r)})};var Bo=L({name:"hono-micro",description:"Create a new Hono microservice with the Crossdelta setup.",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"],["--remove-dir","Remove existing directory before creating (used internally)"]],exampleUsage:"platform new hono-micro my-service",buildContext:async(e,t)=>{let r=(e.name??"my-hono-service").trim();!r.includes("/")&&!r.startsWith(".")&&(r=`${I().services}/${r}`);let n=_(r),o=t.packageManager??(t.yes&&w()),s=N(),i=t.yes?te():[],a=t.packageManager==="bun",c=!!t.yes||!!e.name&&e.name!=="my-hono-service";return{cwd:n,projectName:r,packageManager:o,shouldInstallBun:a,availableIntegrations:s,selectedIntegrations:i,serviceType:"hono",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[ae,se,oe,ce,pt,re],actions:[ie,ne,dt,it,ct,mt],onComplete:({projectName:e,packageManager:t,selectedIntegrations:r,assignedPort:n})=>{m.breakLine().log(Go.bold.green("Hono Microservice created successfully!")),ot(r),Ro(Hp(e),n??8080);let o=t??w();m.breakLine().log(`To start the project, run:
|
|
466
|
+
${Go.bold(`cd ${e} && ${o} run dev`)}`).breakLine().log("Happy shipping with Hono! \u26A1\uFE0F").breakLine()}});import Uo from"chalk";v();h();var Vo=L({name:"nest-micro",description:"Create a new NestJS microservice with the Crossdelta setup.",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"],["--remove-dir","Remove existing directory before creating (used internally)"]],exampleUsage:"platform new nest-micro my-service",buildContext:async(e,t)=>{let r=(e.name??"my-nest-service").trim();!r.includes("/")&&!r.startsWith(".")&&(r=`${I().services}/${r}`);let n=_(r),o=t.packageManager??(t.yes&&w()),s=t.packageManager==="bun",i=N(),a=t.yes?te():[],c=!!t.yes||!!e.name;return{cwd:n,projectName:r,shouldInstallBun:s,packageManager:o,availableIntegrations:i,selectedIntegrations:a,serviceType:"nest",elapsedTime:0,userConfirmed:!!t.yes,skipInputPrompts:c,removeDir:!!t.removeDir||!!t.yes}},prompts:[ae,se,oe,ce,pt,re],actions:[ie,ne,dt,it,lt,Mo,ct,mt],onComplete:({projectName:e,packageManager:t,selectedIntegrations:r})=>{m.breakLine().log(Uo.bold.green("NestJS Microservice created successfully!")),ot(r),m.breakLine().log(`To start the project, run:
|
|
467
|
+
${Uo.bold(`cd ${e} && ${t} run start:dev`)}`).breakLine().log("Happy coding! \u{1F389}").breakLine()}});import A from"chalk";h();import{spawnSync as Up}from"child_process";import{chmodSync as Vp,existsSync as gr,mkdirSync as zp,readFileSync as Jp,writeFileSync as fr}from"fs";import{dirname as Kp,join as hr}from"path";import{existsSync as Gp}from"fs";import{join as gt}from"path";var Bp=()=>typeof import.meta?.url=="string"?j(import.meta.url):typeof __dirname=="string"?__dirname:process.cwd(),dr=()=>{let e=Bp(),t=G();return Q([gt(e,"templates","workspace"),gt(e,"..","..","..","..","templates","workspace"),gt(t,"bin","templates","workspace")],"Workspace templates directory not found.")},zo=()=>{let e=dr(),t=gt(e,"packages","contracts");if(!Gp(t))throw new Error(`Contracts templates directory not found at: ${t}`);return t},ft=(e,t)=>er(e,t);var Jo=e=>{e.endsWith(".sh")&&Vp(e,493)},qp=[{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:"services/.gitkeep",output:"services/.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/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:"CLAUDE.md",output:"CLAUDE.md",isStatic:!0},{template:".claude/rules/cloudevents.md",output:".claude/rules/cloudevents.md",isStatic:!0}],Ko={title:"Creating workspace structure",task:async(e,t)=>{if(gr(e.cwd)){t.title="Workspace directory already exists, skipping...";return}let r=dr(),n=e.includeGitHubCI??!0,o=e.packageManager||"bun",s=c=>{try{let u=Up(c,["--version"],{encoding:"utf-8",timeout:5e3}).stdout?.trim();if(u&&/^\d+\.\d+/.test(u))return`${c}@${u}`}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`},i={projectName:e.projectName,scope:`@${e.projectName}`,githubOwner:e.githubOwner||"",pulumiStackBase:e.pulumiStackBase||e.projectName,packageManager:o,packageManagerVersion:s(o)},a=qp.filter(c=>!(c.isGitHubCI&&!n||c.forPackageManager&&c.forPackageManager!==o));for(let c of a){let p=hr(e.cwd,c.output),l=Kp(p);if(gr(l)||zp(l,{recursive:!0}),c.isStatic){let u=hr(r,c.template);gr(u)?fr(p,Jp(u)):fr(p,""),Jo(p)}else{let u=hr(r,c.template),T=ft(u,i);fr(p,T),Jo(p)}}t.title="Workspace structure created"}};import{spawnSync as Yp}from"child_process";import Zp from"chalk";var Xp=["bunx","@crossdelta/agent-kit","init"],Qp=([e,...t],r)=>{let n=Yp(e,t,{cwd:r,encoding:"utf-8"}),o=`${n.error?.message??""} ${n.stdout??""}${n.stderr??""}`.trim();return{exitCode:n.status??1,output:o}},el=(e,t=Qp)=>{let{exitCode:r,output:n}=t(Xp,e);if(r!==0)throw new Error(`agent-kit init failed (exit ${r}): ${n}`)},qo={title:"Installing agent skills and rules",task:(e,t)=>{try{el(e.cwd),t.title="Agent skills and rules installed"}catch(r){throw t.title=Zp.red(r.message),r}}};v();import{existsSync as Zo,mkdirSync as Yo,readFileSync as tl,writeFileSync as rl}from"fs";import{join as ht}from"path";import nl from"chalk";var ol=()=>{let e=ht(process.cwd(),"package.json");if(!Zo(e))throw new Error("Root package.json not found. Please run this command from the workspace root.");let r=JSON.parse(tl(e,"utf-8")).name;if(!r)throw new Error('package.json must have a "name" field');return r.startsWith("@")?r:`@${r}`},sl=()=>{let e=ol(),{relativePath:t,packagePath:r}=x();if(Zo(r))throw new Error(`${t} already exists. Remove it first if you want to regenerate.`);let n=zo(),o={scope:e,workspaceName:e.replace("@","").replace("/","-")};Yo(r,{recursive:!0}),Yo(ht(r,"src","events"),{recursive:!0});let s=[{template:"package.json.hbs",output:"package.json"},{template:"tsconfig.json.hbs",output:"tsconfig.json"},{template:"tsup.config.ts",output:"tsup.config.ts"},{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 i of s){let a=ht(n,i.template),c=ht(r,i.output),p=ft(a,o);rl(c,p,"utf-8")}},Xo={title:"Initializing contracts package",task:(e,t)=>{let r=process.cwd();try{process.chdir(e.cwd),sl(),t.title="Contracts package initialized"}catch(n){throw t.title=nl.red(`Contracts package failed: ${n.message}`),n}finally{process.chdir(r)}}};import il from"chalk";var Qo={title:"Registering shell completion",task:async(e,t)=>{let r=process.cwd();try{process.chdir(e.cwd),await xe(),t.title="Shell completion registered"}catch{t.title=il.dim("Shell completion skipped")}finally{process.chdir(r)}}};var es=L({name:"workspace",description:"Create a new workspace with infrastructure setup",arguments:[["[name]","Name or path of the workspace"]],options:[["-P, --package-manager <manager>","Specify the package manager (e.g., npm, yarn, pnpm, bun)"],["-y, --yes","Skip all prompts and use default values"],["-o, --github-owner <owner>","GitHub organization or username"],["-s, --pulumi-stack <name>","Pulumi stack base name (org/project)"],["--no-github","Skip GitHub CI/CD workflows"],["--remove-dir","Remove existing directory before creating (internal use)"]],exampleUsage:"pf new workspace my-platform -o my-org",buildContext:(e,t)=>{let r=(e.name??"my-platform").trim(),n=_(r),o=!!t.yes,s=t.packageManager??(o?w():void 0),i=t.packageManager==="bun",a=t.githubOwner??(o?"my-org":void 0),c=t.pulumiStack??(o?`${a}/${r}`:void 0),p=t.github===!1?!1:o?!0:void 0,l=!!e.name,u=t.removeDir||o;return{cwd:n,projectName:r,shouldInstallBun:i,packageManager:s,elapsedTime:0,userConfirmed:o,skipInputPrompts:l&&!o,removeDir:u,githubOwner:a,pulumiStackBase:c,includeGitHubCI:p}},prompts:[{enabled:e=>!e.userConfirmed,task:async(e,t)=>{try{let r=d();if(!await y(t).toggle({message:`\u26A0\uFE0F You are inside an existing workspace (${r}). Create a nested workspace anyway?`,initial:!1}))throw new Error("Workspace creation cancelled - already inside a workspace");t.title=A.yellow("Warning: Creating nested workspace")}catch(r){if(Ie(r)&&r.message?.includes("cancelled"))throw r;t.title="No existing workspace detected"}}},ae,se,Fo,Wo,Ho,oe,ce,re],actions:[ie,ne,Ko,Xo,lt,qo,_o,Qo],onComplete:({projectName:e,includeGitHubCI:t})=>{m.breakLine().log(A.bold.green("Workspace created successfully!")),m.breakLine().log(A.bold("Next steps:")).log(` 1. ${A.cyan(`cd ${e}`)}`).log(` 2. ${A.cyan("exec $SHELL")} ${A.dim("(enable tab completion)")}`),t&&m.breakLine().log(A.bold("GitHub Setup:")).log(" Configure these secrets in your GitHub repository:").log(` \u2022 ${A.yellow("PULUMI_ACCESS_TOKEN")} - Pulumi Cloud access token`).log(` \u2022 ${A.yellow("DIGITALOCEAN_TOKEN")} - DigitalOcean API token`).log(` \u2022 ${A.yellow("NPM_TOKEN")} - (optional) NPM token for private packages`),m.breakLine().log(A.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 yt=[{name:"Hono Microservice",value:"hono-micro",command:Bo},{name:"Nest Microservice",value:"nest-micro",command:Vo},{name:"Workspace (Infrastructure)",value:"workspace",command:es}],ts=()=>{let e=L({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??"",elapsedTime:0,cwd:process.cwd()}),prompts:[{enabled:t=>!t.projectType,task:async(t,r)=>{let o=await y(r).select({message:"Select Project type",choices:yt});t.projectType=yt.find(s=>s.name===o)?.value||"",r.title=`Using ${pe.bold(o)}`}},{enabled:t=>t.projectType!=="workspace"&&t.projectType!=="",task:async(t,r)=>{try{d(),r.title="Workspace detected"}catch{let n=["Not in a workspace directory","",`Current directory: ${process.cwd()}`,"","This command must be run from within a workspace created with pf new workspace","","To create a new workspace, run:",""," pf new workspace my-platform"].join(`
|
|
468
|
+
`);throw new Error(n)}}},{enabled:t=>t.projectType==="workspace",task:async(t,r)=>{try{let n=d();if(!await y(r).toggle({message:`\u26A0\uFE0F You are inside an existing workspace (${n}). Create a nested workspace anyway?`,initial:!1}))throw new Error("Workspace creation cancelled - already inside a workspace");r.title=pe.yellow("Warning: Creating nested workspace")}catch(n){if(Ie(n)&&n.message?.includes("cancelled"))throw n;r.title="No existing workspace detected"}}},{enabled:t=>!!t.projectType,task:async(t,r)=>{let o={"hono-micro":"services/my-hono-service","nest-micro":"services/my-nest-service",workspace:"my-platform"}[t.projectType]||"my-project",s=t.projectType==="workspace"?"\u{1F4E6} Workspace name:":"\u{1F4E6} Service path (e.g., services/my-service):",a=await y(r).input({message:s,initial:o});t.servicePath=a.trim(),r.title=`Path: ${pe.dim(a)}`}},{enabled:t=>{if(!t.servicePath)return!1;let r=_(t.servicePath);return!De(r)},task:async(t,r)=>{if(!await y(r).toggle({message:pe.bold("\u26A0\uFE0F Overwrite existing directory?"),initial:!1}))throw new Error("Project creation was canceled by the user.");t.shouldRemoveDir=!0,r.title=pe.yellow("Will overwrite existing directory")}},{title:"Confirm creation",enabled:t=>t.projectType!=="workspace",task:async(t,r)=>{if(!await y(r).toggle({message:"\u{1F680} Ready to launch your project?",initial:!0}))throw new Error("Project creation was canceled by the user.")}}],actions:[],onComplete:async t=>{yt.find(s=>s.value===t.projectType)||e.error(pe.red(`Project type ${t.projectType} is not supported.`));let r=e.commands.find(s=>s.name()===t.projectType),n={};t.projectType!=="workspace"&&(n.yes=!0);let o=[];t.servicePath&&o.push("servicePath"),t.shouldRemoveDir&&(n.removeDir=!0),await Oo(r,t,n,o)}});for(let t of yt)e.addCommand(t.command);return e};import{Command as vl}from"commander";h();import{createHash as al}from"crypto";import{existsSync as V,readdirSync as rs,readFileSync as ns,unlinkSync as cl,writeFileSync as pl}from"fs";import{join as F}from"path";import ll from"chokidar";v();h();var ml=e=>{let t=F(e,"infra","services");if(!V(t))return[];let r=rs(t).filter(a=>a.endsWith(".ts")&&a!=="index.ts").map(a=>a.replace(".ts","")),n=I(e),o=a=>{let c=F(e,a);return V(c)?rs(c).filter(p=>V(F(c,p,"package.json"))):[]},s=[...o(n.services),...o(n.apps)],i=r.filter(a=>!s.includes(a));for(let a of i)cl(F(t,`${a}.ts`));return i},os=".install-hash",ss=e=>{let t=ns(e);return al("sha256").update(t).digest("hex")},ul=e=>{let t=F(e,"node_modules",os),r=F(e,"bun.lock");return!V(r)||!V(t)?!0:ns(t,"utf-8")!==ss(r)},dl=e=>{let t=F(e,"bun.lock"),r=F(e,"node_modules",os);V(t)&&pl(r,ss(t),"utf-8")},yr=async e=>{let t=ml(e);t.length>0&&console.log(`\u{1F9F9} Cleaned ${t.length} orphaned infra config(s): ${t.join(", ")}`),ul(e)&&(await M({cwd:e,quiet:!0}),dl(e)),await ye("generate-env",{cwd:e})},vr=async e=>{await xo()&&await pr(e)},is=e=>{let{eventsPath:t}=x(e);if(!V(t))return async()=>{};let r=J(async()=>{console.log(`
|
|
469
|
+
\u{1F4E6} Contracts changed, updating streams...`),await pr(e)},500),n=ll.watch(`${t}/**/*.ts`,{ignoreInitial:!0,ignored:["**/index.ts","**/*.test.ts","**/*.spec.ts"]});return n.on("add",r).on("change",r),async()=>{await n.close()}};Ae();import cs from"chalk";v();le();var gl=["SIGINT","SIGTERM"],fl=[k.SUCCESS,k.GENERAL_ERROR,k.CANCELLED],hl=({code:e,signal:t})=>t?gl.includes(t)?k.SUCCESS:k.GENERAL_ERROR:e===null||fl.includes(e)?k.SUCCESS:e,as=e=>!e.isCurrentProcess||e.isRestarting||e.isShuttingDown?{action:"continue"}:{action:"shutdown",exitCode:hl(e)};var kr=e=>new Promise(t=>setTimeout(t,e)),ps=e=>process.stdout.write(`${e}
|
|
470
|
+
`),yl=()=>{process.stdout.write("\x1B[2J\x1B[3J\x1B[H"),process.stdout.isTTY&&process.stdout.write("\x1Bc")},ls=()=>({turboProcess:null,isRestarting:!1,isShuttingDown:!1}),ms=async(e,t,r,n)=>{let{dev:o}=fe(t),s=r.length>0?[...r]:o.filter,i=on(nn(".env.local",t),s,process.env.PORT);i.length>0&&(await pn(i),await kr(50));let a=s.flatMap(p=>["--filter",p]);ps(cs.cyan("\u{1F525} Starting services...")),ps(cs.dim(` Command: turbo run ${Pt} --continue${a.length?` ${a.join(" ")}`:""}`)),e.isShuttingDown=!1,e.isRestarting=!1;let c=sn("turbo",["run",Pt,"--continue","--no-daemon",...a],{cwd:t,envFile:".env.local",onExit:(p,l)=>{let u=as({code:p,signal:l,isRestarting:e.isRestarting,isShuttingDown:e.isShuttingDown,isCurrentProcess:e.turboProcess===c});u.action==="shutdown"&&n(u.exitCode)}});e.turboProcess=c},vt=async e=>{let t=e.turboProcess?.pid;if(t){e.isShuttingDown=!0;try{try{process.kill(-t,"SIGTERM")}catch{e.turboProcess?.kill("SIGTERM")}await kr(200);try{process.kill(-t,"SIGKILL")}catch{}await kr(30)}catch{}e.turboProcess=null,yl()}};var us=new vl("dev").description("Start development mode with auto-reload").option("-f, --filter <packages...>","Only start these workspace packages (e.g. @orderboss/website). Overrides pf.dev.filter, and narrows the ports freed on start so a second worktree does not kill the first one.").action(async e=>{let t=e.filter??[],r;try{r=d()}catch(u){O(u);return}let n=ls(),o,s,i=async(u=k.SUCCESS)=>{n.isShuttingDown||(console.log(`
|
|
471
|
+
\u{1F6D1} Shutting down...`),await vt(n),await Promise.all([o?.(),s?.()]),process.exit(u))},a=()=>ms(n,r,t,i),c=async()=>{await yr(r),await vr(r),await a()},l=J(async()=>{if(!(n.isRestarting||n.isShuttingDown)){n.isRestarting=!0,console.log(`
|
|
586
472
|
\u{1F504} Change detected, restarting...
|
|
587
|
-
`);try{await
|
|
588
|
-
\u{
|
|
589
|
-
|
|
590
|
-
`)}catch(l){await c?.(),await Vt(n),$(l)}});import Gi from"chalk";import{Command as au}from"commander";import{existsSync as qg,readFileSync as Yg,writeFileSync as Zg}from"fs";import Xg from"os";import Li from"path";import pn from"chalk";import{Command as Qg}from"commander";v();var{name:eu,publishConfig:tu}=R,ru=tu?.registry,nu=eu?.split("/")[0],GE=new Qg("token:set").description(pn.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)",nu).option("--registry <registry>","Registry URL",ru).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",()=>`${pn.cyan(`
|
|
473
|
+
`);try{await vt(n),await yr(r),await vr(r),await a()}catch(u){O(u)}finally{n.isRestarting=!1}}},300);process.removeAllListeners("SIGINT"),process.removeAllListeners("SIGTERM"),process.on("SIGINT",()=>i()),process.on("SIGTERM",()=>i());try{await c(),o=Dr(r,l),s=is(r),console.log(`
|
|
474
|
+
\u{1F440} Watching for changes...`),console.log(` Press Ctrl+C to exit
|
|
475
|
+
`)}catch(u){await Promise.all([o?.(),s?.()]),await vt(n),O(u)}});import hs from"chalk";import{Command as Nl}from"commander";import{existsSync as kl,readFileSync as Cl,writeFileSync as xl}from"fs";import wl from"os";import ds from"path";import Cr from"chalk";import{Command as Pl}from"commander";h();var{name:bl,publishConfig:Sl}=E,El=Sl?.registry,Tl=bl?.split("/")[0],EC=new Pl("token:set").description(Cr.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)",Tl).option("--registry <registry>","Registry URL",El).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)=>gs(e,t.scope||"",t.registry||"",t.local,t.force)).addHelpText("after",()=>`${Cr.cyan(`
|
|
591
476
|
Example:`)}
|
|
592
|
-
${
|
|
593
|
-
`)
|
|
594
|
-
//${n}/:_authToken=${e}`:`//${n}/:_authToken=${e}`},
|
|
595
|
-
`),
|
|
477
|
+
${Cr.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
478
|
+
`),$l=e=>e?ds.join(process.cwd(),".npmrc"):ds.join(wl.homedir(),".npmrc"),Rl=(e,t,r)=>{let n=new URL(r).host;return t?`${t}:registry=https://${n}
|
|
479
|
+
//${n}/:_authToken=${e}`:`//${n}/:_authToken=${e}`},Il=e=>kl(e)?Cl(e,"utf8"):"",xr=(e,t)=>xl(e,t),gs=(e,t,r,n=!1,o=!1)=>{let s=$l(n),i=Rl(e,t,r),a=new URL(r).host,c=Il(s),p=new RegExp(`//${a}/:_authToken=\\S+`);if(!c){xr(s,`${i}
|
|
480
|
+
`),m.success(`Created new .npmrc and set token for ${a}`);return}if(p.test(c)){if(!o){m.warn(`Token for ${a} already exists in ${s}. Use --force to overwrite.`);return}c=c.replace(p,i),xr(s,c),m.success(`Overwrote existing token for ${a} in ${s}`);return}c+=`
|
|
596
481
|
${i}
|
|
597
|
-
`,
|
|
482
|
+
`,xr(s,c),m.success(`Appended token for ${a} to ${s}`)},fs=(e,t)=>gs(e,t.scope||"",t.registry||"",t.local,t.force);var{name:Al,publishConfig:Ol}=E,_l=Ol?.registry,Dl=Al?.split("/")[0],wr=new Nl("token").description("Token management commands");wr.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)",Dl).option("--registry <registry>","Registry URL",_l).option("--local","Write token to a local .npmrc in the current directory",!1).option("--force","Force overwrite existing token if already present",!1).action(fs).addHelpText("after",()=>`${hs.cyan(`
|
|
598
483
|
Example:`)}
|
|
599
|
-
${
|
|
600
|
-
`);
|
|
601
|
-
`)),e}catch{return console.log(P.yellow(`Found corrupted configuration, starting fresh.
|
|
602
|
-
`)),null}}async function Cu(e,t){return console.log(P.dim(`
|
|
603
|
-
\u{1F4CB} Get your ${e} API key here:`)),console.log(P.cyan(` ${t}
|
|
604
|
-
`)),yu({message:`Enter your ${e} API key:`,mask:"*",validate:r=>r.trim()?r.length<10?"API key seems too short":!0:"API key cannot be empty"})}async function ku(e,t,r){let n=await zi({message:"Select model:",choices:e,default:t?.provider===r?t.model:void 0});return await Vi({message:"Enter a custom model ID instead?",default:!1})?hu({message:"Enter custom model ID:",default:n,validate:s=>s.trim()?!0:"Model ID cannot be empty"}):n}function Ji(e){return e.length<=12?"****":`${e.slice(0,4)}...${e.slice(-4)}`}function xu(e,t){console.log(P.green.bold(`
|
|
605
|
-
\u2705 AI configuration saved successfully!
|
|
606
|
-
`)),console.log(P.dim(`Configuration file: ${Q}`)),console.log(P.dim("API Key: Stored securely in system keychain")),console.log(P.dim(`Provider: ${e.provider}`)),console.log(P.dim(`Model: ${e.model}`)),console.log(P.dim(`API Key: ${Ji(t)}
|
|
607
|
-
`)),console.log(P.cyan("You can now use AI-powered service generation:")),console.log(P.dim(` pf new hono-micro services/my-service --ai
|
|
608
|
-
`))}async function wu(e){let t=await lt(e);if(t)return t;let r=Me(e);return process.env[r.defaultApiKeyEnvVar]??null}async function Ki(){console.log(P.cyan.bold(`
|
|
609
|
-
\u{1F916} AI Configuration Setup
|
|
610
|
-
`));let e=vu();try{let t=await zi({message:"Select AI provider:",choices:go(),default:e?.provider??ur.provider}),r=Me(t),n,o=await wu(t);o&&(console.log(P.green(`
|
|
611
|
-
\u2713 Found existing API key: ${Ji(o)}`)),await Vi({message:"Use this existing API key?",default:!0})&&(n=o)),n||(n=await Cu(r.name,r.apiKeyUrl)),console.log(P.dim(`
|
|
612
|
-
Fetching available models...`));let s;try{s=(await Ui(t,n)).models,console.log(P.green(`\u2713 Loaded ${s.length} models from ${r.name} API
|
|
613
|
-
`))}catch(c){console.error(P.red(`
|
|
614
|
-
\u274C Failed to fetch models: ${kn(c)}`)),console.log(P.yellow(`
|
|
615
|
-
Please check your API key and try again.
|
|
616
|
-
`)),process.exit(w.CONFIG_ERROR)}let i=await ku(s,e,t),a={provider:t,model:i.trim()};uo(a),await fo(t,n),xu(a,n)}catch(t){throw X(t)&&t.name==="ExitPromptError"&&(console.log(P.yellow(`
|
|
617
|
-
Setup cancelled.
|
|
618
|
-
`)),process.exit(w.CANCELLED)),t}}import{existsSync as mT,readFileSync as dT}from"fs";import{homedir as uT}from"os";import{join as hT}from"path";var gn=async(e,t=!1)=>{try{return _r(e,t),await He({verbose:t}),!0}catch{return!1}};var zt=e=>{let t=new Su("setup").description("Configure platform settings");return t.command("completion").description("Install shell autocompletion").option("--verbose","Enable verbose logging").addHelpText("after",`
|
|
484
|
+
${hs.bold("pf token set <token> --scope @my-workspace --registry https://npm.pkg.github.com")}
|
|
485
|
+
`);wr.action(()=>{let e=q({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 ys=wr;import br from"chalk";import{Command as Ml}from"commander";v();Ae();var DC={DEBUG:process.env.PF_DEBUG==="true"};import{existsSync as FC,readFileSync as WC}from"fs";import{homedir as GC}from"os";import{join as UC}from"path";var Pr=async(e,t=!1)=>{try{return Jt(e,t),await xe({verbose:t}),!0}catch{return!1}};var kt=e=>{let t=new Ml("setup").description("Configure platform settings");return t.command("completion").description("Install shell autocompletion").option("--verbose","Enable verbose logging").addHelpText("after",`
|
|
619
486
|
Examples:
|
|
620
487
|
$ pf setup completion
|
|
621
488
|
$ pf setup completion --verbose
|
|
622
|
-
`).action(async r=>{await
|
|
623
|
-
\u2714 Shell autocompletion installed!`)),console.log(
|
|
624
|
-
`)),console.log(
|
|
625
|
-
`)))}),t.
|
|
626
|
-
|
|
627
|
-
$
|
|
628
|
-
`).action(async()=>{await Ki()}),t.action(()=>{let r=ge({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(r)}),t},bu=zt("pf");z();f();import Tu from"chalk";import{Command as Yi}from"commander";import qi from"chalk";var Eu=e=>({debug:()=>{},info:e?()=>{}:t=>console.log(` ${t}`),warn:e?()=>{}:t=>console.log(qi.yellow(` ${t}`)),error:e?()=>{}:t=>console.error(qi.red(` ${t}`))}),fn=async e=>{let{command:t,args:r,options:n,context:o,silent:s=!1}=e,i=await t.run(r,n),a=i?.effects??[];if(a.length>0){let c={workspace:o.workspace,logger:Eu(s)};Wr(a,c)}if(!s&&i?.output){let c=Array.isArray(i.output)?i.output:[i.output];for(let l of c)console.log(l)}return{effects:a,output:i?.output}};var $u=e=>e.required?`<${e.name}>`:`[${e.name}]`,Au=(e,t)=>{e.argument($u(t),t.description)},Iu=(e,t)=>{t.default!==void 0?e.option(t.flags,t.description,t.default):e.option(t.flags,t.description)},Ru=(e,t)=>Object.fromEntries(e.args.map((r,n)=>[r.name,t[n]])),Nu=e=>e[e.length-2],Fu=(e,t)=>async(...r)=>{try{await fn({command:e,args:Ru(e,r),options:Nu(r),context:t})}catch(n){console.error(Tu.red(`Error executing ${e.name}:`),n instanceof Error?n.message:n),process.exit(1)}},Zi=(e,t)=>{let r=new Yi(e.name).description(e.description);return e.args.forEach(n=>{Au(r,n)}),e.options.forEach(n=>{Iu(r,n)}),r.action(Fu(e,t)),r},hn=(e,t,r,n)=>{let o=new Yi(e).description(t);return r.forEach(s=>{o.addCommand(Zi(s,n))}),o};wt();process.on("SIGINT",()=>{process.exit(w.CANCELLED)});process.on("unhandledRejection",e=>{throw Ye(e)&&process.exit(w.CANCELLED),e});process.on("uncaughtException",e=>{$(e)});var ze=new Mu,Xi=Object.keys(R.bin||{}),[vn="pf",yn]=Xi.length>0?Xi:["pf"],{description:Qi,version:_u,repository:ea,homepage:ju}=R,ta=Qi?.split(/ —|,|\./)[0]||Qi||"Platform CLI",na=ea?.url?`https://${ea.url.replace(/^(git\+|git@)/,"").replace(/\.git$/,"").replace(":","/")}`:null,ra=na||ju,Lu=na?"GitHub":"README",Wu=ra?[Je.bold(ta),`
|
|
629
|
-
|
|
630
|
-
`,Je.cyan("See more at: "),Je.bold(Du(Lu,String(ra)))].join(""):Je.bold(ta),Hu=[zt(vn),Ai(),ji,Bi,io],Gu=async()=>{try{let e=g(),t=Ie(e);if(!t.plugins?.length)return[];let r=x(e),n=Pt({workspaceRoot:e,availableServices:at(e),contracts:{path:`${r.relativePath}/src`,packageName:r.packageName}}),o=[];for(let s of t.plugins)try{let{plugin:i}=await St(s,n),a=hn(i.name,i.description??`Commands from ${i.name}`,i.commands,n);o.push(a)}catch(i){console.warn(`\u26A0\uFE0F Failed to load plugin '${s}':`,i.message)}return o}catch{return[]}},Bu=async()=>{let e=await Gu(),t=[...Hu,...e];ze.name(vn).description(Wu).version(_u||"0.0.1").helpCommand(!1).configureHelp({subcommandTerm:r=>Je.cyan(r.name())}).addHelpText("after",as),yn&&yn!==vn&&ze.alias(yn);for(let r of t)ze.addCommand(r);ze.command("__workspace-hash",{hidden:!0}).action(()=>{let r=process.cwd(),n=Math.abs(r.split("").reduce((o,s)=>(o<<5)-o+s.charCodeAt(0)|0,0));console.log(n)}),cs(ze,Ou,t)};Bu();
|
|
489
|
+
`).action(async r=>{await Pr(e,r.verbose),r.verbose||(console.log(br.green(`
|
|
490
|
+
\u2714 Shell autocompletion installed!`)),console.log(br.dim(` Restart your shell:
|
|
491
|
+
`)),console.log(br.cyan(` exec $SHELL
|
|
492
|
+
`)))}),t.action(()=>{let r=q({title:"\u2699\uFE0F Platform Setup",commands:[{name:"completion",description:"Install shell autocompletion"}],footer:'Run "pf setup <command> --help" for more information'});console.log(r)}),t},jl=kt("pf");z();v();import Wl from"chalk";import{Command as ks}from"commander";import vs from"chalk";var Fl=e=>({debug:()=>{},info:e?()=>{}:t=>console.log(` ${t}`),warn:e?()=>{}:t=>console.log(vs.yellow(` ${t}`)),error:e?()=>{}:t=>console.error(vs.red(` ${t}`))}),Sr=async e=>{let{command:t,args:r,options:n,context:o,silent:s=!1}=e,i=await t.run(r,n),a=i?.effects??[];if(a.length>0){let c={workspace:o.workspace,logger:Fl(s)};Xt(a,c)}if(!s&&i?.output){let c=Array.isArray(i.output)?i.output:[i.output];for(let p of c)console.log(p)}return{effects:a,output:i?.output}};var Hl=e=>e.required?`<${e.name}>`:`[${e.name}]`,Gl=(e,t)=>{e.argument(Hl(t),t.description)},Bl=(e,t)=>{t.default!==void 0?e.option(t.flags,t.description,t.default):e.option(t.flags,t.description)},Ul=(e,t)=>Object.fromEntries(e.args.map((r,n)=>[r.name,t[n]])),Vl=e=>e[e.length-2],zl=(e,t)=>async(...r)=>{try{await Sr({command:e,args:Ul(e,r),options:Vl(r),context:t})}catch(n){console.error(Wl.red(`Error executing ${e.name}:`),n instanceof Error?n.message:n),process.exit(1)}},Cs=(e,t)=>{let r=new ks(e.name).description(e.description);return e.args.forEach(n=>{Gl(r,n)}),e.options.forEach(n=>{Bl(r,n)}),r.action(zl(e,t)),r},Er=(e,t,r,n)=>{let o=new ks(e).description(t);return r.forEach(s=>{o.addCommand(Cs(s,n))}),o};Je();process.on("SIGINT",()=>{process.exit(k.CANCELLED)});process.on("unhandledRejection",e=>{throw Ne(e)&&process.exit(k.CANCELLED),e});process.on("uncaughtException",e=>{O(e)});var Ee=new Kl,xs=Object.keys(E.bin||{}),[$r="pf",Tr]=xs.length>0?xs:["pf"],{description:ws,version:Yl,repository:Ps,homepage:Zl}=E,bs=ws?.split(/ —|,|\./)[0]||ws||"Platform CLI",Es=Ps?.url?`https://${Ps.url.replace(/^(git\+|git@)/,"").replace(/\.git$/,"").replace(":","/")}`:null,Ss=Es||Zl,Xl=Es?"GitHub":"README",Ql=Ss?[Te.bold(bs),`
|
|
493
|
+
|
|
494
|
+
`,Te.cyan("See more at: "),Te.bold(ql(Xl,String(Ss)))].join(""):Te.bold(bs),em=[kt($r),ts(),us,ys,hn],tm=async()=>{try{let e=d(),t=fe(e);if(!t.plugins?.length)return[];let r=x(e),n=Ke({workspaceRoot:e,availableServices:He(e),contracts:{path:`${r.relativePath}/src`,packageName:r.packageName}}),o=[];for(let s of t.plugins)try{let{plugin:i}=await qe(s,n),a=Er(i.name,i.description??`Commands from ${i.name}`,i.commands,n);o.push(a)}catch(i){console.warn(`\u26A0\uFE0F Failed to load plugin '${s}':`,i.message)}return o}catch{return[]}},rm=async()=>{let e=await tm(),t=[...em,...e];Ee.name($r).description(Ql).version(Yl||"0.0.1").helpCommand(!1).configureHelp({subcommandTerm:r=>Te.cyan(r.name())}).addHelpText("after",wn),Tr&&Tr!==$r&&Ee.alias(Tr);for(let r of t)Ee.addCommand(r);Ee.command("__workspace-hash",{hidden:!0}).action(()=>{let r=process.cwd(),n=Math.abs(r.split("").reduce((o,s)=>(o<<5)-o+s.charCodeAt(0)|0,0));console.log(n)}),Pn(Ee,Jl,t)};rm();
|