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
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ UtilService.initializeDependencies();
|
|
|
13
13
|
|
|
14
14
|
import { AboutCommand } from "./commands/about";
|
|
15
15
|
import { GenCommand } from "./commands/gen";
|
|
16
|
+
import { NewCommand } from "./commands/new";
|
|
16
17
|
|
|
17
18
|
const { program } = commander;
|
|
18
19
|
const name = UtilService.getAppName();
|
|
@@ -35,4 +36,10 @@ program
|
|
|
35
36
|
.option("-t, --task", "Generate a task")
|
|
36
37
|
.action(container.resolve(GenCommand).handler);
|
|
37
38
|
|
|
39
|
+
program
|
|
40
|
+
.command("new")
|
|
41
|
+
.option("-n, --name <name>", "Name of the New Project")
|
|
42
|
+
// .option("-d, --dest", "target destination path")
|
|
43
|
+
.action(container.resolve(NewCommand).handler);
|
|
44
|
+
|
|
38
45
|
program.parse(process.argv);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import nodePersist from "node-persist";
|
|
2
|
+
import { singleton } from "tsyringe";
|
|
3
|
+
import { ProjectConfig } from "../types/project";
|
|
4
|
+
import _ from "lodash";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { LogService } from "./log-service";
|
|
7
|
+
import path from "path";
|
|
8
|
+
|
|
9
|
+
@singleton()
|
|
10
|
+
export class CacheService {
|
|
11
|
+
private storageInitialized = false;
|
|
12
|
+
constructor(private logger: LogService) {
|
|
13
|
+
logger.setPrefix(`${this.constructor.name} :: `);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async initialize() {
|
|
17
|
+
if (this.storageInitialized) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const appDataFolder =
|
|
21
|
+
process.env.APPDATA ||
|
|
22
|
+
(process.platform === "darwin"
|
|
23
|
+
? `${process.env.HOME}/Library/Preferences`
|
|
24
|
+
: `${process.env.HOME}/.config`);
|
|
25
|
+
|
|
26
|
+
const location = path.join(appDataFolder, "tssc");
|
|
27
|
+
this.logger.debug(chalk.dim(`Using cache: ${location}`));
|
|
28
|
+
|
|
29
|
+
await nodePersist.init({ dir: location });
|
|
30
|
+
this.storageInitialized = true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async getProject(rootDir: string): Promise<ProjectConfig | null> {
|
|
34
|
+
await this.initialize();
|
|
35
|
+
const project = await nodePersist.getItem(rootDir);
|
|
36
|
+
return project;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async writeProject(project: ProjectConfig): Promise<void> {
|
|
40
|
+
await this.initialize();
|
|
41
|
+
const projectKeys: (keyof ProjectConfig)[] = [
|
|
42
|
+
"rootDir",
|
|
43
|
+
"taskDestination",
|
|
44
|
+
"serviceDestination",
|
|
45
|
+
"commandDestination",
|
|
46
|
+
];
|
|
47
|
+
const cleanedProject: ProjectConfig = _.pick(project, projectKeys);
|
|
48
|
+
await nodePersist.setItem(project.rootDir, cleanedProject);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -6,11 +6,28 @@ import { singleton } from "tsyringe";
|
|
|
6
6
|
const ignoredDirectories = new Set(["node_modules", "dist"]);
|
|
7
7
|
|
|
8
8
|
@singleton()
|
|
9
|
-
export
|
|
9
|
+
export class FileService {
|
|
10
10
|
getRunnerDir(): string {
|
|
11
11
|
return process.cwd();
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
join(path1: string, path2: string) {
|
|
15
|
+
return path.join(path1, path2);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
toRelativePath(fromPath: string, toPath: string) {
|
|
19
|
+
return path.relative(fromPath, toPath);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
toFullPath(relativePath: string) {
|
|
23
|
+
return path.resolve(relativePath);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getFilenameNoExt(somePath: string) {
|
|
27
|
+
const filename = path.basename(somePath);
|
|
28
|
+
return filename.includes(".") ? filename.split(".")[0] || "" : filename;
|
|
29
|
+
}
|
|
30
|
+
|
|
14
31
|
getFilesInDir(dirPath: string): string[] {
|
|
15
32
|
if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) {
|
|
16
33
|
throw new Error(`Directory not found: ${dirPath}`);
|
|
@@ -18,7 +18,12 @@ export class LogService {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
setPrefix(prefix: string) {
|
|
21
|
-
|
|
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
|
+
}
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
public info(msg: string, obj?: unknown): void {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { autoInjectable } from "tsyringe";
|
|
2
|
-
import FileService from "./file-service";
|
|
2
|
+
import { FileService } from "./file-service";
|
|
3
3
|
import { CaseType } from "../types/format";
|
|
4
4
|
import { UtilService } from "./util-service";
|
|
5
5
|
|
|
6
6
|
@autoInjectable()
|
|
7
|
-
export
|
|
7
|
+
export class ProjectService {
|
|
8
8
|
static defaults = {
|
|
9
9
|
targetName: "Foo-Bar-Baz",
|
|
10
10
|
sampleFile: "test-file.ts",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { autoInjectable } from "tsyringe";
|
|
2
|
+
import { UtilService } from "./util-service";
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
5
|
+
const { search, input, checkbox } = require("@inquirer/prompts");
|
|
6
|
+
|
|
7
|
+
@autoInjectable()
|
|
8
|
+
export class PromptService {
|
|
9
|
+
constructor(private utilService: UtilService) {}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Select an option from a list of choices. Allows search filtering.
|
|
13
|
+
* See: https://github.com/SBoudrias/Inquirer.js/tree/main/packages/search
|
|
14
|
+
*
|
|
15
|
+
* @param message the message to prompt (question to ask).
|
|
16
|
+
* @param options the selectable choices to search / choose from.
|
|
17
|
+
* @returns the selected choice value
|
|
18
|
+
*/
|
|
19
|
+
async select(message: string, options: string[]) {
|
|
20
|
+
// wait for logging to catch up before prompting
|
|
21
|
+
await this.utilService.sleep(200);
|
|
22
|
+
|
|
23
|
+
const choices = options.map((opt) => ({ value: opt }));
|
|
24
|
+
|
|
25
|
+
const answer = await search({
|
|
26
|
+
message,
|
|
27
|
+
source: async (input: string | void) => {
|
|
28
|
+
if (!input) {
|
|
29
|
+
return choices;
|
|
30
|
+
}
|
|
31
|
+
return choices.filter((c) =>
|
|
32
|
+
c.value.toLowerCase().includes(input.toLowerCase()),
|
|
33
|
+
);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return answer;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async getInput(message: string, required: boolean = true) {
|
|
41
|
+
return await input({ message, required });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Prompt with multi-select options returning the array of selections.
|
|
46
|
+
*
|
|
47
|
+
* @param message the message string to prompt with.
|
|
48
|
+
* @param options the options to choose from.
|
|
49
|
+
* @returns the selected optoins array
|
|
50
|
+
*/
|
|
51
|
+
async pickMultiple<T>(
|
|
52
|
+
message: string,
|
|
53
|
+
options: { name: string; value: T }[],
|
|
54
|
+
): Promise<T[]> {
|
|
55
|
+
return await checkbox({
|
|
56
|
+
message,
|
|
57
|
+
choices: options,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -4,6 +4,15 @@ import { singleton } from "tsyringe";
|
|
|
4
4
|
|
|
5
5
|
@singleton()
|
|
6
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
|
+
|
|
7
16
|
execSync(command: string) {
|
|
8
17
|
try {
|
|
9
18
|
return childProcess.execSync(command).toString();
|
|
@@ -15,7 +24,12 @@ export class SpawnService {
|
|
|
15
24
|
|
|
16
25
|
exec(command: string) {
|
|
17
26
|
try {
|
|
18
|
-
return
|
|
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
|
+
});
|
|
19
33
|
} catch (error) {
|
|
20
34
|
console.error(`Error executing command: ${command}`, error);
|
|
21
35
|
throw error;
|
package/src/tasks/check-env.ts
CHANGED
|
@@ -2,7 +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 FileService from "../services/file-service";
|
|
5
|
+
import { FileService } from "../services/file-service";
|
|
6
6
|
import path from "path";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -20,6 +20,7 @@ export default class CheckEnvironment extends AppTask {
|
|
|
20
20
|
EnvironmentConfigKeys.PINO_LOG_DIR_PATH,
|
|
21
21
|
EnvironmentConfigKeys.PINO_LOG_FILENAME,
|
|
22
22
|
EnvironmentConfigKeys.PINO_LOG_LEVEL,
|
|
23
|
+
EnvironmentConfigKeys.TSSC_SILENCE_BANNER,
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
constructor(private fileService: FileService) {
|
|
@@ -48,7 +49,8 @@ export default class CheckEnvironment extends AppTask {
|
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
51
|
* Check for the folders we need to generate files in. Add errors
|
|
51
|
-
* when no target directories can be found.
|
|
52
|
+
* when no target directories can be found. Saves project data to
|
|
53
|
+
* state so we don't have to refetch it later.
|
|
52
54
|
*
|
|
53
55
|
* @param projectDir the target project root directory path
|
|
54
56
|
* @param errors string array error messages are added to
|
|
@@ -65,6 +67,12 @@ export default class CheckEnvironment extends AppTask {
|
|
|
65
67
|
errors.push(`Unable to find any ${k} in project`);
|
|
66
68
|
}
|
|
67
69
|
});
|
|
70
|
+
this.setData({
|
|
71
|
+
project: {
|
|
72
|
+
rootDir: projectDir,
|
|
73
|
+
...directories,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
/**
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { SpawnService } from "../services/spawn-service";
|
|
2
|
+
import { FileService } from "../services/file-service";
|
|
3
|
+
import { PromptService } from "../services/prompt-service";
|
|
4
|
+
import { CLIOptions } from "../types/process";
|
|
5
|
+
import { AppTask } from "../wrappers/app-task";
|
|
6
|
+
import { autoInjectable } from "tsyringe";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CreateNewProject
|
|
10
|
+
*/
|
|
11
|
+
@autoInjectable()
|
|
12
|
+
export default class CreateNewProject extends AppTask {
|
|
13
|
+
loggerName = "Create New Project";
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
private fileService: FileService,
|
|
17
|
+
private spawnService: SpawnService,
|
|
18
|
+
private promptService: PromptService,
|
|
19
|
+
) {
|
|
20
|
+
super();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generates a new project. Updates state with outputDestination of the
|
|
25
|
+
* newly generated project path.
|
|
26
|
+
*/
|
|
27
|
+
async run() {
|
|
28
|
+
// get path of the templater
|
|
29
|
+
const templaterFullPath = this.fileService.join(
|
|
30
|
+
__dirname,
|
|
31
|
+
"../../assets/yargs-template/task-runner/templater.sh",
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// get execution directory
|
|
35
|
+
const runnerDir = this.fileService.getRunnerDir();
|
|
36
|
+
|
|
37
|
+
// get project name user input
|
|
38
|
+
const projectName: string = await this.getProjectName();
|
|
39
|
+
|
|
40
|
+
// execute the templater from the runner directory and provide given name
|
|
41
|
+
const shCmd = `bash ${templaterFullPath} ${projectName}`;
|
|
42
|
+
this.spawnService.execSyncFromDir(shCmd, runnerDir);
|
|
43
|
+
|
|
44
|
+
this.setData({
|
|
45
|
+
outputDestination: this.fileService.join(runnerDir, projectName),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolves the project name input from args or prompt.
|
|
51
|
+
*
|
|
52
|
+
* @returns the project name string
|
|
53
|
+
*/
|
|
54
|
+
async getProjectName(): Promise<string> {
|
|
55
|
+
let projectName: string;
|
|
56
|
+
if (this.argService.hasFlag(CLIOptions.name)) {
|
|
57
|
+
projectName = this.argService.getOption<string>(CLIOptions.name);
|
|
58
|
+
} else {
|
|
59
|
+
projectName = await this.promptService.getInput("Enter Project Name");
|
|
60
|
+
}
|
|
61
|
+
if (!projectName) {
|
|
62
|
+
throw new Error("Unable to resolve projectName");
|
|
63
|
+
}
|
|
64
|
+
return projectName;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -2,12 +2,13 @@ import chalk from "chalk";
|
|
|
2
2
|
import { AppTask } from "../wrappers/app-task";
|
|
3
3
|
import { autoInjectable } from "tsyringe";
|
|
4
4
|
import { AppState, GenTargetType } from "../types/state";
|
|
5
|
-
import FileService from "../services/file-service";
|
|
5
|
+
import { FileService } from "../services/file-service";
|
|
6
6
|
import { UtilService } from "../services/util-service";
|
|
7
7
|
import { CaseType } from "../types/format";
|
|
8
8
|
import path from "path";
|
|
9
9
|
import { getCommandTemplate } from "../templates/command";
|
|
10
|
-
import ProjectService from "../services/project-service";
|
|
10
|
+
import { ProjectService } from "../services/project-service";
|
|
11
|
+
import { PromptService } from "../services/prompt-service";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Generates a new command class
|
|
@@ -20,47 +21,40 @@ export default class GenerateCommand extends AppTask {
|
|
|
20
21
|
private fileService: FileService,
|
|
21
22
|
private utilService: UtilService,
|
|
22
23
|
private projectService: ProjectService,
|
|
24
|
+
private promptService: PromptService,
|
|
23
25
|
) {
|
|
24
26
|
super();
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Generates a new command class file.
|
|
31
|
+
*
|
|
32
|
+
* @returns updated state with outputDestination set to generated result path.
|
|
33
|
+
*/
|
|
27
34
|
async run(): Promise<void | Partial<AppState>> {
|
|
28
|
-
const { utilService, fileService,
|
|
35
|
+
const { utilService, fileService, projectService } = this;
|
|
29
36
|
|
|
30
37
|
if (this.state.data.genTargetType !== GenTargetType.Command) {
|
|
31
|
-
return;
|
|
38
|
+
return; // no-op
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
this.logger.info(chalk.blueBright("Generating Command"));
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!targetName) {
|
|
38
|
-
// TODO: Should we prompt for target name here?
|
|
39
|
-
targetName = argService.cleanTargetName(
|
|
40
|
-
ProjectService.defaults.targetName,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const targetDirectory = this.getTargetDirectory();
|
|
45
|
-
if (!targetDirectory) {
|
|
46
|
-
throw new Error("Unable to determine target Directory");
|
|
47
|
-
}
|
|
42
|
+
const targetName = this.state.data.genTargetName!;
|
|
43
|
+
const targetDirectory = this.state.data.project!.commandDestination!;
|
|
48
44
|
|
|
49
45
|
// detect case between commands and task files
|
|
50
|
-
const taskFiles = projectService.getTaskFiles();
|
|
51
46
|
const convention = projectService.getConvention();
|
|
52
47
|
this.logger.debug(`Using convention: ${chalk.magentaBright(convention)}`);
|
|
53
48
|
|
|
54
|
-
this.logger.debug(`Found ${taskFiles.length} task files`);
|
|
55
49
|
const className = utilService.titleizedToCase(
|
|
56
50
|
targetName,
|
|
57
51
|
CaseType.PASCAL_CASE,
|
|
58
52
|
);
|
|
59
|
-
|
|
60
|
-
const taskMappings = new Map();
|
|
53
|
+
const filename = `${utilService.titleizedToCase(targetName, convention)}${ProjectService.defaults.extention}`;
|
|
61
54
|
|
|
55
|
+
const taskMappings = new Map();
|
|
56
|
+
await this.addTasksToMap(taskMappings);
|
|
62
57
|
const rendered = getCommandTemplate(className, taskMappings);
|
|
63
|
-
const filename = `${utilService.titleizedToCase(targetName, convention)}${ProjectService.defaults.extention}`;
|
|
64
58
|
const destination = path.join(targetDirectory, filename);
|
|
65
59
|
|
|
66
60
|
// write contents
|
|
@@ -69,19 +63,78 @@ export default class GenerateCommand extends AppTask {
|
|
|
69
63
|
}
|
|
70
64
|
|
|
71
65
|
/**
|
|
72
|
-
*
|
|
66
|
+
* Checks state for required fields. Executes prior to run method.
|
|
67
|
+
* Skips validation if genTargetType is not set to command.
|
|
68
|
+
*/
|
|
69
|
+
async preRun() {
|
|
70
|
+
if (this.state.data.genTargetType !== GenTargetType.Command) {
|
|
71
|
+
return; // no validation on no-op flow
|
|
72
|
+
}
|
|
73
|
+
if (!this.state.data.genTargetName) {
|
|
74
|
+
throw new Error("Unable to determine targetName");
|
|
75
|
+
}
|
|
76
|
+
if (!this.state.data.project) {
|
|
77
|
+
throw new Error("Unable to determine project");
|
|
78
|
+
}
|
|
79
|
+
if (!this.state.data.project.commandDestination) {
|
|
80
|
+
throw new Error("Unable to determine targetDirectory");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Prompt to select tasks to use in the command being generated.
|
|
73
86
|
*
|
|
74
|
-
* @
|
|
87
|
+
* @param taskMappings the map to add picked tasks to import for the command
|
|
75
88
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
async addTasksToMap(taskMappings: Map<string, string>) {
|
|
90
|
+
if (!this.state.data.project?.taskDestination) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const taskFiles = this.fileService.getFilesInDir(
|
|
95
|
+
this.state.data.project.taskDestination,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
this.logger.debug(`Found ${taskFiles.length} task files`);
|
|
99
|
+
|
|
100
|
+
// prompt for tasks to use in the new command
|
|
101
|
+
const pickedTasks = await this.promptService.pickMultiple(
|
|
102
|
+
"Include Tasks",
|
|
103
|
+
taskFiles.map((tf) => ({
|
|
104
|
+
name: this.utilService.titleizedToCase(
|
|
105
|
+
this.utilService.titleizeAll(this.fileService.getFilenameNoExt(tf)),
|
|
106
|
+
CaseType.PASCAL_CASE,
|
|
107
|
+
),
|
|
108
|
+
value: tf,
|
|
109
|
+
})),
|
|
110
|
+
);
|
|
79
111
|
|
|
80
|
-
|
|
81
|
-
|
|
112
|
+
this.logger.debug(`Selected ${pickedTasks.length} tasks`);
|
|
113
|
+
if (!pickedTasks.length) {
|
|
114
|
+
return;
|
|
82
115
|
}
|
|
83
116
|
|
|
84
|
-
|
|
85
|
-
|
|
117
|
+
console.log(JSON.stringify(pickedTasks));
|
|
118
|
+
|
|
119
|
+
// add them to the map
|
|
120
|
+
for (const picked of pickedTasks) {
|
|
121
|
+
const filename = this.fileService.getFilenameNoExt(picked);
|
|
122
|
+
const taskClassName = this.utilService.titleizedToCase(
|
|
123
|
+
this.utilService.titleizeAll(filename),
|
|
124
|
+
CaseType.PASCAL_CASE,
|
|
125
|
+
);
|
|
126
|
+
const relativeSource = this.state.data.project!.commandDestination!;
|
|
127
|
+
const relativeDest = this.fileService.join(
|
|
128
|
+
this.state.data.project.taskDestination,
|
|
129
|
+
picked,
|
|
130
|
+
);
|
|
131
|
+
taskMappings.set(
|
|
132
|
+
taskClassName,
|
|
133
|
+
this.fileService
|
|
134
|
+
.toRelativePath(relativeSource, relativeDest)
|
|
135
|
+
// remove extension for typescript import
|
|
136
|
+
.replace(ProjectService.defaults.extention, ""),
|
|
137
|
+
);
|
|
138
|
+
}
|
|
86
139
|
}
|
|
87
140
|
}
|
|
@@ -2,9 +2,9 @@ import chalk from "chalk";
|
|
|
2
2
|
import { AppTask } from "../wrappers/app-task";
|
|
3
3
|
import { autoInjectable } from "tsyringe";
|
|
4
4
|
import { GenTargetType } from "../types/state";
|
|
5
|
-
import ProjectService from "../services/project-service";
|
|
5
|
+
import { ProjectService } from "../services/project-service";
|
|
6
6
|
import { UtilService } from "../services/util-service";
|
|
7
|
-
import FileService from "../services/file-service";
|
|
7
|
+
import { FileService } from "../services/file-service";
|
|
8
8
|
import { CaseType } from "../types/format";
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { getServiceTemplate } from "../templates/service";
|
|
@@ -24,26 +24,21 @@ export default class GenerateService extends AppTask {
|
|
|
24
24
|
super();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Generates a new service class file.
|
|
29
|
+
*
|
|
30
|
+
* @returns updated state with outputDestination set to generated result path.
|
|
31
|
+
*/
|
|
27
32
|
async run() {
|
|
28
33
|
if (this.state.data.genTargetType !== GenTargetType.Service) {
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
this.logger.info(chalk.blueBright("Generating Service"));
|
|
33
|
-
const {
|
|
38
|
+
const { utilService, projectService } = this;
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// TODO: Prompt for target name?
|
|
38
|
-
targetName = argService.cleanTargetName(
|
|
39
|
-
ProjectService.defaults.targetName,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const targetDirectory = this.getTargetDirectory();
|
|
44
|
-
if (!targetDirectory) {
|
|
45
|
-
throw new Error("Unable to determine target Directory");
|
|
46
|
-
}
|
|
40
|
+
const targetName = this.state.data.genTargetName!;
|
|
41
|
+
const targetDirectory = this.state.data.project!.serviceDestination!;
|
|
47
42
|
|
|
48
43
|
// detect case
|
|
49
44
|
const convention = projectService.getConvention();
|
|
@@ -63,20 +58,21 @@ export default class GenerateService extends AppTask {
|
|
|
63
58
|
}
|
|
64
59
|
|
|
65
60
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* @returns the destination path of the parent folder to save the new file in.
|
|
61
|
+
* Checks state for required fields. Executes prior to run method.
|
|
62
|
+
* Skips validation if genTargetType is not set to service.
|
|
69
63
|
*/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
64
|
+
async preRun() {
|
|
65
|
+
if (this.state.data.genTargetType !== GenTargetType.Service) {
|
|
66
|
+
return; // no validation on no-op flow
|
|
67
|
+
}
|
|
68
|
+
if (!this.state.data.genTargetName) {
|
|
69
|
+
throw new Error("Unable to determine targetName");
|
|
70
|
+
}
|
|
71
|
+
if (!this.state.data.project) {
|
|
72
|
+
throw new Error("Unable to determine project");
|
|
73
|
+
}
|
|
74
|
+
if (!this.state.data.project.serviceDestination) {
|
|
75
|
+
throw new Error("Unable to determine targetDirectory");
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
// TODO: prompt to select destination from available servicesFolders
|
|
79
|
-
this.logger.warn(`Multiple service folders detected. Using first found.`);
|
|
80
|
-
return servicesFolders[0];
|
|
81
77
|
}
|
|
82
78
|
}
|
|
@@ -5,8 +5,8 @@ import { GenTargetType } from "../types/state";
|
|
|
5
5
|
import { getTaskTemplate } from "../templates/task";
|
|
6
6
|
import { CaseType } from "../types/format";
|
|
7
7
|
import { UtilService } from "../services/util-service";
|
|
8
|
-
import FileService from "../services/file-service";
|
|
9
|
-
import ProjectService from "../services/project-service";
|
|
8
|
+
import { FileService } from "../services/file-service";
|
|
9
|
+
import { ProjectService } from "../services/project-service";
|
|
10
10
|
import path from "path";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -24,27 +24,22 @@ export default class GenerateTask extends AppTask {
|
|
|
24
24
|
super();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Generates a new task class file.
|
|
29
|
+
*
|
|
30
|
+
* @returns updated state with outputDestination set to generated result path.
|
|
31
|
+
*/
|
|
27
32
|
async run() {
|
|
28
33
|
if (this.state.data.genTargetType !== GenTargetType.Task) {
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
|
|
32
|
-
const { utilService
|
|
37
|
+
const { utilService } = this;
|
|
33
38
|
|
|
34
39
|
this.logger.info(chalk.blueBright("Generating Task"));
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// TODO: Prompt for target name?
|
|
39
|
-
targetName = argService.cleanTargetName(
|
|
40
|
-
ProjectService.defaults.targetName,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const targetDirectory = this.getTargetDirectory();
|
|
45
|
-
if (!targetDirectory) {
|
|
46
|
-
throw new Error("Unable to determine target Directory");
|
|
47
|
-
}
|
|
41
|
+
const targetName = this.state.data.genTargetName!;
|
|
42
|
+
const targetDirectory = this.state.data.project!.taskDestination!;
|
|
48
43
|
|
|
49
44
|
// detect case
|
|
50
45
|
const convention = this.projectService.getConvention();
|
|
@@ -64,20 +59,21 @@ export default class GenerateTask extends AppTask {
|
|
|
64
59
|
}
|
|
65
60
|
|
|
66
61
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @returns the destination path of the parent folder to save the new file in.
|
|
62
|
+
* Checks state for required fields. Executes prior to run method.
|
|
63
|
+
* Skips validation if genTargetType is not set to task.
|
|
70
64
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
65
|
+
async preRun() {
|
|
66
|
+
if (this.state.data.genTargetType !== GenTargetType.Task) {
|
|
67
|
+
return; // no validation on no-op flow
|
|
68
|
+
}
|
|
69
|
+
if (!this.state.data.genTargetName) {
|
|
70
|
+
throw new Error("Unable to determine targetName");
|
|
71
|
+
}
|
|
72
|
+
if (!this.state.data.project) {
|
|
73
|
+
throw new Error("Unable to determine project");
|
|
74
|
+
}
|
|
75
|
+
if (!this.state.data.project.taskDestination) {
|
|
76
|
+
throw new Error("Unable to determine targetDirectory");
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
// TODO: prompt to select destination from available tasksFolders
|
|
80
|
-
this.logger.warn(`Multiple task folders detected. Using first found.`);
|
|
81
|
-
return tasksFolders[0];
|
|
82
78
|
}
|
|
83
79
|
}
|