verteilen-core 1.0.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -0
  3. package/bun.lock +730 -0
  4. package/index.ts +1 -0
  5. package/jest.config.js +8 -0
  6. package/package.json +42 -0
  7. package/src/client/analysis.ts +377 -0
  8. package/src/client/client.ts +230 -0
  9. package/src/client/cluster.ts +125 -0
  10. package/src/client/execute.ts +210 -0
  11. package/src/client/http.ts +45 -0
  12. package/src/client/javascript.ts +535 -0
  13. package/src/client/job_execute.ts +216 -0
  14. package/src/client/job_parameter.ts +41 -0
  15. package/src/client/os.ts +210 -0
  16. package/src/client/parameter.ts +58 -0
  17. package/src/client/resource.ts +121 -0
  18. package/src/client/shell.ts +147 -0
  19. package/src/interface/base.ts +82 -0
  20. package/src/interface/bus.ts +144 -0
  21. package/src/interface/enum.ts +181 -0
  22. package/src/interface/execute.ts +47 -0
  23. package/src/interface/record.ts +131 -0
  24. package/src/interface/server.ts +91 -0
  25. package/src/interface/struct.ts +292 -0
  26. package/src/interface/table.ts +34 -0
  27. package/src/interface/ui.ts +35 -0
  28. package/src/interface.ts +50 -0
  29. package/src/lan/en.json +395 -0
  30. package/src/lan/zh_TW.json +395 -0
  31. package/src/plugins/i18n.ts +20 -0
  32. package/src/script/console_manager.ts +135 -0
  33. package/src/script/console_server_manager.ts +46 -0
  34. package/src/script/execute/base.ts +309 -0
  35. package/src/script/execute/feedback.ts +212 -0
  36. package/src/script/execute/region_job.ts +14 -0
  37. package/src/script/execute/region_project.ts +23 -0
  38. package/src/script/execute/region_subtask.ts +14 -0
  39. package/src/script/execute/region_task.ts +23 -0
  40. package/src/script/execute/runner.ts +339 -0
  41. package/src/script/execute/util_parser.ts +175 -0
  42. package/src/script/execute_manager.ts +348 -0
  43. package/src/script/socket_manager.ts +329 -0
  44. package/src/script/webhook_manager.ts +6 -0
  45. package/src/script/webhook_server_manager.ts +102 -0
  46. package/src/util/server/console_handle.ts +248 -0
  47. package/src/util/server/log_handle.ts +194 -0
  48. package/test/TEST.ts +63 -0
  49. package/test/client/execute.test.ts +54 -0
  50. package/test/client/javascript.test.ts +78 -0
  51. package/test/client/server.test.ts +26 -0
  52. package/test/client/task.test.ts +136 -0
  53. package/test/script/parser.test.ts +110 -0
  54. package/test/script/socket.test.ts +27 -0
  55. package/tsconfig.json +15 -0
@@ -0,0 +1,147 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import { ChildProcess, spawn } from "child_process";
7
+ import WebSocket from 'ws';
8
+ import { Header, Messager, ShellFolder, Single } from "../interface";
9
+ import { Client } from "./client";
10
+ import { ClientOS } from "./os";
11
+
12
+
13
+ export class ClientShell {
14
+ private messager:Messager
15
+ private messager_log:Messager
16
+ private os:ClientOS
17
+ private shell_workers:Array<[WebSocket, ChildProcess]> = []
18
+
19
+ constructor(_messager:Messager, _messager_log:Messager, _client:Client){
20
+ this.os = new ClientOS(() => "SHELL", () => "", _messager, _messager_log)
21
+ this.messager = _messager
22
+ this.messager_log = _messager_log
23
+ }
24
+
25
+ /**
26
+ * Open shell console
27
+ * @param input
28
+ */
29
+ open_shell = (data:number, source:WebSocket) => {
30
+ if(this.shell_workers.find(x => x[0] == source)){
31
+ this.messager_log(`[Shell] Error the source already open the shell`)
32
+ return
33
+ }
34
+ const program = process.platform === "win32" ? 'cmd' : 'bash'
35
+ const child = spawn(program, [],
36
+ {
37
+ stdio: ['pipe', 'pipe', 'pipe'],
38
+ shell: true,
39
+ windowsHide: true,
40
+ env: {
41
+ ...process.env,
42
+ }
43
+ })
44
+ this.shell_workers.push([source, child])
45
+ let t = ""
46
+ const workerFeedback = (str:string) => {
47
+ for(let i = 0; i < str.length; i++){
48
+ if(str[i] == '\n'){
49
+ const data:Single = {
50
+ data: t
51
+ }
52
+ const d:Header = {
53
+ name: "shell_reply",
54
+ data: data
55
+ }
56
+ source.send(JSON.stringify(d))
57
+ t = ""
58
+ }else{
59
+ t += str[i]
60
+ }
61
+ }
62
+ }
63
+ child.on('exit', (code, signal) => {
64
+ const index = this.shell_workers.findIndex(x => x[0] == source)
65
+ if(index != -1) this.shell_workers.splice(index, 1)
66
+ })
67
+ child.on('message', (message, sendHandle) => {
68
+ workerFeedback(message.toString())
69
+ })
70
+ child.stdout.setEncoding('utf8');
71
+ child.stdout.on('data', (chunk) => {
72
+ workerFeedback(chunk.toString())
73
+ })
74
+ child.stderr.setEncoding('utf8');
75
+ child.stderr.on('data', (chunk) => {
76
+ workerFeedback(chunk.toString())
77
+ })
78
+ }
79
+
80
+ /**
81
+ * Open shell console
82
+ * @param input
83
+ */
84
+ enter_shell = (input:string, source:WebSocket) => {
85
+ const p = this.shell_workers.find(x => x[0] == source)
86
+ if(p == undefined){
87
+ this.messager_log(`[Shell] Cannot find shell instance`)
88
+ return
89
+ }
90
+ p[1].stdin?.write(input + '\n')
91
+ if(process.platform == 'win32') p[1].stdin?.write("echo %cd%" + '\n')
92
+ else p[1].stdin?.write("pwd" + '\n')
93
+ }
94
+
95
+ /**
96
+ * Open shell console
97
+ * @param input
98
+ */
99
+ close_shell = (data:number, source:WebSocket) => {
100
+ const p = this.shell_workers.find(x => x[0] == source)
101
+ if(p == undefined){
102
+ this.messager_log(`[Shell] Cannot find shell instance`)
103
+ return
104
+ }
105
+ p[1].kill()
106
+ }
107
+
108
+ /**
109
+ * Open shell console
110
+ * @param input
111
+ */
112
+ close_shell_all = (data:number) => {
113
+ this.shell_workers.forEach(p => {
114
+ if(p == undefined){
115
+ this.messager_log(`[Shell] Cannot find shell instance`)
116
+ return
117
+ }
118
+ p[1].kill()
119
+ })
120
+ }
121
+
122
+ shell_folder = (data:string, source:WebSocket) => {
123
+ if(data.length == 0){
124
+ data = process.cwd()
125
+ }
126
+ if(!this.os.fs_dir_exist({path: data})){
127
+ data = process.cwd()
128
+ }
129
+ const d:ShellFolder = {
130
+ path: data,
131
+ cwd: process.cwd(),
132
+ folders: this.os.dir_dirs({path: data}),
133
+ files: this.os.dir_files({path: data})
134
+ }
135
+ const h:Header = {
136
+ name: "shell_folder_reply",
137
+ data: d
138
+ }
139
+ source.send(JSON.stringify(h))
140
+ }
141
+
142
+ disconnect = (source:WebSocket) => {
143
+ const p = this.shell_workers.find(x => x[0] == source)
144
+ if(p == undefined) return
145
+ p[1].kill()
146
+ }
147
+ }
@@ -0,0 +1,82 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import { DataType, DataTypeBase } from "./enum"
7
+ import { ACLType, LocalPermiision } from "./server"
8
+
9
+ export interface ParameterConfigTrigger {
10
+ types: Array<DataTypeBase>
11
+ }
12
+
13
+ export interface ParameterContainer {
14
+ s?: boolean
15
+ name: string
16
+ meta?: any
17
+ config?: ParameterConfigTrigger
18
+ type: DataType
19
+ hidden: boolean
20
+ runtimeOnly: boolean
21
+ value: any
22
+ }
23
+
24
+ export interface Property {
25
+ name: string
26
+ expression: string
27
+ deep?: number
28
+ }
29
+
30
+ export interface Parameter {
31
+ uuid: string
32
+ title: string
33
+ canWrite: boolean
34
+ containers: Array<ParameterContainer>
35
+ }
36
+
37
+ export interface Job {
38
+ s?: boolean
39
+ permission?: LocalPermiision
40
+ index?:number
41
+ uuid: string
42
+ runtime_uuid?: string
43
+ category: number
44
+ type: number
45
+ script: string
46
+ string_args: Array<string>
47
+ number_args: Array<number>
48
+ boolean_args: Array<boolean>
49
+ }
50
+
51
+ export interface Task {
52
+ permission?: LocalPermiision
53
+ uuid: string
54
+ title: string
55
+ description: string
56
+ setupjob: boolean
57
+ cronjob: boolean
58
+ cronjobKey: string
59
+ multi: boolean
60
+ multiKey: string
61
+ properties: Array<Property>
62
+ jobs: Array<Job>
63
+ }
64
+
65
+ export interface Project {
66
+ permission?: LocalPermiision
67
+ acl?: ACLType
68
+ owner?: string
69
+ uuid: string
70
+ title: string
71
+ description: string
72
+ parameter_uuid: string
73
+ parameter?: Parameter
74
+ task: Array<Task>
75
+ }
76
+
77
+ export interface Node {
78
+ permission?: LocalPermiision
79
+ acl?: ACLType
80
+ ID: string
81
+ url: string
82
+ }
@@ -0,0 +1,144 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import { Job, Parameter, Project, Task } from "./base"
7
+ import { ExecuteState } from "./enum"
8
+ import { ExecutionLog, Log, Preference } from "./record"
9
+ import { FeedBack, Header, Setter, ShellFolder, Single, WebsocketPack } from "./struct"
10
+ import { NodeTable } from "./table"
11
+ import { ToastData } from "./ui"
12
+
13
+ type Handler<T = unknown> = (event: T) => void
14
+ export type Messager = (msg:string, tag?:string) => void
15
+ export type Messager_log = (msg:string, tag?:string, meta?:string) => void
16
+
17
+ export interface BusAnalysis {
18
+ name:string
19
+ h:Header
20
+ c:WebsocketPack | undefined
21
+ }
22
+
23
+ export interface Rename {
24
+ oldname: string
25
+ newname: string
26
+ }
27
+
28
+ export interface Login {
29
+ username: string
30
+ password: string
31
+ }
32
+
33
+ export interface RawSend {
34
+ name: string
35
+ token?: string
36
+ data: any
37
+ }
38
+
39
+ export interface EmitterProxy<T> {
40
+ on<Key extends keyof T> (type: T, handler: Handler<T[Key]>): void
41
+ off<Key extends keyof T> (type: T, handler: Handler<T[Key]>): void
42
+ emit<Key extends keyof T> (type: T, handler: T[Key]): void
43
+ }
44
+
45
+ /**
46
+ * The middleware for task scheduler worker with singal sender
47
+ */
48
+ export interface ExecuteProxy {
49
+ executeProjectStart: (data:[Project, number]) => void
50
+ executeProjectFinish: (data:[Project, number]) => void
51
+ /**
52
+ * * 0.Task: Task instance
53
+ * * 1.number: The amounts of subtask need
54
+ */
55
+ executeTaskStart: (data:[Task, number]) => void
56
+ executeTaskFinish: (data:Task) => void
57
+ /**
58
+ * * 0.Task: Task instance
59
+ * * 1.number: Subtask index
60
+ * * 2.string: node uuid
61
+ */
62
+ executeSubtaskStart: (data:[Task, number, string]) => void
63
+ executeSubtaskUpdate: (data:[Task, number, string, ExecuteState]) => void
64
+ /**
65
+ * * 0.Task: Task instance
66
+ * * 1.number: Subtask index
67
+ * * 2.string: node uuid
68
+ */
69
+ executeSubtaskFinish: (data:[Task, number, string]) => void
70
+ /**
71
+ * * 0.Job: Job instance
72
+ * * 1.number: Subtask index
73
+ * * 2.string: node uuid
74
+ */
75
+ executeJobStart: (data:[Job, number, string]) => void
76
+ /**
77
+ * * 0.Job: Job instance
78
+ * * 1.number: Subtask index
79
+ * * 2.string: node uuid
80
+ * * 3.string: meta string
81
+ */
82
+ executeJobFinish: (data:[Job, number, string, number]) => void
83
+ feedbackMessage: (data:FeedBack) => void
84
+ updateParameter: (data:Parameter) => void
85
+ }
86
+
87
+ export interface NodeProxy {
88
+ shellReply: (data:Single, w?:WebsocketPack) => void
89
+ folderReply: (data:ShellFolder, w?:WebsocketPack) => void
90
+ }
91
+
92
+ /**
93
+ * Emitter events container for Primary use
94
+ */
95
+ export type BusType = {
96
+ setting: void
97
+ guide: void
98
+ makeToast: ToastData
99
+ modeSelect: boolean
100
+ createProject: void
101
+ updateProject: void
102
+ recoverProject: Project
103
+ recoverParameter: Parameter
104
+ relogin: void
105
+ loginGuest: void
106
+ login: Setter
107
+ updateTask: void
108
+ updateJob: void
109
+ updateParameter: void
110
+ selectParameter: string
111
+ updateLocate: void
112
+ updateNode: Array<NodeTable>
113
+ updateCurrent: ExecutionLog,
114
+ updateLog: Log
115
+ updateHandle: void
116
+ slowUpdateHandle: void
117
+ shellReply: Single
118
+ folderReply: ShellFolder
119
+ feedbackMessage: FeedBack
120
+ savePreference: Preference
121
+
122
+ renameScript: Rename
123
+ deleteScript: string
124
+
125
+ analysis: BusAnalysis
126
+ debuglog: string
127
+ hotkey: string
128
+ isExpress: boolean
129
+
130
+ delay: Setter
131
+ system: Setter
132
+ }
133
+
134
+ /**
135
+ * Emitter events container for Web client
136
+ */
137
+ export type BusWebType = {
138
+ raw_send: RawSend
139
+
140
+ locate: string
141
+ load_preference: string
142
+ load_cookie: void
143
+ get_token: string
144
+ }
@@ -0,0 +1,181 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ export enum SocketState {
7
+ CONNECTING = 0,
8
+ OPEN = 1,
9
+ CLOSING = 2,
10
+ CLOSED = 3
11
+ }
12
+
13
+ export enum DataType {
14
+ Boolean,
15
+ Number,
16
+ String,
17
+ Object,
18
+ Expression,
19
+ Textarea,
20
+ Select,
21
+ List,
22
+ }
23
+
24
+ export enum DataTypeBase {
25
+ Boolean,
26
+ Number,
27
+ String,
28
+ }
29
+
30
+ export enum ResourceType {
31
+ ALL = ~(~0 << 10),
32
+ SYSTEM = 1 << 0,
33
+ CPU = 1 << 1,
34
+ RAM = 1 << 2,
35
+ BATTERY = 1 << 3,
36
+ LOAD = 1 << 4,
37
+ OS = 1 << 5,
38
+ GPU = 1 << 6,
39
+ DISK = 1 << 7,
40
+ NETWORK = 1 << 8,
41
+ }
42
+
43
+ export enum FrontendUpdate {
44
+ ALL = ~(~0 << 10),
45
+ PROJECT = 1 << 0,
46
+ PARAMETER = 1 << 1,
47
+ }
48
+
49
+ export enum JobCategory {
50
+ Condition,
51
+ Execution
52
+ }
53
+
54
+ export enum ConditionResult {
55
+ None,
56
+ SkipProject,
57
+ ThrowProject,
58
+ SkipTask,
59
+ ThrowTask,
60
+ Pause,
61
+ }
62
+
63
+ export enum JobType {
64
+ COPY_FILE,
65
+ COPY_DIR,
66
+ DELETE_FILE,
67
+ DELETE_DIR,
68
+ CREATE_FILE,
69
+ CREATE_DIR,
70
+ RENAME,
71
+ JAVASCRIPT,
72
+ COMMAND,
73
+ LIB_COMMAND,
74
+ }
75
+
76
+ export enum JobType2 {
77
+ CHECK_PATH,
78
+ JAVASCRIPT,
79
+ }
80
+
81
+ export enum ProjectTemplate {
82
+ DEFAULT = 0,
83
+ DEFAULT_SHORT = 1,
84
+ Blender = 100,
85
+ Blender_Cluster = 101,
86
+ AfterEffect = 200,
87
+ }
88
+
89
+ export enum ParameterTemplate {
90
+ DEFAULT = 0
91
+ }
92
+
93
+ export enum ExecuteState {
94
+ NONE, RUNNING, FINISH, ERROR, SKIP
95
+ }
96
+
97
+ export enum RenderUpdateType {
98
+ All= ~(~0 << 7),
99
+ Project = 1 << 0,
100
+ Node = 1 << 1,
101
+ Parameter = 1 << 2
102
+ }
103
+
104
+ export enum JavascriptLib {
105
+ ALL = ~(~0 << 7),
106
+ OS = 1 << 0,
107
+ ENV = 1 << 1,
108
+ MESSAGE = 1 << 2,
109
+ HTTP = 1 << 3,
110
+ PATH = 1 << 4,
111
+ }
112
+
113
+ export const DataTypeText: { [key:number]:string } = {
114
+ 0: 'types.boolean',
115
+ 1: 'types.number',
116
+ 2: 'types.string',
117
+ 3: 'types.object',
118
+ 4: 'types.expression',
119
+ 5: 'types.textarea',
120
+ 6: 'types.select',
121
+ 7: 'types.list',
122
+ }
123
+
124
+ export const ExecuteStateText: { [key:number]:string } = {
125
+ 0: 'enum.state.none',
126
+ 1: 'enum.state.running',
127
+ 2: 'enum.state.finish',
128
+ 3: 'enum.state.error',
129
+ 4: 'enum.state.skip',
130
+ }
131
+
132
+ export const JobCategoryText: { [key:number]:string } = {
133
+ 0: 'enum.category.condition',
134
+ 1: 'enum.category.execution',
135
+ }
136
+
137
+ export const ConnectionText: { [key:number]:string } = {
138
+ 0: 'enum.connection.connecting',
139
+ 1: 'enum.connection.connected',
140
+ 2: 'enum.connection.closing',
141
+ 3: 'enum.connection.closed',
142
+ }
143
+
144
+ export const JobResultText: { [key:number]:string } = {
145
+ 0: 'enum.jobresult.none',
146
+ 1: 'enum.jobresult.skip-project',
147
+ 2: 'enum.jobresult.throw-project',
148
+ 3: 'enum.jobresult.skip-task',
149
+ 4: 'enum.jobresult.throw-task',
150
+ 5: 'enum.jobresult.pause'
151
+ }
152
+
153
+ export const JobTypeText: { [key:number]:string } = {
154
+ 0: 'enum.jobtype.copy-file',
155
+ 1: 'enum.jobtype.copy-dir',
156
+ 2: 'enum.jobtype.delete-file',
157
+ 3: 'enum.jobtype.delete-dir',
158
+ 4: 'enum.jobtype.create-file',
159
+ 5: 'enum.jobtype.create-dir',
160
+ 6: 'enum.jobtype.rename',
161
+ 7: 'enum.jobtype.javascript',
162
+ 8: 'enum.jobtype.command',
163
+ 9: 'enum.jobtype.lib_command',
164
+ }
165
+
166
+ export const JobType2Text: { [key:number]:string } = {
167
+ 0: 'enum.jobtype2.check-path',
168
+ 1: 'enum.jobtype.javascript',
169
+ }
170
+
171
+ export const ProjectTemplateText: { [key:number]:string } = {
172
+ 0: 'enum.project.default',
173
+ 1: 'enum.project.default_short',
174
+ 100: 'enum.project.blender',
175
+ 101: 'enum.project.blender_cluster',
176
+ 200: 'enum.project.aftereffect',
177
+ }
178
+
179
+ export const ParameterTemplateText: { [key:number]:string } = {
180
+ 0: 'enum.parameter.default'
181
+ }
@@ -0,0 +1,47 @@
1
+ // ========================
2
+ //
3
+ // Share Codebase
4
+ //
5
+ // ========================
6
+ import { Job } from "./base"
7
+ import { ExecuteState } from "./enum"
8
+
9
+ /**
10
+ * The cronjob package, contain subtask state
11
+ */
12
+ export interface CronJobState {
13
+ /**
14
+ * The index order for the cron pacakge
15
+ */
16
+ id: number,
17
+ /**
18
+ * The network instance uuid
19
+ */
20
+ uuid: string,
21
+ /**
22
+ * All the job state package
23
+ */
24
+ work: Array<WorkState>
25
+ }
26
+
27
+ /**
28
+ * The job package, contain jobs state
29
+ */
30
+ export interface WorkState {
31
+ /**
32
+ * The network instance uuid
33
+ */
34
+ uuid: string
35
+ /**
36
+ * Runtime uuid
37
+ */
38
+ runtime: string
39
+ /**
40
+ * Job state
41
+ */
42
+ state: ExecuteState
43
+ /**
44
+ * The job instance
45
+ */
46
+ job: Job
47
+ }