@avtechno/sfr 1.0.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.
@@ -0,0 +1,395 @@
1
+ /// <reference types="typescript" />
2
+
3
+
4
+
5
+ declare type ServiceTypes = ("core" | "application" | "adapter" | "ai-agent");
6
+
7
+ declare type Multer = import("multer").Multer;
8
+
9
+ declare type OAPI_Document = import("openapi-types").OpenAPIV3_1.Document;
10
+ declare type InfoObject = import("openapi-types").OpenAPIV3_1.InfoObject;
11
+ declare type Express = import("express").Express;
12
+ declare type Server = import("socket.io").Server;
13
+ declare type NextFunction = import("express").NextFunction;
14
+ declare type RequestHandler = import("express").RequestHandler;
15
+ declare type ExpressRequest = import("express").Request;
16
+ declare type ExpressResponse = import("express").Response;
17
+ declare type ChannelModel = import("amqplib").Channel;
18
+ declare type Socket = import("socket.io").Socket;
19
+
20
+ declare type BroadcastMQ = import("../mq.mts").BroadcastMQ;
21
+ declare type TargetedMQ = import("../mq.mts").TargetedMQ;
22
+
23
+ declare enum PROTOCOLS {
24
+ REST = "REST",
25
+ WS = "WS",
26
+ MQ = "MQ"
27
+ }
28
+
29
+
30
+ declare type RESTHandlerDescriptor<V, H, C> = {
31
+ meta?: SFRMetadata;
32
+ cfg?: SFRConfig;
33
+ validators: RequestValidators & V;
34
+ handlers: RESTRequestHandlers & H & ThisType<HandlerFacilities & C>;
35
+ controllers?: RequestControllers & C & ThisType<ControllerFacilities>;
36
+ };
37
+
38
+ declare type WSHandlerDescriptor<V, H, C> = {
39
+ cfg?: SFRConfig;
40
+ validators: RequestValidators & V;
41
+ handlers: WSRequestHandlers & H & ThisType<HandlerFacilities & C>;
42
+ controllers?: RequestControllers & C & ThisType<ControllerFacilities & C>;
43
+ };
44
+
45
+ declare interface HandlerFacilities { }
46
+
47
+ declare interface ControllerFacilities { }
48
+
49
+ declare type InjectedFacilities = {
50
+ handlers?: HandlerFacilities;
51
+ controllers?: ControllerFacilities;
52
+ }
53
+
54
+ /**
55
+ * Main Configuration object used by the bundler to apply for a given API Declaration
56
+ *
57
+ *
58
+ */
59
+ declare type SFRConfig = {
60
+ /**
61
+ * Configuration used to explicitly set the API Declaration's root directory upon binding.
62
+
63
+ * **Example**
64
+ * ```
65
+ * //The given REST Declaration will be bound to
66
+ * //"/space/*" instead of /*
67
+ *
68
+ * REST({
69
+ * cfg : {
70
+ * base_dir : "space"
71
+ * },
72
+ *
73
+ * validators : {
74
+ * },
75
+ *
76
+ * handlers : {
77
+ * }
78
+ * })
79
+ * ```
80
+ */
81
+ base_dir?: string;
82
+ /**
83
+ * Directive used to evaluate an API Declaration's public accessibility.
84
+ *
85
+ * setting this to **true (false by default)** will cause the heading middleware to skip certain checks, namely the ff.
86
+ *
87
+ * * Session Validity
88
+ * * Access Authorization
89
+ */
90
+ public?: boolean;
91
+ };
92
+
93
+ declare type OASConfig = Omit<ServiceManifest, "documents"> & InfoObject
94
+
95
+ /**
96
+ * UAC Policy Type Definitions
97
+ *
98
+ * @author Emmanuel Abellana
99
+ * @description Type definitions for service-manifest, the main interchange document for service-coupling functions.
100
+ */
101
+ declare type ServiceManifest = {
102
+ title: string;
103
+ description: string;
104
+ tags?: string[];
105
+ meta: {
106
+ //Specifies the domain of the service
107
+ domain: string;
108
+ service: string;
109
+ /**
110
+ * Specifies the type of service
111
+ *
112
+ * **core** - Specialized services, meant to be used by other types of services.
113
+ *
114
+ * **application** - Standard 1st party services.
115
+ *
116
+ * **adapter** - Services meant to couple with 3rd party services.
117
+ *
118
+ * **ai-agent** - AI-enabled service-agent.
119
+ */
120
+ //"x-service-type": ServiceTypes
121
+
122
+ /**
123
+ * Specifies the port of the service
124
+ */
125
+ port: number;
126
+
127
+ /**
128
+ * Optional: Specifies the framework used by the service
129
+ */
130
+ framework?: string[];
131
+
132
+ /**
133
+ * Optional: Specifies the language used by the service
134
+ */
135
+ language: string;
136
+
137
+ /**
138
+ * Optional: Specifies the type of the service
139
+ */
140
+ type: ("backend" | "frontend");
141
+ };
142
+ documents: ServiceDocuments
143
+ }
144
+ declare type ServiceDocuments = {
145
+ REST?: OAPI_Document;
146
+ MQ?: AsyncAPIDocument;
147
+ WS?: AsyncAPIDocument;
148
+ }
149
+
150
+ declare type RequestValidators = {
151
+ [name: string]: object | RequestHandler;
152
+ };
153
+ declare type RequestControllers = {
154
+ [name: string]: RequestController;
155
+ };
156
+ declare type RequestController = (...args: any[]) => Promise<any>;
157
+ declare type RESTRequestHandlers = {
158
+ GET?: RESTHandlerMap;
159
+ POST?: RESTHandlerMap;
160
+ PUT?: RESTHandlerMap;
161
+ PATCH?: RESTHandlerMap;
162
+ DELETE?: RESTHandlerMap;
163
+ COPY?: RESTHandlerMap;
164
+ HEAD?: RESTHandlerMap;
165
+ OPTIONS?: RESTHandlerMap;
166
+ PROPFIND?: RESTHandlerMap;
167
+ };
168
+ /**
169
+ * Mapping of endpoints and their respective metadata according to OpenAPI standards
170
+ *
171
+ * Note: Some fields are automatically inferred from the SFR build phase and as such, only a subset of the official parameters are exposed.
172
+ *
173
+ * Link: https://spec.openapis.org/oas/v3.1.0#operation-object
174
+ */
175
+ declare type SFRMetadata = {
176
+ tags?: string[];
177
+ summary?: string;
178
+ description?: string;
179
+ deprecated?: boolean;
180
+ };
181
+ declare type RESTRequestType =
182
+ "get" |
183
+ "post" |
184
+ "put" |
185
+ "patch" |
186
+ "delete" |
187
+ "copy" |
188
+ "head" |
189
+ "options" |
190
+ "propfind";
191
+ declare type RESTHandlerMap = {
192
+ [key: string]: SFRMetadata & {
193
+ fn: CustomRequestHandler
194
+ }
195
+ };
196
+ type CustomRequestHandler= (
197
+ req: ExpressRequest,
198
+ res: ExpressResponse,
199
+ next: NextFunction
200
+ ) => any;
201
+ declare type WSRequestHandler = (
202
+ ctx: WSRequestCtx,
203
+ args?: object
204
+ ) => Promise<object>;
205
+ declare type WSRequestHandlers = {
206
+ [event: string]: WSRequestHandler;
207
+ };
208
+ declare type WSRequestCtx = {
209
+ io: Server;
210
+ socket: Socket;
211
+ args: string[];
212
+ };
213
+ declare type RequestResponse =
214
+ | {
215
+ error: object;
216
+ }
217
+ | {
218
+ data: object;
219
+ };
220
+ declare type RESTNamespaceDeclaration = {
221
+ [namespace: string]: DeclarationArtifact & {
222
+ content: {
223
+ handlers: RESTRequestHandlers
224
+ }
225
+ }
226
+ };
227
+ declare type WSNamespaceDeclaration = {
228
+ [namespace: string]: DeclarationArtifact & {
229
+ content: {
230
+ handlers: WSRequestHandlers
231
+ }
232
+ }
233
+ };
234
+ declare type MQNamespaceDeclaration = {
235
+ [namespace: string]: DeclarationArtifact & {
236
+ content: {
237
+ handlers: MQRequestHandlers<any>
238
+ }
239
+ }
240
+ }
241
+ declare type DeclarationArtifact = {
242
+ name: string;
243
+ path: string;
244
+ desc?: string;
245
+ dir?: string[];
246
+ content: {
247
+ cfg: SFRConfig;
248
+ validators: RequestValidators;
249
+ controllers: RequestControllers;
250
+ }
251
+ }
252
+
253
+ declare type NamespaceDeclaration = {
254
+ REST: RESTNamespaceDeclaration;
255
+ WS: WSNamespaceDeclaration;
256
+ MQ: MQNamespaceDeclaration;
257
+ }
258
+ declare type SFRProtocols = {
259
+ REST?: Express;
260
+ WS?: Server;
261
+ MQ?: Connection;
262
+ }
263
+
264
+ declare type Operation = "Read" | "Write";
265
+ declare type Protocol = "REST" | "WS";
266
+ declare type LogFragment = {
267
+ domain: string;
268
+ user_id: string;
269
+ stamp: number;
270
+ host: string;
271
+ type: "in" | "out" | "req";
272
+ };
273
+
274
+ declare type ParserCFG = {
275
+ root: string; //Root directory of the project's source files.
276
+ path: string; //Directory of SFRs.
277
+ out?: string; //Directory for the oas output documents.
278
+ };
279
+
280
+ declare type Channel = import("amqplib").Channel;
281
+ declare type Connection = import("amqplib").Connection;
282
+ declare type ConsumeMessage = import("amqplib").ConsumeMessage;
283
+ declare type ConsumeOptions = import("amqplib").Options.Consume;
284
+
285
+ declare type ConsumerConfig = {
286
+ options?: ConsumeOptions;
287
+ fn: ((msg: ConsumeMessage) => void);
288
+ } & ThisType<ConsumerContext>;
289
+ declare type ConsumerContext = {
290
+ name: string;
291
+ type: string;
292
+ channel: Channel;
293
+ }
294
+
295
+
296
+ /* Commons */
297
+ type CommunicationPattern = (
298
+ "Point-to-Point" |
299
+ "Publish-Subscribe" |
300
+ "Request-Reply" |
301
+ "Routing" |
302
+ "Topic"
303
+ /* "Scatter-Gather" */
304
+ )
305
+
306
+ declare type PatternMQSet = {
307
+ "Point-to-Point": TargetedMQ;
308
+ "Publish-Subscribe": BroadcastMQ;
309
+ "Request-Reply": TargetedMQ;
310
+ "Routing": TargetedMQ;
311
+ "Topic": TargetedMQ;
312
+ }
313
+
314
+ declare type MQHandlerDescriptor<V, H, C> = {
315
+ cfg?: SFRConfig;
316
+ validators: RequestValidators & V;
317
+ handlers: MQRequestHandlers<C> & H & ThisType<HandlerFacilities & C>;
318
+ controllers?: RequestControllers & C & ThisType<ControllerFacilities & C>;
319
+ };
320
+
321
+ declare type MQRequestHandlers<C> = {
322
+ "Point-to-Point"?: MQRequestHandlerMap & ThisType<{ mq: Omit<TargetedMQ, "type" | "reply"> } & C>;
323
+ "Publish-Subscribe"?: MQRequestHandlerMap & ThisType<{ mq: Omit<BroadcastMQ, "type"> } & C>;
324
+ "Request-Reply"?: MQRequestHandlerMap & ThisType<{ mq: Omit<TargetedMQ, "type"> } & C>;
325
+ "Routing"?: RoutingHandlerMap & ThisType<{ mq: Omit<BroadcastMQ, "type"> } & C>;
326
+ "Topic"?: TopicHandlerMap & ThisType<{ mq: Omit<BroadcastMQ, "type"> } & C>;
327
+ };
328
+
329
+ declare type MQRequestHandlerMap = {
330
+ [name: string]: SFRMetadata & MQConsumeOptions;
331
+ }
332
+
333
+ declare type RoutingHandlerMap = {
334
+ [name: string]: SFRMetadata & RoutingOptions;
335
+ }
336
+
337
+ declare type TopicHandlerMap = {
338
+ [name: string]: SFRMetadata & TopicOptions;
339
+ }
340
+
341
+ declare type MQConsumeOptions = {
342
+ options?: ConsumeOptions;
343
+ queue?: string[];
344
+ fn: MQRequestHandler;
345
+ }
346
+
347
+ declare type RoutingOptions = MQConsumeOptions & {
348
+ routing_key: string;
349
+ }
350
+
351
+ declare type TopicOptions = MQConsumeOptions & {
352
+ binding_key: string;
353
+ }
354
+
355
+
356
+ declare type MQRequestHandler = (msg: (ConsumeMessage & { content: any }) | null) => void;
357
+
358
+
359
+ declare type MQRequestCtx = {
360
+ channel: Channel;
361
+ connection: Connection;
362
+ };
363
+
364
+ type AsyncAPIDocument = {
365
+ asyncapi: string;
366
+ info: {
367
+ title: string;
368
+ version: string;
369
+ description?: string;
370
+ };
371
+ channels: {
372
+ [channelName: string]: {
373
+ description?: string;
374
+ subscribe?: AsyncAPIMessage;
375
+ publish?: AsyncAPIMessage;
376
+ };
377
+ };
378
+ components?: {
379
+ messages: {
380
+ [messageName: string]: {
381
+ contentType: string;
382
+ payload: any;
383
+ };
384
+ };
385
+ };
386
+ };
387
+
388
+ type AsyncAPIMessage = {
389
+ summary?: string;
390
+ description?: string;
391
+ message: {
392
+ contentType: string;
393
+ payload: any;
394
+ };
395
+ };
package/src/util.mts ADDED
@@ -0,0 +1,32 @@
1
+ import fs from "fs/promises";
2
+ import { Response } from "express";
3
+ import path from "path";
4
+ import Joi from "joi";
5
+
6
+ export async function get_stats(dirs : string[], base_dir : string) {
7
+ let temp = await Promise.all(dirs.map((v)=> fs.lstat(path.join(base_dir, v)).then((stats)=> ({ stats, dir : v }))));
8
+ const result = temp.filter(({ stats })=> stats.isFile()).map((v)=> v.dir);
9
+ return result;
10
+ }
11
+
12
+ export async function assess_namespace(stats : string[], dir : string){
13
+ let dirs = stats.map((v)=> `file:///${dir.replaceAll("\\", "/")}/${v}`);
14
+ const result = await Promise.all(dirs.map((d)=> import(d).then((v)=> [d.replace(".mjs", "").substring(d.lastIndexOf("/")+1), v.default]))).then(Object.fromEntries);
15
+ return result;
16
+ }
17
+
18
+ export const template = (rule : object, v : object)=> _validate(Joi.object(rule).validate(v));
19
+ function _validate(expression : Joi.ValidationResult){
20
+ let result = expression.error;
21
+ return result ? result.details[0].message : false;
22
+ }
23
+
24
+ export const object_id = Joi.string().hex().length(24).required();
25
+
26
+ /* QoLs */
27
+
28
+ export const handle_res = (controller : Promise<any>, res : Response) =>{
29
+ controller
30
+ .then((data)=> res.json({data}))
31
+ .catch((error)=> res.status(400).json({error}));
32
+ }