@hiliosai/sdk 0.1.16 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -3
- package/dist/index.js +446 -446
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, ServiceBroker, ServiceSchema as ServiceSchema$1, ServiceSettingSchema, Service,
|
|
1
|
+
import { Context, ServiceBroker, ServiceSchema as ServiceSchema$1, ServiceSettingSchema, Service, ActionSchema, ServiceEvents, ServiceMethods, ServiceHooks, Middleware, BrokerOptions } from 'moleculer';
|
|
2
2
|
import env from '@ltv/env';
|
|
3
3
|
export { default as env } from '@ltv/env';
|
|
4
4
|
|
|
@@ -466,8 +466,6 @@ declare const PERMISSIONS: {
|
|
|
466
466
|
};
|
|
467
467
|
declare const ROLE_PERMISSIONS: Record<string, string[]>;
|
|
468
468
|
|
|
469
|
-
declare const configs: BrokerOptions;
|
|
470
|
-
|
|
471
469
|
declare enum IntegrationPlatform {
|
|
472
470
|
WHATSAPP = "whatsapp",
|
|
473
471
|
TELEGRAM = "telegram",
|
|
@@ -860,6 +858,8 @@ declare function defineService<TSettings = unknown, TDatasourceConstructors exte
|
|
|
860
858
|
|
|
861
859
|
declare function defineIntegration<TSettings = unknown, TDatasourceConstructors extends DatasourceConstructorRegistry = DatasourceConstructorRegistry>(config: IntegrationServiceConfig<TSettings, TDatasourceConstructors>): IntegrationServiceSchema<TSettings>;
|
|
862
860
|
|
|
861
|
+
declare const configs: BrokerOptions;
|
|
862
|
+
|
|
863
863
|
declare const nodeEnv: string;
|
|
864
864
|
declare const isDev: boolean;
|
|
865
865
|
declare const isTest: boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import env4 from '@ltv/env';
|
|
2
2
|
import http from 'http';
|
|
3
|
+
import crypto from 'crypto';
|
|
3
4
|
import os from 'os';
|
|
4
5
|
import { Middleware } from '@moleculer/channels';
|
|
5
|
-
import crypto from 'crypto';
|
|
6
6
|
|
|
7
7
|
// src/middlewares/datasource.middleware.ts
|
|
8
8
|
function initializeDatasources(constructorRegistry) {
|
|
@@ -52,12 +52,12 @@ function MemoizeMixin(options) {
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
-
var HEALTH_CHECK_PORT =
|
|
56
|
-
var HEALTH_CHECK_READINESS_PATH =
|
|
55
|
+
var HEALTH_CHECK_PORT = env4.int("HEALTH_CHECK_PORT", 3301);
|
|
56
|
+
var HEALTH_CHECK_READINESS_PATH = env4.string(
|
|
57
57
|
"HEALTH_CHECK_READINESS_PATH",
|
|
58
58
|
"/readyz"
|
|
59
59
|
);
|
|
60
|
-
var HEALTH_CHECK_LIVENESS_PATH =
|
|
60
|
+
var HEALTH_CHECK_LIVENESS_PATH = env4.string(
|
|
61
61
|
"HEALTH_CHECK_LIVENESS_PATH",
|
|
62
62
|
"/livez"
|
|
63
63
|
);
|
|
@@ -244,6 +244,12 @@ var ROLE_PERMISSIONS = {
|
|
|
244
244
|
PERMISSIONS["config.read"]
|
|
245
245
|
]
|
|
246
246
|
};
|
|
247
|
+
var nodeEnv = env4.string("NODE_ENV", "development");
|
|
248
|
+
var isDev = nodeEnv === "development";
|
|
249
|
+
var isTest = nodeEnv === "test";
|
|
250
|
+
var isProd = nodeEnv === "production";
|
|
251
|
+
var REDIS_URL = env4.string("REDIS_URL");
|
|
252
|
+
var env_default = env4;
|
|
247
253
|
|
|
248
254
|
// src/errors/permission.error.ts
|
|
249
255
|
var PermissionError = class _PermissionError extends Error {
|
|
@@ -285,6 +291,98 @@ var TenantError = class _TenantError extends Error {
|
|
|
285
291
|
}
|
|
286
292
|
};
|
|
287
293
|
|
|
294
|
+
// src/middlewares/permissions.middleware.ts
|
|
295
|
+
var permissionHandlers = {
|
|
296
|
+
[PERMISSIONS.AUTHENTICATED]: async (ctx) => !!ctx.meta.user?.id,
|
|
297
|
+
[PERMISSIONS.TENANT_OWNER]: async (ctx) => ctx.meta.user?.roles.includes(PERMISSIONS.OWNER) ?? false,
|
|
298
|
+
[PERMISSIONS.TENANT_MEMBER]: async (ctx) => !!(ctx.meta.user?.tenantId && ctx.meta.tenantId && ctx.meta.user.tenantId === ctx.meta.tenantId)
|
|
299
|
+
};
|
|
300
|
+
var PermissionsMiddleware = {
|
|
301
|
+
// Wrap local action handlers
|
|
302
|
+
localAction(handler, action) {
|
|
303
|
+
if (!action.permissions) {
|
|
304
|
+
return handler;
|
|
305
|
+
}
|
|
306
|
+
const permissions = Array.isArray(action.permissions) ? action.permissions : [action.permissions];
|
|
307
|
+
const permissionNames = [];
|
|
308
|
+
const permissionFunctions = [];
|
|
309
|
+
permissions.forEach((permission) => {
|
|
310
|
+
if (typeof permission === "function") {
|
|
311
|
+
permissionFunctions.push(permission);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (typeof permission === "string") {
|
|
315
|
+
if (permission in permissionHandlers) {
|
|
316
|
+
const handler2 = permissionHandlers[permission];
|
|
317
|
+
permissionFunctions.push(handler2);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
permissionNames.push(permission);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
return async function CheckPermissionsMiddleware(ctx) {
|
|
325
|
+
let hasAccess = false;
|
|
326
|
+
if (ctx.meta.user?.roles.includes(PERMISSIONS.OWNER)) {
|
|
327
|
+
hasAccess = true;
|
|
328
|
+
}
|
|
329
|
+
if (!hasAccess && permissionFunctions.length > 0) {
|
|
330
|
+
const results = await Promise.allSettled(
|
|
331
|
+
permissionFunctions.map((fn) => fn(ctx, action))
|
|
332
|
+
);
|
|
333
|
+
hasAccess = results.some(
|
|
334
|
+
(result) => result.status === "fulfilled" && !!result.value
|
|
335
|
+
);
|
|
336
|
+
const failures = results.filter((r) => r.status === "rejected");
|
|
337
|
+
if (failures.length > 0) {
|
|
338
|
+
ctx.broker.logger.warn(
|
|
339
|
+
`${failures.length} permission functions failed`,
|
|
340
|
+
{
|
|
341
|
+
action: action.name,
|
|
342
|
+
userId: ctx.meta.user?.id
|
|
343
|
+
}
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (!hasAccess && permissionNames.length > 0) {
|
|
348
|
+
const userRoles = ctx.meta.user?.roles ?? [];
|
|
349
|
+
hasAccess = userRoles.some((role) => {
|
|
350
|
+
const rolePermissions = ROLE_PERMISSIONS[role] ?? [];
|
|
351
|
+
return permissionNames.some(
|
|
352
|
+
(permName) => rolePermissions.includes(permName)
|
|
353
|
+
);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
if (!hasAccess) {
|
|
357
|
+
const user = ctx.meta.user;
|
|
358
|
+
ctx.broker.logger.warn("Access denied:", {
|
|
359
|
+
action: action.name,
|
|
360
|
+
userId: user?.id,
|
|
361
|
+
userRoles: user?.roles,
|
|
362
|
+
tenantId: ctx.meta.tenantId,
|
|
363
|
+
requiredPermissions: permissions
|
|
364
|
+
});
|
|
365
|
+
const errorDetails = isDev ? {
|
|
366
|
+
action: action.name,
|
|
367
|
+
requiredPermissions: permissions.map(
|
|
368
|
+
(p) => typeof p === "function" ? "[Function]" : String(p)
|
|
369
|
+
),
|
|
370
|
+
userRoles: user?.roles ?? [],
|
|
371
|
+
userId: user?.id,
|
|
372
|
+
tenantId: ctx.meta.tenantId
|
|
373
|
+
} : {
|
|
374
|
+
action: action.name
|
|
375
|
+
};
|
|
376
|
+
throw new PermissionError(
|
|
377
|
+
"You do not have permission to perform this action",
|
|
378
|
+
errorDetails
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
return handler.call(this, ctx);
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
288
386
|
// src/utils/context-cache.ts
|
|
289
387
|
var ContextCache = class _ContextCache {
|
|
290
388
|
constructor() {
|
|
@@ -489,16 +587,91 @@ var ContextHelpersMiddleware = {
|
|
|
489
587
|
}
|
|
490
588
|
};
|
|
491
589
|
|
|
492
|
-
// src/
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
590
|
+
// src/mixins/datasource.mixin.ts
|
|
591
|
+
function DatasourceMixin(datasourceConstructors = {}) {
|
|
592
|
+
const datasourceInstances = {};
|
|
593
|
+
for (const [key, DatasourceClass] of Object.entries(datasourceConstructors)) {
|
|
594
|
+
datasourceInstances[key] = new DatasourceClass();
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
/**
|
|
598
|
+
* Service created lifecycle hook
|
|
599
|
+
* Initialize datasources and store on service
|
|
600
|
+
*/
|
|
601
|
+
async created() {
|
|
602
|
+
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
603
|
+
datasource.broker = this.broker;
|
|
604
|
+
}
|
|
605
|
+
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
606
|
+
if (typeof datasource.init === "function") {
|
|
607
|
+
await datasource.init();
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
this.$datasources = datasourceInstances;
|
|
611
|
+
},
|
|
612
|
+
/**
|
|
613
|
+
* Service started lifecycle hook
|
|
614
|
+
* Connect datasources that have connect method
|
|
615
|
+
*/
|
|
616
|
+
async started() {
|
|
617
|
+
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
618
|
+
if (typeof datasource.connect === "function") {
|
|
619
|
+
await datasource.connect();
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
/**
|
|
624
|
+
* Service stopped lifecycle hook
|
|
625
|
+
* Disconnect datasources that have disconnect method
|
|
626
|
+
*/
|
|
627
|
+
async stopped() {
|
|
628
|
+
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
629
|
+
if (typeof datasource.disconnect === "function") {
|
|
630
|
+
await datasource.disconnect();
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
/**
|
|
635
|
+
* Hooks to inject datasources into context
|
|
636
|
+
*/
|
|
637
|
+
hooks: {
|
|
638
|
+
before: {
|
|
639
|
+
"*": function injectDatasources(ctx) {
|
|
640
|
+
const datasources = this.$datasources ?? {};
|
|
641
|
+
for (const [, datasource] of Object.entries(datasources)) {
|
|
642
|
+
datasource.context = ctx;
|
|
643
|
+
}
|
|
644
|
+
ctx.datasources = datasources;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/utils/index.ts
|
|
652
|
+
function omit(obj, keys) {
|
|
653
|
+
const result = { ...obj };
|
|
654
|
+
keys.forEach((key) => delete result[key]);
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// src/service/define-service.ts
|
|
659
|
+
function defineService(config) {
|
|
660
|
+
const propsToOmit = ["datasources"];
|
|
661
|
+
const serviceSchema = omit(
|
|
662
|
+
config,
|
|
663
|
+
propsToOmit
|
|
664
|
+
);
|
|
665
|
+
return {
|
|
666
|
+
...serviceSchema,
|
|
667
|
+
mixins: [
|
|
668
|
+
DatasourceMixin(config.datasources),
|
|
669
|
+
MemoizeMixin(),
|
|
670
|
+
...serviceSchema.mixins ?? []
|
|
671
|
+
]
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
var NAMESPACE = env4.string("NAMESPACE", "hios").toLowerCase();
|
|
502
675
|
var CHANNELS = {
|
|
503
676
|
// Webhook processing channels
|
|
504
677
|
WEBHOOK: {
|
|
@@ -589,437 +762,7 @@ var SUBJECTS = {
|
|
|
589
762
|
// All DLQ subjects
|
|
590
763
|
DLQ_ALL: `${NAMESPACE}.dlq.>`};
|
|
591
764
|
|
|
592
|
-
// src/
|
|
593
|
-
var NAMESPACE2 = NAMESPACE.toUpperCase();
|
|
594
|
-
var middleware = Middleware({
|
|
595
|
-
adapter: {
|
|
596
|
-
type: "NATS",
|
|
597
|
-
options: {
|
|
598
|
-
nats: {
|
|
599
|
-
url: env3.string("NATS_URL", "nats://localhost:4222"),
|
|
600
|
-
/** Connection options for reliability */
|
|
601
|
-
connectionOptions: {
|
|
602
|
-
name: "hios",
|
|
603
|
-
timeout: 1e4,
|
|
604
|
-
reconnect: true,
|
|
605
|
-
maxReconnectAttempts: 10,
|
|
606
|
-
reconnectTimeWait: 2e3,
|
|
607
|
-
maxReconnectTimeWait: 3e4,
|
|
608
|
-
pingInterval: 2e4,
|
|
609
|
-
maxPingOut: 2
|
|
610
|
-
},
|
|
611
|
-
/**
|
|
612
|
-
* Stream configuration for multi-tenant messaging
|
|
613
|
-
*
|
|
614
|
-
* Environment variables for production:
|
|
615
|
-
* - NATS_MAX_MESSAGES: Default 100K (dev) -> 10M+ (prod)
|
|
616
|
-
* - NATS_MAX_BYTES_GB: Default 1GB (dev) -> 100GB+ (prod)
|
|
617
|
-
* - NATS_MAX_AGE_DAYS: Default 7 (dev) -> 30+ (prod)
|
|
618
|
-
* - NATS_MAX_MSG_SIZE_MB: Default 1MB (dev) -> 5MB (prod)
|
|
619
|
-
* - NATS_REPLICAS: Default 1 (dev) -> 3 (prod)
|
|
620
|
-
*/
|
|
621
|
-
streamConfig: {
|
|
622
|
-
name: `${NAMESPACE2}_MESSAGES`,
|
|
623
|
-
subjects: [
|
|
624
|
-
SUBJECTS.WEBHOOK_ALL,
|
|
625
|
-
SUBJECTS.PROCESSING_ALL,
|
|
626
|
-
SUBJECTS.RESPONSE_ALL,
|
|
627
|
-
SUBJECTS.SYSTEM_ALL,
|
|
628
|
-
SUBJECTS.DLQ_ALL
|
|
629
|
-
],
|
|
630
|
-
retention: "limits",
|
|
631
|
-
max_msgs: env3.int("NATS_MAX_MESSAGES", 1e5),
|
|
632
|
-
// 100K for dev, 10M+ for prod
|
|
633
|
-
max_bytes: env3.int("NATS_MAX_BYTES_GB", 1) * 1024 * 1024 * 1024,
|
|
634
|
-
// 1GB for dev, 100GB+ for prod
|
|
635
|
-
max_age: env3.int("NATS_MAX_AGE_DAYS", 7) * 24 * 60 * 60 * 1e9,
|
|
636
|
-
// 7 days dev, 30+ days prod
|
|
637
|
-
max_msg_size: env3.int("NATS_MAX_MSG_SIZE_MB", 1) * 1024 * 1024,
|
|
638
|
-
// 1MB dev, 5MB prod
|
|
639
|
-
storage: "file",
|
|
640
|
-
// Persistent storage
|
|
641
|
-
num_replicas: env3.int("NATS_REPLICAS", 1),
|
|
642
|
-
// 1 for dev, 3 for prod
|
|
643
|
-
discard: "old",
|
|
644
|
-
// Remove old messages when limits hit
|
|
645
|
-
duplicate_window: 2 * 60 * 1e9
|
|
646
|
-
// 2 minutes dedup window
|
|
647
|
-
},
|
|
648
|
-
/** Consumer options optimized for LLM processing */
|
|
649
|
-
consumerOptions: {
|
|
650
|
-
config: {
|
|
651
|
-
// Start with new messages (don't replay old ones on restart)
|
|
652
|
-
deliver_policy: "new",
|
|
653
|
-
// Explicit acknowledgment required (critical for LLM processing)
|
|
654
|
-
ack_policy: "explicit",
|
|
655
|
-
// Allow 5 unacknowledged messages per consumer (rate limiting)
|
|
656
|
-
max_ack_pending: 5,
|
|
657
|
-
// Acknowledgment timeout for LLM processing (2 minutes)
|
|
658
|
-
ack_wait: 120 * 1e9,
|
|
659
|
-
// 2 minutes in nanoseconds
|
|
660
|
-
// Maximum delivery attempts before dead letter
|
|
661
|
-
max_deliver: 3,
|
|
662
|
-
// Backoff for failed message retries
|
|
663
|
-
backoff: [
|
|
664
|
-
1e9,
|
|
665
|
-
// 1 second
|
|
666
|
-
5e9,
|
|
667
|
-
// 5 seconds
|
|
668
|
-
3e10
|
|
669
|
-
// 30 seconds
|
|
670
|
-
]
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
},
|
|
674
|
-
/** Application-level flow control */
|
|
675
|
-
maxInFlight: 5,
|
|
676
|
-
// Limit concurrent LLM requests per service
|
|
677
|
-
maxRetries: 2,
|
|
678
|
-
// App-level retries (NATS handles delivery retries)
|
|
679
|
-
/** Dead letter queue for failed messages */
|
|
680
|
-
deadLettering: {
|
|
681
|
-
enabled: true,
|
|
682
|
-
queueName: "FAILED_MESSAGES"
|
|
683
|
-
// Send to dead letter after NATS max_deliver attempts
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
});
|
|
688
|
-
var ChannelsMiddleware = {
|
|
689
|
-
...middleware
|
|
690
|
-
};
|
|
691
|
-
|
|
692
|
-
// src/configs/moleculer/circuit-breaker.ts
|
|
693
|
-
var circuitBreakerConfig = {
|
|
694
|
-
// Enable feature
|
|
695
|
-
enabled: false,
|
|
696
|
-
// Threshold value. 0.5 means that 50% should be failed for tripping.
|
|
697
|
-
threshold: 0.5,
|
|
698
|
-
// Minimum request count. Below it, CB does not trip.
|
|
699
|
-
minRequestCount: 20,
|
|
700
|
-
// Number of seconds for time window.
|
|
701
|
-
windowTime: 60,
|
|
702
|
-
// Number of milliseconds to switch from open to half-open state
|
|
703
|
-
halfOpenTime: 10 * 1e3,
|
|
704
|
-
// A function to check failed requests.
|
|
705
|
-
check: (err) => err.code >= 500
|
|
706
|
-
};
|
|
707
|
-
|
|
708
|
-
// src/configs/moleculer/logger.ts
|
|
709
|
-
var loggerConfig = {
|
|
710
|
-
type: "Console",
|
|
711
|
-
options: {
|
|
712
|
-
// Using colors on the output
|
|
713
|
-
colors: true,
|
|
714
|
-
// Print module names with different colors (like docker-compose for containers)
|
|
715
|
-
moduleColors: false,
|
|
716
|
-
// Line formatter. It can be "json", "short", "simple", "full", a `Function` or a template string like "{timestamp} {level} {nodeID}/{mod}: {msg}"
|
|
717
|
-
formatter: "full",
|
|
718
|
-
// Custom object printer. If not defined, it uses the `util.inspect` method.
|
|
719
|
-
objectPrinter: null,
|
|
720
|
-
// Auto-padding the module name in order to messages begin at the same column.
|
|
721
|
-
autoPadding: false
|
|
722
|
-
}
|
|
723
|
-
};
|
|
724
|
-
var logger_default = loggerConfig;
|
|
725
|
-
|
|
726
|
-
// src/configs/moleculer/metrics.ts
|
|
727
|
-
var metricsConfig = {
|
|
728
|
-
enabled: false,
|
|
729
|
-
// Available built-in reporters: "Console", "CSV", "Event", "Prometheus", "Datadog", "StatsD"
|
|
730
|
-
reporter: {
|
|
731
|
-
type: "Prometheus",
|
|
732
|
-
options: {
|
|
733
|
-
// HTTP port
|
|
734
|
-
port: 3030,
|
|
735
|
-
// HTTP URL path
|
|
736
|
-
path: "/metrics",
|
|
737
|
-
// Default labels which are appended to all metrics labels
|
|
738
|
-
defaultLabels: (registry) => ({
|
|
739
|
-
namespace: registry.broker.namespace,
|
|
740
|
-
nodeID: registry.broker.nodeID
|
|
741
|
-
})
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
};
|
|
745
|
-
|
|
746
|
-
// src/configs/moleculer/registry.ts
|
|
747
|
-
var registryConfig = {
|
|
748
|
-
// Define balancing strategy. More info: https://moleculer.services/docs/0.14/balancing.html
|
|
749
|
-
// Available values: "RoundRobin", "Random", "CpuUsage", "Latency", "Shard"
|
|
750
|
-
strategy: "RoundRobin",
|
|
751
|
-
// Enable local action call preferring. Always call the local action instance if available.
|
|
752
|
-
preferLocal: true
|
|
753
|
-
};
|
|
754
|
-
|
|
755
|
-
// src/configs/moleculer/retry-policy.ts
|
|
756
|
-
var retryPolicyConfig = {
|
|
757
|
-
// Enable feature
|
|
758
|
-
enabled: false,
|
|
759
|
-
// Count of retries
|
|
760
|
-
retries: 5,
|
|
761
|
-
// First delay in milliseconds.
|
|
762
|
-
delay: 100,
|
|
763
|
-
// Maximum delay in milliseconds.
|
|
764
|
-
maxDelay: 1e3,
|
|
765
|
-
// Backoff factor for delay. 2 means exponential backoff.
|
|
766
|
-
factor: 2,
|
|
767
|
-
// A function to check failed requests.
|
|
768
|
-
check: (err) => !!err.retryable
|
|
769
|
-
};
|
|
770
|
-
|
|
771
|
-
// src/configs/moleculer/tracing.ts
|
|
772
|
-
var tracingConfig = {
|
|
773
|
-
enabled: true,
|
|
774
|
-
exporter: "Console",
|
|
775
|
-
events: true,
|
|
776
|
-
stackTrace: true
|
|
777
|
-
};
|
|
778
|
-
|
|
779
|
-
// src/configs/moleculer/tracking.ts
|
|
780
|
-
var trackingConfig = {
|
|
781
|
-
// Enable feature
|
|
782
|
-
enabled: false,
|
|
783
|
-
// Number of milliseconds to wait before shuting down the process.
|
|
784
|
-
shutdownTimeout: 5e3
|
|
785
|
-
};
|
|
786
|
-
|
|
787
|
-
// src/configs/moleculer/index.ts
|
|
788
|
-
var pkgNm = env3.string("NAMESPACE", "hios");
|
|
789
|
-
var nodeID = env3.string("NODE_ID") ?? `${pkgNm}-${os.hostname()}-${process.pid}`;
|
|
790
|
-
var configs = {
|
|
791
|
-
namespace: pkgNm,
|
|
792
|
-
nodeID,
|
|
793
|
-
metadata: {},
|
|
794
|
-
logger: logger_default,
|
|
795
|
-
// Default log level for built-in console logger. It can be overwritten in logger options above.
|
|
796
|
-
// Available values: trace, debug, info, warn, error, fatal
|
|
797
|
-
logLevel: "info",
|
|
798
|
-
cacher: env3.string("REDIS_URL", "Memory"),
|
|
799
|
-
// Define a serializer.
|
|
800
|
-
// Available values: "JSON", "Avro", "ProtoBuf", "MsgPack", "Notepack", "Thrift".
|
|
801
|
-
// More info: https://moleculer.services/docs/0.14/networking.html#Serialization
|
|
802
|
-
serializer: "JSON",
|
|
803
|
-
// Number of milliseconds to wait before reject a request with a RequestTimeout error. Disabled: 0
|
|
804
|
-
requestTimeout: 10 * 1e3,
|
|
805
|
-
// Retry policy settings. More info: https://moleculer.services/docs/0.14/fault-tolerance.html#Retry
|
|
806
|
-
retryPolicy: retryPolicyConfig,
|
|
807
|
-
// Limit of calling level. If it reaches the limit, broker will throw an MaxCallLevelError error. (Infinite loop protection)
|
|
808
|
-
maxCallLevel: 100,
|
|
809
|
-
// Number of seconds to send heartbeat packet to other nodes.
|
|
810
|
-
heartbeatInterval: 10,
|
|
811
|
-
// Number of seconds to wait before setting node to unavailable status.
|
|
812
|
-
heartbeatTimeout: 30,
|
|
813
|
-
// Cloning the params of context if enabled. High performance impact, use it with caution!
|
|
814
|
-
contextParamsCloning: false,
|
|
815
|
-
// Tracking requests and waiting for running requests before shuting down. More info: https://moleculer.services/docs/0.14/context.html#Context-tracking
|
|
816
|
-
tracking: trackingConfig,
|
|
817
|
-
// Disable built-in request & emit balancer. (Transporter must support it, as well.). More info: https://moleculer.services/docs/0.14/networking.html#Disabled-balancer
|
|
818
|
-
disableBalancer: false,
|
|
819
|
-
// Settings of Service Registry. More info: https://moleculer.services/docs/0.14/registry.html
|
|
820
|
-
registry: registryConfig,
|
|
821
|
-
// Settings of Circuit Breaker. More info: https://moleculer.services/docs/0.14/fault-tolerance.html#Circuit-Breaker
|
|
822
|
-
circuitBreaker: circuitBreakerConfig,
|
|
823
|
-
// Settings of bulkhead feature. More info: https://moleculer.services/docs/0.14/fault-tolerance.html#Bulkhead
|
|
824
|
-
bulkhead: bulkheadConfig,
|
|
825
|
-
// Enable action & event parameter validation. More info: https://moleculer.services/docs/0.14/validating.html
|
|
826
|
-
validator: "Fastest",
|
|
827
|
-
// errorHandler: null,
|
|
828
|
-
transporter: env3.string("TRANSPORTER_URL"),
|
|
829
|
-
// Enable/disable built-in metrics function. More info: https://moleculer.services/docs/0.14/metrics.html
|
|
830
|
-
metrics: metricsConfig,
|
|
831
|
-
// Enable built-in tracing function. More info: https://moleculer.services/docs/0.14/tracing.html
|
|
832
|
-
tracing: tracingConfig,
|
|
833
|
-
middlewares: [
|
|
834
|
-
ChannelsMiddleware,
|
|
835
|
-
PermissionsMiddleware,
|
|
836
|
-
ContextHelpersMiddleware
|
|
837
|
-
]
|
|
838
|
-
};
|
|
839
|
-
var moleculer_default = configs;
|
|
840
|
-
var nodeEnv = env3.string("NODE_ENV", "development");
|
|
841
|
-
var isDev = nodeEnv === "development";
|
|
842
|
-
var isTest = nodeEnv === "test";
|
|
843
|
-
var isProd = nodeEnv === "production";
|
|
844
|
-
var REDIS_URL = env3.string("REDIS_URL");
|
|
845
|
-
var env_default = env3;
|
|
846
|
-
|
|
847
|
-
// src/middlewares/permissions.middleware.ts
|
|
848
|
-
var permissionHandlers = {
|
|
849
|
-
[PERMISSIONS.AUTHENTICATED]: async (ctx) => !!ctx.meta.user?.id,
|
|
850
|
-
[PERMISSIONS.TENANT_OWNER]: async (ctx) => ctx.meta.user?.roles.includes(PERMISSIONS.OWNER) ?? false,
|
|
851
|
-
[PERMISSIONS.TENANT_MEMBER]: async (ctx) => !!(ctx.meta.user?.tenantId && ctx.meta.tenantId && ctx.meta.user.tenantId === ctx.meta.tenantId)
|
|
852
|
-
};
|
|
853
|
-
var PermissionsMiddleware = {
|
|
854
|
-
// Wrap local action handlers
|
|
855
|
-
localAction(handler, action) {
|
|
856
|
-
if (!action.permissions) {
|
|
857
|
-
return handler;
|
|
858
|
-
}
|
|
859
|
-
const permissions = Array.isArray(action.permissions) ? action.permissions : [action.permissions];
|
|
860
|
-
const permissionNames = [];
|
|
861
|
-
const permissionFunctions = [];
|
|
862
|
-
permissions.forEach((permission) => {
|
|
863
|
-
if (typeof permission === "function") {
|
|
864
|
-
permissionFunctions.push(permission);
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
if (typeof permission === "string") {
|
|
868
|
-
if (permission in permissionHandlers) {
|
|
869
|
-
const handler2 = permissionHandlers[permission];
|
|
870
|
-
permissionFunctions.push(handler2);
|
|
871
|
-
return;
|
|
872
|
-
}
|
|
873
|
-
permissionNames.push(permission);
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
});
|
|
877
|
-
return async function CheckPermissionsMiddleware(ctx) {
|
|
878
|
-
let hasAccess = false;
|
|
879
|
-
if (ctx.meta.user?.roles.includes(PERMISSIONS.OWNER)) {
|
|
880
|
-
hasAccess = true;
|
|
881
|
-
}
|
|
882
|
-
if (!hasAccess && permissionFunctions.length > 0) {
|
|
883
|
-
const results = await Promise.allSettled(
|
|
884
|
-
permissionFunctions.map((fn) => fn(ctx, action))
|
|
885
|
-
);
|
|
886
|
-
hasAccess = results.some(
|
|
887
|
-
(result) => result.status === "fulfilled" && !!result.value
|
|
888
|
-
);
|
|
889
|
-
const failures = results.filter((r) => r.status === "rejected");
|
|
890
|
-
if (failures.length > 0) {
|
|
891
|
-
ctx.broker.logger.warn(
|
|
892
|
-
`${failures.length} permission functions failed`,
|
|
893
|
-
{
|
|
894
|
-
action: action.name,
|
|
895
|
-
userId: ctx.meta.user?.id
|
|
896
|
-
}
|
|
897
|
-
);
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
if (!hasAccess && permissionNames.length > 0) {
|
|
901
|
-
const userRoles = ctx.meta.user?.roles ?? [];
|
|
902
|
-
hasAccess = userRoles.some((role) => {
|
|
903
|
-
const rolePermissions = ROLE_PERMISSIONS[role] ?? [];
|
|
904
|
-
return permissionNames.some(
|
|
905
|
-
(permName) => rolePermissions.includes(permName)
|
|
906
|
-
);
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
if (!hasAccess) {
|
|
910
|
-
const user = ctx.meta.user;
|
|
911
|
-
ctx.broker.logger.warn("Access denied:", {
|
|
912
|
-
action: action.name,
|
|
913
|
-
userId: user?.id,
|
|
914
|
-
userRoles: user?.roles,
|
|
915
|
-
tenantId: ctx.meta.tenantId,
|
|
916
|
-
requiredPermissions: permissions
|
|
917
|
-
});
|
|
918
|
-
const errorDetails = isDev ? {
|
|
919
|
-
action: action.name,
|
|
920
|
-
requiredPermissions: permissions.map(
|
|
921
|
-
(p) => typeof p === "function" ? "[Function]" : String(p)
|
|
922
|
-
),
|
|
923
|
-
userRoles: user?.roles ?? [],
|
|
924
|
-
userId: user?.id,
|
|
925
|
-
tenantId: ctx.meta.tenantId
|
|
926
|
-
} : {
|
|
927
|
-
action: action.name
|
|
928
|
-
};
|
|
929
|
-
throw new PermissionError(
|
|
930
|
-
"You do not have permission to perform this action",
|
|
931
|
-
errorDetails
|
|
932
|
-
);
|
|
933
|
-
}
|
|
934
|
-
return handler.call(this, ctx);
|
|
935
|
-
};
|
|
936
|
-
}
|
|
937
|
-
};
|
|
938
|
-
|
|
939
|
-
// src/mixins/datasource.mixin.ts
|
|
940
|
-
function DatasourceMixin(datasourceConstructors = {}) {
|
|
941
|
-
const datasourceInstances = {};
|
|
942
|
-
for (const [key, DatasourceClass] of Object.entries(datasourceConstructors)) {
|
|
943
|
-
datasourceInstances[key] = new DatasourceClass();
|
|
944
|
-
}
|
|
945
|
-
return {
|
|
946
|
-
/**
|
|
947
|
-
* Service created lifecycle hook
|
|
948
|
-
* Initialize datasources and store on service
|
|
949
|
-
*/
|
|
950
|
-
async created() {
|
|
951
|
-
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
952
|
-
datasource.broker = this.broker;
|
|
953
|
-
}
|
|
954
|
-
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
955
|
-
if (typeof datasource.init === "function") {
|
|
956
|
-
await datasource.init();
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
this.$datasources = datasourceInstances;
|
|
960
|
-
},
|
|
961
|
-
/**
|
|
962
|
-
* Service started lifecycle hook
|
|
963
|
-
* Connect datasources that have connect method
|
|
964
|
-
*/
|
|
965
|
-
async started() {
|
|
966
|
-
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
967
|
-
if (typeof datasource.connect === "function") {
|
|
968
|
-
await datasource.connect();
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
},
|
|
972
|
-
/**
|
|
973
|
-
* Service stopped lifecycle hook
|
|
974
|
-
* Disconnect datasources that have disconnect method
|
|
975
|
-
*/
|
|
976
|
-
async stopped() {
|
|
977
|
-
for (const [, datasource] of Object.entries(datasourceInstances)) {
|
|
978
|
-
if (typeof datasource.disconnect === "function") {
|
|
979
|
-
await datasource.disconnect();
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
},
|
|
983
|
-
/**
|
|
984
|
-
* Hooks to inject datasources into context
|
|
985
|
-
*/
|
|
986
|
-
hooks: {
|
|
987
|
-
before: {
|
|
988
|
-
"*": function injectDatasources(ctx) {
|
|
989
|
-
const datasources = this.$datasources ?? {};
|
|
990
|
-
for (const [, datasource] of Object.entries(datasources)) {
|
|
991
|
-
datasource.context = ctx;
|
|
992
|
-
}
|
|
993
|
-
ctx.datasources = datasources;
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
};
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
// src/utils/index.ts
|
|
1001
|
-
function omit(obj, keys) {
|
|
1002
|
-
const result = { ...obj };
|
|
1003
|
-
keys.forEach((key) => delete result[key]);
|
|
1004
|
-
return result;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
// src/service/define-service.ts
|
|
1008
|
-
function defineService(config) {
|
|
1009
|
-
const propsToOmit = ["datasources"];
|
|
1010
|
-
const serviceSchema = omit(
|
|
1011
|
-
config,
|
|
1012
|
-
propsToOmit
|
|
1013
|
-
);
|
|
1014
|
-
return {
|
|
1015
|
-
...serviceSchema,
|
|
1016
|
-
mixins: [
|
|
1017
|
-
DatasourceMixin(config.datasources),
|
|
1018
|
-
MemoizeMixin(),
|
|
1019
|
-
...serviceSchema.mixins ?? []
|
|
1020
|
-
]
|
|
1021
|
-
};
|
|
1022
|
-
}
|
|
765
|
+
// src/service/define-integration.ts
|
|
1023
766
|
var SecurityHelpers = {
|
|
1024
767
|
/**
|
|
1025
768
|
* Secure comparison using Node.js crypto.timingSafeEqual
|
|
@@ -1373,6 +1116,263 @@ var UserRole = {
|
|
|
1373
1116
|
VIEWER: "VIEWER"
|
|
1374
1117
|
};
|
|
1375
1118
|
|
|
1119
|
+
// src/configs/moleculer/bulkhead.ts
|
|
1120
|
+
var bulkheadConfig = {
|
|
1121
|
+
// Enable feature.
|
|
1122
|
+
enabled: false,
|
|
1123
|
+
// Maximum concurrent executions.
|
|
1124
|
+
concurrency: 10,
|
|
1125
|
+
// Maximum size of queue
|
|
1126
|
+
maxQueueSize: 100
|
|
1127
|
+
};
|
|
1128
|
+
var NAMESPACE2 = NAMESPACE.toUpperCase();
|
|
1129
|
+
var middleware = Middleware({
|
|
1130
|
+
adapter: {
|
|
1131
|
+
type: "NATS",
|
|
1132
|
+
options: {
|
|
1133
|
+
nats: {
|
|
1134
|
+
url: env4.string("NATS_URL", "nats://localhost:4222"),
|
|
1135
|
+
/** Connection options for reliability */
|
|
1136
|
+
connectionOptions: {
|
|
1137
|
+
name: "hios",
|
|
1138
|
+
timeout: 1e4,
|
|
1139
|
+
reconnect: true,
|
|
1140
|
+
maxReconnectAttempts: 10,
|
|
1141
|
+
reconnectTimeWait: 2e3,
|
|
1142
|
+
maxReconnectTimeWait: 3e4,
|
|
1143
|
+
pingInterval: 2e4,
|
|
1144
|
+
maxPingOut: 2
|
|
1145
|
+
},
|
|
1146
|
+
/**
|
|
1147
|
+
* Stream configuration for multi-tenant messaging
|
|
1148
|
+
*
|
|
1149
|
+
* Environment variables for production:
|
|
1150
|
+
* - NATS_MAX_MESSAGES: Default 100K (dev) -> 10M+ (prod)
|
|
1151
|
+
* - NATS_MAX_BYTES_GB: Default 1GB (dev) -> 100GB+ (prod)
|
|
1152
|
+
* - NATS_MAX_AGE_DAYS: Default 7 (dev) -> 30+ (prod)
|
|
1153
|
+
* - NATS_MAX_MSG_SIZE_MB: Default 1MB (dev) -> 5MB (prod)
|
|
1154
|
+
* - NATS_REPLICAS: Default 1 (dev) -> 3 (prod)
|
|
1155
|
+
*/
|
|
1156
|
+
streamConfig: {
|
|
1157
|
+
name: `${NAMESPACE2}_MESSAGES`,
|
|
1158
|
+
subjects: [
|
|
1159
|
+
SUBJECTS.WEBHOOK_ALL,
|
|
1160
|
+
SUBJECTS.PROCESSING_ALL,
|
|
1161
|
+
SUBJECTS.RESPONSE_ALL,
|
|
1162
|
+
SUBJECTS.SYSTEM_ALL,
|
|
1163
|
+
SUBJECTS.DLQ_ALL
|
|
1164
|
+
],
|
|
1165
|
+
retention: "limits",
|
|
1166
|
+
max_msgs: env4.int("NATS_MAX_MESSAGES", 1e5),
|
|
1167
|
+
// 100K for dev, 10M+ for prod
|
|
1168
|
+
max_bytes: env4.int("NATS_MAX_BYTES_GB", 1) * 1024 * 1024 * 1024,
|
|
1169
|
+
// 1GB for dev, 100GB+ for prod
|
|
1170
|
+
max_age: env4.int("NATS_MAX_AGE_DAYS", 7) * 24 * 60 * 60 * 1e9,
|
|
1171
|
+
// 7 days dev, 30+ days prod
|
|
1172
|
+
max_msg_size: env4.int("NATS_MAX_MSG_SIZE_MB", 1) * 1024 * 1024,
|
|
1173
|
+
// 1MB dev, 5MB prod
|
|
1174
|
+
storage: "file",
|
|
1175
|
+
// Persistent storage
|
|
1176
|
+
num_replicas: env4.int("NATS_REPLICAS", 1),
|
|
1177
|
+
// 1 for dev, 3 for prod
|
|
1178
|
+
discard: "old",
|
|
1179
|
+
// Remove old messages when limits hit
|
|
1180
|
+
duplicate_window: 2 * 60 * 1e9
|
|
1181
|
+
// 2 minutes dedup window
|
|
1182
|
+
},
|
|
1183
|
+
/** Consumer options optimized for LLM processing */
|
|
1184
|
+
consumerOptions: {
|
|
1185
|
+
config: {
|
|
1186
|
+
// Start with new messages (don't replay old ones on restart)
|
|
1187
|
+
deliver_policy: "new",
|
|
1188
|
+
// Explicit acknowledgment required (critical for LLM processing)
|
|
1189
|
+
ack_policy: "explicit",
|
|
1190
|
+
// Allow 5 unacknowledged messages per consumer (rate limiting)
|
|
1191
|
+
max_ack_pending: 5,
|
|
1192
|
+
// Acknowledgment timeout for LLM processing (2 minutes)
|
|
1193
|
+
ack_wait: 120 * 1e9,
|
|
1194
|
+
// 2 minutes in nanoseconds
|
|
1195
|
+
// Maximum delivery attempts before dead letter
|
|
1196
|
+
max_deliver: 3,
|
|
1197
|
+
// Backoff for failed message retries
|
|
1198
|
+
backoff: [
|
|
1199
|
+
1e9,
|
|
1200
|
+
// 1 second
|
|
1201
|
+
5e9,
|
|
1202
|
+
// 5 seconds
|
|
1203
|
+
3e10
|
|
1204
|
+
// 30 seconds
|
|
1205
|
+
]
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
},
|
|
1209
|
+
/** Application-level flow control */
|
|
1210
|
+
maxInFlight: 5,
|
|
1211
|
+
// Limit concurrent LLM requests per service
|
|
1212
|
+
maxRetries: 2,
|
|
1213
|
+
// App-level retries (NATS handles delivery retries)
|
|
1214
|
+
/** Dead letter queue for failed messages */
|
|
1215
|
+
deadLettering: {
|
|
1216
|
+
enabled: true,
|
|
1217
|
+
queueName: "FAILED_MESSAGES"
|
|
1218
|
+
// Send to dead letter after NATS max_deliver attempts
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
var ChannelsMiddleware = {
|
|
1224
|
+
...middleware
|
|
1225
|
+
};
|
|
1226
|
+
|
|
1227
|
+
// src/configs/moleculer/circuit-breaker.ts
|
|
1228
|
+
var circuitBreakerConfig = {
|
|
1229
|
+
// Enable feature
|
|
1230
|
+
enabled: false,
|
|
1231
|
+
// Threshold value. 0.5 means that 50% should be failed for tripping.
|
|
1232
|
+
threshold: 0.5,
|
|
1233
|
+
// Minimum request count. Below it, CB does not trip.
|
|
1234
|
+
minRequestCount: 20,
|
|
1235
|
+
// Number of seconds for time window.
|
|
1236
|
+
windowTime: 60,
|
|
1237
|
+
// Number of milliseconds to switch from open to half-open state
|
|
1238
|
+
halfOpenTime: 10 * 1e3,
|
|
1239
|
+
// A function to check failed requests.
|
|
1240
|
+
check: (err) => err.code >= 500
|
|
1241
|
+
};
|
|
1242
|
+
|
|
1243
|
+
// src/configs/moleculer/logger.ts
|
|
1244
|
+
var loggerConfig = {
|
|
1245
|
+
type: "Console",
|
|
1246
|
+
options: {
|
|
1247
|
+
// Using colors on the output
|
|
1248
|
+
colors: true,
|
|
1249
|
+
// Print module names with different colors (like docker-compose for containers)
|
|
1250
|
+
moduleColors: false,
|
|
1251
|
+
// Line formatter. It can be "json", "short", "simple", "full", a `Function` or a template string like "{timestamp} {level} {nodeID}/{mod}: {msg}"
|
|
1252
|
+
formatter: "full",
|
|
1253
|
+
// Custom object printer. If not defined, it uses the `util.inspect` method.
|
|
1254
|
+
objectPrinter: null,
|
|
1255
|
+
// Auto-padding the module name in order to messages begin at the same column.
|
|
1256
|
+
autoPadding: false
|
|
1257
|
+
}
|
|
1258
|
+
};
|
|
1259
|
+
var logger_default = loggerConfig;
|
|
1260
|
+
|
|
1261
|
+
// src/configs/moleculer/metrics.ts
|
|
1262
|
+
var metricsConfig = {
|
|
1263
|
+
enabled: false,
|
|
1264
|
+
// Available built-in reporters: "Console", "CSV", "Event", "Prometheus", "Datadog", "StatsD"
|
|
1265
|
+
reporter: {
|
|
1266
|
+
type: "Prometheus",
|
|
1267
|
+
options: {
|
|
1268
|
+
// HTTP port
|
|
1269
|
+
port: 3030,
|
|
1270
|
+
// HTTP URL path
|
|
1271
|
+
path: "/metrics",
|
|
1272
|
+
// Default labels which are appended to all metrics labels
|
|
1273
|
+
defaultLabels: (registry) => ({
|
|
1274
|
+
namespace: registry.broker.namespace,
|
|
1275
|
+
nodeID: registry.broker.nodeID
|
|
1276
|
+
})
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
|
|
1281
|
+
// src/configs/moleculer/registry.ts
|
|
1282
|
+
var registryConfig = {
|
|
1283
|
+
// Define balancing strategy. More info: https://moleculer.services/docs/0.14/balancing.html
|
|
1284
|
+
// Available values: "RoundRobin", "Random", "CpuUsage", "Latency", "Shard"
|
|
1285
|
+
strategy: "RoundRobin",
|
|
1286
|
+
// Enable local action call preferring. Always call the local action instance if available.
|
|
1287
|
+
preferLocal: true
|
|
1288
|
+
};
|
|
1289
|
+
|
|
1290
|
+
// src/configs/moleculer/retry-policy.ts
|
|
1291
|
+
var retryPolicyConfig = {
|
|
1292
|
+
// Enable feature
|
|
1293
|
+
enabled: false,
|
|
1294
|
+
// Count of retries
|
|
1295
|
+
retries: 5,
|
|
1296
|
+
// First delay in milliseconds.
|
|
1297
|
+
delay: 100,
|
|
1298
|
+
// Maximum delay in milliseconds.
|
|
1299
|
+
maxDelay: 1e3,
|
|
1300
|
+
// Backoff factor for delay. 2 means exponential backoff.
|
|
1301
|
+
factor: 2,
|
|
1302
|
+
// A function to check failed requests.
|
|
1303
|
+
check: (err) => !!err.retryable
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
// src/configs/moleculer/tracing.ts
|
|
1307
|
+
var tracingConfig = {
|
|
1308
|
+
enabled: true,
|
|
1309
|
+
exporter: "Console",
|
|
1310
|
+
events: true,
|
|
1311
|
+
stackTrace: true
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
// src/configs/moleculer/tracking.ts
|
|
1315
|
+
var trackingConfig = {
|
|
1316
|
+
// Enable feature
|
|
1317
|
+
enabled: false,
|
|
1318
|
+
// Number of milliseconds to wait before shuting down the process.
|
|
1319
|
+
shutdownTimeout: 5e3
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
// src/configs/moleculer/index.ts
|
|
1323
|
+
var pkgNm = env4.string("NAMESPACE", "hios");
|
|
1324
|
+
var nodeID = env4.string("NODE_ID") ?? `${pkgNm}-${os.hostname()}-${process.pid}`;
|
|
1325
|
+
var configs = {
|
|
1326
|
+
namespace: pkgNm,
|
|
1327
|
+
nodeID,
|
|
1328
|
+
metadata: {},
|
|
1329
|
+
logger: logger_default,
|
|
1330
|
+
// Default log level for built-in console logger. It can be overwritten in logger options above.
|
|
1331
|
+
// Available values: trace, debug, info, warn, error, fatal
|
|
1332
|
+
logLevel: "info",
|
|
1333
|
+
cacher: env4.string("REDIS_URL", "Memory"),
|
|
1334
|
+
// Define a serializer.
|
|
1335
|
+
// Available values: "JSON", "Avro", "ProtoBuf", "MsgPack", "Notepack", "Thrift".
|
|
1336
|
+
// More info: https://moleculer.services/docs/0.14/networking.html#Serialization
|
|
1337
|
+
serializer: "JSON",
|
|
1338
|
+
// Number of milliseconds to wait before reject a request with a RequestTimeout error. Disabled: 0
|
|
1339
|
+
requestTimeout: 10 * 1e3,
|
|
1340
|
+
// Retry policy settings. More info: https://moleculer.services/docs/0.14/fault-tolerance.html#Retry
|
|
1341
|
+
retryPolicy: retryPolicyConfig,
|
|
1342
|
+
// Limit of calling level. If it reaches the limit, broker will throw an MaxCallLevelError error. (Infinite loop protection)
|
|
1343
|
+
maxCallLevel: 100,
|
|
1344
|
+
// Number of seconds to send heartbeat packet to other nodes.
|
|
1345
|
+
heartbeatInterval: 10,
|
|
1346
|
+
// Number of seconds to wait before setting node to unavailable status.
|
|
1347
|
+
heartbeatTimeout: 30,
|
|
1348
|
+
// Cloning the params of context if enabled. High performance impact, use it with caution!
|
|
1349
|
+
contextParamsCloning: false,
|
|
1350
|
+
// Tracking requests and waiting for running requests before shuting down. More info: https://moleculer.services/docs/0.14/context.html#Context-tracking
|
|
1351
|
+
tracking: trackingConfig,
|
|
1352
|
+
// Disable built-in request & emit balancer. (Transporter must support it, as well.). More info: https://moleculer.services/docs/0.14/networking.html#Disabled-balancer
|
|
1353
|
+
disableBalancer: false,
|
|
1354
|
+
// Settings of Service Registry. More info: https://moleculer.services/docs/0.14/registry.html
|
|
1355
|
+
registry: registryConfig,
|
|
1356
|
+
// Settings of Circuit Breaker. More info: https://moleculer.services/docs/0.14/fault-tolerance.html#Circuit-Breaker
|
|
1357
|
+
circuitBreaker: circuitBreakerConfig,
|
|
1358
|
+
// Settings of bulkhead feature. More info: https://moleculer.services/docs/0.14/fault-tolerance.html#Bulkhead
|
|
1359
|
+
bulkhead: bulkheadConfig,
|
|
1360
|
+
// Enable action & event parameter validation. More info: https://moleculer.services/docs/0.14/validating.html
|
|
1361
|
+
validator: "Fastest",
|
|
1362
|
+
// errorHandler: null,
|
|
1363
|
+
transporter: env4.string("TRANSPORTER_URL"),
|
|
1364
|
+
// Enable/disable built-in metrics function. More info: https://moleculer.services/docs/0.14/metrics.html
|
|
1365
|
+
metrics: metricsConfig,
|
|
1366
|
+
// Enable built-in tracing function. More info: https://moleculer.services/docs/0.14/tracing.html
|
|
1367
|
+
tracing: tracingConfig,
|
|
1368
|
+
middlewares: [
|
|
1369
|
+
ChannelsMiddleware,
|
|
1370
|
+
PermissionsMiddleware,
|
|
1371
|
+
ContextHelpersMiddleware
|
|
1372
|
+
]
|
|
1373
|
+
};
|
|
1374
|
+
var moleculer_default = configs;
|
|
1375
|
+
|
|
1376
1376
|
// src/datasources/base.datasource.ts
|
|
1377
1377
|
var AbstractDatasource = class {
|
|
1378
1378
|
/**
|