@runium/cli 0.0.8 → 0.0.9

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/app.js CHANGED
@@ -1,6 +1,6 @@
1
- import{existsSync as c}from"node:fs";import{resolve as u}from"node:path";import{Command as v}from"commander";import{Container as o}from"typedi";import*as p from"./commands/index.js";import{CommandService as g,ConfigService as l,ProfileService as m,PluginService as h,ShutdownService as d,OutputService as S,OutputLevel as n,PluginContextService as f}from"./services/index.js";import{getVersion as P}from"./utils/index.js";const C=`\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
1
+ import{existsSync as c}from"node:fs";import{resolve as u}from"node:path";import{Command as v}from"commander";import{Container as o}from"typedi";import*as p from"./commands/index.js";import{CommandService as g,ConfigService as l,ProfileService as m,PluginService as d,ShutdownService as h,OutputService as S,OutputLevel as n,PluginContextService as f}from"./services/index.js";import{getVersion as P}from"./utils/index.js";const C=`\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
2
2
  \u2551 \u2554\u2550\u2557 \u2566 \u2566 \u2554\u2557\u2554 \u2566 \u2566 \u2566 \u2554\u2566\u2557 \u2551
3
3
  \u2551 \u2560\u2566\u255D \u2551 \u2551 \u2551\u2551\u2551 \u2551 \u2551 \u2551 \u2551\u2551\u2551 \u2551
4
4
  \u2551 \u2569\u255A\u2550 \u255A\u2550\u255D \u255D\u255A\u255D \u2569 \u255A\u2550\u255D \u2569 \u2569 \u2551
5
5
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
6
- One Tool to Run Them All!`;class A{program;commandService;configService;profileService;pluginService;shutdownService;outputService;pluginContextService;constructor(){this.program=new v("runium"),this.configService=o.get(l),this.profileService=o.get(m),this.pluginService=o.get(h),this.shutdownService=o.get(d),this.outputService=o.get(S),this.pluginContextService=o.get(f),this.commandService=o.get(g)}async start(){return await this.configService.init().catch(i=>{throw this.initOutput(),i}),await this.shutdownService.init(),await this.profileService.init(),await this.pluginContextService.init(),this.initOutput(),this.initEnv(),await this.loadPlugins(),await this.initProgram(),await this.initPlugins(),this.program.parseAsync()}async loadPlugins(){const i=this.profileService.getPlugins();for(const e of i)if(e.disabled!==!0)try{const t=this.pluginService.resolvePath(e.path,e.file);await this.pluginService.loadPlugin(t,e.options)}catch(t){this.outputService.error(`Failed to load plugin "${e.name}"`);const{code:r,message:s,payload:a}=t;this.outputService.debug("Error details:",{message:s,code:r,payload:a})}}async initProgram(){const i=this.program;i.option("-D, --debug","enable debug mode"),i.option("-E, --env [paths...]","load env files"),i.version(P()),i.description(C),i.on("option:debug",()=>{this.setDebugMode()}),i.on("option:env",e=>{this.loadEnvFiles([e])}),Object.values(p).forEach(e=>{this.commandService.registerCommand(e,i)})}initOutput(){(this.configService.get("output").debug||process.argv.includes("-D")||process.argv.includes("--debug"))&&this.setDebugMode()}setDebugMode(){this.outputService.getLevel()!==n.DEBUG&&(this.outputService.setLevel(n.DEBUG),this.outputService.debug("Debug mode enabled"))}initEnv(){const i=this.configService.get("env");i.path.length>0&&this.loadEnvFiles(i.path)}loadEnvFiles(i){for(const e of i){const t=u(e&&e.trim()||".env");c(t)?process.loadEnvFile(t):this.outputService.error(`Env file "${t}" not found`)}}async initPlugins(){const i=this.pluginService.getAllPlugins();for(const e of i){const t=e.app?.commands;if(t)for(const r of t)this.commandService.registerCommand(r,this.program,e.name)}await this.pluginService.runHook("app.afterInit",{profilePath:this.configService.get("profile").path})}}export{A as RuniumCliApp};
6
+ One Tool to Run Them All!`;class A{program;commandService;configService;profileService;pluginService;shutdownService;outputService;pluginContextService;constructor(){this.program=new v("runium"),this.configService=o.get(l),this.profileService=o.get(m),this.pluginService=o.get(d),this.shutdownService=o.get(h),this.outputService=o.get(S),this.pluginContextService=o.get(f),this.commandService=o.get(g)}async start(){return await this.configService.init().catch(i=>{throw this.initOutput(),i}),await this.shutdownService.init(),await this.profileService.init(),await this.pluginContextService.init(),this.initOutput(),this.initEnv(),await this.loadPlugins(),await this.initProgram(),await this.initPlugins(),this.program.parseAsync()}async loadPlugins(){const i=this.profileService.getPlugins();for(const e of i)if(e.disabled!==!0)try{const t=this.pluginService.resolvePath(e.path,e.file);await this.pluginService.loadPlugin(t,e.options)}catch(t){this.outputService.error(`Failed to load plugin "${e.name}"`);const{code:r,message:s,payload:a}=t;this.outputService.debug("Error details:",{message:s,code:r,payload:a})}}async initProgram(){const i=this.program;i.option("-D, --debug","enable debug mode"),i.option("-E, --env [paths...]","load env files"),i.version(P()),i.description(C),i.on("option:debug",()=>{this.setDebugMode()}),i.on("option:env",e=>{this.loadEnvFiles([e])}),Object.values(p).forEach(e=>{this.commandService.registerCommand(e,i)})}initOutput(){(this.configService.get("output").debug||process.argv.includes("-D")||process.argv.includes("--debug"))&&this.setDebugMode()}setDebugMode(){this.outputService.getLevel()!==n.DEBUG&&(this.outputService.setLevel(n.DEBUG),this.outputService.debug("Debug mode enabled"))}initEnv(){const i=this.configService.get("env");i.path.length>0&&this.loadEnvFiles(i.path)}loadEnvFiles(i){for(const e of i){const t=u(e&&e.trim()||".env");c(t)?(this.outputService.debug(`Loading env file "${t}"`),process.loadEnvFile(t)):this.outputService.error(`Env file "${t}" not found`)}}async initPlugins(){const i=this.pluginService.getAllPlugins();for(const e of i){const t=e.app?.commands;if(t)for(const r of t)this.commandService.registerCommand(r,this.program,e.name)}await this.pluginService.runHook("app.afterInit",{profilePath:this.configService.get("profile").path})}}export{A as RuniumCliApp};
@@ -1 +1 @@
1
- import{dirname as d}from"node:path";import{Option as j}from"commander";import{Container as u}from"typedi";import{ProjectEvent as h,RuniumError as m}from"@runium/core";import{ErrorCode as f}from"../../constants/index.js";import{ShutdownService as P}from"../../services/index.js";import{ProjectStateCommand as S}from"./project-state-command.js";class y extends S{shutdownService;fileWriter=null;constructor(t){super(t),this.shutdownService=u.get(P)}config(){this.command.name("start").description("start project").option("-f, --file","use file path instead of project name").option("-o, --output","output project state changes").addOption(new j("-w, --working-dir <choice>","set working directory").choices(["cwd","project"]).default("cwd")).argument("<name>","project name")}async handle(t,{file:s,workingDir:p,output:c}){const r=s?this.projectService.resolvePath(t):this.ensureProfileProject(t).path,i=this.getProjectDataFileName(s?r:t),e=this.profileService.getPath("projects",i),o=await this.readProjectData(e);if(o&&this.isProjectProcessStarted(o.pid))throw new m(`Project "${t}" is already started`,f.PROJECT_ALREADY_STARTED,{name:t});if(p==="project"){const n=d(r);n!==process.cwd()&&process.chdir(n)}const a=await this.projectService.initProject(r);this.shutdownService.addBlocker(n=>a.stop(n)),await this.fileService.ensureDirExists(d(e)),this.fileWriter=this.fileService.createAtomicWriter(e),this.addProjectListeners(a,{projectPath:r,output:c}),await this.projectService.runHook("project.beforeStart",a),await a.start()}addProjectListeners(t,s){const{projectPath:p,output:c}=s,r={id:t.getConfig().id,pid:process.pid,cwd:process.cwd(),path:p,state:{project:[],tasks:{}}},i=()=>{this.fileWriter.writeJson(r).then()};i(),t.on(h.STATE_CHANGE,async e=>{r.state.project.push(e),i(),c&&this.outputService.info("Project %s",e.status)}),t.on(h.TASK_STATE_CHANGE,(e,o)=>{r.state.tasks[e]||(r.state.tasks[e]=[]),r.state.tasks[e].push(o),i(),c&&this.outputService.info("Task %s %s %s",e,o.status,o.exitCode||o.error||"")})}}export{y as ProjectStartCommand};
1
+ import{dirname as h}from"node:path";import{Option as j}from"commander";import{Container as u}from"typedi";import{ProjectEvent as d,RuniumError as m}from"@runium/core";import{ErrorCode as f}from"../../constants/index.js";import{ShutdownService as P}from"../../services/index.js";import{ProjectStateCommand as S}from"./project-state-command.js";class x extends S{shutdownService;fileWriter=null;constructor(e){super(e),this.shutdownService=u.get(P)}config(){this.command.name("start").description("start project").option("-f, --file","use file path instead of project name").option("-o, --output","output project state changes").addOption(new j("-w, --working-dir <choice>","set working directory").choices(["cwd","project"]).default("cwd")).argument("<name>","project name")}async handle(e,{file:s,workingDir:p,output:c}){const o=s?this.projectService.resolvePath(e):this.ensureProfileProject(e).path,i=this.getProjectDataFileName(s?o:e),t=this.profileService.getPath("projects",i),r=await this.readProjectData(t);if(r&&this.isProjectProcessStarted(r.pid))throw new m(`Project "${e}" is already started`,f.PROJECT_ALREADY_STARTED,{name:e});if(p==="project"){const n=h(o);n!==process.cwd()&&process.chdir(n)}const a=await this.projectService.initProject(o);this.shutdownService.addBlocker(n=>a.stop(n)),await this.fileService.ensureDirExists(h(t)),this.fileWriter=this.fileService.createAtomicWriter(t),this.addProjectListeners(a,{projectPath:o,output:c}),await this.projectService.runHook("project.beforeStart",a),await a.start()}addProjectListeners(e,s){const{projectPath:p,output:c}=s,o={id:e.getConfig().id,pid:process.pid,cwd:process.cwd(),path:p,state:{project:[],tasks:{}}},i=()=>{this.fileWriter.writeJson(o).then()};i(),e.on(d.STATE_CHANGE,async t=>{o.state.project.push(t),i(),c&&this.outputService.info("Project %s",t.status)}),e.on(d.TASK_STATE_CHANGE,(t,r)=>{o.state.tasks[t]||(o.state.tasks[t]=[]),o.state.tasks[t].push(r),i(),c&&this.outputService.info("Task %s %s %s",t,r.status,r.exitCode||r.error||"")}),e.on(d.STATE_CHANGE,t=>{t.status==="stopped"&&t.reason==="action"&&this.shutdownService.shutdown("project-stop")})}}export{x as ProjectStartCommand};
@@ -1 +1 @@
1
- import{formatTimestamp as m}from"../../utils/index.js";import{ProjectStateCommand as S}from"./project-state-command.js";class D extends S{config(){this.command.name("status").description("get project status").option("-f, --file","use file path instead of project name").option("-t, --tasks","show tasks status").option("-a, --all","show status change history").argument("<name>","project name")}async handle(o,{file:p,tasks:l,all:c}){const d=p?this.projectService.resolvePath(o):this.ensureProfileProject(o).path,f=this.getProjectDataFileName(p?d:o),j=this.profileService.getPath("projects",f),r=await this.readProjectData(j);if(r){let{project:s=[]}=r.state;if(c||(s=s.length>0?[s[s.length-1]]:[]),l){const n=s.map(t=>({name:"Project",status:t.status,time:m(t.timestamp),timestamp:t.timestamp,reason:t.reason||""})),{tasks:i=[]}=r.state,h=[];Object.entries(i).forEach(([t,e])=>{c||(e=e.length>0?[e[e.length-1]]:[]),e.forEach(a=>{h.push({name:t,status:a.status,time:m(a.timestamp),timestamp:a.timestamp,reason:[a.reason,a.exitCode].filter(Boolean).join(" ")})})});const u=[...n,...h];u.sort((t,e)=>t.timestamp-e.timestamp),this.outputService.table(u,["time","name","status","reason"])}else{const n=s.map(i=>({status:i.status,time:m(i.timestamp)}));this.outputService.table(n,["time","status"])}}else this.outputService.info(`No project status for "${o}"`)}}export{D as ProjectStatusCommand};
1
+ import{SILENT_EXIT_CODE as g}from"@runium/core";import{formatTimestamp as m}from"../../utils/index.js";import{ProjectStateCommand as P}from"./project-state-command.js";class E extends P{config(){this.command.name("status").description("get project status").option("-f, --file","use file path instead of project name").option("-t, --tasks","show tasks status").option("-a, --all","show status change history").argument("<name>","project name")}async handle(a,{file:p,tasks:d,all:c}){const l=p?this.projectService.resolvePath(a):this.ensureProfileProject(a).path,f=this.getProjectDataFileName(p?l:a),j=this.profileService.getPath("projects",f),r=await this.readProjectData(j);if(r){let{project:o=[]}=r.state;if(c||(o=o.length>0?[o[o.length-1]]:[]),d){const n=o.map(t=>({name:"Project",status:t.status,time:m(t.timestamp),timestamp:t.timestamp,reason:t.reason||""})),{tasks:i=[]}=r.state,h=[];Object.entries(i).forEach(([t,e])=>{c||(e=e.length>0?[e[e.length-1]]:[]),e.forEach(s=>{const S=s.exitCode&&s.exitCode!==g?s.exitCode:"";h.push({name:t,status:s.status,time:m(s.timestamp),timestamp:s.timestamp,reason:[s.reason,S].filter(Boolean).join(" ")})})});const u=[...n,...h];u.sort((t,e)=>t.timestamp-e.timestamp),this.outputService.table(u,["time","name","status","reason"])}else{const n=o.map(i=>({status:i.status,time:m(i.timestamp)}));this.outputService.table(n,["time","status"])}}else this.outputService.info(`No project status for "${a}"`)}}export{E as ProjectStatusCommand};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runium/cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Runium CLI",
5
5
  "author": "TheBeastApp",
6
6
  "license": "MIT",