@triophore/falcon-cli 1.0.6 → 1.0.8
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/ModelGenerator.js +37 -5
- package/lib/RouteGenerator.js +24 -17
- package/package.json +1 -1
- package/templates/example-route.js +10 -79
package/lib/ModelGenerator.js
CHANGED
|
@@ -37,7 +37,7 @@ class ModelGenerator {
|
|
|
37
37
|
|
|
38
38
|
// Generate model interactively
|
|
39
39
|
const modelContent = await this.buildModelInteractively(modelName);
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
// Write model file
|
|
42
42
|
const modelPath = path.join(modelsDir, `${modelName.toLowerCase()}.js`);
|
|
43
43
|
await fs.writeFile(modelPath, modelContent);
|
|
@@ -56,7 +56,7 @@ class ModelGenerator {
|
|
|
56
56
|
async buildModelInteractively(modelName) {
|
|
57
57
|
const fields = {};
|
|
58
58
|
const indexes = [];
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
// Add timestamps option
|
|
61
61
|
const useTimestamps = await confirm({
|
|
62
62
|
message: 'Enable timestamps (createdAt, updatedAt)?',
|
|
@@ -76,7 +76,7 @@ class ModelGenerator {
|
|
|
76
76
|
|
|
77
77
|
const fieldName = await input({
|
|
78
78
|
message: 'Field name:',
|
|
79
|
-
validate: v => v && !fields[v] ? true : 'Invalid or duplicate field name',
|
|
79
|
+
validate: v => v.trim() && !fields[v.trim()] ? true : 'Invalid or duplicate field name',
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
const fieldType = await select({
|
|
@@ -120,6 +120,38 @@ class ModelGenerator {
|
|
|
120
120
|
validate: v => !v || !isNaN(v) ? true : 'Must be a number'
|
|
121
121
|
});
|
|
122
122
|
if (maxLength) fieldOptions.maxlength = parseInt(maxLength);
|
|
123
|
+
|
|
124
|
+
// Enum support for String
|
|
125
|
+
const hasEnum = await confirm({
|
|
126
|
+
message: 'Should this field have enum values (restricted choices)?',
|
|
127
|
+
default: false
|
|
128
|
+
});
|
|
129
|
+
if (hasEnum) {
|
|
130
|
+
const enumValues = await input({
|
|
131
|
+
message: 'Enter enum values (comma-separated):',
|
|
132
|
+
validate: v => v.trim() ? true : 'At least one enum value is required'
|
|
133
|
+
});
|
|
134
|
+
fieldOptions.enum = enumValues.split(',').map(v => v.trim()).filter(v => v);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (fieldType === 'Number') {
|
|
139
|
+
// Enum support for Number
|
|
140
|
+
const hasEnum = await confirm({
|
|
141
|
+
message: 'Should this field have enum values (restricted choices)?',
|
|
142
|
+
default: false
|
|
143
|
+
});
|
|
144
|
+
if (hasEnum) {
|
|
145
|
+
const enumValues = await input({
|
|
146
|
+
message: 'Enter enum values (comma-separated numbers):',
|
|
147
|
+
validate: v => {
|
|
148
|
+
if (!v.trim()) return 'At least one enum value is required';
|
|
149
|
+
const values = v.split(',').map(n => n.trim());
|
|
150
|
+
return values.every(n => !isNaN(n)) ? true : 'All values must be numbers';
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
fieldOptions.enum = enumValues.split(',').map(v => parseFloat(v.trim()));
|
|
154
|
+
}
|
|
123
155
|
}
|
|
124
156
|
|
|
125
157
|
if (fieldType === 'ObjectId') {
|
|
@@ -130,7 +162,7 @@ class ModelGenerator {
|
|
|
130
162
|
fieldOptions.ref = refModel;
|
|
131
163
|
}
|
|
132
164
|
|
|
133
|
-
fields[fieldName] = {
|
|
165
|
+
fields[fieldName.trim()] = {
|
|
134
166
|
type: fieldType,
|
|
135
167
|
...fieldOptions
|
|
136
168
|
};
|
|
@@ -180,7 +212,7 @@ ${fieldsCode}
|
|
|
180
212
|
if (match) {
|
|
181
213
|
const modelsArray = match[1];
|
|
182
214
|
if (!modelsArray.includes(`"${modelName}"`)) {
|
|
183
|
-
const newModelsArray = modelsArray.trim()
|
|
215
|
+
const newModelsArray = modelsArray.trim()
|
|
184
216
|
? `${modelsArray.trim()}, "${modelName}"`
|
|
185
217
|
: `"${modelName}"`;
|
|
186
218
|
settingsContent = settingsContent.replace(
|
package/lib/RouteGenerator.js
CHANGED
|
@@ -77,26 +77,33 @@ class RouteGenerator {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
getRouteTemplate(name, method) {
|
|
80
|
-
method = method === '*' ? 'ANY' : method;
|
|
80
|
+
method = method === '*' ? 'ANY' : method; //${method}
|
|
81
81
|
return `/**
|
|
82
82
|
* ${method} Route for ${name}
|
|
83
83
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
84
|
+
|
|
85
|
+
module.exports.route = async function (context) {
|
|
86
|
+
return {
|
|
87
|
+
options: {
|
|
88
|
+
tags: ['api'],
|
|
89
|
+
description: 'Auto-generated ${method} route',
|
|
90
|
+
notes: 'Returns example data',
|
|
91
|
+
validate: {} // Add payload/query/params validation here
|
|
92
|
+
},
|
|
93
|
+
handler: async (request, h) => {
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
message: 'Hello from Falcon.js!',
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
// data: request.payload // for POST/PUT
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
`
|
|
105
|
+
|
|
106
|
+
;
|
|
100
107
|
}
|
|
101
108
|
}
|
|
102
109
|
|
package/package.json
CHANGED
|
@@ -4,91 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
module.exports.route = async function (context) {
|
|
7
|
-
|
|
8
|
-
// Example GET route
|
|
9
|
-
context.server.route({
|
|
10
|
-
method: 'GET',
|
|
11
|
-
path: '/api/example',
|
|
12
|
-
options: {
|
|
13
|
-
tags: ['api', 'example'],
|
|
14
|
-
description: 'Example GET endpoint',
|
|
15
|
-
notes: 'Returns example data'
|
|
16
|
-
},
|
|
17
|
-
handler: async (request, h) => {
|
|
18
|
-
return {
|
|
19
|
-
success: true,
|
|
20
|
-
message: 'Hello from Falcon.js!',
|
|
21
|
-
timestamp: new Date().toISOString()
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// Example POST route with validation
|
|
27
|
-
context.server.route({
|
|
7
|
+
return {
|
|
28
8
|
method: 'POST',
|
|
29
9
|
path: '/api/example',
|
|
30
10
|
options: {
|
|
31
|
-
tags: ['api'
|
|
32
|
-
description: '
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
11
|
+
tags: ['api'],
|
|
12
|
+
description: 'Auto-generated POST route',
|
|
13
|
+
notes: 'Returns example data',
|
|
14
|
+
validate: {} // Add payload/query/params validation here
|
|
36
15
|
},
|
|
37
16
|
handler: async (request, h) => {
|
|
38
|
-
const { name, email } = request.payload;
|
|
39
|
-
|
|
40
|
-
// Example: Save to database if models are available
|
|
41
|
-
if (context.models.example) {
|
|
42
|
-
const result = await context.models.example.create({
|
|
43
|
-
name,
|
|
44
|
-
email,
|
|
45
|
-
createdAt: new Date()
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
success: true,
|
|
50
|
-
data: result,
|
|
51
|
-
message: 'Data saved successfully'
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
17
|
return {
|
|
56
18
|
success: true,
|
|
57
|
-
message: '
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Example route that sends job to worker
|
|
64
|
-
context.server.route({
|
|
65
|
-
method: 'POST',
|
|
66
|
-
path: '/api/example/job',
|
|
67
|
-
options: {
|
|
68
|
-
tags: ['api', 'jobs'],
|
|
69
|
-
description: 'Queue a job for processing'
|
|
70
|
-
},
|
|
71
|
-
handler: async (request, h) => {
|
|
72
|
-
const jobData = request.payload;
|
|
73
|
-
|
|
74
|
-
// Send job to worker via MQTT (if available)
|
|
75
|
-
if (context.mqtt_client) {
|
|
76
|
-
context.mqtt_client.publish('worker_example_job', JSON.stringify({
|
|
77
|
-
jobId: Date.now().toString(),
|
|
78
|
-
data: jobData,
|
|
79
|
-
timestamp: new Date().toISOString()
|
|
80
|
-
}));
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
success: true,
|
|
84
|
-
message: 'Job queued for processing'
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
success: false,
|
|
90
|
-
message: 'Job queue not available'
|
|
19
|
+
message: 'Hello from Falcon.js!',
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
// data: request.payload // for POST/PUT
|
|
91
22
|
};
|
|
92
23
|
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
24
|
+
};
|
|
25
|
+
};
|