@outwalk/create-firefly 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +58 -0
  2. package/dist/index.js +243 -0
  3. package/package.json +57 -0
  4. package/templates/javascript/.gitignore.template +49 -0
  5. package/templates/javascript/jsconfig.json.template +11 -0
  6. package/templates/javascript/package.json.template +14 -0
  7. package/templates/javascript/src/app/app.controller.js.template +12 -0
  8. package/templates/javascript/src/app/app.service.js.template +9 -0
  9. package/templates/javascript/src/index.js.template +10 -0
  10. package/templates/snippets/custom-database/javascript/define-database.template +7 -0
  11. package/templates/snippets/custom-database/javascript/import-database.template +1 -0
  12. package/templates/snippets/custom-database/typescript/define-database.template +7 -0
  13. package/templates/snippets/custom-database/typescript/import-database.template +1 -0
  14. package/templates/snippets/custom-platform/javascript/define-platform.template +11 -0
  15. package/templates/snippets/custom-platform/javascript/import-platform.template +1 -0
  16. package/templates/snippets/custom-platform/typescript/define-platform.template +11 -0
  17. package/templates/snippets/custom-platform/typescript/import-platform.template +1 -0
  18. package/templates/snippets/express/define-platform.template +2 -0
  19. package/templates/snippets/express/import-platform.template +1 -0
  20. package/templates/snippets/mongoose/define-database.template +2 -0
  21. package/templates/snippets/mongoose/import-database.template +1 -0
  22. package/templates/typescript/.gitignore.template +49 -0
  23. package/templates/typescript/package.json.template +14 -0
  24. package/templates/typescript/src/app/app.controller.ts.template +14 -0
  25. package/templates/typescript/src/app/app.service.ts.template +9 -0
  26. package/templates/typescript/src/index.ts.template +10 -0
  27. package/templates/typescript/tsconfig.json.template +11 -0
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @outwalk/create-firefly
2
+
3
+ A scaffolding tool for creating Firefly projects.
4
+
5
+ ![Actions](https://github.com/OutwalkStudios/firefly/workflows/build/badge.svg)
6
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/OutwalkStudios/firefly/blob/main/LICENSE)
7
+ [![Follow Us](https://img.shields.io/badge/follow-on%20twitter-4AA1EC.svg)](https://twitter.com/OutwalkStudios)
8
+
9
+ ---
10
+
11
+ ## Usage
12
+
13
+ Create a Firefly project by running the following command and then follow the prompts.
14
+
15
+ ```
16
+ npm create @outwalk/firefly
17
+ ```
18
+
19
+ You can also specify settings via command line options.
20
+
21
+ ```
22
+ npm create @outwalk/firefly my-app --language typescript
23
+ ```
24
+
25
+ ### Command Line Options.
26
+
27
+ The first argument passed to the command will be used as the project name/directory, Other settings can be configured using the following command line options:
28
+
29
+ ```
30
+ # Specify the language
31
+ -l, --language
32
+
33
+ # Specify the platform
34
+ -p, --platform
35
+
36
+ # Specify the database
37
+ -d, --database
38
+
39
+ # Prevent automatic dependency installation
40
+ --skip-install
41
+
42
+ # Prevent initilizing a new git repository
43
+ --skip-git
44
+
45
+ # Ignore any warnings (dangerous)
46
+ --force
47
+ ```
48
+ ---
49
+
50
+ ## Reporting Issues
51
+
52
+ If you are having trouble getting something to work with Firefly or run into any problems, you can create a new [issue](https://github.com/OutwalkStudios/firefly/issues).
53
+
54
+ ---
55
+
56
+ ## License
57
+
58
+ Firefly is licensed under the terms of the [**MIT**](https://github.com/OutwalkStudios/firefly/blob/main/LICENSE) license.
package/dist/index.js ADDED
@@ -0,0 +1,243 @@
1
+ 'use strict';
2
+
3
+ var yargs = require('yargs-parser');
4
+ var prompts = require('prompts');
5
+ var chalk = require('chalk');
6
+ var path = require('path');
7
+ var fs = require('fs');
8
+ var child_process = require('child_process');
9
+
10
+ class TemplateBuilder {
11
+ constructor(src, dest) {
12
+ this.src = src;
13
+ this.dest = dest;
14
+ this.values = {};
15
+ }
16
+ inject(marker, value) {
17
+ this.values[marker] = value;
18
+ return this;
19
+ }
20
+ snippet(marker, snippet) {
21
+ this.values[marker] = fs.readFileSync(snippet, "utf8");
22
+ return this;
23
+ }
24
+ build() {
25
+ TemplateBuilder.createDirectory(this.dest);
26
+ TemplateBuilder.copyTemplate(this.src, this.dest, this.values);
27
+ return this;
28
+ }
29
+ /* create a directory */
30
+ static createDirectory(directory) {
31
+ if (!fs.existsSync(directory)) {
32
+ fs.mkdirSync(directory, { recursive: true });
33
+ }
34
+ }
35
+ /* deletes a directory and all subdirectories and files */
36
+ static deleteDirectory(directory) {
37
+ if (fs.existsSync(directory)) {
38
+ const files = fs.readdirSync(directory);
39
+ for (let file of files) {
40
+ const filepath = path.join(directory, file);
41
+ if (fs.statSync(filepath).isDirectory()) {
42
+ TemplateBuilder.deleteDirectory(filepath);
43
+ } else {
44
+ fs.unlinkSync(filepath);
45
+ }
46
+ }
47
+ fs.rmdirSync(directory);
48
+ }
49
+ }
50
+ /* copy a template and apply dynamic values to template markers */
51
+ static copyTemplate(src, dest, values) {
52
+ const filesToCreate = fs.readdirSync(src);
53
+ const render = (content) => {
54
+ const keys = Object.keys(values);
55
+ for (let key of keys) {
56
+ content = content.replace(new RegExp(`{{${key}}}`, "g"), values[key]);
57
+ }
58
+ return content;
59
+ };
60
+ for (let file of filesToCreate) {
61
+ const originalPath = path.join(src, file);
62
+ if (file.endsWith(".template")) {
63
+ file = file.replace(/.template$/, "");
64
+ }
65
+ const newPath = path.join(dest, file);
66
+ const stats = fs.statSync(originalPath);
67
+ if (stats.isFile()) {
68
+ if (path.extname(originalPath) == ".template") {
69
+ fs.writeFileSync(newPath, render(fs.readFileSync(originalPath, "utf8")));
70
+ } else {
71
+ fs.writeFileSync(newPath, fs.readFileSync(originalPath));
72
+ }
73
+ } else if (stats.isDirectory()) {
74
+ TemplateBuilder.createDirectory(newPath);
75
+ TemplateBuilder.copyTemplate(originalPath, newPath, values);
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ const firefly$1 = chalk.hex("#ADFF2F");
82
+ function installDependencies(dependencies, directory) {
83
+ return new Promise((resolve, reject) => {
84
+ console.log(`${firefly$1("[firefly]")} - installing dependencies...`);
85
+ const command = /^win/.test(process.platform) ? "npm.cmd" : "npm";
86
+ const spawnProcess = (command2, args) => {
87
+ const { status, error } = child_process.spawnSync(command2, args, { cwd: directory, stdio: "ignore" });
88
+ if (status != 0)
89
+ throw new Error("failed to install project dependencies.");
90
+ if (error)
91
+ throw error;
92
+ };
93
+ try {
94
+ spawnProcess(command, ["install", "--save"].concat(dependencies));
95
+ resolve();
96
+ } catch (error) {
97
+ reject(error);
98
+ }
99
+ });
100
+ }
101
+ function intitializeGitRepository(directory) {
102
+ return new Promise((resolve, reject) => {
103
+ console.log(`${firefly$1("[firefly]")} - initializing git repository...`);
104
+ try {
105
+ child_process.exec("git init", { cwd: directory });
106
+ resolve();
107
+ } catch {
108
+ reject(new Error("failed to initialize the git repository."));
109
+ }
110
+ });
111
+ }
112
+
113
+ const firefly = chalk.hex("#ADFF2F");
114
+ const args = yargs(process.argv.slice(2));
115
+ prompts.override({
116
+ name: args._[0],
117
+ language: args.l ?? args.language,
118
+ platform: args.p ?? args.platform,
119
+ database: args.d ?? args.database
120
+ });
121
+ const questions = [
122
+ {
123
+ type: "text",
124
+ name: "name",
125
+ message: "Project name:",
126
+ validate: (name) => name != name.toLowerCase() ? "your project name must be lowercase." : true
127
+ },
128
+ {
129
+ type: "select",
130
+ name: "language",
131
+ message: "Select a language:",
132
+ choices: [
133
+ { title: "JavaScript", value: "javascript" },
134
+ { title: "TypeScript", value: "typescript" }
135
+ ]
136
+ },
137
+ {
138
+ type: "select",
139
+ name: "platform",
140
+ message: "Select a platform:",
141
+ choices: [
142
+ { title: "Express", value: "express" },
143
+ { title: "Custom", value: "custom-platform" }
144
+ ]
145
+ },
146
+ {
147
+ type: "select",
148
+ name: "database",
149
+ message: "Select a database:",
150
+ choices: [
151
+ { title: "Mongoose", value: "mongoose" },
152
+ { title: "Custom", value: "custom-database" },
153
+ { title: "None", value: "none" }
154
+ ]
155
+ }
156
+ ];
157
+ (async () => {
158
+ const config = await prompts(questions, { onCancel: () => process.exit() });
159
+ const skipInstall = args["skip-install"];
160
+ const skipGit = args["skip-git"];
161
+ const force = args["force"];
162
+ const settings = { useCurrentDirectory: false };
163
+ const dependencies = ["@outwalk/firefly"];
164
+ if (!["none", "custom-platform"].includes(config.platform)) {
165
+ dependencies.push(config.platform);
166
+ }
167
+ if (!["none", "custom-database"].includes(config.database)) {
168
+ dependencies.push(config.database);
169
+ }
170
+ if (config.name == ".") {
171
+ if (!force && fs.readdirSync(config.name).length > 0) {
172
+ const response = await prompts({
173
+ type: "confirm",
174
+ name: "continue",
175
+ message: "The current directory is not empty. Continue?",
176
+ initial: true
177
+ });
178
+ if (!response.continue)
179
+ return;
180
+ }
181
+ config.name = path.basename(process.cwd());
182
+ settings.useCurrentDirectory = true;
183
+ }
184
+ if (fs.existsSync(config.name)) {
185
+ if (force && !settings.useCurrentDirectory) {
186
+ TemplateBuilder.deleteDirectory(config.name);
187
+ } else {
188
+ console.error(`${chalk.red("[firefly]")} - ${config.name} already exists.`);
189
+ return;
190
+ }
191
+ }
192
+ console.log(`
193
+ ${firefly("[firefly]")} - creating ${config.name}...`);
194
+ const templatePath = path.join(__dirname, "../templates/", config.language);
195
+ const snippetPath = path.join(__dirname, "../templates/snippets");
196
+ const projectPath = !settings.useCurrentDirectory ? config.name : ".";
197
+ try {
198
+ const template = new TemplateBuilder(templatePath, projectPath);
199
+ template.inject("project-name", config.name);
200
+ template.inject("options", config.database != "none" ? "{ platform, database }" : "{ platform }");
201
+ if (config.platform.startsWith("custom")) {
202
+ template.snippet("import-platform", path.join(snippetPath, config.platform, config.language, "import-platform.template"));
203
+ template.snippet("define-platform", path.join(snippetPath, config.platform, config.language, "define-platform.template"));
204
+ } else {
205
+ template.snippet("import-platform", path.join(snippetPath, config.platform, "import-platform.template"));
206
+ template.snippet("define-platform", path.join(snippetPath, config.platform, "define-platform.template"));
207
+ }
208
+ if (config.database.startsWith("custom")) {
209
+ template.snippet("import-database", path.join(snippetPath, config.database, config.language, "import-database.template"));
210
+ template.snippet("define-database", path.join(snippetPath, config.database, config.language, "define-database.template"));
211
+ } else if (config.database != "none") {
212
+ template.snippet("import-database", path.join(snippetPath, config.database, "import-database.template"));
213
+ template.snippet("define-database", path.join(snippetPath, config.database, "define-database.template"));
214
+ } else {
215
+ template.inject("import-database", "");
216
+ template.inject("define-database", "");
217
+ }
218
+ template.build();
219
+ } catch (error) {
220
+ console.error(`${chalk.red("[firefly]")} - ${error.message}`);
221
+ return;
222
+ }
223
+ try {
224
+ if (!skipInstall)
225
+ await installDependencies(dependencies, projectPath);
226
+ if (!skipGit)
227
+ await intitializeGitRepository(projectPath);
228
+ } catch (error) {
229
+ console.error(`${chalk.red("[firefly]")} - ${error.message}`);
230
+ if (!settings.useCurrentDirectory)
231
+ TemplateBuilder.deleteDirectory(config.name);
232
+ return;
233
+ }
234
+ console.log("\n----------------------------------");
235
+ console.log("Get started with your new project!\n");
236
+ if (!settings.useCurrentDirectory) {
237
+ console.log(firefly(` > cd ./${path.relative(process.cwd(), config.name)} `));
238
+ }
239
+ if (skipInstall)
240
+ console.log(firefly(" > npm install"));
241
+ console.log(firefly(" > npm run dev"));
242
+ console.log("----------------------------------");
243
+ })();
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@outwalk/create-firefly",
3
+ "version": "0.1.0",
4
+ "description": "Firefly - a modern scalable web framework.",
5
+ "main": "dist/index.js",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "bin": {
13
+ "create-firefly": "dist/index.js"
14
+ },
15
+ "scripts": {
16
+ "build": "rollup -c",
17
+ "lint": "eslint src",
18
+ "prepublishOnly": "npm run lint && npm run build"
19
+ },
20
+ "keywords": [
21
+ "outwalk",
22
+ "express",
23
+ "decorators",
24
+ "mvc"
25
+ ],
26
+ "files": [
27
+ "dist",
28
+ "templates"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/OutwalkStudios/firefly.git",
33
+ "directory": "packages/create-firefly"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/OutwalkStudios/firefly/issues"
37
+ },
38
+ "homepage": "https://github.com/OutwalkStudios/firefly#readme",
39
+ "author": "Outwalk Studios <support@outwalkstudios.com> (https://www.outwalkstudios.com/)",
40
+ "license": "MIT",
41
+ "dependencies": {
42
+ "chalk": "^4.1.2",
43
+ "prompts": "^2.4.2",
44
+ "yargs-parser": "^21.1.1"
45
+ },
46
+ "devDependencies": {
47
+ "@eslint/js": "^9.1.1",
48
+ "@rollup/plugin-commonjs": "^25.0.7",
49
+ "@rollup/plugin-json": "^6.1.0",
50
+ "@rollup/plugin-node-resolve": "^15.2.3",
51
+ "esbuild": "^0.20.2",
52
+ "eslint": "^9.1.1",
53
+ "globals": "^15.0.0",
54
+ "rollup": "^4.16.4",
55
+ "rollup-plugin-esbuild": "^6.1.1"
56
+ }
57
+ }
@@ -0,0 +1,49 @@
1
+ ### Node ###
2
+ # Logs
3
+ logs
4
+ *.log
5
+ npm-debug.log*
6
+ yarn-debug.log*
7
+ yarn-error.log*
8
+ lerna-debug.log*
9
+
10
+ # Diagnostic reports (https://nodejs.org/api/report.html)
11
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12
+
13
+ # Runtime data
14
+ pids
15
+ *.pid
16
+ *.seed
17
+ *.pid.lock
18
+
19
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
20
+ build/Release
21
+
22
+ # Dependency directories
23
+ node_modules/
24
+
25
+ # TypeScript v1 declaration files
26
+ typings/
27
+
28
+ # TypeScript cache
29
+ *.tsbuildinfo
30
+
31
+ # Optional npm cache directory
32
+ .npm
33
+
34
+ # Optional eslint cache
35
+ .eslintcache
36
+
37
+ # Output of 'npm pack'
38
+ *.tgz
39
+
40
+ # dotenv environment variables file
41
+ .env
42
+ .env.test
43
+
44
+ # rollup.js default build output
45
+ dist/
46
+
47
+ # Temporary folders
48
+ tmp/
49
+ temp/
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "experimentalDecorators": true,
4
+ "baseUrl": "./src",
5
+ "paths": {
6
+ "@/*": [
7
+ "./*"
8
+ ]
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "{{project-name}}",
3
+ "main": "dist/index.js",
4
+ "private": true,
5
+ "engines": {
6
+ "node": "^18",
7
+ "npm": "^9"
8
+ },
9
+ "scripts": {
10
+ "build": "firefly build",
11
+ "start": "firefly start",
12
+ "dev": "firefly start --dev"
13
+ }
14
+ }
@@ -0,0 +1,12 @@
1
+ import { Controller, Inject, Get } from "@outwalk/firefly";
2
+
3
+ @Controller()
4
+ export class AppController {
5
+
6
+ @Inject() appService;
7
+
8
+ @Get()
9
+ getHelloWorld() {
10
+ return this.appService.getHelloWorld();
11
+ }
12
+ }
@@ -0,0 +1,9 @@
1
+ import { Injectable } from "@outwalk/firefly";
2
+
3
+ @Injectable()
4
+ export class AppService {
5
+
6
+ getHelloWorld() {
7
+ return "Hello World!";
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ import { Application } from "@outwalk/firefly";
2
+ {{import-platform}}
3
+ {{import-database}}
4
+
5
+ {{define-platform}}
6
+
7
+ {{define-database}}
8
+
9
+ /* start the application */
10
+ new Application({{options}}).listen();
@@ -0,0 +1,7 @@
1
+ /* implement a database using the firefly database interface */
2
+ class CustomDatabase extends Database {
3
+
4
+ async connect() {}
5
+ }
6
+
7
+ const database = new CustomDatabase();
@@ -0,0 +1 @@
1
+ import { Database } from "@outwalk/firefly";
@@ -0,0 +1,7 @@
1
+ /* implement a database using the firefly database interface */
2
+ class CustomDatabase extends Database {
3
+
4
+ async connect(): Promise<void> {}
5
+ }
6
+
7
+ const database = new CustomDatabase();
@@ -0,0 +1 @@
1
+ import { Database } from "@outwalk/firefly";
@@ -0,0 +1,11 @@
1
+ /* implement a platform using the firefly platform interface */
2
+ class CustomPlatform extends Platform {
3
+
4
+ loadController(route, middleware, routes) {}
5
+
6
+ loadErrorHandler() {}
7
+
8
+ listen(port) {}
9
+ }
10
+
11
+ const platform = new CustomPlatform();
@@ -0,0 +1 @@
1
+ import { Platform } from "@outwalk/firefly";
@@ -0,0 +1,11 @@
1
+ /* implement a platform using the firefly platform interface */
2
+ class CustomPlatform extends Platform {
3
+
4
+ loadController(route: string, middleware: Function[], routes: Route[]): void {}
5
+
6
+ loadErrorHandler(): void {}
7
+
8
+ listen(port: number): void {}
9
+ }
10
+
11
+ const platform = new CustomPlatform();
@@ -0,0 +1 @@
1
+ import { Platform, Route } from "@outwalk/firefly";
@@ -0,0 +1,2 @@
1
+ /* setup the platform and global middleware */
2
+ const platform = new ExpressPlatform();
@@ -0,0 +1 @@
1
+ import { ExpressPlatform } from "@outwalk/firefly/express";
@@ -0,0 +1,2 @@
1
+ /* setup the database and global plugins */
2
+ const database = new MongooseDriver();
@@ -0,0 +1 @@
1
+ import { MongooseDriver } from "@outwalk/firefly/mongoose";
@@ -0,0 +1,49 @@
1
+ ### Node ###
2
+ # Logs
3
+ logs
4
+ *.log
5
+ npm-debug.log*
6
+ yarn-debug.log*
7
+ yarn-error.log*
8
+ lerna-debug.log*
9
+
10
+ # Diagnostic reports (https://nodejs.org/api/report.html)
11
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12
+
13
+ # Runtime data
14
+ pids
15
+ *.pid
16
+ *.seed
17
+ *.pid.lock
18
+
19
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
20
+ build/Release
21
+
22
+ # Dependency directories
23
+ node_modules/
24
+
25
+ # TypeScript v1 declaration files
26
+ typings/
27
+
28
+ # TypeScript cache
29
+ *.tsbuildinfo
30
+
31
+ # Optional npm cache directory
32
+ .npm
33
+
34
+ # Optional eslint cache
35
+ .eslintcache
36
+
37
+ # Output of 'npm pack'
38
+ *.tgz
39
+
40
+ # dotenv environment variables file
41
+ .env
42
+ .env.test
43
+
44
+ # rollup.js default build output
45
+ dist/
46
+
47
+ # Temporary folders
48
+ tmp/
49
+ temp/
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "{{project-name}}",
3
+ "main": "dist/index.js",
4
+ "private": true,
5
+ "engines": {
6
+ "node": "^18",
7
+ "npm": "^9"
8
+ },
9
+ "scripts": {
10
+ "build": "firefly build",
11
+ "start": "firefly start",
12
+ "dev": "firefly start --dev"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ import { Controller, Inject, Get } from "@outwalk/firefly";
2
+ import { AppService } from "./app.service";
3
+
4
+ @Controller()
5
+ export class AppController {
6
+
7
+ @Inject()
8
+ appService: AppService;
9
+
10
+ @Get()
11
+ getHelloWorld(): string {
12
+ return this.appService.getHelloWorld();
13
+ }
14
+ }
@@ -0,0 +1,9 @@
1
+ import { Injectable } from "@outwalk/firefly";
2
+
3
+ @Injectable()
4
+ export class AppService {
5
+
6
+ getHelloWorld(): string {
7
+ return "Hello World!";
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ import { Application } from "@outwalk/firefly";
2
+ {{import-platform}}
3
+ {{import-database}}
4
+
5
+ {{define-platform}}
6
+
7
+ {{define-database}}
8
+
9
+ /* start the application */
10
+ new Application({{options}}).listen();
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "experimentalDecorators": true,
4
+ "baseUrl": "./src",
5
+ "paths": {
6
+ "@/*": [
7
+ "./*"
8
+ ]
9
+ }
10
+ }
11
+ }