hammerkit 1.4.0-beta.6 → 1.5.0-alpha.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 (182) hide show
  1. package/.devcontainer/Dockerfile +5 -0
  2. package/.devcontainer/devcontainer.json +40 -0
  3. package/Dockerfile +1 -1
  4. package/README.md +13 -86
  5. package/SUMMARY.md +43 -0
  6. package/build.schema.json +56 -2
  7. package/dist/cli.js +97 -0
  8. package/dist/cli.spec.js +5 -0
  9. package/dist/console/console-context-mock.js +11 -0
  10. package/dist/console/get-logger.js +23 -0
  11. package/dist/docker/pull.js +5 -5
  12. package/dist/docker/remove-container.js +21 -0
  13. package/dist/docker/stream.js +19 -21
  14. package/dist/docker/using-container.js +28 -0
  15. package/dist/environment/get-process-env.js +4 -4
  16. package/dist/environment/replace-env-variables.js +2 -3
  17. package/dist/executer/abort.js +13 -0
  18. package/dist/executer/check-readiness.js +25 -0
  19. package/dist/executer/create-scheduler-state.js +32 -0
  20. package/dist/executer/docker-node.js +123 -0
  21. package/dist/executer/docker-service.js +113 -0
  22. package/dist/executer/environment-mock.js +17 -0
  23. package/dist/executer/event-cache.js +165 -0
  24. package/dist/executer/execute-command.js +42 -0
  25. package/dist/executer/execute-docker.js +73 -223
  26. package/dist/executer/execute.spec.js +37 -37
  27. package/dist/executer/execution-steps.js +57 -0
  28. package/dist/executer/get-docker-executor.js +21 -20
  29. package/dist/executer/hierarchy-scheduler.js +94 -0
  30. package/dist/executer/kubernetes-service.js +64 -0
  31. package/dist/executer/label-values.js +65 -0
  32. package/dist/executer/local-node.js +57 -0
  33. package/dist/executer/print-container-options.js +17 -0
  34. package/dist/{logging/log-strategy.js → executer/process-item.js} +1 -1
  35. package/dist/executer/process-listener.js +3 -0
  36. package/dist/executer/process-manager.js +111 -0
  37. package/dist/executer/process-manager.spec.js +91 -0
  38. package/dist/executer/{executor.js → process.js} +1 -1
  39. package/dist/executer/{execute-result.js → readonly-state.js} +1 -1
  40. package/dist/executer/schedule.js +139 -0
  41. package/dist/executer/scheduler/check-for-loop.js +21 -0
  42. package/dist/executer/scheduler/enqueue-next.js +27 -0
  43. package/dist/{testing/test-context.js → executer/scheduler/node-state.js} +1 -1
  44. package/dist/executer/scheduler/scheduler-result.js +3 -0
  45. package/dist/executer/scheduler/scheduler-state.js +3 -0
  46. package/dist/executer/scheduler/service-state.js +3 -0
  47. package/dist/executer/service-dns.js +6 -0
  48. package/dist/executer/set-user-permission.js +16 -0
  49. package/dist/executer/start-node.js +59 -0
  50. package/dist/executer/state-listener.js +3 -0
  51. package/dist/executer/state.js +49 -0
  52. package/dist/executer/states.js +4 -129
  53. package/dist/executer/watch-node.js +57 -0
  54. package/dist/executer/watch-service.js +54 -0
  55. package/dist/executer/work-scope.js +10 -0
  56. package/dist/file/get-file-context-mock.js +1 -0
  57. package/dist/file/get-file-context-mock.spec.js +28 -27
  58. package/dist/file/get-file-context.js +73 -63
  59. package/dist/file/move-files.js +1 -1
  60. package/dist/get-work-context.js +29 -0
  61. package/dist/index.js +11 -10
  62. package/dist/log.js +209 -52
  63. package/dist/logging/grouped-logger.js +31 -19
  64. package/dist/logging/interactive-logger.js +20 -23
  65. package/dist/logging/live-logger.js +7 -17
  66. package/dist/optimizer/calculate-checksum.js +1 -1
  67. package/dist/optimizer/get-cache-directory.js +8 -13
  68. package/dist/optimizer/get-work-node-cache-stats.js +68 -21
  69. package/dist/optimizer/read-work-node-cache.js +2 -2
  70. package/dist/optimizer/work-node-cache-description.js +12 -11
  71. package/dist/optimizer/write-work-node-cache.js +9 -8
  72. package/dist/{executer/execution-context.js → parser/build-file-service.js} +1 -1
  73. package/dist/{optimizer → parser}/cache-method.js +0 -0
  74. package/dist/parser/get-build-file.js +1 -1
  75. package/dist/parser/parse-boolean.js +29 -0
  76. package/dist/parser/parse-boolean.spec.js +48 -0
  77. package/dist/parser/parse-build-file-references.js +2 -2
  78. package/dist/parser/parse-build-file-services.js +58 -0
  79. package/dist/parser/parse-build-file-task-command.js +6 -5
  80. package/dist/parser/parse-build-file-task-source.js +5 -5
  81. package/dist/parser/parse-build-file.js +29 -17
  82. package/dist/parser/parse-context.js +13 -0
  83. package/dist/parser/parse-envs.js +4 -3
  84. package/dist/parser/parse-healthcheck.js +28 -0
  85. package/dist/parser/parse-label-arguments.js +23 -0
  86. package/dist/parser/parse-service-selector.js +39 -0
  87. package/dist/parser/parse-string-array.js +6 -5
  88. package/dist/parser/parse-string-map.js +30 -0
  89. package/dist/parser/parse-string.js +20 -0
  90. package/dist/parser/read-build-file.js +16 -5
  91. package/dist/parser/read-env-file.js +7 -7
  92. package/dist/planner/utils/get-container-mounts.js +24 -0
  93. package/dist/planner/utils/normalize-path.js +17 -0
  94. package/dist/planner/utils/parse-work-node-mount.js +3 -14
  95. package/dist/planner/utils/parse-work-node-mount.spec.js +10 -10
  96. package/dist/planner/utils/parse-work-service-volume.js +21 -0
  97. package/dist/planner/utils/plan-work-command.js +1 -1
  98. package/dist/planner/utils/plan-work-dependency.js +29 -24
  99. package/dist/planner/utils/plan-work-node.js +203 -120
  100. package/dist/planner/utils/plan-work-nodes.js +60 -12
  101. package/dist/planner/utils/plan-work-tree.js +8 -4
  102. package/dist/planner/utils/plan-work-volume.js +25 -0
  103. package/dist/planner/validate.js +56 -8
  104. package/dist/planner/work-context.js +20 -0
  105. package/dist/planner/work-mount.js +3 -0
  106. package/dist/planner/work-node-id.js +4 -4
  107. package/dist/planner/work-node-id.spec.js +11 -8
  108. package/dist/planner/work-node-path.js +0 -1
  109. package/dist/planner/work-node-status.js +121 -18
  110. package/dist/planner/work-node.js +3 -3
  111. package/dist/planner/work-service-id.js +13 -0
  112. package/dist/planner/work-service-volume.js +3 -0
  113. package/dist/planner/work-service.js +6 -0
  114. package/dist/planner/work-services.js +3 -0
  115. package/dist/planner/work-volume.js +3 -0
  116. package/dist/program.js +155 -91
  117. package/dist/program.spec.js +20 -0
  118. package/dist/start-watch-processes.js +28 -0
  119. package/dist/testing/cli.js +73 -0
  120. package/dist/testing/create-build-file.js +1 -1
  121. package/dist/testing/example-test-suite.js +54 -0
  122. package/dist/testing/expect.js +30 -18
  123. package/dist/testing/get-logger.js +23 -0
  124. package/dist/testing/get-node.js +2 -2
  125. package/dist/testing/get-test-context.js +6 -5
  126. package/dist/testing/get-test-suite.js +2 -51
  127. package/dist/testing/integration/cache.spec.js +25 -28
  128. package/dist/testing/integration/cancellation.spec.js +19 -21
  129. package/dist/testing/integration/clean.spec.js +29 -13
  130. package/dist/testing/integration/cmd.spec.js +5 -8
  131. package/dist/testing/integration/concurrency.spec.js +8 -17
  132. package/dist/testing/integration/docker.spec.js +6 -9
  133. package/dist/testing/integration/env.spec.js +27 -34
  134. package/dist/testing/integration/error.spec.js +5 -9
  135. package/dist/testing/integration/extend.spec.js +32 -0
  136. package/dist/testing/integration/glob.spec.js +35 -28
  137. package/dist/testing/integration/include.spec.js +17 -16
  138. package/dist/testing/integration/invalid.spec.js +3 -2
  139. package/dist/testing/integration/invalid_loop.spec.js +13 -0
  140. package/dist/testing/integration/kubernetes.spec.js +15 -0
  141. package/dist/testing/integration/labels.spec.js +47 -0
  142. package/dist/testing/integration/local.spec.js +4 -7
  143. package/dist/testing/integration/monorepo.spec.js +6 -30
  144. package/dist/testing/integration/multi-line.spec.js +4 -4
  145. package/dist/testing/integration/program.spec.js +3 -10
  146. package/dist/testing/integration/reference.spec.js +10 -13
  147. package/dist/testing/integration/services.spec.js +14 -0
  148. package/dist/testing/integration/store.spec.js +42 -35
  149. package/dist/testing/integration/unknown.spec.js +4 -4
  150. package/dist/testing/integration/validate.spec.js +4 -4
  151. package/dist/testing/integration/watch.spec.js +25 -23
  152. package/dist/testing/lazy.js +17 -0
  153. package/dist/testing/start-watch-processes.js +29 -0
  154. package/dist/testing/test-suite-setup.js +3 -0
  155. package/dist/utils/abort-event.js +24 -0
  156. package/dist/utils/abortable-function.js +71 -0
  157. package/dist/utils/debouncer.spec.js +8 -8
  158. package/dist/utils/environment-config.js +13 -0
  159. package/dist/utils/fail-never.js +1 -1
  160. package/dist/utils/sleep.spec.js +3 -3
  161. package/package.json +24 -21
  162. package/dist/console/get-console-context-mock.js +0 -33
  163. package/dist/executer/clean.js +0 -22
  164. package/dist/executer/execute-local.js +0 -58
  165. package/dist/executer/execute.js +0 -95
  166. package/dist/executer/execution-context-event.js +0 -3
  167. package/dist/executer/execution-context-mock.js +0 -3
  168. package/dist/executer/executor-mock.js +0 -39
  169. package/dist/executer/get-environment-mock.js +0 -17
  170. package/dist/executer/get-execution-context-mock.js +0 -19
  171. package/dist/executer/get-local-executor.js +0 -22
  172. package/dist/executer/get-ready-work-nodes.js +0 -15
  173. package/dist/executer/restore.js +0 -22
  174. package/dist/executer/store.js +0 -23
  175. package/dist/logging/get-logger.js +0 -23
  176. package/dist/logging/message-to-console.js +0 -16
  177. package/dist/optimizer/optimize.js +0 -32
  178. package/dist/optimizer/work-node-description.js +0 -12
  179. package/dist/planner/utils/find-build-task.js +0 -18
  180. package/dist/testing/create-work-tree.js +0 -11
  181. package/dist/utils/defer.js +0 -57
  182. package/dist/utils/defer.spec.js +0 -76
@@ -19,7 +19,7 @@ async function moveFiles(node, context, folder) {
19
19
  if (await context.file.exists(folder.to)) {
20
20
  await context.file.remove(folder.to);
21
21
  }
22
- node.status.console.write('internal', 'debug', `copy ${folder.from} to ${folder.to}`);
22
+ context.status.task(node).write('debug', `copy ${folder.from} to ${folder.to}`);
23
23
  await context.file.copy(folder.from, folder.to);
24
24
  }
25
25
  }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWorkScope = void 0;
4
+ const plan_work_tree_1 = require("./planner/utils/plan-work-tree");
5
+ const plan_work_nodes_1 = require("./planner/utils/plan-work-nodes");
6
+ const work_scope_1 = require("./executer/work-scope");
7
+ const replace_env_variables_1 = require("./environment/replace-env-variables");
8
+ const work_service_1 = require("./planner/work-service");
9
+ const work_node_1 = require("./planner/work-node");
10
+ const get_process_env_1 = require("./environment/get-process-env");
11
+ function getWorkScope(buildFile, contextFilter, environment) {
12
+ const tree = (0, work_scope_1.isContextTaskFilter)(contextFilter)
13
+ ? (0, plan_work_tree_1.planWorkTree)(buildFile, { taskName: contextFilter.taskName })
14
+ : (0, plan_work_nodes_1.planWorkNodes)(buildFile, contextFilter);
15
+ for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(tree.nodes)) {
16
+ node.envs = (0, replace_env_variables_1.replaceEnvVariables)(node.envs, environment.processEnvs);
17
+ if (!(0, work_node_1.isContainerWorkNode)(node)) {
18
+ node.envs = (0, get_process_env_1.extendHostVariables)(node.envs, environment);
19
+ }
20
+ }
21
+ for (const service of (0, plan_work_nodes_1.iterateWorkServices)(tree.services)) {
22
+ if ((0, work_service_1.isContainerWorkService)(service)) {
23
+ service.envs = (0, replace_env_variables_1.replaceEnvVariables)(service.envs, environment.processEnvs);
24
+ }
25
+ }
26
+ return tree;
27
+ }
28
+ exports.getWorkScope = getWorkScope;
29
+ //# sourceMappingURL=get-work-context.js.map
package/dist/index.js CHANGED
@@ -4,20 +4,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const program_1 = require("./program");
5
5
  const log_1 = require("./log");
6
6
  const get_file_context_1 = require("./file/get-file-context");
7
- const defer_1 = require("./utils/defer");
8
- const cancelDefer = new defer_1.Defer();
7
+ const work_node_status_1 = require("./planner/work-node-status");
8
+ const execute_docker_1 = require("./executer/execute-docker");
9
+ const abortCtrl = new AbortController();
9
10
  process.on('SIGINT', function () {
10
- if (!cancelDefer.isResolved) {
11
- cancelDefer.resolve();
12
- }
11
+ abortCtrl.abort();
13
12
  });
14
- program_1.getProgram({
13
+ (0, program_1.getProgram)({
15
14
  cwd: process.cwd(),
16
- cancelDefer,
15
+ abortCtrl,
17
16
  processEnvs: process.env,
18
- file: get_file_context_1.getFileContext(),
19
- console: log_1.consoleContext(),
17
+ file: (0, get_file_context_1.getFileContext)(process.cwd()),
18
+ console: (0, log_1.consoleContext)(),
19
+ status: (0, work_node_status_1.statusConsole)(),
20
+ docker: (0, execute_docker_1.getContainerCli)(),
20
21
  }, process.argv).then(({ program, args }) => {
21
- program.parse(args);
22
+ return program.parseAsync(args);
22
23
  });
23
24
  //# sourceMappingURL=index.js.map
package/dist/log.js CHANGED
@@ -3,10 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.showCursor = exports.hideCursor = exports.writeWorkTreeStatus = exports.getNodeName = exports.getNodeNameLength = exports.printWorkTreeResult = exports.isVerbose = exports.consoleContext = exports.getLogLevel = exports.getLogs = void 0;
6
+ exports.showCursor = exports.hideCursor = exports.writeWorkTreeStatus = exports.formatDate = exports.writeNodeLogToConsole = exports.getNodeName = exports.getNodeNameLengthForWorkTree = exports.getNodeNameLength = exports.printTitle = exports.printItem = exports.printProperty = exports.getNodeNameLengthForSchedulerState = exports.printWorkTreeResult = exports.getType = exports.isVerbose = exports.consoleContext = exports.getErrorMessage = exports.getLogLevel = exports.getLogs = void 0;
7
7
  const readline_1 = require("readline");
8
8
  const plan_work_nodes_1 = require("./planner/utils/plan-work-nodes");
9
9
  const colors_1 = __importDefault(require("colors"));
10
+ const fail_never_1 = require("./utils/fail-never");
10
11
  function getLogs(chunk) {
11
12
  return chunk
12
13
  .toString()
@@ -27,44 +28,88 @@ function getLogLevel(level) {
27
28
  }
28
29
  }
29
30
  exports.getLogLevel = getLogLevel;
31
+ function getErrorMessage(e) {
32
+ if (e instanceof Error) {
33
+ return e.message;
34
+ }
35
+ else if (typeof e === 'string') {
36
+ return e;
37
+ }
38
+ else {
39
+ return `unknown error ${e}`;
40
+ }
41
+ }
42
+ exports.getErrorMessage = getErrorMessage;
30
43
  function consoleContext() {
31
44
  return {
32
45
  debug(message) {
33
- process.stdout.write(`${getLogLevel('debug')}: ${message}\n`);
46
+ process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('debug')}: ${message}\n`);
34
47
  },
35
48
  error(message) {
36
- process.stdout.write(`${getLogLevel('error')}: ${message}\n`);
49
+ process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('error')}: ${message}\n`);
37
50
  },
38
51
  info(message) {
39
- process.stdout.write(`${getLogLevel('info')}: ${message}\n`);
52
+ process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('info')}: ${message}\n`);
40
53
  },
41
54
  warn(message) {
42
- process.stdout.write(`${getLogLevel('warn')}: ${message}\n`);
55
+ process.stdout.write(`${formatDate(new Date())} ${getType('cli')} ${getLogLevel('warn')}: ${message}\n`);
43
56
  },
44
57
  };
45
58
  }
46
59
  exports.consoleContext = consoleContext;
47
60
  exports.isVerbose = process.argv.some((a) => a === '--verbose');
48
- async function printWorkTreeResult(workTree, result, logConsoleOnFail) {
49
- const maxNodeNameLength = getNodeNameLength(workTree);
50
- if (logConsoleOnFail && (!result.success || exports.isVerbose)) {
51
- for (const node of plan_work_nodes_1.iterateWorkNodes(workTree.nodes)) {
52
- if (node.status.state.type === 'failed' || exports.isVerbose) {
53
- const logs = await node.status.console.read();
54
- for (const log of logs) {
55
- if (log.level === 'debug' && !exports.isVerbose) {
56
- continue;
57
- }
58
- process.stdout.write(`${colors_1.default.grey('task:')} ${getNodeName(node, maxNodeNameLength)} ${getLogLevel(log.level)}: ${log.message}\n`);
59
- }
60
- process.stdout.write('-----------------\n');
61
+ const typeLength = ['service', 'task', 'cli']
62
+ .map((s) => s.length)
63
+ .reduce((max, current) => (max > current ? max : current), 0);
64
+ function getType(type) {
65
+ return colors_1.default.grey(getNodeName(type, typeLength) + ':');
66
+ }
67
+ exports.getType = getType;
68
+ async function printWorkTreeResult(schedulerState, env) {
69
+ const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
70
+ for (const log of env.status.read()) {
71
+ if (exports.isVerbose || (log.type === 'status' && log.level === 'error')) {
72
+ process.stdout.write(`${formatDate(log.date)} ${getType(log.context.type)} ${getNodeName(log.context.name, maxNodeNameLength)} - ${colors_1.default.white(log.message)}\n`);
73
+ }
74
+ }
75
+ for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
76
+ if (state.type === 'end' && state.reason === 'crash') {
77
+ const message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)}`;
78
+ for (const log of env.status.service(state.service).logs()) {
79
+ process.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
80
+ }
81
+ }
82
+ }
83
+ for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
84
+ if (state.type === 'error' || state.type === 'crash') {
85
+ const message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)}`;
86
+ for (const log of env.status.task(state.node).logs()) {
87
+ process.stdout.write(`${formatDate(log.date)} ${message} - ${log.console}: ${log.message}\n`);
88
+ }
89
+ }
90
+ }
91
+ for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
92
+ let message = `${formatDate(new Date())} ${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)} - ${getStateText(state)}`;
93
+ if (state.type === 'end') {
94
+ if (state.reason === 'crash') {
95
+ message += ` crashed`;
61
96
  }
97
+ process.stdout.write(`${message}\n`);
62
98
  }
63
99
  }
64
- for (const node of plan_work_nodes_1.iterateWorkNodes(workTree.nodes)) {
65
- let message = `${colors_1.default.grey('task:')} ${getNodeName(node, maxNodeNameLength)} - ${getStateText(node.status.state)}`;
66
- if (node.status.state.type === 'completed') {
67
- message += ` in ${node.status.state.duration}ms`;
100
+ for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
101
+ let message = `${formatDate(new Date())} ${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
102
+ if (state.type === 'completed') {
103
+ message += ` in ${state.duration}ms`;
104
+ if (state.cached) {
105
+ message += ' [CACHED]';
106
+ }
107
+ }
108
+ if (state.type === 'crash') {
109
+ message += ` exited with ${state.exitCode}`;
110
+ }
111
+ if (state.type === 'error') {
112
+ message += ` with message ${state.errorMessage}`;
68
113
  }
69
114
  process.stdout.write(`${message}\n`);
70
115
  }
@@ -75,66 +120,178 @@ function getStateText(state) {
75
120
  if (state.type === 'running') {
76
121
  return colors_1.default.blue(state.type);
77
122
  }
78
- else if (state.type === 'pending') {
123
+ else if (state.type === 'pending' || state.type === 'starting') {
79
124
  return colors_1.default.yellow(state.type);
80
125
  }
81
126
  else if (state.type === 'completed') {
82
127
  return colors_1.default.green(state.type);
83
128
  }
84
- else if (state.type === 'failed') {
129
+ else if (state.type === 'crash') {
85
130
  return colors_1.default.red(state.type);
86
131
  }
87
- else if (state.type === 'aborted') {
132
+ else if (state.type === 'error') {
88
133
  return colors_1.default.red(state.type);
89
134
  }
90
- else if (state.type === 'cancel') {
135
+ else if (state.type === 'end') {
91
136
  return colors_1.default.bgRed(state.type);
92
137
  }
138
+ else if (state.type === 'canceled') {
139
+ return colors_1.default.bgRed(state.type);
140
+ }
141
+ else if (state.type === 'ready') {
142
+ return colors_1.default.blue(state.type);
143
+ }
93
144
  else {
94
- //TODO fail never
95
- return '';
145
+ (0, fail_never_1.failNever)(state, 'unknown node state');
146
+ }
147
+ }
148
+ function getNodeNameLengthForSchedulerState(schedulerState) {
149
+ function* Names() {
150
+ for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
151
+ yield node.node.name;
152
+ }
153
+ for (const service of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
154
+ yield service.service.name;
155
+ }
96
156
  }
157
+ return getNodeNameLength(Names);
158
+ }
159
+ exports.getNodeNameLengthForSchedulerState = getNodeNameLengthForSchedulerState;
160
+ function printProperty(name, value) {
161
+ process.stdout.write(` ${colors_1.default.grey(`${name}:`)} ${value}\n`);
97
162
  }
98
- function getNodeNameLength(workTree) {
163
+ exports.printProperty = printProperty;
164
+ function printItem(item) {
165
+ process.stdout.write(`• ${item.name}${item.description ? `: ${colors_1.default.white(item.description)}` : ''}\n`);
166
+ }
167
+ exports.printItem = printItem;
168
+ function printTitle(name) {
169
+ process.stdout.write(`${colors_1.default.bgWhite(name + ':\n')}`);
170
+ }
171
+ exports.printTitle = printTitle;
172
+ function getNodeNameLength(names) {
99
173
  let maxNodeNameLength = 0;
100
- for (const node of plan_work_nodes_1.iterateWorkNodes(workTree.nodes)) {
101
- if (node.name.length > maxNodeNameLength) {
102
- maxNodeNameLength = node.name.length;
174
+ for (const name of names()) {
175
+ if (name.length > maxNodeNameLength) {
176
+ maxNodeNameLength = name.length;
103
177
  }
104
178
  }
105
179
  return maxNodeNameLength;
106
180
  }
107
181
  exports.getNodeNameLength = getNodeNameLength;
108
- function getNodeName(node, maxNodeNameLength) {
109
- return colors_1.default.white(node.name) + ' '.repeat(maxNodeNameLength - node.name.length);
182
+ function getNodeNameLengthForWorkTree(nodes, services) {
183
+ function* Names() {
184
+ for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(nodes)) {
185
+ yield node.node.name;
186
+ }
187
+ for (const service of (0, plan_work_nodes_1.iterateWorkServices)(services)) {
188
+ yield service.service.name;
189
+ }
190
+ }
191
+ return getNodeNameLength(Names);
192
+ }
193
+ exports.getNodeNameLengthForWorkTree = getNodeNameLengthForWorkTree;
194
+ function getNodeName(name, maxNodeNameLength) {
195
+ return colors_1.default.white(name) + ' '.repeat(Math.max(0, maxNodeNameLength - name.length));
110
196
  }
111
197
  exports.getNodeName = getNodeName;
112
- function writeWorkTreeStatus(workTree, ticker) {
113
- readline_1.clearScreenDown(process.stdout);
114
- const maxNodeNameLength = getNodeNameLength(workTree);
198
+ function writeNodeLogToConsole(log, maxNodeNameLength) {
199
+ const content = log.type === 'console'
200
+ ? log.console === 'stdout'
201
+ ? colors_1.default.white(log.message)
202
+ : colors_1.default.red(log.message)
203
+ : `${getLogLevel(log.level)} - ${log.message}`;
204
+ process.stdout.write(`${formatDate(log.date)} ${colors_1.default.grey(log.context.type + ':')} ${getNodeName(log.context.name, maxNodeNameLength)} - ${log.date.toLocaleTimeString()} - ${content}\n`);
205
+ }
206
+ exports.writeNodeLogToConsole = writeNodeLogToConsole;
207
+ function formatDate(date) {
208
+ return colors_1.default.grey(`[${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
209
+ .getDay()
210
+ .toString()
211
+ .padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date
212
+ .getMinutes()
213
+ .toString()
214
+ .padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}.${date
215
+ .getMilliseconds()
216
+ .toString()
217
+ .padStart(3, '0')}]`);
218
+ }
219
+ exports.formatDate = formatDate;
220
+ function writeWorkTreeStatus(schedulerState, env, ticker) {
221
+ (0, readline_1.clearScreenDown)(process.stdout);
222
+ const maxNodeNameLength = getNodeNameLengthForSchedulerState(schedulerState);
115
223
  let count = 0;
116
- for (const node of plan_work_nodes_1.iterateWorkNodes(workTree.nodes)) {
117
- const completedDepCount = Object.keys(node.status.completedDependencies).length;
118
- const totalDepCount = completedDepCount + Object.keys(node.status.pendingDependencies).length;
119
- let message = `${colors_1.default.grey('task:')} ${getNodeName(node, maxNodeNameLength)} - ${getStateText(node.status.state)}`;
120
- if (totalDepCount > 0 && completedDepCount !== totalDepCount) {
121
- message += ` | ${colors_1.default.grey(` awaiting dependencies (${completedDepCount}/${totalDepCount})`)}`;
122
- }
123
- if (node.status.state.type === 'running') {
224
+ for (const state of (0, plan_work_nodes_1.iterateWorkServices)(schedulerState.service)) {
225
+ let message = `${getType('service')} ${getNodeName(state.service.name, maxNodeNameLength)} - ${getStateText(state)}`;
226
+ const currentMessage = env.status.service(state.service).current();
227
+ if (currentMessage) {
228
+ message += ` ${currentMessage.message}`;
229
+ }
230
+ count += printWithTruncate(message);
231
+ }
232
+ for (const state of (0, plan_work_nodes_1.iterateWorkNodes)(schedulerState.node)) {
233
+ let message = `${getType('task')} ${getNodeName(state.node.name, maxNodeNameLength)} - ${getStateText(state)}`;
234
+ if (state.type === 'pending') {
235
+ const totalDepCount = state.node.deps.length;
236
+ const totalServiceCount = state.node.needs.length;
237
+ const completedDepCount = state.node.deps.filter((d) => schedulerState.node[d.id]?.type === 'completed').length;
238
+ const runningServiceCount = state.node.needs.filter((n) => schedulerState.service[n.id]?.type === 'ready').length;
239
+ if (totalDepCount > 0 && completedDepCount !== totalDepCount) {
240
+ message += ` | ${colors_1.default.grey(` awaiting dependencies (${completedDepCount}/${totalDepCount})`)}`;
241
+ }
242
+ if (totalServiceCount > 0 && runningServiceCount !== totalServiceCount) {
243
+ message += ` | ${colors_1.default.grey(` awaiting service (${runningServiceCount}/${totalServiceCount})`)}`;
244
+ }
245
+ }
246
+ if (state.type === 'starting' || state.type === 'ready') {
124
247
  message += ` | ${spinner[ticker % spinner.length]}`;
125
- if (node.status.console.current) {
126
- message += ` ${node.status.console.current.message}`;
248
+ const currentMessage = env.status.task(state.node).current();
249
+ if (currentMessage) {
250
+ message += ` ${currentMessage.message}`;
127
251
  }
128
252
  }
129
- else if (node.status.state.type === 'completed') {
130
- message += ` in ${node.status.state.duration}ms`;
253
+ else if (state.type === 'running') {
254
+ message += ` | ${spinner[ticker % spinner.length]}`;
255
+ const currentMessage = env.status.task(state.node).currentLog();
256
+ if (currentMessage) {
257
+ message += ` ${currentMessage.message}`;
258
+ }
131
259
  }
132
- process.stdout.write(`${message}\n`);
133
- count++;
260
+ else if (state.type === 'completed') {
261
+ message += ` in ${state.duration}ms`;
262
+ if (state.cached) {
263
+ message += ' [CACHED]';
264
+ }
265
+ }
266
+ else if (state.type === 'error') {
267
+ message += ` ${state.errorMessage}`;
268
+ }
269
+ count += printWithTruncate(message);
134
270
  }
135
- readline_1.moveCursor(process.stdout, 0, -1 * count);
271
+ (0, readline_1.moveCursor)(process.stdout, 0, -1 * count);
136
272
  }
137
273
  exports.writeWorkTreeStatus = writeWorkTreeStatus;
274
+ function countChar(message, char) {
275
+ let result = 0;
276
+ for (let i = 0; i < message.length; i++) {
277
+ if (message[i] === char) {
278
+ result++;
279
+ }
280
+ }
281
+ return result;
282
+ }
283
+ function printWithTruncate(message) {
284
+ let lineCount = 0;
285
+ let index = 0;
286
+ do {
287
+ const newLineCount = countChar(message, '\n');
288
+ process.stdout.write(`${message.substr(index, process.stdout.columns)}\n`);
289
+ index += process.stdout.columns;
290
+ lineCount++;
291
+ lineCount += newLineCount;
292
+ } while (index < message.length);
293
+ return lineCount;
294
+ }
138
295
  function hideCursor() {
139
296
  process.stdout.write('\x1B[?25l');
140
297
  }
@@ -2,26 +2,38 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.groupedLogger = void 0;
4
4
  const log_1 = require("../log");
5
- const message_to_console_1 = require("./message-to-console");
6
- function groupedLogger() {
7
- let maxNodeNameLength = 0;
8
- return {
9
- start(executionContext, workTree) {
10
- maxNodeNameLength = log_1.getNodeNameLength(workTree);
11
- executionContext.events.on(async (evt) => {
12
- if (evt.newState.type === 'completed' || evt.newState.type === 'failed' || evt.newState.type === 'aborted') {
13
- const node = workTree.nodes[evt.nodeId];
14
- for (const log of await node.status.console.read()) {
15
- message_to_console_1.logMessageToConsole(node, log, maxNodeNameLength);
16
- }
5
+ const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
6
+ function groupedLogger(state, env) {
7
+ const maxNodeNameLength = (0, log_1.getNodeNameLengthForWorkTree)(state.current.node, state.current.service);
8
+ const completedNodes = [];
9
+ const completedServices = [];
10
+ state.on((currentState) => {
11
+ for (const node of (0, plan_work_nodes_1.iterateWorkNodes)(currentState.node)) {
12
+ if (completedNodes.indexOf(node.node.id) >= 0) {
13
+ continue;
14
+ }
15
+ if (node.type === 'crash' || node.type === 'error' || node.type === 'completed') {
16
+ completedNodes.push(node.node.id);
17
+ for (const log of env.status.task(node.node).read()) {
18
+ (0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
17
19
  }
18
- });
19
- },
20
- async finish(workTree, result) {
21
- await log_1.printWorkTreeResult(workTree, result, false);
22
- },
23
- abort(e) {
24
- process.stderr.write(`${e.message}\n`);
20
+ }
21
+ }
22
+ for (const service of (0, plan_work_nodes_1.iterateWorkServices)(currentState.service)) {
23
+ if (completedServices.indexOf(service.service.id) >= 0) {
24
+ continue;
25
+ }
26
+ if (service.type === 'end') {
27
+ completedServices.push(service.service.id);
28
+ for (const log of env.status.service(service.service).read()) {
29
+ (0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
30
+ }
31
+ }
32
+ }
33
+ });
34
+ return {
35
+ async complete(evt, env) {
36
+ await (0, log_1.printWorkTreeResult)(evt.state, env);
25
37
  },
26
38
  };
27
39
  }
@@ -3,33 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.interactiveLogger = void 0;
4
4
  const log_1 = require("../log");
5
5
  const readline_1 = require("readline");
6
- function interactiveLogger() {
6
+ function interactiveLogger(state, env) {
7
7
  let running = true;
8
8
  let count = 0;
9
+ const tickerFn = () => {
10
+ if (!running) {
11
+ return;
12
+ }
13
+ count++;
14
+ (0, log_1.writeWorkTreeStatus)(state.current, env, count);
15
+ if (running) {
16
+ setTimeout(tickerFn, 100);
17
+ }
18
+ };
19
+ (0, log_1.hideCursor)();
20
+ tickerFn();
21
+ state.on((currentState) => {
22
+ (0, log_1.writeWorkTreeStatus)(currentState, env, count);
23
+ });
9
24
  return {
10
- start(executionContext, workTree) {
11
- log_1.hideCursor();
12
- log_1.writeWorkTreeStatus(workTree, count);
13
- const tickerFn = () => {
14
- count++;
15
- log_1.writeWorkTreeStatus(workTree, count);
16
- if (running) {
17
- setTimeout(tickerFn, 100);
18
- }
19
- };
20
- tickerFn();
21
- executionContext.events.on(({ workTree }) => {
22
- log_1.writeWorkTreeStatus(workTree, count);
23
- });
24
- },
25
- async finish(workTree, result) {
25
+ async complete(evt, env) {
26
26
  running = false;
27
- readline_1.clearScreenDown(process.stdout);
28
- await log_1.printWorkTreeResult(workTree, result, true);
29
- log_1.showCursor();
30
- },
31
- abort(e) {
32
- process.stderr.write(`${e.message}\n`);
27
+ (0, readline_1.clearScreenDown)(process.stdout);
28
+ await (0, log_1.printWorkTreeResult)(evt.state, env);
29
+ (0, log_1.showCursor)();
33
30
  },
34
31
  };
35
32
  }
@@ -2,24 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.liveLogger = void 0;
4
4
  const log_1 = require("../log");
5
- const plan_work_nodes_1 = require("../planner/utils/plan-work-nodes");
6
- const message_to_console_1 = require("./message-to-console");
7
- function liveLogger() {
8
- let maxNodeNameLength = 0;
5
+ function liveLogger(state, env) {
6
+ const maxNodeNameLength = (0, log_1.getNodeNameLengthForWorkTree)(state.current.node, state.current.service);
7
+ env.status.on((log) => {
8
+ (0, log_1.writeNodeLogToConsole)(log, maxNodeNameLength);
9
+ });
9
10
  return {
10
- start(executionContext, workTree) {
11
- maxNodeNameLength = log_1.getNodeNameLength(workTree);
12
- for (const node of plan_work_nodes_1.iterateWorkNodes(workTree.nodes)) {
13
- node.status.console.on((log) => {
14
- message_to_console_1.logMessageToConsole(node, log, maxNodeNameLength);
15
- });
16
- }
17
- },
18
- async finish(workTree, result) {
19
- await log_1.printWorkTreeResult(workTree, result, false);
20
- },
21
- abort(e) {
22
- process.stderr.write(`${e.message}\n`);
11
+ async complete(evt, env) {
12
+ await (0, log_1.printWorkTreeResult)(evt.state, env);
23
13
  },
24
14
  };
25
15
  }
@@ -4,7 +4,7 @@ exports.calculateChecksum = void 0;
4
4
  const crypto_1 = require("crypto");
5
5
  async function calculateChecksum(environment, path) {
6
6
  const input = await environment.file.read(path);
7
- return crypto_1.createHash('sha1').update(input).digest('hex');
7
+ return (0, crypto_1.createHash)('sha1').update(input).digest('hex');
8
8
  }
9
9
  exports.calculateChecksum = calculateChecksum;
10
10
  //# sourceMappingURL=calculate-checksum.js.map
@@ -1,33 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getHammerkitDirectory = exports.getCacheStatsFile = exports.getCacheStatsDirectory = exports.getCacheDescriptionFile = exports.getCacheDirectory = void 0;
3
+ exports.getHammerkitDirectory = exports.getCacheStatsFile = exports.getCacheDescriptionFile = exports.getCacheDirectory = void 0;
4
4
  const path_1 = require("path");
5
- const crypto_1 = require("crypto");
6
5
  function getCacheDirectory(nodeId) {
7
- return path_1.join(getHammerkitDirectory(), 'cache', nodeId);
6
+ return (0, path_1.join)(getHammerkitDirectory(), 'cache', nodeId);
8
7
  }
9
8
  exports.getCacheDirectory = getCacheDirectory;
10
9
  function getCacheDescriptionFile(nodeId) {
11
- return path_1.join(getCacheDirectory(nodeId), 'description.json');
10
+ return (0, path_1.join)(getCacheDirectory(nodeId), 'description.json');
12
11
  }
13
12
  exports.getCacheDescriptionFile = getCacheDescriptionFile;
14
- function getCacheStatsDirectory(nodeId, cwd) {
15
- return path_1.join(getCacheDirectory(nodeId), crypto_1.createHash('sha1').update(cwd).digest('hex'));
16
- }
17
- exports.getCacheStatsDirectory = getCacheStatsDirectory;
18
- function getCacheStatsFile(nodeId, cwd) {
19
- return path_1.join(getCacheStatsDirectory(nodeId, cwd), 'stats.json');
13
+ function getCacheStatsFile(nodeId) {
14
+ return (0, path_1.join)(getCacheDirectory(nodeId), 'stats.json');
20
15
  }
21
16
  exports.getCacheStatsFile = getCacheStatsFile;
22
17
  function getHammerkitDirectory() {
23
18
  if (process.platform === 'win32') {
24
- return path_1.join(process.env.APPDATA, 'hammerkit');
19
+ return (0, path_1.join)(process.env.APPDATA, 'hammerkit');
25
20
  }
26
21
  else if (process.platform === 'darwin') {
27
- return path_1.join(process.env.HOME, 'Library', 'Application Support', 'hammerkit');
22
+ return (0, path_1.join)(process.env.HOME, 'Library', 'Application Support', 'hammerkit');
28
23
  }
29
24
  else {
30
- return path_1.join(process.env.HOME, '.hammerkit');
25
+ return (0, path_1.join)(process.env.HOME, '.hammerkit');
31
26
  }
32
27
  }
33
28
  exports.getHammerkitDirectory = getHammerkitDirectory;