task-script-support-cli 0.1.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/yargs-template/task-runner/.prettierignore +3 -0
- package/assets/yargs-template/task-runner/.prettierrc +1 -0
- package/assets/yargs-template/task-runner/.vscode/launch.json +34 -0
- package/assets/yargs-template/task-runner/eslint.config.ts +11 -0
- package/assets/yargs-template/task-runner/install-link.sh +21 -0
- package/assets/yargs-template/task-runner/package-lock.json +3387 -0
- package/assets/yargs-template/task-runner/package.json +51 -0
- package/assets/yargs-template/task-runner/src/commands/verify.ts +10 -0
- package/assets/yargs-template/task-runner/src/index.ts +46 -0
- package/assets/yargs-template/task-runner/src/services/banner-service.ts +38 -0
- package/assets/yargs-template/task-runner/src/services/log-service.ts +48 -0
- package/assets/yargs-template/task-runner/src/services/spawn-service.ts +87 -0
- package/assets/yargs-template/task-runner/src/services/util-service.ts +28 -0
- package/assets/yargs-template/task-runner/src/tasks/check-env.ts +49 -0
- package/assets/yargs-template/task-runner/src/tasks/log-state.ts +22 -0
- package/assets/yargs-template/task-runner/src/tasks/print-banner.ts +73 -0
- package/assets/yargs-template/task-runner/src/types/process.ts +9 -0
- package/assets/yargs-template/task-runner/src/types/state.ts +31 -0
- package/assets/yargs-template/task-runner/src/wrappers/app-task.ts +42 -0
- package/assets/yargs-template/task-runner/src/wrappers/command.ts +20 -0
- package/assets/yargs-template/task-runner/src/wrappers/dependencies.ts +24 -0
- package/assets/yargs-template/task-runner/task-runner +3 -0
- package/assets/yargs-template/task-runner/templater.sh +57 -0
- package/assets/yargs-template/task-runner/tests/commands/verify.test.ts +42 -0
- package/assets/yargs-template/task-runner/tests/services/spawn-service.test.ts +132 -0
- package/assets/yargs-template/task-runner/tests/services/util-service.test.ts +36 -0
- package/assets/yargs-template/task-runner/tests/setup.ts +1 -0
- package/assets/yargs-template/task-runner/tests/tasks/check-env.test.ts +30 -0
- package/assets/yargs-template/task-runner/tsconfig.json +27 -0
- package/assets/yargs-template/task-runner/vitest.config.ts +14 -0
- package/dist/assets/yargs-template/task-runner/.prettierignore +3 -0
- package/dist/assets/yargs-template/task-runner/.prettierrc +1 -0
- package/dist/assets/yargs-template/task-runner/.vscode/launch.json +34 -0
- package/dist/assets/yargs-template/task-runner/eslint.config.ts +11 -0
- package/dist/assets/yargs-template/task-runner/install-link.sh +21 -0
- package/dist/assets/yargs-template/task-runner/package-lock.json +3387 -0
- package/dist/assets/yargs-template/task-runner/package.json +51 -0
- package/dist/assets/yargs-template/task-runner/src/commands/verify.ts +10 -0
- package/dist/assets/yargs-template/task-runner/src/index.ts +46 -0
- package/dist/assets/yargs-template/task-runner/src/services/banner-service.ts +38 -0
- package/dist/assets/yargs-template/task-runner/src/services/log-service.ts +48 -0
- package/dist/assets/yargs-template/task-runner/src/services/spawn-service.ts +87 -0
- package/dist/assets/yargs-template/task-runner/src/services/util-service.ts +28 -0
- package/dist/assets/yargs-template/task-runner/src/tasks/check-env.ts +49 -0
- package/dist/assets/yargs-template/task-runner/src/tasks/log-state.ts +22 -0
- package/dist/assets/yargs-template/task-runner/src/tasks/print-banner.ts +73 -0
- package/dist/assets/yargs-template/task-runner/src/types/process.ts +9 -0
- package/dist/assets/yargs-template/task-runner/src/types/state.ts +31 -0
- package/dist/assets/yargs-template/task-runner/src/wrappers/app-task.ts +42 -0
- package/dist/assets/yargs-template/task-runner/src/wrappers/command.ts +20 -0
- package/dist/assets/yargs-template/task-runner/src/wrappers/dependencies.ts +24 -0
- package/dist/assets/yargs-template/task-runner/task-runner +3 -0
- package/dist/assets/yargs-template/task-runner/templater.sh +57 -0
- package/dist/assets/yargs-template/task-runner/tests/commands/verify.test.ts +42 -0
- package/dist/assets/yargs-template/task-runner/tests/services/spawn-service.test.ts +132 -0
- package/dist/assets/yargs-template/task-runner/tests/services/util-service.test.ts +36 -0
- package/dist/assets/yargs-template/task-runner/tests/setup.ts +1 -0
- package/dist/assets/yargs-template/task-runner/tests/tasks/check-env.test.ts +30 -0
- package/dist/assets/yargs-template/task-runner/tsconfig.json +27 -0
- package/dist/assets/yargs-template/task-runner/vitest.config.ts +14 -0
- package/dist/package.json +8 -3
- package/dist/src/commands/gen.d.ts +3 -1
- package/dist/src/commands/gen.d.ts.map +1 -1
- package/dist/src/commands/gen.js +4 -0
- package/dist/src/commands/gen.js.map +1 -1
- package/dist/src/commands/new.d.ts +8 -0
- package/dist/src/commands/new.d.ts.map +1 -0
- package/dist/src/commands/new.js +25 -0
- package/dist/src/commands/new.js.map +1 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/services/cache-service.d.ts +11 -0
- package/dist/src/services/cache-service.d.ts.map +1 -0
- package/dist/src/services/cache-service.js +64 -0
- package/dist/src/services/cache-service.js.map +1 -0
- package/dist/src/services/file-service.d.ts +5 -1
- package/dist/src/services/file-service.d.ts.map +1 -1
- package/dist/src/services/file-service.js +16 -2
- package/dist/src/services/file-service.js.map +1 -1
- package/dist/src/services/log-service.d.ts.map +1 -1
- package/dist/src/services/log-service.js +7 -1
- package/dist/src/services/log-service.js.map +1 -1
- package/dist/src/services/project-service.d.ts +2 -2
- package/dist/src/services/project-service.d.ts.map +1 -1
- package/dist/src/services/project-service.js +5 -7
- package/dist/src/services/project-service.js.map +1 -1
- package/dist/src/services/prompt-service.d.ts +27 -0
- package/dist/src/services/prompt-service.d.ts.map +1 -0
- package/dist/src/services/prompt-service.js +67 -0
- package/dist/src/services/prompt-service.js.map +1 -0
- package/dist/src/services/spawn-service.d.ts +2 -1
- package/dist/src/services/spawn-service.d.ts.map +1 -1
- package/dist/src/services/spawn-service.js +16 -1
- package/dist/src/services/spawn-service.js.map +1 -1
- package/dist/src/services/util-service.d.ts +2 -0
- package/dist/src/services/util-service.d.ts.map +1 -1
- package/dist/src/services/util-service.js +4 -0
- package/dist/src/services/util-service.js.map +1 -1
- package/dist/src/tasks/check-env.d.ts +3 -2
- package/dist/src/tasks/check-env.d.ts.map +1 -1
- package/dist/src/tasks/check-env.js +11 -3
- package/dist/src/tasks/check-env.js.map +1 -1
- package/dist/src/tasks/create-new-project.d.ts +26 -0
- package/dist/src/tasks/create-new-project.d.ts.map +1 -0
- package/dist/src/tasks/create-new-project.js +76 -0
- package/dist/src/tasks/create-new-project.js.map +1 -0
- package/dist/src/tasks/generate-command.d.ts +18 -6
- package/dist/src/tasks/generate-command.d.ts.map +1 -1
- package/dist/src/tasks/generate-command.js +66 -29
- package/dist/src/tasks/generate-command.js.map +1 -1
- package/dist/src/tasks/generate-service.d.ts +10 -6
- package/dist/src/tasks/generate-service.d.ts.map +1 -1
- package/dist/src/tasks/generate-service.js +27 -26
- package/dist/src/tasks/generate-service.js.map +1 -1
- package/dist/src/tasks/generate-task.d.ts +10 -6
- package/dist/src/tasks/generate-task.d.ts.map +1 -1
- package/dist/src/tasks/generate-task.js +27 -26
- package/dist/src/tasks/generate-task.js.map +1 -1
- package/dist/src/tasks/print-banner.d.ts +3 -3
- package/dist/src/tasks/print-banner.d.ts.map +1 -1
- package/dist/src/tasks/print-banner.js +12 -8
- package/dist/src/tasks/print-banner.js.map +1 -1
- package/dist/src/tasks/print-generated-results.d.ts.map +1 -1
- package/dist/src/tasks/print-generated-results.js +13 -10
- package/dist/src/tasks/print-generated-results.js.map +1 -1
- package/dist/src/tasks/select-gen-target-name.d.ts +15 -0
- package/dist/src/tasks/select-gen-target-name.d.ts.map +1 -0
- package/dist/src/tasks/select-gen-target-name.js +58 -0
- package/dist/src/tasks/select-gen-target-name.js.map +1 -0
- package/dist/src/tasks/select-gen-target.d.ts +5 -0
- package/dist/src/tasks/select-gen-target.d.ts.map +1 -1
- package/dist/src/tasks/select-gen-target.js +16 -2
- package/dist/src/tasks/select-gen-target.js.map +1 -1
- package/dist/src/tasks/sync-configuration.d.ts +34 -0
- package/dist/src/tasks/sync-configuration.d.ts.map +1 -0
- package/dist/src/tasks/sync-configuration.js +116 -0
- package/dist/src/tasks/sync-configuration.js.map +1 -0
- package/dist/src/tasks/test-task.d.ts +10 -0
- package/dist/src/tasks/test-task.d.ts.map +1 -0
- package/dist/src/tasks/test-task.js +36 -0
- package/dist/src/tasks/test-task.js.map +1 -0
- package/dist/src/templates/command.js +2 -2
- package/dist/src/templates/command.js.map +1 -1
- package/dist/src/templates/service.js +1 -1
- package/dist/src/templates/service.js.map +1 -1
- package/dist/src/types/process.d.ts +2 -1
- package/dist/src/types/process.d.ts.map +1 -1
- package/dist/src/types/process.js +1 -0
- package/dist/src/types/process.js.map +1 -1
- package/dist/src/types/project.d.ts +12 -0
- package/dist/src/types/project.d.ts.map +1 -0
- package/dist/src/types/project.js +3 -0
- package/dist/src/types/project.js.map +1 -0
- package/dist/src/types/state.d.ts +5 -1
- package/dist/src/types/state.d.ts.map +1 -1
- package/dist/src/types/state.js +1 -0
- package/dist/src/types/state.js.map +1 -1
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +16 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +8 -3
- package/src/commands/gen.ts +4 -0
- package/src/commands/new.ts +10 -0
- package/src/index.ts +7 -0
- package/src/services/cache-service.ts +50 -0
- package/src/services/file-service.ts +18 -1
- package/src/services/log-service.ts +6 -1
- package/src/services/project-service.ts +2 -2
- package/src/services/prompt-service.ts +60 -0
- package/src/services/spawn-service.ts +15 -1
- package/src/services/util-service.ts +5 -0
- package/src/tasks/check-env.ts +10 -2
- package/src/tasks/create-new-project.ts +66 -0
- package/src/tasks/generate-command.ts +84 -31
- package/src/tasks/generate-service.ts +24 -28
- package/src/tasks/generate-task.ts +24 -28
- package/src/tasks/print-banner.ts +10 -6
- package/src/tasks/print-generated-results.ts +15 -15
- package/src/tasks/select-gen-target-name.ts +44 -0
- package/src/tasks/select-gen-target.ts +16 -1
- package/src/tasks/sync-configuration.ts +121 -0
- package/src/tasks/test-task.ts +20 -0
- package/src/templates/command.ts +2 -2
- package/src/templates/service.ts +1 -1
- package/src/types/process.ts +1 -0
- package/src/types/project.ts +12 -0
- package/src/types/state.ts +7 -1
- package/tests/index.spec.ts +8 -0
- package/tests/setup.ts +1 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "task-runner",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "jiti src/index.ts",
|
|
8
|
+
"dev": "npm run build && node dist/src/index.js",
|
|
9
|
+
"clean": "rm -rf ./dist",
|
|
10
|
+
"lint": "eslint --config eslint.config.ts",
|
|
11
|
+
"watch": "onchange './*{.json,.sh,.ts}' 'src/*.ts' -- npm run build",
|
|
12
|
+
"format": "prettier --write ./",
|
|
13
|
+
"format-check": "prettier --check .",
|
|
14
|
+
"hooks-one-time-setup": "npx simple-git-hooks",
|
|
15
|
+
"prettier-watch": "onchange \"**/*\" -- prettier --write --ignore-unknown {{changed}}",
|
|
16
|
+
"build": "rm -rf ./dist && npx tsc && node dist/src/index.js -v",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test-watch": "vitest"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"description": "",
|
|
24
|
+
"simple-git-hooks": {
|
|
25
|
+
"pre-commit": "npx pretty-quick --staged && npm run lint"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"chalk": "^4.1.2",
|
|
29
|
+
"dotenv": "^17.2.3",
|
|
30
|
+
"figlet": "^1.9.4",
|
|
31
|
+
"immutable": "^5.1.4",
|
|
32
|
+
"reflect-metadata": "^0.2.2",
|
|
33
|
+
"task-script-support": "^2.3.0",
|
|
34
|
+
"tsyringe": "^4.10.0",
|
|
35
|
+
"yargs": "^18.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@eslint/js": "^9.39.3",
|
|
39
|
+
"@types/node": "^24.10.1",
|
|
40
|
+
"@types/yargs": "^17.0.35",
|
|
41
|
+
"eslint": "^10.0.3",
|
|
42
|
+
"jiti": "^2.6.1",
|
|
43
|
+
"onchange": "^7.1.0",
|
|
44
|
+
"prettier": "^3.7.1",
|
|
45
|
+
"pretty-quick": "^4.2.2",
|
|
46
|
+
"simple-git-hooks": "^2.13.1",
|
|
47
|
+
"typescript": "^5.9.3",
|
|
48
|
+
"typescript-eslint": "^8.48.0",
|
|
49
|
+
"vitest": "^4.0.15"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { singleton } from "tsyringe";
|
|
2
|
+
import { Command } from "../wrappers/command";
|
|
3
|
+
import CheckEnv from "../tasks/check-env";
|
|
4
|
+
import PrintBanner from "../tasks/print-banner";
|
|
5
|
+
import LogState from "../tasks/log-state";
|
|
6
|
+
|
|
7
|
+
@singleton()
|
|
8
|
+
export class VerifyCommand extends Command {
|
|
9
|
+
tasks = [PrintBanner, CheckEnv, LogState];
|
|
10
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
import { container } from "tsyringe";
|
|
5
|
+
|
|
6
|
+
dotenv.config({ quiet: true });
|
|
7
|
+
import yargs from "yargs";
|
|
8
|
+
import { hideBin } from "yargs/helpers";
|
|
9
|
+
|
|
10
|
+
import { initializeInjectables } from "./wrappers/dependencies";
|
|
11
|
+
initializeInjectables();
|
|
12
|
+
|
|
13
|
+
import { UtilService } from "./services/util-service";
|
|
14
|
+
import { VerifyCommand } from "./commands/verify";
|
|
15
|
+
|
|
16
|
+
const name = UtilService.getAppName();
|
|
17
|
+
|
|
18
|
+
yargs(hideBin(process.argv))
|
|
19
|
+
.usage(`${UtilService.titleizeAll(name)} CLI Client`)
|
|
20
|
+
.command(
|
|
21
|
+
"verify",
|
|
22
|
+
"check the app is working",
|
|
23
|
+
(yargs) => {
|
|
24
|
+
yargs
|
|
25
|
+
.option("bf", {
|
|
26
|
+
alias: "banner-font",
|
|
27
|
+
type: "string",
|
|
28
|
+
describe: "provide a font for the app banner",
|
|
29
|
+
})
|
|
30
|
+
.option("rf", {
|
|
31
|
+
alias: "random-font",
|
|
32
|
+
type: "boolean",
|
|
33
|
+
describe: "use a random font for app banner",
|
|
34
|
+
default: false,
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
container.resolve(VerifyCommand).handler,
|
|
38
|
+
)
|
|
39
|
+
.option("d", {
|
|
40
|
+
alias: "debug",
|
|
41
|
+
type: "boolean",
|
|
42
|
+
describe: "enable extra logging",
|
|
43
|
+
default: false,
|
|
44
|
+
})
|
|
45
|
+
.help()
|
|
46
|
+
.parse();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { singleton } from "tsyringe";
|
|
2
|
+
import figlet from "figlet";
|
|
3
|
+
|
|
4
|
+
@singleton()
|
|
5
|
+
export class BannerService {
|
|
6
|
+
_selectFonts = [
|
|
7
|
+
"AMC Slash",
|
|
8
|
+
"Calvin S",
|
|
9
|
+
"Bell",
|
|
10
|
+
"Pagga",
|
|
11
|
+
"Shadow",
|
|
12
|
+
"Small Block",
|
|
13
|
+
];
|
|
14
|
+
defaultFontFamily: string = "Cybermedium";
|
|
15
|
+
|
|
16
|
+
async toBanner(text: string, font?: string): Promise<string> {
|
|
17
|
+
return await figlet.text(text, {
|
|
18
|
+
font: font || this.defaultFontFamily,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getSupportedFonts(): Promise<string[]> {
|
|
23
|
+
return await new Promise((res, rej) => {
|
|
24
|
+
figlet.fonts((err, fonts) =>
|
|
25
|
+
err ? rej(err) : res(fonts || ([] as string[])),
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getRandomFont(): Promise<string> {
|
|
31
|
+
const randomIndexBetween = (start = 0, end = 0) =>
|
|
32
|
+
Math.floor(Math.random() * (end - start + 1)) + start;
|
|
33
|
+
|
|
34
|
+
const bannerFonts: string[] = await this.getSupportedFonts();
|
|
35
|
+
const randomFontIndex = randomIndexBetween(0, bannerFonts.length - 1);
|
|
36
|
+
return bannerFonts[randomFontIndex] || this.defaultFontFamily;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { inject, injectable } from "tsyringe";
|
|
2
|
+
import { PinoLogger } from "task-script-support";
|
|
3
|
+
import pino from "pino";
|
|
4
|
+
|
|
5
|
+
@injectable()
|
|
6
|
+
export class LogService {
|
|
7
|
+
logger: pino.Logger;
|
|
8
|
+
|
|
9
|
+
static ParentInstance?: pino.Logger;
|
|
10
|
+
|
|
11
|
+
constructor(@inject("PinoLogger") private pinoLogger: PinoLogger) {
|
|
12
|
+
if (!LogService.ParentInstance) {
|
|
13
|
+
this.logger = pinoLogger.getLogger();
|
|
14
|
+
LogService.ParentInstance = this.logger;
|
|
15
|
+
} else {
|
|
16
|
+
this.logger = LogService.ParentInstance.child({});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setPrefix(prefix: string) {
|
|
21
|
+
if (!LogService.ParentInstance) {
|
|
22
|
+
this.logger = this.pinoLogger.getLogger(prefix);
|
|
23
|
+
LogService.ParentInstance = this.logger;
|
|
24
|
+
} else {
|
|
25
|
+
this.logger = LogService.ParentInstance.child({}, { msgPrefix: prefix });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public info(msg: string, obj?: unknown): void {
|
|
30
|
+
this.logger.info(obj, msg);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public error(err: Error | string, msg?: string, obj?: unknown): void {
|
|
34
|
+
if (err instanceof Error) {
|
|
35
|
+
this.logger.error({ err, ...(obj ? obj : {}) }, msg || "Error occurred");
|
|
36
|
+
} else {
|
|
37
|
+
this.logger.error(obj, `${msg}: ${err}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public warn(msg: string, obj?: unknown): void {
|
|
42
|
+
this.logger.warn(obj, msg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public debug(msg: string, obj?: unknown): void {
|
|
46
|
+
this.logger.debug(obj, msg);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import childProcess, { ChildProcess, spawn } from "node:child_process";
|
|
2
|
+
import type { ProcessOutput, ProcessStatus } from "../types/process";
|
|
3
|
+
import { singleton } from "tsyringe";
|
|
4
|
+
|
|
5
|
+
@singleton()
|
|
6
|
+
export class SpawnService {
|
|
7
|
+
execSyncFromDir(command: string, dir: string) {
|
|
8
|
+
try {
|
|
9
|
+
return childProcess.execSync(command, { cwd: dir }).toString();
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.error(`Error executing command: ${command}`);
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
execSync(command: string) {
|
|
17
|
+
try {
|
|
18
|
+
return childProcess.execSync(command).toString();
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error(`Error executing command: ${command}`);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exec(command: string): Promise<ProcessOutput> {
|
|
26
|
+
try {
|
|
27
|
+
return new Promise((res, rej) => {
|
|
28
|
+
return childProcess.exec(command, (err, stdout, stderr) => {
|
|
29
|
+
if (err) return rej(err);
|
|
30
|
+
return res({ stdout, stderr });
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error(`Error executing command: ${command}`, error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
backgroundExec(command: string, args: string[] = []): ChildProcess {
|
|
40
|
+
const child = spawn(command, args, {
|
|
41
|
+
detached: true,
|
|
42
|
+
stdio: "ignore",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
child.unref();
|
|
46
|
+
return child;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
isProcessCompleted(pid: number): boolean {
|
|
50
|
+
try {
|
|
51
|
+
// sending signal 0 checks if the process exists
|
|
52
|
+
process.kill(pid, 0);
|
|
53
|
+
return false;
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
kill(pid: number) {
|
|
61
|
+
try {
|
|
62
|
+
process.kill(pid);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Failed to kill process with PID ${pid}: ${(error as Error).message}`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
forceKill(pid: number) {
|
|
71
|
+
try {
|
|
72
|
+
process.kill(pid, "SIGKILL");
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Failed to forcefully kill process with PID ${pid}: ${(error as Error).message}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getProcessStatus(pid: number): Promise<ProcessStatus> {
|
|
81
|
+
const completed = this.isProcessCompleted(pid);
|
|
82
|
+
return {
|
|
83
|
+
pid,
|
|
84
|
+
status: completed ? "completed" : "running",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { singleton } from "tsyringe";
|
|
2
|
+
import pkgJson from "../../package.json";
|
|
3
|
+
|
|
4
|
+
@singleton()
|
|
5
|
+
export class UtilService {
|
|
6
|
+
static TITLEIZE_TEXT_BREAKPONT: RegExp = /[. _-]/g;
|
|
7
|
+
|
|
8
|
+
static titleize = (s: string) =>
|
|
9
|
+
s ? `${s[0]?.toUpperCase()}${s.slice(1, s.length)}` : s;
|
|
10
|
+
titleize = (s: string) => UtilService.titleize(s);
|
|
11
|
+
|
|
12
|
+
titleizeAll = (s: string) => UtilService.titleizeAll(s);
|
|
13
|
+
static titleizeAll = (str: string) =>
|
|
14
|
+
str
|
|
15
|
+
.trim()
|
|
16
|
+
.split(UtilService.TITLEIZE_TEXT_BREAKPONT)
|
|
17
|
+
.map(UtilService.titleize)
|
|
18
|
+
.join(" ");
|
|
19
|
+
|
|
20
|
+
static getAppName = () => pkgJson.name;
|
|
21
|
+
getAppName = () => pkgJson.name;
|
|
22
|
+
|
|
23
|
+
static getAppVersion = () => pkgJson.version;
|
|
24
|
+
getAppVersion = () => pkgJson.version;
|
|
25
|
+
|
|
26
|
+
static getAppDescription = () => pkgJson.description;
|
|
27
|
+
getAppDescription = () => pkgJson.description;
|
|
28
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { AppTask } from "../wrappers/app-task";
|
|
3
|
+
import { autoInjectable } from "tsyringe";
|
|
4
|
+
import { EnvironmentConfigKeys } from "../types/state";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Checks the environment configuration
|
|
8
|
+
*/
|
|
9
|
+
@autoInjectable()
|
|
10
|
+
export default class CheckEnv extends AppTask {
|
|
11
|
+
loggerName = "Check Environment";
|
|
12
|
+
|
|
13
|
+
async run() {
|
|
14
|
+
this.logger.info(chalk.blueBright("Running Check Environment"));
|
|
15
|
+
|
|
16
|
+
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]
|
|
27
|
+
.filter((e) => !!process.env[e])
|
|
28
|
+
.forEach((e) => {
|
|
29
|
+
this.logger.info(`Read value for ${e}: ${process.env[e]}`);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
requiredEnv
|
|
33
|
+
.filter((e) => !process.env[e])
|
|
34
|
+
.forEach((e) =>
|
|
35
|
+
errorMessages.push(`Missing required environment variable ${e}`),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// fail the process on bad environment
|
|
39
|
+
if (errorMessages.length) {
|
|
40
|
+
this.logger.error(
|
|
41
|
+
new Error("Misconfigured Environment"),
|
|
42
|
+
chalk.red(errorMessages.join("\n")),
|
|
43
|
+
);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.state = this.setData({ environmentValidated: true });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { AppTask } from "../wrappers/app-task";
|
|
3
|
+
import { autoInjectable } from "tsyringe";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Logs the app state
|
|
7
|
+
*/
|
|
8
|
+
@autoInjectable()
|
|
9
|
+
export default class LogState extends AppTask {
|
|
10
|
+
loggerName = "Log State";
|
|
11
|
+
async run() {
|
|
12
|
+
if (!this.state.args.debug) {
|
|
13
|
+
this.logger.debug(
|
|
14
|
+
chalk.dim("Skipping logging state, use debug flag to see state"),
|
|
15
|
+
);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.logger.info(chalk.blueBright("Running Log State"));
|
|
20
|
+
this.logger.debug("state", this.state);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { autoInjectable } from "tsyringe";
|
|
2
|
+
import { AppState } from "../types/state";
|
|
3
|
+
import { AppTask } from "../wrappers/app-task";
|
|
4
|
+
import { BannerService } from "../services/banner-service";
|
|
5
|
+
import { UtilService } from "../services/util-service";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Prints an app banner to the console
|
|
10
|
+
*/
|
|
11
|
+
@autoInjectable()
|
|
12
|
+
export default class PrintBanner extends AppTask {
|
|
13
|
+
loggerName = "Print Banner";
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
private bannnerSvc: BannerService,
|
|
17
|
+
private utilService: UtilService,
|
|
18
|
+
) {
|
|
19
|
+
super();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async preRun() {
|
|
23
|
+
await this.validateFont();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async run({ args }: AppState): Promise<Partial<AppState> | void> {
|
|
27
|
+
let font = "";
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
if (args.randomFont) {
|
|
31
|
+
font = await this.bannnerSvc.getRandomFont();
|
|
32
|
+
console.log(`Using random font ${font}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// allow banner-font as user input
|
|
36
|
+
if (args.bannerFont) {
|
|
37
|
+
font = args.bannerFont;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log(
|
|
41
|
+
chalk.blueBright(
|
|
42
|
+
await this.bannnerSvc.toBanner(this.utilService.getAppName(), font),
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// mutate state
|
|
47
|
+
this.setData({
|
|
48
|
+
banner: { font: font || this.bannnerSvc.defaultFontFamily },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// return updated state instead of calling setData
|
|
52
|
+
return { data: { banner: { status: "success" } } } as const;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
this.setData({ banner: { status: "failed" }, errorMessages: [`${err}`] });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
Helper for ensuring font is supported if provided as input
|
|
60
|
+
*/
|
|
61
|
+
async validateFont() {
|
|
62
|
+
const { args } = this.state;
|
|
63
|
+
if (!args.bannerFont) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const fontName = args.bannerFont;
|
|
68
|
+
const availableFonts = await this.bannnerSvc.getSupportedFonts();
|
|
69
|
+
if (!availableFonts.includes(fontName)) {
|
|
70
|
+
throw new Error(`Unsupported font provided: ${chalk.red(fontName)}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AppState as State } from "task-script-support";
|
|
2
|
+
|
|
3
|
+
// Add app data here as needed. Use readonly for immutable fields.
|
|
4
|
+
//
|
|
5
|
+
// Note: this object gets passed to deepMerge upon updating app state
|
|
6
|
+
// which also merges array fields. This might be fine or you might want
|
|
7
|
+
// to make your arrays <type>[] | undefined to allow clobbering.
|
|
8
|
+
export interface AppStateData {
|
|
9
|
+
readonly errorMessages?: string[];
|
|
10
|
+
readonly banner?: {
|
|
11
|
+
readonly status?: "success" | "failed";
|
|
12
|
+
readonly font?: string;
|
|
13
|
+
};
|
|
14
|
+
readonly environmentValidated?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type CLIArgs = {
|
|
18
|
+
readonly debug: boolean;
|
|
19
|
+
readonly randomFont: boolean;
|
|
20
|
+
readonly bannerFont?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type AppState = State<AppStateData, CLIArgs>;
|
|
24
|
+
|
|
25
|
+
export const EnvironmentConfigKeys = {
|
|
26
|
+
PINO_LOG_DIR_PATH: "PINO_LOG_DIR_PATH",
|
|
27
|
+
PINO_LOG_LEVEL: "PINO_LOG_LEVEL",
|
|
28
|
+
NODE_ENV: "NODE_ENV",
|
|
29
|
+
PINO_LOG_FILENAME: "PINO_LOG_FILENAME",
|
|
30
|
+
PINO_LOG_TARGET: "PINO_LOG_TARGET",
|
|
31
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { autoInjectable } from "tsyringe";
|
|
2
|
+
import { CommandService, Task } from "task-script-support";
|
|
3
|
+
import { LogService } from "../services/log-service";
|
|
4
|
+
import type { AppState, AppStateData, CLIArgs } from "../types/state";
|
|
5
|
+
|
|
6
|
+
@autoInjectable()
|
|
7
|
+
export class AppTask extends Task<AppStateData, CLIArgs> {
|
|
8
|
+
state: AppState = {
|
|
9
|
+
id: "uninitialized",
|
|
10
|
+
args: {} as CLIArgs,
|
|
11
|
+
data: {},
|
|
12
|
+
};
|
|
13
|
+
loggerName: string = "";
|
|
14
|
+
|
|
15
|
+
get logger(): LogService {
|
|
16
|
+
return this._logService!;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor(
|
|
20
|
+
public _logService?: LogService,
|
|
21
|
+
public _commandService?: CommandService<AppStateData, CLIArgs>,
|
|
22
|
+
) {
|
|
23
|
+
super();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//@override
|
|
27
|
+
async initialize() {
|
|
28
|
+
if (this.loggerName) {
|
|
29
|
+
this.logger!.setPrefix(`${this.loggerName} :: `);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//@override
|
|
34
|
+
async run(state: AppState): Promise<Partial<AppState> | void> {
|
|
35
|
+
throw new Error(`run not implemented (${state.id})`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setData(data: Partial<AppStateData>) {
|
|
39
|
+
this.state = this._commandService!.setData(this.state, data);
|
|
40
|
+
return this.state;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CommandService, TaskClass } from "task-script-support";
|
|
2
|
+
import { inject } from "tsyringe";
|
|
3
|
+
import { AppStateData, CLIArgs } from "../types/state";
|
|
4
|
+
|
|
5
|
+
export class Command {
|
|
6
|
+
tasks: TaskClass<AppStateData, CLIArgs>[] = [];
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
@inject(CommandService<AppStateData, CLIArgs>)
|
|
10
|
+
private commandService: CommandService<AppStateData, CLIArgs>,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
get handler(): (...cliArgs: unknown[]) => Promise<void> {
|
|
14
|
+
return this.commandService.fromTasks(this.getTasks());
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getTasks(): TaskClass<AppStateData, CLIArgs>[] {
|
|
18
|
+
return this.tasks;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CommandService, PinoLogger } from "task-script-support";
|
|
2
|
+
import { container } from "tsyringe";
|
|
3
|
+
import { AppStateData, CLIArgs } from "../types/state";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Register external dependencies as injectables
|
|
7
|
+
*/
|
|
8
|
+
export const initializeInjectables = () => {
|
|
9
|
+
// register command service
|
|
10
|
+
container.registerSingleton(CommandService<AppStateData, CLIArgs>);
|
|
11
|
+
|
|
12
|
+
// configure args provider
|
|
13
|
+
const command = container.resolve(CommandService<AppStateData, CLIArgs>);
|
|
14
|
+
command.argsProvider = (...yargsArgs: unknown[]) => {
|
|
15
|
+
const args = command.argsProvider_Yargs(...yargsArgs);
|
|
16
|
+
|
|
17
|
+
// and register args
|
|
18
|
+
container.registerInstance("Args", args);
|
|
19
|
+
return args;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// register pino
|
|
23
|
+
container.registerInstance("PinoLogger", new PinoLogger());
|
|
24
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ -z "$1" ]]; then
|
|
5
|
+
echo "Missing required parameter. Usage: ./templater.sh <output-name>"
|
|
6
|
+
exit 1;
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
DIR_LIST_TO_COPY=('.vscode' 'src' 'tests')
|
|
10
|
+
FILE_LIST_TO_COPY=('.gitignore' '.prettierignore' '.prettierrc' 'task-runner' 'install-link.sh' 'eslint.config.ts' 'vitest.config.ts' 'package-lock.json' 'package.json' 'tsconfig.json')
|
|
11
|
+
NAME_REF_LIST=('package.json' 'package-lock.json' 'install-link.sh')
|
|
12
|
+
CWD=$(pwd)
|
|
13
|
+
SCRIPT_DIR=$(dirname "$0")
|
|
14
|
+
DESTINATION="$CWD/$1"
|
|
15
|
+
|
|
16
|
+
# ensure dest exists
|
|
17
|
+
if [ -f "$DESTINATION" ]; then
|
|
18
|
+
echo "Using destination: $DESTINATION"
|
|
19
|
+
else
|
|
20
|
+
echo "Creating destination directory: $DESTINATION"
|
|
21
|
+
mkdir -p "$DESTINATION"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# copy directories
|
|
25
|
+
for folder in "${DIR_LIST_TO_COPY[@]}"; do
|
|
26
|
+
echo "Running Copy/: cp -R $SCRIPT_DIR/$folder $DESTINATION/$folder"
|
|
27
|
+
cp -R "$SCRIPT_DIR/$folder" "$DESTINATION/$folder"
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
# copy files
|
|
31
|
+
for filename in "${FILE_LIST_TO_COPY[@]}"; do
|
|
32
|
+
echo "Running Copy: cp $SCRIPT_DIR/$filename $DESTINATION/$filename"
|
|
33
|
+
cp "$SCRIPT_DIR/$filename" "$DESTINATION/$filename"
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
# fix naming
|
|
37
|
+
for fileToEdit in "${NAME_REF_LIST[@]}"; do
|
|
38
|
+
dest="$DESTINATION/$fileToEdit"
|
|
39
|
+
replace_pattern="s/task-runner/$1/g"
|
|
40
|
+
echo "Running Patch: cat \"$dest\" | sed -i \"$replace_pattern\" "
|
|
41
|
+
output=$(cat "$dest" | sed "$replace_pattern")
|
|
42
|
+
echo "$output" > "$dest"
|
|
43
|
+
|
|
44
|
+
# echo "Running patch: sed -i \"s/task-runner/$1/g\" \"$DESTINATION/$fileToEdit\""
|
|
45
|
+
# sed -i "s/task-runner/$1/g" "$DESTINATION/$fileToEdit"
|
|
46
|
+
done
|
|
47
|
+
mv "$DESTINATION/task-runner" "$DESTINATION/$1"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# cd into destination and run git init
|
|
51
|
+
echo "initializing with git"
|
|
52
|
+
INITIALIZED=$(cd "$DESTINATION" && git init -b main)
|
|
53
|
+
|
|
54
|
+
echo;
|
|
55
|
+
echo " Try:"
|
|
56
|
+
echo " cd $DESTINATION && npm i && npm run dev"
|
|
57
|
+
echo;
|