@runium/plugin-task-manager 0.0.1
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/commands/task-command.js +1 -0
- package/commands/task-restart.js +1 -0
- package/commands/task-start.js +1 -0
- package/commands/task-status.js +1 -0
- package/commands/task-stop.js +1 -0
- package/commands/task.js +1 -0
- package/constants.js +1 -0
- package/index.js +1 -0
- package/ipc/client.js +1 -0
- package/ipc/daemon.js +1 -0
- package/ipc/init.js +1 -0
- package/ipc/server.js +1 -0
- package/package.json +19 -0
- package/request-handler.js +1 -0
- package/types.js +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{initIPC as p}from"../ipc/init.js";class y extends runium.class.RuniumCommand{async handle(e,t,{file:r}){await this.process(e,t,r)}async process(e,t,r){let a=null;t&&(a=r?runium.utils.pathToId(t):t);const n=await p(`${this.action}:${Date.now()}`),{result:s}=await n.sendRequest({taskId:e,projectId:a,action:this.action});if(n.disconnect(),!Array.isArray(s)&&s&&s.error)throw new runium.class.RuniumError(s.error.message,s.error.code,s.error.payload);const i=Array.isArray(s)?s.filter(o=>o.result):[];if(i.length){const o=i.map(l=>{const{data:u,error:c,project:m}=l.result,d=c?c.message:u||"Ok";return{project:m,result:d}});runium.output.table(o,["project","result"])}else runium.output.log(t?`Project "${t}" not started`:"No started projects found")}}export{y as TaskCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskCommand as t}from"./task-command.js";import{TaskAction as e}from"../types.js";class n extends t{action=e.RESTART_TASK;config(){this.command.name("restart").description("restart task").option("-f, --file","use file path instead of project name").argument("<task>","task name").argument("[project]","project name")}}export{n as TaskRestartCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskCommand as t}from"./task-command.js";import{TaskAction as a}from"../types.js";class m extends t{action=a.START_TASK;config(){this.command.name("start").description("start task").option("-f, --file","use file path instead of project name").argument("<task>","task name").argument("[project]","project name")}}export{m as TaskStartCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskCommand as t}from"./task-command.js";import{TaskAction as a}from"../types.js";class n extends t{action=a.GET_TASK_STATUS;config(){this.command.name("status").description("get task status").option("-f, --file","use file path instead of project name").argument("<task>","task name").argument("[project]","project name")}}export{n as TaskStatusCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskCommand as t}from"./task-command.js";import{TaskAction as o}from"../types.js";class m extends t{action=o.STOP_TASK;config(){this.command.name("stop").description("stop task").option("-f, --file","use file path instead of project name").argument("<task>","task name").argument("[project]","project name")}}export{m as TaskStopCommand};
|
package/commands/task.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskStartCommand as m}from"./task-start.js";import{TaskStatusCommand as a}from"./task-status.js";import{TaskRestartCommand as o}from"./task-restart.js";import{TaskStopCommand as s}from"./task-stop.js";class i extends runium.class.RuniumCommand{subcommands=[m,o,s,a];config(){this.command.name("task").description("manage tasks")}async handle(){this.command.help()}}export{i as TaskCommand};
|
package/constants.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E="runium-task-manager",n=3e4,e="ipc-daemon.log",N="ipc-daemon.pid";var t=(_=>(_.IPC_CLIENT_CONNECTION_ERROR="ipc-client-connection-error",_.REQUEST_HANDLER_ERROR="request-handler-error",_.ACTION_CANNOT_BE_PERFORMED="action-cannot-be-performed",_.PROJECT_NOT_STARTED="project-not-started",_))(t||{});export{t as ErrorCode,e as IPC_DAEMON_LOG_FILENAME,n as IPC_DAEMON_NO_CLIENTS_TIMEOUT,N as IPC_DAEMON_PID_FILENAME,E as IPC_PIPE_NAME};
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskCommand as o}from"./commands/task.js";import{initRequestHandler as e}from"./request-handler.js";function c(){return{name:"task-manager",app:{commands:[o]},hooks:{project:{async beforeStart({path:t,project:r,name:n}){e({path:t,project:r,name:n}).then(()=>{})}}}}}export{c as default};
|
package/ipc/client.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{IPCClient as o}from"ipc-eventer";import{randomUUID as n}from"crypto";import{ErrorCode as i}from"../constants.js";class C extends o{socket=null;requestResolvers=new Map;requestHandler=null;constructor(s,t){super(s,{name:t,reconnect:!1})}async init(){await new Promise((s,t)=>{this.on("connected",e=>{this.socket=e,e.on("response",r=>this.onResponse(r)),e.on("request",r=>this.onRequest(r)),s()}),this.on("error",e=>t(e)),this.connect().catch(e=>t(e))})}setRequestHandler(s){this.requestHandler=s}async sendRequest(s){return new Promise(t=>{const e=n();this.requestResolvers.set(e,t),this.socket?.emit("request",{id:e,params:s})})}onResponse(s){const t=s.id,e=this.requestResolvers.get(t);e&&(this.requestResolvers.delete(t),e(s))}async onRequest(s){const t=s.id,e=s.params;try{const r=await this.requestHandler?.(e);this.socket?.emit("response",{id:t,result:r})}catch(r){this.socket?.emit("response",{id:t,result:{error:{message:r.message||JSON.stringify(r),code:i.REQUEST_HANDLER_ERROR,payload:s}}})}}}export{C as TaskManagerIPCClient};
|
package/ipc/daemon.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{TaskManagerIPCServer as r}from"./server.js";(async()=>{const e=process.argv[2],o=new r(e);await o.init().then(()=>{console.log("IPC daemon started:",e),process.send?.("started"),o.on("exit",()=>{console.log("IPC daemon stopped:",e),process.exit(0)})}).catch(s=>{console.error("Failed to start IPC daemon",s),process.send?.("failed")})})();
|
package/ipc/init.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{spawn as u}from"node:child_process";import{join as g}from"node:path";import{openSync as m}from"node:fs";import{TaskManagerIPCClient as w}from"./client.js";import{ErrorCode as C,IPC_PIPE_NAME as s,IPC_DAEMON_LOG_FILENAME as E,IPC_DAEMON_PID_FILENAME as I}from"../constants.js";async function M(a="task-manager"){let n=!0;const r=new w(s,a);await r.init().catch(()=>n=!1);try{n||(await p(s),await r.connect())}catch(o){throw new runium.class.RuniumError("Failed to connect to IPC daemon",C.IPC_CLIENT_CONNECTION_ERROR,{pipeName:s,clientName:a,original:o})}return r}async function p(a){const n=g(import.meta.dirname,"daemon.js");await runium.storage.ensureDirExists(["task-manager"]);const r=runium.storage.getPath(["task-manager",E]),o=m(r,"w"),c=m(r,"w"),t=u(process.execPath,[n,a],{detached:!0,stdio:["ignore",o,c,"ipc"]});return await runium.storage.write(["task-manager",I],String(t.pid)),t.unref(),new Promise((d,i)=>{t.on("message",e=>{e==="started"?d():i(new Error("Failed to start IPC daemon"))}),t.on("error",e=>{i(e)}),t.on("exit",(e,P)=>{i(new Error(`IPC daemon exited with code ${e} and signal ${P}`))})})}export{M as initIPC};
|
package/ipc/server.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{setTimeout as c}from"node:timers";import{randomUUID as p}from"crypto";import{IPCServer as l}from"ipc-eventer";import{ErrorCode as a,IPC_DAEMON_NO_CLIENTS_TIMEOUT as o}from"../constants.js";class v extends l{clients=new Map;projectClients=new Map;noClientsTimeout=null;pendingRequests=new Map;constructor(t){super(t)}async init(){await new Promise((t,s)=>{this.on("listening",()=>t()),this.on("error",e=>s(e)),this.on("connected",e=>this.onClientConnected(e)),this.on("disconnected",e=>this.onClientDisconnected(e)),this.start()})}onClientConnected(t){const s=t.name||t.id;if(console.log("Client connected:",s),this.clients.set(s,t),s?.startsWith("project:")){const e=s.split(":")[1];this.projectClients.set(e,t)}t.on("request",e=>this.onClientRequest(t,e)),t.on("response",e=>this.onClientResponse(t,e)),this.noClientsTimeout&&(clearTimeout(this.noClientsTimeout),this.noClientsTimeout=null)}onClientDisconnected(t){const s=t.name||t.id;if(console.log("Client disconnected:",s),this.clients.delete(s),s?.startsWith("project:")){const e=s.split(":")[1];this.projectClients.delete(e)}this.clients.size===0&&(console.log(`No clients connected. Wait for new client (${o}ms)`),this.noClientsTimeout=c(()=>{console.log("No new clients connected for timeout. Stop IPC server"),this.emit("exit")},o))}async onClientRequest(t,s){try{const e=Array.from(this.projectClients.values());if(e.length===0){t.emit("response",{id:s.id,result:[]});return}const n=p();this.pendingRequests.set(n,{socket:t,requestId:s.id,pendingResponses:[],responsesCount:e.length}),e.forEach(i=>{const r={id:n,params:s.params};i.emit("request",r)})}catch(e){t.emit("response",{id:s.id,result:{error:{message:e.message||"Unknown error",code:a.REQUEST_HANDLER_ERROR,payload:s}}})}}onClientResponse(t,s){const e=s.id,n=this.pendingRequests.get(e);if(n&&(n.pendingResponses.push(s),n.pendingResponses.length>=n.responsesCount)){const i={id:n.requestId,result:n.pendingResponses};n.socket.emit("response",i),this.pendingRequests.delete(e)}}}export{v as TaskManagerIPCServer};
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runium/plugin-task-manager",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Runium plugin for task management",
|
|
5
|
+
"author": "TheBeastApp",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"runium",
|
|
10
|
+
"runium-plugin",
|
|
11
|
+
"task-manager",
|
|
12
|
+
"tasks"
|
|
13
|
+
],
|
|
14
|
+
"module": "./index.js",
|
|
15
|
+
"main": "./index.js",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"ipc-eventer": "^1.0.3"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{initIPC as m}from"./ipc/init.js";import{TaskAction as i}from"./types.js";import{ErrorCode as c}from"./constants.js";async function q({path:e,project:r,name:n}){const{ProjectEvent:T,ProjectStatus:u}=runium.enum,o=P({path:e,project:r,name:n});let t=null;r.on(T.STATE_CHANGE,async s=>{s.status===u.STARTED?(t=await m(`project:${n||runium.utils.pathToId(e)}`),t.setRequestHandler(o)):s.status===u.STOPPED&&t&&(t.disconnect(),t=null)})}function P({project:e,name:r,path:n}){const T=r||runium.utils.pathToId(n),{ProjectStatus:u}=runium.enum;return async({projectId:o,action:t,taskId:s})=>{if((!o||o===T)&&e.getState().status===u.STARTED){const a={project:r||n,status:!0},R=e.getTaskState(s);if(R){let l="";switch(t){case i.START_TASK:await e.startTask(s);break;case i.RESTART_TASK:await e.restartTask(s);break;case i.STOP_TASK:await e.stopTask(s);break;case i.GET_TASK_STATUS:a.data=R.status;break;default:l="Action not supported";break}return l&&(a.error={message:l,code:c.ACTION_CANNOT_BE_PERFORMED},a.status=!1),a}else a.status=!1,a.error={message:"Task not found",code:c.ACTION_CANNOT_BE_PERFORMED};return a}return null}}export{q as initRequestHandler};
|
package/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var t=(e=>(e.START_TASK="start-task",e.RESTART_TASK="restart-task",e.STOP_TASK="stop-task",e.GET_TASK_STATUS="get-task-status",e))(t||{});export{t as TaskAction};
|