@whyour/qinglong 2.18.2-2 → 2.18.2-5

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 (176) hide show
  1. package/package.json +4 -4
  2. package/shell/preload/client.js +149 -40
  3. package/shell/preload/client.py +200 -30
  4. package/shell/preload/sitecustomize.js +1 -1
  5. package/shell/preload/sitecustomize.py +1 -1
  6. package/shell/share.sh +3 -3
  7. package/shell/update.sh +4 -1
  8. package/static/build/api/cron.js +10 -40
  9. package/static/build/api/system.js +15 -0
  10. package/static/build/app.js +1 -0
  11. package/static/build/config/index.js +2 -2
  12. package/static/build/config/util.js +17 -2
  13. package/static/build/data/notify.js +5 -6
  14. package/static/build/interface/schedule.js +9 -0
  15. package/static/build/loaders/bootAfter.js +12 -0
  16. package/static/build/loaders/initFile.js +2 -2
  17. package/static/build/protos/api.js +1285 -168
  18. package/static/build/protos/cron.js +46 -41
  19. package/static/build/protos/health.js +12 -13
  20. package/static/build/schedule/addCron.js +5 -5
  21. package/static/build/schedule/api.js +86 -1
  22. package/static/build/services/cron.js +70 -32
  23. package/static/build/services/notify.js +3 -4
  24. package/static/build/services/system.js +16 -1
  25. package/static/build/services/user.js +2 -1
  26. package/static/build/shared/utils.js +3 -0
  27. package/static/build/validation/schedule.js +42 -0
  28. package/static/dist/1134.b851963c.async.js +1 -0
  29. package/static/dist/1174.41a43fee.async.js +1 -0
  30. package/static/dist/1212.f87fd07a.async.js +1 -0
  31. package/static/dist/1706.ac98cb3f.async.js +1 -0
  32. package/static/dist/1887.9e0d3da8.async.js +1 -0
  33. package/static/dist/1969.d61ba5fb.async.js +1 -0
  34. package/static/dist/198.db47fc1a.async.js +1 -0
  35. package/static/dist/2003.8eafeca8.async.js +1 -0
  36. package/static/dist/2208.03c2cf4a.async.js +1 -0
  37. package/static/dist/2231.29b754cf.async.js +1 -0
  38. package/static/dist/2336.0756f45f.async.js +1 -0
  39. package/static/dist/2506.a6334794.async.js +1 -0
  40. package/static/dist/2577.aa8fe709.async.js +1 -0
  41. package/static/dist/2636.70ece391.async.js +1 -0
  42. package/static/dist/2750.7aa38add.async.js +1 -0
  43. package/static/dist/2783.0787fd60.async.js +1 -0
  44. package/static/dist/2843.e968a7af.async.js +1 -0
  45. package/static/dist/2905.a8f810e1.async.js +1 -0
  46. package/static/dist/293.80d14a4f.async.js +1 -0
  47. package/static/dist/2958.1a7daa3c.async.js +1 -0
  48. package/static/dist/3055.a99f8e4c.async.js +1 -0
  49. package/static/dist/3617.b7d4b2ed.async.js +1 -0
  50. package/static/dist/3711.9814cb8c.async.js +1 -0
  51. package/static/dist/3730.3654e8fa.async.js +1 -0
  52. package/static/dist/3840.801ded2b.async.js +1 -0
  53. package/static/dist/4324.5a5887d1.async.js +1 -0
  54. package/static/dist/4462.02fd0a33.async.js +1 -0
  55. package/static/dist/4481.4d51cf36.async.js +1 -0
  56. package/static/dist/4507.8541bc6d.async.js +1 -0
  57. package/static/dist/4559.faab3673.async.js +1 -0
  58. package/static/dist/4756.64d6d0a4.async.js +1 -0
  59. package/static/dist/4818.c83facd7.async.js +1 -0
  60. package/static/dist/4821.64537e48.async.js +1 -0
  61. package/static/dist/{8142.e3e82eda.async.js → 4934.1ca6b6b0.async.js} +1 -1
  62. package/static/dist/4944.3be3e188.async.js +1 -0
  63. package/static/dist/5.3ebdd181.async.js +1 -0
  64. package/static/dist/5232.f4b06476.async.js +1 -0
  65. package/static/dist/5325.54777fe5.async.js +1 -0
  66. package/static/dist/5363.2fedc735.async.js +1 -0
  67. package/static/dist/5436.f2e37c36.async.js +1 -0
  68. package/static/dist/5580.48b4722f.async.js +1 -0
  69. package/static/dist/5662.678b0cfb.async.js +1 -0
  70. package/static/dist/5759.45438497.async.js +1 -0
  71. package/static/dist/5876.93680102.async.js +1 -0
  72. package/static/dist/5878.32535c39.async.js +1 -0
  73. package/static/dist/591.1c6b5df7.async.js +1 -0
  74. package/static/dist/6367.8b0e838c.async.js +1 -0
  75. package/static/dist/6431.c50479be.async.js +1 -0
  76. package/static/dist/6437.91ff515b.async.js +1 -0
  77. package/static/dist/6598.01b8b308.async.js +1 -0
  78. package/static/dist/6711.84451b08.async.js +1 -0
  79. package/static/dist/6841.e92e9802.async.js +1 -0
  80. package/static/dist/685.2419bacf.async.js +1 -0
  81. package/static/dist/7036.fdeb74d0.async.js +1 -0
  82. package/static/dist/7272.1c73bcc5.async.js +1 -0
  83. package/static/dist/7278.96bf439f.async.js +1 -0
  84. package/static/dist/752.66fdc531.async.js +1 -0
  85. package/static/dist/7540.6bb57f5f.async.js +1 -0
  86. package/static/dist/7647.e9446154.async.js +1 -0
  87. package/static/dist/7661.6684ddda.async.js +1 -0
  88. package/static/dist/7714.1e826854.async.js +1 -0
  89. package/static/dist/7846.7d689939.async.js +1 -0
  90. package/static/dist/7993.ed86bf44.async.js +1 -0
  91. package/static/dist/8025.7dc65c6a.async.js +1 -0
  92. package/static/dist/8038.58b0571f.async.js +1 -0
  93. package/static/dist/8080.056470f6.async.js +1 -0
  94. package/static/dist/8142.a074ddf1.async.js +1 -0
  95. package/static/dist/831.9756b44d.async.js +1 -0
  96. package/static/dist/8315.3c15bde0.async.js +1 -0
  97. package/static/dist/8394.452e865e.async.js +1 -0
  98. package/static/dist/8416.69691e31.async.js +1 -0
  99. package/static/dist/8526.bb556c43.async.js +1 -0
  100. package/static/dist/8682.597beedb.async.js +1 -0
  101. package/static/dist/8776.e8798a5a.async.js +1 -0
  102. package/static/dist/8779.3e755010.async.js +1 -0
  103. package/static/dist/8826.b3f9fa78.async.js +1 -0
  104. package/static/dist/8851.a57942be.async.js +1 -0
  105. package/static/dist/8878.8367da80.async.js +1 -0
  106. package/static/dist/9033.f2e29d04.async.js +1 -0
  107. package/static/dist/9082.9f6c6520.async.js +1 -0
  108. package/static/dist/9095.816eeb1a.async.js +1 -0
  109. package/static/dist/9187.4bacb25e.async.js +1 -0
  110. package/static/dist/9308.3202ac13.async.js +1 -0
  111. package/static/dist/9674.1b962b29.chunk.css +1 -0
  112. package/static/dist/9674.962a6cda.async.js +1 -0
  113. package/static/dist/9853.695fdd64.async.js +1 -0
  114. package/static/dist/9974.c867bc89.async.js +1 -0
  115. package/static/dist/index.html +2 -2
  116. package/static/dist/{layouts__index.c986408d.async.js → layouts__index.623b87d2.async.js} +1 -1
  117. package/static/dist/preload_helper.68e6986a.js +1 -0
  118. package/static/dist/{src__pages__config__index.de6dca30.async.js → src__pages__config__index.622b6ee8.async.js} +1 -1
  119. package/static/dist/src__pages__crontab__const.323d5124.async.js +1 -0
  120. package/static/dist/{src__pages__crontab__detail.80d30a01.async.js → src__pages__crontab__detail.c7d28d13.async.js} +1 -1
  121. package/static/dist/src__pages__crontab__index.b6a281d6.async.js +1 -0
  122. package/static/dist/{src__pages__crontab__logModal.6a345e8a.async.js → src__pages__crontab__logModal.0767c532.async.js} +1 -1
  123. package/static/dist/src__pages__crontab__modal.b20074c2.async.js +1 -0
  124. package/static/dist/src__pages__crontab__type.db7c1858.async.js +1 -0
  125. package/static/dist/src__pages__dependence__modal.1bb8572d.async.js +1 -0
  126. package/static/dist/{src__pages__diff__index.a4176b58.async.js → src__pages__diff__index.013b7c75.async.js} +1 -1
  127. package/static/dist/src__pages__env__editNameModal.115bb8ea.async.js +1 -0
  128. package/static/dist/{src__pages__env__index.f3bfe0c7.async.js → src__pages__env__index.7205e719.async.js} +1 -1
  129. package/static/dist/{src__pages__env__modal.066399fd.async.js → src__pages__env__modal.d923acdb.async.js} +1 -1
  130. package/static/dist/{src__pages__error__index.656c9940.async.js → src__pages__error__index.a17578c5.async.js} +1 -1
  131. package/static/dist/{src__pages__initialization__index.75484c39.async.js → src__pages__initialization__index.684197ee.async.js} +1 -1
  132. package/static/dist/{src__pages__log__index.8a782756.async.js → src__pages__log__index.43024b22.async.js} +1 -1
  133. package/static/dist/{src__pages__login__index.8a653852.async.js → src__pages__login__index.cd6e3152.async.js} +1 -1
  134. package/static/dist/{src__pages__script__editModal.e7bf71bd.async.js → src__pages__script__editModal.10dd9857.async.js} +1 -1
  135. package/static/dist/src__pages__script__editNameModal.7d1cc6b4.async.js +1 -0
  136. package/static/dist/src__pages__script__index.1d172186.async.js +1 -0
  137. package/static/dist/src__pages__script__renameModal.09dfb133.async.js +1 -0
  138. package/static/dist/src__pages__script__saveModal.21b81bcc.async.js +1 -0
  139. package/static/dist/src__pages__script__setting.c6503aaf.async.js +1 -0
  140. package/static/dist/{src__pages__setting__about.f6325812.chunk.css → src__pages__setting__about.e6db5090.chunk.css} +1 -1
  141. package/static/dist/src__pages__setting__appModal.b115baf8.async.js +1 -0
  142. package/static/dist/{src__pages__setting__checkUpdate.04c00c9c.async.js → src__pages__setting__checkUpdate.c152dfaf.async.js} +1 -1
  143. package/static/dist/{src__pages__setting__dependence.55c598d0.chunk.css → src__pages__setting__dependence.28ecea01.chunk.css} +1 -1
  144. package/static/dist/{src__pages__setting__dependence.0dd0969b.async.js → src__pages__setting__dependence.f3afc194.async.js} +1 -1
  145. package/static/dist/{src__pages__setting__index.d666f8ec.chunk.css → src__pages__setting__index.7cf46d4a.chunk.css} +1 -1
  146. package/static/dist/src__pages__setting__index.f6051186.async.js +1 -0
  147. package/static/dist/{src__pages__setting__notification.b038afec.async.js → src__pages__setting__notification.b7722a0b.async.js} +1 -1
  148. package/static/dist/{src__pages__setting__other.55c598d0.chunk.css → src__pages__setting__other.28ecea01.chunk.css} +1 -1
  149. package/static/dist/src__pages__setting__other.45f67bd2.async.js +1 -0
  150. package/static/dist/{src__pages__setting__security.af57bd6a.async.js → src__pages__setting__security.534a5e67.async.js} +1 -1
  151. package/static/dist/{src__pages__setting__systemLog.501844bd.async.js → src__pages__setting__systemLog.cb8a2174.async.js} +1 -1
  152. package/static/dist/{src__pages__subscription__index.b43143e7.async.js → src__pages__subscription__index.30fefd8e.async.js} +1 -1
  153. package/static/dist/{src__pages__subscription__logModal.02c80eb3.async.js → src__pages__subscription__logModal.9bf0b4f6.async.js} +1 -1
  154. package/static/dist/src__pages__subscription__modal.10cd630d.async.js +1 -0
  155. package/static/dist/static/codicon.63b8ee5b.ttf +0 -0
  156. package/static/dist/{umi.e783bacd.js → umi.e6d28cd5.js} +1 -1
  157. package/version.yaml +9 -6
  158. package/static/dist/2208.c1a40612.async.js +0 -1
  159. package/static/dist/3127.2579e73a.async.js +0 -1
  160. package/static/dist/4402.49bbe98d.async.js +0 -1
  161. package/static/dist/8826.37966028.async.js +0 -1
  162. package/static/dist/preload_helper.6482f199.js +0 -1
  163. package/static/dist/src__pages__crontab__index.9e38b6dc.async.js +0 -1
  164. package/static/dist/src__pages__crontab__modal.78b1e588.async.js +0 -1
  165. package/static/dist/src__pages__crontab__type.bde5cda4.async.js +0 -1
  166. package/static/dist/src__pages__dependence__modal.e6696a7c.async.js +0 -1
  167. package/static/dist/src__pages__env__editNameModal.02322e80.async.js +0 -1
  168. package/static/dist/src__pages__script__editNameModal.c048343e.async.js +0 -1
  169. package/static/dist/src__pages__script__index.9d9099c1.async.js +0 -1
  170. package/static/dist/src__pages__script__renameModal.357c6c72.async.js +0 -1
  171. package/static/dist/src__pages__script__saveModal.61fcb1fe.async.js +0 -1
  172. package/static/dist/src__pages__script__setting.f2d78204.async.js +0 -1
  173. package/static/dist/src__pages__setting__appModal.9eeaeee7.async.js +0 -1
  174. package/static/dist/src__pages__setting__index.46a8e768.async.js +0 -1
  175. package/static/dist/src__pages__setting__other.0d869d58.async.js +0 -1
  176. package/static/dist/src__pages__subscription__modal.a61ece75.async.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyour/qinglong",
3
- "version": "2.18.2-2",
3
+ "version": "2.18.2-5",
4
4
  "description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,7 +24,7 @@
24
24
  "schedule": "npm run build:back && node static/build/schedule/index.js",
25
25
  "public": "npm run build:back && node static/build/public.js",
26
26
  "update": "npm run build:back && node static/build/update.js",
27
- "gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true",
27
+ "gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true,snakeToCamel=false",
28
28
  "gen:api": "python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./back/protos/api.proto",
29
29
  "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
30
30
  "postinstall": "max setup 2>/dev/null || true",
@@ -104,7 +104,7 @@
104
104
  "node-schedule": "^2.1.0",
105
105
  "nodemailer": "^6.9.16",
106
106
  "p-queue-cjs": "7.3.4",
107
- "protobufjs": "^7.4.0",
107
+ "@bufbuild/protobuf": "^2.2.3",
108
108
  "pstree.remy": "^1.1.8",
109
109
  "reflect-metadata": "^0.2.2",
110
110
  "sequelize": "^6.37.5",
@@ -187,7 +187,7 @@
187
187
  "react-split-pane": "^0.1.92",
188
188
  "sockjs-client": "^1.6.0",
189
189
  "ts-node": "^10.9.2",
190
- "ts-proto": "^1.146.0",
190
+ "ts-proto": "^2.6.1",
191
191
  "tslib": "^2.4.0",
192
192
  "typescript": "5.2.2",
193
193
  "vh-check": "^2.0.5",
@@ -1,45 +1,154 @@
1
1
  const grpc = require('@grpc/grpc-js');
2
2
  const protoLoader = require('@grpc/proto-loader');
3
+ const { join } = require('path');
3
4
 
4
- const PROTO_PATH = `${process.env.QL_DIR}/back/protos/api.proto`;
5
- const options = {
6
- keepCase: true,
7
- longs: String,
8
- enums: String,
9
- defaults: true,
10
- };
11
-
12
- const packageDefinition = protoLoader.loadSync(PROTO_PATH, options);
13
- const apiProto = grpc.loadPackageDefinition(packageDefinition).com.ql.api;
14
-
15
- const client = new apiProto.Api(
16
- `0.0.0.0:5500`,
17
- grpc.credentials.createInsecure(),
18
- { 'grpc.enable_http_proxy': 0 },
19
- );
20
-
21
- const promisify = (fn) => {
22
- return (...args) => {
23
- return new Promise((resolve, reject) => {
24
- fn.call(client, ...args, (err, response) => {
25
- if (err) return reject(err);
26
- resolve(response);
5
+ class GrpcClient {
6
+ static #config = {
7
+ protoPath: join(process.env.QL_DIR, 'back/protos/api.proto'),
8
+ serverAddress: '0.0.0.0:5500',
9
+ protoOptions: {
10
+ keepCase: true,
11
+ longs: String,
12
+ enums: String,
13
+ defaults: true,
14
+ },
15
+ grpcOptions: {
16
+ 'grpc.enable_http_proxy': 0,
17
+ 'grpc.keepalive_time_ms': 120000,
18
+ 'grpc.keepalive_timeout_ms': 20000,
19
+ 'grpc.max_receive_message_length': 100 * 1024 * 1024,
20
+ },
21
+ defaultTimeout: 30000,
22
+ };
23
+
24
+ static #methods = [
25
+ 'getEnvs',
26
+ 'createEnv',
27
+ 'updateEnv',
28
+ 'deleteEnvs',
29
+ 'moveEnv',
30
+ 'disableEnvs',
31
+ 'enableEnvs',
32
+ 'updateEnvNames',
33
+ 'getEnvById',
34
+ 'systemNotify',
35
+ 'getCronDetail',
36
+ 'createCron',
37
+ 'updateCron',
38
+ 'deleteCrons',
39
+ ];
40
+
41
+ #client;
42
+ #api = {};
43
+
44
+ constructor() {
45
+ this.#initializeClient();
46
+ this.#bindMethods();
47
+ }
48
+
49
+ #initializeClient() {
50
+ try {
51
+ const { protoPath, protoOptions, serverAddress, grpcOptions } =
52
+ GrpcClient.#config;
53
+
54
+ const packageDefinition = protoLoader.loadSync(protoPath, protoOptions);
55
+ const apiProto = grpc.loadPackageDefinition(packageDefinition).com.ql.api;
56
+
57
+ this.#client = new apiProto.Api(
58
+ serverAddress,
59
+ grpc.credentials.createInsecure(),
60
+ grpcOptions,
61
+ );
62
+
63
+ this.#checkConnection();
64
+ } catch (error) {
65
+ console.error('Failed to initialize gRPC client:', error);
66
+ process.exit(1);
67
+ }
68
+ }
69
+
70
+ #checkConnection() {
71
+ this.#client.waitForReady(Date.now() + 5000, (error) => {
72
+ if (error) {
73
+ console.error('gRPC client connection failed:', error);
74
+ process.exit(1);
75
+ }
76
+ });
77
+ }
78
+
79
+ #promisifyMethod(methodName) {
80
+ const capitalizedMethod =
81
+ methodName.charAt(0).toUpperCase() + methodName.slice(1);
82
+ const method = this.#client[capitalizedMethod].bind(this.#client);
83
+
84
+ return async (params = {}) => {
85
+ return new Promise((resolve, reject) => {
86
+ const metadata = new grpc.Metadata();
87
+ const deadline = new Date(
88
+ Date.now() + GrpcClient.#config.defaultTimeout,
89
+ );
90
+
91
+ method(params, metadata, { deadline }, (error, response) => {
92
+ if (error) {
93
+ return reject(error);
94
+ }
95
+ resolve(response);
96
+ });
27
97
  });
98
+ };
99
+ }
100
+
101
+ #bindMethods() {
102
+ GrpcClient.#methods.forEach((method) => {
103
+ this.#api[method] = this.#promisifyMethod(method);
28
104
  });
29
- };
30
- };
31
-
32
- const api = {
33
- getEnvs: promisify(client.GetEnvs),
34
- createEnv: promisify(client.CreateEnv),
35
- updateEnv: promisify(client.UpdateEnv),
36
- deleteEnvs: promisify(client.DeleteEnvs),
37
- moveEnv: promisify(client.MoveEnv),
38
- disableEnvs: promisify(client.DisableEnvs),
39
- enableEnvs: promisify(client.EnableEnvs),
40
- updateEnvNames: promisify(client.UpdateEnvNames),
41
- getEnvById: promisify(client.GetEnvById),
42
- systemNotify: promisify(client.SystemNotify),
43
- };
44
-
45
- module.exports = api;
105
+ }
106
+
107
+ getApi() {
108
+ return {
109
+ ...this.#api,
110
+ close: this.close.bind(this),
111
+ };
112
+ }
113
+
114
+ close() {
115
+ if (this.#client) {
116
+ this.#client.close();
117
+ this.#client = null;
118
+ }
119
+ }
120
+ }
121
+
122
+ const grpcClient = new GrpcClient();
123
+
124
+ process.on('SIGTERM', () => {
125
+ grpcClient.close();
126
+ process.exit(0);
127
+ });
128
+
129
+ process.on('SIGINT', () => {
130
+ grpcClient.close();
131
+ process.exit(0);
132
+ });
133
+
134
+ process.on('unhandledRejection', (reason, promise) => {
135
+ if (reason instanceof Error) {
136
+ if (reason.stack) {
137
+ const relevantStack = reason.stack
138
+ .split('\n')
139
+ .filter((line) => {
140
+ return (
141
+ !line.includes('node:internal') &&
142
+ !line.includes('node_modules/@grpc') &&
143
+ !line.includes('processTicksAndRejections')
144
+ );
145
+ })
146
+ .join('\n');
147
+ console.error(relevantStack);
148
+ }
149
+ } else {
150
+ console.error(reason);
151
+ }
152
+ });
153
+
154
+ module.exports = grpcClient.getApi();
@@ -2,7 +2,7 @@ import subprocess
2
2
  import json
3
3
  import tempfile
4
4
  import os
5
- from typing import Dict, List
5
+ from typing import Dict, List, TypedDict, Optional
6
6
  from functools import wraps
7
7
 
8
8
 
@@ -11,16 +11,170 @@ def error_handler(func):
11
11
  def wrapper(*args, **kwargs):
12
12
  try:
13
13
  return func(*args, **kwargs)
14
- except json.JSONDecodeError as e:
15
- raise Exception(f"parse json error: {str(e)}")
16
- except subprocess.SubprocessError as e:
17
- raise Exception(f"node process error: {str(e)}")
14
+ except TypeError as e:
15
+ if "missing" in str(e):
16
+ func_name = func.__name__
17
+ annotations = func.__annotations__
18
+ param_type = next(
19
+ (t for name, t in annotations.items() if name != "return"), None
20
+ )
21
+ if param_type and hasattr(param_type, "__annotations__"):
22
+ required_fields = {
23
+ k: v
24
+ for k, v in param_type.__annotations__.items()
25
+ if not getattr(param_type, "__total__", True)
26
+ or k in getattr(param_type, "__required_keys__", set())
27
+ }
28
+ fields_str = ", ".join(
29
+ f'"{k}": {v.__name__}' for k, v in required_fields.items()
30
+ )
31
+ raise Exception(
32
+ f"{func_name}() requires a dictionary with parameters: {{{fields_str}}}"
33
+ ) from None
34
+ raise Exception(f"{str(e)}") from None
18
35
  except Exception as e:
19
- raise Exception(f"unknown error: {str(e)}")
36
+ error_msg = str(e)
37
+ if "Error:" in error_msg:
38
+ error_msg = error_msg.split("Error:")[-1].split("\n")[0].strip()
39
+ raise Exception(f"{error_msg}") from None
20
40
 
21
41
  return wrapper
22
42
 
23
43
 
44
+ class EnvItem(TypedDict, total=False):
45
+ id: Optional[int]
46
+ name: Optional[str]
47
+ value: Optional[str]
48
+ remarks: Optional[str]
49
+ status: Optional[int]
50
+ position: Optional[int]
51
+
52
+
53
+ class GetEnvsParams(TypedDict, total=False):
54
+ searchValue: str
55
+
56
+
57
+ class CreateEnvParams(TypedDict):
58
+ envs: List[EnvItem]
59
+
60
+
61
+ class UpdateEnvParams(TypedDict):
62
+ env: EnvItem
63
+
64
+
65
+ class DeleteEnvsParams(TypedDict):
66
+ ids: List[int]
67
+
68
+
69
+ class MoveEnvParams(TypedDict):
70
+ id: int
71
+ fromIndex: int
72
+ toIndex: int
73
+
74
+
75
+ class DisableEnvsParams(TypedDict):
76
+ ids: List[int]
77
+
78
+
79
+ class EnableEnvsParams(TypedDict):
80
+ ids: List[int]
81
+
82
+
83
+ class UpdateEnvNamesParams(TypedDict):
84
+ ids: List[int]
85
+ name: str
86
+
87
+
88
+ class GetEnvByIdParams(TypedDict):
89
+ id: int
90
+
91
+
92
+ class SystemNotifyParams(TypedDict):
93
+ title: str
94
+ content: str
95
+
96
+
97
+ class EnvsResponse(TypedDict):
98
+ code: int
99
+ data: List[EnvItem]
100
+ message: Optional[str]
101
+
102
+
103
+ class EnvResponse(TypedDict):
104
+ code: int
105
+ data: EnvItem
106
+ message: Optional[str]
107
+
108
+
109
+ class Response(TypedDict):
110
+ code: int
111
+ message: Optional[str]
112
+
113
+
114
+ class ExtraScheduleItem(TypedDict, total=False):
115
+ schedule: Optional[str]
116
+
117
+
118
+ class CronItem(TypedDict, total=False):
119
+ id: Optional[int]
120
+ command: Optional[str]
121
+ schedule: Optional[str]
122
+ name: Optional[str]
123
+ labels: List[str]
124
+ sub_id: Optional[int]
125
+ extra_schedules: List[ExtraScheduleItem]
126
+ task_before: Optional[str]
127
+ task_after: Optional[str]
128
+ status: Optional[int]
129
+ log_path: Optional[str]
130
+ pid: Optional[int]
131
+ last_running_time: Optional[int]
132
+ last_execution_time: Optional[int]
133
+
134
+
135
+ class CreateCronParams(TypedDict):
136
+ command: str
137
+ schedule: str
138
+ name: Optional[str]
139
+ labels: List[str]
140
+ sub_id: Optional[int]
141
+ extra_schedules: List[ExtraScheduleItem]
142
+ task_before: Optional[str]
143
+ task_after: Optional[str]
144
+
145
+
146
+ class UpdateCronParams(TypedDict):
147
+ id: int
148
+ command: str
149
+ schedule: str
150
+ name: Optional[str]
151
+ labels: List[str]
152
+ sub_id: Optional[int]
153
+ extra_schedules: List[ExtraScheduleItem]
154
+ task_before: Optional[str]
155
+ task_after: Optional[str]
156
+
157
+
158
+ class DeleteCronsParams(TypedDict):
159
+ ids: List[int]
160
+
161
+
162
+ class CronDetailParams(TypedDict):
163
+ log_path: str
164
+
165
+
166
+ class CronsResponse(TypedDict):
167
+ code: int
168
+ data: List[CronItem]
169
+ message: Optional[str]
170
+
171
+
172
+ class CronResponse(TypedDict):
173
+ code: int
174
+ data: CronItem
175
+ message: Optional[str]
176
+
177
+
24
178
  class Client:
25
179
  def __init__(self):
26
180
  self.temp_dir = tempfile.mkdtemp(prefix="node_client_")
@@ -46,7 +200,8 @@ class Client:
46
200
  }} catch (error) {{
47
201
  console.error(JSON.stringify({{
48
202
  error: error.message,
49
- stack: error.stack
203
+ stack: error.stack,
204
+ name: error.name
50
205
  }}));
51
206
  process.exit(1);
52
207
  }}
@@ -56,58 +211,73 @@ class Client:
56
211
  with open(self.temp_script, "w", encoding="utf-8") as f:
57
212
  f.write(node_code)
58
213
 
59
- try:
60
- result = subprocess.run(
61
- ["node", self.temp_script],
62
- capture_output=True,
63
- text=True,
64
- timeout=30,
65
- )
214
+ result = subprocess.run(
215
+ ["node", self.temp_script],
216
+ capture_output=True,
217
+ text=True,
218
+ timeout=30,
219
+ )
66
220
 
67
- if result.returncode != 0:
68
- error_data = json.loads(result.stderr)
69
- raise Exception(f"{error_data.get('stack')}")
221
+ if result.returncode != 0:
222
+ error_data = json.loads(result.stderr)
223
+ raise Exception(
224
+ f"{error_data.get('name', 'Error')}: {error_data.get('stack')}"
225
+ )
70
226
 
71
- return json.loads(result.stdout)
72
- except subprocess.TimeoutExpired:
73
- raise Exception("node process timeout")
227
+ return json.loads(result.stdout)
74
228
 
75
229
  @error_handler
76
- def getEnvs(self, params: Dict = None) -> Dict:
230
+ def getEnvs(self, params: GetEnvsParams = None) -> EnvsResponse:
77
231
  return self._execute_node("getEnvs", params)
78
232
 
79
233
  @error_handler
80
- def createEnv(self, data: Dict) -> Dict:
234
+ def createEnv(self, data: CreateEnvParams) -> EnvsResponse:
81
235
  return self._execute_node("createEnv", data)
82
236
 
83
237
  @error_handler
84
- def updateEnv(self, data: Dict) -> Dict:
238
+ def updateEnv(self, data: UpdateEnvParams) -> EnvResponse:
85
239
  return self._execute_node("updateEnv", data)
86
240
 
87
241
  @error_handler
88
- def deleteEnvs(self, data: Dict) -> Dict:
242
+ def deleteEnvs(self, data: DeleteEnvsParams) -> Response:
89
243
  return self._execute_node("deleteEnvs", data)
90
244
 
91
245
  @error_handler
92
- def moveEnv(self, data: Dict) -> Dict:
246
+ def moveEnv(self, data: MoveEnvParams) -> EnvResponse:
93
247
  return self._execute_node("moveEnv", data)
94
248
 
95
249
  @error_handler
96
- def disableEnvs(self, data: Dict) -> Dict:
250
+ def disableEnvs(self, data: DisableEnvsParams) -> Response:
97
251
  return self._execute_node("disableEnvs", data)
98
252
 
99
253
  @error_handler
100
- def enableEnvs(self, data: Dict) -> Dict:
254
+ def enableEnvs(self, data: EnableEnvsParams) -> Response:
101
255
  return self._execute_node("enableEnvs", data)
102
256
 
103
257
  @error_handler
104
- def updateEnvNames(self, data: Dict) -> Dict:
258
+ def updateEnvNames(self, data: UpdateEnvNamesParams) -> Response:
105
259
  return self._execute_node("updateEnvNames", data)
106
260
 
107
261
  @error_handler
108
- def getEnvById(self, data: Dict) -> Dict:
262
+ def getEnvById(self, data: GetEnvByIdParams) -> EnvResponse:
109
263
  return self._execute_node("getEnvById", data)
110
264
 
111
265
  @error_handler
112
- def systemNotify(self, data: Dict) -> Dict:
266
+ def systemNotify(self, data: SystemNotifyParams) -> Response:
113
267
  return self._execute_node("systemNotify", data)
268
+
269
+ @error_handler
270
+ def getCronDetail(self, data: CronDetailParams) -> CronResponse:
271
+ return self._execute_node("getCronDetail", data)
272
+
273
+ @error_handler
274
+ def createCron(self, data: CreateCronParams) -> CronResponse:
275
+ return self._execute_node("createCron", data)
276
+
277
+ @error_handler
278
+ def updateCron(self, data: UpdateCronParams) -> CronResponse:
279
+ return self._execute_node("updateCron", data)
280
+
281
+ @error_handler
282
+ def deleteCrons(self, data: DeleteCronsParams) -> Response:
283
+ return self._execute_node("deleteCrons", data)
@@ -98,7 +98,7 @@ try {
98
98
 
99
99
  run();
100
100
 
101
- const { sendNotify } = require('./notify.js');
101
+ const { sendNotify } = require('./__ql_notify__.js');
102
102
  global.QLAPI = {
103
103
  notify: sendNotify,
104
104
  ...client,
@@ -107,7 +107,7 @@ try:
107
107
 
108
108
  run()
109
109
 
110
- from notify import send
110
+ from __ql_notify__ import send
111
111
 
112
112
  class BaseApi(Client):
113
113
  def notify(self, *args, **kwargs):
package/shell/share.sh CHANGED
@@ -474,17 +474,17 @@ handle_task_end() {
474
474
  local end_timestamp=$(format_timestamp "$time_format" "$etime")
475
475
  local diff_time=$(($end_timestamp - $begin_timestamp))
476
476
  local suffix=""
477
- [[ "$MANUAL" == "true" ]] && suffix="(手动停止)"
477
+ [[ "${MANUAL:=}" == "true" ]] && suffix="(手动停止)"
478
478
 
479
479
  [[ "$diff_time" == 0 ]] && diff_time=1
480
480
 
481
481
  if [[ $ID ]]; then
482
- local error=$(update_cron "\"$ID\"" "1" "" "$log_path" "$begin_timestamp" "$diff_time")
482
+ local error=$(update_cron "\"$ID\"" "1" "$$" "$log_path" "$begin_timestamp" "$diff_time")
483
483
  if [[ $error ]]; then
484
484
  error_message=", 任务状态更新失败(${error})"
485
485
  fi
486
486
  fi
487
- echo -e "\n## 执行结束$suffix... $end_time 耗时 $diff_time 秒${error_message}     "
487
+ echo -e "\n## 执行结束$suffix... $end_time 耗时 $diff_time 秒${error_message:=}     "
488
488
  }
489
489
 
490
490
  init_env
package/shell/update.sh CHANGED
@@ -543,6 +543,9 @@ main() {
543
543
  resettfa)
544
544
  eval update_auth_config "\\\"twoFactorActivated\\\":false" "禁用两步验证" $cmd
545
545
  ;;
546
+ resetpwd)
547
+ eval update_auth_config "\\\"password\\\":\\\"$p2\\\"" "重置密码" $cmd
548
+ ;;
546
549
  *)
547
550
  eval echo -e "命令输入错误...\\\n" $cmd
548
551
  eval usage $cmd
@@ -553,7 +556,7 @@ main() {
553
556
  local end_time=$(format_time "$time_format" "$etime")
554
557
  local end_timestamp=$(format_timestamp "$time_format" "$etime")
555
558
  local diff_time=$(($end_timestamp - $begin_timestamp))
556
- [[ $ID ]] && update_cron "\"$ID\"" "1" "" "$log_path" "$begin_timestamp" "$diff_time"
559
+ [[ $ID ]] && update_cron "\"$ID\"" "1" "$$" "$log_path" "$begin_timestamp" "$diff_time"
557
560
 
558
561
  if [[ "$p1" != "repo" ]] && [[ "$p1" != "raw" ]]; then
559
562
  eval echo -e "\\\n\#\# 执行结束... $end_time 耗时 $diff_time 秒     " $cmd
@@ -8,7 +8,7 @@ const typedi_1 = require("typedi");
8
8
  const cron_1 = __importDefault(require("../services/cron"));
9
9
  const cronView_1 = __importDefault(require("../services/cronView"));
10
10
  const celebrate_1 = require("celebrate");
11
- const cron_parser_1 = __importDefault(require("cron-parser"));
11
+ const schedule_1 = require("../validation/schedule");
12
12
  const route = (0, express_1.Router)();
13
13
  exports.default = (app) => {
14
14
  app.use('/crons', route);
@@ -141,27 +141,13 @@ exports.default = (app) => {
141
141
  }
142
142
  });
143
143
  route.post('/', (0, celebrate_1.celebrate)({
144
- body: celebrate_1.Joi.object({
145
- command: celebrate_1.Joi.string().required(),
146
- schedule: celebrate_1.Joi.string().required(),
147
- name: celebrate_1.Joi.string().optional(),
148
- labels: celebrate_1.Joi.array().optional(),
149
- sub_id: celebrate_1.Joi.number().optional().allow(null),
150
- extra_schedules: celebrate_1.Joi.array().optional().allow(null),
151
- task_before: celebrate_1.Joi.string().optional().allow('').allow(null),
152
- task_after: celebrate_1.Joi.string().optional().allow('').allow(null),
153
- }),
144
+ body: celebrate_1.Joi.object(schedule_1.commonCronSchema),
154
145
  }), async (req, res, next) => {
155
146
  const logger = typedi_1.Container.get('logger');
156
147
  try {
157
- if (cron_parser_1.default.parseExpression(req.body.schedule).hasNext()) {
158
- const cronService = typedi_1.Container.get(cron_1.default);
159
- const data = await cronService.create(req.body);
160
- return res.send({ code: 200, data });
161
- }
162
- else {
163
- return res.send({ code: 400, message: 'param schedule error' });
164
- }
148
+ const cronService = typedi_1.Container.get(cron_1.default);
149
+ const data = await cronService.create(req.body);
150
+ return res.send({ code: 200, data });
165
151
  }
166
152
  catch (e) {
167
153
  return next(e);
@@ -267,29 +253,13 @@ exports.default = (app) => {
267
253
  }
268
254
  });
269
255
  route.put('/', (0, celebrate_1.celebrate)({
270
- body: celebrate_1.Joi.object({
271
- labels: celebrate_1.Joi.array().optional().allow(null),
272
- command: celebrate_1.Joi.string().required(),
273
- schedule: celebrate_1.Joi.string().required(),
274
- name: celebrate_1.Joi.string().optional().allow(null),
275
- sub_id: celebrate_1.Joi.number().optional().allow(null),
276
- extra_schedules: celebrate_1.Joi.array().optional().allow(null),
277
- task_before: celebrate_1.Joi.string().optional().allow('').allow(null),
278
- task_after: celebrate_1.Joi.string().optional().allow('').allow(null),
279
- id: celebrate_1.Joi.number().required(),
280
- }),
256
+ body: celebrate_1.Joi.object(Object.assign(Object.assign({}, schedule_1.commonCronSchema), { id: celebrate_1.Joi.number().required() })),
281
257
  }), async (req, res, next) => {
282
258
  const logger = typedi_1.Container.get('logger');
283
259
  try {
284
- if (!req.body.schedule ||
285
- cron_parser_1.default.parseExpression(req.body.schedule).hasNext()) {
286
- const cronService = typedi_1.Container.get(cron_1.default);
287
- const data = await cronService.update(req.body);
288
- return res.send({ code: 200, data });
289
- }
290
- else {
291
- return res.send({ code: 400, message: 'param schedule error' });
292
- }
260
+ const cronService = typedi_1.Container.get(cron_1.default);
261
+ const data = await cronService.update(req.body);
262
+ return res.send({ code: 200, data });
293
263
  }
294
264
  catch (e) {
295
265
  return next(e);
@@ -338,7 +308,7 @@ exports.default = (app) => {
338
308
  const logger = typedi_1.Container.get('logger');
339
309
  try {
340
310
  const cronService = typedi_1.Container.get(cron_1.default);
341
- const data = await cronService.import_crontab();
311
+ const data = await cronService.importCrontab();
342
312
  return res.send({ code: 200, data });
343
313
  }
344
314
  catch (e) {