modular365-shared 1.0.3

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.
Files changed (66) hide show
  1. package/dist/createService.d.ts +20 -0
  2. package/dist/createService.d.ts.map +1 -0
  3. package/dist/createService.js +65 -0
  4. package/dist/createService.js.map +1 -0
  5. package/dist/dsClient.d.ts +11 -0
  6. package/dist/dsClient.d.ts.map +1 -0
  7. package/dist/dsClient.js +73 -0
  8. package/dist/dsClient.js.map +1 -0
  9. package/dist/index.d.ts +20 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +63 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/logger.d.ts +3 -0
  14. package/dist/logger.d.ts.map +1 -0
  15. package/dist/logger.js +18 -0
  16. package/dist/logger.js.map +1 -0
  17. package/dist/middleware/cors.d.ts +8 -0
  18. package/dist/middleware/cors.d.ts.map +1 -0
  19. package/dist/middleware/cors.js +19 -0
  20. package/dist/middleware/cors.js.map +1 -0
  21. package/dist/middleware/errorHandler.d.ts +7 -0
  22. package/dist/middleware/errorHandler.d.ts.map +1 -0
  23. package/dist/middleware/errorHandler.js +27 -0
  24. package/dist/middleware/errorHandler.js.map +1 -0
  25. package/dist/middleware/jwtAuth.d.ts +6 -0
  26. package/dist/middleware/jwtAuth.d.ts.map +1 -0
  27. package/dist/middleware/jwtAuth.js +36 -0
  28. package/dist/middleware/jwtAuth.js.map +1 -0
  29. package/dist/middleware/requestId.d.ts +7 -0
  30. package/dist/middleware/requestId.d.ts.map +1 -0
  31. package/dist/middleware/requestId.js +15 -0
  32. package/dist/middleware/requestId.js.map +1 -0
  33. package/dist/middleware/requestLogger.d.ts +8 -0
  34. package/dist/middleware/requestLogger.d.ts.map +1 -0
  35. package/dist/middleware/requestLogger.js +36 -0
  36. package/dist/middleware/requestLogger.js.map +1 -0
  37. package/dist/middleware/securityHeaders.d.ts +3 -0
  38. package/dist/middleware/securityHeaders.d.ts.map +1 -0
  39. package/dist/middleware/securityHeaders.js +12 -0
  40. package/dist/middleware/securityHeaders.js.map +1 -0
  41. package/dist/queue/connection.d.ts +4 -0
  42. package/dist/queue/connection.d.ts.map +1 -0
  43. package/dist/queue/connection.js +26 -0
  44. package/dist/queue/connection.js.map +1 -0
  45. package/dist/queue/queues.d.ts +16 -0
  46. package/dist/queue/queues.d.ts.map +1 -0
  47. package/dist/queue/queues.js +75 -0
  48. package/dist/queue/queues.js.map +1 -0
  49. package/dist/types/express-augment.d.ts +18 -0
  50. package/dist/types/express-augment.d.ts.map +1 -0
  51. package/dist/types/express-augment.js +4 -0
  52. package/dist/types/express-augment.js.map +1 -0
  53. package/dist/types/express.d.ts +8 -0
  54. package/dist/types/index.d.ts +94 -0
  55. package/dist/types/index.d.ts.map +1 -0
  56. package/dist/types/index.js +4 -0
  57. package/dist/types/index.js.map +1 -0
  58. package/dist/utils/AppError.d.ts +35 -0
  59. package/dist/utils/AppError.d.ts.map +1 -0
  60. package/dist/utils/AppError.js +46 -0
  61. package/dist/utils/AppError.js.map +1 -0
  62. package/dist/utils/helpers.d.ts +9 -0
  63. package/dist/utils/helpers.d.ts.map +1 -0
  64. package/dist/utils/helpers.js +40 -0
  65. package/dist/utils/helpers.js.map +1 -0
  66. package/package.json +27 -0
@@ -0,0 +1,20 @@
1
+ import { Express } from 'express';
2
+ import { DataServiceClient } from './dsClient';
3
+ import type pino from 'pino';
4
+ export interface ServiceOptions {
5
+ name: string;
6
+ port: number;
7
+ registerRoutes: (app: Express, ds: DataServiceClient, logger: pino.Logger) => void;
8
+ }
9
+ export interface ServiceInstance {
10
+ app: Express;
11
+ ds: DataServiceClient;
12
+ logger: pino.Logger;
13
+ start: () => Promise<void>;
14
+ }
15
+ /**
16
+ * Standard service bootstrap used by every microservice.
17
+ * Sets up middleware stack, health check, structured logging, graceful shutdown.
18
+ */
19
+ export declare function createService(opts: ServiceOptions): ServiceInstance;
20
+ //# sourceMappingURL=createService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createService.d.ts","sourceRoot":"","sources":["../src/createService.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAO3C,OAAO,EAA2B,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGxE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;CACpF;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,OAAO,CAAC;IACb,EAAE,EAAE,iBAAiB,CAAC;IACtB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAqDnE"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createService = createService;
7
+ const express_1 = __importDefault(require("express"));
8
+ const cors_1 = require("./middleware/cors");
9
+ const requestId_1 = require("./middleware/requestId");
10
+ const securityHeaders_1 = require("./middleware/securityHeaders");
11
+ const requestLogger_1 = require("./middleware/requestLogger");
12
+ const errorHandler_1 = require("./middleware/errorHandler");
13
+ const logger_1 = require("./logger");
14
+ const dsClient_1 = require("./dsClient");
15
+ const connection_1 = require("./queue/connection");
16
+ const queues_1 = require("./queue/queues");
17
+ /**
18
+ * Standard service bootstrap used by every microservice.
19
+ * Sets up middleware stack, health check, structured logging, graceful shutdown.
20
+ */
21
+ function createService(opts) {
22
+ const logger = (0, logger_1.createLogger)(opts.name);
23
+ const dataServiceUrl = process.env.DATA_SERVICE_URL;
24
+ const dataServiceApiKey = process.env.DATA_SERVICE_API_KEY;
25
+ if (!dataServiceUrl || !dataServiceApiKey) {
26
+ logger.fatal('DATA_SERVICE_URL and DATA_SERVICE_API_KEY are required');
27
+ process.exit(1);
28
+ }
29
+ const ds = (0, dsClient_1.createDataServiceClient)(dataServiceUrl, dataServiceApiKey);
30
+ const app = (0, express_1.default)();
31
+ // Global middleware
32
+ app.use(securityHeaders_1.securityHeaders);
33
+ app.use((0, cors_1.createCorsMiddleware)());
34
+ app.use(requestId_1.requestIdMiddleware);
35
+ app.use((0, requestLogger_1.createRequestLogger)(logger));
36
+ // Health check — always accessible, before auth
37
+ app.get('/health', (_req, res) => {
38
+ res.json({ status: 'ok', service: opts.name });
39
+ });
40
+ // Service-specific routes
41
+ opts.registerRoutes(app, ds, logger);
42
+ // Error handler — must be last
43
+ app.use(errorHandler_1.errorHandler);
44
+ const start = async () => {
45
+ const server = app.listen(opts.port, () => {
46
+ logger.info({ port: opts.port }, `${opts.name} running`);
47
+ });
48
+ server.timeout = 120000;
49
+ const shutdown = async () => {
50
+ logger.info('Shutting down...');
51
+ server.close();
52
+ await (0, queues_1.closeAllQueues)();
53
+ await (0, connection_1.closeRedisConnection)();
54
+ process.exit(0);
55
+ };
56
+ process.on('SIGTERM', shutdown);
57
+ process.on('SIGINT', shutdown);
58
+ setTimeout(() => {
59
+ logger.error('Forced shutdown after timeout');
60
+ process.exit(1);
61
+ }, 10000).unref();
62
+ };
63
+ return { app, ds, logger, start };
64
+ }
65
+ //# sourceMappingURL=createService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createService.js","sourceRoot":"","sources":["../src/createService.ts"],"names":[],"mappings":";;;;;AA6BA,sCAqDC;AAlFD,sDAA2C;AAC3C,4CAAyD;AACzD,sDAA6D;AAC7D,kEAA+D;AAC/D,8DAAiE;AACjE,4DAAyD;AACzD,qCAAwC;AACxC,yCAAwE;AACxE,mDAA0D;AAC1D,2CAAgD;AAgBhD;;;GAGG;AACH,SAAgB,aAAa,CAAC,IAAoB;IAChD,MAAM,MAAM,GAAG,IAAA,qBAAY,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEvC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACpD,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC3D,IAAI,CAAC,cAAc,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,GAAG,IAAA,kCAAuB,EAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;IACtE,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IAEtB,oBAAoB;IACpB,GAAG,CAAC,GAAG,CAAC,iCAAe,CAAC,CAAC;IACzB,GAAG,CAAC,GAAG,CAAC,IAAA,2BAAoB,GAAE,CAAC,CAAC;IAChC,GAAG,CAAC,GAAG,CAAC,+BAAmB,CAAC,CAAC;IAC7B,GAAG,CAAC,GAAG,CAAC,IAAA,mCAAmB,EAAC,MAAM,CAAC,CAAC,CAAC;IAErC,gDAAgD;IAChD,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAErC,+BAA+B;IAC/B,GAAG,CAAC,GAAG,CAAC,2BAAY,CAAC,CAAC;IAEtB,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC;QAExB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,IAAA,uBAAc,GAAE,CAAC;YACvB,MAAM,IAAA,iCAAoB,GAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,UAAU,CAAC,GAAG,EAAE;YACd,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { QuerySpec, MutateSpec, TransactionSpec, QueryResult, MutateResult, SchemaResult } from './types';
2
+ export declare class DataServiceClient {
3
+ private client;
4
+ constructor(baseURL: string, apiKey: string);
5
+ query(spec: QuerySpec): Promise<QueryResult>;
6
+ mutate(spec: MutateSpec): Promise<MutateResult>;
7
+ transaction(spec: TransactionSpec): Promise<MutateResult[]>;
8
+ schema(table: string, tenantId: string): Promise<SchemaResult | null>;
9
+ }
10
+ export declare function createDataServiceClient(baseURL: string, apiKey: string): DataServiceClient;
11
+ //# sourceMappingURL=dsClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsClient.d.ts","sourceRoot":"","sources":["../src/dsClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/G,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAgB;gBAElB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAWrC,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAU5C,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAU/C,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAU3D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAY5E;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAE1F"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DataServiceClient = void 0;
7
+ exports.createDataServiceClient = createDataServiceClient;
8
+ const axios_1 = __importDefault(require("axios"));
9
+ class DataServiceClient {
10
+ constructor(baseURL, apiKey) {
11
+ this.client = axios_1.default.create({
12
+ baseURL,
13
+ headers: {
14
+ 'X-API-Key': apiKey,
15
+ 'Content-Type': 'application/json',
16
+ },
17
+ timeout: 30000,
18
+ });
19
+ }
20
+ async query(spec) {
21
+ var _a, _b;
22
+ try {
23
+ const { data } = await this.client.post('/api/v1/query', spec);
24
+ return data;
25
+ }
26
+ catch (err) {
27
+ const axErr = err;
28
+ throw new Error(((_b = (_a = axErr.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || axErr.message || 'Query failed');
29
+ }
30
+ }
31
+ async mutate(spec) {
32
+ var _a, _b;
33
+ try {
34
+ const { data } = await this.client.post('/api/v1/mutate', spec);
35
+ return data;
36
+ }
37
+ catch (err) {
38
+ const axErr = err;
39
+ throw new Error(((_b = (_a = axErr.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || axErr.message || 'Mutate failed');
40
+ }
41
+ }
42
+ async transaction(spec) {
43
+ var _a, _b;
44
+ try {
45
+ const { data } = await this.client.post('/api/v1/transaction', spec);
46
+ return data;
47
+ }
48
+ catch (err) {
49
+ const axErr = err;
50
+ throw new Error(((_b = (_a = axErr.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || axErr.message || 'Transaction failed');
51
+ }
52
+ }
53
+ async schema(table, tenantId) {
54
+ var _a, _b, _c;
55
+ try {
56
+ const { data } = await this.client.get(`/api/v1/schema/${table}`, {
57
+ params: { tenant_id: tenantId },
58
+ });
59
+ return data;
60
+ }
61
+ catch (err) {
62
+ const axErr = err;
63
+ if (((_a = axErr.response) === null || _a === void 0 ? void 0 : _a.status) === 404)
64
+ return null;
65
+ throw new Error(((_c = (_b = axErr.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) || axErr.message || 'Schema fetch failed');
66
+ }
67
+ }
68
+ }
69
+ exports.DataServiceClient = DataServiceClient;
70
+ function createDataServiceClient(baseURL, apiKey) {
71
+ return new DataServiceClient(baseURL, apiKey);
72
+ }
73
+ //# sourceMappingURL=dsClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsClient.js","sourceRoot":"","sources":["../src/dsClient.ts"],"names":[],"mappings":";;;;;;AA6DA,0DAEC;AA/DD,kDAA6C;AAG7C,MAAa,iBAAiB;IAG5B,YAAY,OAAe,EAAE,MAAc;QACzC,IAAI,CAAC,MAAM,GAAG,eAAK,CAAC,MAAM,CAAC;YACzB,OAAO;YACP,OAAO,EAAE;gBACP,WAAW,EAAE,MAAM;gBACnB,cAAc,EAAE,kBAAkB;aACnC;YACD,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAe;;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAqE,CAAC;YACpF,MAAM,IAAI,KAAK,CAAC,CAAA,MAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,IAAI,0CAAE,KAAK,KAAI,KAAK,CAAC,OAAO,IAAI,cAAc,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAgB;;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAqE,CAAC;YACpF,MAAM,IAAI,KAAK,CAAC,CAAA,MAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,IAAI,0CAAE,KAAK,KAAI,KAAK,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAqB;;QACrC,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAqE,CAAC;YACpF,MAAM,IAAI,KAAK,CAAC,CAAA,MAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,IAAI,0CAAE,KAAK,KAAI,KAAK,CAAC,OAAO,IAAI,oBAAoB,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,QAAgB;;QAC1C,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,KAAK,EAAE,EAAE;gBAChE,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE;aAChC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAsF,CAAC;YACrG,IAAI,CAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,MAAM,MAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,CAAA,MAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,IAAI,0CAAE,KAAK,KAAI,KAAK,CAAC,OAAO,IAAI,qBAAqB,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;CACF;AAxDD,8CAwDC;AAED,SAAgB,uBAAuB,CAAC,OAAe,EAAE,MAAc;IACrE,OAAO,IAAI,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import './types/express-augment';
2
+ export * from './types';
3
+ export { DataServiceClient, createDataServiceClient } from './dsClient';
4
+ export { createService } from './createService';
5
+ export type { ServiceOptions, ServiceInstance } from './createService';
6
+ export { createLogger } from './logger';
7
+ export { AppError } from './utils/AppError';
8
+ export { errorHandler } from './middleware/errorHandler';
9
+ export { createJwtAuthMiddleware } from './middleware/jwtAuth';
10
+ export type { JwtAuthOptions } from './middleware/jwtAuth';
11
+ export { createCorsMiddleware } from './middleware/cors';
12
+ export type { CorsOptions } from './middleware/cors';
13
+ export { requestIdMiddleware } from './middleware/requestId';
14
+ export { securityHeaders } from './middleware/securityHeaders';
15
+ export { createRequestLogger } from './middleware/requestLogger';
16
+ export { getQueue, createWorker, closeAllQueues, QUEUE_NAMES } from './queue/queues';
17
+ export type { QueueName } from './queue/queues';
18
+ export { getRedisConnection, closeRedisConnection } from './queue/connection';
19
+ export { parseOrderBy, isSafeIdent, loadLang, allowedExtensions } from './utils/helpers';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,yBAAyB,CAAC;AAGjC,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAGxE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACrF,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAG9E,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.allowedExtensions = exports.loadLang = exports.isSafeIdent = exports.parseOrderBy = exports.closeRedisConnection = exports.getRedisConnection = exports.QUEUE_NAMES = exports.closeAllQueues = exports.createWorker = exports.getQueue = exports.createRequestLogger = exports.securityHeaders = exports.requestIdMiddleware = exports.createCorsMiddleware = exports.createJwtAuthMiddleware = exports.errorHandler = exports.AppError = exports.createLogger = exports.createService = exports.createDataServiceClient = exports.DataServiceClient = void 0;
18
+ // ── Express Augmentation (side-effect: augments Express.Request) ──
19
+ require("./types/express-augment");
20
+ // ── Types ────────────────────────────────────────────────────
21
+ __exportStar(require("./types"), exports);
22
+ // ── Data Service Client ──────────────────────────────────────
23
+ var dsClient_1 = require("./dsClient");
24
+ Object.defineProperty(exports, "DataServiceClient", { enumerable: true, get: function () { return dsClient_1.DataServiceClient; } });
25
+ Object.defineProperty(exports, "createDataServiceClient", { enumerable: true, get: function () { return dsClient_1.createDataServiceClient; } });
26
+ // ── Service Bootstrap ────────────────────────────────────────
27
+ var createService_1 = require("./createService");
28
+ Object.defineProperty(exports, "createService", { enumerable: true, get: function () { return createService_1.createService; } });
29
+ // ── Logger ───────────────────────────────────────────────────
30
+ var logger_1 = require("./logger");
31
+ Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
32
+ // ── Error Handling ───────────────────────────────────────────
33
+ var AppError_1 = require("./utils/AppError");
34
+ Object.defineProperty(exports, "AppError", { enumerable: true, get: function () { return AppError_1.AppError; } });
35
+ var errorHandler_1 = require("./middleware/errorHandler");
36
+ Object.defineProperty(exports, "errorHandler", { enumerable: true, get: function () { return errorHandler_1.errorHandler; } });
37
+ // ── Middleware ────────────────────────────────────────────────
38
+ var jwtAuth_1 = require("./middleware/jwtAuth");
39
+ Object.defineProperty(exports, "createJwtAuthMiddleware", { enumerable: true, get: function () { return jwtAuth_1.createJwtAuthMiddleware; } });
40
+ var cors_1 = require("./middleware/cors");
41
+ Object.defineProperty(exports, "createCorsMiddleware", { enumerable: true, get: function () { return cors_1.createCorsMiddleware; } });
42
+ var requestId_1 = require("./middleware/requestId");
43
+ Object.defineProperty(exports, "requestIdMiddleware", { enumerable: true, get: function () { return requestId_1.requestIdMiddleware; } });
44
+ var securityHeaders_1 = require("./middleware/securityHeaders");
45
+ Object.defineProperty(exports, "securityHeaders", { enumerable: true, get: function () { return securityHeaders_1.securityHeaders; } });
46
+ var requestLogger_1 = require("./middleware/requestLogger");
47
+ Object.defineProperty(exports, "createRequestLogger", { enumerable: true, get: function () { return requestLogger_1.createRequestLogger; } });
48
+ // ── Queue ────────────────────────────────────────────────────
49
+ var queues_1 = require("./queue/queues");
50
+ Object.defineProperty(exports, "getQueue", { enumerable: true, get: function () { return queues_1.getQueue; } });
51
+ Object.defineProperty(exports, "createWorker", { enumerable: true, get: function () { return queues_1.createWorker; } });
52
+ Object.defineProperty(exports, "closeAllQueues", { enumerable: true, get: function () { return queues_1.closeAllQueues; } });
53
+ Object.defineProperty(exports, "QUEUE_NAMES", { enumerable: true, get: function () { return queues_1.QUEUE_NAMES; } });
54
+ var connection_1 = require("./queue/connection");
55
+ Object.defineProperty(exports, "getRedisConnection", { enumerable: true, get: function () { return connection_1.getRedisConnection; } });
56
+ Object.defineProperty(exports, "closeRedisConnection", { enumerable: true, get: function () { return connection_1.closeRedisConnection; } });
57
+ // ── Utilities ────────────────────────────────────────────────
58
+ var helpers_1 = require("./utils/helpers");
59
+ Object.defineProperty(exports, "parseOrderBy", { enumerable: true, get: function () { return helpers_1.parseOrderBy; } });
60
+ Object.defineProperty(exports, "isSafeIdent", { enumerable: true, get: function () { return helpers_1.isSafeIdent; } });
61
+ Object.defineProperty(exports, "loadLang", { enumerable: true, get: function () { return helpers_1.loadLang; } });
62
+ Object.defineProperty(exports, "allowedExtensions", { enumerable: true, get: function () { return helpers_1.allowedExtensions; } });
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,qEAAqE;AACrE,mCAAiC;AAEjC,gEAAgE;AAChE,0CAAwB;AAExB,gEAAgE;AAChE,uCAAwE;AAA/D,6GAAA,iBAAiB,OAAA;AAAE,mHAAA,uBAAuB,OAAA;AAEnD,gEAAgE;AAChE,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAGtB,gEAAgE;AAChE,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AAErB,gEAAgE;AAChE,6CAA4C;AAAnC,oGAAA,QAAQ,OAAA;AACjB,0DAAyD;AAAhD,4GAAA,YAAY,OAAA;AAErB,iEAAiE;AACjE,gDAA+D;AAAtD,kHAAA,uBAAuB,OAAA;AAEhC,0CAAyD;AAAhD,4GAAA,oBAAoB,OAAA;AAE7B,oDAA6D;AAApD,gHAAA,mBAAmB,OAAA;AAC5B,gEAA+D;AAAtD,kHAAA,eAAe,OAAA;AACxB,4DAAiE;AAAxD,oHAAA,mBAAmB,OAAA;AAE5B,gEAAgE;AAChE,yCAAqF;AAA5E,kGAAA,QAAQ,OAAA;AAAE,sGAAA,YAAY,OAAA;AAAE,wGAAA,cAAc,OAAA;AAAE,qGAAA,WAAW,OAAA;AAE5D,iDAA8E;AAArE,gHAAA,kBAAkB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAEjD,gEAAgE;AAChE,2CAAyF;AAAhF,uGAAA,YAAY,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,mGAAA,QAAQ,OAAA;AAAE,4GAAA,iBAAiB,OAAA"}
@@ -0,0 +1,3 @@
1
+ import pino from 'pino';
2
+ export declare function createLogger(serviceName: string): pino.Logger;
3
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAQ7D"}
package/dist/logger.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createLogger = createLogger;
7
+ const pino_1 = __importDefault(require("pino"));
8
+ const isProduction = process.env.NODE_ENV === 'production';
9
+ function createLogger(serviceName) {
10
+ return (0, pino_1.default)({
11
+ name: serviceName,
12
+ level: process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug'),
13
+ ...(isProduction
14
+ ? {}
15
+ : { transport: { target: 'pino-pretty', options: { colorize: true } } }),
16
+ });
17
+ }
18
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;;;AAIA,oCAQC;AAZD,gDAAwB;AAExB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAE3D,SAAgB,YAAY,CAAC,WAAmB;IAC9C,OAAO,IAAA,cAAI,EAAC;QACV,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,GAAG,CAAC,YAAY;YACd,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;KAC3E,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export interface CorsOptions {
3
+ origin?: string;
4
+ methods?: string;
5
+ headers?: string;
6
+ }
7
+ export declare function createCorsMiddleware(opts?: CorsOptions): (req: Request, res: Response, next: NextFunction) => void;
8
+ //# sourceMappingURL=cors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,WAAgB,IAKpC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAU5E"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCorsMiddleware = createCorsMiddleware;
4
+ function createCorsMiddleware(opts = {}) {
5
+ const origin = opts.origin || '*';
6
+ const methods = opts.methods || 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
7
+ const headers = opts.headers || 'Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Request-ID, X-Tenant-ID';
8
+ return function cors(req, res, next) {
9
+ res.header('Access-Control-Allow-Origin', origin);
10
+ res.header('Access-Control-Allow-Headers', headers);
11
+ res.header('Access-Control-Allow-Methods', methods);
12
+ if (req.method === 'OPTIONS') {
13
+ res.sendStatus(200);
14
+ return;
15
+ }
16
+ next();
17
+ };
18
+ }
19
+ //# sourceMappingURL=cors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":";;AAQA,oDAeC;AAfD,SAAgB,oBAAoB,CAAC,OAAoB,EAAE;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,wCAAwC,CAAC;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,0FAA0F,CAAC;IAE3H,OAAO,SAAS,IAAI,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QAClE,GAAG,CAAC,MAAM,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;QAClD,GAAG,CAAC,MAAM,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;QACpD,GAAG,CAAC,MAAM,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ /**
3
+ * Global Express error handler — converts all errors to RFC 7807 Problem Detail.
4
+ * Register AFTER all routes: app.use(errorHandler)
5
+ */
6
+ export declare function errorHandler(err: Error, req: Request, res: Response, _next: NextFunction): void;
7
+ //# sourceMappingURL=errorHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM1D;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAgB/F"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.errorHandler = errorHandler;
4
+ const AppError_1 = require("../utils/AppError");
5
+ const logger_1 = require("../logger");
6
+ const logger = (0, logger_1.createLogger)('error-handler');
7
+ /**
8
+ * Global Express error handler — converts all errors to RFC 7807 Problem Detail.
9
+ * Register AFTER all routes: app.use(errorHandler)
10
+ */
11
+ function errorHandler(err, req, res, _next) {
12
+ if (err instanceof AppError_1.AppError) {
13
+ const problem = err.toProblemDetail(`${req.method} ${req.originalUrl}`);
14
+ logger.warn({ status: err.status, path: req.originalUrl, detail: err.message }, 'App error');
15
+ res.status(err.status).json(problem);
16
+ return;
17
+ }
18
+ logger.error({ err, path: req.originalUrl }, 'Unhandled error');
19
+ res.status(500).json({
20
+ type: 'https://api.modular365.co.il/errors/internal-server-error',
21
+ title: 'Internal Server Error',
22
+ status: 500,
23
+ detail: process.env.NODE_ENV === 'production' ? 'An unexpected error occurred' : err.message,
24
+ instance: `${req.method} ${req.originalUrl}`,
25
+ });
26
+ }
27
+ //# sourceMappingURL=errorHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":";;AAUA,oCAgBC;AAzBD,gDAA6C;AAC7C,sCAAyC;AAEzC,MAAM,MAAM,GAAG,IAAA,qBAAY,EAAC,eAAe,CAAC,CAAC;AAE7C;;;GAGG;AACH,SAAgB,YAAY,CAAC,GAAU,EAAE,GAAY,EAAE,GAAa,EAAE,KAAmB;IACvF,IAAI,GAAG,YAAY,mBAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7F,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAChE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,2DAA2D;QACjE,KAAK,EAAE,uBAAuB;QAC9B,MAAM,EAAE,GAAG;QACX,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO;QAC5F,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE;KAC7C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export interface JwtAuthOptions {
3
+ secret: string;
4
+ }
5
+ export declare function createJwtAuthMiddleware(opts: JwtAuthOptions): (req: Request, _res: Response, next: NextFunction) => void;
6
+ //# sourceMappingURL=jwtAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwtAuth.d.ts","sourceRoot":"","sources":["../../src/middleware/jwtAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI1D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,IAClC,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CA0BhF"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createJwtAuthMiddleware = createJwtAuthMiddleware;
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const AppError_1 = require("../utils/AppError");
9
+ function createJwtAuthMiddleware(opts) {
10
+ return function jwtAuth(req, _res, next) {
11
+ const authHeader = req.headers['authorization'];
12
+ if (!authHeader) {
13
+ throw AppError_1.AppError.unauthorized('Missing Authorization header');
14
+ }
15
+ const token = authHeader.split(' ')[1];
16
+ if (!token) {
17
+ throw AppError_1.AppError.unauthorized('Invalid Authorization header format');
18
+ }
19
+ try {
20
+ const decoded = jsonwebtoken_1.default.verify(token, opts.secret);
21
+ req.user = decoded;
22
+ req.company = decoded.company;
23
+ req.tenantId = decoded.company;
24
+ if (!req.company) {
25
+ throw AppError_1.AppError.badRequest('Token missing company claim');
26
+ }
27
+ next();
28
+ }
29
+ catch (err) {
30
+ if (err instanceof AppError_1.AppError)
31
+ throw err;
32
+ throw AppError_1.AppError.forbidden('Invalid or expired token');
33
+ }
34
+ };
35
+ }
36
+ //# sourceMappingURL=jwtAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwtAuth.js","sourceRoot":"","sources":["../../src/middleware/jwtAuth.ts"],"names":[],"mappings":";;;;;AAQA,0DA2BC;AAlCD,gEAA+B;AAC/B,gDAA6C;AAM7C,SAAgB,uBAAuB,CAAC,IAAoB;IAC1D,OAAO,SAAS,OAAO,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB;QACtE,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,mBAAQ,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,mBAAQ,CAAC,YAAY,CAAC,qCAAqC,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAA4B,CAAC;YAC1E,GAAG,CAAC,IAAI,GAAG,OAAkC,CAAC;YAC9C,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,OAAiB,CAAC;YACxC,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAiB,CAAC;YAEzC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,mBAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC,CAAC;YAC3D,CAAC;YACD,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,mBAAQ;gBAAE,MAAM,GAAG,CAAC;YACvC,MAAM,mBAAQ,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ /**
3
+ * Injects X-Request-ID into every request. Uses existing header if present
4
+ * (forwarded from gateway), otherwise generates a new UUID.
5
+ */
6
+ export declare function requestIdMiddleware(req: Request, res: Response, next: NextFunction): void;
7
+ //# sourceMappingURL=requestId.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestId.d.ts","sourceRoot":"","sources":["../../src/middleware/requestId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAKzF"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestIdMiddleware = requestIdMiddleware;
4
+ const crypto_1 = require("crypto");
5
+ /**
6
+ * Injects X-Request-ID into every request. Uses existing header if present
7
+ * (forwarded from gateway), otherwise generates a new UUID.
8
+ */
9
+ function requestIdMiddleware(req, res, next) {
10
+ const requestId = req.headers['x-request-id'] || (0, crypto_1.randomUUID)();
11
+ req.requestId = requestId;
12
+ res.setHeader('X-Request-ID', requestId);
13
+ next();
14
+ }
15
+ //# sourceMappingURL=requestId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestId.js","sourceRoot":"","sources":["../../src/middleware/requestId.ts"],"names":[],"mappings":";;AAOA,kDAKC;AAXD,mCAAoC;AAEpC;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IACjF,MAAM,SAAS,GAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAY,IAAI,IAAA,mBAAU,GAAE,CAAC;IAC1E,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACzC,IAAI,EAAE,CAAC;AACT,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import pino from 'pino';
3
+ /**
4
+ * Structured request logging:
5
+ * { method, path, statusCode, duration_ms, userId, tenantId, traceId }
6
+ */
7
+ export declare function createRequestLogger(logger: pino.Logger): (req: Request, res: Response, next: NextFunction) => void;
8
+ //# sourceMappingURL=requestLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestLogger.d.ts","sourceRoot":"","sources":["../../src/middleware/requestLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,IACvB,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CA0BrF"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRequestLogger = createRequestLogger;
4
+ /**
5
+ * Structured request logging:
6
+ * { method, path, statusCode, duration_ms, userId, tenantId, traceId }
7
+ */
8
+ function createRequestLogger(logger) {
9
+ return function requestLogger(req, res, next) {
10
+ const start = Date.now();
11
+ res.on('finish', () => {
12
+ var _a;
13
+ const duration = Date.now() - start;
14
+ const logData = {
15
+ method: req.method,
16
+ path: req.originalUrl,
17
+ statusCode: res.statusCode,
18
+ duration_ms: duration,
19
+ traceId: req.requestId,
20
+ userId: (_a = req.user) === null || _a === void 0 ? void 0 : _a.id,
21
+ tenantId: req.company,
22
+ };
23
+ if (res.statusCode >= 500) {
24
+ logger.error(logData, 'Request failed');
25
+ }
26
+ else if (res.statusCode >= 400) {
27
+ logger.warn(logData, 'Request error');
28
+ }
29
+ else {
30
+ logger.info(logData, 'Request completed');
31
+ }
32
+ });
33
+ next();
34
+ };
35
+ }
36
+ //# sourceMappingURL=requestLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestLogger.js","sourceRoot":"","sources":["../../src/middleware/requestLogger.ts"],"names":[],"mappings":";;AAOA,kDA2BC;AA/BD;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,MAAmB;IACrD,OAAO,SAAS,aAAa,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;;YACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACpC,MAAM,OAAO,GAAG;gBACd,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,GAAG,CAAC,WAAW;gBACrB,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,WAAW,EAAE,QAAQ;gBACrB,OAAO,EAAE,GAAG,CAAC,SAAS;gBACtB,MAAM,EAAE,MAAA,GAAG,CAAC,IAAI,0CAAE,EAAE;gBACpB,QAAQ,EAAE,GAAG,CAAC,OAAO;aACtB,CAAC;YAEF,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBAC1B,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;YAC1C,CAAC;iBAAM,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export declare function securityHeaders(_req: Request, res: Response, next: NextFunction): void;
3
+ //# sourceMappingURL=securityHeaders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"securityHeaders.d.ts","sourceRoot":"","sources":["../../src/middleware/securityHeaders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAOtF"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.securityHeaders = securityHeaders;
4
+ function securityHeaders(_req, res, next) {
5
+ res.setHeader('X-Content-Type-Options', 'nosniff');
6
+ res.setHeader('X-Frame-Options', 'DENY');
7
+ res.setHeader('X-XSS-Protection', '0');
8
+ res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
9
+ res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
10
+ next();
11
+ }
12
+ //# sourceMappingURL=securityHeaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"securityHeaders.js","sourceRoot":"","sources":["../../src/middleware/securityHeaders.ts"],"names":[],"mappings":";;AAEA,0CAOC;AAPD,SAAgB,eAAe,CAAC,IAAa,EAAE,GAAa,EAAE,IAAkB;IAC9E,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;IACnD,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACzC,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACvC,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,iCAAiC,CAAC,CAAC;IACpE,GAAG,CAAC,SAAS,CAAC,2BAA2B,EAAE,qCAAqC,CAAC,CAAC;IAClF,IAAI,EAAE,CAAC;AACT,CAAC"}
@@ -0,0 +1,4 @@
1
+ import IORedis from 'ioredis';
2
+ export declare function getRedisConnection(): IORedis;
3
+ export declare function closeRedisConnection(): Promise<void>;
4
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/queue/connection.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAI9B,wBAAgB,kBAAkB,IAAI,OAAO,CAS5C;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK1D"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getRedisConnection = getRedisConnection;
7
+ exports.closeRedisConnection = closeRedisConnection;
8
+ const ioredis_1 = __importDefault(require("ioredis"));
9
+ let sharedConnection = null;
10
+ function getRedisConnection() {
11
+ if (!sharedConnection) {
12
+ const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
13
+ sharedConnection = new ioredis_1.default(redisUrl, {
14
+ maxRetriesPerRequest: null, // required by BullMQ
15
+ enableReadyCheck: false,
16
+ });
17
+ }
18
+ return sharedConnection;
19
+ }
20
+ async function closeRedisConnection() {
21
+ if (sharedConnection) {
22
+ await sharedConnection.quit();
23
+ sharedConnection = null;
24
+ }
25
+ }
26
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/queue/connection.ts"],"names":[],"mappings":";;;;;AAIA,gDASC;AAED,oDAKC;AApBD,sDAA8B;AAE9B,IAAI,gBAAgB,GAAmB,IAAI,CAAC;AAE5C,SAAgB,kBAAkB;IAChC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,wBAAwB,CAAC;QACnE,gBAAgB,GAAG,IAAI,iBAAO,CAAC,QAAQ,EAAE;YACvC,oBAAoB,EAAE,IAAI,EAAE,qBAAqB;YACjD,gBAAgB,EAAE,KAAK;SACxB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,gBAAiB,CAAC;AAC3B,CAAC;AAEM,KAAK,UAAU,oBAAoB;IACxC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAC9B,gBAAgB,GAAG,IAAI,CAAC;IAC1B,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Queue, Worker, Job } from 'bullmq';
2
+ export declare const QUEUE_NAMES: {
3
+ readonly EMAIL: "email";
4
+ readonly SMS: "sms";
5
+ readonly PDF_GENERATION: "pdf-generation";
6
+ readonly EVENT_RUNNER: "event-runner";
7
+ readonly AUDIT: "audit";
8
+ readonly PAYMENT_RECURRING: "payment-recurring";
9
+ readonly REMINDER: "reminder";
10
+ readonly DATA_SYNC: "data-sync";
11
+ };
12
+ export type QueueName = typeof QUEUE_NAMES[keyof typeof QUEUE_NAMES];
13
+ export declare function getQueue(name: QueueName): Queue;
14
+ export declare function createWorker<T>(name: QueueName, processor: (job: Job<T>) => Promise<void>, concurrency?: number): Worker<T>;
15
+ export declare function closeAllQueues(): Promise<void>;
16
+ //# sourceMappingURL=queues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queues.d.ts","sourceRoot":"","sources":["../../src/queue/queues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAM5C,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAIrE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAe/C;AAED,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACzC,WAAW,GAAE,MAAU,GACtB,MAAM,CAAC,CAAC,CAAC,CA+BX;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAKpD"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QUEUE_NAMES = void 0;
4
+ exports.getQueue = getQueue;
5
+ exports.createWorker = createWorker;
6
+ exports.closeAllQueues = closeAllQueues;
7
+ const bullmq_1 = require("bullmq");
8
+ const connection_1 = require("./connection");
9
+ const logger_1 = require("../logger");
10
+ const logger = (0, logger_1.createLogger)('queue');
11
+ exports.QUEUE_NAMES = {
12
+ EMAIL: 'email',
13
+ SMS: 'sms',
14
+ PDF_GENERATION: 'pdf-generation',
15
+ EVENT_RUNNER: 'event-runner',
16
+ AUDIT: 'audit',
17
+ PAYMENT_RECURRING: 'payment-recurring',
18
+ REMINDER: 'reminder',
19
+ DATA_SYNC: 'data-sync',
20
+ };
21
+ const queues = new Map();
22
+ function getQueue(name) {
23
+ let queue = queues.get(name);
24
+ if (!queue) {
25
+ queue = new bullmq_1.Queue(name, {
26
+ connection: (0, connection_1.getRedisConnection)(),
27
+ defaultJobOptions: {
28
+ attempts: 3,
29
+ backoff: { type: 'exponential', delay: 2000 },
30
+ removeOnComplete: { count: 1000 },
31
+ removeOnFail: { count: 5000 },
32
+ },
33
+ });
34
+ queues.set(name, queue);
35
+ }
36
+ return queue;
37
+ }
38
+ function createWorker(name, processor, concurrency = 1) {
39
+ const worker = new bullmq_1.Worker(name, async (job) => {
40
+ const start = Date.now();
41
+ try {
42
+ await processor(job);
43
+ logger.info({
44
+ worker: name,
45
+ jobId: job.id,
46
+ duration_ms: Date.now() - start,
47
+ status: 'success',
48
+ }, 'Job completed');
49
+ }
50
+ catch (err) {
51
+ logger.error({
52
+ worker: name,
53
+ jobId: job.id,
54
+ attempt: job.attemptsMade,
55
+ error: err.message,
56
+ status: 'failed',
57
+ }, 'Job failed');
58
+ throw err;
59
+ }
60
+ }, {
61
+ connection: (0, connection_1.getRedisConnection)(),
62
+ concurrency,
63
+ });
64
+ worker.on('error', (err) => {
65
+ logger.error({ worker: name, error: err.message }, 'Worker error');
66
+ });
67
+ return worker;
68
+ }
69
+ async function closeAllQueues() {
70
+ for (const [, queue] of queues) {
71
+ await queue.close();
72
+ }
73
+ queues.clear();
74
+ }
75
+ //# sourceMappingURL=queues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queues.js","sourceRoot":"","sources":["../../src/queue/queues.ts"],"names":[],"mappings":";;;AAqBA,4BAeC;AAED,oCAmCC;AAED,wCAKC;AAhFD,mCAA4C;AAC5C,6CAAkD;AAClD,sCAAyC;AAEzC,MAAM,MAAM,GAAG,IAAA,qBAAY,EAAC,OAAO,CAAC,CAAC;AAExB,QAAA,WAAW,GAAG;IACzB,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,cAAc;IAC5B,KAAK,EAAE,OAAO;IACd,iBAAiB,EAAE,mBAAmB;IACtC,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;CACd,CAAC;AAIX,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;AAExC,SAAgB,QAAQ,CAAC,IAAe;IACtC,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,cAAK,CAAC,IAAI,EAAE;YACtB,UAAU,EAAE,IAAA,+BAAkB,GAAE;YAChC,iBAAiB,EAAE;gBACjB,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE;gBAC7C,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;gBACjC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;aAC9B;SACF,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,YAAY,CAC1B,IAAe,EACf,SAAyC,EACzC,cAAsB,CAAC;IAEvB,MAAM,MAAM,GAAG,IAAI,eAAM,CAAI,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,GAAG,CAAC,EAAE;gBACb,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC/B,MAAM,EAAE,SAAS;aAClB,EAAE,eAAe,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC;gBACX,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,GAAG,CAAC,EAAE;gBACb,OAAO,EAAE,GAAG,CAAC,YAAY;gBACzB,KAAK,EAAG,GAAa,CAAC,OAAO;gBAC7B,MAAM,EAAE,QAAQ;aACjB,EAAE,YAAY,CAAC,CAAC;YACjB,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,EAAE;QACD,UAAU,EAAE,IAAA,+BAAkB,GAAE;QAChC,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACzB,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,KAAK,UAAU,cAAc;IAClC,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAC/B,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC"}
@@ -0,0 +1,18 @@
1
+ declare global {
2
+ namespace Express {
3
+ interface Request {
4
+ user?: {
5
+ id: number;
6
+ user: string;
7
+ company: string;
8
+ roles?: string[];
9
+ permissions?: string[];
10
+ };
11
+ company?: string;
12
+ requestId?: string;
13
+ tenantId?: string;
14
+ }
15
+ }
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=express-augment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express-augment.d.ts","sourceRoot":"","sources":["../../src/types/express-augment.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAC;gBAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;gBAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;aAAE,CAAC;YAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB;KACF;CACF;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /// <reference types="express" />
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=express-augment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express-augment.js","sourceRoot":"","sources":["../../src/types/express-augment.ts"],"names":[],"mappings":";AAAA,iCAAiC"}
@@ -0,0 +1,8 @@
1
+ declare namespace Express {
2
+ interface Request {
3
+ user?: { id: number; user: string; company: string; roles?: string[]; permissions?: string[] };
4
+ company?: string;
5
+ requestId?: string;
6
+ tenantId?: string;
7
+ }
8
+ }
@@ -0,0 +1,94 @@
1
+ export interface FilterLeaf {
2
+ field: string;
3
+ op: string;
4
+ value: unknown;
5
+ }
6
+ export interface FilterGroup {
7
+ and?: Array<FilterLeaf | FilterGroup>;
8
+ or?: Array<FilterLeaf | FilterGroup>;
9
+ }
10
+ export interface SortSpec {
11
+ field: string;
12
+ direction: 'ASC' | 'DESC';
13
+ }
14
+ export interface PaginationSpec {
15
+ page: number;
16
+ per_page: number;
17
+ }
18
+ export interface AggregateSpec {
19
+ function: 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX' | 'COUNT_DISTINCT';
20
+ field: string;
21
+ alias?: string;
22
+ }
23
+ export interface JoinSpec {
24
+ table: string;
25
+ type: 'INNER' | 'LEFT' | 'RIGHT';
26
+ on: {
27
+ left: string;
28
+ right: string;
29
+ };
30
+ }
31
+ export interface QuerySpec {
32
+ table: string;
33
+ select?: string[];
34
+ filters?: FilterGroup;
35
+ joins?: JoinSpec[];
36
+ sort?: SortSpec[];
37
+ pagination?: PaginationSpec;
38
+ aggregates?: AggregateSpec[];
39
+ group_by?: string[];
40
+ tenant_id: string;
41
+ }
42
+ export interface MutateSpec {
43
+ operation: 'insert' | 'update' | 'delete' | 'upsert';
44
+ table: string;
45
+ data?: Record<string, unknown>;
46
+ filters?: FilterGroup;
47
+ details?: Array<{
48
+ table: string;
49
+ rows: Record<string, unknown>[];
50
+ }>;
51
+ validate?: boolean;
52
+ tenant_id: string;
53
+ }
54
+ export interface TransactionSpec {
55
+ operations: MutateSpec[];
56
+ tenant_id: string;
57
+ }
58
+ export interface QueryResult {
59
+ data: Record<string, unknown>[];
60
+ total: number;
61
+ page: number;
62
+ per_page: number;
63
+ }
64
+ export interface MutateResult {
65
+ affected_rows: number;
66
+ insert_id: number;
67
+ returning?: Record<string, unknown>[];
68
+ }
69
+ export interface SchemaResult {
70
+ columns: string[];
71
+ schema: Record<string, unknown>[];
72
+ }
73
+ export interface ApiResponse<T = unknown> {
74
+ data: T;
75
+ meta?: {
76
+ page: number;
77
+ perPage: number;
78
+ total: number;
79
+ totalPages: number;
80
+ };
81
+ }
82
+ export interface ProblemDetail {
83
+ type: string;
84
+ title: string;
85
+ status: number;
86
+ detail: string;
87
+ instance?: string;
88
+ errors?: Array<{
89
+ field: string;
90
+ message: string;
91
+ code: string;
92
+ }>;
93
+ }
94
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC;IACtC,EAAE,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,gBAAgB,CAAC;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CACnC;AAID,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // ── Data Service Types ───────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA,gEAAgE"}
@@ -0,0 +1,35 @@
1
+ import type { ProblemDetail } from '../types';
2
+ export declare class AppError extends Error {
3
+ readonly status: number;
4
+ readonly type: string;
5
+ readonly title: string;
6
+ readonly errors?: Array<{
7
+ field: string;
8
+ message: string;
9
+ code: string;
10
+ }>;
11
+ constructor(opts: {
12
+ status: number;
13
+ title: string;
14
+ detail: string;
15
+ type?: string;
16
+ errors?: Array<{
17
+ field: string;
18
+ message: string;
19
+ code: string;
20
+ }>;
21
+ });
22
+ toProblemDetail(instance?: string): ProblemDetail;
23
+ static badRequest(detail: string, errors?: Array<{
24
+ field: string;
25
+ message: string;
26
+ code: string;
27
+ }>): AppError;
28
+ static unauthorized(detail?: string): AppError;
29
+ static forbidden(detail?: string): AppError;
30
+ static notFound(detail?: string): AppError;
31
+ static conflict(detail: string): AppError;
32
+ static tooManyRequests(detail?: string): AppError;
33
+ static internal(detail?: string): AppError;
34
+ }
35
+ //# sourceMappingURL=AppError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppError.d.ts","sourceRoot":"","sources":["../../src/utils/AppError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;gBAErE,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAClE;IASD,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,aAAa;IAWjD,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,QAAQ;IAI7G,MAAM,CAAC,YAAY,CAAC,MAAM,GAAE,MAAkC,GAAG,QAAQ;IAIzE,MAAM,CAAC,SAAS,CAAC,MAAM,GAAE,MAAmC,GAAG,QAAQ;IAIvE,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAE,MAA6B,GAAG,QAAQ;IAIhE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIzC,MAAM,CAAC,eAAe,CAAC,MAAM,GAAE,MAA8B,GAAG,QAAQ;IAIxE,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAE,MAAgC,GAAG,QAAQ;CAGpE"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppError = void 0;
4
+ class AppError extends Error {
5
+ constructor(opts) {
6
+ super(opts.detail);
7
+ this.name = 'AppError';
8
+ this.status = opts.status;
9
+ this.title = opts.title;
10
+ this.type = opts.type || `https://api.modular365.co.il/errors/${opts.title.toLowerCase().replace(/\s+/g, '-')}`;
11
+ this.errors = opts.errors;
12
+ }
13
+ toProblemDetail(instance) {
14
+ return {
15
+ type: this.type,
16
+ title: this.title,
17
+ status: this.status,
18
+ detail: this.message,
19
+ instance,
20
+ errors: this.errors,
21
+ };
22
+ }
23
+ static badRequest(detail, errors) {
24
+ return new AppError({ status: 400, title: 'Bad Request', detail, errors });
25
+ }
26
+ static unauthorized(detail = 'Authentication required') {
27
+ return new AppError({ status: 401, title: 'Unauthorized', detail });
28
+ }
29
+ static forbidden(detail = 'Insufficient permissions') {
30
+ return new AppError({ status: 403, title: 'Forbidden', detail });
31
+ }
32
+ static notFound(detail = 'Resource not found') {
33
+ return new AppError({ status: 404, title: 'Not Found', detail });
34
+ }
35
+ static conflict(detail) {
36
+ return new AppError({ status: 409, title: 'Conflict', detail });
37
+ }
38
+ static tooManyRequests(detail = 'Rate limit exceeded') {
39
+ return new AppError({ status: 429, title: 'Too Many Requests', detail });
40
+ }
41
+ static internal(detail = 'Internal server error') {
42
+ return new AppError({ status: 500, title: 'Internal Server Error', detail });
43
+ }
44
+ }
45
+ exports.AppError = AppError;
46
+ //# sourceMappingURL=AppError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppError.js","sourceRoot":"","sources":["../../src/utils/AppError.ts"],"names":[],"mappings":";;;AAEA,MAAa,QAAS,SAAQ,KAAK;IAMjC,YAAY,IAMX;QACC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,uCAAuC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;QAChH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,eAAe,CAAC,QAAiB;QAC/B,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,OAAO;YACpB,QAAQ;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,MAAc,EAAE,MAAgE;QAChG,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,SAAiB,yBAAyB;QAC5D,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,SAAiB,0BAA0B;QAC1D,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,SAAiB,oBAAoB;QACnD,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,MAAc;QAC5B,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,SAAiB,qBAAqB;QAC3D,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,SAAiB,uBAAuB;QACtD,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,CAAC;CACF;AA3DD,4BA2DC"}
@@ -0,0 +1,9 @@
1
+ import type { DataServiceClient } from '../dsClient';
2
+ export declare function parseOrderBy(str: string | undefined | null): Array<{
3
+ field: string;
4
+ direction: string;
5
+ }>;
6
+ export declare const isSafeIdent: (s: unknown) => s is string;
7
+ export declare function loadLang(ds: DataServiceClient, company: string): Promise<Map<string, Record<string, unknown>>>;
8
+ export declare const allowedExtensions: string[];
9
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAQxG;AAED,eAAO,MAAM,WAAW,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,MACM,CAAC;AAErD,wBAAsB,QAAQ,CAAC,EAAE,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAOpH;AAgBD,eAAO,MAAM,iBAAiB,UAAiD,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.allowedExtensions = exports.isSafeIdent = void 0;
4
+ exports.parseOrderBy = parseOrderBy;
5
+ exports.loadLang = loadLang;
6
+ function parseOrderBy(str) {
7
+ if (!(str === null || str === void 0 ? void 0 : str.trim()))
8
+ return [{ field: 'fid', direction: 'DESC' }];
9
+ return str.split(',').map(part => {
10
+ const parts = part.trim().split(/\s+/);
11
+ const field = parts[0].replace(/`/g, '');
12
+ const direction = (parts[1] || 'ASC').toUpperCase() === 'DESC' ? 'DESC' : 'ASC';
13
+ return { field, direction };
14
+ });
15
+ }
16
+ const isSafeIdent = (s) => typeof s === 'string' && /^[A-Za-z0-9_]+$/.test(s);
17
+ exports.isSafeIdent = isSafeIdent;
18
+ async function loadLang(ds, company) {
19
+ const result = await ds.query({
20
+ table: 'lang',
21
+ tenant_id: company,
22
+ pagination: { page: 1, per_page: 10000 },
23
+ });
24
+ return new Map(result.data.map((r) => [String(r.id), r]));
25
+ }
26
+ const generateMix = (str) => {
27
+ let results = [''];
28
+ for (const char of str) {
29
+ const newResults = [];
30
+ for (const partial of results) {
31
+ newResults.push(partial + char.toLowerCase());
32
+ newResults.push(partial + char.toUpperCase());
33
+ }
34
+ results = newResults;
35
+ }
36
+ return results;
37
+ };
38
+ const allowedBase = ['jpg', 'jpeg', 'bmp', 'png', 'xls', 'pdf', 'xlsx', 'doc', 'docx', 'txt'];
39
+ exports.allowedExtensions = [...new Set(allowedBase.flatMap(generateMix))];
40
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":";;;AAGA,oCAQC;AAKD,4BAOC;AApBD,SAAgB,YAAY,CAAC,GAA8B;IACzD,IAAI,CAAC,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,IAAI,EAAE,CAAA;QAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAChF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,MAAM,WAAW,GAAG,CAAC,CAAU,EAAe,EAAE,CACrD,OAAO,CAAC,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AADxC,QAAA,WAAW,eAC6B;AAE9C,KAAK,UAAU,QAAQ,CAAC,EAAqB,EAAE,OAAe;IACnE,MAAM,MAAM,GAAgB,MAAM,EAAE,CAAC,KAAK,CAAC;QACzC,KAAK,EAAE,MAAM;QACb,SAAS,EAAE,OAAO;QAClB,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE;KACzC,CAAC,CAAC;IACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,GAAW,EAAY,EAAE;IAC5C,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC;IACnB,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAC9C,UAAU,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,GAAG,UAAU,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACjF,QAAA,iBAAiB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "modular365-shared",
3
+ "version": "1.0.3",
4
+ "description": "Shared utilities ",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": ["dist"],
8
+ "scripts": {
9
+ "build": "tsc && node -e \"require('fs').copyFileSync('src/types/express.d.ts','dist/types/express.d.ts')\"",
10
+ "dev": "tsc --watch",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "dependencies": {
14
+ "axios": "^1.7.9",
15
+ "express": "^5.1.0",
16
+ "jsonwebtoken": "^9.0.2",
17
+ "pino": "^9.6.0",
18
+ "pino-pretty": "^13.0.0",
19
+ "bullmq": "^5.34.8"
20
+ },
21
+ "devDependencies": {
22
+ "@types/express": "^5.0.0",
23
+ "@types/jsonwebtoken": "^9.0.9",
24
+ "@types/node": "^22.0.0",
25
+ "typescript": "^5.7.0"
26
+ }
27
+ }