@triophore/falcon-cli 1.0.0 ā 1.0.2
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/lib/ProjectGenerator.js +136 -138
- package/lib/RouteGenerator.js +101 -0
- package/lib/ServiceGenerator.js +85 -0
- package/package.json +4 -4
- package/templates/example-service.js +6 -6
- package/templates/example-worker.js +9 -9
- package/templates/index.txt +1 -1
package/lib/ProjectGenerator.js
CHANGED
|
@@ -6,122 +6,120 @@ const { spawn } = require('child_process');
|
|
|
6
6
|
const { showSuccess, runNpmInstall, createDirectory } = require('./utils');
|
|
7
7
|
|
|
8
8
|
class ProjectGenerator {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.verbose = options.verbose || false;
|
|
11
|
+
this.skipInstall = options.skipInstall || false;
|
|
12
|
+
this.useDefaults = options.useDefaults || false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async create(projectName, template = 'basic') {
|
|
16
|
+
const currentDir = process.cwd();
|
|
17
|
+
|
|
18
|
+
// Get project name if not provided
|
|
19
|
+
if (!projectName) {
|
|
20
|
+
projectName = await input({
|
|
21
|
+
message: 'Project name:',
|
|
22
|
+
validate: v => v.trim() ? true : 'Project name is required',
|
|
23
|
+
});
|
|
13
24
|
}
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await fs.access(projectPath);
|
|
31
|
-
const overwrite = await confirm({
|
|
32
|
-
message: `Directory "${projectName}" already exists. Overwrite?`,
|
|
33
|
-
default: false
|
|
34
|
-
});
|
|
35
|
-
if (!overwrite) {
|
|
36
|
-
console.log('ā Project creation cancelled');
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
} catch (error) {
|
|
40
|
-
// Directory doesn't exist, which is good
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log(`\nš Creating Falcon.js project: ${projectName}\n`);
|
|
44
|
-
|
|
45
|
-
// Create project structure
|
|
46
|
-
await this.createProjectStructure(projectPath, projectName, template);
|
|
47
|
-
|
|
48
|
-
// Install dependencies
|
|
49
|
-
if (!this.skipInstall) {
|
|
50
|
-
console.log('š¦ Installing dependencies...');
|
|
51
|
-
await runNpmInstall(projectPath);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
showSuccess(projectName, this.skipInstall);
|
|
26
|
+
const projectPath = path.join(currentDir, projectName);
|
|
27
|
+
|
|
28
|
+
// Check if directory exists
|
|
29
|
+
try {
|
|
30
|
+
await fs.access(projectPath);
|
|
31
|
+
const overwrite = await confirm({
|
|
32
|
+
message: `Directory "${projectName}" already exists. Overwrite?`,
|
|
33
|
+
default: false
|
|
34
|
+
});
|
|
35
|
+
if (!overwrite) {
|
|
36
|
+
console.log('ā Project creation cancelled');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
// Directory doesn't exist, which is good
|
|
55
41
|
}
|
|
56
42
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
'logs',
|
|
67
|
-
'public'
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
for (const dir of directories) {
|
|
71
|
-
await createDirectory(path.join(projectPath, dir));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Create files
|
|
75
|
-
await this.createPackageJson(projectPath, projectName);
|
|
76
|
-
await this.createSettings(projectPath, projectName);
|
|
77
|
-
await this.createIndexJs(projectPath);
|
|
78
|
-
await this.createEnvFile(projectPath, projectName);
|
|
79
|
-
await this.createExampleFiles(projectPath);
|
|
43
|
+
console.log(`\nš Creating Falcon.js project: ${projectName}\n`);
|
|
44
|
+
|
|
45
|
+
// Create project structure
|
|
46
|
+
await this.createProjectStructure(projectPath, projectName, template);
|
|
47
|
+
|
|
48
|
+
// Install dependencies
|
|
49
|
+
if (!this.skipInstall) {
|
|
50
|
+
console.log('š¦ Installing dependencies...');
|
|
51
|
+
await runNpmInstall(projectPath);
|
|
80
52
|
}
|
|
81
53
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"@hapi/inert": "^7.1.0",
|
|
101
|
-
"@hapi/vision": "^7.0.3",
|
|
102
|
-
"joi": "^17.13.3",
|
|
103
|
-
"mongoose": "^8.3.1",
|
|
104
|
-
"redis": "^4.7.0",
|
|
105
|
-
"mqtt": "^5.13.3",
|
|
106
|
-
"log4js": "^6.9.1",
|
|
107
|
-
"rate-limiter-flexible": "^2.4.2",
|
|
108
|
-
"hapi-alive": "^2.0.4",
|
|
109
|
-
"hapi-swagger": "^17.2.1",
|
|
110
|
-
"dotenv": "^16.0.0"
|
|
111
|
-
},
|
|
112
|
-
devDependencies: {
|
|
113
|
-
"nodemon": "^3.1.10"
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
await fs.writeFile(
|
|
118
|
-
path.join(projectPath, 'package.json'),
|
|
119
|
-
JSON.stringify(packageJson, null, 2)
|
|
120
|
-
);
|
|
54
|
+
showSuccess(projectName, this.skipInstall);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async createProjectStructure(projectPath, projectName, template) {
|
|
58
|
+
// Create directories
|
|
59
|
+
const directories = [
|
|
60
|
+
'models/mongo',
|
|
61
|
+
'routes',
|
|
62
|
+
'services',
|
|
63
|
+
'workers',
|
|
64
|
+
'validators',
|
|
65
|
+
'init',
|
|
66
|
+
'logs',
|
|
67
|
+
'public'
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
for (const dir of directories) {
|
|
71
|
+
await createDirectory(path.join(projectPath, dir));
|
|
121
72
|
}
|
|
122
73
|
|
|
123
|
-
|
|
124
|
-
|
|
74
|
+
// Create files
|
|
75
|
+
await this.createPackageJson(projectPath, projectName);
|
|
76
|
+
await this.createSettings(projectPath, projectName);
|
|
77
|
+
await this.createIndexJs(projectPath);
|
|
78
|
+
await this.createEnvFile(projectPath, projectName);
|
|
79
|
+
await this.createExampleFiles(projectPath);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async createPackageJson(projectPath, projectName) {
|
|
83
|
+
const packageJson = {
|
|
84
|
+
name: projectName,
|
|
85
|
+
version: "1.0.0",
|
|
86
|
+
description: "Falcon.js application",
|
|
87
|
+
main: "index.js",
|
|
88
|
+
scripts: {
|
|
89
|
+
start: "node index.js",
|
|
90
|
+
dev: "nodemon index.js",
|
|
91
|
+
test: "echo \"Error: no test specified\" && exit 1"
|
|
92
|
+
},
|
|
93
|
+
keywords: ["falcon", "nodejs", "api"],
|
|
94
|
+
author: "",
|
|
95
|
+
license: "ISC",
|
|
96
|
+
type: "commonjs",
|
|
97
|
+
dependencies: {
|
|
98
|
+
"@triophore/falconjs": "^1.0.0",
|
|
99
|
+
"@hapi/boom": "^10.0.1",
|
|
100
|
+
"@hapi/inert": "^7.1.0",
|
|
101
|
+
"@hapi/vision": "^7.0.3",
|
|
102
|
+
"joi": "^17.13.3",
|
|
103
|
+
"mongoose": "^8.3.1",
|
|
104
|
+
"redis": "^4.7.0",
|
|
105
|
+
"rate-limiter-flexible": "^2.4.2",
|
|
106
|
+
"hapi-alive": "^2.0.4",
|
|
107
|
+
"hapi-swagger": "^17.2.1",
|
|
108
|
+
"dotenv": "^16.0.0"
|
|
109
|
+
},
|
|
110
|
+
devDependencies: {
|
|
111
|
+
"nodemon": "^3.1.10"
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
await fs.writeFile(
|
|
116
|
+
path.join(projectPath, 'package.json'),
|
|
117
|
+
JSON.stringify(packageJson, null, 2)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async createSettings(projectPath, projectName) {
|
|
122
|
+
const settings = `module.exports.settings = {
|
|
125
123
|
name: "${projectName}",
|
|
126
124
|
http: {
|
|
127
125
|
host: process.env.HTTP_HOST || "localhost",
|
|
@@ -179,19 +177,19 @@ class ProjectGenerator {
|
|
|
179
177
|
postInit: "post"
|
|
180
178
|
};`;
|
|
181
179
|
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
await fs.writeFile(path.join(projectPath, 'settings.js'), settings);
|
|
181
|
+
}
|
|
184
182
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
183
|
+
async createIndexJs(projectPath) {
|
|
184
|
+
const indexContent = await fs.readFile(
|
|
185
|
+
path.join(__dirname, '../templates/index.txt'),
|
|
186
|
+
'utf8'
|
|
187
|
+
);
|
|
188
|
+
await fs.writeFile(path.join(projectPath, 'index.js'), indexContent);
|
|
189
|
+
}
|
|
192
190
|
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
async createEnvFile(projectPath, projectName) {
|
|
192
|
+
const envContent = `# Falcon.js Environment Configuration
|
|
195
193
|
# Generated by falcon-cli
|
|
196
194
|
|
|
197
195
|
# Server Configuration
|
|
@@ -221,26 +219,26 @@ LOG_MAX_SIZE=10M
|
|
|
221
219
|
MODE=DEV
|
|
222
220
|
`;
|
|
223
221
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
222
|
+
await fs.writeFile(path.join(projectPath, '.env'), envContent);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async createExampleFiles(projectPath) {
|
|
226
|
+
const templates = [
|
|
227
|
+
{ src: 'example-route.js', dest: 'routes/example.js' },
|
|
228
|
+
{ src: 'example-validator.js', dest: 'validators/ExamplePayload.js' },
|
|
229
|
+
{ src: 'example-service.js', dest: 'services/example.js' },
|
|
230
|
+
{ src: 'example-worker.js', dest: 'workers/example.js' },
|
|
231
|
+
{ src: 'post-init.js', dest: 'init/post.js' }
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
for (const template of templates) {
|
|
235
|
+
const content = await fs.readFile(
|
|
236
|
+
path.join(__dirname, '../templates', template.src),
|
|
237
|
+
'utf8'
|
|
238
|
+
);
|
|
239
|
+
await fs.writeFile(path.join(projectPath, template.dest), content);
|
|
243
240
|
}
|
|
241
|
+
}
|
|
244
242
|
}
|
|
245
243
|
|
|
246
244
|
module.exports = ProjectGenerator;
|
|
@@ -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.
|
|
3
|
+
"version": "1.0.2",
|
|
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
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const { FalconBaseService } = require('falconjs');
|
|
1
|
+
const { FalconBaseService } = require('@triophore/falconjs');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Example service - rename and customize as needed
|
|
5
5
|
*/
|
|
6
6
|
class ExampleService extends FalconBaseService {
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
constructor() {
|
|
9
9
|
super('example'); // Service ID for MQTT topics
|
|
10
10
|
}
|
|
@@ -15,7 +15,7 @@ class ExampleService extends FalconBaseService {
|
|
|
15
15
|
async onMessage(topic, msg) {
|
|
16
16
|
try {
|
|
17
17
|
const message = JSON.parse(msg.toString());
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
switch (topic) {
|
|
20
20
|
case 'service_example':
|
|
21
21
|
await this.handleRequest(message);
|
|
@@ -33,9 +33,9 @@ class ExampleService extends FalconBaseService {
|
|
|
33
33
|
*/
|
|
34
34
|
async handleRequest(request) {
|
|
35
35
|
console.log('Processing request:', request);
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
// Your service logic here
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
// Send response back via MQTT
|
|
40
40
|
this.publish({
|
|
41
41
|
status: 'completed',
|
|
@@ -49,7 +49,7 @@ class ExampleService extends FalconBaseService {
|
|
|
49
49
|
*/
|
|
50
50
|
async run() {
|
|
51
51
|
console.log('Example service is running...');
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
// Your initialization logic here
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const { FalconBaseWorker } = require('falconjs');
|
|
1
|
+
const { FalconBaseWorker } = require('@triophore/falconjs');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Example worker - rename and customize as needed
|
|
5
5
|
*/
|
|
6
6
|
class ExampleWorker extends FalconBaseWorker {
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
constructor() {
|
|
9
9
|
super('example'); // Worker ID for MQTT topics
|
|
10
10
|
}
|
|
@@ -15,7 +15,7 @@ class ExampleWorker extends FalconBaseWorker {
|
|
|
15
15
|
async onMessage(topic, msg) {
|
|
16
16
|
try {
|
|
17
17
|
const message = JSON.parse(msg.toString());
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
switch (topic) {
|
|
20
20
|
case 'worker_example_job':
|
|
21
21
|
await this.processJob(message);
|
|
@@ -33,12 +33,12 @@ class ExampleWorker extends FalconBaseWorker {
|
|
|
33
33
|
*/
|
|
34
34
|
async processJob(job) {
|
|
35
35
|
const { jobId, data } = job;
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
console.log(`Processing job ${jobId}:`, data);
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
// Simulate work
|
|
40
40
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
// Update job status in database if available
|
|
43
43
|
if (this.models.job) {
|
|
44
44
|
await this.models.job.findByIdAndUpdate(jobId, {
|
|
@@ -47,7 +47,7 @@ class ExampleWorker extends FalconBaseWorker {
|
|
|
47
47
|
result: { processed: true }
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
// Send completion notification
|
|
52
52
|
await this.publish('worker_example_complete', {
|
|
53
53
|
jobId: jobId,
|
|
@@ -62,13 +62,13 @@ class ExampleWorker extends FalconBaseWorker {
|
|
|
62
62
|
async run() {
|
|
63
63
|
const args = this.parseArgs();
|
|
64
64
|
console.log('Example worker started with args:', args);
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
// If specific job passed as argument, process it immediately
|
|
67
67
|
if (args.jobId) {
|
|
68
68
|
await this.processJob(args);
|
|
69
69
|
process.exit(0); // Exit after processing single job
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
// Otherwise, keep running and wait for MQTT jobs
|
|
73
73
|
console.log('Waiting for jobs...');
|
|
74
74
|
}
|