@nmakarov/cli-toolkit 0.21.0 → 0.25.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 (68) hide show
  1. package/dist/args.cjs +1 -4
  2. package/dist/args.cjs.map +1 -1
  3. package/dist/args.js +1 -1
  4. package/dist/args.js.map +1 -1
  5. package/dist/cli-runner.cjs +1370 -623
  6. package/dist/cli-runner.cjs.map +1 -1
  7. package/dist/cli-runner.js +1415 -667
  8. package/dist/cli-runner.js.map +1 -1
  9. package/dist/db.cjs +173 -158
  10. package/dist/db.cjs.map +1 -1
  11. package/dist/db.js +172 -151
  12. package/dist/db.js.map +1 -1
  13. package/dist/errors.cjs +2 -2
  14. package/dist/errors.cjs.map +1 -1
  15. package/dist/errors.js +2 -1
  16. package/dist/errors.js.map +1 -1
  17. package/dist/filedatabase.cjs +19 -19
  18. package/dist/filedatabase.cjs.map +1 -1
  19. package/dist/filedatabase.js +19 -16
  20. package/dist/filedatabase.js.map +1 -1
  21. package/dist/http-client.cjs +9 -11
  22. package/dist/http-client.cjs.map +1 -1
  23. package/dist/http-client.js +10 -9
  24. package/dist/http-client.js.map +1 -1
  25. package/dist/http-client2.cjs +34 -37
  26. package/dist/http-client2.cjs.map +1 -1
  27. package/dist/http-client2.js +34 -34
  28. package/dist/http-client2.js.map +1 -1
  29. package/dist/index.cjs +1831 -713
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +1837 -713
  32. package/dist/index.js.map +1 -1
  33. package/dist/init.cjs +93 -68
  34. package/dist/init.cjs.map +1 -1
  35. package/dist/init.js +108 -82
  36. package/dist/init.js.map +1 -1
  37. package/dist/logger.cjs +5 -5
  38. package/dist/logger.cjs.map +1 -1
  39. package/dist/logger.js +5 -4
  40. package/dist/logger.js.map +1 -1
  41. package/dist/mock-server.cjs +21 -33
  42. package/dist/mock-server.cjs.map +1 -1
  43. package/dist/mock-server.js +21 -28
  44. package/dist/mock-server.js.map +1 -1
  45. package/dist/params.cjs +18 -9
  46. package/dist/params.cjs.map +1 -1
  47. package/dist/params.js +18 -6
  48. package/dist/params.js.map +1 -1
  49. package/dist/s3.cjs +286 -0
  50. package/dist/s3.cjs.map +1 -0
  51. package/dist/s3.js +273 -0
  52. package/dist/s3.js.map +1 -0
  53. package/dist/screen.cjs +34 -39
  54. package/dist/screen.cjs.map +1 -1
  55. package/dist/screen.js +48 -46
  56. package/dist/screen.js.map +1 -1
  57. package/dist/tasks.cjs +1354 -501
  58. package/dist/tasks.cjs.map +1 -1
  59. package/dist/tasks.js +1369 -527
  60. package/dist/tasks.js.map +1 -1
  61. package/dist/utils.cjs +7 -8
  62. package/dist/utils.cjs.map +1 -1
  63. package/dist/utils.js +6 -6
  64. package/dist/utils.js.map +1 -1
  65. package/package.json +32 -47
  66. package/scripts/ssm/{parse-cli.ts → parse-cli.js} +4 -4
  67. package/scripts/ssm/{ssm-admin.ts → ssm-admin.js} +12 -12
  68. package/scripts/ssm/{ssm-pull.ts → ssm-pull.js} +10 -13
package/dist/init.js CHANGED
@@ -14,7 +14,7 @@ var __export = (target, all) => {
14
14
  __defProp(target, name, { get: all[name], enumerable: true });
15
15
  };
16
16
 
17
- // src/screen/components.ts
17
+ // src/screen/components.js
18
18
  import { createElement as h } from "react";
19
19
  import { Box, Text } from "ink";
20
20
  function getScreenWidth(maxWidth = null) {
@@ -89,13 +89,12 @@ function ScreenFooter({ lines, textStyle }) {
89
89
  );
90
90
  }
91
91
  var init_components = __esm({
92
- "src/screen/components.ts"() {
93
- "use strict";
92
+ "src/screen/components.js"() {
94
93
  }
95
94
  });
96
95
 
97
- // src/screen/list-components.ts
98
- import React2, { useState, useEffect, useRef, createElement } from "react";
96
+ // src/screen/list-components.js
97
+ import React, { useState, useEffect, useRef, createElement } from "react";
99
98
  import { Box as Box2, Text as Text2 } from "ink";
100
99
  function MultiColumnListComponent({ items, ctx, selectedIndexRef }) {
101
100
  const [, forceUpdate] = useState({});
@@ -231,11 +230,11 @@ function MultiColumnListWithPreviewComponent({
231
230
  const previewRows = [];
232
231
  if (typeof previewContent === "string") {
233
232
  previewRows.push(h2(ScreenRow, { key: "preview-string", children: h2(Text2, { bold: true }, previewContent) }));
234
- } else if (typeof previewContent === "object" && !React2.isValidElement(previewContent) && previewContent !== null) {
233
+ } else if (typeof previewContent === "object" && !React.isValidElement(previewContent) && previewContent !== null) {
235
234
  Object.entries(previewContent).forEach(([key, value], idx) => {
236
235
  previewRows.push(h2(ScreenRow, { key: `preview-${key}-${idx}`, children: h2(Text2, {}, `${key}: ${value}`) }));
237
236
  });
238
- } else if (React2.isValidElement(previewContent)) {
237
+ } else if (React.isValidElement(previewContent)) {
239
238
  previewRows.push(h2(ScreenRow, { key: "preview-element", children: previewContent }));
240
239
  }
241
240
  return h2(
@@ -248,11 +247,13 @@ function MultiColumnListWithPreviewComponent({
248
247
  ...previewRows
249
248
  );
250
249
  }
251
- function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sortable = false, maxHeight, sortHighlightStyle, selectionMarker = " " }) {
250
+ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sortable = false, maxHeight, sortHighlightStyle, selectionMarker = " ", onSelectionChange }) {
252
251
  const [, forceUpdate] = useState({});
253
252
  const [sortOrder, setSortOrder] = useState("none");
254
253
  const [scrollOffset, setScrollOffset] = useState(0);
255
254
  const scrollStateRef = useRef({ scrollOffset: 0, maxHeight: 0, totalItems: 0 });
255
+ const itemsRef = useRef(items);
256
+ itemsRef.current = items;
256
257
  const defaultGetTitle = (item) => {
257
258
  return getTitle ? getTitle(item) : typeof item.value === "string" ? item.value : item.value?.title || item.name;
258
259
  };
@@ -266,18 +267,24 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
266
267
  return titleA > titleB ? -1 : titleA < titleB ? 1 : 0;
267
268
  }
268
269
  }) : items;
270
+ const displayItemsRef = useRef(displayItems);
271
+ displayItemsRef.current = displayItems;
269
272
  const effectiveMaxHeight = maxHeight || displayItems.length;
270
- const canScroll = displayItems.length > effectiveMaxHeight;
273
+ const _canScroll = displayItems.length > effectiveMaxHeight;
271
274
  const maxScrollOffset = Math.max(0, displayItems.length - effectiveMaxHeight);
272
275
  const clampedScrollOffset = Math.min(Math.max(0, scrollOffset), maxScrollOffset);
273
276
  const visibleItems = displayItems.slice(clampedScrollOffset, clampedScrollOffset + effectiveMaxHeight);
274
277
  const canScrollUp = clampedScrollOffset > 0;
275
278
  const canScrollDown = clampedScrollOffset < maxScrollOffset;
276
279
  scrollStateRef.current = { scrollOffset, maxHeight: effectiveMaxHeight, totalItems: displayItems.length };
280
+ const onSelectionChangeRef = useRef(onSelectionChange);
281
+ onSelectionChangeRef.current = onSelectionChange;
277
282
  useEffect(() => {
278
283
  ctx.setAction("moveUp", () => {
279
284
  const newIndex = Math.max(0, selectedIndexRef.current - 1);
280
285
  selectedIndexRef.current = newIndex;
286
+ const list = displayItemsRef.current;
287
+ onSelectionChangeRef.current?.(newIndex, list[newIndex]);
281
288
  const { scrollOffset: currentScrollOffset, maxHeight: currentMaxHeight, totalItems } = scrollStateRef.current;
282
289
  const currentMaxScrollOffset = Math.max(0, totalItems - currentMaxHeight);
283
290
  const currentClampedScrollOffset = Math.min(Math.max(0, currentScrollOffset), currentMaxScrollOffset);
@@ -287,18 +294,11 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
287
294
  forceUpdate({});
288
295
  });
289
296
  ctx.setAction("moveDown", () => {
290
- const currentItems = sortable && sortOrder !== "none" ? [...items].sort((a, b) => {
291
- const titleA = titleGetter(a).toLowerCase();
292
- const titleB = titleGetter(b).toLowerCase();
293
- if (sortOrder === "asc") {
294
- return titleA < titleB ? -1 : titleA > titleB ? 1 : 0;
295
- } else {
296
- return titleA > titleB ? -1 : titleA < titleB ? 1 : 0;
297
- }
298
- }) : items;
299
- const maxIndex = currentItems.length - 1;
297
+ const currentItems = displayItemsRef.current;
298
+ const maxIndex = Math.max(0, currentItems.length - 1);
300
299
  const newIndex = Math.min(maxIndex, selectedIndexRef.current + 1);
301
300
  selectedIndexRef.current = newIndex;
301
+ onSelectionChangeRef.current?.(newIndex, currentItems[newIndex]);
302
302
  const { scrollOffset: currentScrollOffset, maxHeight: currentMaxHeight, totalItems } = scrollStateRef.current;
303
303
  const currentMaxScrollOffset = Math.max(0, totalItems - currentMaxHeight);
304
304
  const currentClampedScrollOffset = Math.min(Math.max(0, currentScrollOffset), currentMaxScrollOffset);
@@ -308,8 +308,7 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
308
308
  forceUpdate({});
309
309
  });
310
310
  ctx.setAction("scrollUp", () => {
311
- const { scrollOffset: currentScrollOffset, maxHeight: currentMaxHeight, totalItems } = scrollStateRef.current;
312
- const currentMaxScrollOffset = Math.max(0, totalItems - currentMaxHeight);
311
+ const { scrollOffset: currentScrollOffset } = scrollStateRef.current;
313
312
  const newScrollOffset = Math.max(0, currentScrollOffset - 1);
314
313
  setScrollOffset(newScrollOffset);
315
314
  forceUpdate({});
@@ -324,9 +323,9 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
324
323
  if (sortable) {
325
324
  ctx.setAction("toggleSort", () => {
326
325
  const nextSort = sortOrder === "none" ? "asc" : sortOrder === "asc" ? "desc" : "none";
327
- const currentSelectedItem = displayItems[selectedIndexRef.current];
326
+ const currentSelectedItem = displayItemsRef.current[selectedIndexRef.current];
328
327
  setSortOrder(nextSort);
329
- const newSortedItems = nextSort !== "none" ? [...items].sort((a, b) => {
328
+ const newSortedItems = nextSort !== "none" ? [...itemsRef.current].sort((a, b) => {
330
329
  const titleA = titleGetter(a).toLowerCase();
331
330
  const titleB = titleGetter(b).toLowerCase();
332
331
  if (nextSort === "asc") {
@@ -334,7 +333,7 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
334
333
  } else {
335
334
  return titleA > titleB ? -1 : titleA < titleB ? 1 : 0;
336
335
  }
337
- }) : items;
336
+ }) : itemsRef.current;
338
337
  const newIndex = newSortedItems.findIndex((item) => item === currentSelectedItem);
339
338
  if (newIndex !== -1) {
340
339
  selectedIndexRef.current = newIndex;
@@ -472,14 +471,13 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
472
471
  }
473
472
  var h2;
474
473
  var init_list_components = __esm({
475
- "src/screen/list-components.ts"() {
476
- "use strict";
474
+ "src/screen/list-components.js"() {
477
475
  init_components();
478
476
  h2 = createElement;
479
477
  }
480
478
  });
481
479
 
482
- // src/screen/screens.ts
480
+ // src/screen/screens.js
483
481
  import { useState as useState2, createElement as h3 } from "react";
484
482
  import { render, useInput, Text as Text3 } from "ink";
485
483
  function groupKeyBindings(bindings) {
@@ -557,7 +555,7 @@ async function showScreen(config2) {
557
555
  let renderResult = null;
558
556
  let initialized = false;
559
557
  const Screen = () => {
560
- const [updateCounter, setUpdateCounter] = useState2(0);
558
+ const [, setUpdateCounter] = useState2(0);
561
559
  if (!initialized) {
562
560
  const defaultBindings = [
563
561
  { key: "escape", caption: "go back", action: "back", protected: true, order: 1 },
@@ -676,7 +674,7 @@ async function showScreen(config2) {
676
674
  }
677
675
  }
678
676
  if (matchedBinding && actions[matchedBinding.action]) {
679
- const actionResult = actions[matchedBinding.action]({
677
+ actions[matchedBinding.action]({
680
678
  input,
681
679
  key,
682
680
  binding: matchedBinding
@@ -806,8 +804,7 @@ async function showMultiColumnListWithPreviewScreen(config2) {
806
804
  }
807
805
  var showMenuScreen, showWordGridScreen;
808
806
  var init_screens = __esm({
809
- "src/screen/screens.ts"() {
810
- "use strict";
807
+ "src/screen/screens.js"() {
811
808
  init_components();
812
809
  init_list_components();
813
810
  showMenuScreen = showListScreen;
@@ -815,9 +812,9 @@ var init_screens = __esm({
815
812
  }
816
813
  });
817
814
 
818
- // src/screen/ui-elements.ts
815
+ // src/screen/ui-elements.js
819
816
  import { createElement as h4 } from "react";
820
- import { Box as Box4, Text as Text4 } from "ink";
817
+ import { Box as Box3, Text as Text4 } from "ink";
821
818
  function ListItem({
822
819
  children,
823
820
  isSelected = false,
@@ -827,7 +824,7 @@ function ListItem({
827
824
  dimColor = false
828
825
  }) {
829
826
  return h4(
830
- Box4,
827
+ Box3,
831
828
  {},
832
829
  h4(Text4, {
833
830
  color: isSelected ? backgroundColor || "green" : color,
@@ -842,10 +839,10 @@ function TextBlock({
842
839
  color = "white",
843
840
  dimmed = false,
844
841
  bold = false,
845
- maxWidth
842
+ maxWidth: _maxWidth
846
843
  }) {
847
844
  return h4(
848
- Box4,
845
+ Box3,
849
846
  {},
850
847
  h4(Text4, {
851
848
  color,
@@ -856,7 +853,7 @@ function TextBlock({
856
853
  }
857
854
  function Divider({ character = "\u2500", width = 80 }) {
858
855
  return h4(
859
- Box4,
856
+ Box3,
860
857
  { marginY: 1 },
861
858
  h4(Text4, { dimColor: true }, character.repeat(width))
862
859
  );
@@ -871,7 +868,7 @@ function GridCell({
871
868
  align = "left"
872
869
  }) {
873
870
  return h4(
874
- Box4,
871
+ Box3,
875
872
  { width },
876
873
  h4(Text4, {
877
874
  color,
@@ -882,25 +879,24 @@ function GridCell({
882
879
  }, children)
883
880
  );
884
881
  }
885
- function InputField({ prompt, value, onChange, onSubmit }) {
882
+ function InputField({ prompt, value, onChange: _onChange, onSubmit: _onSubmit }) {
886
883
  return h4(
887
- Box4,
884
+ Box3,
888
885
  { flexDirection: "column" },
889
886
  h4(Text4, {}, prompt),
890
887
  h4(
891
- Box4,
888
+ Box3,
892
889
  { marginTop: 1 },
893
890
  h4(Text4, { color: "cyan" }, " > ", value, "_")
894
891
  )
895
892
  );
896
893
  }
897
894
  var init_ui_elements = __esm({
898
- "src/screen/ui-elements.ts"() {
899
- "use strict";
895
+ "src/screen/ui-elements.js"() {
900
896
  }
901
897
  });
902
898
 
903
- // src/screen/utils.ts
899
+ // src/screen/utils.js
904
900
  function buildBreadcrumb(parts) {
905
901
  if (parts.length === 0) return "";
906
902
  if (parts.length === 1) return parts[0];
@@ -914,12 +910,11 @@ function buildDetailBreadcrumb(path, suffix = "") {
914
910
  return suffix ? `${breadcrumb} ${suffix}` : breadcrumb;
915
911
  }
916
912
  var init_utils = __esm({
917
- "src/screen/utils.ts"() {
918
- "use strict";
913
+ "src/screen/utils.js"() {
919
914
  }
920
915
  });
921
916
 
922
- // src/screen/footer-builder.ts
917
+ // src/screen/footer-builder.js
923
918
  function buildFooter(config2 = {}) {
924
919
  const {
925
920
  navigation = null,
@@ -970,8 +965,7 @@ function organizeFooterMessages(messages) {
970
965
  }
971
966
  var FooterPresets;
972
967
  var init_footer_builder = __esm({
973
- "src/screen/footer-builder.ts"() {
974
- "use strict";
968
+ "src/screen/footer-builder.js"() {
975
969
  FooterPresets = {
976
970
  /**
977
971
  * Menu screen footer
@@ -1030,10 +1024,10 @@ var init_footer_builder = __esm({
1030
1024
  }
1031
1025
  });
1032
1026
 
1033
- // src/screen/index.ts
1027
+ // src/screen/index.js
1034
1028
  var screen_exports = {};
1035
1029
  __export(screen_exports, {
1036
- Box: () => Box5,
1030
+ Box: () => Box4,
1037
1031
  Divider: () => Divider,
1038
1032
  FooterPresets: () => FooterPresets,
1039
1033
  GridCell: () => GridCell,
@@ -1042,7 +1036,7 @@ __export(screen_exports, {
1042
1036
  ListItem: () => ListItem,
1043
1037
  MultiColumnListComponent: () => MultiColumnListComponent,
1044
1038
  MultiColumnListWithPreviewComponent: () => MultiColumnListWithPreviewComponent,
1045
- React: () => React5,
1039
+ React: () => React2,
1046
1040
  ScreenBody: () => ScreenBody,
1047
1041
  ScreenContainer: () => ScreenContainer,
1048
1042
  ScreenDivider: () => ScreenDivider,
@@ -1056,6 +1050,7 @@ __export(screen_exports, {
1056
1050
  buildFooter: () => buildFooter,
1057
1051
  h: () => createElement2,
1058
1052
  load: () => load,
1053
+ memo: () => memo,
1059
1054
  organizeFooterMessages: () => organizeFooterMessages,
1060
1055
  showListScreen: () => showListScreen,
1061
1056
  showMenuScreen: () => showMenuScreen,
@@ -1064,14 +1059,15 @@ __export(screen_exports, {
1064
1059
  showScreen: () => showScreen,
1065
1060
  showWordGridScreen: () => showWordGridScreen,
1066
1061
  useCallback: () => useCallback,
1067
- useEffect: () => useEffect3,
1062
+ useEffect: () => useEffect2,
1068
1063
  useInput: () => useInput2,
1064
+ useLayoutEffect: () => useLayoutEffect,
1069
1065
  useMemo: () => useMemo,
1070
- useRef: () => useRef3,
1066
+ useRef: () => useRef2,
1071
1067
  useState: () => useState3
1072
1068
  });
1073
- import React5, { useState as useState3, useEffect as useEffect3, useRef as useRef3, useMemo, useCallback, createElement as createElement2 } from "react";
1074
- import { Box as Box5, Text as Text5, useInput as useInput2 } from "ink";
1069
+ import React2, { useState as useState3, useEffect as useEffect2, useLayoutEffect, useRef as useRef2, useMemo, useCallback, memo, createElement as createElement2 } from "react";
1070
+ import { Box as Box4, Text as Text5, useInput as useInput2 } from "ink";
1075
1071
  async function load() {
1076
1072
  if (loadPromise) return loadPromise;
1077
1073
  loadPromise = Promise.all([
@@ -1083,8 +1079,7 @@ async function load() {
1083
1079
  }
1084
1080
  var loadPromise;
1085
1081
  var init_screen = __esm({
1086
- "src/screen/index.ts"() {
1087
- "use strict";
1082
+ "src/screen/index.js"() {
1088
1083
  init_screens();
1089
1084
  init_list_components();
1090
1085
  init_components();
@@ -1099,7 +1094,7 @@ var init_screen = __esm({
1099
1094
  }
1100
1095
  });
1101
1096
 
1102
- // src/args/index.ts
1097
+ // src/args/index.js
1103
1098
  import { readFileSync, existsSync } from "fs";
1104
1099
  import { resolve, dirname, basename, extname, join, isAbsolute } from "path";
1105
1100
  import { config } from "dotenv";
@@ -1582,10 +1577,10 @@ var Args = class _Args {
1582
1577
  }
1583
1578
  };
1584
1579
 
1585
- // src/params/index.ts
1580
+ // src/params/index.js
1586
1581
  import Joi from "joi";
1587
1582
 
1588
- // src/errors.ts
1583
+ // src/errors.js
1589
1584
  var FrameworkError = class extends Error {
1590
1585
  constructor(message) {
1591
1586
  super(message);
@@ -1605,7 +1600,7 @@ var InitError = class extends FrameworkError {
1605
1600
  }
1606
1601
  };
1607
1602
 
1608
- // src/params/custom-types.ts
1603
+ // src/params/custom-types.js
1609
1604
  var joiEdateType = (value, helpers) => {
1610
1605
  if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(value)) {
1611
1606
  const testDate = new Date(value);
@@ -1698,7 +1693,7 @@ function calculateTimeOffset(amount, unit, sign) {
1698
1693
  }
1699
1694
  return sign === "+" ? amount * multiplier : -amount * multiplier;
1700
1695
  }
1701
- var joiStringArrayType = (type) => (value, helpers) => {
1696
+ var joiStringArrayType = (type) => (value, _helpers) => {
1702
1697
  if (value === void 0 || typeof value === "function") {
1703
1698
  return [];
1704
1699
  }
@@ -1724,7 +1719,7 @@ var joiStringArrayType = (type) => (value, helpers) => {
1724
1719
  return arr;
1725
1720
  };
1726
1721
 
1727
- // src/params/index.ts
1722
+ // src/params/index.js
1728
1723
  var Params = class _Params {
1729
1724
  context;
1730
1725
  // Partial context during initialization
@@ -1984,7 +1979,7 @@ var Params = class _Params {
1984
1979
  definition = val;
1985
1980
  val = val.value;
1986
1981
  }
1987
- const def = this.assignDefinition(key, definition);
1982
+ this.assignDefinition(key, definition);
1988
1983
  if (!this.runAllRegisteredSetters(key, val)) {
1989
1984
  this.params[key] = val;
1990
1985
  }
@@ -2043,6 +2038,18 @@ var Params = class _Params {
2043
2038
  this._currentModule = prev;
2044
2039
  }
2045
2040
  }
2041
+ /**
2042
+ * Async variant of {@link runWithModule} for modules that await params.get().
2043
+ */
2044
+ async runWithModuleAsync(moduleName, fn) {
2045
+ const prev = this._currentModule;
2046
+ this._currentModule = moduleName;
2047
+ try {
2048
+ return await fn();
2049
+ } finally {
2050
+ this._currentModule = prev;
2051
+ }
2052
+ }
2046
2053
  /**
2047
2054
  * Infer module name from call stack: first caller outside params/index gives path like .../src/<moduleName>/...
2048
2055
  */
@@ -2103,11 +2110,11 @@ var Params = class _Params {
2103
2110
  }
2104
2111
  };
2105
2112
 
2106
- // src/logger/index.ts
2113
+ // src/logger/index.js
2107
2114
  import chalk from "chalk";
2108
2115
  import util from "util";
2109
2116
 
2110
- // src/logger/transports.ts
2117
+ // src/logger/transports.js
2111
2118
  var ConsoleTransport = class {
2112
2119
  write(payload) {
2113
2120
  console.info(payload);
@@ -2127,7 +2134,7 @@ var ParentProcessTransport = class {
2127
2134
  }
2128
2135
  };
2129
2136
 
2130
- // src/logger/index.ts
2137
+ // src/logger/index.js
2131
2138
  var ALL_LEVELS = [
2132
2139
  "silly",
2133
2140
  "debug",
@@ -2200,6 +2207,7 @@ var Logger = class _Logger {
2200
2207
  }
2201
2208
  /**
2202
2209
  * Initialize logger from context and CLI parameters. Whatever is in options goes (after discovered params).
2210
+ * Params are tracked under the `logger` module for --showUsedParams.
2203
2211
  */
2204
2212
  static init(context, options) {
2205
2213
  const paramDefs = {
@@ -2213,7 +2221,7 @@ var Logger = class _Logger {
2213
2221
  progressWithTimes: "boolean default false",
2214
2222
  progressThrottleMs: "number"
2215
2223
  };
2216
- const discovered = context.params.getAllForModule(paramDefs);
2224
+ const discovered = context.params.getAllForModule("logger", paramDefs);
2217
2225
  const config2 = { ...discovered, ...options };
2218
2226
  const logger = new _Logger(context, config2);
2219
2227
  context.logger = logger;
@@ -2409,9 +2417,9 @@ var Logger = class _Logger {
2409
2417
  }
2410
2418
  };
2411
2419
 
2412
- // src/init/index.ts
2420
+ // src/init/index.js
2413
2421
  import { EventEmitter } from "events";
2414
- function extractComponentOptions(opts, componentName) {
2422
+ function extractComponentOptions(opts, _componentName) {
2415
2423
  const reservedKeys = ["overrides", "defaults", "modules"];
2416
2424
  const componentOptions = {};
2417
2425
  for (const [key, value] of Object.entries(opts)) {
@@ -2478,6 +2486,19 @@ function printAllParameters(context) {
2478
2486
  async function init(flow, opts = {}) {
2479
2487
  let stop = false;
2480
2488
  let context = null;
2489
+ let cleanupRan = false;
2490
+ const runRegisteredCleanups = async (ctx) => {
2491
+ if (cleanupRan) return;
2492
+ cleanupRan = true;
2493
+ const fns = [...ctx.cleanupFunctions].reverse();
2494
+ for (const fn of fns) {
2495
+ try {
2496
+ await fn(ctx);
2497
+ } catch (error) {
2498
+ ctx.logger.warn("[cleanup] error in cleanup function:", error);
2499
+ }
2500
+ }
2501
+ };
2481
2502
  try {
2482
2503
  try {
2483
2504
  const screenModule = await Promise.resolve().then(() => (init_screen(), screen_exports));
@@ -2500,13 +2521,24 @@ async function init(flow, opts = {}) {
2500
2521
  printAllParameters(context);
2501
2522
  process.exit(0);
2502
2523
  }
2524
+ let sigintCount = 0;
2503
2525
  process.on("SIGINT", async () => {
2504
- if (stop) {
2505
- context.logger.warn("[process] killed");
2506
- process.exit(2);
2526
+ if (!context) return;
2527
+ sigintCount += 1;
2528
+ if (sigintCount === 1) {
2529
+ stop = true;
2530
+ context.logger.info(`>> emitting stop with allowance ${stopAllowance}`);
2531
+ context.emitter.emit("stop", stopAllowance);
2532
+ return;
2507
2533
  }
2534
+ context.logger.warn("[process] second SIGINT: running cleanup then exit");
2535
+ await runRegisteredCleanups(context);
2536
+ process.exit(2);
2537
+ });
2538
+ process.on("SIGTERM", () => {
2539
+ if (!context || stop) return;
2508
2540
  stop = true;
2509
- context.logger.info(`>> emitting stop with allowance ${stopAllowance}`);
2541
+ context.logger.info(`>> SIGTERM: emitting stop with allowance ${stopAllowance}`);
2510
2542
  context.emitter.emit("stop", stopAllowance);
2511
2543
  });
2512
2544
  await flow(context);
@@ -2531,13 +2563,7 @@ async function init(flow, opts = {}) {
2531
2563
  }
2532
2564
  } finally {
2533
2565
  if (context) {
2534
- for (const fn of context.cleanupFunctions.reverse()) {
2535
- try {
2536
- await fn(context);
2537
- } catch (error) {
2538
- context.logger.warn("[cleanup] error in cleanup function:", error);
2539
- }
2540
- }
2566
+ await runRegisteredCleanups(context);
2541
2567
  }
2542
2568
  }
2543
2569
  }