floating-live 0.15.11 → 0.16.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +14 -10
  2. package/dist/FloatingLive.d.ts +6 -0
  3. package/dist/FloatingLive.js +8 -0
  4. package/dist/app.d.ts +46 -0
  5. package/dist/app.js +126 -0
  6. package/dist/command/index.d.ts +1 -0
  7. package/dist/command/index.js +1 -0
  8. package/dist/command/manager.d.ts +23 -0
  9. package/dist/command/manager.js +46 -0
  10. package/dist/command/types.d.ts +25 -0
  11. package/{esm/types/command.js → dist/command/types.js} +1 -1
  12. package/dist/error/index.d.ts +11 -0
  13. package/dist/error/index.js +9 -0
  14. package/dist/error/types.d.ts +6 -0
  15. package/{esm/types/error.js → dist/error/types.js} +1 -1
  16. package/dist/event/index.d.ts +1 -0
  17. package/dist/event/index.js +1 -0
  18. package/dist/event/manager.d.ts +9 -0
  19. package/dist/event/manager.js +17 -0
  20. package/dist/event/types.d.ts +42 -0
  21. package/{esm/types/events.js → dist/event/types.js} +1 -1
  22. package/dist/hook/index.d.ts +1 -0
  23. package/dist/hook/index.js +1 -0
  24. package/dist/hook/manager.d.ts +25 -0
  25. package/dist/hook/manager.js +79 -0
  26. package/dist/hook/types.d.ts +22 -0
  27. package/{esm/types/hook.js → dist/hook/types.js} +1 -1
  28. package/dist/index.d.ts +8 -5
  29. package/dist/index.js +8 -23
  30. package/dist/{types → live}/message.d.ts +185 -248
  31. package/{esm/types → dist/live}/message.js +1 -1
  32. package/dist/live/messageInfo.d.ts +93 -0
  33. package/dist/live/messageInfo.js +28 -0
  34. package/dist/live/platform.d.ts +40 -0
  35. package/dist/live/platform.js +1 -0
  36. package/dist/live/room.d.ts +150 -0
  37. package/dist/live/room.js +120 -0
  38. package/dist/plugin/context/CommonPluginContext.d.ts +45 -0
  39. package/dist/plugin/context/CommonPluginContext.js +273 -0
  40. package/dist/plugin/context/SafePluginContext.d.ts +34 -0
  41. package/dist/plugin/context/SafePluginContext.js +91 -0
  42. package/dist/plugin/index.d.ts +8 -0
  43. package/dist/plugin/index.js +5 -0
  44. package/dist/plugin/manager.d.ts +31 -0
  45. package/dist/plugin/manager.js +93 -0
  46. package/dist/plugin/types.d.ts +73 -0
  47. package/dist/plugin/types.js +1 -0
  48. package/dist/plugins/room/index.d.ts +116 -0
  49. package/dist/plugins/room/index.js +172 -0
  50. package/dist/utils/EventEmitter.d.ts +6 -0
  51. package/dist/utils/EventEmitter.js +26 -0
  52. package/dist/utils/index.d.ts +2 -0
  53. package/dist/utils/index.js +4 -0
  54. package/dist/value/index.d.ts +1 -0
  55. package/dist/value/index.js +1 -0
  56. package/dist/value/manager.d.ts +24 -0
  57. package/dist/value/manager.js +63 -0
  58. package/dist/value/types.d.ts +19 -0
  59. package/dist/value/types.js +1 -0
  60. package/package.json +9 -40
  61. package/src/source.md +29 -0
  62. package/tsconfig.tsbuildinfo +1 -0
  63. package/dist/core/LiveRoom.d.ts +0 -44
  64. package/dist/core/LiveRoom.js +0 -81
  65. package/dist/core/index.d.ts +0 -1
  66. package/dist/core/index.js +0 -17
  67. package/dist/core/plugin.d.ts +0 -17
  68. package/dist/core/plugin.js +0 -28
  69. package/dist/enums.d.ts +0 -51
  70. package/dist/enums.js +0 -59
  71. package/dist/live.d.ts +0 -39
  72. package/dist/live.js +0 -51
  73. package/dist/module/command.d.ts +0 -18
  74. package/dist/module/command.js +0 -42
  75. package/dist/module/hook.d.ts +0 -15
  76. package/dist/module/hook.js +0 -51
  77. package/dist/module/manifest.d.ts +0 -15
  78. package/dist/module/manifest.js +0 -44
  79. package/dist/module/plugin.d.ts +0 -16
  80. package/dist/module/plugin.js +0 -85
  81. package/dist/module/room.d.ts +0 -34
  82. package/dist/module/room.js +0 -164
  83. package/dist/module/value.d.ts +0 -26
  84. package/dist/module/value.js +0 -60
  85. package/dist/types/command.d.ts +0 -23
  86. package/dist/types/command.js +0 -2
  87. package/dist/types/error.d.ts +0 -10
  88. package/dist/types/error.js +0 -2
  89. package/dist/types/events.d.ts +0 -41
  90. package/dist/types/events.js +0 -2
  91. package/dist/types/hook.d.ts +0 -15
  92. package/dist/types/hook.js +0 -2
  93. package/dist/types/index.d.ts +0 -9
  94. package/dist/types/index.js +0 -25
  95. package/dist/types/manifest.d.ts +0 -4
  96. package/dist/types/manifest.js +0 -2
  97. package/dist/types/message.js +0 -2
  98. package/dist/types/plugin.d.ts +0 -13
  99. package/dist/types/plugin.js +0 -2
  100. package/dist/types/room.d.ts +0 -98
  101. package/dist/types/room.js +0 -2
  102. package/dist/types/value.d.ts +0 -2
  103. package/dist/types/value.js +0 -2
  104. package/dist/utils.d.ts +0 -2
  105. package/dist/utils.js +0 -21
  106. package/esm/core/LiveRoom.js +0 -77
  107. package/esm/core/index.js +0 -1
  108. package/esm/core/plugin.js +0 -24
  109. package/esm/enums.js +0 -56
  110. package/esm/index.js +0 -5
  111. package/esm/live.js +0 -47
  112. package/esm/module/command.js +0 -38
  113. package/esm/module/hook.js +0 -47
  114. package/esm/module/manifest.js +0 -40
  115. package/esm/module/plugin.js +0 -81
  116. package/esm/module/room.js +0 -160
  117. package/esm/module/value.js +0 -56
  118. package/esm/types/index.js +0 -9
  119. package/esm/types/manifest.js +0 -1
  120. package/esm/types/plugin.js +0 -1
  121. package/esm/types/room.js +0 -1
  122. package/esm/types/value.js +0 -1
  123. package/esm/utils.js +0 -17
@@ -0,0 +1,91 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _SafePluginContext_permissions;
13
+ import { AppError } from "../../error";
14
+ import { CommonPluginContext } from "./CommonPluginContext";
15
+ export class SafePluginContext extends CommonPluginContext {
16
+ get safe() {
17
+ return true;
18
+ }
19
+ constructor(app, pluginName, options) {
20
+ super(app, pluginName);
21
+ _SafePluginContext_permissions.set(this, {});
22
+ __classPrivateFieldSet(this, _SafePluginContext_permissions, options.permissions, "f");
23
+ }
24
+ throwNotPermitted(permission, cause) {
25
+ this.throw(new AppError("plugin:no_permission", {
26
+ message: "插件权限不足",
27
+ cause,
28
+ permission,
29
+ }));
30
+ }
31
+ register(plugin, options) {
32
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["plugin.register"]) {
33
+ this.throwNotPermitted("plugin.register", "无插件安装权限");
34
+ }
35
+ return super.register(plugin, options);
36
+ }
37
+ unregister(pluginName) {
38
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["plugin.register"]) {
39
+ this.throwNotPermitted("plugin.register", "无插件安装权限");
40
+ }
41
+ return super.unregister(pluginName);
42
+ }
43
+ emit(type, detail, options) {
44
+ if (!(__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["event.emit.advanced"] ||
45
+ __classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["event.emit"]?.includes(type))) {
46
+ this.throwNotPermitted(`event.emit:${type}`, `无事件[${type}]的发送权限`);
47
+ }
48
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["event.emit.advanced"] && options) {
49
+ this.throwNotPermitted("event.emit.advanced", `无事件高级发送权限`);
50
+ }
51
+ return super.emit(type, detail, options);
52
+ }
53
+ call(name, ...args) {
54
+ if (!(__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["command.call.advanced"] ||
55
+ __classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["command.call"]?.includes(name))) {
56
+ this.throwNotPermitted(`command.call:${name}`, `无命令[${name}]的调用权限`);
57
+ }
58
+ return super.call(name, ...args);
59
+ }
60
+ callWithOptions(name, options, ...args) {
61
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["command.call.advanced"]) {
62
+ this.throwNotPermitted("command.call.advanced", "无命令高级调用权限");
63
+ }
64
+ return super.callWithOptions(name, options, ...args);
65
+ }
66
+ registerCommand(name, func, options) {
67
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["command.register"]?.includes(name)) {
68
+ this.throwNotPermitted(`command.call:${name}`, `无命令[${name}]的注册权限`);
69
+ }
70
+ return super.registerCommand(name, func, options);
71
+ }
72
+ useHook(name, func, options) {
73
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["hook.use"]?.includes(name)) {
74
+ this.throwNotPermitted(`hook.use:${name}`, `无钩子[${name}]的挂载权限`);
75
+ }
76
+ return super.useHook(name, func, options);
77
+ }
78
+ unuseHook(name, func) {
79
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["hook.use"]?.includes(name)) {
80
+ this.throwNotPermitted(`hook.use:${name}`, `无钩子[${name}]的挂载权限`);
81
+ }
82
+ return super.unuseHook(name, func);
83
+ }
84
+ callHook(name, ctx, options) {
85
+ if (!__classPrivateFieldGet(this, _SafePluginContext_permissions, "f")["hook.call"]?.includes(name)) {
86
+ this.throwNotPermitted(`hook.call:${name}`, `无钩子[${name}]的调用权限`);
87
+ }
88
+ return super.callHook(name, ctx);
89
+ }
90
+ }
91
+ _SafePluginContext_permissions = new WeakMap();
@@ -0,0 +1,8 @@
1
+ import type { PluginItem, PluginContext } from "./types";
2
+ export type * from "./types";
3
+ export declare class BasePlugin implements PluginItem {
4
+ static pluginName: string;
5
+ pluginName: string;
6
+ ctx: PluginContext;
7
+ constructor(ctx: PluginContext, options?: any);
8
+ }
@@ -0,0 +1,5 @@
1
+ export class BasePlugin {
2
+ constructor(ctx, options) {
3
+ this.ctx = ctx;
4
+ }
5
+ }
@@ -0,0 +1,31 @@
1
+ import type { App } from "../app";
2
+ import { AppError, ErrorOptions } from "../error";
3
+ import { PluginItem, PluginConstructor, PluginContext } from "./types";
4
+ export interface PluginErrorOptions extends ErrorOptions {
5
+ pluginName: string;
6
+ }
7
+ export declare class PluginError extends AppError {
8
+ pluginName: string;
9
+ constructor(id: string, options: PluginErrorOptions);
10
+ }
11
+ export interface PluginData<T> {
12
+ plugin: PluginItem;
13
+ context: PluginContext;
14
+ exposes?: T;
15
+ }
16
+ export declare class PluginManager {
17
+ /** 插件列表 */
18
+ private list;
19
+ protected readonly app: App;
20
+ constructor(app: App);
21
+ /** 注册插件 */
22
+ register(pluginConstructor: PluginConstructor, options?: Record<string, any>): Promise<PluginItem | undefined>;
23
+ /** 移除插件 */
24
+ unregister(pluginName: string): Promise<void>;
25
+ /** 获取插件实例 */
26
+ get(pluginName: string): PluginData<any> | undefined;
27
+ has(pluginName: string): boolean;
28
+ getPlugin(pluginName: string): PluginItem | undefined;
29
+ getExposes(pluginName: string): any;
30
+ toData(): string[];
31
+ }
@@ -0,0 +1,93 @@
1
+ import { CommonPluginContext } from "./context/CommonPluginContext";
2
+ import { AppError } from "../error";
3
+ export class PluginError extends AppError {
4
+ constructor(id, options) {
5
+ super(id, options);
6
+ this.pluginName = options.pluginName;
7
+ }
8
+ }
9
+ export class PluginManager {
10
+ constructor(app) {
11
+ /** 插件列表 */
12
+ this.list = new Map();
13
+ this.app = app;
14
+ }
15
+ /** 注册插件 */
16
+ async register(pluginConstructor, options = {}) {
17
+ const pluginName = pluginConstructor.pluginName;
18
+ if (!pluginName) {
19
+ throw new PluginError("plugin:register_id_missing", {
20
+ message: "插件注册失败",
21
+ cause: "插件缺少pluginName字段",
22
+ pluginName: "",
23
+ });
24
+ }
25
+ if (this.list.has(pluginName)) {
26
+ throw new PluginError("plugin:register_id_duplicate", {
27
+ message: `插件注册失败: ${pluginName}`,
28
+ cause: "已存在相同id的插件",
29
+ pluginName,
30
+ });
31
+ }
32
+ const registerCtx = { pluginName, options };
33
+ const pluginCtx = new CommonPluginContext(this.app, pluginName);
34
+ return await this.app
35
+ .callHook("plugin.register", registerCtx)
36
+ .then(async (ctx) => {
37
+ if (ctx.defaultPrevented)
38
+ return;
39
+ // 执行插件函数
40
+ const plugin = new pluginConstructor(pluginCtx, registerCtx.options || {});
41
+ // 调用插件的register钩子
42
+ await plugin.register?.(pluginCtx, registerCtx.options || {});
43
+ this.list.set(pluginName, { plugin, context: pluginCtx });
44
+ this.app.emit("plugin:register", { pluginName });
45
+ return plugin;
46
+ })
47
+ .catch((err) => {
48
+ throw new PluginError("plugin:register_fail", {
49
+ message: `插件注册失败: ${pluginName}`,
50
+ cause: err,
51
+ pluginName,
52
+ });
53
+ });
54
+ }
55
+ /** 移除插件 */
56
+ async unregister(pluginName) {
57
+ const pluginData = this.list.get(pluginName);
58
+ // 检测插件是否存在
59
+ if (!pluginData) {
60
+ throw new PluginError("plugin:unregister_unexist", {
61
+ message: `插件移除失败: ${pluginName}`,
62
+ cause: "插件不存在",
63
+ pluginName,
64
+ });
65
+ }
66
+ else {
67
+ const { plugin, context } = pluginData;
68
+ // 调用插件和上下文的destroy钩子
69
+ plugin.destroy?.(context);
70
+ context.destroy();
71
+ // 从列表中移除插件
72
+ this.list.delete(pluginName);
73
+ // 移除插件注册事件
74
+ this.app.emit("plugin:unregister", { pluginName });
75
+ }
76
+ }
77
+ /** 获取插件实例 */
78
+ get(pluginName) {
79
+ return this.list.get(pluginName);
80
+ }
81
+ has(pluginName) {
82
+ return this.list.has(pluginName);
83
+ }
84
+ getPlugin(pluginName) {
85
+ return this.list.get(pluginName)?.plugin;
86
+ }
87
+ getExposes(pluginName) {
88
+ return this.list.get(pluginName)?.exposes;
89
+ }
90
+ toData() {
91
+ return [...this.list.keys()];
92
+ }
93
+ }
@@ -0,0 +1,73 @@
1
+ import { CommandOptions, CommandCallOptions, AppCommandMap, CommandFunction } from "../command";
2
+ import { AppError, ErrorOptions } from "../error";
3
+ import { AppEventListener, AppEventEmitOptions, AppEventDetailMap } from "../event";
4
+ import { AppHookMap, HookCallOptions, HookContext, HookFunction, HookUseOptions } from "../hook";
5
+ import { AppValueMap, ValueOptions } from "../value";
6
+ /** 插件对象 */
7
+ export interface PluginItem {
8
+ pluginName: string;
9
+ register?(ctx: PluginContext, options?: Record<string, any>): void;
10
+ destroy?(ctx: PluginContext): void;
11
+ }
12
+ /** 插件构造器 */
13
+ export interface PluginConstructor {
14
+ pluginName: string;
15
+ new (ctx: PluginContext, options: any): PluginItem;
16
+ }
17
+ /** 插件注册选项 */
18
+ export interface PluginRegisterOptions {
19
+ }
20
+ /** 插件上下文 */
21
+ export interface PluginContext {
22
+ /** 监听事件 */
23
+ on<K extends keyof AppEventDetailMap>(type: K, listener: AppEventListener<AppEventDetailMap[K]>): void;
24
+ /** 单次监听事件 */
25
+ once<K extends keyof AppEventDetailMap>(type: K, listener: AppEventListener<AppEventDetailMap[K]>): void;
26
+ /** 取消监听事件 */
27
+ off<K extends keyof AppEventDetailMap>(type: K, listener: AppEventListener<AppEventDetailMap[K]>): void;
28
+ /** 发送事件 */
29
+ emit<K extends keyof AppEventDetailMap>(type: K, detail: AppEventDetailMap[K], options?: AppEventEmitOptions & EventInit): void;
30
+ /** 抛出错误 */
31
+ throw(err?: Error): void;
32
+ /** 生成错误 */
33
+ error(id: string, options: ErrorOptions): AppError;
34
+ /** 注册插件 */
35
+ register(plugin: PluginConstructor, options?: PluginRegisterOptions): void;
36
+ /** 取消注册插件 */
37
+ unregister(pluginName: string): void;
38
+ /** 获取插件暴露对象 */
39
+ getPluginExposes<T>(pluginName: string): T;
40
+ /** 等待plugin注册 */
41
+ whenRegister(pluginName: string, callback: (exposes: any) => (() => void) | void): void;
42
+ /** 是否存在插件 */
43
+ hasPlugin(pluginName: string): boolean;
44
+ /** 注册指令 */
45
+ registerCommand<T extends keyof AppCommandMap>(name: T, func: CommandFunction<AppCommandMap[T]>, options?: CommandOptions): void;
46
+ /** 取消注册指令 */
47
+ unregisterCommand(name: string): void;
48
+ /** 调用指令 */
49
+ call<T extends keyof AppCommandMap>(name: T, ...args: Parameters<AppCommandMap[T]>): ReturnType<AppCommandMap[T]>;
50
+ /** 调用指令(可配置) */
51
+ callWithOptions<T extends keyof AppCommandMap>(name: T, options: CommandCallOptions, ...args: Parameters<AppCommandMap[T]>): ReturnType<AppCommandMap[T]>;
52
+ /** 挂载钩子 */
53
+ useHook<T extends keyof AppHookMap>(name: T, func: HookFunction<AppHookMap[T]>, options?: HookUseOptions): void;
54
+ /** 取消挂载钩子 */
55
+ unuseHook<T extends keyof AppHookMap>(name: T, func: HookFunction<AppHookMap[T]>): void;
56
+ /** 调用钩子 */
57
+ callHook<T extends keyof AppHookMap>(name: T, ctx: AppHookMap[T], options?: HookCallOptions): Promise<HookContext<AppHookMap[T]>>;
58
+ /** 调用同步钩子 */
59
+ callHookSync<T extends keyof AppHookMap>(name: T, ctx: AppHookMap[T], options?: HookCallOptions): HookContext<AppHookMap[T]>;
60
+ /** 注册值 */
61
+ registerValue<K extends keyof AppValueMap>(name: K, options: ValueOptions<AppValueMap[K]>): void;
62
+ /** 取消注册值 */
63
+ unregisterValue(name: string): void;
64
+ /** 监听值 */
65
+ watch<K extends keyof AppValueMap>(name: K, watcher: (value: AppValueMap[K]) => void): void;
66
+ /** 取消监听值 */
67
+ unwatch<K extends keyof AppValueMap>(name: K, watcher: (value: AppValueMap[K]) => void): void;
68
+ /** 获取值 */
69
+ getValue<K extends keyof AppValueMap>(name: K): AppValueMap[K];
70
+ /** 设置值 */
71
+ setValue<K extends keyof AppValueMap>(name: K, value: AppValueMap[K]): void;
72
+ destroy(): void;
73
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,116 @@
1
+ import { LiveMessage } from "../../live/message";
2
+ import { LiveRoom, LiveRoomDetailInfo, LiveRoomData, LiveRoomStatsInfo, LiveRoomStatus } from "../../live/room";
3
+ import { BasePlugin } from "../../plugin";
4
+ import { PluginContext } from "../../plugin/types";
5
+ declare module "../.." {
6
+ interface AppCommandMap {
7
+ add: (platform: string, id: number, options?: boolean | Record<string, any>) => void;
8
+ remove: (key: string) => void;
9
+ move: (key: string, position: number) => void;
10
+ open: (key: string) => void;
11
+ close: (key: string) => void;
12
+ update: (key: string) => void;
13
+ "room.snapshot": () => LiveRoomData[];
14
+ [name: `${string}.room.create`]: (id: string | number, options: Record<string, any>) => LiveRoom | Promise<LiveRoom>;
15
+ }
16
+ interface AppEventDetailMap {
17
+ "live:message": {
18
+ message: LiveMessage.All;
19
+ };
20
+ "live:raw": {
21
+ platform: string;
22
+ roomId: string | number;
23
+ data: any;
24
+ };
25
+ "room:connecting": {
26
+ key: string;
27
+ };
28
+ "room:connected": {
29
+ key: string;
30
+ };
31
+ "room:disconnect": {
32
+ key: string;
33
+ };
34
+ "room:enter": {
35
+ key: string;
36
+ };
37
+ "room:add": {
38
+ key: string;
39
+ room: LiveRoomData;
40
+ };
41
+ "room:remove": {
42
+ key: string;
43
+ };
44
+ "room:move": {
45
+ key: string;
46
+ position: number;
47
+ };
48
+ "room:open": {
49
+ key: string;
50
+ room: LiveRoomData;
51
+ };
52
+ "room:close": {
53
+ key: string;
54
+ room: LiveRoomData;
55
+ };
56
+ "room:update": {
57
+ key: string;
58
+ room: LiveRoomData;
59
+ };
60
+ "room:detail": {
61
+ key: string;
62
+ detail: LiveRoomDetailInfo;
63
+ };
64
+ "room:stats": {
65
+ key: string;
66
+ stats: LiveRoomStatsInfo;
67
+ };
68
+ "room:status": {
69
+ key: string;
70
+ status: LiveRoomStatus;
71
+ liveId?: string | number;
72
+ timestamp: number;
73
+ };
74
+ }
75
+ interface AppHookMap {
76
+ "live.message": {
77
+ message: LiveMessage.All;
78
+ };
79
+ "room.add": {
80
+ platform: string;
81
+ id: string | number;
82
+ options: Record<string, any>;
83
+ };
84
+ }
85
+ }
86
+ export default class Room extends BasePlugin {
87
+ static pluginName: string;
88
+ private map;
89
+ private symbolRoomEventHandlers;
90
+ constructor(ctx: PluginContext);
91
+ /** 添加房间监听实例 */
92
+ attachRoom(room: LiveRoom, open?: boolean): void;
93
+ /** 添加房间 */
94
+ add(platform: string, id: number, options?: boolean | Record<string, any>): Promise<void>;
95
+ /** 移除房间 */
96
+ remove(key: string): void;
97
+ /** 获取房间 */
98
+ get(key: string): LiveRoom | undefined;
99
+ has(key: string): boolean;
100
+ /** 获取房间信息 */
101
+ info(key: string): LiveRoomData | undefined;
102
+ /** 更新房间信息 */
103
+ update(key: string): void;
104
+ /** 获取房间key列表 */
105
+ get keys(): Array<string>;
106
+ /** 获取房间列表 */
107
+ getList(): Array<LiveRoom>;
108
+ /** 打开房间连接 */
109
+ open(key: string): void;
110
+ /** 关闭房间连接 */
111
+ close(key: string): void;
112
+ /** 更改某个房间的顺序 */
113
+ move(key: string, position: number): void;
114
+ /** 获取快照 */
115
+ getSnapshot(): LiveRoomData[];
116
+ }
@@ -0,0 +1,172 @@
1
+ import { AppError } from "../../error";
2
+ import { BasePlugin } from "../../plugin";
3
+ import { bindCommand } from "../../utils";
4
+ class Room extends BasePlugin {
5
+ constructor(ctx) {
6
+ super(ctx);
7
+ this.map = new Map();
8
+ this.symbolRoomEventHandlers = Symbol("room.roomEventHandlers");
9
+ ctx.registerCommand("add", bindCommand(this.add, this));
10
+ ctx.registerCommand("remove", bindCommand(this.remove, this));
11
+ ctx.registerCommand("open", bindCommand(this.open, this));
12
+ ctx.registerCommand("close", bindCommand(this.close, this));
13
+ ctx.registerCommand("update", bindCommand(this.update, this));
14
+ ctx.registerCommand("room.snapshot", bindCommand(this.getSnapshot, this));
15
+ }
16
+ /** 添加房间监听实例 */
17
+ attachRoom(room, open) {
18
+ let key = room.key;
19
+ if (this.map.has(key)) {
20
+ this.ctx.throw(new AppError("room:add_exist", {
21
+ message: "房间已存在",
22
+ }));
23
+ return;
24
+ }
25
+ this.map.set(key, room);
26
+ const eventHandlers = [];
27
+ room[this.symbolRoomEventHandlers] = eventHandlers;
28
+ const setHandler = (type, listener) => {
29
+ room.on(type, listener);
30
+ eventHandlers.push([type, listener]);
31
+ };
32
+ // 添加监听事件
33
+ // 直播消息
34
+ setHandler("message", ({ message }) => {
35
+ const ctx = { message };
36
+ this.ctx.callHook("live.message", ctx).then((ctx) => {
37
+ !ctx.defaultPrevented &&
38
+ this.ctx.emit("live:message", { message: ctx.message });
39
+ });
40
+ });
41
+ // 直播消息源数据
42
+ setHandler("raw", ({ platform, roomId, data }) => {
43
+ this.ctx.emit("live:raw", { platform, roomId, data });
44
+ });
45
+ // 正在连接服务器
46
+ setHandler("connecting", () => {
47
+ this.ctx.emit("room:connecting", { key });
48
+ });
49
+ // 连接到服务器
50
+ setHandler("connected", () => {
51
+ this.ctx.emit("room:connected", { key });
52
+ });
53
+ // 与服务器的连接已断开
54
+ setHandler("disconnect", () => {
55
+ this.ctx.emit("room:disconnect", { key });
56
+ });
57
+ // 连接到直播间
58
+ setHandler("enter", () => {
59
+ this.ctx.emit("room:enter", { key });
60
+ });
61
+ // 获取房间信息
62
+ setHandler("update", () => {
63
+ this.ctx.emit("room:update", { key, room: room.toData() });
64
+ });
65
+ // 直播展示信息更改
66
+ setHandler("detail", ({ detail }) => {
67
+ this.ctx.emit("room:detail", { key, detail });
68
+ });
69
+ // 直播状态更改
70
+ setHandler("status", ({ liveId, timestamp, status }) => {
71
+ this.ctx.emit("room:status", { key, status, liveId, timestamp });
72
+ });
73
+ // 统计数据更新
74
+ setHandler("stats", ({ stats }) => {
75
+ this.ctx.emit("room:stats", { key, stats });
76
+ });
77
+ // 房间被打开
78
+ setHandler("open", () => {
79
+ this.ctx.emit("room:open", { key, room: room.toData() });
80
+ });
81
+ // 房间被关闭
82
+ setHandler("close", () => {
83
+ this.ctx.emit("room:close", { key, room: room.toData() });
84
+ });
85
+ if (open) {
86
+ room.open();
87
+ }
88
+ this.ctx.emit("room:add", { key, room: room.toData() });
89
+ }
90
+ /** 添加房间 */
91
+ async add(platform, id, options) {
92
+ const opt = typeof options == "boolean" ? { open: options } : options || {};
93
+ const ctx = { platform, id, options: opt };
94
+ const res = await this.ctx.callHook("room.add", ctx);
95
+ if (!res.defaultPrevented) {
96
+ this.ctx.throw(this.ctx.error("room:add_fail", { message: "无法添加房间" }));
97
+ }
98
+ const room = await this.ctx.call(`${platform}.room.create`, id, opt);
99
+ if (!room) {
100
+ this.ctx.throw(this.ctx.error("room:create_fail", { message: "无法创建房间" }));
101
+ }
102
+ else {
103
+ this.attachRoom(room);
104
+ }
105
+ }
106
+ /** 移除房间 */
107
+ remove(key) {
108
+ let room = this.map.get(key);
109
+ if (!room) {
110
+ this.ctx.throw(this.ctx.error("room:remove_unexist", {
111
+ message: "房间不存在",
112
+ }));
113
+ }
114
+ this.map.delete(key); // 从表中删除房间
115
+ room[this.symbolRoomEventHandlers].forEach(([type, listener]) => {
116
+ room?.removeEventListener(type, listener);
117
+ }); // 移除房间监听实例
118
+ this.ctx.emit("room:remove", { key });
119
+ }
120
+ /** 获取房间 */
121
+ get(key) {
122
+ return this.map.get(key);
123
+ }
124
+ has(key) {
125
+ return this.map.has(key);
126
+ }
127
+ /** 获取房间信息 */
128
+ info(key) {
129
+ let room = this.map.get(key);
130
+ return room ? room.toData() : undefined;
131
+ }
132
+ /** 更新房间信息 */
133
+ update(key) {
134
+ let room = this.map.get(key);
135
+ room && room.getInfo();
136
+ }
137
+ /** 获取房间key列表 */
138
+ get keys() {
139
+ return [...this.map.keys()];
140
+ }
141
+ /** 获取房间列表 */
142
+ getList() {
143
+ return [...this.map.values()];
144
+ }
145
+ /** 打开房间连接 */
146
+ open(key) {
147
+ let room = this.map.get(key);
148
+ room?.available && !room.opened && room.open();
149
+ }
150
+ /** 关闭房间连接 */
151
+ close(key) {
152
+ let room = this.map.get(key);
153
+ room?.opened && room.close();
154
+ }
155
+ /** 更改某个房间的顺序 */
156
+ move(key, position) {
157
+ const arr = [...this.map];
158
+ const index = arr.findIndex(([k]) => k == key);
159
+ if (index == -1)
160
+ return;
161
+ const [item] = arr.splice(index, 1);
162
+ arr.splice(position, 0, item);
163
+ this.map = new Map(arr);
164
+ this.ctx.emit("room:move", { key, position });
165
+ }
166
+ /** 获取快照 */
167
+ getSnapshot() {
168
+ return this.getList().map((room) => room.toData());
169
+ }
170
+ }
171
+ Room.pluginName = "room";
172
+ export default Room;
@@ -0,0 +1,6 @@
1
+ export declare class CustomEventEmitter extends EventTarget {
2
+ on(type: string, listener: (e: any) => void): void;
3
+ once(type: string, listener: (e: any) => void): void;
4
+ off(type: string, listener: (e: any) => void): void;
5
+ emit(type: string, detail: any, options?: EventInit): void;
6
+ }
@@ -0,0 +1,26 @@
1
+ const listenerMap = new WeakMap();
2
+ function getListenerCallback(listener) {
3
+ const existed = listenerMap.get(listener);
4
+ if (existed)
5
+ return existed;
6
+ const newItem = (e) => {
7
+ listener(e.detail);
8
+ };
9
+ listenerMap.set(listener, newItem);
10
+ return newItem;
11
+ }
12
+ export class CustomEventEmitter extends EventTarget {
13
+ on(type, listener) {
14
+ this.addEventListener(type, getListenerCallback(listener));
15
+ }
16
+ once(type, listener) {
17
+ this.addEventListener(type, getListenerCallback(listener), { once: true });
18
+ }
19
+ off(type, listener) {
20
+ this.removeEventListener(type, getListenerCallback(listener));
21
+ }
22
+ emit(type, detail, options) {
23
+ const event = new CustomEvent(type, { detail, ...options });
24
+ this.dispatchEvent(event);
25
+ }
26
+ }
@@ -0,0 +1,2 @@
1
+ import { CommandContext } from "../command";
2
+ export declare function bindCommand<T extends (...args: any) => any>(command: T, thisArg: any): (e: CommandContext, ...args: Parameters<T>) => ReturnType<T>;
@@ -0,0 +1,4 @@
1
+ export function bindCommand(command, thisArg) {
2
+ const c = ((e, ...args) => command(...args)).bind(thisArg);
3
+ return c;
4
+ }
@@ -0,0 +1 @@
1
+ export * from "./types";
@@ -0,0 +1 @@
1
+ export * from "./types";
@@ -0,0 +1,24 @@
1
+ import { App } from "../app";
2
+ import { ValueAccessOptions, ValueOptions } from "./types";
3
+ export declare class ValueManager {
4
+ private list;
5
+ protected readonly app: App;
6
+ constructor(app: App);
7
+ /** 注册值 */
8
+ register<T>(name: string, { get, set, pluginName }: ValueOptions<T>): void;
9
+ /** 取消注册 */
10
+ unregister(name: string): void;
11
+ /** 获取值 */
12
+ get(name: string, options?: ValueAccessOptions): any;
13
+ /** 获取值(不存在则返回undefined) */
14
+ getNullable(name: string, options?: ValueAccessOptions): any;
15
+ /** 设置值 */
16
+ set(name: string, value: any, options?: ValueAccessOptions): boolean;
17
+ /** 检测值是否存在 */
18
+ has(name: string): boolean;
19
+ emit(name: string, value: any): void;
20
+ watch(name: string, listener: (value: any) => void): void;
21
+ unwatch(name: string, listener: (value: any) => void): void;
22
+ /** 获取注册的所有值 */
23
+ getData(): Record<string, any>;
24
+ }