@tradejs/cli 3.1.1 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -28101,16 +28101,20 @@ var init_runtimeScorecard2 = __esm({
28101
28101
  // src/scripts/runtimeConfig.ts
28102
28102
  var runtimeConfig_exports = {};
28103
28103
  __export(runtimeConfig_exports, {
28104
+ buildBootstrapRuntimeDeployment: () => buildBootstrapRuntimeDeployment,
28105
+ isEquivalentRuntimeStrategyRelease: () => isEquivalentRuntimeStrategyRelease,
28104
28106
  main: () => main37,
28107
+ pointRuntimeDeploymentAtRelease: () => pointRuntimeDeploymentAtRelease,
28105
28108
  runtimeConfig: () => runtimeConfig
28106
28109
  });
28107
- var import_config9, import_promises28, import_node_path23, import_runtimeDeployments2, import_runtimeStrategyConfigs2, import_runtimeStrategyReleases, import_runtimeStrategies, import_strategies11, argv, action, option, hasFlag, required2, projectRoot12, userName2, OPERATIONAL_CONFIG_KEYS, toReleaseConfig, writeMigrationBackup, publish, migrate, publishDraft, updateControlState, rollback, verify, inspect, runtimeConfig, main37;
28110
+ var import_config9, import_promises28, import_node_path23, import_node_util2, import_runtimeDeployments2, import_runtimeStrategyConfigs2, import_runtimeStrategyReleases, import_runtimeStrategies, import_strategies11, argv, action, option, hasFlag, required2, projectRoot12, userName2, OPERATIONAL_CONFIG_KEYS, toReleaseConfig, writeMigrationBackup, publish, buildBootstrapRuntimeDeployment, isEquivalentRuntimeStrategyRelease, pointRuntimeDeploymentAtRelease, bootstrap, migrate, rollout, publishDraft, updateControlState, rollback, verify, inspect, runtimeConfig, main37;
28108
28111
  var init_runtimeConfig = __esm({
28109
28112
  "src/scripts/runtimeConfig.ts"() {
28110
28113
  "use strict";
28111
28114
  import_config9 = require("dotenv/config");
28112
28115
  import_promises28 = require("fs/promises");
28113
28116
  import_node_path23 = __toESM(require("path"));
28117
+ import_node_util2 = require("util");
28114
28118
  import_runtimeDeployments2 = require("@tradejs/infra/runtimeDeployments");
28115
28119
  import_runtimeStrategyConfigs2 = require("@tradejs/infra/runtimeStrategyConfigs");
28116
28120
  import_runtimeStrategyReleases = require("@tradejs/infra/runtimeStrategyReleases");
@@ -28176,6 +28180,131 @@ var init_runtimeConfig = __esm({
28176
28180
  createdBy: `cli:${userName2}`
28177
28181
  });
28178
28182
  };
28183
+ buildBootstrapRuntimeDeployment = ({
28184
+ deploymentId,
28185
+ label,
28186
+ connectorName,
28187
+ provider,
28188
+ accountId,
28189
+ strategyName,
28190
+ releaseVersion,
28191
+ config: config2
28192
+ }) => ({
28193
+ id: deploymentId,
28194
+ label,
28195
+ connectorName,
28196
+ provider,
28197
+ accountId,
28198
+ universe: config2.UNIVERSE,
28199
+ interval: String(config2.INTERVAL),
28200
+ enabled: true,
28201
+ strategies: [
28202
+ {
28203
+ strategyName,
28204
+ releaseVersion,
28205
+ controlState: "entries_paused"
28206
+ }
28207
+ ]
28208
+ });
28209
+ isEquivalentRuntimeStrategyRelease = ({
28210
+ release,
28211
+ config: config2,
28212
+ strategyPackage,
28213
+ strategyPackageVersion,
28214
+ runtimePackageVersion
28215
+ }) => Boolean(
28216
+ release && (0, import_node_util2.isDeepStrictEqual)(release.config, config2) && (release.strategyPackage ?? null) === (strategyPackage ?? null) && (release.strategyPackageVersion ?? null) === (strategyPackageVersion ?? null) && (release.runtimePackageVersion ?? null) === (runtimePackageVersion ?? null)
28217
+ );
28218
+ pointRuntimeDeploymentAtRelease = ({
28219
+ deployment,
28220
+ strategyName,
28221
+ releaseVersion
28222
+ }) => ({
28223
+ ...deployment,
28224
+ strategies: deployment.strategies.map(
28225
+ (strategy) => strategy.strategyName === strategyName ? {
28226
+ strategyName,
28227
+ releaseVersion,
28228
+ controlState: "entries_paused"
28229
+ } : strategy
28230
+ )
28231
+ });
28232
+ bootstrap = async () => {
28233
+ const strategyName = required2("strategy");
28234
+ const deploymentId = required2("deployment");
28235
+ const accountId = required2("account");
28236
+ const connectorName = option("connector") ?? "bybit";
28237
+ const provider = option("provider") ?? connectorName;
28238
+ const label = option("label") ?? deploymentId;
28239
+ const configFile = import_node_path23.default.resolve(projectRoot12, required2("file"));
28240
+ const sourceConfig = JSON.parse(
28241
+ await (0, import_promises28.readFile)(configFile, "utf8")
28242
+ );
28243
+ const existingDeployment = await (0, import_runtimeDeployments2.getRuntimeDeployment)(userName2, deploymentId);
28244
+ if (existingDeployment) {
28245
+ throw new Error(
28246
+ `Deployment already exists: ${deploymentId}; publish a release and switch its pointer instead`
28247
+ );
28248
+ }
28249
+ const releaseConfig = await toReleaseConfig(strategyName, sourceConfig);
28250
+ const previewDeployment = buildBootstrapRuntimeDeployment({
28251
+ deploymentId,
28252
+ label,
28253
+ connectorName,
28254
+ provider,
28255
+ accountId,
28256
+ strategyName,
28257
+ releaseVersion: 1,
28258
+ config: releaseConfig
28259
+ });
28260
+ if (!hasFlag("write")) {
28261
+ console.log(
28262
+ JSON.stringify(
28263
+ {
28264
+ dryRun: true,
28265
+ releaseConfig,
28266
+ deployment: {
28267
+ ...previewDeployment,
28268
+ strategies: previewDeployment.strategies.map((strategy) => ({
28269
+ ...strategy,
28270
+ releaseVersion: "<allocated on write>"
28271
+ }))
28272
+ }
28273
+ },
28274
+ null,
28275
+ 2
28276
+ )
28277
+ );
28278
+ return;
28279
+ }
28280
+ const backupPath = await writeMigrationBackup({
28281
+ userName: userName2,
28282
+ capturedAt: Date.now(),
28283
+ reason: "bootstrap",
28284
+ sourceConfig
28285
+ });
28286
+ const release = await publish({ strategyName, sourceConfig });
28287
+ const deployment = await (0, import_runtimeDeployments2.saveRuntimeDeployment)(
28288
+ userName2,
28289
+ buildBootstrapRuntimeDeployment({
28290
+ deploymentId,
28291
+ label,
28292
+ connectorName,
28293
+ provider,
28294
+ accountId,
28295
+ strategyName,
28296
+ releaseVersion: release.releaseVersion,
28297
+ config: release.config
28298
+ })
28299
+ );
28300
+ console.log(
28301
+ JSON.stringify(
28302
+ { bootstrapped: true, backupPath, release, deployment },
28303
+ null,
28304
+ 2
28305
+ )
28306
+ );
28307
+ };
28179
28308
  migrate = async () => {
28180
28309
  const strategyName = required2("strategy");
28181
28310
  const configId = option("config") ?? "config";
@@ -28237,6 +28366,95 @@ var init_runtimeConfig = __esm({
28237
28366
  )
28238
28367
  );
28239
28368
  };
28369
+ rollout = async () => {
28370
+ const strategyName = required2("strategy");
28371
+ const deploymentId = required2("deployment");
28372
+ const configFile = import_node_path23.default.resolve(projectRoot12, required2("file"));
28373
+ const [deployment, sourceConfig] = await Promise.all([
28374
+ (0, import_runtimeDeployments2.getRuntimeDeployment)(userName2, deploymentId),
28375
+ (0, import_promises28.readFile)(configFile, "utf8").then(
28376
+ (value) => JSON.parse(value)
28377
+ )
28378
+ ]);
28379
+ if (!deployment) throw new Error(`Deployment not found: ${deploymentId}`);
28380
+ const reference = deployment.strategies.find(
28381
+ (strategy) => strategy.strategyName === strategyName
28382
+ );
28383
+ if (!reference?.releaseVersion) {
28384
+ throw new Error(`${strategyName} is not a versioned deployment reference`);
28385
+ }
28386
+ const [config2, metadata, currentRelease] = await Promise.all([
28387
+ toReleaseConfig(strategyName, sourceConfig),
28388
+ (0, import_runtimeStrategies.getRuntimeStrategyPackageMetadata)({ strategyName, projectRoot: projectRoot12 }),
28389
+ (0, import_runtimeStrategyReleases.getRuntimeStrategyRelease)(userName2, strategyName, reference.releaseVersion)
28390
+ ]);
28391
+ const unchanged = isEquivalentRuntimeStrategyRelease({
28392
+ release: currentRelease,
28393
+ config: config2,
28394
+ ...metadata
28395
+ });
28396
+ const preview = {
28397
+ deploymentId,
28398
+ strategyName,
28399
+ currentReleaseVersion: reference.releaseVersion,
28400
+ nextControlState: "entries_paused",
28401
+ unchanged,
28402
+ config: config2,
28403
+ ...metadata
28404
+ };
28405
+ if (!hasFlag("write")) {
28406
+ console.log(JSON.stringify({ dryRun: true, ...preview }, null, 2));
28407
+ return;
28408
+ }
28409
+ if (unchanged) {
28410
+ console.log(
28411
+ JSON.stringify(
28412
+ {
28413
+ rolledOut: false,
28414
+ reason: "release_config_and_packages_unchanged",
28415
+ release: currentRelease,
28416
+ deployment
28417
+ },
28418
+ null,
28419
+ 2
28420
+ )
28421
+ );
28422
+ return;
28423
+ }
28424
+ const backupPath = await writeMigrationBackup({
28425
+ userName: userName2,
28426
+ capturedAt: Date.now(),
28427
+ reason: "rollout",
28428
+ deployment,
28429
+ currentRelease,
28430
+ sourceConfig
28431
+ });
28432
+ const release = await (0, import_runtimeStrategyReleases.publishRuntimeStrategyRelease)({
28433
+ userName: userName2,
28434
+ strategyName,
28435
+ config: config2,
28436
+ ...metadata,
28437
+ createdBy: `cli:${userName2}`
28438
+ });
28439
+ const updatedDeployment = pointRuntimeDeploymentAtRelease({
28440
+ deployment,
28441
+ strategyName,
28442
+ releaseVersion: release.releaseVersion
28443
+ });
28444
+ await (0, import_runtimeDeployments2.saveRuntimeDeployment)(userName2, updatedDeployment);
28445
+ console.log(
28446
+ JSON.stringify(
28447
+ {
28448
+ rolledOut: true,
28449
+ backupPath,
28450
+ release,
28451
+ deployment: updatedDeployment
28452
+ },
28453
+ null,
28454
+ 2
28455
+ )
28456
+ );
28457
+ };
28240
28458
  publishDraft = async () => {
28241
28459
  const strategyName = required2("strategy");
28242
28460
  const draft = await (0, import_runtimeStrategyReleases.getRuntimeStrategyDraft)(userName2, strategyName);
@@ -28345,7 +28563,9 @@ var init_runtimeConfig = __esm({
28345
28563
  console.log(JSON.stringify({ userName: userName2, deployments, releases }, null, 2));
28346
28564
  };
28347
28565
  runtimeConfig = async () => {
28566
+ if (action === "bootstrap") return bootstrap();
28348
28567
  if (action === "migrate") return migrate();
28568
+ if (action === "rollout") return rollout();
28349
28569
  if (action === "publish-draft") return publishDraft();
28350
28570
  if (action === "verify") return verify();
28351
28571
  if (action === "pause") return updateControlState("entries_paused");
@@ -28353,7 +28573,7 @@ var init_runtimeConfig = __esm({
28353
28573
  if (action === "rollback") return rollback();
28354
28574
  if (action === "inspect") return inspect();
28355
28575
  throw new Error(
28356
- "Usage: tradejs runtime-config inspect|verify|migrate|publish-draft|pause|resume|rollback"
28576
+ "Usage: tradejs runtime-config inspect|verify|bootstrap|migrate|rollout|publish-draft|pause|resume|rollback"
28357
28577
  );
28358
28578
  };
28359
28579
  main37 = runtimeConfig;
@@ -30,13 +30,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/scripts/runtimeConfig.ts
31
31
  var runtimeConfig_exports = {};
32
32
  __export(runtimeConfig_exports, {
33
+ buildBootstrapRuntimeDeployment: () => buildBootstrapRuntimeDeployment,
34
+ isEquivalentRuntimeStrategyRelease: () => isEquivalentRuntimeStrategyRelease,
33
35
  main: () => main,
36
+ pointRuntimeDeploymentAtRelease: () => pointRuntimeDeploymentAtRelease,
34
37
  runtimeConfig: () => runtimeConfig
35
38
  });
36
39
  module.exports = __toCommonJS(runtimeConfig_exports);
37
40
  var import_config = require("dotenv/config");
38
41
  var import_promises = require("fs/promises");
39
42
  var import_node_path = __toESM(require("path"));
43
+ var import_node_util = require("util");
40
44
  var import_runtimeDeployments = require("@tradejs/infra/runtimeDeployments");
41
45
  var import_runtimeStrategyConfigs = require("@tradejs/infra/runtimeStrategyConfigs");
42
46
  var import_runtimeStrategyReleases = require("@tradejs/infra/runtimeStrategyReleases");
@@ -102,6 +106,131 @@ var publish = async ({
102
106
  createdBy: `cli:${userName}`
103
107
  });
104
108
  };
109
+ var buildBootstrapRuntimeDeployment = ({
110
+ deploymentId,
111
+ label,
112
+ connectorName,
113
+ provider,
114
+ accountId,
115
+ strategyName,
116
+ releaseVersion,
117
+ config
118
+ }) => ({
119
+ id: deploymentId,
120
+ label,
121
+ connectorName,
122
+ provider,
123
+ accountId,
124
+ universe: config.UNIVERSE,
125
+ interval: String(config.INTERVAL),
126
+ enabled: true,
127
+ strategies: [
128
+ {
129
+ strategyName,
130
+ releaseVersion,
131
+ controlState: "entries_paused"
132
+ }
133
+ ]
134
+ });
135
+ var isEquivalentRuntimeStrategyRelease = ({
136
+ release,
137
+ config,
138
+ strategyPackage,
139
+ strategyPackageVersion,
140
+ runtimePackageVersion
141
+ }) => Boolean(
142
+ release && (0, import_node_util.isDeepStrictEqual)(release.config, config) && (release.strategyPackage ?? null) === (strategyPackage ?? null) && (release.strategyPackageVersion ?? null) === (strategyPackageVersion ?? null) && (release.runtimePackageVersion ?? null) === (runtimePackageVersion ?? null)
143
+ );
144
+ var pointRuntimeDeploymentAtRelease = ({
145
+ deployment,
146
+ strategyName,
147
+ releaseVersion
148
+ }) => ({
149
+ ...deployment,
150
+ strategies: deployment.strategies.map(
151
+ (strategy) => strategy.strategyName === strategyName ? {
152
+ strategyName,
153
+ releaseVersion,
154
+ controlState: "entries_paused"
155
+ } : strategy
156
+ )
157
+ });
158
+ var bootstrap = async () => {
159
+ const strategyName = required("strategy");
160
+ const deploymentId = required("deployment");
161
+ const accountId = required("account");
162
+ const connectorName = option("connector") ?? "bybit";
163
+ const provider = option("provider") ?? connectorName;
164
+ const label = option("label") ?? deploymentId;
165
+ const configFile = import_node_path.default.resolve(projectRoot, required("file"));
166
+ const sourceConfig = JSON.parse(
167
+ await (0, import_promises.readFile)(configFile, "utf8")
168
+ );
169
+ const existingDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(userName, deploymentId);
170
+ if (existingDeployment) {
171
+ throw new Error(
172
+ `Deployment already exists: ${deploymentId}; publish a release and switch its pointer instead`
173
+ );
174
+ }
175
+ const releaseConfig = await toReleaseConfig(strategyName, sourceConfig);
176
+ const previewDeployment = buildBootstrapRuntimeDeployment({
177
+ deploymentId,
178
+ label,
179
+ connectorName,
180
+ provider,
181
+ accountId,
182
+ strategyName,
183
+ releaseVersion: 1,
184
+ config: releaseConfig
185
+ });
186
+ if (!hasFlag("write")) {
187
+ console.log(
188
+ JSON.stringify(
189
+ {
190
+ dryRun: true,
191
+ releaseConfig,
192
+ deployment: {
193
+ ...previewDeployment,
194
+ strategies: previewDeployment.strategies.map((strategy) => ({
195
+ ...strategy,
196
+ releaseVersion: "<allocated on write>"
197
+ }))
198
+ }
199
+ },
200
+ null,
201
+ 2
202
+ )
203
+ );
204
+ return;
205
+ }
206
+ const backupPath = await writeMigrationBackup({
207
+ userName,
208
+ capturedAt: Date.now(),
209
+ reason: "bootstrap",
210
+ sourceConfig
211
+ });
212
+ const release = await publish({ strategyName, sourceConfig });
213
+ const deployment = await (0, import_runtimeDeployments.saveRuntimeDeployment)(
214
+ userName,
215
+ buildBootstrapRuntimeDeployment({
216
+ deploymentId,
217
+ label,
218
+ connectorName,
219
+ provider,
220
+ accountId,
221
+ strategyName,
222
+ releaseVersion: release.releaseVersion,
223
+ config: release.config
224
+ })
225
+ );
226
+ console.log(
227
+ JSON.stringify(
228
+ { bootstrapped: true, backupPath, release, deployment },
229
+ null,
230
+ 2
231
+ )
232
+ );
233
+ };
105
234
  var migrate = async () => {
106
235
  const strategyName = required("strategy");
107
236
  const configId = option("config") ?? "config";
@@ -163,6 +292,95 @@ var migrate = async () => {
163
292
  )
164
293
  );
165
294
  };
295
+ var rollout = async () => {
296
+ const strategyName = required("strategy");
297
+ const deploymentId = required("deployment");
298
+ const configFile = import_node_path.default.resolve(projectRoot, required("file"));
299
+ const [deployment, sourceConfig] = await Promise.all([
300
+ (0, import_runtimeDeployments.getRuntimeDeployment)(userName, deploymentId),
301
+ (0, import_promises.readFile)(configFile, "utf8").then(
302
+ (value) => JSON.parse(value)
303
+ )
304
+ ]);
305
+ if (!deployment) throw new Error(`Deployment not found: ${deploymentId}`);
306
+ const reference = deployment.strategies.find(
307
+ (strategy) => strategy.strategyName === strategyName
308
+ );
309
+ if (!reference?.releaseVersion) {
310
+ throw new Error(`${strategyName} is not a versioned deployment reference`);
311
+ }
312
+ const [config, metadata, currentRelease] = await Promise.all([
313
+ toReleaseConfig(strategyName, sourceConfig),
314
+ (0, import_runtimeStrategies.getRuntimeStrategyPackageMetadata)({ strategyName, projectRoot }),
315
+ (0, import_runtimeStrategyReleases.getRuntimeStrategyRelease)(userName, strategyName, reference.releaseVersion)
316
+ ]);
317
+ const unchanged = isEquivalentRuntimeStrategyRelease({
318
+ release: currentRelease,
319
+ config,
320
+ ...metadata
321
+ });
322
+ const preview = {
323
+ deploymentId,
324
+ strategyName,
325
+ currentReleaseVersion: reference.releaseVersion,
326
+ nextControlState: "entries_paused",
327
+ unchanged,
328
+ config,
329
+ ...metadata
330
+ };
331
+ if (!hasFlag("write")) {
332
+ console.log(JSON.stringify({ dryRun: true, ...preview }, null, 2));
333
+ return;
334
+ }
335
+ if (unchanged) {
336
+ console.log(
337
+ JSON.stringify(
338
+ {
339
+ rolledOut: false,
340
+ reason: "release_config_and_packages_unchanged",
341
+ release: currentRelease,
342
+ deployment
343
+ },
344
+ null,
345
+ 2
346
+ )
347
+ );
348
+ return;
349
+ }
350
+ const backupPath = await writeMigrationBackup({
351
+ userName,
352
+ capturedAt: Date.now(),
353
+ reason: "rollout",
354
+ deployment,
355
+ currentRelease,
356
+ sourceConfig
357
+ });
358
+ const release = await (0, import_runtimeStrategyReleases.publishRuntimeStrategyRelease)({
359
+ userName,
360
+ strategyName,
361
+ config,
362
+ ...metadata,
363
+ createdBy: `cli:${userName}`
364
+ });
365
+ const updatedDeployment = pointRuntimeDeploymentAtRelease({
366
+ deployment,
367
+ strategyName,
368
+ releaseVersion: release.releaseVersion
369
+ });
370
+ await (0, import_runtimeDeployments.saveRuntimeDeployment)(userName, updatedDeployment);
371
+ console.log(
372
+ JSON.stringify(
373
+ {
374
+ rolledOut: true,
375
+ backupPath,
376
+ release,
377
+ deployment: updatedDeployment
378
+ },
379
+ null,
380
+ 2
381
+ )
382
+ );
383
+ };
166
384
  var publishDraft = async () => {
167
385
  const strategyName = required("strategy");
168
386
  const draft = await (0, import_runtimeStrategyReleases.getRuntimeStrategyDraft)(userName, strategyName);
@@ -271,7 +489,9 @@ var inspect = async () => {
271
489
  console.log(JSON.stringify({ userName, deployments, releases }, null, 2));
272
490
  };
273
491
  var runtimeConfig = async () => {
492
+ if (action === "bootstrap") return bootstrap();
274
493
  if (action === "migrate") return migrate();
494
+ if (action === "rollout") return rollout();
275
495
  if (action === "publish-draft") return publishDraft();
276
496
  if (action === "verify") return verify();
277
497
  if (action === "pause") return updateControlState("entries_paused");
@@ -279,12 +499,15 @@ var runtimeConfig = async () => {
279
499
  if (action === "rollback") return rollback();
280
500
  if (action === "inspect") return inspect();
281
501
  throw new Error(
282
- "Usage: tradejs runtime-config inspect|verify|migrate|publish-draft|pause|resume|rollback"
502
+ "Usage: tradejs runtime-config inspect|verify|bootstrap|migrate|rollout|publish-draft|pause|resume|rollback"
283
503
  );
284
504
  };
285
505
  var main = runtimeConfig;
286
506
  // Annotate the CommonJS export names for ESM import in node:
287
507
  0 && (module.exports = {
508
+ buildBootstrapRuntimeDeployment,
509
+ isEquivalentRuntimeStrategyRelease,
288
510
  main,
511
+ pointRuntimeDeploymentAtRelease,
289
512
  runtimeConfig
290
513
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "3.1.1",
3
+ "version": "3.1.3",
4
4
  "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -32,13 +32,13 @@
32
32
  "tradejs": "dist/cli.js"
33
33
  },
34
34
  "dependencies": {
35
- "@tradejs/connectors": "^3.1.1",
36
- "@tradejs/core": "^3.1.1",
37
- "@tradejs/indicators": "^3.1.1",
38
- "@tradejs/infra": "^3.1.1",
39
- "@tradejs/node": "^3.1.1",
35
+ "@tradejs/connectors": "^3.1.3",
36
+ "@tradejs/core": "^3.1.3",
37
+ "@tradejs/indicators": "^3.1.3",
38
+ "@tradejs/infra": "^3.1.3",
39
+ "@tradejs/node": "^3.1.3",
40
40
  "@tradejs/strategy-kit": "^3.0.0",
41
- "@tradejs/types": "^3.1.1",
41
+ "@tradejs/types": "^3.1.3",
42
42
  "args": "^5.0.3",
43
43
  "bcryptjs": "^2.4.3",
44
44
  "chalk": "4.1.2",