@primno/cli
Version:
Command-line interface tool for initializing, building, and deploying Primno workspaces
2 lines (1 loc) • 23.3 kB
JavaScript
import{Command as e,Argument as t,program as n}from"commander";import r from"fs";import o from"path";import{a as i,g as s,b as a,c}from"./shared.mjs";import u from"node-plop";import l from"ora";import p from"@rollup/plugin-virtual";import{Observable as d,map as m}from"rxjs";import h from"@rollup/plugin-commonjs";import w from"@rollup/plugin-node-resolve";import f from"@rollup/plugin-typescript";import{rollup as g,watch as y}from"rollup";import b from"@rollup/plugin-terser";import{Listr as v}from"listr2";import k from"chalk";import S from"@rollup/plugin-babel";import E from"mustache";import{readFile as O}from"fs/promises";import{ConnectionString as N,ConnStringTokenProvider as P}from"@primno/dataverse-auth";import{DataverseClient as C}from"@primno/dataverse-client";import{spawnSync as I}from"child_process";import _ from"cors";import j from"express";import R from"https";import A from"http";import T from"selfsigned";import x from"open";import L from"process";import"url";const $="AuthType=OAuth;Url=<Url>;UserName=<UserName>;TokenCacheStorePath=./.cache/token.json",U="<set_solution_unique_name>",W=[{name:"dev",connectionString:$}],D={name:"name",version:"1.0.0",sourceRoot:"src",distDir:"dist",environment:"dev",serve:{https:!0,port:12357,certificate:{selfSigned:!0}},deploy:{solutionUniqueName:U,webResourceNameTemplate:"{{editorName}}_/js/{{projectName}}.js"},build:{moduleNameTemplate:"mn_{{projectName}}"}},M=l();class q{constructor(e,t){this.templateName=e,this.destinationDir=t}getActions(){}async run(e,t){const n=o.join(i(this.templateName),"plopfile.js"),r=(await u(n,{destBasePath:this.destinationDir,force:!1})).getGenerator(e);let s=[];null!=r.prompts&&(s=await r.runPrompts());const a=await r.runActions({...t,...s},{onComment:e=>{M.info(e),M.start()},onSuccess:e=>{M.succeed(` ${e.type} ${e.path}`),M.start()},onFailure:e=>{const t=[e.type,e.path,e.error||e.message].filter((e=>null!=e)).join(" ");M.fail(` ${t}`),M.start()}});if(M.stop(),a.failures.length>0)throw new Error("Failed to run template action")}}function F(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)}function B(e,...t){if(!t.length)return e;const n=t.shift();if(F(e)&&F(n))for(const t in n)F(n[t])?(e[t]||Object.assign(e,{[t]:{}}),B(e[t],n[t])):Object.assign(e,{[t]:n[t]});return B(e,...t)}var z,J;!function(e){e[e.Action=0]="Action",e[e.Observable=1]="Observable",e[e.Level=2]="Level",e[e.Root=3]="Root"}(z||(z={}));class G{constructor(e,t){this._concurrent=!1,this._exitOnError=!0,this._title=t,this._type=e}static newAction(e,t){const n=new G(z.Action,e);return n._action=t,n}static newObservable(e,t){const n=new G(z.Observable,e);return n._observable=t,n}static newLevel(e){return new G(z.Level,e)}static newRoot(){return new G(z.Root)}get type(){return this._type}set type(e){this._type=e}get title(){return this._title}set title(e){this._title=e}get action(){return this._action}get observable(){return this._observable}get concurrent(){return this._concurrent}set concurrent(e){this._concurrent=e}get exitOnError(){return this._exitOnError}set exitOnError(e){this._exitOnError=e}get persistentOutput(){return!0}}class X{constructor(e,t){this.taskInfo=e,this.parent=t,this.tasks=[]}static new(){return new X(G.newRoot())}addSubtasks(e){if(e.type!==z.Root)throw new Error("Only root tasks are supported");return this.tasks.push(...e.tasks),this}addTaskAsLevel(e,t){if(e.type!==z.Root)throw new Error("Only root tasks are supported");return e.taskInfo.type=z.Level,e.taskInfo.title=t,this.tasks.push(e),this}newLevel(e){const t=new X(G.newLevel(e),this);return this.tasks.push(t),t}newAction(e){return this.tasks.push(new X(G.newAction(e.title,e.action),this)),this}newActions(e){return e.forEach((e=>this.newAction(e))),this}newObservable(e,t){return this.tasks.push(new X(G.newObservable(e,t))),this}withConcurrency(e){return this.taskInfo.concurrent=e,this}endLevel(){if(!this.parent)throw new Error("This task has no parent");return this.parent}get type(){return this.taskInfo.type}getListRTask(){switch(this.type){case z.Action:return{title:this.taskInfo.title,task:async(e,t)=>{const n=this.taskInfo.action,r=(e=>{let t=e.task;for(;t.listr.parentTask;)t=t.listr.parentTask;return t})(t);try{const e=await n();if("string"!=typeof e||r.hasFailed())return e;t.output=e}catch(e){if(!r.hasFailed())throw e}},options:{persistentOutput:this.taskInfo.persistentOutput}};case z.Observable:return{title:this.taskInfo.title,task:(e,t)=>this.taskInfo.observable,options:{persistentOutput:this.taskInfo.persistentOutput}};case z.Level:case z.Root:const e=this.tasks.map((e=>e.getListRTask())).filter((e=>null!=e));return 0===e.length?null:this.type===z.Level?{title:this.taskInfo.title,task:(t,n)=>n.newListr(e,this.getListROptions())}:e}}getListROptions(){return{concurrent:this.taskInfo.concurrent,exitOnError:this.taskInfo.exitOnError}}getListR(){const e=this.getListRTask();if(null==e)throw new Error("An empty task can't be run");return new v(e,{rendererOptions:{formatOutput:"wrap",collapseErrors:!1,showErrorMessage:!0,showTimer:!0,collapse:!1,lazy:!0},...this.getListROptions()})}async run(){const e=this.getListR();await e.run()}}!function(e){e.Error="Error",e.Warning="Warning",e.Info="Info"}(J||(J={}));class H{constructor(e=!1){this._messages=[],this._showProgress=e}get messages(){return this._messages}get showProgress(){return this._showProgress}get startedOn(){return this._startedOn}get endOn(){return this._endOn}get hasErrors(){return this._messages.some((e=>e.type===J.Error))}addWarning(e){this.addMessage(e,J.Warning)}addInfo(e){this.addMessage(e,J.Info)}addError(e){this.addMessage(e,J.Error)}addMessage(e,t){this.messages.some((t=>t.message==e))||this.messages.push({message:e,type:t})}start(){this._messages=[],this._startedOn=new Date,this._endOn=void 0}end(){this._endOn=new Date}toString(){const e=this.messages.map((e=>`[${(e=>{switch(e){case J.Error:return k.red(e);case J.Warning:return k.yellow(e);case J.Info:return k.blue(e);default:return e}})(e.type)}] ${e.message}`)).join("\r\n");return this.showProgress?[k.gray(null==this.startedOn?"Waiting starting":`Starting at ${this.startedOn.toLocaleTimeString()}`),e,k.gray(null==this.endOn?"Waiting ending":`Ending at ${this.endOn.toLocaleTimeString()}`)].join("\r\n"):e}}function Z(e){if(e.loc?.file){const t=o.relative(".",e.loc.file);return`${e.message} from "${t}":${e.loc.line}:${e.loc.column}`}return`${e.message}`}function V(e){return t=>{const n=Z(t);e.addWarning(n)}}function K(e){return(t,n)=>{if(!("CIRCULAR_DEPENDENCY"===t.code&&t.ids?.at(0)?.includes("node_modules")||"THIS_IS_UNDEFINED"===t.code&&t.id?.includes("node_modules")))return e(t,n)}}class Y{constructor(e){const t=s(),n=[...Object.keys(t.dependencies||{}),...Object.keys(t.peerDependencies||{})];Array.isArray(e)||(e=[e]);const r=[b()];this.rollupOptions=e.map((e=>({input:{input:e.sourcePath,plugins:[w(),f({tsconfig:"./tsconfig.json",noEmitOnError:!1}),S({babelHelpers:"bundled",presets:[["@babel/preset-env",{useBuiltIns:"usage",corejs:3}]]}),h(),...e.production?r:[],...e.plugins??[]],external:n},output:{format:e.format,name:e.moduleName,file:e.destinationPath,sourcemap:!e.production&&"inline"}})))}async bundle(){let e;const t=new H(!1);try{t.start();for(const n of this.rollupOptions){const r=n.input;r.onwarn=K(V(t)),e=await g(r),await e.write(n.output)}}catch(e){t.addError(e.message)}finally{return t.end(),await(e?.close()),t}}watch(){return new d((e=>{let t;try{const n=new H(!0),r=this.rollupOptions.map((e=>({...e.input,output:e.output,onwarn:V(n)})));t=y(r),t.on("event",(t=>{switch(t.code){case"START":n.start();break;case"ERROR":{const e=Z(t.error);n.addError(e)}break;case"END":n.end()}e.next(n),"result"in t&&t.result&&t.result.close()}))}catch(t){e.error(new Error(`Watching error occurred: ${t}`))}finally{t?.close()}}))}}var Q,ee,te;function ne(e){const t=o.resolve(".",e.sourcePath).split(o.sep).join(o.posix.sep);switch(e.mode){case Q.primnoImportLocal:return`import * as primno from "@primno/core/dist/primno-d365.esm.js";\n export default primno;\n primno.initialize({\n config: ${JSON.stringify(e.config)}\n });`;case Q.primnoEmbedded:return`import * as primno from "@primno/core/dist/primno-d365.esm.js";\n export default primno;\n import * as esm from "${t}";\n primno.initialize({\n config: ${JSON.stringify(e.config)},\n esm\n });`;case Q.moduleOnly:return`export * from "${t}";`;default:throw new Error("Unknown mode")}}!function(e){e[e.primnoImportLocal=0]="primnoImportLocal",e[e.primnoEmbedded=1]="primnoEmbedded",e[e.moduleOnly=2]="moduleOnly"}(Q||(Q={}));class re{constructor(e){Array.isArray(e)||(e=[e]),this.options=e,this.bundler=new Y(e.map((e=>({production:e.production,moduleName:e.moduleName,destinationPath:e.destinationPath,sourcePath:"entry",plugins:[p({entry:ne({config:e.primnoConfig,sourcePath:e.sourcePath,mode:e.mode})})],format:e.mode===Q.moduleOnly?"esm":"umd"}))))}addModulesMessages(e){this.options.forEach((t=>{t.mode!==Q.primnoImportLocal&&e.addInfo(`External function prefix is ${t.moduleName}. Eg: Call ${t.moduleName}.onFormLoad to trigger the form load event.`)}))}async bundle(){const e=await this.bundler.bundle();return this.addModulesMessages(e),e}watch(){return this.bundler.watch().pipe(m((e=>(this.addModulesMessages(e),e))))}}class oe{constructor(e){this.client=e}async getByName(e){return(await this.client.retrieveMultipleRecords("solutions",{top:1,filters:[{conditions:[{attribute:"uniquename",operator:"eq",value:e}]}],select:["uniquename","solutionid"],expands:[{attribute:"publisherid",select:["customizationprefix"]}]})).entities[0]}async addSolutionComponent(e){return await this.client.executeAction("AddSolutionComponent",e)}}!function(e){e[e.WebResource=61]="WebResource"}(ee||(ee={})),function(e){e[e.HTML=1]="HTML",e[e.CSS=2]="CSS",e[e.JS=3]="JS",e[e.XML=4]="XML",e[e.PNG=5]="PNG",e[e.JPG=6]="JPG",e[e.GIF=7]="GIF",e[e.Silverlight=8]="Silverlight",e[e.XSL=9]="XSL",e[e.ICO=10]="ICO",e[e.SVG=11]="SVG",e[e.RESX=12]="RESX"}(te||(te={}));class ie{constructor(e){this.client=e}async createOrUpdate(e){try{const t=await this.findByName(e.name);if(null==t){return(await this.create(e)).webresourceid}if(e.content!==t.content)return e.webresourceid=t.webresourceid,await this.update(e),e.webresourceid}catch(e){throw new Error(`Web resource updating error: ${e}`)}}async create(e){return await this.client.createRecord("webresourceset",e)}async update(e){return await this.client.updateRecord("webresourceset",e.webresourceid,e)}async findByName(e){return(await this.client.retrieveMultipleRecords("webresourceset",{select:["webresourceid","name","webresourcetype","content","description","displayname"],filters:[{conditions:[{attribute:"name",operator:"eq",value:e}]}]})).entities[0]}}const se={};function ae(e,t){if(null==se[e]){const n=new P(e,{oAuth:{persistence:{serviceName:"primno-cli",accountName:"primno-cli"},deviceCodeCallback:e=>t(e.verificationUri,e.userCode)}});se[e]=new C(n)}return se[e]}class ce{constructor(e,t){if(this.sourcePath=e,this.config=t,null==t.environment?.connectionString||t.environment?.connectionString===$)throw new Error("Invalid connection string");if(null==t.solutionUniqueName||t.solutionUniqueName===U)throw new Error("Invalid solution name")}async deploy(){try{const e=ae(this.config.environment.connectionString,this.config.deviceCodeCallback),t=new oe(e),n=new ie(e),r=await t.getByName(this.config.solutionUniqueName);if(null==r)throw new Error("Solution not found");const o=this.getWebResourceName(r),i=await O(this.sourcePath,{encoding:"base64"}),s=await n.createOrUpdate({content:i,name:o,displayname:`${this.config.projectName} - ${o}`,description:"Web resource generated by Primno CLI",webresourcetype:te.JS,solutionid:r.solutionid});return null!=s&&await t.addSolutionComponent({ComponentId:s,ComponentType:ee.WebResource,DoNotIncludeSubcomponents:!1,AddRequiredComponents:!1,SolutionUniqueName:this.config.solutionUniqueName}),s}catch(e){throw new Error(`Unable to deploy ${this.sourcePath}: ${e.message}`)}}}class ue extends ce{constructor(e,t,n){super(e,n),this.entryPoint=t}getWebResourceName(e){if(null==e?.publisherid?.customizationprefix)throw new Error("Customization prefix not found");const t={editorName:e.publisherid.customizationprefix,projectName:this.config.projectName,entryPoint:this.entryPoint};return E.render(this.config.webResourcePathFormat,t)}}function le(e){return(e.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)??[]).map((e=>e.toLowerCase())).join("_")}class pe{constructor(e,t){if(this.config=t,!r.existsSync(e))throw new Error(`The source file of the entry point was not found: ${e}`);this._srcPath=e,this._name=o.basename(e,".entry.ts")}get name(){return this._name}get sourcePath(){return this._srcPath}get distributionPath(){return o.join(this.config.distDir,`${this.name}.js`)}static generatePrimnoConfig(e){const{port:t=12357,entryPointName:n,localImport:r}=e;return r?{moduleResolverConfig:{uri:`https://localhost:${t}/build/${n}.js`,type:"import"}}:{moduleResolverConfig:{type:"embedded"}}}async build(e){const t=pe.createBundlerOptions([this],e),n=new re(t);return await n.bundle()}static generateModuleName(e,t,n){const r={projectName:le(n.name),entryPoint:le(t)};return E.render(e,r)}static createBundlerOptions(e,t){return e.map((e=>({moduleName:pe.generateModuleName(e.config.build?.moduleNameTemplate,e.name,e.config),sourcePath:e.sourcePath,destinationPath:e.distributionPath,production:t.production,mode:t.mode,primnoConfig:pe.generatePrimnoConfig({localImport:t.mode===Q.primnoImportLocal,port:e.config.serve?.port,entryPointName:e.name})})))}async deploy(e){const{environment:t,deviceCodeCallback:n}=e,r=this.config.deploy;if(null==r)throw new Error("No deployment configuration");const o=new ue(this.distributionPath,this.name,{environment:t,solutionUniqueName:r.solutionUniqueName,webResourcePathFormat:r.webResourceNameTemplate,projectName:this.config.name,deviceCodeCallback:n});return await o.deploy()}watch(e){const t=e??{mode:Q.primnoEmbedded,production:!1},n=pe.createBundlerOptions([this],t);return new re(n).watch()}}class de{constructor(e){this.dirName=e}async spawn(...e){const t=await I("npm",e,{cwd:this.dirName,shell:!0});if(t.error)throw new Error(t.error.message);if(0!=t.stderr.byteLength){const e=t.stderr.toString().split("\n").filter((e=>e.includes("ERR!"))).join("\n");if(e.length>0)throw new Error(e)}}async install(e,t){t?.dev?await this.spawn("install",...e,"--save-dev"):await this.spawn("install",...e)}async link(e){await this.spawn("link",e)}}const me=30;function he(){const e=o.join("./.cache/","certs"),t=o.join(e,"self-signed.pem");let n=!1;if(n=r.existsSync(t),n){const e=864e5,o=r.statSync(t);((new Date).getTime()-o.ctime.getTime())/e>me&&(n=!1)}if(!n){r.mkdirSync(e,{recursive:!0});const n=T.generate([{name:"commonName",value:"localhost"},{name:"organizationName",value:"Dev"}],{algorithm:"sha256",days:me,keySize:2048,extensions:[{name:"basicConstraints",cA:!0},{name:"keyUsage",keyCertSign:!0,digitalSignature:!0,nonRepudiation:!0,keyEncipherment:!0,dataEncipherment:!0},{name:"extKeyUsage",serverAuth:!0,clientAuth:!0,codeSigning:!0,timeStamping:!0},{name:"subjectAltName",altNames:[{type:2,value:"localhost"},{type:2,value:"localhost.localdomain"},{type:2,value:"[::1]"},{type:7,ip:"127.0.0.1"},{type:7,ip:"fe80::1"}]}]});r.writeFileSync(t,n.private+n.cert,{encoding:"utf8"})}return{cert:r.readFileSync(t,{encoding:"utf8"}),regenerated:!n}}class we{constructor(e){this.config=e}async serve(e){if(null!=this.server)throw new Error("Server already started");const t=j();t.use(_()).use("/build",j.static(e)).get("/",((e,t)=>{t.send('<h1>Primno</h1><p>Development server is ready.</p><p>Navigate to the <a href="/redirect">D365 / Power Apps environment</a>.</p>')})).get("/redirect",((e,t)=>{t.redirect(this.config.environmentUrl)}));let n=!1;if(this.config?.https){const e={};if(this.config.certificate?.selfSigned){const t=he();e.cert=t.cert,e.key=t.cert,n=t.regenerated}else this.config.certificate?.pfx&&(e.pfx=r.readFileSync(this.config.certificate.pfx),e.passphrase=this.config.certificate.pfxPassword);this.server=R.createServer(e,t)}else this.server=A.createServer(t);try{await this.listen(this.config.port)}catch(e){if("EADDRINUSE"===e.code)throw new Error(`Port ${this.config.port} is already in use`);throw new Error(e.message)}return{directory:e,port:this.config.port,schema:this.config.https?"https":"http",newSelfSignedCert:n}}listen(e){return new Promise(((t,n)=>{this.server.on("error",(e=>n(e))).on("listening",(()=>t())).listen(e)}))}stop(){this.server?.close(),this.server=null}}class fe{constructor(e){this.options=e}async publish(){const e=ae(this.options.environment.connectionString,this.options.deviceCodeCallback),t={ParameterXml:`<importexportxml><webresources>${this.options.webResourcesId.map((e=>{return`<webresource>${t=e,t.replace(/[<>&'"]/g,(e=>{switch(e){case"<":return"<";case">":return">";case"&":return"&";case"'":return"'";case'"':return""";default:return""}}))}</webresource>`;var t})).join("")}</webresources></importexportxml>`};return await e.executeAction("PublishXml",t)}}class ge{constructor(e){this.dirPath=e,this._config=this.loadConfig(),this._environments=this.loadEnvironments(),this._entryPoint=new pe(o.join(e,this._config.sourceRoot,"app.entry.ts"),this._config)}get name(){return this.config.name}get config(){return this._config}get entryPoint(){return this._entryPoint}get environment(){return this._environments.find((e=>e.name==this.config.environment))}async build(e){await this.buildTask(e).run()}buildTask(e){return X.new().newAction({title:"Build",action:async()=>{const t=await this._entryPoint.build(e);if(t.hasErrors)throw new Error(t.toString());return t.toString()}}).withConcurrency(3)}async generate(e,t){const n=new q(e,this.dirPath);await n.run("new",{name:t})}async deploy(e){await this.deployTask(e).run()}deployTask(e){if(null==this.environment)throw new Error("Environment not found");const t=[];return X.new().withConcurrency(!1).addSubtasks(this.buildTask(e)).newAction({title:"Upload",action:()=>new d((e=>{this.entryPoint.deploy({environment:this.environment,deviceCodeCallback:(t,n)=>{e.next(`Device authentication required. Open ${t} and enter code ${n}`),x(t)}}).then((n=>{null!=n&&t.push(n),e.complete()})).catch((t=>e.error(t)))}))}).addSubtasks(this.publishTask({webResourcesId:t}))}publishTask(e){const{webResourcesId:t}=e;return X.new().newAction({title:"Publish",action:()=>new d((e=>{if(0==t.length)return void e.complete();new fe({webResourcesId:t,environment:this.environment,deviceCodeCallback:(t,n)=>{e.next(`Device authentication required. Open ${t} and enter code ${n}`),x(t)}}).publish().then((()=>e.complete())).catch((t=>e.error(t)))}))})}async watch(e){await this.watchTask(e).run()}watchTask(e){return X.new().newObservable("Watching",this.entryPoint.watch(e).pipe(m((e=>e.toString()))))}async start(e){await this.startTask(e).run()}startTask(e){return X.new().addTaskAsLevel(this.deployTask({production:!1,mode:Q.primnoImportLocal}),"Deploy").addSubtasks(this.serveTask({openInBrowser:e.openInBrowser})).addSubtasks(this.watchTask({mode:Q.moduleOnly,production:!1}))}serveTask(e){return X.new().newAction({title:"Serve",action:async()=>{const t=new we({...this.config.serve,environmentUrl:(n=this.environment?.connectionString,new N(n).serviceUri)});var n;const r=await t.serve(this.config.distDir),o=new H,i=`${r.schema}://localhost:${r.port}/`,s=`${i}redirect`;if(o.addInfo(`Serving on ${i}`),r.newSelfSignedCert&&o.addWarning("New self-signed certificate generated. Accept it in your browser."),e.openInBrowser)try{await x(s)}catch{o.addWarning(`Unable to open browser. Please open ${s} manually.`)}return o.toString()}})}loadConfig(){try{const e=r.readFileSync(o.join(this.dirPath,"primno.json"),"utf-8");return B(D,JSON.parse(e))}catch{throw new Error("Unable to load workspace configuration")}}loadEnvironments(){const e=r.readFileSync(o.join(this.dirPath,"primno.env.json"),"utf-8");return JSON.parse(e)??[]}static async create(e,t){const n=o.join(e,t);if(r.existsSync(n))throw new Error("The workspace already exists");let i={...D,name:t};const s=W,a=new q("workspace",n);await a.run("new",{name:t,workspaceConfig:JSON.stringify(i,null,2),environments:JSON.stringify(s,null,2)}),console.log("Installing packages ...");const c=new de(n);return await c.install(["tslib","@types/xrm","@primno/core","@primno/cli"],{dev:!0}),console.log("Packages installed"),new ge(n)}static isWorkspace(e){return r.existsSync(o.join(e,"primno.json"))}}const ye=new e("new").alias("n").argument("<name>","project name").description("create a new primno workspace.").action((async function(e){try{await ge.create(".",e)}catch(e){console.error(e.message)}}));const be=new e("start").alias("s").summary("start local development server").description("deploy primno in local development mode and run a web server that watches the source files for changes").option("--no-open","do not open the browser").action((async function(e){if(!ge.isWorkspace("."))return void console.error("This action must be run in a primno project directory");const t=new ge(".");await t.start({openInBrowser:e.open})}));const ve=new e("build").alias("b").summary("build workspace").option("-p, --production","production mode",!1).description("compile a primno workspace into a single file into the dist directory.").action((async function(e){if(!ge.isWorkspace("."))return void console.error("This action must be run in a primno project directory");const t=new ge(".");await t.build({production:e.production,mode:Q.primnoEmbedded})}));const ke=new e("watch").alias("w").description("build the workspace and rebuild on file changes").action((async function(){if(!ge.isWorkspace("."))return void console.error("This action must be run in a primno project directory");const e=new ge(".");await e.watch({mode:Q.primnoEmbedded,production:!1})}));const Se=new e("deploy").summary("build and deploy").description("build and deploy the workspace to a Power Apps / D365 web resource").option("-p, --production","production mode",!1).action((async function(e){if(!ge.isWorkspace("."))return void console.error("This action must be run in a primno project directory");const t=new ge(".");await t.deploy({production:e.production,mode:Q.primnoEmbedded})}));const Ee=new e("generate").alias("g").description("generate a new component (in alpha)").addArgument(new t("<type>","generator type.").choices(["component"])).argument("<name>",'name of the new component, can contain a path (e.g. "sales/order")').action((async function(e,t){try{if(!ge.isWorkspace("."))return void console.error("This action must be run in a primno project directory");const n=new ge(".");await n.generate(e,t)}catch(e){console.error(e.message)}})),Oe=s(a()),Ne=Oe.version;function Pe(e){n.name("mn").version(Oe.version).description(Oe.description).addCommand(be).addCommand(ye).addCommand(ve).addCommand(ke).addCommand(Se).addCommand(Ee).parseAsync(L.argv).catch((e=>{c(e.message),L.exitCode=1}))}export{Ne as VERSION,Pe as default};