@milaboratories/pl-deployments 2.4.6 → 2.4.8

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 (96) hide show
  1. package/dist/common/os_and_arch.cjs +39 -0
  2. package/dist/common/os_and_arch.cjs.map +1 -0
  3. package/dist/common/os_and_arch.d.ts +0 -1
  4. package/dist/common/os_and_arch.js +34 -0
  5. package/dist/common/os_and_arch.js.map +1 -0
  6. package/dist/common/pl_binary.cjs +34 -0
  7. package/dist/common/pl_binary.cjs.map +1 -0
  8. package/dist/common/pl_binary.d.ts +0 -1
  9. package/dist/common/pl_binary.js +30 -0
  10. package/dist/common/pl_binary.js.map +1 -0
  11. package/dist/common/pl_binary_download.cjs +172 -0
  12. package/dist/common/pl_binary_download.cjs.map +1 -0
  13. package/dist/common/pl_binary_download.d.ts +0 -1
  14. package/dist/common/pl_binary_download.js +148 -0
  15. package/dist/common/pl_binary_download.js.map +1 -0
  16. package/dist/common/pl_version.cjs +11 -0
  17. package/dist/common/pl_version.cjs.map +1 -0
  18. package/dist/common/pl_version.d.ts +0 -1
  19. package/dist/common/pl_version.js +9 -0
  20. package/dist/common/pl_version.js.map +1 -0
  21. package/dist/index.cjs +26 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.ts +0 -1
  24. package/dist/index.js +5 -64
  25. package/dist/index.js.map +1 -1
  26. package/dist/local/options.d.ts +0 -1
  27. package/dist/local/pid.cjs +24 -0
  28. package/dist/local/pid.cjs.map +1 -0
  29. package/dist/local/pid.d.ts +0 -1
  30. package/dist/local/pid.js +20 -0
  31. package/dist/local/pid.js.map +1 -0
  32. package/dist/local/pl.cjs +217 -0
  33. package/dist/local/pl.cjs.map +1 -0
  34. package/dist/local/pl.d.ts +0 -1
  35. package/dist/local/pl.js +192 -0
  36. package/dist/local/pl.js.map +1 -0
  37. package/dist/local/process.cjs +42 -0
  38. package/dist/local/process.cjs.map +1 -0
  39. package/dist/local/process.d.ts +0 -1
  40. package/dist/local/process.js +37 -0
  41. package/dist/local/process.js.map +1 -0
  42. package/dist/local/trace.cjs +27 -0
  43. package/dist/local/trace.cjs.map +1 -0
  44. package/dist/local/trace.d.ts +0 -1
  45. package/dist/local/trace.js +23 -0
  46. package/dist/local/trace.js.map +1 -0
  47. package/dist/package.json.cjs +7 -0
  48. package/dist/package.json.cjs.map +1 -0
  49. package/dist/package.json.js +5 -0
  50. package/dist/package.json.js.map +1 -0
  51. package/dist/ssh/__tests__/common-utils.d.ts +0 -1
  52. package/dist/ssh/connection_info.cjs +62 -0
  53. package/dist/ssh/connection_info.cjs.map +1 -0
  54. package/dist/ssh/connection_info.d.ts +0 -1
  55. package/dist/ssh/connection_info.js +55 -0
  56. package/dist/ssh/connection_info.js.map +1 -0
  57. package/dist/ssh/pl.cjs +500 -0
  58. package/dist/ssh/pl.cjs.map +1 -0
  59. package/dist/ssh/pl.d.ts +0 -1
  60. package/dist/ssh/pl.js +497 -0
  61. package/dist/ssh/pl.js.map +1 -0
  62. package/dist/ssh/pl_paths.cjs +67 -0
  63. package/dist/ssh/pl_paths.cjs.map +1 -0
  64. package/dist/ssh/pl_paths.d.ts +0 -1
  65. package/dist/ssh/pl_paths.js +50 -0
  66. package/dist/ssh/pl_paths.js.map +1 -0
  67. package/dist/ssh/ssh.cjs +621 -0
  68. package/dist/ssh/ssh.cjs.map +1 -0
  69. package/dist/ssh/ssh.d.ts +0 -1
  70. package/dist/ssh/ssh.js +619 -0
  71. package/dist/ssh/ssh.js.map +1 -0
  72. package/dist/ssh/supervisord.cjs +149 -0
  73. package/dist/ssh/supervisord.cjs.map +1 -0
  74. package/dist/ssh/supervisord.d.ts +0 -1
  75. package/dist/ssh/supervisord.js +140 -0
  76. package/dist/ssh/supervisord.js.map +1 -0
  77. package/package.json +16 -14
  78. package/src/common/pl_version.ts +3 -2
  79. package/dist/common/os_and_arch.d.ts.map +0 -1
  80. package/dist/common/pl_binary.d.ts.map +0 -1
  81. package/dist/common/pl_binary_download.d.ts.map +0 -1
  82. package/dist/common/pl_version.d.ts.map +0 -1
  83. package/dist/index.d.ts.map +0 -1
  84. package/dist/index.mjs +0 -1366
  85. package/dist/index.mjs.map +0 -1
  86. package/dist/local/options.d.ts.map +0 -1
  87. package/dist/local/pid.d.ts.map +0 -1
  88. package/dist/local/pl.d.ts.map +0 -1
  89. package/dist/local/process.d.ts.map +0 -1
  90. package/dist/local/trace.d.ts.map +0 -1
  91. package/dist/ssh/__tests__/common-utils.d.ts.map +0 -1
  92. package/dist/ssh/connection_info.d.ts.map +0 -1
  93. package/dist/ssh/pl.d.ts.map +0 -1
  94. package/dist/ssh/pl_paths.d.ts.map +0 -1
  95. package/dist/ssh/ssh.d.ts.map +0 -1
  96. package/dist/ssh/supervisord.d.ts.map +0 -1
@@ -0,0 +1,217 @@
1
+ 'use strict';
2
+
3
+ var process$1 = require('./process.cjs');
4
+ var pl_binary = require('../common/pl_binary.cjs');
5
+ var tsHelpers = require('@milaboratories/ts-helpers');
6
+ var pid = require('./pid.cjs');
7
+ var trace = require('./trace.cjs');
8
+ var upath = require('upath');
9
+ var fsp = require('node:fs/promises');
10
+ var os = require('node:os');
11
+
12
+ function _interopNamespaceDefault(e) {
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
30
+
31
+ const LocalConfigYaml = 'config-local.yaml';
32
+ /**
33
+ * Represents a local running pl-core,
34
+ * and has methods to start, check if it's running, stop and wait for stopping it.
35
+ * Also, a hook on pl-core closed can be provided.
36
+ */
37
+ class LocalPl {
38
+ logger;
39
+ workingDir;
40
+ startOptions;
41
+ initialStartHistory;
42
+ onClose;
43
+ onError;
44
+ onCloseAndError;
45
+ onCloseAndErrorNoStop;
46
+ instance;
47
+ pid;
48
+ nRuns = 0;
49
+ lastRunHistory = {};
50
+ wasStopped = false;
51
+ constructor(logger, workingDir, startOptions, initialStartHistory, onClose, onError, onCloseAndError, onCloseAndErrorNoStop) {
52
+ this.logger = logger;
53
+ this.workingDir = workingDir;
54
+ this.startOptions = startOptions;
55
+ this.initialStartHistory = initialStartHistory;
56
+ this.onClose = onClose;
57
+ this.onError = onError;
58
+ this.onCloseAndError = onCloseAndError;
59
+ this.onCloseAndErrorNoStop = onCloseAndErrorNoStop;
60
+ }
61
+ async start() {
62
+ await trace.withTrace(this.logger, async (trace, t) => {
63
+ this.wasStopped = false;
64
+ const instance = process$1.processRun(this.logger, this.startOptions);
65
+ instance.on('error', (e) => {
66
+ this.logger.error(`error '${e}', while running platforma, started opts: ${JSON.stringify(this.debugInfo())}`);
67
+ // keep in mind there are no awaits here, it will be asynchronous
68
+ if (this.onError !== undefined)
69
+ void this.onError(this);
70
+ if (this.onCloseAndError !== undefined)
71
+ void this.onCloseAndError(this);
72
+ if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)
73
+ void this.onCloseAndErrorNoStop(this);
74
+ });
75
+ instance.on('close', () => {
76
+ this.logger.warn(`platforma was closed, started opts: ${JSON.stringify(this.debugInfo())}`);
77
+ // keep in mind there are no awaits here, it will be asynchronous
78
+ if (this.onClose !== undefined)
79
+ void this.onClose(this);
80
+ if (this.onCloseAndError !== undefined)
81
+ void this.onCloseAndError(this);
82
+ if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)
83
+ void this.onCloseAndErrorNoStop(this);
84
+ });
85
+ trace('started', true);
86
+ const pidFile = trace('pidFile', pid.filePid(this.workingDir));
87
+ trace('pid', tsHelpers.notEmpty(instance.pid));
88
+ trace('pidWritten', await pid.writePid(pidFile, tsHelpers.notEmpty(instance.pid)));
89
+ this.nRuns++;
90
+ this.instance = instance;
91
+ this.pid = instance.pid;
92
+ this.lastRunHistory = t;
93
+ });
94
+ }
95
+ stop() {
96
+ // TODO use this.instance to stop the process
97
+ this.wasStopped = true;
98
+ process$1.processStop(tsHelpers.notEmpty(this.pid));
99
+ }
100
+ async waitStopped() {
101
+ await process$1.processWaitStopped(tsHelpers.notEmpty(this.pid), 15000);
102
+ }
103
+ stopped() {
104
+ return this.wasStopped;
105
+ }
106
+ async isAlive() {
107
+ return await process$1.isProcessAlive(tsHelpers.notEmpty(this.pid));
108
+ }
109
+ debugInfo() {
110
+ return {
111
+ lastRunHistory: this.lastRunHistory,
112
+ nRuns: this.nRuns,
113
+ pid: this.pid,
114
+ workingDir: this.workingDir,
115
+ initialStartHistory: this.initialStartHistory,
116
+ wasStopped: this.wasStopped,
117
+ };
118
+ }
119
+ }
120
+ /**
121
+ * Starts pl-core, if the option was provided downloads a binary, reads license environments etc.
122
+ */
123
+ async function localPlatformaInit(logger, _ops) {
124
+ // filling-in default values
125
+ // Backend could consume a lot of CPU power,
126
+ // we want to keep at least a couple for UI and other apps to work.
127
+ const numCpu = Math.max(os__namespace.cpus().length - 2, 1);
128
+ const ops = mergeDefaultOps(_ops, numCpu);
129
+ return await trace.withTrace(logger, async (trace, t) => {
130
+ trace('startOptions', { ...ops, config: 'too wordy' });
131
+ const workDir = upath.resolve(ops.workingDir);
132
+ if (ops.closeOld) {
133
+ trace('closeOld', await localPlatformaReadPidAndStop(logger, workDir));
134
+ }
135
+ const configPath = upath.join(workDir, LocalConfigYaml);
136
+ logger.info(`writing configuration '${configPath}'...`);
137
+ await fsp.writeFile(configPath, ops.config);
138
+ const plBinPath = upath.join(workDir, 'binaries');
139
+ const baseBinaryPath = await pl_binary.resolveLocalPlBinaryPath(logger, plBinPath, ops.plBinary);
140
+ const binaryPath = trace('binaryPath', upath.join('binaries', baseBinaryPath));
141
+ const processOpts = plProcessOps(binaryPath, configPath, ops, workDir, process.env);
142
+ trace('processOpts', {
143
+ cmd: processOpts.cmd,
144
+ args: processOpts.args,
145
+ cwd: processOpts.opts.cwd,
146
+ });
147
+ const pl = new LocalPl(logger, ops.workingDir, processOpts, t, ops.onClose, ops.onError, ops.onCloseAndError, ops.onCloseAndErrorNoStop);
148
+ await pl.start();
149
+ return pl;
150
+ });
151
+ }
152
+ /** Reads a pid of the old pl-core if it was started in the same working directory,
153
+ * and closes it. */
154
+ async function localPlatformaReadPidAndStop(logger, workingDir) {
155
+ return await trace.withTrace(logger, async (trace, t) => {
156
+ const file = trace('pidFilePath', pid.filePid(workingDir));
157
+ const oldPid = trace('pid', await pid.readPid(file));
158
+ const alive = trace('wasAlive', await process$1.isProcessAlive(oldPid));
159
+ if (oldPid !== undefined && alive) {
160
+ trace('stopped', process$1.processStop(oldPid));
161
+ trace('waitStopped', await process$1.processWaitStopped(oldPid, 10_000));
162
+ }
163
+ return t;
164
+ });
165
+ }
166
+ /** Gets default options for the whole init process
167
+ * and overrides them with the provided options. */
168
+ function mergeDefaultOps(ops, numCpu) {
169
+ const result = {
170
+ plBinary: pl_binary.newDefaultPlBinarySource(),
171
+ spawnOptions: {
172
+ env: {
173
+ GOMAXPROCS: String(numCpu),
174
+ },
175
+ },
176
+ closeOld: true,
177
+ };
178
+ if (ops.spawnOptions?.env) {
179
+ result.spawnOptions.env = { ...result.spawnOptions.env, ...ops.spawnOptions.env };
180
+ }
181
+ if (ops.spawnOptions) {
182
+ const withoutEnv = { ...ops.spawnOptions };
183
+ delete withoutEnv['env'];
184
+ result.spawnOptions = { ...result.spawnOptions, ...withoutEnv };
185
+ }
186
+ const withoutSpawnOps = { ...ops };
187
+ delete withoutSpawnOps['spawnOptions'];
188
+ return { ...result, ...withoutSpawnOps };
189
+ }
190
+ /** Gets default options for a platforma local binary
191
+ * and overrides them with the provided options. */
192
+ function plProcessOps(binaryPath, configPath, ops, workDir, defaultEnv) {
193
+ const result = {
194
+ cmd: binaryPath,
195
+ args: ['--config', configPath],
196
+ opts: {
197
+ env: { ...defaultEnv },
198
+ cwd: workDir,
199
+ stdio: ['pipe', 'ignore', 'inherit'],
200
+ windowsHide: true, // hide a terminal on Windows
201
+ },
202
+ };
203
+ if (ops.spawnOptions?.env) {
204
+ result.opts.env = { ...result.opts.env, ...ops.spawnOptions.env };
205
+ }
206
+ const withoutEnv = { ...ops.spawnOptions };
207
+ delete withoutEnv['env'];
208
+ result.opts = { ...result.opts, ...withoutEnv };
209
+ return result;
210
+ }
211
+
212
+ exports.LocalConfigYaml = LocalConfigYaml;
213
+ exports.LocalPl = LocalPl;
214
+ exports.localPlatformaInit = localPlatformaInit;
215
+ exports.mergeDefaultOps = mergeDefaultOps;
216
+ exports.plProcessOps = plProcessOps;
217
+ //# sourceMappingURL=pl.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pl.cjs","sources":["../../src/local/pl.ts"],"sourcesContent":["import type {\n ProcessOptions } from './process';\nimport {\n isProcessAlive,\n processStop,\n processWaitStopped,\n processRun,\n} from './process';\nimport type { PlBinarySource } from '../common/pl_binary';\nimport { newDefaultPlBinarySource, resolveLocalPlBinaryPath } from '../common/pl_binary';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport type { ChildProcess, SpawnOptions } from 'node:child_process';\nimport { filePid, readPid, writePid } from './pid';\nimport type { Trace } from './trace';\nimport { withTrace } from './trace';\nimport upath from 'upath';\nimport fsp from 'node:fs/promises';\nimport type { Required } from 'utility-types';\nimport * as os from 'node:os';\n\nexport const LocalConfigYaml = 'config-local.yaml';\n\n/**\n * Represents a local running pl-core,\n * and has methods to start, check if it's running, stop and wait for stopping it.\n * Also, a hook on pl-core closed can be provided.\n */\nexport class LocalPl {\n private instance?: ChildProcess;\n public pid?: number;\n private nRuns: number = 0;\n private lastRunHistory: Trace = {};\n private wasStopped = false;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly workingDir: string,\n private readonly startOptions: ProcessOptions,\n private readonly initialStartHistory: Trace,\n private readonly onClose?: (pl: LocalPl) => Promise<void>,\n private readonly onError?: (pl: LocalPl) => Promise<void>,\n private readonly onCloseAndError?: (pl: LocalPl) => Promise<void>,\n private readonly onCloseAndErrorNoStop?: (pl: LocalPl) => Promise<void>,\n ) {}\n\n async start() {\n await withTrace(this.logger, async (trace, t) => {\n this.wasStopped = false;\n const instance = processRun(this.logger, this.startOptions);\n instance.on('error', (e: any) => {\n this.logger.error(\n `error '${e}', while running platforma, started opts: ${JSON.stringify(this.debugInfo())}`,\n );\n\n // keep in mind there are no awaits here, it will be asynchronous\n if (this.onError !== undefined) void this.onError(this);\n if (this.onCloseAndError !== undefined) void this.onCloseAndError(this);\n if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)\n void this.onCloseAndErrorNoStop(this);\n });\n instance.on('close', () => {\n this.logger.warn(`platforma was closed, started opts: ${JSON.stringify(this.debugInfo())}`);\n\n // keep in mind there are no awaits here, it will be asynchronous\n if (this.onClose !== undefined) void this.onClose(this);\n if (this.onCloseAndError !== undefined) void this.onCloseAndError(this);\n if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)\n void this.onCloseAndErrorNoStop(this);\n });\n\n trace('started', true);\n\n const pidFile = trace('pidFile', filePid(this.workingDir));\n trace('pid', notEmpty(instance.pid));\n trace('pidWritten', await writePid(pidFile, notEmpty(instance.pid)));\n\n this.nRuns++;\n this.instance = instance;\n this.pid = instance.pid;\n this.lastRunHistory = t;\n });\n }\n\n stop() {\n // TODO use this.instance to stop the process\n this.wasStopped = true;\n processStop(notEmpty(this.pid));\n }\n\n async waitStopped() {\n await processWaitStopped(notEmpty(this.pid), 15000);\n }\n\n stopped() {\n return this.wasStopped;\n }\n\n async isAlive(): Promise<boolean> {\n return await isProcessAlive(notEmpty(this.pid));\n }\n\n debugInfo() {\n return {\n lastRunHistory: this.lastRunHistory,\n nRuns: this.nRuns,\n pid: this.pid,\n workingDir: this.workingDir,\n initialStartHistory: this.initialStartHistory,\n wasStopped: this.wasStopped,\n };\n }\n}\n\n/** Options to start a local pl-core. */\nexport type LocalPlOptions = {\n /** From what directory start a process. */\n readonly workingDir: string;\n /** A string representation of yaml config. */\n readonly config: string;\n /** How to get a binary, download it or get an existing one (default: download latest version) */\n readonly plBinary?: PlBinarySource;\n /** Additional options for a process, environments, stdout, stderr etc. */\n readonly spawnOptions?: SpawnOptions;\n /**\n * If the previous pl-core was started from the same directory,\n * we can check if it's still running and then stop it before starting a new one.\n * (default: true)\n */\n readonly closeOld?: boolean;\n\n readonly onClose?: (pl: LocalPl) => Promise<void>;\n readonly onError?: (pl: LocalPl) => Promise<void>;\n readonly onCloseAndError?: (pl: LocalPl) => Promise<void>;\n readonly onCloseAndErrorNoStop?: (pl: LocalPl) => Promise<void>;\n};\n\nexport type LocalPlOptionsFull = Required<LocalPlOptions, 'plBinary' | 'spawnOptions' | 'closeOld'>;\n\n/**\n * Starts pl-core, if the option was provided downloads a binary, reads license environments etc.\n */\nexport async function localPlatformaInit(logger: MiLogger, _ops: LocalPlOptions): Promise<LocalPl> {\n // filling-in default values\n\n // Backend could consume a lot of CPU power,\n // we want to keep at least a couple for UI and other apps to work.\n const numCpu = Math.max(os.cpus().length - 2, 1);\n const ops = mergeDefaultOps(_ops, numCpu);\n\n return await withTrace(logger, async (trace, t) => {\n trace('startOptions', { ...ops, config: 'too wordy' });\n\n const workDir = upath.resolve(ops.workingDir);\n\n if (ops.closeOld) {\n trace('closeOld', await localPlatformaReadPidAndStop(logger, workDir));\n }\n\n const configPath = upath.join(workDir, LocalConfigYaml);\n\n logger.info(`writing configuration '${configPath}'...`);\n await fsp.writeFile(configPath, ops.config);\n\n const plBinPath = upath.join(workDir, 'binaries');\n const baseBinaryPath = await resolveLocalPlBinaryPath(logger, plBinPath, ops.plBinary);\n const binaryPath = trace('binaryPath', upath.join('binaries', baseBinaryPath));\n\n const processOpts = plProcessOps(binaryPath, configPath, ops, workDir, process.env);\n trace('processOpts', {\n cmd: processOpts.cmd,\n args: processOpts.args,\n cwd: processOpts.opts.cwd,\n });\n\n const pl = new LocalPl(\n logger,\n ops.workingDir,\n processOpts,\n t,\n ops.onClose,\n ops.onError,\n ops.onCloseAndError,\n ops.onCloseAndErrorNoStop,\n );\n await pl.start();\n\n return pl;\n });\n}\n\n/** Reads a pid of the old pl-core if it was started in the same working directory,\n * and closes it. */\nasync function localPlatformaReadPidAndStop(\n logger: MiLogger,\n workingDir: string,\n): Promise<Record<string, any>> {\n return await withTrace(logger, async (trace, t) => {\n const file = trace('pidFilePath', filePid(workingDir));\n\n const oldPid = trace('pid', await readPid(file));\n const alive = trace('wasAlive', await isProcessAlive(oldPid));\n\n if (oldPid !== undefined && alive) {\n trace('stopped', processStop(oldPid));\n trace('waitStopped', await processWaitStopped(oldPid, 10_000));\n }\n\n return t;\n });\n}\n\n/** Gets default options for the whole init process\n * and overrides them with the provided options. */\nexport function mergeDefaultOps(ops: LocalPlOptions, numCpu: number): LocalPlOptionsFull {\n const result: {\n plBinary: PlBinarySource;\n spawnOptions: SpawnOptions;\n closeOld: boolean;\n } = {\n plBinary: newDefaultPlBinarySource(),\n spawnOptions: {\n env: {\n GOMAXPROCS: String(numCpu),\n },\n },\n closeOld: true,\n };\n\n if (ops.spawnOptions?.env) {\n result.spawnOptions.env = { ...result.spawnOptions.env, ...ops.spawnOptions.env };\n }\n\n if (ops.spawnOptions) {\n const withoutEnv = { ...ops.spawnOptions };\n delete withoutEnv['env'];\n result.spawnOptions = { ...result.spawnOptions, ...withoutEnv };\n }\n\n const withoutSpawnOps = { ...ops };\n delete withoutSpawnOps['spawnOptions'];\n\n return { ...result, ...withoutSpawnOps };\n}\n\n/** Gets default options for a platforma local binary\n * and overrides them with the provided options. */\nexport function plProcessOps(\n binaryPath: any,\n configPath: string,\n ops: LocalPlOptionsFull,\n workDir: string,\n defaultEnv: Record<string, string | undefined>,\n): ProcessOptions {\n const result: ProcessOptions = {\n cmd: binaryPath,\n args: ['--config', configPath],\n opts: {\n env: { ...defaultEnv },\n cwd: workDir,\n stdio: ['pipe', 'ignore', 'inherit'],\n windowsHide: true, // hide a terminal on Windows\n },\n };\n\n if (ops.spawnOptions?.env) {\n result.opts.env = { ...result.opts.env, ...ops.spawnOptions.env };\n }\n\n const withoutEnv = { ...ops.spawnOptions };\n delete withoutEnv['env'];\n result.opts = { ...result.opts, ...withoutEnv };\n\n return result;\n}\n"],"names":["withTrace","processRun","filePid","notEmpty","writePid","processStop","processWaitStopped","isProcessAlive","os","resolveLocalPlBinaryPath","readPid","newDefaultPlBinarySource"],"mappings":"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"}
@@ -71,4 +71,3 @@ export declare function mergeDefaultOps(ops: LocalPlOptions, numCpu: number): Lo
71
71
  /** Gets default options for a platforma local binary
72
72
  * and overrides them with the provided options. */
73
73
  export declare function plProcessOps(binaryPath: any, configPath: string, ops: LocalPlOptionsFull, workDir: string, defaultEnv: Record<string, string | undefined>): ProcessOptions;
74
- //# sourceMappingURL=pl.d.ts.map
@@ -0,0 +1,192 @@
1
+ import { processStop, processWaitStopped, isProcessAlive, processRun } from './process.js';
2
+ import { newDefaultPlBinarySource, resolveLocalPlBinaryPath } from '../common/pl_binary.js';
3
+ import { notEmpty } from '@milaboratories/ts-helpers';
4
+ import { filePid, writePid, readPid } from './pid.js';
5
+ import { withTrace } from './trace.js';
6
+ import upath from 'upath';
7
+ import fsp from 'node:fs/promises';
8
+ import * as os from 'node:os';
9
+
10
+ const LocalConfigYaml = 'config-local.yaml';
11
+ /**
12
+ * Represents a local running pl-core,
13
+ * and has methods to start, check if it's running, stop and wait for stopping it.
14
+ * Also, a hook on pl-core closed can be provided.
15
+ */
16
+ class LocalPl {
17
+ logger;
18
+ workingDir;
19
+ startOptions;
20
+ initialStartHistory;
21
+ onClose;
22
+ onError;
23
+ onCloseAndError;
24
+ onCloseAndErrorNoStop;
25
+ instance;
26
+ pid;
27
+ nRuns = 0;
28
+ lastRunHistory = {};
29
+ wasStopped = false;
30
+ constructor(logger, workingDir, startOptions, initialStartHistory, onClose, onError, onCloseAndError, onCloseAndErrorNoStop) {
31
+ this.logger = logger;
32
+ this.workingDir = workingDir;
33
+ this.startOptions = startOptions;
34
+ this.initialStartHistory = initialStartHistory;
35
+ this.onClose = onClose;
36
+ this.onError = onError;
37
+ this.onCloseAndError = onCloseAndError;
38
+ this.onCloseAndErrorNoStop = onCloseAndErrorNoStop;
39
+ }
40
+ async start() {
41
+ await withTrace(this.logger, async (trace, t) => {
42
+ this.wasStopped = false;
43
+ const instance = processRun(this.logger, this.startOptions);
44
+ instance.on('error', (e) => {
45
+ this.logger.error(`error '${e}', while running platforma, started opts: ${JSON.stringify(this.debugInfo())}`);
46
+ // keep in mind there are no awaits here, it will be asynchronous
47
+ if (this.onError !== undefined)
48
+ void this.onError(this);
49
+ if (this.onCloseAndError !== undefined)
50
+ void this.onCloseAndError(this);
51
+ if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)
52
+ void this.onCloseAndErrorNoStop(this);
53
+ });
54
+ instance.on('close', () => {
55
+ this.logger.warn(`platforma was closed, started opts: ${JSON.stringify(this.debugInfo())}`);
56
+ // keep in mind there are no awaits here, it will be asynchronous
57
+ if (this.onClose !== undefined)
58
+ void this.onClose(this);
59
+ if (this.onCloseAndError !== undefined)
60
+ void this.onCloseAndError(this);
61
+ if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)
62
+ void this.onCloseAndErrorNoStop(this);
63
+ });
64
+ trace('started', true);
65
+ const pidFile = trace('pidFile', filePid(this.workingDir));
66
+ trace('pid', notEmpty(instance.pid));
67
+ trace('pidWritten', await writePid(pidFile, notEmpty(instance.pid)));
68
+ this.nRuns++;
69
+ this.instance = instance;
70
+ this.pid = instance.pid;
71
+ this.lastRunHistory = t;
72
+ });
73
+ }
74
+ stop() {
75
+ // TODO use this.instance to stop the process
76
+ this.wasStopped = true;
77
+ processStop(notEmpty(this.pid));
78
+ }
79
+ async waitStopped() {
80
+ await processWaitStopped(notEmpty(this.pid), 15000);
81
+ }
82
+ stopped() {
83
+ return this.wasStopped;
84
+ }
85
+ async isAlive() {
86
+ return await isProcessAlive(notEmpty(this.pid));
87
+ }
88
+ debugInfo() {
89
+ return {
90
+ lastRunHistory: this.lastRunHistory,
91
+ nRuns: this.nRuns,
92
+ pid: this.pid,
93
+ workingDir: this.workingDir,
94
+ initialStartHistory: this.initialStartHistory,
95
+ wasStopped: this.wasStopped,
96
+ };
97
+ }
98
+ }
99
+ /**
100
+ * Starts pl-core, if the option was provided downloads a binary, reads license environments etc.
101
+ */
102
+ async function localPlatformaInit(logger, _ops) {
103
+ // filling-in default values
104
+ // Backend could consume a lot of CPU power,
105
+ // we want to keep at least a couple for UI and other apps to work.
106
+ const numCpu = Math.max(os.cpus().length - 2, 1);
107
+ const ops = mergeDefaultOps(_ops, numCpu);
108
+ return await withTrace(logger, async (trace, t) => {
109
+ trace('startOptions', { ...ops, config: 'too wordy' });
110
+ const workDir = upath.resolve(ops.workingDir);
111
+ if (ops.closeOld) {
112
+ trace('closeOld', await localPlatformaReadPidAndStop(logger, workDir));
113
+ }
114
+ const configPath = upath.join(workDir, LocalConfigYaml);
115
+ logger.info(`writing configuration '${configPath}'...`);
116
+ await fsp.writeFile(configPath, ops.config);
117
+ const plBinPath = upath.join(workDir, 'binaries');
118
+ const baseBinaryPath = await resolveLocalPlBinaryPath(logger, plBinPath, ops.plBinary);
119
+ const binaryPath = trace('binaryPath', upath.join('binaries', baseBinaryPath));
120
+ const processOpts = plProcessOps(binaryPath, configPath, ops, workDir, process.env);
121
+ trace('processOpts', {
122
+ cmd: processOpts.cmd,
123
+ args: processOpts.args,
124
+ cwd: processOpts.opts.cwd,
125
+ });
126
+ const pl = new LocalPl(logger, ops.workingDir, processOpts, t, ops.onClose, ops.onError, ops.onCloseAndError, ops.onCloseAndErrorNoStop);
127
+ await pl.start();
128
+ return pl;
129
+ });
130
+ }
131
+ /** Reads a pid of the old pl-core if it was started in the same working directory,
132
+ * and closes it. */
133
+ async function localPlatformaReadPidAndStop(logger, workingDir) {
134
+ return await withTrace(logger, async (trace, t) => {
135
+ const file = trace('pidFilePath', filePid(workingDir));
136
+ const oldPid = trace('pid', await readPid(file));
137
+ const alive = trace('wasAlive', await isProcessAlive(oldPid));
138
+ if (oldPid !== undefined && alive) {
139
+ trace('stopped', processStop(oldPid));
140
+ trace('waitStopped', await processWaitStopped(oldPid, 10_000));
141
+ }
142
+ return t;
143
+ });
144
+ }
145
+ /** Gets default options for the whole init process
146
+ * and overrides them with the provided options. */
147
+ function mergeDefaultOps(ops, numCpu) {
148
+ const result = {
149
+ plBinary: newDefaultPlBinarySource(),
150
+ spawnOptions: {
151
+ env: {
152
+ GOMAXPROCS: String(numCpu),
153
+ },
154
+ },
155
+ closeOld: true,
156
+ };
157
+ if (ops.spawnOptions?.env) {
158
+ result.spawnOptions.env = { ...result.spawnOptions.env, ...ops.spawnOptions.env };
159
+ }
160
+ if (ops.spawnOptions) {
161
+ const withoutEnv = { ...ops.spawnOptions };
162
+ delete withoutEnv['env'];
163
+ result.spawnOptions = { ...result.spawnOptions, ...withoutEnv };
164
+ }
165
+ const withoutSpawnOps = { ...ops };
166
+ delete withoutSpawnOps['spawnOptions'];
167
+ return { ...result, ...withoutSpawnOps };
168
+ }
169
+ /** Gets default options for a platforma local binary
170
+ * and overrides them with the provided options. */
171
+ function plProcessOps(binaryPath, configPath, ops, workDir, defaultEnv) {
172
+ const result = {
173
+ cmd: binaryPath,
174
+ args: ['--config', configPath],
175
+ opts: {
176
+ env: { ...defaultEnv },
177
+ cwd: workDir,
178
+ stdio: ['pipe', 'ignore', 'inherit'],
179
+ windowsHide: true, // hide a terminal on Windows
180
+ },
181
+ };
182
+ if (ops.spawnOptions?.env) {
183
+ result.opts.env = { ...result.opts.env, ...ops.spawnOptions.env };
184
+ }
185
+ const withoutEnv = { ...ops.spawnOptions };
186
+ delete withoutEnv['env'];
187
+ result.opts = { ...result.opts, ...withoutEnv };
188
+ return result;
189
+ }
190
+
191
+ export { LocalConfigYaml, LocalPl, localPlatformaInit, mergeDefaultOps, plProcessOps };
192
+ //# sourceMappingURL=pl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pl.js","sources":["../../src/local/pl.ts"],"sourcesContent":["import type {\n ProcessOptions } from './process';\nimport {\n isProcessAlive,\n processStop,\n processWaitStopped,\n processRun,\n} from './process';\nimport type { PlBinarySource } from '../common/pl_binary';\nimport { newDefaultPlBinarySource, resolveLocalPlBinaryPath } from '../common/pl_binary';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport type { ChildProcess, SpawnOptions } from 'node:child_process';\nimport { filePid, readPid, writePid } from './pid';\nimport type { Trace } from './trace';\nimport { withTrace } from './trace';\nimport upath from 'upath';\nimport fsp from 'node:fs/promises';\nimport type { Required } from 'utility-types';\nimport * as os from 'node:os';\n\nexport const LocalConfigYaml = 'config-local.yaml';\n\n/**\n * Represents a local running pl-core,\n * and has methods to start, check if it's running, stop and wait for stopping it.\n * Also, a hook on pl-core closed can be provided.\n */\nexport class LocalPl {\n private instance?: ChildProcess;\n public pid?: number;\n private nRuns: number = 0;\n private lastRunHistory: Trace = {};\n private wasStopped = false;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly workingDir: string,\n private readonly startOptions: ProcessOptions,\n private readonly initialStartHistory: Trace,\n private readonly onClose?: (pl: LocalPl) => Promise<void>,\n private readonly onError?: (pl: LocalPl) => Promise<void>,\n private readonly onCloseAndError?: (pl: LocalPl) => Promise<void>,\n private readonly onCloseAndErrorNoStop?: (pl: LocalPl) => Promise<void>,\n ) {}\n\n async start() {\n await withTrace(this.logger, async (trace, t) => {\n this.wasStopped = false;\n const instance = processRun(this.logger, this.startOptions);\n instance.on('error', (e: any) => {\n this.logger.error(\n `error '${e}', while running platforma, started opts: ${JSON.stringify(this.debugInfo())}`,\n );\n\n // keep in mind there are no awaits here, it will be asynchronous\n if (this.onError !== undefined) void this.onError(this);\n if (this.onCloseAndError !== undefined) void this.onCloseAndError(this);\n if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)\n void this.onCloseAndErrorNoStop(this);\n });\n instance.on('close', () => {\n this.logger.warn(`platforma was closed, started opts: ${JSON.stringify(this.debugInfo())}`);\n\n // keep in mind there are no awaits here, it will be asynchronous\n if (this.onClose !== undefined) void this.onClose(this);\n if (this.onCloseAndError !== undefined) void this.onCloseAndError(this);\n if (this.onCloseAndErrorNoStop !== undefined && !this.wasStopped)\n void this.onCloseAndErrorNoStop(this);\n });\n\n trace('started', true);\n\n const pidFile = trace('pidFile', filePid(this.workingDir));\n trace('pid', notEmpty(instance.pid));\n trace('pidWritten', await writePid(pidFile, notEmpty(instance.pid)));\n\n this.nRuns++;\n this.instance = instance;\n this.pid = instance.pid;\n this.lastRunHistory = t;\n });\n }\n\n stop() {\n // TODO use this.instance to stop the process\n this.wasStopped = true;\n processStop(notEmpty(this.pid));\n }\n\n async waitStopped() {\n await processWaitStopped(notEmpty(this.pid), 15000);\n }\n\n stopped() {\n return this.wasStopped;\n }\n\n async isAlive(): Promise<boolean> {\n return await isProcessAlive(notEmpty(this.pid));\n }\n\n debugInfo() {\n return {\n lastRunHistory: this.lastRunHistory,\n nRuns: this.nRuns,\n pid: this.pid,\n workingDir: this.workingDir,\n initialStartHistory: this.initialStartHistory,\n wasStopped: this.wasStopped,\n };\n }\n}\n\n/** Options to start a local pl-core. */\nexport type LocalPlOptions = {\n /** From what directory start a process. */\n readonly workingDir: string;\n /** A string representation of yaml config. */\n readonly config: string;\n /** How to get a binary, download it or get an existing one (default: download latest version) */\n readonly plBinary?: PlBinarySource;\n /** Additional options for a process, environments, stdout, stderr etc. */\n readonly spawnOptions?: SpawnOptions;\n /**\n * If the previous pl-core was started from the same directory,\n * we can check if it's still running and then stop it before starting a new one.\n * (default: true)\n */\n readonly closeOld?: boolean;\n\n readonly onClose?: (pl: LocalPl) => Promise<void>;\n readonly onError?: (pl: LocalPl) => Promise<void>;\n readonly onCloseAndError?: (pl: LocalPl) => Promise<void>;\n readonly onCloseAndErrorNoStop?: (pl: LocalPl) => Promise<void>;\n};\n\nexport type LocalPlOptionsFull = Required<LocalPlOptions, 'plBinary' | 'spawnOptions' | 'closeOld'>;\n\n/**\n * Starts pl-core, if the option was provided downloads a binary, reads license environments etc.\n */\nexport async function localPlatformaInit(logger: MiLogger, _ops: LocalPlOptions): Promise<LocalPl> {\n // filling-in default values\n\n // Backend could consume a lot of CPU power,\n // we want to keep at least a couple for UI and other apps to work.\n const numCpu = Math.max(os.cpus().length - 2, 1);\n const ops = mergeDefaultOps(_ops, numCpu);\n\n return await withTrace(logger, async (trace, t) => {\n trace('startOptions', { ...ops, config: 'too wordy' });\n\n const workDir = upath.resolve(ops.workingDir);\n\n if (ops.closeOld) {\n trace('closeOld', await localPlatformaReadPidAndStop(logger, workDir));\n }\n\n const configPath = upath.join(workDir, LocalConfigYaml);\n\n logger.info(`writing configuration '${configPath}'...`);\n await fsp.writeFile(configPath, ops.config);\n\n const plBinPath = upath.join(workDir, 'binaries');\n const baseBinaryPath = await resolveLocalPlBinaryPath(logger, plBinPath, ops.plBinary);\n const binaryPath = trace('binaryPath', upath.join('binaries', baseBinaryPath));\n\n const processOpts = plProcessOps(binaryPath, configPath, ops, workDir, process.env);\n trace('processOpts', {\n cmd: processOpts.cmd,\n args: processOpts.args,\n cwd: processOpts.opts.cwd,\n });\n\n const pl = new LocalPl(\n logger,\n ops.workingDir,\n processOpts,\n t,\n ops.onClose,\n ops.onError,\n ops.onCloseAndError,\n ops.onCloseAndErrorNoStop,\n );\n await pl.start();\n\n return pl;\n });\n}\n\n/** Reads a pid of the old pl-core if it was started in the same working directory,\n * and closes it. */\nasync function localPlatformaReadPidAndStop(\n logger: MiLogger,\n workingDir: string,\n): Promise<Record<string, any>> {\n return await withTrace(logger, async (trace, t) => {\n const file = trace('pidFilePath', filePid(workingDir));\n\n const oldPid = trace('pid', await readPid(file));\n const alive = trace('wasAlive', await isProcessAlive(oldPid));\n\n if (oldPid !== undefined && alive) {\n trace('stopped', processStop(oldPid));\n trace('waitStopped', await processWaitStopped(oldPid, 10_000));\n }\n\n return t;\n });\n}\n\n/** Gets default options for the whole init process\n * and overrides them with the provided options. */\nexport function mergeDefaultOps(ops: LocalPlOptions, numCpu: number): LocalPlOptionsFull {\n const result: {\n plBinary: PlBinarySource;\n spawnOptions: SpawnOptions;\n closeOld: boolean;\n } = {\n plBinary: newDefaultPlBinarySource(),\n spawnOptions: {\n env: {\n GOMAXPROCS: String(numCpu),\n },\n },\n closeOld: true,\n };\n\n if (ops.spawnOptions?.env) {\n result.spawnOptions.env = { ...result.spawnOptions.env, ...ops.spawnOptions.env };\n }\n\n if (ops.spawnOptions) {\n const withoutEnv = { ...ops.spawnOptions };\n delete withoutEnv['env'];\n result.spawnOptions = { ...result.spawnOptions, ...withoutEnv };\n }\n\n const withoutSpawnOps = { ...ops };\n delete withoutSpawnOps['spawnOptions'];\n\n return { ...result, ...withoutSpawnOps };\n}\n\n/** Gets default options for a platforma local binary\n * and overrides them with the provided options. */\nexport function plProcessOps(\n binaryPath: any,\n configPath: string,\n ops: LocalPlOptionsFull,\n workDir: string,\n defaultEnv: Record<string, string | undefined>,\n): ProcessOptions {\n const result: ProcessOptions = {\n cmd: binaryPath,\n args: ['--config', configPath],\n opts: {\n env: { ...defaultEnv },\n cwd: workDir,\n stdio: ['pipe', 'ignore', 'inherit'],\n windowsHide: true, // hide a terminal on Windows\n },\n };\n\n if (ops.spawnOptions?.env) {\n result.opts.env = { ...result.opts.env, ...ops.spawnOptions.env };\n }\n\n const withoutEnv = { ...ops.spawnOptions };\n delete withoutEnv['env'];\n result.opts = { ...result.opts, ...withoutEnv };\n\n return result;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ var node_child_process = require('node:child_process');
4
+ var tsHelpers = require('@milaboratories/ts-helpers');
5
+
6
+ function processRun(logger, opts) {
7
+ logger.info(`Running:
8
+ cmd: ${JSON.stringify([opts.cmd, ...opts.args])}
9
+ wd: ${opts.opts.cwd}`);
10
+ logger.info(' spawning child process');
11
+ return node_child_process.spawn(opts.cmd, opts.args, opts.opts);
12
+ }
13
+ // eslint-disable-next-line @typescript-eslint/require-await
14
+ async function isProcessAlive(pid) {
15
+ try {
16
+ process.kill(pid, 0);
17
+ return true;
18
+ }
19
+ catch (_e) {
20
+ return false;
21
+ }
22
+ }
23
+ function processStop(pid) {
24
+ return process.kill(pid, 'SIGINT');
25
+ }
26
+ async function processWaitStopped(pid, maxMs) {
27
+ const sleepMs = 100;
28
+ let total = 0;
29
+ while (await isProcessAlive(pid)) {
30
+ await tsHelpers.sleep(sleepMs);
31
+ total += sleepMs;
32
+ if (total > maxMs) {
33
+ throw new Error(`The process did not stopped after ${maxMs} ms.`);
34
+ }
35
+ }
36
+ }
37
+
38
+ exports.isProcessAlive = isProcessAlive;
39
+ exports.processRun = processRun;
40
+ exports.processStop = processStop;
41
+ exports.processWaitStopped = processWaitStopped;
42
+ //# sourceMappingURL=process.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.cjs","sources":["../../src/local/process.ts"],"sourcesContent":["import type { SpawnOptions, ChildProcess } from 'node:child_process';\nimport { spawn } from 'node:child_process';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { sleep } from '@milaboratories/ts-helpers';\n\nexport type ProcessOptions = {\n cmd: string;\n args: string[];\n opts: SpawnOptions;\n};\n\nexport function processRun(logger: MiLogger, opts: ProcessOptions): ChildProcess {\n logger.info(`Running:\ncmd: ${JSON.stringify([opts.cmd, ...opts.args])}\nwd: ${opts.opts.cwd}`);\n\n logger.info(' spawning child process');\n return spawn(opts.cmd, opts.args, opts.opts);\n}\n\n// eslint-disable-next-line @typescript-eslint/require-await\nexport async function isProcessAlive(pid: number) {\n try {\n process.kill(pid, 0);\n return true;\n } catch (_e) {\n return false;\n }\n}\n\nexport function processStop(pid: number) {\n return process.kill(pid, 'SIGINT');\n}\n\nexport async function processWaitStopped(pid: number, maxMs: number) {\n const sleepMs = 100;\n let total = 0;\n while (await isProcessAlive(pid)) {\n await sleep(sleepMs);\n total += sleepMs;\n if (total > maxMs) {\n throw new Error(`The process did not stopped after ${maxMs} ms.`);\n }\n }\n}\n"],"names":["spawn","sleep"],"mappings":";;;;;AAWM,SAAU,UAAU,CAAC,MAAgB,EAAE,IAAoB,EAAA;IAC/D,MAAM,CAAC,IAAI,CAAC,CAAA;AACP,KAAA,EAAA,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,IAAA,EAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA,CAAE,CAAC;AAEpB,IAAA,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC;AACvC,IAAA,OAAOA,wBAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;AAC9C;AAEA;AACO,eAAe,cAAc,CAAC,GAAW,EAAA;AAC9C,IAAA,IAAI;AACF,QAAA,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACpB,QAAA,OAAO,IAAI;IACb;IAAE,OAAO,EAAE,EAAE;AACX,QAAA,OAAO,KAAK;IACd;AACF;AAEM,SAAU,WAAW,CAAC,GAAW,EAAA;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC;AACpC;AAEO,eAAe,kBAAkB,CAAC,GAAW,EAAE,KAAa,EAAA;IACjE,MAAM,OAAO,GAAG,GAAG;IACnB,IAAI,KAAK,GAAG,CAAC;AACb,IAAA,OAAO,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE;AAChC,QAAA,MAAMC,eAAK,CAAC,OAAO,CAAC;QACpB,KAAK,IAAI,OAAO;AAChB,QAAA,IAAI,KAAK,GAAG,KAAK,EAAE;AACjB,YAAA,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,CAAA,IAAA,CAAM,CAAC;QACnE;IACF;AACF;;;;;;;"}
@@ -9,4 +9,3 @@ export declare function processRun(logger: MiLogger, opts: ProcessOptions): Chil
9
9
  export declare function isProcessAlive(pid: number): Promise<boolean>;
10
10
  export declare function processStop(pid: number): true;
11
11
  export declare function processWaitStopped(pid: number, maxMs: number): Promise<void>;
12
- //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { sleep } from '@milaboratories/ts-helpers';
3
+
4
+ function processRun(logger, opts) {
5
+ logger.info(`Running:
6
+ cmd: ${JSON.stringify([opts.cmd, ...opts.args])}
7
+ wd: ${opts.opts.cwd}`);
8
+ logger.info(' spawning child process');
9
+ return spawn(opts.cmd, opts.args, opts.opts);
10
+ }
11
+ // eslint-disable-next-line @typescript-eslint/require-await
12
+ async function isProcessAlive(pid) {
13
+ try {
14
+ process.kill(pid, 0);
15
+ return true;
16
+ }
17
+ catch (_e) {
18
+ return false;
19
+ }
20
+ }
21
+ function processStop(pid) {
22
+ return process.kill(pid, 'SIGINT');
23
+ }
24
+ async function processWaitStopped(pid, maxMs) {
25
+ const sleepMs = 100;
26
+ let total = 0;
27
+ while (await isProcessAlive(pid)) {
28
+ await sleep(sleepMs);
29
+ total += sleepMs;
30
+ if (total > maxMs) {
31
+ throw new Error(`The process did not stopped after ${maxMs} ms.`);
32
+ }
33
+ }
34
+ }
35
+
36
+ export { isProcessAlive, processRun, processStop, processWaitStopped };
37
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sources":["../../src/local/process.ts"],"sourcesContent":["import type { SpawnOptions, ChildProcess } from 'node:child_process';\nimport { spawn } from 'node:child_process';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { sleep } from '@milaboratories/ts-helpers';\n\nexport type ProcessOptions = {\n cmd: string;\n args: string[];\n opts: SpawnOptions;\n};\n\nexport function processRun(logger: MiLogger, opts: ProcessOptions): ChildProcess {\n logger.info(`Running:\ncmd: ${JSON.stringify([opts.cmd, ...opts.args])}\nwd: ${opts.opts.cwd}`);\n\n logger.info(' spawning child process');\n return spawn(opts.cmd, opts.args, opts.opts);\n}\n\n// eslint-disable-next-line @typescript-eslint/require-await\nexport async function isProcessAlive(pid: number) {\n try {\n process.kill(pid, 0);\n return true;\n } catch (_e) {\n return false;\n }\n}\n\nexport function processStop(pid: number) {\n return process.kill(pid, 'SIGINT');\n}\n\nexport async function processWaitStopped(pid: number, maxMs: number) {\n const sleepMs = 100;\n let total = 0;\n while (await isProcessAlive(pid)) {\n await sleep(sleepMs);\n total += sleepMs;\n if (total > maxMs) {\n throw new Error(`The process did not stopped after ${maxMs} ms.`);\n }\n }\n}\n"],"names":[],"mappings":";;;AAWM,SAAU,UAAU,CAAC,MAAgB,EAAE,IAAoB,EAAA;IAC/D,MAAM,CAAC,IAAI,CAAC,CAAA;AACP,KAAA,EAAA,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,IAAA,EAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA,CAAE,CAAC;AAEpB,IAAA,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC;AACvC,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;AAC9C;AAEA;AACO,eAAe,cAAc,CAAC,GAAW,EAAA;AAC9C,IAAA,IAAI;AACF,QAAA,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACpB,QAAA,OAAO,IAAI;IACb;IAAE,OAAO,EAAE,EAAE;AACX,QAAA,OAAO,KAAK;IACd;AACF;AAEM,SAAU,WAAW,CAAC,GAAW,EAAA;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC;AACpC;AAEO,eAAe,kBAAkB,CAAC,GAAW,EAAE,KAAa,EAAA;IACjE,MAAM,OAAO,GAAG,GAAG;IACnB,IAAI,KAAK,GAAG,CAAC;AACb,IAAA,OAAO,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE;AAChC,QAAA,MAAM,KAAK,CAAC,OAAO,CAAC;QACpB,KAAK,IAAI,OAAO;AAChB,QAAA,IAAI,KAAK,GAAG,KAAK,EAAE;AACjB,YAAA,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,CAAA,IAAA,CAAM,CAAC;QACnE;IACF;AACF;;;;"}
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ function newTrace() {
4
+ return {};
5
+ }
6
+ function trace(t, k, v) {
7
+ t[k] = v;
8
+ return v;
9
+ }
10
+ /** Creates a trace and runs a function with it. The function can record all its
11
+ * logs or traces using `trace` fn. */
12
+ async function withTrace(logger, fn) {
13
+ const t = newTrace();
14
+ try {
15
+ const result = await fn((k, v) => trace(t, k, v), t);
16
+ return result;
17
+ }
18
+ catch (e) {
19
+ logger.error(`error ${e} while doing traced operation, state: ${JSON.stringify(t)}`);
20
+ throw e;
21
+ }
22
+ }
23
+
24
+ exports.newTrace = newTrace;
25
+ exports.trace = trace;
26
+ exports.withTrace = withTrace;
27
+ //# sourceMappingURL=trace.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.cjs","sources":["../../src/local/trace.ts"],"sourcesContent":["import type { MiLogger } from '@milaboratories/ts-helpers';\n\n/** Records all inputs and outputs of one's choice, so if the error happened\n * one can check how it was by just printing this structure. */\nexport type Trace = Record<string, any>;\n\nexport function newTrace(): Trace {\n return {};\n}\n\nexport function trace(t: Trace, k: string, v: any) {\n t[k] = v;\n return v;\n}\n\n/** Creates a trace and runs a function with it. The function can record all its\n * logs or traces using `trace` fn. */\nexport async function withTrace<T>(\n logger: MiLogger,\n fn: (trace: (k: string, v: any) => typeof v, t: Trace) => Promise<T>,\n): Promise<T> {\n const t = newTrace();\n try {\n const result = await fn((k: string, v: any) => trace(t, k, v), t);\n return result;\n } catch (e: any) {\n logger.error(`error ${e} while doing traced operation, state: ${JSON.stringify(t)}`);\n throw e;\n }\n}\n"],"names":[],"mappings":";;SAMgB,QAAQ,GAAA;AACtB,IAAA,OAAO,EAAE;AACX;SAEgB,KAAK,CAAC,CAAQ,EAAE,CAAS,EAAE,CAAM,EAAA;AAC/C,IAAA,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACR,IAAA,OAAO,CAAC;AACV;AAEA;AACsC;AAC/B,eAAe,SAAS,CAC7B,MAAgB,EAChB,EAAoE,EAAA;AAEpE,IAAA,MAAM,CAAC,GAAG,QAAQ,EAAE;AACpB,IAAA,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAS,EAAE,CAAM,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACjE,QAAA,OAAO,MAAM;IACf;IAAE,OAAO,CAAM,EAAE;AACf,QAAA,MAAM,CAAC,KAAK,CAAC,CAAA,MAAA,EAAS,CAAC,CAAA,sCAAA,EAAyC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA,CAAE,CAAC;AACpF,QAAA,MAAM,CAAC;IACT;AACF;;;;;;"}
@@ -7,4 +7,3 @@ export declare function trace(t: Trace, k: string, v: any): any;
7
7
  /** Creates a trace and runs a function with it. The function can record all its
8
8
  * logs or traces using `trace` fn. */
9
9
  export declare function withTrace<T>(logger: MiLogger, fn: (trace: (k: string, v: any) => typeof v, t: Trace) => Promise<T>): Promise<T>;
10
- //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1,23 @@
1
+ function newTrace() {
2
+ return {};
3
+ }
4
+ function trace(t, k, v) {
5
+ t[k] = v;
6
+ return v;
7
+ }
8
+ /** Creates a trace and runs a function with it. The function can record all its
9
+ * logs or traces using `trace` fn. */
10
+ async function withTrace(logger, fn) {
11
+ const t = newTrace();
12
+ try {
13
+ const result = await fn((k, v) => trace(t, k, v), t);
14
+ return result;
15
+ }
16
+ catch (e) {
17
+ logger.error(`error ${e} while doing traced operation, state: ${JSON.stringify(t)}`);
18
+ throw e;
19
+ }
20
+ }
21
+
22
+ export { newTrace, trace, withTrace };
23
+ //# sourceMappingURL=trace.js.map