UNPKG

9.73 kBPlain TextView Raw
1import {
2 Contributing,
3 Cyan,
4 CyanSafe,
5 Git,
6 Glob,
7 IAutoInquire,
8 IAutoMapper,
9 License
10} from "./classLibrary/TargetUtil/CyanResponse";
11import path from "path";
12import {IFileFactory, SimpleFileFactory} from "./classLibrary/RootFileFactory";
13import * as fs from "fs";
14import chalk, {Chalk} from "chalk";
15import rimraf from "rimraf";
16import {DocumentParser} from "./classLibrary/SpecialParser/DocumentParser";
17import {GlobFactory} from "./classLibrary/GlobFactory";
18import {ParsingStrategy} from "./classLibrary/ParsingStrategy/ParsingStrategy";
19import {GuidResolver} from "./classLibrary/ParsingStrategy/GuidResolver";
20import {IfElseResolver} from "./classLibrary/ParsingStrategy/IfElseResolver";
21import {InverseIfElseResolver} from "./classLibrary/ParsingStrategy/InverseIfElseResolver";
22import {InlineFlagResolver} from "./classLibrary/ParsingStrategy/InlineFlagResolver";
23import {InverseInlineFlagResolver} from "./classLibrary/ParsingStrategy/InverseInlineFlagResolver";
24import {VariableResolver} from "./classLibrary/ParsingStrategy/VariableResolver";
25import {MoveResolver} from "./classLibrary/ParsingStrategy/MoveResolver";
26import {PackageResolver} from "./classLibrary/ParsingStrategy/PackageResolver";
27import {Parser} from "./classLibrary/Parser";
28import {LicenseResolver} from "./classLibrary/SpecialParser/LicenseResolver";
29import {ContributingResolver} from "./classLibrary/SpecialParser/ContributingParser";
30import {FileSystemInstance} from "./classLibrary/File";
31import {FileWriter} from "./classLibrary/FileWriter";
32import {Execute} from "./classLibrary/TargetUtil/Execute";
33import {CyanParser} from "./classLibrary/SpecialParser/CyanParser";
34import inquirer, {Inquirer} from "inquirer";
35import {spawn} from "child_process";
36import {Dependency} from "./Depedency";
37
38
39export async function GenerateTemplate(dep: Dependency, templatePath: string, folderName: string, settings: CyanSafe, copyNode: boolean): Promise<string> {
40
41 //Generate baseline file fileFactory with To and From reading settled
42 let to: string = path.resolve(process.cwd(), folderName);
43 let fileFactory: IFileFactory = new SimpleFileFactory(dep.core, templatePath, to);
44
45 //Check if the target path is empty
46 if (fs.existsSync(to)) {
47 let del = await dep.autoInquirer.InquirePredicate("There is an existing folder " + chalk.yellowBright(folderName) + ", do you want do delete that folder and proceed?");
48 if (!del) return chalk.redBright("Template creation has been halted");
49 console.log(chalk.cyanBright("Please wait..."));
50 rimraf.sync(to);
51 console.log(chalk.greenBright("Deletion has been completed!"));
52 }
53
54 //Setup DocumentParser for future usage
55 let docParser: DocumentParser = new DocumentParser(settings.docs);
56
57
58 console.log(chalk.cyanBright("Preparing template, please wait..."));
59 //Setup GlobFactory to read streams
60 let globFactory: GlobFactory = new GlobFactory(dep.util, fileFactory);
61
62
63 //Create all relevant parsing strategy
64 let strategies: ParsingStrategy[] = [
65 new GuidResolver(dep.core),
66 new IfElseResolver(dep.util),
67 new InverseIfElseResolver(dep.util),
68 new InlineFlagResolver(dep.util, settings.comments),
69 new InverseInlineFlagResolver(dep.util, settings.comments),
70 new VariableResolver(dep.util),
71 new MoveResolver(dep.util),
72 new PackageResolver(dep.util)
73 ];
74
75 let parser: Parser = new Parser(dep.util, strategies, settings);
76
77 //Special Parsing Strategies
78 let licenseParser: LicenseResolver = new LicenseResolver(new VariableResolver(dep.util));
79 let contributingParser: ContributingResolver = new ContributingResolver(dep.core);
80
81 console.log(chalk.greenBright("Preparation done!"));
82 console.log(chalk.cyanBright("Performing variable and flag scans..."));
83
84
85 //Obtain all globs
86 let files: FileSystemInstance[] = settings.globs.Map((g: Glob) => globFactory.GenerateFiles(g.root, g.pattern, g.ignore)).Flatten();
87 if (!copyNode) files = files.Where((f: FileSystemInstance) => !f.sourceAbsolutePath.includes("node_modules"));
88
89 //remove package.lock
90 files = files.Where(f => f.sourceAbsolutePath.ReplaceAll("\\\\", "/").split("/").Last()! !== "package-lock.json")
91 .Where(f => f.sourceAbsolutePath.ReplaceAll("\\\\", "/").split("/").Last()! !== "yarn.lock");
92
93
94 //Add in the cyan.docs flag
95 settings.flags = dep.autoMapper.JoinObjects(settings.flags, docParser.GetAllFlags());
96 settings.variable = dep.autoMapper.JoinObjects(settings.variable, docParser.GetVariables());
97
98 //Set the folder name in
99 let fn: object = {cyan: {folder: {name: folderName.ReplaceAll("\\\\", "/").split("/").Last()!}}};
100 settings.variable = dep.autoMapper.JoinObjects(settings.variable, fn);
101
102 //Generate flag counting data structures
103 parser.CountFiles(files);
104
105 //files all the name that are removed before starting to read
106 files = parser.ParseFiles(files);
107
108 //Read file asynchronously
109 files = await globFactory.ReadFiles(files);
110
111 //Add license if document parser found one
112 let license: License | undefined = docParser.GetLicense();
113 if (license) files.push(licenseParser.ResolveLicense(license, path.resolve(to, "LICENSE.MD")));
114 //Add Contributing if found one
115 let contributing: Contributing | undefined = docParser.GetContributing();
116 if (contributing) files.push(contributingParser.ResolveContributing(contributing, path.resolve(to, "CONTRIBUTING.MD")));
117
118 let ok: boolean = parser.CountOccurence(files);
119
120 if (!ok) {
121 let answers: boolean = await dep.autoInquirer.InquirePredicate("There were variables missing from the template file, are you sure you want to continue?");
122 if (!answers) return "The template generation has been cancelled";
123 console.log(chalk.greenBright("Ignoring warning..."));
124 }
125
126 //Parse Templates
127 files = parser.ParseContent(files);
128
129 //Generate warning of possible code
130 parser.CountPossibleRemains(files);
131
132
133 console.log(chalk.cyanBright("Generating template..."));
134
135 //Asynchronous write to target directory
136 let writer: FileWriter = new FileWriter(dep.util);
137 await writer.AWriteFile(files);
138
139 if (settings.npm) {
140 console.log(chalk.cyanBright("Installing NPM modules"));
141 let reply = "";
142 let hasYarn = await ExecuteCommandSimple("yarn", ["-v"], "", true);
143 if (hasYarn) {
144 console.info(chalk.greenBright("Yarn Detected... Using yarn!"));
145 reply = await ExecuteCommand("yarn", ["--prefer-offline"], "Installed NPM Modules", folderName, settings.npm);
146 } else {
147 reply = await ExecuteCommand("npm", ["i"], "Installed NPM Modules", folderName, settings.npm);
148 }
149 console.log(reply);
150 }
151 let git: Git = docParser.GetGit()!;
152 if (git) {
153 await ExecuteCommandSimple("git", ["init"], folderName);
154 await ExecuteCommandSimple("git", ["config", "user.name", git.username], folderName);
155 await ExecuteCommandSimple("git", ["config", "user.email", git.email], folderName);
156 await ExecuteCommandSimple("git", ["rm", "-rf", "--cached", "."]);
157 await ExecuteCommandSimple("git", ["add", "."], folderName);
158 let reply = await ExecuteCommand("git", ["commit", "-m", '"Initial Commit~"'], "Initialized Git repository!", folderName);
159 console.log(reply);
160
161 if (git.remote != null) {
162 let useRemote: boolean = await dep.autoInquirer.InquirePredicate("Do you want to set your remote 'origin' to " + chalk.yellowBright(git.remote) + " and immediately push to origin?");
163 if (useRemote) {
164 await ExecuteCommandSimple("git", ["remote", "add", "origin", git.remote], folderName);
165 let reply: string = await ExecuteCommand("git", ["push", "origin", "--all"], "Added and pushed to remote repository", folderName);
166 console.log(reply);
167 }
168 }
169 }
170 return chalk.greenBright("Complete~!!");
171}
172
173// Executes the cyan.config.js
174export async function Interrogate(dep: Dependency, autoInquirer: IAutoInquire, templatePath: string, folderName: string): Promise<CyanSafe> {
175 //Gets relative path to configure file of the selected template
176 let configFile = path.resolve(templatePath, "./cyan.config.js");
177 let relConfigPath: string = path.relative(__dirname, configFile);
178
179 let execute: Execute = new Execute(dep.core, folderName, __dirname, configFile, autoInquirer, dep.autoMapper);
180 let cyanSafe: CyanParser = new CyanParser();
181
182 //Get Template generating functions
183 let Template: (nameFolder: string, c: Chalk, inq: Inquirer, autoInquire: IAutoInquire, autoMap: IAutoMapper, execute: Execute) => Promise<Cyan>
184 = eval(`require("${relConfigPath.ReplaceAll("\\\\", "/")}")`);
185 let rawSettings: Cyan = await Template(folderName.ReplaceAll("\\\\", "/").split('/').Last()!, chalk, inquirer, autoInquirer, dep.autoMapper, execute);
186 // Escape and normalize raw settings to "safe"
187 return cyanSafe.Save(rawSettings);
188}
189
190export async function ExecuteCommandSimple(command: string, variables: string[], cd?: string, ignore: boolean = false): Promise<boolean> {
191 let p = cd != null ? path.resolve(process.cwd(), cd) : process.cwd();
192
193 console.log(p);
194 return await new Promise<boolean>(function (resolve) {
195 spawn(command, variables, {
196 stdio: ignore ? "ignore" : "inherit",
197 shell: true,
198 cwd: p
199 })
200 .on("exit", (code: number) => {
201 console.info(`${command} ${variables.join(' ')} ${cd ? 'at ' + cd : ''} with code ${code}`);
202 if (code === 0) {
203 resolve(true);
204 } else {
205 resolve(false);
206 }
207 })
208 .on("error", err => console.info(err));
209 });
210}
211
212async function ExecuteCommand(command: string, variables: string[], done: string, cd?: string, cdExt?: string): Promise<string> {
213 cdExt = cdExt || ".";
214 let p = cd != null ? path.resolve(process.cwd(), cd, cdExt) : process.cwd();
215 return await new Promise<string>(function (resolve: (s: string) => void) {
216 spawn(command, variables, {stdio: "inherit", shell: true, cwd: p})
217 .on("exit", () => {
218 resolve(chalk.greenBright(done));
219 });
220 });
221}
222
\No newline at end of file