@triophore/falcon-cli 1.0.0 → 1.0.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.
@@ -0,0 +1,101 @@
1
+ const { input, select, confirm } = require("@inquirer/prompts");
2
+ const fs = require("fs").promises;
3
+ const path = require("path");
4
+
5
+ class RouteGenerator {
6
+ constructor(options = {}) {
7
+ this.verbose = options.verbose || false;
8
+ this.type = options.type || 'route'; // 'route' or 'validator'
9
+ }
10
+
11
+ async generate(name) {
12
+ const currentDir = process.cwd();
13
+
14
+ // Check if we're in a Falcon project
15
+ try {
16
+ await fs.access(path.join(currentDir, 'settings.js'));
17
+ } catch (error) {
18
+ throw new Error('Not in a Falcon.js project directory. Run this command from your project root.');
19
+ }
20
+
21
+ if (!name) {
22
+ name = await input({
23
+ message: `${this.type === 'validator' ? 'Validator' : 'Route'} name (e.g., User):`,
24
+ validate: v => v.trim() ? true : 'Name is required',
25
+ });
26
+ }
27
+
28
+ if (this.type === 'validator') {
29
+ await this.generateValidator(currentDir, name);
30
+ } else {
31
+ await this.generateRoute(currentDir, name);
32
+ }
33
+ }
34
+
35
+ async generateRoute(projectDir, name) {
36
+ const routesDir = path.join(projectDir, 'routes');
37
+ await fs.mkdir(routesDir, { recursive: true });
38
+
39
+ // Determine path and filename
40
+ // If name contains /, treat as path
41
+ const parts = name.split('/');
42
+ const fileName = parts.pop();
43
+ const subDir = parts.join('/');
44
+
45
+ const targetDir = path.join(routesDir, subDir);
46
+ await fs.mkdir(targetDir, { recursive: true });
47
+
48
+ const filePath = path.join(targetDir, `${fileName}.js`);
49
+
50
+ // Check if file exists
51
+ try {
52
+ await fs.access(filePath);
53
+ const overwrite = await confirm({
54
+ message: `Route file ${filePath} already exists. Overwrite?`,
55
+ default: false
56
+ });
57
+ if (!overwrite) return;
58
+ } catch (e) {
59
+ // File doesn't exist, proceed
60
+ }
61
+
62
+ // Helper to get template content
63
+ const templatePath = path.join(__dirname, '..', 'templates', 'example-route.js');
64
+ let content = await fs.readFile(templatePath, 'utf8');
65
+
66
+ // Simple replacements if needed, or just use the example as a starter
67
+ // For now, we'll just write the template
68
+
69
+ await fs.writeFile(filePath, content);
70
+ console.log(`✅ Route created: ${filePath}`);
71
+ }
72
+
73
+ async generateValidator(projectDir, name) {
74
+ const validatorsDir = path.join(projectDir, 'validators');
75
+ await fs.mkdir(validatorsDir, { recursive: true });
76
+
77
+ const filePath = path.join(validatorsDir, `${name}.js`);
78
+
79
+ // Check if file exists
80
+ try {
81
+ await fs.access(filePath);
82
+ const overwrite = await confirm({
83
+ message: `Validator file ${filePath} already exists. Overwrite?`,
84
+ default: false
85
+ });
86
+ if (!overwrite) return;
87
+ } catch (e) {
88
+ // File doesn't exist, proceed
89
+ }
90
+
91
+ const templatePath = path.join(__dirname, '..', 'templates', 'example-validator.js');
92
+ let content = await fs.readFile(templatePath, 'utf8');
93
+
94
+ // Replace Joi with Joi (no change needed usually, but good for future)
95
+
96
+ await fs.writeFile(filePath, content);
97
+ console.log(`✅ Validator created: ${filePath}`);
98
+ }
99
+ }
100
+
101
+ module.exports = RouteGenerator;
@@ -0,0 +1,85 @@
1
+ const { input, confirm } = require("@inquirer/prompts");
2
+ const fs = require("fs").promises;
3
+ const path = require("path");
4
+
5
+ class ServiceGenerator {
6
+ constructor(options = {}) {
7
+ this.verbose = options.verbose || false;
8
+ this.type = options.type || 'service'; // 'service' or 'worker'
9
+ }
10
+
11
+ async generate(name) {
12
+ const currentDir = process.cwd();
13
+
14
+ // Check if we're in a Falcon project
15
+ try {
16
+ await fs.access(path.join(currentDir, 'settings.js'));
17
+ } catch (error) {
18
+ throw new Error('Not in a Falcon.js project directory. Run this command from your project root.');
19
+ }
20
+
21
+ if (!name) {
22
+ name = await input({
23
+ message: `${this.type === 'worker' ? 'Worker' : 'Service'} name (e.g., Email):`,
24
+ validate: v => v.trim() ? true : 'Name is required',
25
+ });
26
+ }
27
+
28
+ const dirName = this.type === 'worker' ? 'workers' : 'services';
29
+ const targetDir = path.join(currentDir, dirName);
30
+ await fs.mkdir(targetDir, { recursive: true });
31
+
32
+ const filePath = path.join(targetDir, `${name}.js`);
33
+
34
+ // Check if file exists
35
+ try {
36
+ await fs.access(filePath);
37
+ const overwrite = await confirm({
38
+ message: `${this.type === 'worker' ? 'Worker' : 'Service'} file ${filePath} already exists. Overwrite?`,
39
+ default: false
40
+ });
41
+ if (!overwrite) return;
42
+ } catch (e) {
43
+ // File doesn't exist, proceed
44
+ }
45
+
46
+ // Get template
47
+ const templateName = this.type === 'worker' ? 'example-worker.js' : 'example-service.js';
48
+ const templatePath = path.join(__dirname, '..', 'templates', templateName);
49
+ let content = await fs.readFile(templatePath, 'utf8');
50
+
51
+ await fs.writeFile(filePath, content);
52
+ console.log(`✅ ${this.type === 'worker' ? 'Worker' : 'Service'} created: ${filePath}`);
53
+
54
+ // Update settings.js to include the service/worker
55
+ await this.updateSettings(currentDir, name, dirName);
56
+ }
57
+
58
+ async updateSettings(projectDir, name, listName) {
59
+ const settingsPath = path.join(projectDir, 'settings.js');
60
+ let settingsContent = await fs.readFile(settingsPath, 'utf8');
61
+
62
+ // Regex to find the array: services: [...] or workers: [...]
63
+ const regex = new RegExp(`${listName}:\\s*\\[(.*?)\\]`, 's');
64
+ const match = settingsContent.match(regex);
65
+
66
+ if (match) {
67
+ const listContent = match[1];
68
+ // Simple check if name is already there
69
+ if (!listContent.includes(`"${name}"`) && !listContent.includes(`'${name}'`)) {
70
+ const newListContent = listContent.trim()
71
+ ? `${listContent.trim()}, "${name}"`
72
+ : `"${name}"`;
73
+
74
+ settingsContent = settingsContent.replace(
75
+ regex,
76
+ `${listName}: [${newListContent}]`
77
+ );
78
+ await fs.writeFile(settingsPath, settingsContent);
79
+ console.log(`✅ Added "${name}" to settings.js ${listName} array`);
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ module.exports = ServiceGenerator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@triophore/falcon-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -17,6 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
+ "@hapi/boom": "^10.0.1",
20
21
  "@inquirer/prompts": "^7.9.0",
21
22
  "acorn": "^8.15.0",
22
23
  "ajv": "^8.17.1",
@@ -25,11 +26,10 @@
25
26
  "joi": "^18.0.1",
26
27
  "mongoose": "^8.19.3",
27
28
  "prompt-sync": "^4.2.0",
29
+ "rate-limiter-flexible": "^2.4.2",
28
30
  "reflect-metadata": "^0.2.2",
29
31
  "sequelize": "^6.37.7",
30
32
  "unzipper": "^0.12.3",
31
- "yargs": "^18.0.0",
32
- "@hapi/boom": "^10.0.1",
33
- "rate-limiter-flexible": "^2.4.2"
33
+ "yargs": "^18.0.0"
34
34
  }
35
35
  }