task-script-support-cli 0.2.11 → 0.2.13

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 (32) hide show
  1. package/assets/yargs-template/task-runner/README.md +67 -0
  2. package/assets/yargs-template/task-runner/package-lock.json +3 -3
  3. package/assets/yargs-template/task-runner/package.json +3 -1
  4. package/assets/yargs-template/task-runner/src/commands/help-command.ts +8 -0
  5. package/assets/yargs-template/task-runner/src/index.ts +8 -1
  6. package/assets/yargs-template/task-runner/src/services/log-service.ts +8 -0
  7. package/assets/yargs-template/task-runner/src/services/util-service.ts +49 -0
  8. package/assets/yargs-template/task-runner/src/tasks/check-env.ts +24 -13
  9. package/assets/yargs-template/task-runner/src/tasks/show-help.ts +19 -0
  10. package/assets/yargs-template/task-runner/src/types/state.ts +3 -0
  11. package/assets/yargs-template/task-runner/src/wrappers/app-task.ts +5 -0
  12. package/assets/yargs-template/task-runner/tests/tasks/check-env.test.ts +56 -9
  13. package/dist/assets/yargs-template/task-runner/README.md +67 -0
  14. package/dist/assets/yargs-template/task-runner/package-lock.json +3 -3
  15. package/dist/assets/yargs-template/task-runner/package.json +3 -1
  16. package/dist/assets/yargs-template/task-runner/src/commands/help-command.ts +8 -0
  17. package/dist/assets/yargs-template/task-runner/src/index.ts +8 -1
  18. package/dist/assets/yargs-template/task-runner/src/services/log-service.ts +8 -0
  19. package/dist/assets/yargs-template/task-runner/src/services/util-service.ts +49 -0
  20. package/dist/assets/yargs-template/task-runner/src/tasks/check-env.ts +24 -13
  21. package/dist/assets/yargs-template/task-runner/src/tasks/show-help.ts +19 -0
  22. package/dist/assets/yargs-template/task-runner/src/types/state.ts +3 -0
  23. package/dist/assets/yargs-template/task-runner/src/wrappers/app-task.ts +5 -0
  24. package/dist/assets/yargs-template/task-runner/tests/tasks/check-env.test.ts +56 -9
  25. package/dist/package.json +1 -1
  26. package/dist/src/services/templater-service.d.ts.map +1 -1
  27. package/dist/src/services/templater-service.js +2 -0
  28. package/dist/src/services/templater-service.js.map +1 -1
  29. package/dist/src/tasks/stdout/print-generated-results.js +1 -1
  30. package/package.json +1 -1
  31. package/src/services/templater-service.ts +2 -0
  32. package/src/tasks/stdout/print-generated-results.ts +1 -1
@@ -0,0 +1,67 @@
1
+ ## task-runner
2
+
3
+ To get started, first run `npm install`, then:
4
+
5
+ ```
6
+ npm start
7
+ ```
8
+
9
+ ### Building the project
10
+
11
+ To build the project, run:
12
+
13
+ ```bash
14
+ npm run build
15
+ ```
16
+
17
+ or automatically run the build on file changes:
18
+
19
+ ```bash
20
+ npm run watch
21
+ ```
22
+
23
+ A build will compile the TypeScript code and output to a `dist` directory.
24
+
25
+ ### Linting
26
+
27
+ To lint the code, run:
28
+
29
+ ```bash
30
+ npm run lint
31
+ ```
32
+
33
+ ### Formatting
34
+
35
+ To format the code using Prettier, run:
36
+
37
+ ```bash
38
+ npm run format
39
+ ```
40
+
41
+ or automatically run formatting on file changes:
42
+
43
+ ```bash
44
+ npm run format-watch
45
+ ```
46
+
47
+ ### Clean
48
+
49
+ To clean up the project (delete dist folder):
50
+
51
+ ```bash
52
+ npm run clean
53
+ ```
54
+
55
+ ### Test
56
+
57
+ Run the tests:
58
+
59
+ ```
60
+ npm run test
61
+ ```
62
+
63
+ or automatically run them on file changes:
64
+
65
+ ```
66
+ npm run test-watch
67
+ ```
@@ -2838,9 +2838,9 @@
2838
2838
  }
2839
2839
  },
2840
2840
  "node_modules/task-script-support": {
2841
- "version": "2.3.0",
2842
- "resolved": "https://registry.npmjs.org/task-script-support/-/task-script-support-2.3.0.tgz",
2843
- "integrity": "sha512-6CpSaK6s4VIvT8UqrHLzhwlHxA/cGY475budPsWSbLLOXqLLyA7Slys1WsowtiumAjGYWz6LDC83O+LDrGkIzQ==",
2841
+ "version": "2.3.2",
2842
+ "resolved": "https://registry.npmjs.org/task-script-support/-/task-script-support-2.3.2.tgz",
2843
+ "integrity": "sha512-7q9xmr76iESQun1d/73TOnlacnRJTaV0D+XdcGcILT9AjkdCZXg8F45f6VbFJ9f26gBITe6+MLIe9mhJr2ooQw==",
2844
2844
  "license": "MIT",
2845
2845
  "dependencies": {
2846
2846
  "immutable": "^5.1.4",
@@ -12,8 +12,10 @@
12
12
  "format": "prettier --write ./",
13
13
  "format-check": "prettier --check .",
14
14
  "hooks-one-time-setup": "npx simple-git-hooks",
15
- "prettier-watch": "onchange \"**/*\" -- prettier --write --ignore-unknown {{changed}}",
15
+ "format-watch": "onchange \"**/*\" -- prettier --write --ignore-unknown {{changed}}",
16
16
  "build": "rm -rf ./dist && npx tsc && node dist/src/index.js -v",
17
+ "docker-build": "docker build -t local/task-runner:latest .",
18
+ "docker-run": "docker run --rm -it local/task-runner:latest",
17
19
  "test": "vitest run",
18
20
  "test-watch": "vitest"
19
21
  },
@@ -0,0 +1,8 @@
1
+ import { singleton } from "tsyringe";
2
+ import { Command } from "../wrappers/command";
3
+ import ShowHelp from "../tasks/show-help";
4
+
5
+ @singleton()
6
+ export class HelpCommand extends Command {
7
+ tasks = [ShowHelp];
8
+ }
@@ -12,11 +12,18 @@ initializeInjectables();
12
12
 
13
13
  import { UtilService } from "./services/util-service";
14
14
  import { VerifyCommand } from "./commands/verify";
15
+ import { HelpCommand } from "./commands/help-command";
15
16
 
16
17
  const name = UtilService.getAppName();
18
+ const yargsInstance = yargs(hideBin(process.argv));
19
+ container.registerInstance("yargs", yargsInstance);
17
20
 
18
- yargs(hideBin(process.argv))
21
+ yargsInstance
19
22
  .usage(`${UtilService.titleizeAll(name)} CLI Client`)
23
+ .command({
24
+ command: "$0",
25
+ handler: container.resolve(HelpCommand).handler,
26
+ })
20
27
  .command(
21
28
  "verify",
22
29
  "check the app is working",
@@ -17,6 +17,14 @@ export class LogService {
17
17
  }
18
18
  }
19
19
 
20
+ flush(): Promise<void> {
21
+ return new Promise((res, rej) => {
22
+ this.logger.flush((err?: Error) => {
23
+ return err ? rej(err) : res();
24
+ });
25
+ });
26
+ }
27
+
20
28
  setPrefix(prefix: string) {
21
29
  if (!LogService.ParentInstance) {
22
30
  this.logger = this.pinoLogger.getLogger(prefix);
@@ -5,6 +5,12 @@ import pkgJson from "../../package.json";
5
5
  export class UtilService {
6
6
  static TITLEIZE_TEXT_BREAKPONT: RegExp = /[. _-]/g;
7
7
 
8
+ /**
9
+ * Convert a string to title case.
10
+ *
11
+ * @param s the string to titleize
12
+ * @returns the titleized string.
13
+ */
8
14
  static titleize = (s: string) =>
9
15
  s ? `${s[0]?.toUpperCase()}${s.slice(1, s.length)}` : s;
10
16
  titleize = (s: string) => UtilService.titleize(s);
@@ -17,6 +23,9 @@ export class UtilService {
17
23
  .map(UtilService.titleize)
18
24
  .join(" ");
19
25
 
26
+ /**
27
+ * Get App information.
28
+ */
20
29
  static getAppName = () => pkgJson.name;
21
30
  getAppName = () => pkgJson.name;
22
31
 
@@ -25,4 +34,44 @@ export class UtilService {
25
34
 
26
35
  static getAppDescription = () => pkgJson.description;
27
36
  getAppDescription = () => pkgJson.description;
37
+
38
+ /**
39
+ * Mask a secret or sensitive value.
40
+ *
41
+ * @param value the string value to mask
42
+ * @returns the masked string
43
+ */
44
+ static maskValue = (value: string) => {
45
+ const maskChar = "*";
46
+ let endReveal = 2;
47
+ const longLength = 64;
48
+ const midLength = 8;
49
+ const shortLength = 4;
50
+ const tooSmallLength = 2;
51
+
52
+ // mask the whole thing
53
+ if (!value || value.length <= tooSmallLength) {
54
+ return maskChar.repeat((value || "").length);
55
+ }
56
+
57
+ // mask all but last char
58
+ if (value.length <= shortLength) {
59
+ return `${maskChar.repeat(value.length - 1)}${value.slice(-1)}`;
60
+ }
61
+
62
+ // reveal less on shorter strings
63
+ if (value.length <= midLength) {
64
+ endReveal = 1;
65
+ }
66
+
67
+ // reveal more on longer strings
68
+ if (value.length >= longLength) {
69
+ endReveal = 3;
70
+ }
71
+
72
+ const end = value.length - endReveal;
73
+ const start = endReveal;
74
+ return `${value.slice(0, start)}${maskChar.repeat(end - start)}${value.slice(end)}`;
75
+ };
76
+ maskValue = (v: string) => UtilService.maskValue(v);
28
77
  }
@@ -2,6 +2,7 @@ import chalk from "chalk";
2
2
  import { AppTask } from "../wrappers/app-task";
3
3
  import { autoInjectable } from "tsyringe";
4
4
  import { EnvironmentConfigKeys } from "../types/state";
5
+ import { UtilService } from "../services/util-service";
5
6
 
6
7
  /**
7
8
  * Checks the environment configuration
@@ -10,26 +11,36 @@ import { EnvironmentConfigKeys } from "../types/state";
10
11
  export default class CheckEnv extends AppTask {
11
12
  loggerName = "Check Environment";
12
13
 
14
+ requiredEnv: string[] = [];
15
+ secretEnv: Set<string> = new Set([
16
+ // add keys that should be masked in log output here
17
+ ]);
18
+ optionalEnv = [
19
+ EnvironmentConfigKeys.NODE_ENV,
20
+ EnvironmentConfigKeys.PINO_LOG_TARGET,
21
+ EnvironmentConfigKeys.PINO_LOG_DIR_PATH,
22
+ EnvironmentConfigKeys.PINO_LOG_FILENAME,
23
+ EnvironmentConfigKeys.PINO_LOG_LEVEL,
24
+ ];
25
+
13
26
  async run() {
14
- this.logger.info(chalk.blueBright("Running Check Environment"));
27
+ this.logger.debug(chalk.blueBright("Running Check Environment"));
15
28
 
16
29
  const errorMessages: string[] = [];
17
- const requiredEnv: string[] = [];
18
- const optionalEnv = [
19
- EnvironmentConfigKeys.NODE_ENV,
20
- EnvironmentConfigKeys.PINO_LOG_TARGET,
21
- EnvironmentConfigKeys.PINO_LOG_DIR_PATH,
22
- EnvironmentConfigKeys.PINO_LOG_FILENAME,
23
- EnvironmentConfigKeys.PINO_LOG_LEVEL,
24
- ];
25
-
26
- [...optionalEnv, ...requiredEnv]
30
+
31
+ [...this.optionalEnv, ...this.requiredEnv]
27
32
  .filter((e) => !!process.env[e])
28
33
  .forEach((e) => {
29
- this.logger.info(`Read value for ${e}: ${process.env[e]}`);
34
+ let envVal = process.env[e] || "";
35
+ if (this.secretEnv.has(e)) {
36
+ envVal = UtilService.maskValue(envVal);
37
+ }
38
+ this.logger.debug(
39
+ `Read value for ${e}: ${chalk.magentaBright(envVal)}`,
40
+ );
30
41
  });
31
42
 
32
- requiredEnv
43
+ this.requiredEnv
33
44
  .filter((e) => !process.env[e])
34
45
  .forEach((e) =>
35
46
  errorMessages.push(`Missing required environment variable ${e}`),
@@ -0,0 +1,19 @@
1
+ import { AppTask } from "../wrappers/app-task";
2
+ import { autoInjectable, inject } from "tsyringe";
3
+ import type { Yargs } from "../types/state";
4
+
5
+ /**
6
+ * Show the yargs help menu
7
+ */
8
+ @autoInjectable()
9
+ export default class ShowHelp extends AppTask {
10
+ loggerName = "ShowHelp";
11
+
12
+ constructor(@inject("yargs") private yargs: Yargs) {
13
+ super();
14
+ }
15
+
16
+ async run() {
17
+ this.yargs.showHelp();
18
+ }
19
+ }
@@ -1,4 +1,5 @@
1
1
  import { AppState as State, TaskClass } from "task-script-support";
2
+ import yargs from "yargs";
2
3
 
3
4
  // Add app data here as needed. Use readonly for immutable fields.
4
5
  //
@@ -31,3 +32,5 @@ export const EnvironmentConfigKeys = {
31
32
  };
32
33
 
33
34
  export type AppTaskClass = TaskClass<AppStateData, CLIArgs>;
35
+
36
+ export type Yargs = typeof yargs;
@@ -35,6 +35,11 @@ export class AppTask extends Task<AppStateData, CLIArgs> {
35
35
  throw new Error(`run not implemented (${state.id})`);
36
36
  }
37
37
 
38
+ //@override
39
+ async postRun() {
40
+ await this.logger.flush();
41
+ }
42
+
38
43
  setData(data: Partial<AppStateData>) {
39
44
  this.state = this._commandService!.setData(this.state, data);
40
45
  return this.state;
@@ -1,30 +1,77 @@
1
- import { describe, it, expect, vi } from "vitest";
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
2
  import CheckEnv from "../../src/tasks/check-env";
3
3
  import { LogService } from "../../src/services/log-service";
4
4
  import { CommandService } from "task-script-support";
5
5
  import { AppStateData, CLIArgs } from "../../src/types/state";
6
+ import { container } from "tsyringe";
6
7
 
7
8
  describe("CheckEnv", () => {
8
- it("should set environmentValidated to true", async () => {
9
- const mockLogService = {
9
+ let mockLogService = {} as LogService;
10
+ let mockCommandService = {} as CommandService<AppStateData, CLIArgs>;
11
+
12
+ beforeEach(() => {
13
+ container.reset();
14
+
15
+ mockLogService = {
10
16
  info: vi.fn(),
11
17
  debug: vi.fn(),
18
+ error: vi.fn(),
12
19
  } as unknown as LogService;
13
- const mockCommandService = {
20
+
21
+ mockCommandService = {
14
22
  setData: vi.fn((state, data) => ({
15
23
  ...state,
16
24
  data: { ...state.data, ...data },
17
25
  })),
18
26
  } as unknown as CommandService<AppStateData, CLIArgs>;
19
27
 
20
- const checkEnv = Object.create(CheckEnv.prototype);
21
- checkEnv._commandService = mockCommandService;
22
- checkEnv._logService = mockLogService;
23
- checkEnv.state = { id: "test", args: [], data: {} };
28
+ container.registerInstance(LogService, mockLogService);
29
+ container.registerInstance(
30
+ CommandService<AppStateData, CLIArgs>,
31
+ mockCommandService,
32
+ );
33
+ });
34
+
35
+ it("should set environmentValidated to true", async () => {
36
+ const checkEnv = container.resolve(CheckEnv);
37
+
24
38
  await checkEnv.run();
25
- expect(mockLogService.info).toHaveBeenCalledWith(
39
+ expect(mockLogService.debug).toHaveBeenCalledWith(
26
40
  "Running Check Environment",
27
41
  );
28
42
  expect(checkEnv.state.data.environmentValidated).toBe(true);
29
43
  });
44
+
45
+ it("should call exit on missing required environment variable", async () => {
46
+ const testError = new Error("process.exit called");
47
+ const mockExit = vi.spyOn(process, "exit").mockImplementation(() => {
48
+ throw testError;
49
+ });
50
+ const checkEnv = container.resolve(CheckEnv);
51
+ checkEnv.requiredEnv = ["MISSING_ENV_VAR"];
52
+ try {
53
+ expect(await checkEnv.run()).toThrow(testError);
54
+ } catch (err) {
55
+ expect(`${err}`).toContain("process.exit");
56
+ expect(err).toBe(testError);
57
+ }
58
+ expect(mockLogService.error).toHaveBeenCalled();
59
+ mockExit.mockRestore();
60
+ });
61
+
62
+ it("should group environment issues into single error log", async () => {
63
+ const testError = new Error("process.exit called");
64
+ const mockExit = vi.spyOn(process, "exit").mockImplementation(() => {
65
+ throw testError;
66
+ });
67
+ const checkEnv = container.resolve(CheckEnv);
68
+ checkEnv.requiredEnv = ["MISSING_ENV_1", "MISSING_ENV_2", "MISSING_ENV_3"];
69
+ try {
70
+ await checkEnv.run();
71
+ } catch (err) {
72
+ expect(err).toBe(testError);
73
+ }
74
+ expect(mockLogService.error).toHaveBeenCalledOnce();
75
+ mockExit.mockRestore();
76
+ });
30
77
  });
@@ -0,0 +1,67 @@
1
+ ## task-runner
2
+
3
+ To get started, first run `npm install`, then:
4
+
5
+ ```
6
+ npm start
7
+ ```
8
+
9
+ ### Building the project
10
+
11
+ To build the project, run:
12
+
13
+ ```bash
14
+ npm run build
15
+ ```
16
+
17
+ or automatically run the build on file changes:
18
+
19
+ ```bash
20
+ npm run watch
21
+ ```
22
+
23
+ A build will compile the TypeScript code and output to a `dist` directory.
24
+
25
+ ### Linting
26
+
27
+ To lint the code, run:
28
+
29
+ ```bash
30
+ npm run lint
31
+ ```
32
+
33
+ ### Formatting
34
+
35
+ To format the code using Prettier, run:
36
+
37
+ ```bash
38
+ npm run format
39
+ ```
40
+
41
+ or automatically run formatting on file changes:
42
+
43
+ ```bash
44
+ npm run format-watch
45
+ ```
46
+
47
+ ### Clean
48
+
49
+ To clean up the project (delete dist folder):
50
+
51
+ ```bash
52
+ npm run clean
53
+ ```
54
+
55
+ ### Test
56
+
57
+ Run the tests:
58
+
59
+ ```
60
+ npm run test
61
+ ```
62
+
63
+ or automatically run them on file changes:
64
+
65
+ ```
66
+ npm run test-watch
67
+ ```
@@ -2838,9 +2838,9 @@
2838
2838
  }
2839
2839
  },
2840
2840
  "node_modules/task-script-support": {
2841
- "version": "2.3.0",
2842
- "resolved": "https://registry.npmjs.org/task-script-support/-/task-script-support-2.3.0.tgz",
2843
- "integrity": "sha512-6CpSaK6s4VIvT8UqrHLzhwlHxA/cGY475budPsWSbLLOXqLLyA7Slys1WsowtiumAjGYWz6LDC83O+LDrGkIzQ==",
2841
+ "version": "2.3.2",
2842
+ "resolved": "https://registry.npmjs.org/task-script-support/-/task-script-support-2.3.2.tgz",
2843
+ "integrity": "sha512-7q9xmr76iESQun1d/73TOnlacnRJTaV0D+XdcGcILT9AjkdCZXg8F45f6VbFJ9f26gBITe6+MLIe9mhJr2ooQw==",
2844
2844
  "license": "MIT",
2845
2845
  "dependencies": {
2846
2846
  "immutable": "^5.1.4",
@@ -12,8 +12,10 @@
12
12
  "format": "prettier --write ./",
13
13
  "format-check": "prettier --check .",
14
14
  "hooks-one-time-setup": "npx simple-git-hooks",
15
- "prettier-watch": "onchange \"**/*\" -- prettier --write --ignore-unknown {{changed}}",
15
+ "format-watch": "onchange \"**/*\" -- prettier --write --ignore-unknown {{changed}}",
16
16
  "build": "rm -rf ./dist && npx tsc && node dist/src/index.js -v",
17
+ "docker-build": "docker build -t local/task-runner:latest .",
18
+ "docker-run": "docker run --rm -it local/task-runner:latest",
17
19
  "test": "vitest run",
18
20
  "test-watch": "vitest"
19
21
  },
@@ -0,0 +1,8 @@
1
+ import { singleton } from "tsyringe";
2
+ import { Command } from "../wrappers/command";
3
+ import ShowHelp from "../tasks/show-help";
4
+
5
+ @singleton()
6
+ export class HelpCommand extends Command {
7
+ tasks = [ShowHelp];
8
+ }
@@ -12,11 +12,18 @@ initializeInjectables();
12
12
 
13
13
  import { UtilService } from "./services/util-service";
14
14
  import { VerifyCommand } from "./commands/verify";
15
+ import { HelpCommand } from "./commands/help-command";
15
16
 
16
17
  const name = UtilService.getAppName();
18
+ const yargsInstance = yargs(hideBin(process.argv));
19
+ container.registerInstance("yargs", yargsInstance);
17
20
 
18
- yargs(hideBin(process.argv))
21
+ yargsInstance
19
22
  .usage(`${UtilService.titleizeAll(name)} CLI Client`)
23
+ .command({
24
+ command: "$0",
25
+ handler: container.resolve(HelpCommand).handler,
26
+ })
20
27
  .command(
21
28
  "verify",
22
29
  "check the app is working",
@@ -17,6 +17,14 @@ export class LogService {
17
17
  }
18
18
  }
19
19
 
20
+ flush(): Promise<void> {
21
+ return new Promise((res, rej) => {
22
+ this.logger.flush((err?: Error) => {
23
+ return err ? rej(err) : res();
24
+ });
25
+ });
26
+ }
27
+
20
28
  setPrefix(prefix: string) {
21
29
  if (!LogService.ParentInstance) {
22
30
  this.logger = this.pinoLogger.getLogger(prefix);
@@ -5,6 +5,12 @@ import pkgJson from "../../package.json";
5
5
  export class UtilService {
6
6
  static TITLEIZE_TEXT_BREAKPONT: RegExp = /[. _-]/g;
7
7
 
8
+ /**
9
+ * Convert a string to title case.
10
+ *
11
+ * @param s the string to titleize
12
+ * @returns the titleized string.
13
+ */
8
14
  static titleize = (s: string) =>
9
15
  s ? `${s[0]?.toUpperCase()}${s.slice(1, s.length)}` : s;
10
16
  titleize = (s: string) => UtilService.titleize(s);
@@ -17,6 +23,9 @@ export class UtilService {
17
23
  .map(UtilService.titleize)
18
24
  .join(" ");
19
25
 
26
+ /**
27
+ * Get App information.
28
+ */
20
29
  static getAppName = () => pkgJson.name;
21
30
  getAppName = () => pkgJson.name;
22
31
 
@@ -25,4 +34,44 @@ export class UtilService {
25
34
 
26
35
  static getAppDescription = () => pkgJson.description;
27
36
  getAppDescription = () => pkgJson.description;
37
+
38
+ /**
39
+ * Mask a secret or sensitive value.
40
+ *
41
+ * @param value the string value to mask
42
+ * @returns the masked string
43
+ */
44
+ static maskValue = (value: string) => {
45
+ const maskChar = "*";
46
+ let endReveal = 2;
47
+ const longLength = 64;
48
+ const midLength = 8;
49
+ const shortLength = 4;
50
+ const tooSmallLength = 2;
51
+
52
+ // mask the whole thing
53
+ if (!value || value.length <= tooSmallLength) {
54
+ return maskChar.repeat((value || "").length);
55
+ }
56
+
57
+ // mask all but last char
58
+ if (value.length <= shortLength) {
59
+ return `${maskChar.repeat(value.length - 1)}${value.slice(-1)}`;
60
+ }
61
+
62
+ // reveal less on shorter strings
63
+ if (value.length <= midLength) {
64
+ endReveal = 1;
65
+ }
66
+
67
+ // reveal more on longer strings
68
+ if (value.length >= longLength) {
69
+ endReveal = 3;
70
+ }
71
+
72
+ const end = value.length - endReveal;
73
+ const start = endReveal;
74
+ return `${value.slice(0, start)}${maskChar.repeat(end - start)}${value.slice(end)}`;
75
+ };
76
+ maskValue = (v: string) => UtilService.maskValue(v);
28
77
  }
@@ -2,6 +2,7 @@ import chalk from "chalk";
2
2
  import { AppTask } from "../wrappers/app-task";
3
3
  import { autoInjectable } from "tsyringe";
4
4
  import { EnvironmentConfigKeys } from "../types/state";
5
+ import { UtilService } from "../services/util-service";
5
6
 
6
7
  /**
7
8
  * Checks the environment configuration
@@ -10,26 +11,36 @@ import { EnvironmentConfigKeys } from "../types/state";
10
11
  export default class CheckEnv extends AppTask {
11
12
  loggerName = "Check Environment";
12
13
 
14
+ requiredEnv: string[] = [];
15
+ secretEnv: Set<string> = new Set([
16
+ // add keys that should be masked in log output here
17
+ ]);
18
+ optionalEnv = [
19
+ EnvironmentConfigKeys.NODE_ENV,
20
+ EnvironmentConfigKeys.PINO_LOG_TARGET,
21
+ EnvironmentConfigKeys.PINO_LOG_DIR_PATH,
22
+ EnvironmentConfigKeys.PINO_LOG_FILENAME,
23
+ EnvironmentConfigKeys.PINO_LOG_LEVEL,
24
+ ];
25
+
13
26
  async run() {
14
- this.logger.info(chalk.blueBright("Running Check Environment"));
27
+ this.logger.debug(chalk.blueBright("Running Check Environment"));
15
28
 
16
29
  const errorMessages: string[] = [];
17
- const requiredEnv: string[] = [];
18
- const optionalEnv = [
19
- EnvironmentConfigKeys.NODE_ENV,
20
- EnvironmentConfigKeys.PINO_LOG_TARGET,
21
- EnvironmentConfigKeys.PINO_LOG_DIR_PATH,
22
- EnvironmentConfigKeys.PINO_LOG_FILENAME,
23
- EnvironmentConfigKeys.PINO_LOG_LEVEL,
24
- ];
25
-
26
- [...optionalEnv, ...requiredEnv]
30
+
31
+ [...this.optionalEnv, ...this.requiredEnv]
27
32
  .filter((e) => !!process.env[e])
28
33
  .forEach((e) => {
29
- this.logger.info(`Read value for ${e}: ${process.env[e]}`);
34
+ let envVal = process.env[e] || "";
35
+ if (this.secretEnv.has(e)) {
36
+ envVal = UtilService.maskValue(envVal);
37
+ }
38
+ this.logger.debug(
39
+ `Read value for ${e}: ${chalk.magentaBright(envVal)}`,
40
+ );
30
41
  });
31
42
 
32
- requiredEnv
43
+ this.requiredEnv
33
44
  .filter((e) => !process.env[e])
34
45
  .forEach((e) =>
35
46
  errorMessages.push(`Missing required environment variable ${e}`),
@@ -0,0 +1,19 @@
1
+ import { AppTask } from "../wrappers/app-task";
2
+ import { autoInjectable, inject } from "tsyringe";
3
+ import type { Yargs } from "../types/state";
4
+
5
+ /**
6
+ * Show the yargs help menu
7
+ */
8
+ @autoInjectable()
9
+ export default class ShowHelp extends AppTask {
10
+ loggerName = "ShowHelp";
11
+
12
+ constructor(@inject("yargs") private yargs: Yargs) {
13
+ super();
14
+ }
15
+
16
+ async run() {
17
+ this.yargs.showHelp();
18
+ }
19
+ }
@@ -1,4 +1,5 @@
1
1
  import { AppState as State, TaskClass } from "task-script-support";
2
+ import yargs from "yargs";
2
3
 
3
4
  // Add app data here as needed. Use readonly for immutable fields.
4
5
  //
@@ -31,3 +32,5 @@ export const EnvironmentConfigKeys = {
31
32
  };
32
33
 
33
34
  export type AppTaskClass = TaskClass<AppStateData, CLIArgs>;
35
+
36
+ export type Yargs = typeof yargs;
@@ -35,6 +35,11 @@ export class AppTask extends Task<AppStateData, CLIArgs> {
35
35
  throw new Error(`run not implemented (${state.id})`);
36
36
  }
37
37
 
38
+ //@override
39
+ async postRun() {
40
+ await this.logger.flush();
41
+ }
42
+
38
43
  setData(data: Partial<AppStateData>) {
39
44
  this.state = this._commandService!.setData(this.state, data);
40
45
  return this.state;
@@ -1,30 +1,77 @@
1
- import { describe, it, expect, vi } from "vitest";
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
2
  import CheckEnv from "../../src/tasks/check-env";
3
3
  import { LogService } from "../../src/services/log-service";
4
4
  import { CommandService } from "task-script-support";
5
5
  import { AppStateData, CLIArgs } from "../../src/types/state";
6
+ import { container } from "tsyringe";
6
7
 
7
8
  describe("CheckEnv", () => {
8
- it("should set environmentValidated to true", async () => {
9
- const mockLogService = {
9
+ let mockLogService = {} as LogService;
10
+ let mockCommandService = {} as CommandService<AppStateData, CLIArgs>;
11
+
12
+ beforeEach(() => {
13
+ container.reset();
14
+
15
+ mockLogService = {
10
16
  info: vi.fn(),
11
17
  debug: vi.fn(),
18
+ error: vi.fn(),
12
19
  } as unknown as LogService;
13
- const mockCommandService = {
20
+
21
+ mockCommandService = {
14
22
  setData: vi.fn((state, data) => ({
15
23
  ...state,
16
24
  data: { ...state.data, ...data },
17
25
  })),
18
26
  } as unknown as CommandService<AppStateData, CLIArgs>;
19
27
 
20
- const checkEnv = Object.create(CheckEnv.prototype);
21
- checkEnv._commandService = mockCommandService;
22
- checkEnv._logService = mockLogService;
23
- checkEnv.state = { id: "test", args: [], data: {} };
28
+ container.registerInstance(LogService, mockLogService);
29
+ container.registerInstance(
30
+ CommandService<AppStateData, CLIArgs>,
31
+ mockCommandService,
32
+ );
33
+ });
34
+
35
+ it("should set environmentValidated to true", async () => {
36
+ const checkEnv = container.resolve(CheckEnv);
37
+
24
38
  await checkEnv.run();
25
- expect(mockLogService.info).toHaveBeenCalledWith(
39
+ expect(mockLogService.debug).toHaveBeenCalledWith(
26
40
  "Running Check Environment",
27
41
  );
28
42
  expect(checkEnv.state.data.environmentValidated).toBe(true);
29
43
  });
44
+
45
+ it("should call exit on missing required environment variable", async () => {
46
+ const testError = new Error("process.exit called");
47
+ const mockExit = vi.spyOn(process, "exit").mockImplementation(() => {
48
+ throw testError;
49
+ });
50
+ const checkEnv = container.resolve(CheckEnv);
51
+ checkEnv.requiredEnv = ["MISSING_ENV_VAR"];
52
+ try {
53
+ expect(await checkEnv.run()).toThrow(testError);
54
+ } catch (err) {
55
+ expect(`${err}`).toContain("process.exit");
56
+ expect(err).toBe(testError);
57
+ }
58
+ expect(mockLogService.error).toHaveBeenCalled();
59
+ mockExit.mockRestore();
60
+ });
61
+
62
+ it("should group environment issues into single error log", async () => {
63
+ const testError = new Error("process.exit called");
64
+ const mockExit = vi.spyOn(process, "exit").mockImplementation(() => {
65
+ throw testError;
66
+ });
67
+ const checkEnv = container.resolve(CheckEnv);
68
+ checkEnv.requiredEnv = ["MISSING_ENV_1", "MISSING_ENV_2", "MISSING_ENV_3"];
69
+ try {
70
+ await checkEnv.run();
71
+ } catch (err) {
72
+ expect(err).toBe(testError);
73
+ }
74
+ expect(mockLogService.error).toHaveBeenCalledOnce();
75
+ mockExit.mockRestore();
76
+ });
30
77
  });
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-script-support-cli",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "main": "index.js",
5
5
  "type": "commonjs",
6
6
  "preferGlobal": true,
@@ -1 +1 @@
1
- {"version":3,"file":"templater-service.d.ts","sourceRoot":"./src/","sources":["src/services/templater-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,qBACa,eAAe;IA6BxB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,MAAM;IA7BhB,OAAO,CAAC,UAAU,CAA0B;IAE5C,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,WAAW,CAAU;IAE7B,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,cAAc,CAWpB;IACF,OAAO,CAAC,WAAW,CAMjB;gBAGQ,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,UAAU;IASf,YAAY,CAAC,UAAU,EAAE,MAAM;YAqB9B,uBAAuB;YAMvB,eAAe;YASf,SAAS;YAST,SAAS;YAWT,eAAe;YAOf,kBAAkB;YAOlB,gCAAgC;YAUhC,gBAAgB;YAOhB,iBAAiB;CAQhC"}
1
+ {"version":3,"file":"templater-service.d.ts","sourceRoot":"./src/","sources":["src/services/templater-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,qBACa,eAAe;IA+BxB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,MAAM;IA/BhB,OAAO,CAAC,UAAU,CAA0B;IAE5C,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,WAAW,CAAU;IAE7B,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,cAAc,CAYpB;IACF,OAAO,CAAC,WAAW,CAOjB;gBAGQ,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,UAAU;IASf,YAAY,CAAC,UAAU,EAAE,MAAM;YAqB9B,uBAAuB;YAMvB,eAAe;YASf,SAAS;YAST,SAAS;YAWT,eAAe;YAOf,kBAAkB;YAOlB,gCAAgC;YAUhC,gBAAgB;YAOhB,iBAAiB;CAQhC"}
@@ -36,6 +36,7 @@ let TemplateService = class TemplateService {
36
36
  "task-runner",
37
37
  "install-link.sh",
38
38
  "Dockerfile",
39
+ "README.md",
39
40
  "eslint.config.ts",
40
41
  "vitest.config.ts",
41
42
  "package-lock.json",
@@ -47,6 +48,7 @@ let TemplateService = class TemplateService {
47
48
  "package.json",
48
49
  "package-lock.json",
49
50
  "install-link.sh",
51
+ "README.md",
50
52
  "Dockerfile",
51
53
  ];
52
54
  constructor(spawnService, logger) {
@@ -1 +1 @@
1
- {"version":3,"file":"templater-service.js","sourceRoot":"./src/","sources":["src/services/templater-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templater-service.js","sourceRoot":"./src/","sources":["src/services/templater-service.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,7 @@ const util_service_1 = require("../../services/util-service");
19
19
  const file_service_1 = require("../../services/file-service");
20
20
  const newProjectMessage = (dest) => `
21
21
  Try:
22
- cd ${dest} && npm i && npm start -- help
22
+ cd ${dest} && npm i && npm start
23
23
  `;
24
24
  /**
25
25
  * Prints the generated output results
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-script-support-cli",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "main": "index.js",
5
5
  "type": "commonjs",
6
6
  "preferGlobal": true,
@@ -24,6 +24,7 @@ export class TemplateService {
24
24
  "task-runner",
25
25
  "install-link.sh",
26
26
  "Dockerfile",
27
+ "README.md",
27
28
  "eslint.config.ts",
28
29
  "vitest.config.ts",
29
30
  "package-lock.json",
@@ -35,6 +36,7 @@ export class TemplateService {
35
36
  "package.json",
36
37
  "package-lock.json",
37
38
  "install-link.sh",
39
+ "README.md",
38
40
  "Dockerfile",
39
41
  ];
40
42
 
@@ -6,7 +6,7 @@ import { FileService } from "../../services/file-service";
6
6
 
7
7
  const newProjectMessage = (dest: string) => `
8
8
  Try:
9
- cd ${dest} && npm i && npm start -- help
9
+ cd ${dest} && npm i && npm start
10
10
  `;
11
11
 
12
12
  /**