@hiliosai/sdk 0.1.14 → 0.1.16

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 CHANGED
@@ -1,4 +1,4 @@
1
- import { Context, ServiceBroker, ServiceSchema as ServiceSchema$1, ServiceSettingSchema, Service, BrokerOptions, ActionSchema, ServiceEvents, ServiceMethods, ServiceHooks } from 'moleculer';
1
+ import { Context, ServiceBroker, ServiceSchema as ServiceSchema$1, ServiceSettingSchema, Service, BrokerOptions, ActionSchema, ServiceEvents, ServiceMethods, ServiceHooks, Middleware } from 'moleculer';
2
2
  import env from '@ltv/env';
3
3
  export { default as env } from '@ltv/env';
4
4
 
@@ -57,7 +57,7 @@ interface PermissionHelpers {
57
57
  auditLog(action: string, resource?: unknown, metadata?: Record<string, unknown>): void;
58
58
  createError(message: string, code: string, statusCode?: number): Error;
59
59
  }
60
- type AppContext<TDatasources = unknown, TParams = unknown, TMeta extends AppMeta = AppMeta, TLocals = unknown> = Context<TParams, TMeta, TLocals> & PermissionHelpers & {
60
+ type AppContext<TDatasources = unknown, TParams = unknown, TMeta extends AppMeta = AppMeta, TLocals = Record<string, unknown>> = Context<TParams, TMeta, TLocals> & PermissionHelpers & {
61
61
  datasources: TDatasources;
62
62
  broker: Context['broker'] & {
63
63
  sendToChannel: SendToChannelMethod;
@@ -823,13 +823,9 @@ type Permission = keyof typeof PERMISSIONS | string | ((ctx: AppContext, action:
823
823
  interface ActionWithPermissions extends ActionSchema {
824
824
  permissions?: Permission | Permission[];
825
825
  }
826
- declare const PermissionsMiddleware: {
827
- localAction(handler: (...args: unknown[]) => unknown, action: ActionWithPermissions): ((...args: unknown[]) => unknown) | ((this: Service, ctx: AppContext) => Promise<unknown>);
828
- };
826
+ declare const PermissionsMiddleware: Middleware;
829
827
 
830
- declare const ContextHelpersMiddleware: {
831
- localAction(handler: (...args: unknown[]) => unknown): (this: unknown, ctx: AppContext) => unknown;
832
- };
828
+ declare const ContextHelpersMiddleware: Middleware;
833
829
 
834
830
  /**
835
831
  * Define a service
package/dist/index.js CHANGED
@@ -245,6 +245,250 @@ var ROLE_PERMISSIONS = {
245
245
  ]
246
246
  };
247
247
 
248
+ // src/errors/permission.error.ts
249
+ var PermissionError = class _PermissionError extends Error {
250
+ constructor(message, data) {
251
+ super(message);
252
+ this.code = "PERMISSION_DENIED";
253
+ this.statusCode = 403;
254
+ this.name = "PermissionError";
255
+ this.data = data;
256
+ if (Error.captureStackTrace) {
257
+ Error.captureStackTrace(this, _PermissionError);
258
+ }
259
+ }
260
+ };
261
+
262
+ // src/errors/auth.error.ts
263
+ var AuthenticationError = class _AuthenticationError extends Error {
264
+ constructor(message, data) {
265
+ super(message);
266
+ this.code = "AUTH_REQUIRED";
267
+ this.statusCode = 401;
268
+ this.name = "AuthenticationError";
269
+ this.data = data;
270
+ if (Error.captureStackTrace) {
271
+ Error.captureStackTrace(this, _AuthenticationError);
272
+ }
273
+ }
274
+ };
275
+ var TenantError = class _TenantError extends Error {
276
+ constructor(message, data) {
277
+ super(message);
278
+ this.code = "TENANT_REQUIRED";
279
+ this.statusCode = 401;
280
+ this.name = "TenantError";
281
+ this.data = data;
282
+ if (Error.captureStackTrace) {
283
+ Error.captureStackTrace(this, _TenantError);
284
+ }
285
+ }
286
+ };
287
+
288
+ // src/utils/context-cache.ts
289
+ var ContextCache = class _ContextCache {
290
+ constructor() {
291
+ this.memoryCache = /* @__PURE__ */ new Map();
292
+ this.TTL = 5 * 60 * 1e3;
293
+ this.cleanupInterval = setInterval(() => this.cleanup(), 60 * 1e3);
294
+ }
295
+ static getInstance() {
296
+ if (!_ContextCache.instance) {
297
+ _ContextCache.instance = new _ContextCache();
298
+ }
299
+ return _ContextCache.instance;
300
+ }
301
+ async get(key, factory) {
302
+ const cached = this.memoryCache.get(key);
303
+ if (cached && Date.now() - cached.timestamp < this.TTL) {
304
+ return cached.value;
305
+ }
306
+ const value = await factory();
307
+ this.memoryCache.set(key, { value, timestamp: Date.now() });
308
+ return value;
309
+ }
310
+ set(key, value) {
311
+ this.memoryCache.set(key, { value, timestamp: Date.now() });
312
+ }
313
+ delete(key) {
314
+ return this.memoryCache.delete(key);
315
+ }
316
+ clear() {
317
+ this.memoryCache.clear();
318
+ }
319
+ cleanup() {
320
+ const now = Date.now();
321
+ const keysToDelete = [];
322
+ this.memoryCache.forEach((entry, key) => {
323
+ if (now - entry.timestamp > this.TTL) {
324
+ keysToDelete.push(key);
325
+ }
326
+ });
327
+ keysToDelete.forEach((key) => this.memoryCache.delete(key));
328
+ }
329
+ destroy() {
330
+ if (this.cleanupInterval) {
331
+ clearInterval(this.cleanupInterval);
332
+ }
333
+ this.clear();
334
+ }
335
+ };
336
+
337
+ // src/utils/permission-calculator.ts
338
+ var PermissionCalculator = class {
339
+ static calculateUserPermissions(user) {
340
+ if (!user || !Array.isArray(user.roles)) {
341
+ return [];
342
+ }
343
+ const explicitPermissions = Array.isArray(user.permissions) ? user.permissions : [];
344
+ const rolePermissions = user.roles.flatMap((role) => {
345
+ return ROLE_PERMISSIONS[role] ?? [];
346
+ });
347
+ const allPermissions = [...explicitPermissions, ...rolePermissions];
348
+ const uniquePermissions = [];
349
+ allPermissions.forEach((permission) => {
350
+ if (!uniquePermissions.includes(permission)) {
351
+ uniquePermissions.push(permission);
352
+ }
353
+ });
354
+ return uniquePermissions;
355
+ }
356
+ static hasPermission(user, permission) {
357
+ if (typeof permission !== "string" || !permission.trim()) {
358
+ return false;
359
+ }
360
+ if (!user || typeof user !== "object") {
361
+ return false;
362
+ }
363
+ if (!Array.isArray(user.roles)) {
364
+ return false;
365
+ }
366
+ if (Array.isArray(user.permissions) && user.permissions.includes(permission)) {
367
+ return true;
368
+ }
369
+ return user.roles.some((role) => {
370
+ const rolePermissions = ROLE_PERMISSIONS[role] ?? [];
371
+ return rolePermissions.includes(permission);
372
+ });
373
+ }
374
+ };
375
+
376
+ // src/middlewares/context-helpers.middleware.ts
377
+ var ContextHelpersMiddleware = {
378
+ // Add helper functions to context before action handlers
379
+ localAction(handler) {
380
+ return function ContextHelpersWrapper(ctx) {
381
+ const cache = ContextCache.getInstance();
382
+ const memoizedPermissions = /* @__PURE__ */ new Map();
383
+ ctx.hasPermission = function(permission) {
384
+ if (memoizedPermissions.has(permission)) {
385
+ const cachedResult = memoizedPermissions.get(permission);
386
+ return cachedResult === true;
387
+ }
388
+ const user = ctx.meta.user;
389
+ if (!user) {
390
+ memoizedPermissions.set(permission, false);
391
+ return false;
392
+ }
393
+ const result = PermissionCalculator.hasPermission(user, permission);
394
+ memoizedPermissions.set(permission, result);
395
+ return result;
396
+ };
397
+ ctx.getUserPermissions = async function() {
398
+ const user = ctx.meta.user;
399
+ if (!user) return [];
400
+ const cacheKey = `permissions:${user.id}:${JSON.stringify(user.roles)}`;
401
+ return cache.get(cacheKey, () => {
402
+ return PermissionCalculator.calculateUserPermissions(user);
403
+ });
404
+ };
405
+ ctx.hasRole = function(role) {
406
+ const user = ctx.ensureUser();
407
+ return Array.isArray(user.roles) && user.roles.includes(role);
408
+ };
409
+ ctx.isTenantMember = function() {
410
+ const user = ctx.ensureUser();
411
+ return !!(user.tenantId && ctx.meta.tenantId && user.tenantId === ctx.meta.tenantId);
412
+ };
413
+ ctx.isTenantOwner = function() {
414
+ return ctx.isTenantMember() && ctx.hasRole("OWNER");
415
+ };
416
+ ctx.ensureUser = () => {
417
+ if (!ctx.meta.user) {
418
+ ctx.broker.logger.error("Authentication required", {
419
+ action: ctx.action?.name,
420
+ requestId: ctx.meta.requestId,
421
+ userAgent: ctx.meta.userAgent,
422
+ ip: ctx.meta.clientIP
423
+ });
424
+ throw new AuthenticationError("Authentication required", {
425
+ code: "AUTH_REQUIRED",
426
+ statusCode: 401,
427
+ requestId: ctx.meta.requestId
428
+ });
429
+ }
430
+ return ctx.meta.user;
431
+ };
432
+ ctx.ensureTenant = () => {
433
+ if (!ctx.meta.tenantId) {
434
+ ctx.broker.logger.error("Tenant required", {
435
+ action: ctx.action?.name,
436
+ userId: ctx.meta.user?.id,
437
+ requestId: ctx.meta.requestId
438
+ });
439
+ throw new TenantError("Tenant required", {
440
+ code: "TENANT_REQUIRED",
441
+ statusCode: 401,
442
+ tenantId: ctx.meta.tenantId,
443
+ requestId: ctx.meta.requestId
444
+ });
445
+ }
446
+ return {
447
+ id: ctx.meta.tenantId,
448
+ name: ctx.meta.tenantName ?? ""
449
+ };
450
+ };
451
+ ctx.auditLog = function(action, resource, metadata) {
452
+ ctx.broker.logger.info("Audit log", {
453
+ action,
454
+ resource: resource ? {
455
+ type: typeof resource,
456
+ id: resource.id
457
+ } : void 0,
458
+ userId: ctx.meta.user?.id,
459
+ tenantId: ctx.meta.tenantId,
460
+ requestId: ctx.meta.requestId,
461
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
462
+ ...metadata
463
+ });
464
+ };
465
+ ctx.createError = function(message, code, statusCode = 400) {
466
+ const errorData = {
467
+ code,
468
+ statusCode,
469
+ userId: ctx.meta.user?.id,
470
+ tenantId: ctx.meta.tenantId,
471
+ requestId: ctx.meta.requestId,
472
+ action: ctx.action?.name,
473
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
474
+ };
475
+ ctx.broker.logger.warn("Context error created", {
476
+ message,
477
+ ...errorData
478
+ });
479
+ if (code === "AUTH_REQUIRED") {
480
+ return new AuthenticationError(message, errorData);
481
+ }
482
+ if (code === "TENANT_REQUIRED") {
483
+ return new TenantError(message, errorData);
484
+ }
485
+ return new Error(message);
486
+ };
487
+ return handler.call(this, ctx);
488
+ };
489
+ }
490
+ };
491
+
248
492
  // src/configs/moleculer/bulkhead.ts
249
493
  var bulkheadConfig = {
250
494
  // Enable feature.
@@ -600,46 +844,6 @@ var isProd = nodeEnv === "production";
600
844
  var REDIS_URL = env3.string("REDIS_URL");
601
845
  var env_default = env3;
602
846
 
603
- // src/errors/permission.error.ts
604
- var PermissionError = class _PermissionError extends Error {
605
- constructor(message, data) {
606
- super(message);
607
- this.code = "PERMISSION_DENIED";
608
- this.statusCode = 403;
609
- this.name = "PermissionError";
610
- this.data = data;
611
- if (Error.captureStackTrace) {
612
- Error.captureStackTrace(this, _PermissionError);
613
- }
614
- }
615
- };
616
-
617
- // src/errors/auth.error.ts
618
- var AuthenticationError = class _AuthenticationError extends Error {
619
- constructor(message, data) {
620
- super(message);
621
- this.code = "AUTH_REQUIRED";
622
- this.statusCode = 401;
623
- this.name = "AuthenticationError";
624
- this.data = data;
625
- if (Error.captureStackTrace) {
626
- Error.captureStackTrace(this, _AuthenticationError);
627
- }
628
- }
629
- };
630
- var TenantError = class _TenantError extends Error {
631
- constructor(message, data) {
632
- super(message);
633
- this.code = "TENANT_REQUIRED";
634
- this.statusCode = 401;
635
- this.name = "TenantError";
636
- this.data = data;
637
- if (Error.captureStackTrace) {
638
- Error.captureStackTrace(this, _TenantError);
639
- }
640
- }
641
- };
642
-
643
847
  // src/middlewares/permissions.middleware.ts
644
848
  var permissionHandlers = {
645
849
  [PERMISSIONS.AUTHENTICATED]: async (ctx) => !!ctx.meta.user?.id,
@@ -732,210 +936,6 @@ var PermissionsMiddleware = {
732
936
  }
733
937
  };
734
938
 
735
- // src/utils/context-cache.ts
736
- var ContextCache = class _ContextCache {
737
- constructor() {
738
- this.memoryCache = /* @__PURE__ */ new Map();
739
- this.TTL = 5 * 60 * 1e3;
740
- this.cleanupInterval = setInterval(() => this.cleanup(), 60 * 1e3);
741
- }
742
- static getInstance() {
743
- if (!_ContextCache.instance) {
744
- _ContextCache.instance = new _ContextCache();
745
- }
746
- return _ContextCache.instance;
747
- }
748
- async get(key, factory) {
749
- const cached = this.memoryCache.get(key);
750
- if (cached && Date.now() - cached.timestamp < this.TTL) {
751
- return cached.value;
752
- }
753
- const value = await factory();
754
- this.memoryCache.set(key, { value, timestamp: Date.now() });
755
- return value;
756
- }
757
- set(key, value) {
758
- this.memoryCache.set(key, { value, timestamp: Date.now() });
759
- }
760
- delete(key) {
761
- return this.memoryCache.delete(key);
762
- }
763
- clear() {
764
- this.memoryCache.clear();
765
- }
766
- cleanup() {
767
- const now = Date.now();
768
- const keysToDelete = [];
769
- this.memoryCache.forEach((entry, key) => {
770
- if (now - entry.timestamp > this.TTL) {
771
- keysToDelete.push(key);
772
- }
773
- });
774
- keysToDelete.forEach((key) => this.memoryCache.delete(key));
775
- }
776
- destroy() {
777
- if (this.cleanupInterval) {
778
- clearInterval(this.cleanupInterval);
779
- }
780
- this.clear();
781
- }
782
- };
783
-
784
- // src/utils/permission-calculator.ts
785
- var PermissionCalculator = class {
786
- static calculateUserPermissions(user) {
787
- if (!user || !Array.isArray(user.roles)) {
788
- return [];
789
- }
790
- const explicitPermissions = Array.isArray(user.permissions) ? user.permissions : [];
791
- const rolePermissions = user.roles.flatMap((role) => {
792
- return ROLE_PERMISSIONS[role] ?? [];
793
- });
794
- const allPermissions = [...explicitPermissions, ...rolePermissions];
795
- const uniquePermissions = [];
796
- allPermissions.forEach((permission) => {
797
- if (!uniquePermissions.includes(permission)) {
798
- uniquePermissions.push(permission);
799
- }
800
- });
801
- return uniquePermissions;
802
- }
803
- static hasPermission(user, permission) {
804
- if (typeof permission !== "string" || !permission.trim()) {
805
- return false;
806
- }
807
- if (!user || typeof user !== "object") {
808
- return false;
809
- }
810
- if (!Array.isArray(user.roles)) {
811
- return false;
812
- }
813
- if (Array.isArray(user.permissions) && user.permissions.includes(permission)) {
814
- return true;
815
- }
816
- return user.roles.some((role) => {
817
- const rolePermissions = ROLE_PERMISSIONS[role] ?? [];
818
- return rolePermissions.includes(permission);
819
- });
820
- }
821
- };
822
-
823
- // src/middlewares/context-helpers.middleware.ts
824
- var ContextHelpersMiddleware = {
825
- // Add helper functions to context before action handlers
826
- localAction(handler) {
827
- return function ContextHelpersWrapper(ctx) {
828
- const cache = ContextCache.getInstance();
829
- const memoizedPermissions = /* @__PURE__ */ new Map();
830
- ctx.hasPermission = function(permission) {
831
- if (memoizedPermissions.has(permission)) {
832
- const cachedResult = memoizedPermissions.get(permission);
833
- return cachedResult === true;
834
- }
835
- const user = ctx.meta.user;
836
- if (!user) {
837
- memoizedPermissions.set(permission, false);
838
- return false;
839
- }
840
- const result = PermissionCalculator.hasPermission(user, permission);
841
- memoizedPermissions.set(permission, result);
842
- return result;
843
- };
844
- ctx.getUserPermissions = async function() {
845
- const user = ctx.meta.user;
846
- if (!user) return [];
847
- const cacheKey = `permissions:${user.id}:${JSON.stringify(user.roles)}`;
848
- return cache.get(cacheKey, () => {
849
- return PermissionCalculator.calculateUserPermissions(user);
850
- });
851
- };
852
- ctx.hasRole = function(role) {
853
- const user = ctx.ensureUser();
854
- return Array.isArray(user.roles) && user.roles.includes(role);
855
- };
856
- ctx.isTenantMember = function() {
857
- const user = ctx.ensureUser();
858
- return !!(user.tenantId && ctx.meta.tenantId && user.tenantId === ctx.meta.tenantId);
859
- };
860
- ctx.isTenantOwner = function() {
861
- return ctx.isTenantMember() && ctx.hasRole("OWNER");
862
- };
863
- ctx.ensureUser = () => {
864
- if (!ctx.meta.user) {
865
- ctx.broker.logger.error("Authentication required", {
866
- action: ctx.action?.name,
867
- requestId: ctx.meta.requestId,
868
- userAgent: ctx.meta.userAgent,
869
- ip: ctx.meta.clientIP
870
- });
871
- throw new AuthenticationError("Authentication required", {
872
- code: "AUTH_REQUIRED",
873
- statusCode: 401,
874
- requestId: ctx.meta.requestId
875
- });
876
- }
877
- return ctx.meta.user;
878
- };
879
- ctx.ensureTenant = () => {
880
- if (!ctx.meta.tenantId) {
881
- ctx.broker.logger.error("Tenant required", {
882
- action: ctx.action?.name,
883
- userId: ctx.meta.user?.id,
884
- requestId: ctx.meta.requestId
885
- });
886
- throw new TenantError("Tenant required", {
887
- code: "TENANT_REQUIRED",
888
- statusCode: 401,
889
- tenantId: ctx.meta.tenantId,
890
- requestId: ctx.meta.requestId
891
- });
892
- }
893
- return {
894
- id: ctx.meta.tenantId,
895
- name: ctx.meta.tenantName ?? ""
896
- };
897
- };
898
- ctx.auditLog = function(action, resource, metadata) {
899
- ctx.broker.logger.info("Audit log", {
900
- action,
901
- resource: resource ? {
902
- type: typeof resource,
903
- id: resource.id
904
- } : void 0,
905
- userId: ctx.meta.user?.id,
906
- tenantId: ctx.meta.tenantId,
907
- requestId: ctx.meta.requestId,
908
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
909
- ...metadata
910
- });
911
- };
912
- ctx.createError = function(message, code, statusCode = 400) {
913
- const errorData = {
914
- code,
915
- statusCode,
916
- userId: ctx.meta.user?.id,
917
- tenantId: ctx.meta.tenantId,
918
- requestId: ctx.meta.requestId,
919
- action: ctx.action?.name,
920
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
921
- };
922
- ctx.broker.logger.warn("Context error created", {
923
- message,
924
- ...errorData
925
- });
926
- if (code === "AUTH_REQUIRED") {
927
- return new AuthenticationError(message, errorData);
928
- }
929
- if (code === "TENANT_REQUIRED") {
930
- return new TenantError(message, errorData);
931
- }
932
- return new Error(message);
933
- };
934
- return handler.call(this, ctx);
935
- };
936
- }
937
- };
938
-
939
939
  // src/mixins/datasource.mixin.ts
940
940
  function DatasourceMixin(datasourceConstructors = {}) {
941
941
  const datasourceInstances = {};
@@ -1236,10 +1236,10 @@ function defineIntegration(config) {
1236
1236
  i_verifyWebhook: {
1237
1237
  rest: {
1238
1238
  method: "GET",
1239
- path: "/:tenantId"
1239
+ path: "/:channelId"
1240
1240
  },
1241
1241
  params: {
1242
- tenantId: "string",
1242
+ channelId: "string",
1243
1243
  mode: "string",
1244
1244
  token: "string",
1245
1245
  challenge: "string"
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@hiliosai/sdk",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "type": "module",
5
+ "license": "UNLICENSED",
5
6
  "main": "./dist/index.js",
6
7
  "types": "./dist/index.d.ts",
7
8
  "exports": {
@@ -19,7 +20,6 @@
19
20
  "typecheck": "tsc --noEmit"
20
21
  },
21
22
  "dependencies": {
22
- "@hiliosai/sdk": "workspace:*",
23
23
  "@ltv/env": "4.0.3",
24
24
  "@moleculer/channels": "0.2.0",
25
25
  "moleculer": "0.14.35"