floating-live 0.15.0-beta.0 → 0.15.0-beta.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.
Files changed (42) hide show
  1. package/README.md +3 -34
  2. package/dist/core/LiveRoom.d.ts +0 -2
  3. package/dist/core/index.d.ts +0 -1
  4. package/dist/core/index.js +0 -1
  5. package/dist/core/plugin.d.ts +17 -0
  6. package/dist/core/plugin.js +28 -0
  7. package/dist/index.d.ts +0 -1
  8. package/dist/index.js +0 -1
  9. package/dist/live.d.ts +17 -19
  10. package/dist/live.js +19 -38
  11. package/dist/module/command.d.ts +15 -0
  12. package/dist/module/command.js +24 -0
  13. package/dist/module/hook.d.ts +13 -0
  14. package/dist/module/hook.js +44 -0
  15. package/dist/module/plugin.d.ts +15 -0
  16. package/dist/module/{ModPlugin.js → plugin.js} +19 -25
  17. package/dist/module/{ModRoom.d.ts → room.d.ts} +2 -12
  18. package/dist/module/room.js +125 -0
  19. package/dist/module/store.d.ts +14 -0
  20. package/dist/module/store.js +42 -0
  21. package/dist/module/values.d.ts +21 -0
  22. package/dist/module/values.js +41 -0
  23. package/dist/types/events.d.ts +26 -0
  24. package/dist/types/index.d.ts +0 -1
  25. package/dist/types/index.js +0 -1
  26. package/dist/types/plugin.d.ts +9 -2
  27. package/dist/types/room.d.ts +10 -0
  28. package/package.json +8 -15
  29. package/dist/core/Reglist.d.ts +0 -29
  30. package/dist/core/Reglist.js +0 -69
  31. package/dist/module/ModAuth.d.ts +0 -10
  32. package/dist/module/ModAuth.js +0 -35
  33. package/dist/module/ModCommand.d.ts +0 -9
  34. package/dist/module/ModCommand.js +0 -19
  35. package/dist/module/ModMessage.d.ts +0 -9
  36. package/dist/module/ModMessage.js +0 -16
  37. package/dist/module/ModPlugin.d.ts +0 -20
  38. package/dist/module/ModRoom.js +0 -164
  39. package/dist/module/ModState.d.ts +0 -12
  40. package/dist/module/ModState.js +0 -29
  41. package/dist/types/auth.d.ts +0 -19
  42. /package/dist/types/{auth.js → events.js} +0 -0
@@ -0,0 +1,21 @@
1
+ import { FloatingLive } from "../live";
2
+ interface ValueConfig<T> {
3
+ get: () => T;
4
+ set?: (value: T) => void;
5
+ }
6
+ export declare class ModValues {
7
+ private list;
8
+ protected readonly main: FloatingLive;
9
+ constructor(main: FloatingLive);
10
+ /** 注册值 */
11
+ register<T>(name: string, config: ValueConfig<T>): void;
12
+ /** 取消注册 */
13
+ unregister(name: string): void;
14
+ /** 获取值 */
15
+ get(name: string): any;
16
+ /** 设置值 */
17
+ set(name: string, value: any): boolean;
18
+ /** 获取注册的所有值 */
19
+ getMap(): Record<string, any>;
20
+ }
21
+ export {};
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModValues = void 0;
4
+ class ModValues {
5
+ constructor(main) {
6
+ this.list = new Map();
7
+ this.main = main;
8
+ }
9
+ /** 注册值 */
10
+ register(name, config) {
11
+ this.list.set(name, config);
12
+ }
13
+ /** 取消注册 */
14
+ unregister(name) {
15
+ this.list.delete(name);
16
+ }
17
+ /** 获取值 */
18
+ get(name) {
19
+ return this.list.get(name)?.get();
20
+ }
21
+ /** 设置值 */
22
+ set(name, value) {
23
+ const valueConfig = this.list.get(name);
24
+ if (valueConfig?.set) {
25
+ valueConfig?.set(value);
26
+ return true;
27
+ }
28
+ else {
29
+ return false;
30
+ }
31
+ }
32
+ /** 获取注册的所有值 */
33
+ getMap() {
34
+ const map = {};
35
+ this.list.forEach((config, name) => {
36
+ map[name] = config.get();
37
+ });
38
+ return map;
39
+ }
40
+ }
41
+ exports.ModValues = ModValues;
@@ -0,0 +1,26 @@
1
+ import { RoomStatus } from "../enums";
2
+ import { Message } from "./message";
3
+ import { RoomDetail, RoomInfo, RoomStatsInfo } from "./room";
4
+ export interface FloatingEventMap {
5
+ "live:message": (msg: Message.All) => void;
6
+ "live:raw": (data: any) => void;
7
+ "room:connect": (key: string) => void;
8
+ "room:disconnect": (key: string) => void;
9
+ "room:info": (key: string, info: RoomInfo) => void;
10
+ "room:detail": (key: string, info: RoomDetail) => void;
11
+ "room:status": (key: string, info: {
12
+ status: RoomStatus;
13
+ id?: string;
14
+ timestamp?: number;
15
+ }) => void;
16
+ "room:stats": (key: string, info: RoomStatsInfo) => void;
17
+ "room:open": (key: string, info: RoomInfo) => void;
18
+ "room:close": (key: string, info: RoomInfo) => void;
19
+ "room:add": (key: string, info: RoomInfo) => void;
20
+ "room:remove": (key: string, info: RoomInfo) => void;
21
+ "plugin:add": (name: string) => void;
22
+ "plugin:remove": (name: string) => void;
23
+ "command:add": (name: string) => void;
24
+ "command:remove": (name: string) => void;
25
+ error: (err: Error) => void;
26
+ }
@@ -1,4 +1,3 @@
1
1
  export * from "./message";
2
2
  export * from "./plugin";
3
3
  export * from "./room";
4
- export * from "./auth";
@@ -17,4 +17,3 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./message"), exports);
18
18
  __exportStar(require("./plugin"), exports);
19
19
  __exportStar(require("./room"), exports);
20
- __exportStar(require("./auth"), exports);
@@ -1,8 +1,15 @@
1
1
  import { FloatingLive } from "../live";
2
2
  /** 插件模块, 加载时调用 */
3
- export declare type FloatingLivePlugin<C extends object = object, E extends object | void = object | void> = () => {
3
+ export declare type FloatingLivePlugin<C extends object = object> = () => {
4
4
  /** 插件名称 */
5
5
  name: string;
6
- register: (ctx: FloatingLive, config?: C) => E;
6
+ register: (ctx: FloatingLive, config?: C) => void;
7
7
  destroy?: (ctx: FloatingLive) => void;
8
8
  };
9
+ export interface IPlugin {
10
+ destroy: () => void;
11
+ }
12
+ export interface PluginConstructor {
13
+ pluginName: string;
14
+ new (ctx: FloatingLive, config: any): IPlugin;
15
+ }
@@ -1,5 +1,15 @@
1
1
  import { RoomStatus } from "../enums";
2
2
  import { UserInfo } from "./message";
3
+ /** 房间配置 */
4
+ export interface RoomConfig {
5
+ /** 添加后是否打开房间 */
6
+ open?: boolean;
7
+ /** 口令 */
8
+ tokens?: Record<string, number>;
9
+ /** 凭据 */
10
+ credentials?: string;
11
+ }
12
+ /** 房间信息 */
3
13
  export interface RoomInfo {
4
14
  /** 平台id */
5
15
  platform: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floating-live",
3
- "version": "0.15.0-beta.0",
3
+ "version": "0.15.0-beta.2",
4
4
  "type": "commonjs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,8 +20,12 @@
20
20
  "require": "./dist/types/index.js"
21
21
  },
22
22
  "./enums": {
23
- "types": "./dist/enum.d.ts",
24
- "require": "./dist/enum.js"
23
+ "types": "./dist/enums.d.ts",
24
+ "require": "./dist/enums.js"
25
+ },
26
+ "./utils": {
27
+ "types": "./dist/utils.d.ts",
28
+ "require": "./dist/utils.js"
25
29
  }
26
30
  },
27
31
  "scripts": {
@@ -32,18 +36,7 @@
32
36
  "build": "npm run clear && npm run tsc",
33
37
  "prepare": "npm run build"
34
38
  },
35
- "dependencies": {
36
- "@types/qrcode": "^1.5.2",
37
- "acfun-live-danmaku": "^0.6.1",
38
- "axios": "^1.4.0",
39
- "bilibili-live-ws": "^6.3.1",
40
- "fs-extra": "^11.1.0",
41
- "qrcode": "^1.5.3"
42
- },
43
39
  "devDependencies": {
44
- "@types/fs-extra": "^9.0.13",
45
- "@types/websocket": "^1.0.5",
46
- "@types/ws": "^8.5.3",
47
40
  "rimraf": "^3.0.2",
48
41
  "ts-node": "^10.9.1",
49
42
  "typescript": "^4.8.4"
@@ -51,4 +44,4 @@
51
44
  "peerDependencies": {
52
45
  "events": "^3.3.0"
53
46
  }
54
- }
47
+ }
@@ -1,29 +0,0 @@
1
- import { FloatingLive } from "../live";
2
- /** 插件可注册对象模块 */
3
- export declare class Reglist<T> {
4
- /** 功能列表 */
5
- private readonly list;
6
- /** 插件与功能名称绑定表 */
7
- private readonly pluginIdMap;
8
- private readonly name;
9
- protected readonly main: FloatingLive;
10
- constructor(main: FloatingLive, name: string);
11
- /** 注册一个对象 */
12
- register(id: string, item: T): void;
13
- /** 取消某一插件在该模块中的注册 */
14
- unregister(pluginName: string): void;
15
- /** 获取名称 */
16
- getName(): string;
17
- /** 根据id获取注册对象 */
18
- get(id: string): T | undefined;
19
- /** 检查注册对象是否存在 */
20
- has(id: string): boolean;
21
- /** 获取注册对象列表 */
22
- getList(): T[];
23
- /** 遍历 */
24
- forEach(callbackfn: (value: T, key: string) => void): void;
25
- /** 获取注册id列表 */
26
- getIdList(): string[];
27
- /** 获取注册id列表 */
28
- getIdByPlugin(name: string): string[];
29
- }
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Reglist = void 0;
4
- /** 插件可注册对象模块 */
5
- class Reglist {
6
- constructor(main, name) {
7
- this.main = main;
8
- this.name = name;
9
- this.list = new Map();
10
- this.pluginIdMap = new Map();
11
- }
12
- /** 注册一个对象 */
13
- register(id, item) {
14
- // 如果组件缺少id, 或者id与已安装插件重复, 则报错
15
- if (!id)
16
- throw new TypeError("id is required!");
17
- if (this.list.has(id))
18
- throw new TypeError(`${this.name} duplicate id: ${id}!`);
19
- // 将组件添加至列表中
20
- this.list.set(id, item);
21
- // 将插件名称与注册id关联
22
- if (this.main.plugin.currentPlugin) {
23
- if (this.pluginIdMap.has(this.main.plugin.currentPlugin)) {
24
- this.pluginIdMap.get(this.main.plugin.currentPlugin)?.push(id);
25
- }
26
- else {
27
- this.pluginIdMap.set(this.main.plugin.currentPlugin, [id]);
28
- }
29
- }
30
- }
31
- /** 取消某一插件在该模块中的注册 */
32
- unregister(pluginName) {
33
- if (this.pluginIdMap.has(pluginName)) {
34
- const handlerList = this.pluginIdMap.get(pluginName);
35
- handlerList?.forEach((plugin) => {
36
- this.list.delete(plugin);
37
- });
38
- }
39
- }
40
- /** 获取名称 */
41
- getName() {
42
- return this.name;
43
- }
44
- /** 根据id获取注册对象 */
45
- get(id) {
46
- return this.list.get(id);
47
- }
48
- /** 检查注册对象是否存在 */
49
- has(id) {
50
- return this.list.has(id);
51
- }
52
- /** 获取注册对象列表 */
53
- getList() {
54
- return [...this.list.values()];
55
- }
56
- /** 遍历 */
57
- forEach(callbackfn) {
58
- this.list.forEach(callbackfn);
59
- }
60
- /** 获取注册id列表 */
61
- getIdList() {
62
- return [...this.list.keys()];
63
- }
64
- /** 获取注册id列表 */
65
- getIdByPlugin(name) {
66
- return [...(this.pluginIdMap.get(name) || [])];
67
- }
68
- }
69
- exports.Reglist = Reglist;
@@ -1,10 +0,0 @@
1
- import { Reglist } from "../core/Reglist";
2
- import { FloatingLive } from "../live";
3
- import { AuthOptions } from "../types/auth";
4
- export declare class ModAuth {
5
- options: Reglist<AuthOptions>;
6
- status: Record<string, string | number>;
7
- main: FloatingLive;
8
- constructor(main: FloatingLive);
9
- set(name: string, auth: string): void;
10
- }
@@ -1,35 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ModAuth = void 0;
4
- const Reglist_1 = require("../core/Reglist");
5
- class ModAuth {
6
- constructor(main) {
7
- this.status = {};
8
- this.options = new Reglist_1.Reglist(main, "auth.options");
9
- this.main = main;
10
- this.main.state.register("auth", () => {
11
- const options = {};
12
- this.options.forEach((val, key) => {
13
- options[key] = val;
14
- });
15
- return {
16
- options: options,
17
- status: this.status,
18
- };
19
- });
20
- this.main.command.batchRegister({
21
- auth: (platform, auth) => {
22
- if (this.main.command.has(`auth.${platform}`)) {
23
- this.main.command.execute(`auth.${platform}`, auth);
24
- }
25
- else {
26
- this.set(platform, auth);
27
- }
28
- },
29
- });
30
- }
31
- set(name, auth) {
32
- this.main.room.setAuth(name, auth);
33
- }
34
- }
35
- exports.ModAuth = ModAuth;
@@ -1,9 +0,0 @@
1
- import { FloatingLive } from "../live";
2
- import { Reglist } from "../core/Reglist";
3
- export default class ModCommand extends Reglist<(...args: any[]) => any> {
4
- constructor(main: FloatingLive);
5
- /** 批量注册命令 */
6
- batchRegister(list: Record<string, (...args: any) => any>): void;
7
- /** 执行命令 */
8
- execute(name: string, ...args: any[]): any;
9
- }
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const Reglist_1 = require("../core/Reglist");
4
- class ModCommand extends Reglist_1.Reglist {
5
- constructor(main) {
6
- super(main, "command");
7
- }
8
- /** 批量注册命令 */
9
- batchRegister(list) {
10
- for (const key in list) {
11
- this.register(key, list[key]);
12
- }
13
- }
14
- /** 执行命令 */
15
- execute(name, ...args) {
16
- return this.get(name)?.(...args);
17
- }
18
- }
19
- exports.default = ModCommand;
@@ -1,9 +0,0 @@
1
- import { Message } from "../types/message";
2
- import { FloatingLive } from "../live";
3
- import { Reglist } from "../core/Reglist";
4
- export declare class ModMessage {
5
- main: FloatingLive;
6
- handler: Reglist<(msg: Message.All) => void>;
7
- constructor(main: FloatingLive);
8
- handle(msg: Message.All): void;
9
- }
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ModMessage = void 0;
4
- const Reglist_1 = require("../core/Reglist");
5
- class ModMessage {
6
- constructor(main) {
7
- this.main = main;
8
- this.handler = new Reglist_1.Reglist(main, "message.handler");
9
- }
10
- handle(msg) {
11
- this.handler.getList().forEach((handler) => {
12
- handler(msg);
13
- });
14
- }
15
- }
16
- exports.ModMessage = ModMessage;
@@ -1,20 +0,0 @@
1
- import { FloatingLive } from "../live";
2
- import { FloatingLivePlugin } from "../types/plugin";
3
- export declare class ModPlugin<T extends FloatingLive> {
4
- private current;
5
- /** 插件列表 */
6
- private list;
7
- private pluginEvent;
8
- private main;
9
- private exports;
10
- constructor(main: T);
11
- /** 获取当前安装插件 */
12
- get currentPlugin(): string | null;
13
- addPluginEvent(eventName: string, listener: (...args: any[]) => void): void;
14
- /** 访问插件操作对象 */
15
- access(name: string): object | undefined;
16
- /** 注册插件 */
17
- register<C extends object, E extends void | object>(pluginFunc: FloatingLivePlugin<C, E>, pluginConfig?: C): {} | undefined;
18
- /** 移除插件 */
19
- unregister(name: string): void;
20
- }
@@ -1,164 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ModRoom = void 0;
4
- const Reglist_1 = require("../core/Reglist");
5
- /** 直播间监听实例控制器 */
6
- class ModRoom {
7
- constructor(main) {
8
- this.roomMap = new Map();
9
- this.auths = new Map();
10
- this.configs = new Map();
11
- this.main = main;
12
- this.generator = new Reglist_1.Reglist(this.main, "room.generator");
13
- this.main.state.register("room", () => {
14
- const list = [];
15
- this.roomMap.forEach((room) => {
16
- list.push(room.info);
17
- });
18
- return { list };
19
- });
20
- this.main.command.batchRegister({
21
- add: (platform, id, open) => {
22
- this.add(platform, id, open);
23
- },
24
- remove: (key) => {
25
- this.remove(key);
26
- },
27
- open: (key) => {
28
- this.open(key);
29
- },
30
- close: (key) => {
31
- this.close(key);
32
- },
33
- update: (key) => {
34
- this.update(key);
35
- },
36
- });
37
- }
38
- /** 设置登录凭据 */
39
- setAuth(platform, auth) {
40
- this.auths.set(platform, auth);
41
- this.roomMap.forEach((room) => {
42
- if (room.platform == platform) {
43
- room.setAuth?.(auth);
44
- }
45
- });
46
- }
47
- /** 设置房间配置 */
48
- setConfig(platform, config) {
49
- this.configs.set(platform, config);
50
- }
51
- /** 生成房间 */
52
- generate(platform, id, open) {
53
- platform = platform.toLowerCase();
54
- const config = this.configs.get(platform) || {};
55
- const auth = this.auths.get(platform);
56
- let platformGenerator = this.generator.get(platform);
57
- if (platformGenerator) {
58
- return platformGenerator(id, open, { auth, ...config });
59
- }
60
- else {
61
- this.main.emit("room:unknown_platform", platform);
62
- }
63
- }
64
- /** 添加房间监听实例 */
65
- addRoom(room, open) {
66
- let key = room.key;
67
- if (this.roomMap.has(key)) {
68
- this.main.emit("room:exist", key);
69
- return;
70
- }
71
- this.roomMap.set(key, room);
72
- // 添加监听事件
73
- // 直播消息
74
- room.on("msg", (data) => {
75
- this.main.message.handle(data);
76
- this.main.emit("live:message", data);
77
- });
78
- // 直播消息源数据
79
- room.on("raw", (data, { platform, room }) => {
80
- this.main.emit("live:raw", data, { platform, room });
81
- });
82
- // 连接到直播间
83
- room.on("connect", () => {
84
- this.main.emit("room:connect", key);
85
- });
86
- // 与直播间的连接已断开
87
- room.on("disconnect", () => {
88
- this.main.emit("room:disconnect", key);
89
- });
90
- // 获取房间信息
91
- room.on("info", () => {
92
- this.main.emit("room:info", key, room.info);
93
- });
94
- // 直播展示信息更改
95
- room.on("detail", (data) => {
96
- this.main.emit("room:detail", key, data);
97
- });
98
- // 直播状态更改
99
- room.on("status", (status, { id, timestamp }) => {
100
- this.main.emit("room:status", key, status, { id, timestamp });
101
- });
102
- // 统计数据更新
103
- room.on("stats", (data) => {
104
- this.main.emit("room:stats", key, data);
105
- });
106
- // 房间被打开
107
- room.on("open", () => {
108
- this.main.emit("room:open", key, room.info);
109
- });
110
- // 房间被关闭
111
- room.on("close", () => {
112
- this.main.emit("room:close", key, room.info);
113
- });
114
- if (open) {
115
- room.open();
116
- }
117
- this.main.emit("room:add", key, room.info);
118
- }
119
- /** 添加房间 */
120
- add(platform, id, open) {
121
- const room = this.generate(platform, id, open);
122
- room && this.addRoom(room);
123
- }
124
- /** 移除房间 */
125
- remove(roomKey) {
126
- if (!this.roomMap.has(roomKey)) {
127
- this.main.emit("room:unexist", roomKey);
128
- return;
129
- }
130
- let room = this.roomMap.get(roomKey);
131
- this.roomMap.delete(roomKey); // 从表中删除房间
132
- room?.removeAllListeners(); // 移除房间监听实例
133
- this.main.emit("room:remove", roomKey);
134
- }
135
- /** 获取房间 */
136
- get(roomKey) {
137
- return this.roomMap.get(roomKey);
138
- }
139
- /** 获取房间信息 */
140
- info(roomKey) {
141
- let room = this.roomMap.get(roomKey);
142
- return room ? room.info : undefined;
143
- }
144
- /** 更新房间信息 */
145
- update(roomKey) {
146
- let room = this.roomMap.get(roomKey);
147
- room && room.getInfo();
148
- }
149
- /** 获取roomKey列表 */
150
- get keys() {
151
- return [...this.roomMap.keys()];
152
- }
153
- /** 打开房间连接 */
154
- open(roomKey) {
155
- let room = this.roomMap.get(roomKey);
156
- room?.available && !room.opened && room.open();
157
- }
158
- /** 关闭房间连接 */
159
- close(roomKey) {
160
- let room = this.roomMap.get(roomKey);
161
- room?.opened && room.close();
162
- }
163
- }
164
- exports.ModRoom = ModRoom;
@@ -1,12 +0,0 @@
1
- import { FloatingLive } from "../live";
2
- import { Reglist } from "../core/Reglist";
3
- export declare class ModState extends Reglist<() => object> {
4
- constructor(main: FloatingLive);
5
- generate(): Record<string, any>;
6
- /** 设置一个值 */
7
- set(name: string, value: any): void;
8
- /** 在数组中添加一个值 */
9
- arrayPush(name: string, value: any): void;
10
- /** 在数组中移除一个值 */
11
- arrayRemove(name: string, key: string, val: string): void;
12
- }
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ModState = void 0;
4
- const Reglist_1 = require("../core/Reglist");
5
- class ModState extends Reglist_1.Reglist {
6
- constructor(main) {
7
- super(main, "state");
8
- }
9
- generate() {
10
- const state = {};
11
- this.forEach((gen, key) => {
12
- state[key] = gen();
13
- });
14
- return state;
15
- }
16
- /** 设置一个值 */
17
- set(name, value) {
18
- this.main.emit("state:set", name, value);
19
- }
20
- /** 在数组中添加一个值 */
21
- arrayPush(name, value) {
22
- this.main.emit("state:array_push", name, value);
23
- }
24
- /** 在数组中移除一个值 */
25
- arrayRemove(name, key, val) {
26
- this.main.emit("state:array_remove", name, key, val);
27
- }
28
- }
29
- exports.ModState = ModState;
@@ -1,19 +0,0 @@
1
- export interface AuthOptions {
2
- /** 直接输入凭证 */
3
- auth: {
4
- /** 凭证类型 */
5
- type: string;
6
- };
7
- /** 二维码登录 */
8
- qrcode?: {
9
- /** 二维码类型 */
10
- type: "url" | "base64";
11
- };
12
- /** 验证码登录 */
13
- verify?: {
14
- /** 验证码发送等待间隔(秒) */
15
- wait: number;
16
- /** 第三方验证接口 */
17
- captcha?: string;
18
- };
19
- }
File without changes