@outwalk/create-firefly 0.15.1 → 0.16.1

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/dist/index.js CHANGED
@@ -1,231 +1,224 @@
1
1
  #!/usr/bin/env node
2
- import yargs from 'yargs-parser';
3
- import prompts from 'prompts';
4
- import path from 'node:path';
5
- import fs from 'node:fs';
6
- import chalk from 'chalk';
7
- import { exec, spawnSync } from 'node:child_process';
8
- import path$1 from 'path';
9
- import url from 'url';
10
-
2
+ import yargs from "yargs-parser";
3
+ import prompts from "prompts";
4
+ import path from "node:path";
5
+ import fs from "node:fs";
6
+ import chalk from "chalk";
7
+ import { exec, spawnSync } from "node:child_process";
8
+ import path$1 from "path";
9
+ import url from "url";
10
+ //#region src/utils/logging.js
11
11
  const firefly = chalk.hex("#ADFF2F");
12
12
  const logger = {
13
- log: (...message) => console.log(`${firefly("[firefly]")} - `, ...message),
14
- warn: (...message) => console.log(`${chalk.yellow("[firefly]")} - `, ...message),
15
- error: (...message) => console.log(`${chalk.red("[firefly]")} - `, ...message)
13
+ log: (...message) => console.log(`${firefly("[firefly]")} - `, ...message),
14
+ warn: (...message) => console.log(`${chalk.yellow("[firefly]")} - `, ...message),
15
+ error: (...message) => console.log(`${chalk.red("[firefly]")} - `, ...message)
16
16
  };
17
-
18
- class TemplateBuilder {
19
- constructor(src, dest) {
20
- this.src = src;
21
- this.dest = dest;
22
- this.values = {};
23
- }
24
- inject(marker, value) {
25
- this.values[marker] = value;
26
- return this;
27
- }
28
- snippet(marker, snippet) {
29
- this.values[marker] = fs.readFileSync(snippet, "utf8");
30
- return this;
31
- }
32
- build() {
33
- TemplateBuilder.createDirectory(this.dest);
34
- TemplateBuilder.copyTemplate(this.src, this.dest, this.values);
35
- return this;
36
- }
37
- /* create a directory */
38
- static createDirectory(directory) {
39
- if (!fs.existsSync(directory)) {
40
- fs.mkdirSync(directory, { recursive: true });
41
- }
42
- }
43
- /* deletes a directory and all subdirectories and files */
44
- static deleteDirectory(directory) {
45
- if (fs.existsSync(directory)) {
46
- const files = fs.readdirSync(directory);
47
- for (let file of files) {
48
- const filepath = path.join(directory, file);
49
- if (fs.statSync(filepath).isDirectory()) {
50
- TemplateBuilder.deleteDirectory(filepath);
51
- } else {
52
- fs.unlinkSync(filepath);
53
- }
54
- }
55
- fs.rmdirSync(directory);
56
- }
57
- }
58
- /* copy a template and apply dynamic values to template markers */
59
- static copyTemplate(src, dest, values) {
60
- const filesToCreate = fs.readdirSync(src);
61
- const render = (content) => {
62
- const keys = Object.keys(values);
63
- for (let key of keys) {
64
- content = content.replace(new RegExp(`{{${key}}}`, "g"), values[key]);
65
- }
66
- return content.replace(/\n{3,}/g, "\n\n");
67
- };
68
- for (let file of filesToCreate) {
69
- const originalPath = path.join(src, file);
70
- if (file.endsWith(".template")) {
71
- file = file.replace(/.template$/, "");
72
- }
73
- const newPath = path.join(dest, file);
74
- const stats = fs.statSync(originalPath);
75
- if (stats.isFile()) {
76
- if (path.extname(originalPath) == ".template") {
77
- fs.writeFileSync(newPath, render(fs.readFileSync(originalPath, "utf8")));
78
- } else {
79
- fs.writeFileSync(newPath, fs.readFileSync(originalPath));
80
- }
81
- } else if (stats.isDirectory()) {
82
- TemplateBuilder.createDirectory(newPath);
83
- TemplateBuilder.copyTemplate(originalPath, newPath, values);
84
- }
85
- }
86
- }
87
- }
88
-
17
+ //#endregion
18
+ //#region src/utils/template.js
19
+ var TemplateBuilder = class TemplateBuilder {
20
+ constructor(src, dest) {
21
+ this.src = src;
22
+ this.dest = dest;
23
+ this.values = {};
24
+ }
25
+ inject(marker, value) {
26
+ this.values[marker] = value;
27
+ return this;
28
+ }
29
+ snippet(marker, snippet) {
30
+ this.values[marker] = fs.readFileSync(snippet, "utf8");
31
+ return this;
32
+ }
33
+ build() {
34
+ TemplateBuilder.createDirectory(this.dest);
35
+ TemplateBuilder.copyTemplate(this.src, this.dest, this.values);
36
+ return this;
37
+ }
38
+ static createDirectory(directory) {
39
+ if (!fs.existsSync(directory)) fs.mkdirSync(directory, { recursive: true });
40
+ }
41
+ static deleteDirectory(directory) {
42
+ if (fs.existsSync(directory)) {
43
+ const files = fs.readdirSync(directory);
44
+ for (let file of files) {
45
+ const filepath = path.join(directory, file);
46
+ if (fs.statSync(filepath).isDirectory()) TemplateBuilder.deleteDirectory(filepath);
47
+ else fs.unlinkSync(filepath);
48
+ }
49
+ fs.rmdirSync(directory);
50
+ }
51
+ }
52
+ static copyTemplate(src, dest, values) {
53
+ const filesToCreate = fs.readdirSync(src);
54
+ const render = (content) => {
55
+ const keys = Object.keys(values);
56
+ for (let key of keys) content = content.replace(new RegExp(`{{${key}}}`, "g"), values[key]);
57
+ return content.replace(/\n{3,}/g, "\n\n");
58
+ };
59
+ for (let file of filesToCreate) {
60
+ const originalPath = path.join(src, file);
61
+ if (file.endsWith(".template")) file = file.replace(/.template$/, "");
62
+ const newPath = path.join(dest, file);
63
+ const stats = fs.statSync(originalPath);
64
+ if (stats.isFile()) {
65
+ if (path.extname(originalPath) == ".template") fs.writeFileSync(newPath, render(fs.readFileSync(originalPath, "utf8")));
66
+ else fs.writeFileSync(newPath, fs.readFileSync(originalPath));
67
+ } else if (stats.isDirectory()) {
68
+ TemplateBuilder.createDirectory(newPath);
69
+ TemplateBuilder.copyTemplate(originalPath, newPath, values);
70
+ }
71
+ }
72
+ }
73
+ };
74
+ //#endregion
75
+ //#region src/utils/dependencies.js
89
76
  function installDependencies(dependencies, directory) {
90
- return new Promise((resolve, reject) => {
91
- logger.log("installing dependencies...");
92
- const command = /^win/.test(process.platform) ? "npm.cmd" : "npm";
93
- const spawnProcess = (command2, args) => {
94
- const { status, error } = spawnSync(command2, args, { cwd: directory, stdio: "ignore" });
95
- if (status != 0) throw new Error("failed to install project dependencies.");
96
- if (error) throw error;
97
- };
98
- try {
99
- spawnProcess(command, ["install", "--save"].concat(dependencies));
100
- resolve();
101
- } catch (error) {
102
- reject(error);
103
- }
104
- });
77
+ return new Promise((resolve, reject) => {
78
+ logger.log("installing dependencies...");
79
+ const command = /^win/.test(process.platform) ? "npm.cmd" : "npm";
80
+ const spawnProcess = (command, args) => {
81
+ const { status, error } = spawnSync(command, args, {
82
+ cwd: directory,
83
+ stdio: "ignore"
84
+ });
85
+ if (status != 0) throw new Error("failed to install project dependencies.");
86
+ if (error) throw error;
87
+ };
88
+ try {
89
+ spawnProcess(command, ["install", "--save"].concat(dependencies));
90
+ resolve();
91
+ } catch (error) {
92
+ reject(error);
93
+ }
94
+ });
105
95
  }
106
96
  function intitializeGitRepository(directory) {
107
- return new Promise((resolve, reject) => {
108
- logger.log("initializing git repository...");
109
- try {
110
- exec("git init", { cwd: directory });
111
- resolve();
112
- } catch {
113
- reject(new Error("failed to initialize the git repository."));
114
- }
115
- });
97
+ return new Promise((resolve, reject) => {
98
+ logger.log("initializing git repository...");
99
+ try {
100
+ exec("git init", { cwd: directory });
101
+ resolve();
102
+ } catch {
103
+ reject(/* @__PURE__ */ new Error("failed to initialize the git repository."));
104
+ }
105
+ });
116
106
  }
117
-
107
+ //#endregion
108
+ //#region src/utils/files.js
118
109
  const Module = {
119
- __filename: (fileUrl) => {
120
- return import.meta.url ? url.fileURLToPath(fileUrl) : __filename;
121
- },
122
- __dirname: (fileUrl) => {
123
- return import.meta.url ? path$1.dirname(Module.__filename(fileUrl)) : __dirname;
124
- }
110
+ __filename: (fileUrl) => {
111
+ return import.meta.url ? url.fileURLToPath(fileUrl) : __filename;
112
+ },
113
+ __dirname: (fileUrl) => {
114
+ return import.meta.url ? path$1.dirname(Module.__filename(fileUrl)) : __dirname;
115
+ }
125
116
  };
126
-
117
+ //#endregion
118
+ //#region src/index.js
127
119
  const args = yargs(process.argv.slice(2));
128
120
  prompts.override({
129
- name: args._[0],
130
- language: args.l ?? args.language,
131
- platform: args.p ?? args.platform
121
+ name: args._[0],
122
+ language: args.l ?? args.language,
123
+ platform: args.p ?? args.platform
132
124
  });
133
- const express = { template: "express", dependencies: ["express"] };
134
- const hono = { template: "hono", dependencies: ["hono", "@hono/node-server"] };
135
125
  const questions = [
136
- {
137
- type: "text",
138
- name: "name",
139
- message: "Project name:",
140
- validate: (name) => name != name.toLowerCase() ? "your project name must be lowercase." : true
141
- },
142
- {
143
- type: "select",
144
- name: "language",
145
- message: "Select a language:",
146
- choices: [
147
- { title: "JavaScript", value: "javascript" },
148
- { title: "TypeScript", value: "typescript" }
149
- ]
150
- },
151
- {
152
- type: "select",
153
- name: "platform",
154
- message: "Select a platform:",
155
- choices: [
156
- { title: "Express", value: JSON.stringify(express) },
157
- { title: "Hono", value: JSON.stringify(hono) },
158
- { title: "No Platform (Node)", value: null }
159
- ]
160
- }
126
+ {
127
+ type: "text",
128
+ name: "name",
129
+ message: "Project name:",
130
+ validate: (name) => name != name.toLowerCase() ? "your project name must be lowercase." : true
131
+ },
132
+ {
133
+ type: "select",
134
+ name: "language",
135
+ message: "Select a language:",
136
+ choices: [{
137
+ title: "JavaScript",
138
+ value: "javascript"
139
+ }, {
140
+ title: "TypeScript",
141
+ value: "typescript"
142
+ }]
143
+ },
144
+ {
145
+ type: "select",
146
+ name: "platform",
147
+ message: "Select a platform:",
148
+ choices: [{
149
+ title: "Express",
150
+ value: JSON.stringify({
151
+ template: "express",
152
+ dependencies: ["express"]
153
+ })
154
+ }, {
155
+ title: "None",
156
+ value: null
157
+ }]
158
+ }
161
159
  ];
162
160
  (async () => {
163
- const config = await prompts(questions, { onCancel: () => process.exit() });
164
- const skipInstall = args["skip-install"];
165
- const skipGit = args["skip-git"];
166
- const force = args["force"];
167
- const platform = JSON.parse(config.platform);
168
- const settings = { useCurrentDirectory: false };
169
- const dependencies = ["@outwalk/firefly", ...platform?.dependencies ?? []];
170
- if (config.language != "javascript") {
171
- dependencies.push(config.language);
172
- }
173
- if (config.name == ".") {
174
- if (!force && fs.readdirSync(config.name).length > 0) {
175
- const response = await prompts({
176
- type: "confirm",
177
- name: "continue",
178
- message: "The current directory is not empty. Continue?",
179
- initial: true
180
- });
181
- if (!response.continue) return;
182
- }
183
- config.name = path.basename(process.cwd());
184
- settings.useCurrentDirectory = true;
185
- }
186
- if (fs.existsSync(config.name)) {
187
- if (force && !settings.useCurrentDirectory) {
188
- TemplateBuilder.deleteDirectory(config.name);
189
- } else {
190
- logger.error(`${config.name} already exists.`);
191
- return;
192
- }
193
- }
194
- console.log("\n");
195
- logger.log(`creating ${config.name}...`);
196
- const templatePath = path.join(Module.__dirname(import.meta.url), "../templates/", config.language);
197
- const snippetPath = path.join(Module.__dirname(import.meta.url), "../templates/snippets");
198
- const projectPath = !settings.useCurrentDirectory ? config.name : ".";
199
- try {
200
- const template = new TemplateBuilder(templatePath, projectPath);
201
- template.inject("project-name", config.name);
202
- template.inject("options", !platform ? "" : "{ platform }");
203
- if (platform) {
204
- template.snippet("import-platform", path.join(snippetPath, platform.template, "import-platform.template"));
205
- template.snippet("define-platform", path.join(snippetPath, platform.template, "define-platform.template"));
206
- } else {
207
- template.inject("import-platform", "");
208
- template.inject("define-platform", "");
209
- }
210
- template.build();
211
- } catch (error) {
212
- logger.error(error.message);
213
- return;
214
- }
215
- try {
216
- if (!skipInstall) await installDependencies(dependencies, projectPath);
217
- if (!skipGit) await intitializeGitRepository(projectPath);
218
- } catch (error) {
219
- logger.error(error.message);
220
- if (!settings.useCurrentDirectory) TemplateBuilder.deleteDirectory(config.name);
221
- return;
222
- }
223
- console.log("\n----------------------------------");
224
- console.log("Get started with your new project!\n");
225
- if (!settings.useCurrentDirectory) {
226
- console.log(firefly(` > cd ./${path.relative(process.cwd(), config.name)} `));
227
- }
228
- if (skipInstall) console.log(firefly(" > npm install"));
229
- console.log(firefly(" > npm run dev"));
230
- console.log("----------------------------------");
161
+ const config = await prompts(questions, { onCancel: () => process.exit() });
162
+ const skipInstall = args["skip-install"];
163
+ const skipGit = args["skip-git"];
164
+ const force = args["force"];
165
+ const platform = JSON.parse(config.platform);
166
+ const settings = { useCurrentDirectory: false };
167
+ const dependencies = ["@outwalk/firefly", ...platform?.dependencies ?? []];
168
+ if (config.language != "javascript") dependencies.push(config.language);
169
+ if (config.name == ".") {
170
+ if (!force && fs.readdirSync(config.name).length > 0) {
171
+ if (!(await prompts({
172
+ type: "confirm",
173
+ name: "continue",
174
+ message: "The current directory is not empty. Continue?",
175
+ initial: true
176
+ })).continue) return;
177
+ }
178
+ config.name = path.basename(process.cwd());
179
+ settings.useCurrentDirectory = true;
180
+ }
181
+ if (fs.existsSync(config.name)) {
182
+ if (force && !settings.useCurrentDirectory) TemplateBuilder.deleteDirectory(config.name);
183
+ else {
184
+ logger.error(`${config.name} already exists.`);
185
+ return;
186
+ }
187
+ }
188
+ console.log("\n");
189
+ logger.log(`creating ${config.name}...`);
190
+ const templatePath = path.join(Module.__dirname(import.meta.url), "../templates/", config.language);
191
+ const snippetPath = path.join(Module.__dirname(import.meta.url), "../templates/snippets");
192
+ const projectPath = !settings.useCurrentDirectory ? config.name : ".";
193
+ try {
194
+ const template = new TemplateBuilder(templatePath, projectPath);
195
+ template.inject("project-name", config.name);
196
+ template.inject("options", !platform ? "" : "{ platform }");
197
+ if (platform) {
198
+ template.snippet("import-platform", path.join(snippetPath, platform.template, "import-platform.template"));
199
+ template.snippet("define-platform", path.join(snippetPath, platform.template, "define-platform.template"));
200
+ } else {
201
+ template.inject("import-platform", "");
202
+ template.inject("define-platform", "");
203
+ }
204
+ template.build();
205
+ } catch (error) {
206
+ logger.error(error.message);
207
+ return;
208
+ }
209
+ try {
210
+ if (!skipInstall) await installDependencies(dependencies, projectPath);
211
+ if (!skipGit) await intitializeGitRepository(projectPath);
212
+ } catch (error) {
213
+ logger.error(error.message);
214
+ if (!settings.useCurrentDirectory) TemplateBuilder.deleteDirectory(config.name);
215
+ return;
216
+ }
217
+ console.log("\n----------------------------------");
218
+ console.log("Get started with your new project!\n");
219
+ if (!settings.useCurrentDirectory) console.log(firefly(` > cd ./${path.relative(process.cwd(), config.name)} `));
220
+ if (skipInstall) console.log(firefly(" > npm install"));
221
+ console.log(firefly(" > npm run dev"));
222
+ console.log("----------------------------------");
231
223
  })();
224
+ //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@outwalk/create-firefly",
3
3
  "type": "module",
4
- "version": "0.15.1",
4
+ "version": "0.16.1",
5
5
  "description": "Firefly - a modern scalable web framework.",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -13,13 +13,12 @@
13
13
  "create-firefly": "dist/index.js"
14
14
  },
15
15
  "scripts": {
16
- "build": "rollup -c",
16
+ "build": "rolldown -c",
17
17
  "lint": "eslint src",
18
18
  "prepublishOnly": "npm run lint && npm run build"
19
19
  },
20
20
  "keywords": [
21
21
  "express",
22
- "hono",
23
22
  "decorators",
24
23
  "project",
25
24
  "generator",
@@ -48,13 +47,8 @@
48
47
  },
49
48
  "devDependencies": {
50
49
  "@eslint/js": "^10.0.1",
51
- "@rollup/plugin-commonjs": "^29.0.3",
52
- "@rollup/plugin-json": "^6.1.0",
53
- "@rollup/plugin-node-resolve": "^16.0.3",
54
- "esbuild": "^0.28.2",
55
50
  "eslint": "^10.10.0",
56
51
  "globals": "^17.12.0",
57
- "rollup": "^4.63.2",
58
- "rollup-plugin-esbuild": "^6.2.1"
52
+ "rolldown": "^1.2.8"
59
53
  }
60
54
  }
@@ -4,8 +4,7 @@
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "engines": {
7
- "node": ">=22",
8
- "npm": ">=11"
7
+ "node": ">=22"
9
8
  },
10
9
  "scripts": {
11
10
  "build": "firefly build",
@@ -4,8 +4,7 @@
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "engines": {
7
- "node": ">=22",
8
- "npm": ">=11"
7
+ "node": ">=22"
9
8
  },
10
9
  "scripts": {
11
10
  "build": "firefly build",
@@ -1,2 +0,0 @@
1
- /* setup the platform and global middleware */
2
- const platform = new HonoPlatform();
@@ -1 +0,0 @@
1
- import { HonoPlatform } from "@outwalk/firefly/hono";