zcatalyst-cli 1.17.4 → 1.18.0-beta.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 (42) hide show
  1. package/docs/command_needs/rc.toml +2 -2
  2. package/docs/commands/functions/shell.toml +4 -0
  3. package/docs/endpoints/lib/env.toml +3 -0
  4. package/docs/shell/dependencies/tunnel-server.toml +4 -0
  5. package/docs/shell/index.toml +7 -0
  6. package/lib/appsail-utils.js +7 -1
  7. package/lib/command_needs/rc.js +8 -8
  8. package/lib/commands/functions/shell.js +97 -1
  9. package/lib/commands/serve.js +1 -1
  10. package/lib/deploy/features/appsail/index.js +4 -3
  11. package/lib/deploy/features/appsail/utils.js +1 -1
  12. package/lib/endpoints/index.js +8 -1
  13. package/lib/endpoints/lib/env.js +20 -2
  14. package/lib/endpoints/lib/sdk.js +2 -2
  15. package/lib/endpoints/lib/tunnel.js +66 -0
  16. package/lib/init/features/appsail/index.js +2 -2
  17. package/lib/internal/api.js +9 -1
  18. package/lib/port-resolver.js +1 -1
  19. package/lib/repl-server.js +9 -0
  20. package/lib/serve/server/lib/appsail/index.js +9 -8
  21. package/lib/serve/server/lib/master.js +18 -9
  22. package/lib/serve/server/lib/python/index.js +3 -0
  23. package/lib/shell/dependencies/http-functions.js +21 -8
  24. package/lib/shell/dependencies/invoker/bio/java/JavabioInvoker.java +28 -32
  25. package/lib/shell/dependencies/invoker/bio/node.mjs +2 -2
  26. package/lib/shell/dependencies/invoker/cron/java/JavacronInvoker.java +62 -13
  27. package/lib/shell/dependencies/invoker/cron/node.mjs +28 -24
  28. package/lib/shell/dependencies/invoker/event/java/JavaeventInvoker.java +40 -6
  29. package/lib/shell/dependencies/invoker/event/node.mjs +22 -9
  30. package/lib/shell/dependencies/invoker/integ/java/JavaintegInvoker.java +3 -3
  31. package/lib/shell/dependencies/invoker/integ/node.mjs +6 -6
  32. package/lib/shell/dependencies/local-function.js +290 -199
  33. package/lib/shell/dependencies/tunnel-server.js +173 -0
  34. package/lib/shell/index.js +55 -1
  35. package/lib/shell/prepare/languages/java.js +1 -1
  36. package/lib/shell/prepare/languages/node.js +3 -1
  37. package/lib/shell/prepare/languages/python.js +1 -0
  38. package/lib/util_modules/constants/index.js +3 -1
  39. package/lib/util_modules/constants/lib/needed-scopes.js +52 -0
  40. package/lib/util_modules/constants/lib/scopes.js +5 -0
  41. package/lib/util_modules/constants/lib/urls.js +8 -0
  42. package/package.json +3 -3
@@ -28,10 +28,290 @@ const logger_1 = require("../../util_modules/logger");
28
28
  const project_1 = require("../../util_modules/project");
29
29
  const shell_1 = require("../../util_modules/shell");
30
30
  const http_functions_1 = require("../dependencies/http-functions");
31
+ const events_1 = __importDefault(require("events"));
31
32
  const ensure_java_userconfig_1 = require("../../fn-utils/lib/ensure-java-userconfig");
32
33
  class LocalFunction {
33
34
  constructor(repl, target) {
34
35
  var _a, _b, _c;
36
+ this.localFnEvents = new events_1.default();
37
+ this.killed = false;
38
+ this._call = (shell = true) => (rawData = {}) => {
39
+ let data;
40
+ try {
41
+ if (shell) {
42
+ if (typeof rawData === 'string') {
43
+ const content = fs_1.SYNC.readJSONFile((0, path_1.resolve)(runtime_store_1.default.get('cwd'), rawData));
44
+ if (content === undefined) {
45
+ return new error_1.default('content is undefined for provided file path');
46
+ }
47
+ rawData = content;
48
+ }
49
+ switch (this.target.type) {
50
+ case constants_1.FN_TYPE.cron: {
51
+ data = { data: rawData };
52
+ break;
53
+ }
54
+ case constants_1.FN_TYPE.event:
55
+ if (!('event_bus_details' in rawData)) {
56
+ (0, logger_1.info)('For event function kindly use event:generate command to generate the input json.');
57
+ (0, logger_1.info)('You can also provide event details as per documentation.');
58
+ return new error_1.default('Event bus details missing');
59
+ }
60
+ data = rawData;
61
+ break;
62
+ default: {
63
+ data = rawData;
64
+ }
65
+ }
66
+ }
67
+ else {
68
+ data = rawData;
69
+ }
70
+ }
71
+ catch (e) {
72
+ (0, logger_1.info)('the input must be in the form of json or a path to a file containing json data.');
73
+ return new error_1.default('Invalid input');
74
+ }
75
+ return (() => __awaiter(this, void 0, void 0, function* () {
76
+ var _a, _b, _c, _d, _e, _f;
77
+ const projectRoot = runtime_store_1.default.get('project.root');
78
+ const accessToken = yield credential_1.default.getAccessToken();
79
+ const slaveOptions = [];
80
+ const debugPort = runtime_store_1.default.get('context.port.debug.' + constants_1.FN_TYPE.basic, null);
81
+ yield fs_1.ASYNC.ensureFile(this.responseFile, true);
82
+ yield fs_1.ASYNC.ensureFile(this.metaFile, true);
83
+ const slaveFnTarget = { index: this.target.index, name: this.target.name };
84
+ if ((_a = this.target.stack) === null || _a === void 0 ? void 0 : _a.startsWith(runtime_1.default.language.node.value)) {
85
+ if (debugPort !== null) {
86
+ slaveOptions.push('--inspect-brk=' + debugPort);
87
+ }
88
+ slaveOptions.push(this.nodeInvoker);
89
+ slaveOptions.push(JSON.stringify(slaveFnTarget));
90
+ slaveOptions.push(JSON.stringify(data));
91
+ slaveOptions.push(JSON.stringify({
92
+ 'x-zc-projectid': (0, project_1.getProjectId)(),
93
+ 'x-zc-project-domain': (0, project_1.getDomainPrefix)() + '.' + constants_1.ORIGIN.app.replace('https://', ''),
94
+ 'x-zc-project-key': (0, project_1.getDomainKey)(),
95
+ 'x-zc-environment': (0, project_1.getEnvName)()
96
+ }));
97
+ slaveOptions.push(JSON.stringify({
98
+ 'x-zc-user-cred-type': 'token',
99
+ 'x-zc-user-cred-token': accessToken,
100
+ 'x-zc-admin-cred-type': 'token',
101
+ 'x-zc-admin-cred-token': accessToken,
102
+ 'x-zc-user-type': 'admin'
103
+ }));
104
+ slaveOptions.push(JSON.stringify((0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build)));
105
+ this.slave = (0, shell_1.spawn)('node', slaveOptions, {
106
+ cwd: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name),
107
+ stdio: 'pipe',
108
+ env: Object.assign({ X_ZOHO_CATALYST_IS_LOCAL: 'true', X_ZOHO_CATALYST_FUNCTION_LOADED: 'true', X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone) }, this.target.env_var)
109
+ }).RAW();
110
+ }
111
+ else if ((_b = this.target.stack) === null || _b === void 0 ? void 0 : _b.startsWith(runtime_1.default.language.java.value)) {
112
+ const javaInvokerDir = (0, path_1.parse)(this.javaInvoker).dir;
113
+ slaveOptions.push('-cp');
114
+ slaveOptions.push(javaInvokerDir +
115
+ fn_utils_1.fnUtils.java.classPathSep +
116
+ (0, path_1.join)(javaInvokerDir, 'lib', '*'));
117
+ if (debugPort !== null) {
118
+ slaveOptions.push('-Xdebug');
119
+ slaveOptions.push('-Xrunjdwp:transport=dt_socket,address=' +
120
+ debugPort +
121
+ ',server=y,suspend=y');
122
+ }
123
+ slaveOptions.push((0, path_1.basename)(this.javaInvoker));
124
+ slaveOptions.push(javaInvokerDir);
125
+ slaveOptions.push(JSON.stringify(slaveFnTarget));
126
+ slaveOptions.push(JSON.stringify(data));
127
+ slaveOptions.push(JSON.stringify({
128
+ 'x-zc-projectid': (0, project_1.getProjectId)(),
129
+ 'x-zc-project-domain': (0, project_1.getDomainPrefix)() + '.' + constants_1.ORIGIN.app.replace('https://', ''),
130
+ 'x-zc-project-key': (0, project_1.getDomainKey)(),
131
+ 'x-zc-environment': (0, project_1.getEnvName)()
132
+ }));
133
+ slaveOptions.push(JSON.stringify({
134
+ 'x-zc-user-cred-type': 'token',
135
+ 'x-zc-user-cred-token': accessToken,
136
+ 'x-zc-admin-cred-type': 'token',
137
+ 'x-zc-admin-cred-token': accessToken,
138
+ 'x-zc-user-type': 'admin'
139
+ }));
140
+ const configKey = `${this.target.stack}.bin`;
141
+ const userConfigCmd = userConfig_1.default.get(configKey);
142
+ const spawnCommand = (0, ensure_java_userconfig_1.getJavaSpawnCommand)(userConfigCmd, 'java', this.target.stack);
143
+ this.slave = (0, shell_1.spawn)(spawnCommand, slaveOptions, {
144
+ cwd: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name),
145
+ stdio: 'pipe',
146
+ env: Object.assign({ X_ZOHO_CATALYST_IS_LOCAL: 'true', X_ZOHO_CATALYST_FUNCTION_LOADED: 'true', X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone) }, this.target.env_var)
147
+ }).RAW();
148
+ }
149
+ else if ((_c = this.target.stack) === null || _c === void 0 ? void 0 : _c.startsWith(runtime_1.default.language.python.value)) {
150
+ const stackVersion = (_d = this.target.stack) === null || _d === void 0 ? void 0 : _d.replace('python_', '');
151
+ const runtimesDir = constants_1.ENVPATH.runtimes.data;
152
+ const httpPort = parseInt(runtime_store_1.default.get('context.port.http.' + constants_1.REMOTE_REF.functions.type[constants_1.FN_TYPE.basic]), 10);
153
+ const runTimePort = yield port_resolver_1.default.getFreePort(httpPort, 20, false);
154
+ yield fs_1.ASYNC.ensureFile(this.responseFile, true);
155
+ yield fs_1.ASYNC.ensureFile(this.metaFile, true);
156
+ slaveOptions.push('-u');
157
+ slaveOptions.push((0, path_1.join)(runtimesDir, runtime_1.default.language.python.value, `zcatalyst_runtime_${stackVersion.replace('_', '')}`, 'main.py'));
158
+ this.slave = (0, shell_1.spawn)(userConfig_1.default.get(`python${stackVersion}.bin`), slaveOptions, {
159
+ cwd: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name),
160
+ stdio: 'pipe',
161
+ env: Object.assign({ X_ZOHO_CATALYST_IS_LOCAL: 'true', X_ZOHO_CATALYST_FUNCTION_LOADED: 'true', X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, X_ZOHO_CATALYST_CODE_LOCATION: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name), X_ZOHO_CATALYST_SERVER_LISTEN_PORT: runTimePort.toString(), CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone) }, this.target.env_var)
162
+ }).RAW();
163
+ this.slave.once('spawn', () => __awaiter(this, void 0, void 0, function* () {
164
+ const jsonData = data;
165
+ jsonData.timestamp = Date.now();
166
+ const reqJson = JSON.stringify(jsonData);
167
+ yield (0, http_functions_1.checkIfRuntimeServerRunning)(runTimePort.toString());
168
+ const writeResponse = (response, status) => {
169
+ fs_1.SYNC.writeFile(this.responseFile, response);
170
+ fs_1.SYNC.writeFile(this.metaFile, JSON.stringify({ response: { statusCode: status } }));
171
+ };
172
+ const req = http_1.default
173
+ .request(`http://127.0.0.1:${runTimePort}`, {
174
+ headers: {
175
+ 'x-zc-projectid': (0, project_1.getProjectId)(),
176
+ 'x-zc-project-domain': (0, project_1.getDomainPrefix)() +
177
+ '.' +
178
+ constants_1.ORIGIN.app.replace('https://', ''),
179
+ 'x-zc-project-key': (0, project_1.getDomainKey)(),
180
+ 'x-zc-environment': (0, project_1.getEnvName)(),
181
+ 'x-zc-user-cred-type': 'token',
182
+ 'x-zc-user-cred-token': accessToken,
183
+ 'x-zc-admin-cred-type': 'token',
184
+ 'x-zc-admin-cred-token': accessToken,
185
+ 'x-zc-user-type': 'admin',
186
+ 'Content-Length': reqJson.length
187
+ }
188
+ }, (resp) => {
189
+ var _a;
190
+ if ([
191
+ constants_1.REMOTE_REF.functions.type.cron,
192
+ constants_1.REMOTE_REF.functions.type.event
193
+ ].includes(this.target.type + '')) {
194
+ switch (resp.statusCode) {
195
+ case 200: {
196
+ writeResponse('SUCCESS', 200);
197
+ break;
198
+ }
199
+ case 532: {
200
+ writeResponse('CODE_EXCEPTION', 532);
201
+ break;
202
+ }
203
+ case 530: {
204
+ writeResponse('FAILURE', 530);
205
+ break;
206
+ }
207
+ case 500: {
208
+ writeResponse('INTERNAL_SERVER_ERROR', 500);
209
+ break;
210
+ }
211
+ }
212
+ (_a = this.slave) === null || _a === void 0 ? void 0 : _a.kill('SIGTERM');
213
+ return;
214
+ }
215
+ resp.on('data', (data) => {
216
+ const respStr = data.toString();
217
+ fs_1.SYNC.writeFile(this.responseFile, respStr);
218
+ });
219
+ resp.on('close', () => {
220
+ var _a;
221
+ const metaJson = {
222
+ response: { statusCode: resp.statusCode }
223
+ };
224
+ fs_1.SYNC.writeFile(this.metaFile, JSON.stringify(metaJson));
225
+ (_a = this.slave) === null || _a === void 0 ? void 0 : _a.kill('SIGTERM');
226
+ });
227
+ })
228
+ .on('error', (err) => {
229
+ var _a;
230
+ (0, logger_1.debug)(err);
231
+ (_a = this.slave) === null || _a === void 0 ? void 0 : _a.kill('SIGTERM');
232
+ });
233
+ req.write(reqJson);
234
+ req.end();
235
+ }));
236
+ }
237
+ if (this.slave === null) {
238
+ throw new error_1.default('Slave listening started before initializing', {
239
+ exit: 2
240
+ });
241
+ }
242
+ (_e = this.slave.stdout) === null || _e === void 0 ? void 0 : _e.on('data', (message) => {
243
+ (0, shell_1.clearLine)(process.stdout);
244
+ (0, logger_1.info)(message.toString());
245
+ });
246
+ (_f = this.slave.stderr) === null || _f === void 0 ? void 0 : _f.on('data', (message) => {
247
+ const errorStr = js_1.JS.trim(message.toString());
248
+ (0, shell_1.clearLine)(process.stdout);
249
+ (0, logger_1.info)(errorStr);
250
+ });
251
+ this.slave.on('exit', (code, sig) => __awaiter(this, void 0, void 0, function* () {
252
+ (0, logger_1.debug)(`local fn slave exit: ${code}, ${sig}`);
253
+ if (code === 0) {
254
+ (0, logger_1.info)(`[CLI] Function ${this.target.name} execution complete`);
255
+ (0, logger_1.info)();
256
+ const response = yield fs_1.ASYNC.readFile(this.responseFile);
257
+ let meta;
258
+ try {
259
+ meta = JSON.parse((yield fs_1.ASYNC.readFile(this.metaFile))).response;
260
+ }
261
+ catch (err) {
262
+ meta = {};
263
+ }
264
+ switch (this.target.type) {
265
+ case constants_1.FN_TYPE.basic:
266
+ (0, logger_1.info)(`[response - ${this.target.name}] ${response + ''}`);
267
+ (0, logger_1.info)(`[status - ${this.target.name}] ${(meta.statusCode || 200) + ''}`);
268
+ this.localFnEvents.emit('response', {
269
+ data: response,
270
+ status: meta.statsCode
271
+ });
272
+ break;
273
+ case constants_1.FN_TYPE.cron:
274
+ case constants_1.FN_TYPE.event:
275
+ (0, logger_1.info)(`[status - ${this.target.name}] ${response || 'Unknown'}`);
276
+ if (!response) {
277
+ (0, logger_1.info)(`[CLI] Make sure to close the ${this.target.name} (${this.target.type}) function.`);
278
+ }
279
+ this.localFnEvents.emit('response', {
280
+ status: meta.statusCode
281
+ });
282
+ break;
283
+ case constants_1.FN_TYPE.integration:
284
+ (0, logger_1.info)(`[response - ${this.target.name}] ${response + ''}`);
285
+ try {
286
+ this.localFnEvents.emit('response', JSON.parse(response || ''));
287
+ }
288
+ catch (er) {
289
+ (0, logger_1.debug)('Invalid integration response: ', er);
290
+ }
291
+ break;
292
+ }
293
+ }
294
+ else {
295
+ (code === 130 || sig === 'SIGINT') &&
296
+ (0, logger_1.info)(`[CLI] Function ${this.target.name} interrupted`);
297
+ (code === 143 ||
298
+ sig === 'SIGTERM' ||
299
+ sig === 'SIGQUIT' ||
300
+ sig === 'SIGKILL') &&
301
+ (0, logger_1.info)(`[CLI] Function ${this.target.name} process killed`);
302
+ this.localFnEvents.listenerCount('error') > 0 &&
303
+ this.localFnEvents.emit('error', new error_1.default(`Function(${this.target.name}) process exited with ${code ? 'status: ' + code : 'signal: ' + sig}`, {
304
+ skipHelp: true
305
+ }));
306
+ }
307
+ this.repl.showPrompt();
308
+ }));
309
+ this.slave.on('error', (err) => {
310
+ this.localFnEvents.emit('error', err);
311
+ });
312
+ return this.slave;
313
+ }))();
314
+ };
35
315
  if (target.type === undefined ||
36
316
  !Object.values(constants_1.FN_TYPE).includes(target.type)) {
37
317
  throw new error_1.default('target type is not defined', { exit: 2 });
@@ -66,209 +346,12 @@ class LocalFunction {
66
346
  }, 1000);
67
347
  });
68
348
  }
69
- _call(rawData = {}) {
70
- let data;
71
- try {
72
- data = JSON.stringify(rawData);
73
- if (!data.startsWith('{') || !data.endsWith('}')) {
74
- const content = fs_1.SYNC.readFile((0, path_1.resolve)(runtime_store_1.default.get('cwd'), data.slice(1, data.length - 1)));
75
- if (content === undefined) {
76
- return new error_1.default('content is undefined for provided file path');
77
- }
78
- data = content;
79
- }
80
- }
81
- catch (e) {
82
- (0, logger_1.info)('the input must be in the form of json or a path to a file containing json data.');
83
- return new error_1.default('Invalid input');
84
- }
85
- if (this.target.type === constants_1.FN_TYPE.event && !data.includes('event_bus_details')) {
86
- (0, logger_1.info)('For event function kindly use event:generate command to generate the input json.');
87
- (0, logger_1.info)('You can also provide event details as per documentation.');
88
- return new error_1.default('Event bus details missing');
89
- }
90
- return (() => __awaiter(this, void 0, void 0, function* () {
91
- var _a, _b, _c, _d, _e, _f;
92
- const projectRoot = runtime_store_1.default.get('project.root');
93
- const accessToken = yield credential_1.default.getAccessToken();
94
- const slaveOptions = [];
95
- const debugPort = runtime_store_1.default.get('context.port.debug.' + constants_1.FN_TYPE.basic, null);
96
- yield fs_1.ASYNC.ensureFile(this.responseFile, true);
97
- yield fs_1.ASYNC.ensureFile(this.metaFile, true);
98
- const slaveFnTarget = { index: this.target.index, name: this.target.name };
99
- if ((_a = this.target.stack) === null || _a === void 0 ? void 0 : _a.startsWith(runtime_1.default.language.node.value)) {
100
- if (debugPort !== null) {
101
- slaveOptions.push('--inspect-brk=' + debugPort);
102
- }
103
- slaveOptions.push(this.nodeInvoker);
104
- slaveOptions.push(JSON.stringify(slaveFnTarget));
105
- slaveOptions.push(data);
106
- slaveOptions.push(JSON.stringify({
107
- 'x-zc-projectid': (0, project_1.getProjectId)(),
108
- 'x-zc-project-domain': (0, project_1.getDomainPrefix)() + '.' + constants_1.ORIGIN.app.replace('https://', ''),
109
- 'x-zc-project-key': (0, project_1.getDomainKey)(),
110
- 'x-zc-environment': (0, project_1.getEnvName)()
111
- }));
112
- slaveOptions.push(JSON.stringify({
113
- 'x-zc-user-cred-type': 'token',
114
- 'x-zc-user-cred-token': accessToken,
115
- 'x-zc-admin-cred-type': 'token',
116
- 'x-zc-admin-cred-token': accessToken,
117
- 'x-zc-user-type': 'admin'
118
- }));
119
- slaveOptions.push(JSON.stringify((0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build)));
120
- this.slave = (0, shell_1.spawn)('node', slaveOptions, {
121
- cwd: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name),
122
- stdio: 'pipe',
123
- env: Object.assign({ X_ZOHO_CATALYST_IS_LOCAL: 'true', X_ZOHO_CATALYST_FUNCTION_LOADED: 'true', X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone) }, this.target.env_var)
124
- }).RAW();
125
- }
126
- else if ((_b = this.target.stack) === null || _b === void 0 ? void 0 : _b.startsWith(runtime_1.default.language.java.value)) {
127
- const javaInvokerDir = (0, path_1.parse)(this.javaInvoker).dir;
128
- slaveOptions.push('-cp');
129
- slaveOptions.push(javaInvokerDir + fn_utils_1.fnUtils.java.classPathSep + (0, path_1.join)(javaInvokerDir, 'lib', '*'));
130
- if (debugPort !== null) {
131
- slaveOptions.push('-Xdebug');
132
- slaveOptions.push('-Xrunjdwp:transport=dt_socket,address=' + debugPort + ',server=y,suspend=y');
133
- }
134
- slaveOptions.push((0, path_1.basename)(this.javaInvoker));
135
- slaveOptions.push(javaInvokerDir);
136
- slaveOptions.push(JSON.stringify(slaveFnTarget));
137
- slaveOptions.push(data);
138
- slaveOptions.push(JSON.stringify({
139
- 'x-zc-projectid': (0, project_1.getProjectId)(),
140
- 'x-zc-project-domain': (0, project_1.getDomainPrefix)() + '.' + constants_1.ORIGIN.app.replace('https://', ''),
141
- 'x-zc-project-key': (0, project_1.getDomainKey)(),
142
- 'x-zc-environment': (0, project_1.getEnvName)()
143
- }));
144
- slaveOptions.push(JSON.stringify({
145
- 'x-zc-user-cred-type': 'token',
146
- 'x-zc-user-cred-token': accessToken,
147
- 'x-zc-admin-cred-type': 'token',
148
- 'x-zc-admin-cred-token': accessToken,
149
- 'x-zc-user-type': 'admin'
150
- }));
151
- const configKey = `${this.target.stack}.bin`;
152
- const userConfigCmd = userConfig_1.default.get(configKey);
153
- const spawnCommand = (0, ensure_java_userconfig_1.getJavaSpawnCommand)(userConfigCmd, 'java', this.target.stack);
154
- this.slave = (0, shell_1.spawn)(spawnCommand, slaveOptions, {
155
- cwd: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name),
156
- stdio: 'pipe',
157
- env: Object.assign({ X_ZOHO_CATALYST_IS_LOCAL: 'true', X_ZOHO_CATALYST_FUNCTION_LOADED: 'true', X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone) }, this.target.env_var)
158
- }).RAW();
159
- }
160
- else if ((_c = this.target.stack) === null || _c === void 0 ? void 0 : _c.startsWith(runtime_1.default.language.python.value)) {
161
- const stackVersion = (_d = this.target.stack) === null || _d === void 0 ? void 0 : _d.replace('python_', '');
162
- const runtimesDir = constants_1.ENVPATH.runtimes.data;
163
- const httpPort = parseInt(runtime_store_1.default.get('context.port.http.' + constants_1.REMOTE_REF.functions.type[constants_1.FN_TYPE.basic]), 10);
164
- const runTimePort = yield port_resolver_1.default.getFreePort(httpPort, 20, false);
165
- yield fs_1.ASYNC.ensureFile(this.responseFile, true);
166
- yield fs_1.ASYNC.ensureFile(this.metaFile, true);
167
- slaveOptions.push('-u');
168
- slaveOptions.push((0, path_1.join)(runtimesDir, runtime_1.default.language.python.value, `zcatalyst_runtime_${stackVersion.replace('_', '')}`, 'main.py'));
169
- this.slave = (0, shell_1.spawn)(userConfig_1.default.get(`python${stackVersion}.bin`), slaveOptions, {
170
- cwd: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name),
171
- stdio: 'pipe',
172
- env: Object.assign({ X_ZOHO_CATALYST_IS_LOCAL: 'true', X_ZOHO_CATALYST_FUNCTION_LOADED: 'true', X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, X_ZOHO_CATALYST_CODE_LOCATION: (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, constants_1.FOLDERNAME.functions, this.target.name), X_ZOHO_CATALYST_SERVER_LISTEN_PORT: runTimePort.toString(), CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone) }, this.target.env_var)
173
- }).RAW();
174
- this.slave.on('spawn', () => __awaiter(this, void 0, void 0, function* () {
175
- const jsonData = JSON.parse(data);
176
- jsonData.timestamp = Date.now();
177
- const reqJson = JSON.stringify(jsonData);
178
- yield (0, http_functions_1.checkIfRuntimeServerRunning)(runTimePort.toString());
179
- const req = http_1.default
180
- .request(`http://127.0.0.1:${runTimePort}`, {
181
- headers: {
182
- 'x-zc-projectid': (0, project_1.getProjectId)(),
183
- 'x-zc-project-domain': (0, project_1.getDomainPrefix)() +
184
- '.' +
185
- constants_1.ORIGIN.app.replace('https://', ''),
186
- 'x-zc-project-key': (0, project_1.getDomainKey)(),
187
- 'x-zc-environment': (0, project_1.getEnvName)(),
188
- 'x-zc-user-cred-type': 'token',
189
- 'x-zc-user-cred-token': accessToken,
190
- 'x-zc-admin-cred-type': 'token',
191
- 'x-zc-admin-cred-token': accessToken,
192
- 'x-zc-user-type': 'admin',
193
- 'Content-Length': reqJson.length
194
- }
195
- }, (resp) => {
196
- resp.on('data', (data) => {
197
- const respStr = data.toString();
198
- fs_1.SYNC.writeFile(this.responseFile, respStr);
199
- });
200
- resp.on('close', () => {
201
- var _a;
202
- const metaJson = { response: { statusCode: resp.statusCode } };
203
- fs_1.SYNC.writeFile(this.metaFile, JSON.stringify(metaJson));
204
- (_a = this.slave) === null || _a === void 0 ? void 0 : _a.kill('SIGINT');
205
- });
206
- })
207
- .on('error', (err) => {
208
- var _a;
209
- console.log(err);
210
- (_a = this.slave) === null || _a === void 0 ? void 0 : _a.kill('SIGINT');
211
- });
212
- req.write(reqJson);
213
- req.end();
214
- }));
215
- }
216
- if (this.slave === null) {
217
- throw new error_1.default('Slave listening started before initialising', {
218
- exit: 2
219
- });
220
- }
221
- (_e = this.slave.stdout) === null || _e === void 0 ? void 0 : _e.on('data', (message) => {
222
- (0, shell_1.clearLine)(process.stdout);
223
- (0, logger_1.info)(message.toString());
224
- });
225
- (_f = this.slave.stderr) === null || _f === void 0 ? void 0 : _f.on('data', (message) => {
226
- const errorStr = js_1.JS.trim(message.toString());
227
- (0, shell_1.clearLine)(process.stdout);
228
- (0, logger_1.info)(errorStr);
229
- });
230
- this.slave.on('exit', (code) => __awaiter(this, void 0, void 0, function* () {
231
- if (code !== null && code !== 130) {
232
- (0, logger_1.info)('[cli] Function execution complete');
233
- (0, logger_1.info)();
234
- const response = yield fs_1.ASYNC.readFile(this.responseFile);
235
- let meta;
236
- try {
237
- meta = JSON.parse((yield fs_1.ASYNC.readFile(this.metaFile))).response;
238
- }
239
- catch (err) {
240
- meta = {};
241
- }
242
- switch (this.target.type) {
243
- case constants_1.FN_TYPE.basic:
244
- (0, logger_1.info)('[response]');
245
- (0, logger_1.info)(response);
246
- (0, logger_1.info)('[status]');
247
- (0, logger_1.info)(meta.statusCode || 200);
248
- break;
249
- case constants_1.FN_TYPE.cron:
250
- case constants_1.FN_TYPE.event:
251
- (0, logger_1.info)('[status]');
252
- (0, logger_1.info)(response);
253
- break;
254
- case constants_1.FN_TYPE.integration:
255
- (0, logger_1.info)('[response]');
256
- (0, logger_1.info)(response);
257
- break;
258
- default:
259
- break;
260
- }
261
- }
262
- this.repl.showPrompt();
263
- }));
264
- return this.slave;
265
- }))();
266
- }
267
349
  shutdown() {
268
350
  return __awaiter(this, void 0, void 0, function* () {
269
351
  return new Promise((res) => {
270
352
  if (this.slave) {
271
- this.slave.kill('SIGINT');
353
+ this.killed = true;
354
+ this.slave.kill('SIGTERM');
272
355
  }
273
356
  if (this.watcher) {
274
357
  this.watcher.close().then(res).catch(res);
@@ -279,5 +362,13 @@ class LocalFunction {
279
362
  });
280
363
  });
281
364
  }
365
+ once(event, fn) {
366
+ this.localFnEvents.once(event, fn);
367
+ return this;
368
+ }
369
+ removeListener(event, fn) {
370
+ this.localFnEvents.removeListener(event, fn);
371
+ return this;
372
+ }
282
373
  }
283
374
  exports.default = LocalFunction;