@cloudnux/cli 0.1.0 → 0.11.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.
@@ -45,6 +45,89 @@
45
45
  "options"
46
46
  ]
47
47
  },
48
+ "FilterCondition": {
49
+ "oneOf": [
50
+ {
51
+ "type": [
52
+ "string",
53
+ "number",
54
+ "boolean",
55
+ "null"
56
+ ]
57
+ },
58
+ {
59
+ "type": "object",
60
+ "properties": {
61
+ "$eq": {},
62
+ "$ne": {},
63
+ "$gt": {
64
+ "type": [
65
+ "number",
66
+ "string"
67
+ ]
68
+ },
69
+ "$gte": {
70
+ "type": [
71
+ "number",
72
+ "string"
73
+ ]
74
+ },
75
+ "$lt": {
76
+ "type": [
77
+ "number",
78
+ "string"
79
+ ]
80
+ },
81
+ "$lte": {
82
+ "type": [
83
+ "number",
84
+ "string"
85
+ ]
86
+ },
87
+ "$in": {
88
+ "type": "array"
89
+ },
90
+ "$nin": {
91
+ "type": "array"
92
+ },
93
+ "$all": {
94
+ "type": "array"
95
+ },
96
+ "$size": {
97
+ "type": "number"
98
+ },
99
+ "$regex": {
100
+ "type": "string"
101
+ },
102
+ "$startsWith": {
103
+ "type": "string"
104
+ },
105
+ "$endsWith": {
106
+ "type": "string"
107
+ },
108
+ "$contains": {
109
+ "type": "string"
110
+ },
111
+ "$exists": {
112
+ "type": "boolean"
113
+ },
114
+ "$type": {
115
+ "type": "string",
116
+ "enum": [
117
+ "string",
118
+ "number",
119
+ "boolean",
120
+ "object",
121
+ "array",
122
+ "null",
123
+ "undefined"
124
+ ]
125
+ }
126
+ },
127
+ "additionalProperties": false
128
+ }
129
+ ]
130
+ },
48
131
  "ScheduleTrigger": {
49
132
  "type": "object",
50
133
  "properties": {
@@ -53,10 +136,191 @@
53
136
  "properties": {
54
137
  "pattern": {
55
138
  "type": "string"
139
+ },
140
+ "name": {
141
+ "type": "string"
142
+ }
143
+ },
144
+ "required": [
145
+ "pattern",
146
+ "name"
147
+ ],
148
+ "additionalProperties": false
149
+ }
150
+ },
151
+ "required": [
152
+ "options"
153
+ ]
154
+ },
155
+ "EventTrigger": {
156
+ "type": "object",
157
+ "properties": {
158
+ "options": {
159
+ "type": "object",
160
+ "properties": {
161
+ "source": {
162
+ "type": "string"
163
+ },
164
+ "sourceType": {
165
+ "type": "string"
166
+ },
167
+ "filter": {
168
+ "type": "object",
169
+ "additionalProperties": {
170
+ "oneOf": [
171
+ {
172
+ "type": [
173
+ "string",
174
+ "number",
175
+ "boolean",
176
+ "null"
177
+ ]
178
+ },
179
+ {
180
+ "type": "object",
181
+ "properties": {
182
+ "$eq": {},
183
+ "$ne": {},
184
+ "$gt": {
185
+ "type": [
186
+ "number",
187
+ "string"
188
+ ]
189
+ },
190
+ "$gte": {
191
+ "type": [
192
+ "number",
193
+ "string"
194
+ ]
195
+ },
196
+ "$lt": {
197
+ "type": [
198
+ "number",
199
+ "string"
200
+ ]
201
+ },
202
+ "$lte": {
203
+ "type": [
204
+ "number",
205
+ "string"
206
+ ]
207
+ },
208
+ "$in": {
209
+ "type": "array"
210
+ },
211
+ "$nin": {
212
+ "type": "array"
213
+ },
214
+ "$all": {
215
+ "type": "array"
216
+ },
217
+ "$size": {
218
+ "type": "number"
219
+ },
220
+ "$regex": {
221
+ "type": "string"
222
+ },
223
+ "$startsWith": {
224
+ "type": "string"
225
+ },
226
+ "$endsWith": {
227
+ "type": "string"
228
+ },
229
+ "$contains": {
230
+ "type": "string"
231
+ },
232
+ "$exists": {
233
+ "type": "boolean"
234
+ },
235
+ "$type": {
236
+ "type": "string",
237
+ "enum": [
238
+ "string",
239
+ "number",
240
+ "boolean",
241
+ "object",
242
+ "array",
243
+ "null",
244
+ "undefined"
245
+ ]
246
+ }
247
+ },
248
+ "additionalProperties": false
249
+ },
250
+ {
251
+ "type": "object",
252
+ "properties": {
253
+ "$and": {
254
+ "type": "array",
255
+ "items": {
256
+ "$ref": "#/definitions/FilterCondition"
257
+ }
258
+ }
259
+ },
260
+ "required": [
261
+ "$and"
262
+ ],
263
+ "additionalProperties": false
264
+ },
265
+ {
266
+ "type": "object",
267
+ "properties": {
268
+ "$or": {
269
+ "type": "array",
270
+ "items": {
271
+ "$ref": "#/definitions/FilterCondition"
272
+ }
273
+ }
274
+ },
275
+ "required": [
276
+ "$or"
277
+ ],
278
+ "additionalProperties": false
279
+ }
280
+ ]
281
+ }
56
282
  }
57
283
  },
58
284
  "required": [
59
- "pattern"
285
+ "source",
286
+ "sourceType"
287
+ ],
288
+ "additionalProperties": false
289
+ }
290
+ },
291
+ "required": [
292
+ "options"
293
+ ]
294
+ },
295
+ "WebSocketEvent": {
296
+ "enum": [
297
+ "connect",
298
+ "disconnect",
299
+ "message"
300
+ ]
301
+ },
302
+ "WebSocketTrigger": {
303
+ "type": "object",
304
+ "properties": {
305
+ "options": {
306
+ "type": "object",
307
+ "properties": {
308
+ "path": {
309
+ "type": "string"
310
+ },
311
+ "event": {
312
+ "$ref": "#/definitions/WebSocketEvent"
313
+ },
314
+ "route": {
315
+ "type": "string"
316
+ },
317
+ "routeKey": {
318
+ "type": "string"
319
+ }
320
+ },
321
+ "required": [
322
+ "path",
323
+ "event"
60
324
  ],
61
325
  "additionalProperties": false
62
326
  }
@@ -71,7 +335,9 @@
71
335
  "type": {
72
336
  "enum": [
73
337
  "http",
74
- "schedule"
338
+ "schedule",
339
+ "event",
340
+ "websocket"
75
341
  ]
76
342
  }
77
343
  },
@@ -99,6 +365,30 @@
99
365
  "then": {
100
366
  "$ref": "#/definitions/ScheduleTrigger"
101
367
  }
368
+ },
369
+ {
370
+ "if": {
371
+ "properties": {
372
+ "type": {
373
+ "const": "event"
374
+ }
375
+ }
376
+ },
377
+ "then": {
378
+ "$ref": "#/definitions/EventTrigger"
379
+ }
380
+ },
381
+ {
382
+ "if": {
383
+ "properties": {
384
+ "type": {
385
+ "const": "websocket"
386
+ }
387
+ }
388
+ },
389
+ "then": {
390
+ "$ref": "#/definitions/WebSocketTrigger"
391
+ }
102
392
  }
103
393
  ],
104
394
  "required": [
@@ -17,7 +17,7 @@
17
17
  "workingDir": {
18
18
  "type": "string",
19
19
  "description": "Path to store the current environment build artifacts",
20
- "default": ".epf/<environment>"
20
+ "default": ".nux/<environment>"
21
21
  },
22
22
  "title": {
23
23
  "type": "string",
@@ -107,7 +107,7 @@
107
107
  "workingDir": {
108
108
  "type": "string",
109
109
  "description": "Path to store the build artifacts for all environments",
110
- "default": "./.epf"
110
+ "default": "./.nux"
111
111
  },
112
112
  "environments": {
113
113
  "type": "object",
@@ -1,53 +1,72 @@
1
- import { Context, S3Event,
2
- APIGatewayProxyEventV2WithJWTAuthorizer,
3
- ScheduledEvent
4
- } from "aws-lambda";
5
-
6
- import { createRouter, httpMatcher, scheduleMatcher } from "@@cloudcore";
7
- import { functions } from "@@cloud";
8
- //import { initialize } from "@@datastore";
9
- import { logger } from "@@utils";
1
+ import { createRouter } from "@cloudnux/aws-cloud-provider/router";
2
+ import { awsCloudProvider } from "@cloudnux/aws-cloud-provider";
3
+ import {
4
+ httpHandler,
5
+ eventBrokerHandler,
6
+ scheduleHandler,
7
+ websocketHandler,
8
+ useCloudProvider,
9
+ } from "@cloudnux/cloud-sdk";
10
+ import { initializeLogger, logger } from "@cloudnux/utils";
10
11
 
11
12
  import * as src from "../../../packages/modules/<%=module%>/src";
12
13
 
13
- type AWSEventType = S3Event | APIGatewayProxyEventV2WithJWTAuthorizer | ScheduledEvent;
14
+ useCloudProvider(awsCloudProvider);
14
15
 
15
16
  const router = createRouter();
16
17
  <%_ for(var [key,entry] of Object.entries(entries)) { _%>
17
18
  <%_ if(entry.trigger.type.toLowerCase() === "http") { _%>
18
- router.add({
19
- matcher: httpMatcher("<%=entry.trigger.options.method%>", "<%=entry.trigger.options.route%>"),
20
- createContext: functions.httpAdapter.input,
21
- func: src["<%= entry.handler %>"]
22
- });
23
- <%_ } _%>
24
- <%_ if(entry.trigger.type.toLowerCase() === "schedule") { _%>
25
- router.add({
26
- matcher: scheduleMatcher("<%= key %>"),
27
- createContext: functions.scheduleAdapter.input,
28
- func: src["<%= entry.handler %>"]
29
- });
30
- <%_ } _%>
19
+ router.http(
20
+ "<%= entry.trigger.options.method %>",
21
+ "<%= entry.trigger.options.route %>",
22
+ (event, context) => {
23
+ return httpHandler(src["<%= entry.handler %>"], event, context);
24
+ }
25
+ );
26
+ <%_ } _%>
27
+ <%_ if(entry.trigger.type.toLowerCase() === "schedule") { _%>
28
+ router.schedule(
29
+ "<%= entry.trigger.options.name %>",
30
+ "<%= entry.trigger.options.pattern %>",
31
+ (event, context) => {
32
+ return scheduleHandler(src["<%= entry.handler %>"], event, context);
33
+ }
34
+ );
35
+ <%_ } _%>
36
+ <%_ if(entry.trigger.type.toLowerCase() === "event") { _%>
37
+ router.event(
38
+ "<%= entry.trigger.options.source %>",
39
+ "<%= entry.trigger.options.sourceType %>",
40
+ (event, context) => {
41
+ return eventBrokerHandler(src["<%= entry.handler %>"], event, context);
42
+ }
43
+ );
44
+ <%_ } _%>
45
+ <%_ if(entry.trigger.type.toLowerCase() === "websocket") { _%>
46
+ <%_ const wsRouteKey = entry.trigger.options.event === "connect" ? "$connect" : entry.trigger.options.event === "disconnect" ? "$disconnect" : entry.trigger.options.route || "$default" _%>
47
+ router.websocket(
48
+ "<%= wsRouteKey %>",
49
+ (event, context) => {
50
+ return websocketHandler(src["<%= entry.handler %>"],event,context);
51
+ }
52
+ );
53
+ <%_ } _%>
31
54
  <%_ } _%>
32
55
 
33
- export async function handler(event: AWSEventType, context: Context) {
34
- logger.initialize("locations", context.awsRequestId);
35
- logger.info("request started");
36
- logger.debug({ event }, "Received event");
37
-
56
+ export async function handler(event, context) {
57
+ initializeLogger("<%=module%>",context.awsRequestId);
58
+ logger.info("request started", { requestId: context.awsRequestId });
59
+ logger.debug("Received event", { event, requestId: context.awsRequestId });
60
+ let response;
38
61
  try {
39
- //await initialize();
40
- const handlerType = "rawPath" in event ? "Http" : "source" in event ? "Schedule" : null;
41
-
42
- if (!handlerType) {
43
- throw new Error("Invalid handler type");
44
- }
45
- const output = await router.run(handlerType, functions[`${handlerType.toLowerCase()}Adapter`], event, context);
46
- logger.debug({ output }, "Response Sent");
47
- logger.info("request completed");
48
- return output;
49
- } catch (error) {
50
- logger.error({ error }, "Error occurred");
62
+ response = await router.run(event, context);
63
+ return response;
64
+ }
65
+ catch (error) {
66
+ logger.error("Error occurred", { error, requestId: context.awsRequestId });
51
67
  throw error;
52
68
  }
69
+ finally {
70
+ logger.info("request finished", { response, requestId: context.awsRequestId });
71
+ }
53
72
  }
@@ -64,4 +64,22 @@ module "schedule_trigger_for_<%= module %>" {
64
64
  <% } %>
65
65
  }
66
66
  }
67
+ <% } %>
68
+
69
+ <%_ const eventEntries = Object.entries(entries).filter(([k,e]) => e.trigger.type.toLowerCase() === "event" && e.trigger.options.sourceType?.toLowerCase() === "sqs") _%>
70
+ <% if(eventEntries.length > 0) { %>
71
+ module "sqs_trigger_for_<%= module %>" {
72
+ source = "../.deploy/aws/sqs"
73
+ lambda_name = "<%= module %>"
74
+ event_sources = {
75
+ <% for(const [key,entry] of eventEntries) { %>
76
+ "<%= key %>" = {
77
+ queue_name = "<%= entry.trigger.options.source %>"
78
+ enabled = true
79
+ batch_size = 10
80
+ }
81
+ <% } %>
82
+ }
83
+ }
84
+
67
85
  <% } %>
@@ -1,106 +1,42 @@
1
- import Fastify from "fastify";
2
- import pino from "pino";
1
+ import { useCloudProvider } from "@cloudnux/cloud-sdk";
2
+ import { createRouter, localCloudProvider } from '@cloudnux/local-cloud-provider';
3
+ import { queuesPlugin } from "@cloudnux/local-cloud-provider/queue-plugin";
4
+ import { schedulerPlugin } from "@cloudnux/local-cloud-provider/schedule-plugin";
5
+ import { devConsolePlugin } from "@cloudnux/local-cloud-provider/dev-console-plugin";
6
+ import { websocketsPlugin } from "@cloudnux/local-cloud-provider/websocket-plugin";
7
+ import { initializeLogger } from "@cloudnux/utils";
8
+
9
+ useCloudProvider(localCloudProvider);
3
10
 
4
11
  <%_ for(const module of moduleNames){ _%>
5
- import <%=module%>Entries from "./<%=module%>/index.ts"
12
+ import <%=module%>Entries from "./<%=module%>"
6
13
  <%_ } _%>
7
14
 
8
- // Create a custom logger
9
- const customLogger = pino({
10
- level: 'info', // Set the log level (e.g., 'info', 'error', 'debug')
11
- base: null, // Remove default metadata like pid and hostname
12
- hooks: {
13
- logMethod(args, method) {
14
- // Intercept log messages and send them to the parent process
15
- const [message, ...rest] = args;
16
- const safePayload = JSON.stringify(message, getCircularReplacer());
17
-
18
- sendMessage('LOG', { level: method.name, message:safePayload, additionalData: rest });
19
- return method.apply(this, args);
20
- },
21
- },
22
- });
23
-
24
- // Function to send logs to the parent process
25
- function sendMessage(type: string, payload: any) {
26
-
27
- if (process && process.send) {
28
- process.send({ type, payload: payload });
29
- } else {
30
- console.log(`[${type}]`, payload); // Fallback for non-parent process
31
- }
32
- }
33
-
34
- function getCircularReplacer() {
35
- const seen = new WeakSet();
36
- return (key: string, value: any) => {
37
- if (typeof value === 'object' && value !== null) {
38
- if (seen.has(value)) {
39
- return '[Circular]';
40
- }
41
- seen.add(value);
42
- }
43
- return value;
44
- };
45
- }
46
-
47
- const fastify = Fastify({
48
- maxParamLength : 1000,
49
- loggerInstance:customLogger,
50
- });
51
-
52
- // Add fastify hooks
53
- fastify.addHook('onRegister', async (instance, opts) => {
54
- sendMessage("APP_REGISTERED", { prefix: instance.prefix, opts });
55
- });
56
-
57
- fastify.addHook('onRoute', (routeOptions) => {
58
- sendMessage('ROUTE_REGISTERED', {
59
- method: routeOptions.method,
60
- url: routeOptions.url,
61
- handler: routeOptions.handler.name,
62
- });
63
- });
64
-
65
- fastify.addHook('onListen', function (done) {
66
- try{
67
- sendMessage('LISTENING', {
68
- port: 3000,
69
- host:"::"
70
- });
71
- }catch(err){
72
- sendMessage('ERROR', {err});
73
- }finally{
74
- const err = null; // to be updated later to handle crash errors
75
- done(err)
76
- }
77
- });
15
+ const router = createRouter({logger : true});
78
16
 
79
- fastify.addHook('preHandler', (request, reply, done) => {
80
- sendMessage('REQUEST', { id: request.id, params: request.params, query: request.query, body: request.body, headers: request.headers, url: request.url, method:request.method, time: new Date().toLocaleTimeString() });
81
- done();
82
- });
17
+ router.register(queuesPlugin, { prefix: "queues" });
18
+ router.register(schedulerPlugin, { prefix: "schedules" });
19
+ router.register(devConsolePlugin, { prefix: 'console' });
20
+ router.register(websocketsPlugin, { prefix: "websockets" });
83
21
 
84
- fastify.addHook('onResponse', (request, reply, done) => {
85
- sendMessage('RESPONSE', { id: request.id, status: reply.statusCode, body: reply.raw, time: new Date().toLocaleTimeString() });
86
- done();
87
- });
22
+ <%_ for(const module of moduleNames){ _%>
23
+ router.register(<%=module%>Entries, { prefix: "api" });
24
+ <%_ } _%>
88
25
 
89
- fastify.addHook('onError', (request, reply, error, done) => {
90
- sendMessage('ERROR', {error, request, reply});
91
- done();
26
+ router.addHook('onRequest', async (request, reply) => {
27
+ const [pathname] = request.url.split('?');
28
+ const match = pathname.match(/^\/api\/([^/]+)(?:\/([^/]+))?/);
29
+ initializeLogger(match?.[2] || "", request.id);
92
30
  });
93
-
94
- // Register the fastify-raw-body plugin
95
- fastify.register(require('fastify-raw-body'), {
96
- field: 'rawBody',
97
- encoding: 'utf8',
31
+ router.addHook('onResponse', async () => {
32
+ initializeLogger("default", undefined);
98
33
  });
99
34
 
100
- <%_ for(const module of moduleNames){ _%>
101
- fastify.register(<%=module%>Entries, { prefix: "<%=module%>/" });
102
- <%_ } _%>
103
-
104
- fastify.listen({ port: 3000, host : "::" }).then((address) => {
105
- // init in entrypoint
35
+ router.listen({ port: 3000, host: "::" }, (err) => {
36
+ if (err) {
37
+ console.error('Error starting server:', err);
38
+ process.exit(1);
39
+ }
40
+ else
41
+ console.log(`Server listening on port ${router?.server?.address()?.port} ...`)
106
42
  });