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.
- package/assets/yargs-template/task-runner/README.md +67 -0
- package/assets/yargs-template/task-runner/package-lock.json +3 -3
- package/assets/yargs-template/task-runner/package.json +3 -1
- package/assets/yargs-template/task-runner/src/commands/help-command.ts +8 -0
- package/assets/yargs-template/task-runner/src/index.ts +8 -1
- package/assets/yargs-template/task-runner/src/services/log-service.ts +8 -0
- package/assets/yargs-template/task-runner/src/services/util-service.ts +49 -0
- package/assets/yargs-template/task-runner/src/tasks/check-env.ts +24 -13
- package/assets/yargs-template/task-runner/src/tasks/show-help.ts +19 -0
- package/assets/yargs-template/task-runner/src/types/state.ts +3 -0
- package/assets/yargs-template/task-runner/src/wrappers/app-task.ts +5 -0
- package/assets/yargs-template/task-runner/tests/tasks/check-env.test.ts +56 -9
- package/dist/assets/yargs-template/task-runner/README.md +67 -0
- package/dist/assets/yargs-template/task-runner/package-lock.json +3 -3
- package/dist/assets/yargs-template/task-runner/package.json +3 -1
- package/dist/assets/yargs-template/task-runner/src/commands/help-command.ts +8 -0
- package/dist/assets/yargs-template/task-runner/src/index.ts +8 -1
- package/dist/assets/yargs-template/task-runner/src/services/log-service.ts +8 -0
- package/dist/assets/yargs-template/task-runner/src/services/util-service.ts +49 -0
- package/dist/assets/yargs-template/task-runner/src/tasks/check-env.ts +24 -13
- package/dist/assets/yargs-template/task-runner/src/tasks/show-help.ts +19 -0
- package/dist/assets/yargs-template/task-runner/src/types/state.ts +3 -0
- package/dist/assets/yargs-template/task-runner/src/wrappers/app-task.ts +5 -0
- package/dist/assets/yargs-template/task-runner/tests/tasks/check-env.test.ts +56 -9
- package/dist/package.json +1 -1
- package/dist/src/services/templater-service.d.ts.map +1 -1
- package/dist/src/services/templater-service.js +2 -0
- package/dist/src/services/templater-service.js.map +1 -1
- package/dist/src/tasks/stdout/print-generated-results.js +1 -1
- package/package.json +1 -1
- package/src/services/templater-service.ts +2 -0
- 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.
|
|
2842
|
-
"resolved": "https://registry.npmjs.org/task-script-support/-/task-script-support-2.3.
|
|
2843
|
-
"integrity": "sha512-
|
|
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
|
-
"
|
|
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
|
},
|
|
@@ -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
|
-
|
|
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.
|
|
27
|
+
this.logger.debug(chalk.blueBright("Running Check Environment"));
|
|
15
28
|
|
|
16
29
|
const errorMessages: string[] = [];
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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.
|
|
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.
|
|
2842
|
-
"resolved": "https://registry.npmjs.org/task-script-support/-/task-script-support-2.3.
|
|
2843
|
-
"integrity": "sha512-
|
|
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
|
-
"
|
|
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
|
},
|
|
@@ -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
|
-
|
|
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.
|
|
27
|
+
this.logger.debug(chalk.blueBright("Running Check Environment"));
|
|
15
28
|
|
|
16
29
|
const errorMessages: string[] = [];
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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.
|
|
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 +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;
|
|
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":";;;;;;;;;;;;;;;AAAA,0DAA6B;AAC7B,sDAAyB;AACzB,uCAA0C;AAC1C,mDAA+C;AAC/C,+CAA2C;AAC3C,8DAAkE;AAElE,MAAM,gBAAgB,GAAG;;KAEpB,CAAC;AAGC,IAAM,eAAe,GAArB,MAAM,eAAe;
|
|
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
|
|
22
|
+
cd ${dest} && npm i && npm start
|
|
23
23
|
`;
|
|
24
24
|
/**
|
|
25
25
|
* Prints the generated output results
|
package/package.json
CHANGED
|
@@ -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
|
|