@mu-cabin/opms-permission 0.9.1 → 0.9.2

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.cjs CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  DataHandler: () => DataHandler,
34
34
  EnumOrgQueryMode: () => EnumOrgQueryMode,
35
35
  EnumOrgQueryScope: () => EnumOrgQueryScope,
36
+ EventEmitter: () => EventEmitter,
36
37
  OpmsPermission: () => Permission,
37
38
  getOrgTree: () => getOrgTree,
38
39
  getUserInfo: () => getUserInfo,
@@ -393,6 +394,104 @@ async function queryOrgCompanies(baseUrl, params) {
393
394
  );
394
395
  }
395
396
 
397
+ // src/utils/eventEmitter.ts
398
+ var EventEmitter = class {
399
+ constructor(allowedEvents) {
400
+ this.eventListeners = /* @__PURE__ */ new Map();
401
+ this.allowedEvents = new Set(allowedEvents || []);
402
+ }
403
+ /**
404
+ * Add event listener
405
+ */
406
+ listen(event, listener) {
407
+ if (this.allowedEvents.size > 0 && !this.allowedEvents.has(event)) {
408
+ const allowedEventsList = Array.from(this.allowedEvents).join(", ");
409
+ throw new Error(
410
+ `Event "${String(event)}" is not registered. Allowed events: ${allowedEventsList}`
411
+ );
412
+ }
413
+ if (!this.eventListeners.has(event)) {
414
+ this.eventListeners.set(event, /* @__PURE__ */ new Set());
415
+ }
416
+ const listeners = this.eventListeners.get(event);
417
+ listeners.add(listener);
418
+ return () => {
419
+ listeners.delete(listener);
420
+ if (listeners.size === 0) {
421
+ this.eventListeners.delete(event);
422
+ }
423
+ };
424
+ }
425
+ /**
426
+ * Remove event listener
427
+ */
428
+ unlisten(event, listener) {
429
+ const listeners = this.eventListeners.get(event);
430
+ if (listeners) {
431
+ listeners.delete(listener);
432
+ if (listeners.size === 0) {
433
+ this.eventListeners.delete(event);
434
+ }
435
+ }
436
+ }
437
+ /**
438
+ * Remove all listeners for a specific event or all events
439
+ */
440
+ unlistenAll(event) {
441
+ if (event) {
442
+ this.eventListeners.delete(event);
443
+ } else {
444
+ this.eventListeners.clear();
445
+ }
446
+ }
447
+ /**
448
+ * Emit event to all listeners
449
+ */
450
+ emit(event, data) {
451
+ const listeners = this.eventListeners.get(event);
452
+ if (listeners) {
453
+ listeners.forEach((listener) => {
454
+ try {
455
+ listener(data);
456
+ } catch (error) {
457
+ console.error(`Error in event listener for ${String(event)}:`, error);
458
+ }
459
+ });
460
+ }
461
+ }
462
+ /**
463
+ * Get the number of listeners for a specific event
464
+ */
465
+ getListenerCount(event) {
466
+ const listeners = this.eventListeners.get(event);
467
+ return listeners ? listeners.size : 0;
468
+ }
469
+ /**
470
+ * Check if there are any listeners for a specific event
471
+ */
472
+ hasListeners(event) {
473
+ return this.getListenerCount(event) > 0;
474
+ }
475
+ /**
476
+ * Get all registered event types
477
+ */
478
+ getEventTypes() {
479
+ return Array.from(this.eventListeners.keys());
480
+ }
481
+ /**
482
+ * Get all allowed event types
483
+ */
484
+ getAllowedEvents() {
485
+ return Array.from(this.allowedEvents);
486
+ }
487
+ /**
488
+ * Check if an event is allowed
489
+ */
490
+ isEventAllowed(event) {
491
+ return this.allowedEvents.size === 0 || this.allowedEvents.has(event);
492
+ }
493
+ };
494
+
396
495
  // src/permission.ts
397
496
  var DataHandler = {
398
497
  iterateOrgTree(orgTree) {
@@ -463,11 +562,59 @@ var Permission = class {
463
562
  this.widgetMap = {};
464
563
  this.menuList = [];
465
564
  this.menuMap = {};
565
+ // Event emitter instance - only allow tokenChange event
566
+ this.eventEmitter = new EventEmitter(["tokenChange"]);
466
567
  this.baseUrl = options.baseUrl;
467
568
  this.systemId = options.systemId;
468
569
  storage.setSystemId(this.systemId);
469
570
  storage.setVersion("1.0.0");
470
571
  }
572
+ /**
573
+ * Add event listener
574
+ */
575
+ listen(event, listener) {
576
+ try {
577
+ return this.eventEmitter.listen(event, listener);
578
+ } catch (error) {
579
+ if (error instanceof Error && error.message.includes("not registered")) {
580
+ const allowedEvents = this.eventEmitter.getAllowedEvents();
581
+ throw new Error(
582
+ `Permission event "${String(event)}" is not supported. Available events: ${allowedEvents.join(", ")}`
583
+ );
584
+ }
585
+ throw error;
586
+ }
587
+ }
588
+ /**
589
+ * Remove event listener
590
+ */
591
+ unlisten(event, listener) {
592
+ this.eventEmitter.unlisten(event, listener);
593
+ }
594
+ /**
595
+ * Remove all listeners for a specific event or all events
596
+ */
597
+ unlistenAll(event) {
598
+ this.eventEmitter.unlistenAll(event);
599
+ }
600
+ /**
601
+ * Emit event to all listeners
602
+ */
603
+ emit(event, data) {
604
+ this.eventEmitter.emit(event, data);
605
+ }
606
+ /**
607
+ * Get available events that can be listened to
608
+ */
609
+ getAvailableEvents() {
610
+ return this.eventEmitter.getAllowedEvents();
611
+ }
612
+ /**
613
+ * Check if an event is supported
614
+ */
615
+ isEventSupported(event) {
616
+ return this.eventEmitter.isEventAllowed(event);
617
+ }
471
618
  /**
472
619
  * Login using code from URL, save userInfo
473
620
  */
@@ -494,6 +641,7 @@ var Permission = class {
494
641
  const { token } = obj;
495
642
  url.searchParams.delete("code");
496
643
  storage.setItem(TOKEN_KEY, token);
644
+ this.emit("tokenChange", token);
497
645
  return token;
498
646
  }
499
647
  /**
@@ -505,6 +653,7 @@ var Permission = class {
505
653
  }
506
654
  clear() {
507
655
  storage.clear();
656
+ this.emit("tokenChange", "");
508
657
  }
509
658
  async getUserInfo() {
510
659
  const data = await getUserInfo(this.baseUrl);
@@ -616,6 +765,7 @@ var Permission = class {
616
765
  }
617
766
  setToken(token) {
618
767
  storage.setItem(TOKEN_KEY, token);
768
+ this.emit("tokenChange", token);
619
769
  }
620
770
  // --- Getters ---
621
771
  // get userInfo(): UserInfo | null {
@@ -728,6 +878,7 @@ function jumpToSSOLogout({
728
878
  DataHandler,
729
879
  EnumOrgQueryMode,
730
880
  EnumOrgQueryScope,
881
+ EventEmitter,
731
882
  OpmsPermission,
732
883
  getOrgTree,
733
884
  getUserInfo,
package/dist/index.d.mts CHANGED
@@ -200,6 +200,56 @@ declare function handlePermissionTree<T extends {
200
200
  noAuthMap: Record<number | string, T>;
201
201
  };
202
202
 
203
+ type PermissionEventType = 'tokenChange';
204
+ type PermissionEventListener<T = any> = (data: T) => void;
205
+ interface PermissionEventMap {
206
+ tokenChange: string;
207
+ }
208
+ /**
209
+ * Generic Event Emitter class for handling events
210
+ */
211
+ declare class EventEmitter<TEventMap extends Record<string, any> = PermissionEventMap> {
212
+ private eventListeners;
213
+ private allowedEvents;
214
+ constructor(allowedEvents?: (keyof TEventMap)[]);
215
+ /**
216
+ * Add event listener
217
+ */
218
+ listen<TEvent extends keyof TEventMap>(event: TEvent, listener: PermissionEventListener<TEventMap[TEvent]>): () => void;
219
+ /**
220
+ * Remove event listener
221
+ */
222
+ unlisten<TEvent extends keyof TEventMap>(event: TEvent, listener: PermissionEventListener<TEventMap[TEvent]>): void;
223
+ /**
224
+ * Remove all listeners for a specific event or all events
225
+ */
226
+ unlistenAll(event?: keyof TEventMap): void;
227
+ /**
228
+ * Emit event to all listeners
229
+ */
230
+ emit<TEvent extends keyof TEventMap>(event: TEvent, data: TEventMap[TEvent]): void;
231
+ /**
232
+ * Get the number of listeners for a specific event
233
+ */
234
+ getListenerCount(event: keyof TEventMap): number;
235
+ /**
236
+ * Check if there are any listeners for a specific event
237
+ */
238
+ hasListeners(event: keyof TEventMap): boolean;
239
+ /**
240
+ * Get all registered event types
241
+ */
242
+ getEventTypes(): (keyof TEventMap)[];
243
+ /**
244
+ * Get all allowed event types
245
+ */
246
+ getAllowedEvents(): (keyof TEventMap)[];
247
+ /**
248
+ * Check if an event is allowed
249
+ */
250
+ isEventAllowed(event: keyof TEventMap): boolean;
251
+ }
252
+
203
253
  interface PermissionOptions {
204
254
  systemId: string;
205
255
  baseUrl: string;
@@ -246,7 +296,32 @@ declare class Permission {
246
296
  menuMap: {
247
297
  [path: string]: MenuItem;
248
298
  };
299
+ private eventEmitter;
249
300
  constructor(options: PermissionOptions);
301
+ /**
302
+ * Add event listener
303
+ */
304
+ listen<T extends PermissionEventType>(event: T, listener: PermissionEventListener<PermissionEventMap[T]>): () => void;
305
+ /**
306
+ * Remove event listener
307
+ */
308
+ unlisten<T extends PermissionEventType>(event: T, listener: PermissionEventListener<PermissionEventMap[T]>): void;
309
+ /**
310
+ * Remove all listeners for a specific event or all events
311
+ */
312
+ unlistenAll(event?: PermissionEventType): void;
313
+ /**
314
+ * Emit event to all listeners
315
+ */
316
+ private emit;
317
+ /**
318
+ * Get available events that can be listened to
319
+ */
320
+ getAvailableEvents(): PermissionEventType[];
321
+ /**
322
+ * Check if an event is supported
323
+ */
324
+ isEventSupported(event: string): event is PermissionEventType;
250
325
  /**
251
326
  * Login using code from URL, save userInfo
252
327
  */
@@ -346,4 +421,4 @@ declare function jumpToSSOLogout({ baseUrl, redirectToUrl, clientId, }: {
346
421
  clientId?: string;
347
422
  }): void;
348
423
 
349
- export { type ApiResponse, type ChildOrganization, type CodeSourceType, DataHandler, EnumOrgQueryMode, EnumOrgQueryScope, type MenuItem, type OpenIndicatorType, Permission as OpmsPermission, type Option, type OrgRecord, type OrgTreeItem, type Resource, type ResourceType, type UserInfo, type UserOrgTreeParams, type UserOrganization, type UserRole, getOrgTree, getUserInfo, getUserOrgTree, jumpToSSOLogin, jumpToSSOLogout, login, logout, queryOrgCompanies, queryResource };
424
+ export { type ApiResponse, type ChildOrganization, type CodeSourceType, DataHandler, EnumOrgQueryMode, EnumOrgQueryScope, EventEmitter, type MenuItem, type OpenIndicatorType, Permission as OpmsPermission, type Option, type OrgRecord, type OrgTreeItem, type PermissionEventListener, type PermissionEventMap, type PermissionEventType, type Resource, type ResourceType, type UserInfo, type UserOrgTreeParams, type UserOrganization, type UserRole, getOrgTree, getUserInfo, getUserOrgTree, jumpToSSOLogin, jumpToSSOLogout, login, logout, queryOrgCompanies, queryResource };
package/dist/index.d.ts CHANGED
@@ -200,6 +200,56 @@ declare function handlePermissionTree<T extends {
200
200
  noAuthMap: Record<number | string, T>;
201
201
  };
202
202
 
203
+ type PermissionEventType = 'tokenChange';
204
+ type PermissionEventListener<T = any> = (data: T) => void;
205
+ interface PermissionEventMap {
206
+ tokenChange: string;
207
+ }
208
+ /**
209
+ * Generic Event Emitter class for handling events
210
+ */
211
+ declare class EventEmitter<TEventMap extends Record<string, any> = PermissionEventMap> {
212
+ private eventListeners;
213
+ private allowedEvents;
214
+ constructor(allowedEvents?: (keyof TEventMap)[]);
215
+ /**
216
+ * Add event listener
217
+ */
218
+ listen<TEvent extends keyof TEventMap>(event: TEvent, listener: PermissionEventListener<TEventMap[TEvent]>): () => void;
219
+ /**
220
+ * Remove event listener
221
+ */
222
+ unlisten<TEvent extends keyof TEventMap>(event: TEvent, listener: PermissionEventListener<TEventMap[TEvent]>): void;
223
+ /**
224
+ * Remove all listeners for a specific event or all events
225
+ */
226
+ unlistenAll(event?: keyof TEventMap): void;
227
+ /**
228
+ * Emit event to all listeners
229
+ */
230
+ emit<TEvent extends keyof TEventMap>(event: TEvent, data: TEventMap[TEvent]): void;
231
+ /**
232
+ * Get the number of listeners for a specific event
233
+ */
234
+ getListenerCount(event: keyof TEventMap): number;
235
+ /**
236
+ * Check if there are any listeners for a specific event
237
+ */
238
+ hasListeners(event: keyof TEventMap): boolean;
239
+ /**
240
+ * Get all registered event types
241
+ */
242
+ getEventTypes(): (keyof TEventMap)[];
243
+ /**
244
+ * Get all allowed event types
245
+ */
246
+ getAllowedEvents(): (keyof TEventMap)[];
247
+ /**
248
+ * Check if an event is allowed
249
+ */
250
+ isEventAllowed(event: keyof TEventMap): boolean;
251
+ }
252
+
203
253
  interface PermissionOptions {
204
254
  systemId: string;
205
255
  baseUrl: string;
@@ -246,7 +296,32 @@ declare class Permission {
246
296
  menuMap: {
247
297
  [path: string]: MenuItem;
248
298
  };
299
+ private eventEmitter;
249
300
  constructor(options: PermissionOptions);
301
+ /**
302
+ * Add event listener
303
+ */
304
+ listen<T extends PermissionEventType>(event: T, listener: PermissionEventListener<PermissionEventMap[T]>): () => void;
305
+ /**
306
+ * Remove event listener
307
+ */
308
+ unlisten<T extends PermissionEventType>(event: T, listener: PermissionEventListener<PermissionEventMap[T]>): void;
309
+ /**
310
+ * Remove all listeners for a specific event or all events
311
+ */
312
+ unlistenAll(event?: PermissionEventType): void;
313
+ /**
314
+ * Emit event to all listeners
315
+ */
316
+ private emit;
317
+ /**
318
+ * Get available events that can be listened to
319
+ */
320
+ getAvailableEvents(): PermissionEventType[];
321
+ /**
322
+ * Check if an event is supported
323
+ */
324
+ isEventSupported(event: string): event is PermissionEventType;
250
325
  /**
251
326
  * Login using code from URL, save userInfo
252
327
  */
@@ -346,4 +421,4 @@ declare function jumpToSSOLogout({ baseUrl, redirectToUrl, clientId, }: {
346
421
  clientId?: string;
347
422
  }): void;
348
423
 
349
- export { type ApiResponse, type ChildOrganization, type CodeSourceType, DataHandler, EnumOrgQueryMode, EnumOrgQueryScope, type MenuItem, type OpenIndicatorType, Permission as OpmsPermission, type Option, type OrgRecord, type OrgTreeItem, type Resource, type ResourceType, type UserInfo, type UserOrgTreeParams, type UserOrganization, type UserRole, getOrgTree, getUserInfo, getUserOrgTree, jumpToSSOLogin, jumpToSSOLogout, login, logout, queryOrgCompanies, queryResource };
424
+ export { type ApiResponse, type ChildOrganization, type CodeSourceType, DataHandler, EnumOrgQueryMode, EnumOrgQueryScope, EventEmitter, type MenuItem, type OpenIndicatorType, Permission as OpmsPermission, type Option, type OrgRecord, type OrgTreeItem, type PermissionEventListener, type PermissionEventMap, type PermissionEventType, type Resource, type ResourceType, type UserInfo, type UserOrgTreeParams, type UserOrganization, type UserRole, getOrgTree, getUserInfo, getUserOrgTree, jumpToSSOLogin, jumpToSSOLogout, login, logout, queryOrgCompanies, queryResource };
package/dist/index.mjs CHANGED
@@ -345,6 +345,104 @@ async function queryOrgCompanies(baseUrl, params) {
345
345
  );
346
346
  }
347
347
 
348
+ // src/utils/eventEmitter.ts
349
+ var EventEmitter = class {
350
+ constructor(allowedEvents) {
351
+ this.eventListeners = /* @__PURE__ */ new Map();
352
+ this.allowedEvents = new Set(allowedEvents || []);
353
+ }
354
+ /**
355
+ * Add event listener
356
+ */
357
+ listen(event, listener) {
358
+ if (this.allowedEvents.size > 0 && !this.allowedEvents.has(event)) {
359
+ const allowedEventsList = Array.from(this.allowedEvents).join(", ");
360
+ throw new Error(
361
+ `Event "${String(event)}" is not registered. Allowed events: ${allowedEventsList}`
362
+ );
363
+ }
364
+ if (!this.eventListeners.has(event)) {
365
+ this.eventListeners.set(event, /* @__PURE__ */ new Set());
366
+ }
367
+ const listeners = this.eventListeners.get(event);
368
+ listeners.add(listener);
369
+ return () => {
370
+ listeners.delete(listener);
371
+ if (listeners.size === 0) {
372
+ this.eventListeners.delete(event);
373
+ }
374
+ };
375
+ }
376
+ /**
377
+ * Remove event listener
378
+ */
379
+ unlisten(event, listener) {
380
+ const listeners = this.eventListeners.get(event);
381
+ if (listeners) {
382
+ listeners.delete(listener);
383
+ if (listeners.size === 0) {
384
+ this.eventListeners.delete(event);
385
+ }
386
+ }
387
+ }
388
+ /**
389
+ * Remove all listeners for a specific event or all events
390
+ */
391
+ unlistenAll(event) {
392
+ if (event) {
393
+ this.eventListeners.delete(event);
394
+ } else {
395
+ this.eventListeners.clear();
396
+ }
397
+ }
398
+ /**
399
+ * Emit event to all listeners
400
+ */
401
+ emit(event, data) {
402
+ const listeners = this.eventListeners.get(event);
403
+ if (listeners) {
404
+ listeners.forEach((listener) => {
405
+ try {
406
+ listener(data);
407
+ } catch (error) {
408
+ console.error(`Error in event listener for ${String(event)}:`, error);
409
+ }
410
+ });
411
+ }
412
+ }
413
+ /**
414
+ * Get the number of listeners for a specific event
415
+ */
416
+ getListenerCount(event) {
417
+ const listeners = this.eventListeners.get(event);
418
+ return listeners ? listeners.size : 0;
419
+ }
420
+ /**
421
+ * Check if there are any listeners for a specific event
422
+ */
423
+ hasListeners(event) {
424
+ return this.getListenerCount(event) > 0;
425
+ }
426
+ /**
427
+ * Get all registered event types
428
+ */
429
+ getEventTypes() {
430
+ return Array.from(this.eventListeners.keys());
431
+ }
432
+ /**
433
+ * Get all allowed event types
434
+ */
435
+ getAllowedEvents() {
436
+ return Array.from(this.allowedEvents);
437
+ }
438
+ /**
439
+ * Check if an event is allowed
440
+ */
441
+ isEventAllowed(event) {
442
+ return this.allowedEvents.size === 0 || this.allowedEvents.has(event);
443
+ }
444
+ };
445
+
348
446
  // src/permission.ts
349
447
  var DataHandler = {
350
448
  iterateOrgTree(orgTree) {
@@ -415,11 +513,59 @@ var Permission = class {
415
513
  this.widgetMap = {};
416
514
  this.menuList = [];
417
515
  this.menuMap = {};
516
+ // Event emitter instance - only allow tokenChange event
517
+ this.eventEmitter = new EventEmitter(["tokenChange"]);
418
518
  this.baseUrl = options.baseUrl;
419
519
  this.systemId = options.systemId;
420
520
  storage.setSystemId(this.systemId);
421
521
  storage.setVersion("1.0.0");
422
522
  }
523
+ /**
524
+ * Add event listener
525
+ */
526
+ listen(event, listener) {
527
+ try {
528
+ return this.eventEmitter.listen(event, listener);
529
+ } catch (error) {
530
+ if (error instanceof Error && error.message.includes("not registered")) {
531
+ const allowedEvents = this.eventEmitter.getAllowedEvents();
532
+ throw new Error(
533
+ `Permission event "${String(event)}" is not supported. Available events: ${allowedEvents.join(", ")}`
534
+ );
535
+ }
536
+ throw error;
537
+ }
538
+ }
539
+ /**
540
+ * Remove event listener
541
+ */
542
+ unlisten(event, listener) {
543
+ this.eventEmitter.unlisten(event, listener);
544
+ }
545
+ /**
546
+ * Remove all listeners for a specific event or all events
547
+ */
548
+ unlistenAll(event) {
549
+ this.eventEmitter.unlistenAll(event);
550
+ }
551
+ /**
552
+ * Emit event to all listeners
553
+ */
554
+ emit(event, data) {
555
+ this.eventEmitter.emit(event, data);
556
+ }
557
+ /**
558
+ * Get available events that can be listened to
559
+ */
560
+ getAvailableEvents() {
561
+ return this.eventEmitter.getAllowedEvents();
562
+ }
563
+ /**
564
+ * Check if an event is supported
565
+ */
566
+ isEventSupported(event) {
567
+ return this.eventEmitter.isEventAllowed(event);
568
+ }
423
569
  /**
424
570
  * Login using code from URL, save userInfo
425
571
  */
@@ -446,6 +592,7 @@ var Permission = class {
446
592
  const { token } = obj;
447
593
  url.searchParams.delete("code");
448
594
  storage.setItem(TOKEN_KEY, token);
595
+ this.emit("tokenChange", token);
449
596
  return token;
450
597
  }
451
598
  /**
@@ -457,6 +604,7 @@ var Permission = class {
457
604
  }
458
605
  clear() {
459
606
  storage.clear();
607
+ this.emit("tokenChange", "");
460
608
  }
461
609
  async getUserInfo() {
462
610
  const data = await getUserInfo(this.baseUrl);
@@ -568,6 +716,7 @@ var Permission = class {
568
716
  }
569
717
  setToken(token) {
570
718
  storage.setItem(TOKEN_KEY, token);
719
+ this.emit("tokenChange", token);
571
720
  }
572
721
  // --- Getters ---
573
722
  // get userInfo(): UserInfo | null {
@@ -679,6 +828,7 @@ export {
679
828
  DataHandler,
680
829
  EnumOrgQueryMode,
681
830
  EnumOrgQueryScope,
831
+ EventEmitter,
682
832
  Permission as OpmsPermission,
683
833
  getOrgTree,
684
834
  getUserInfo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mu-cabin/opms-permission",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Frontend SDK for OPMS permission and auth management.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",