@vex-chat/types 0.10.18 → 0.11.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.
@@ -0,0 +1,8 @@
1
+ # Changesets
2
+
3
+ Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
+ with multi-package repos, or single-package repos to help you version and publish your code. You can
5
+ find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
+
7
+ We have a quick list of common questions to get you started engaging with this project in
8
+ [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
3
+ "changelog": "@changesets/cli/changelog",
4
+ "commit": false,
5
+ "fixed": [],
6
+ "linked": [],
7
+ "access": "public",
8
+ "baseBranch": "master",
9
+ "updateInternalDependencies": "patch",
10
+ "ignore": []
11
+ }
@@ -0,0 +1 @@
1
+ yarn prettier && git add --all && npx lint-staged
package/RELEASING.md ADDED
@@ -0,0 +1,85 @@
1
+ # Releasing @vex-chat/types
2
+
3
+ This repo uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing.
4
+
5
+ ## Dependency Chain
6
+
7
+ ```
8
+ @vex-chat/types ← you are here
9
+ └─ @vex-chat/crypto ← depends on types
10
+ └─ @vex-chat/libvex ← depends on crypto + types
11
+ └─ vex-desktop ← depends on libvex + crypto
12
+ ```
13
+
14
+ **types must be published first** when making cross-repo changes.
15
+
16
+ ## Day-to-Day Workflow
17
+
18
+ ### 1. Work on a feature branch
19
+
20
+ ```bash
21
+ git checkout -b my-feature
22
+ # ... make changes ...
23
+ ```
24
+
25
+ ### 2. Add a changeset before pushing
26
+
27
+ ```bash
28
+ npx changeset
29
+ ```
30
+
31
+ This prompts you to:
32
+
33
+ - Select the package (`@vex-chat/types`)
34
+ - Choose bump type (patch / minor / major)
35
+ - Write a short summary of the change
36
+
37
+ It creates a file in `.changeset/` — commit it with your code.
38
+
39
+ ### 3. Push and open a PR
40
+
41
+ ```bash
42
+ git add .
43
+ git commit -m "my feature"
44
+ git push -u origin my-feature
45
+ ```
46
+
47
+ ### 4. Merge to master
48
+
49
+ After merge, the **Release** GitHub Action will:
50
+
51
+ 1. Detect pending changesets
52
+ 2. Open a **"chore: version packages"** PR with bumped version + updated CHANGELOG.md
53
+ 3. When you merge that PR, it publishes to npm automatically
54
+
55
+ ## Release Candidates
56
+
57
+ ```bash
58
+ npx changeset pre enter rc # enter RC mode
59
+ npx changeset version # produces e.g. 0.12.0-rc.0
60
+ npx changeset publish # publishes with --tag rc
61
+
62
+ # ... more changes + changesets ...
63
+ npx changeset version # produces 0.12.0-rc.1
64
+ npx changeset publish
65
+
66
+ # ready for stable:
67
+ npx changeset pre exit
68
+ npx changeset version # produces 0.12.0
69
+ npx changeset publish # publishes as @latest
70
+ ```
71
+
72
+ ## GitHub Secrets Required
73
+
74
+ - `NPM_TOKEN` — npm access token with publish permission for `@vex-chat` scope
75
+ - `GITHUB_TOKEN` — provided automatically by GitHub Actions
76
+
77
+ ## Local Development
78
+
79
+ You can still use `yalc` for local cross-repo development:
80
+
81
+ ```bash
82
+ yarn push # builds and pushes to yalc for local consumers
83
+ ```
84
+
85
+ When publishing for real, changesets handles versioning — yalc is just for local dev loops.
package/dist/index.d.ts CHANGED
@@ -1,229 +1,211 @@
1
- /// <reference types="node" />
2
1
  import nacl from "tweetnacl";
3
- export declare namespace XTypes {
4
- namespace CRYPTO {
5
- interface IXKeyRing {
6
- identityKeys: nacl.BoxKeyPair;
7
- ephemeralKeys: nacl.BoxKeyPair;
8
- preKeys: IPreKeys;
9
- }
10
- interface IPreKeys {
11
- keyPair: nacl.BoxKeyPair;
12
- signature: Uint8Array;
13
- index?: number;
14
- }
15
- interface ISession {
16
- sessionID: string;
17
- userID: string;
18
- mode: "initiator" | "receiver";
19
- SK: Uint8Array;
20
- publicKey: Uint8Array;
21
- fingerprint: Uint8Array;
22
- lastUsed: Date;
23
- }
24
- }
25
- namespace HTTP {
26
- interface IFilePayload {
27
- owner: string;
28
- signed: string;
29
- nonce: string;
30
- file?: string;
31
- }
32
- interface IFileResponse {
33
- details: XTypes.SQL.IFile;
34
- data: Buffer;
35
- }
36
- enum TokenScopes {
37
- Register = 0,
38
- File = 1,
39
- Avatar = 2,
40
- Device = 3,
41
- Invite = 4,
42
- Emoji = 5,
43
- Connect = 6
44
- }
45
- interface IActionToken {
46
- key: string;
47
- time: Date;
48
- scope: TokenScopes;
49
- }
50
- interface IDevicePayload {
51
- username: string;
52
- signKey: string;
53
- preKey: string;
54
- preKeySignature: string;
55
- preKeyIndex: number;
56
- signed: string;
57
- deviceName: string;
58
- }
59
- interface IRegistrationPayload extends IDevicePayload {
60
- username: string;
61
- signKey: string;
62
- preKey: string;
63
- preKeySignature: string;
64
- preKeyIndex: number;
65
- signed: string;
66
- deviceName: string;
67
- password: string;
68
- }
69
- }
70
- namespace WS {
71
- interface IBaseMsg {
72
- transmissionID: string;
73
- type: string;
74
- }
75
- interface ISucessMsg extends IBaseMsg {
76
- data: any;
77
- timestamp?: string;
78
- }
79
- interface IErrMsg extends IBaseMsg {
80
- error: string;
81
- data?: any;
82
- }
83
- interface IChallMsg extends IBaseMsg {
84
- type: "challenge";
85
- challenge: Uint8Array;
86
- }
87
- interface IRespMsg extends IBaseMsg {
88
- type: "response";
89
- signed: Uint8Array;
90
- }
91
- interface IReceiptMsg extends IBaseMsg {
92
- nonce: Uint8Array;
93
- }
94
- interface IResourceMsg extends IBaseMsg {
95
- resourceType: string;
96
- action: string;
97
- data?: any;
98
- }
99
- interface INotifyMsg extends IBaseMsg {
100
- event: string;
101
- data?: any;
102
- }
103
- interface IKeyBundle {
104
- signKey: Uint8Array;
105
- preKey: IPreKeys;
106
- otk?: IPreKeys;
107
- }
108
- interface IPreKeys {
109
- deviceID: string;
110
- publicKey: Uint8Array;
111
- signature: Uint8Array;
112
- index: number;
113
- }
114
- interface IMail {
115
- mailID: string;
116
- mailType: MailType;
117
- sender: string;
118
- recipient: string;
119
- cipher: Uint8Array;
120
- nonce: Uint8Array;
121
- extra: Uint8Array;
122
- group: Uint8Array | null;
123
- forward: boolean;
124
- authorID: string;
125
- readerID: string;
126
- }
127
- enum MailType {
128
- initial = 0,
129
- subsequent = 1
130
- }
131
- enum SocketAuthErrors {
132
- BadSignature = 0,
133
- InvalidToken = 1,
134
- UserNotRegistered = 2
135
- }
136
- }
137
- namespace SQL {
138
- interface IUser {
139
- userID: string;
140
- username: string;
141
- lastSeen: Date;
142
- passwordHash: string;
143
- passwordSalt: string;
144
- }
145
- interface IDevice {
146
- deviceID: string;
147
- owner: string;
148
- signKey: string;
149
- name: string;
150
- lastLogin: string;
151
- deleted: boolean;
152
- }
153
- interface IInvite {
154
- inviteID: string;
155
- serverID: string;
156
- owner: string;
157
- expiration: string;
158
- }
159
- interface IMail {
160
- mailID: string;
161
- mailType: WS.MailType;
162
- header: string;
163
- recipient: string;
164
- sender: string;
165
- cipher: string;
166
- nonce: string;
167
- extra: string;
168
- time: Date;
169
- group: string | null;
170
- forward: boolean;
171
- authorID: string;
172
- readerID: string;
173
- }
174
- interface IEmoji {
175
- emojiID: string;
176
- owner: string;
177
- name: string;
178
- }
179
- interface IFile {
180
- fileID: string;
181
- owner: string;
182
- nonce: string;
183
- }
184
- interface IServer {
185
- serverID: string;
186
- name: string;
187
- icon?: string;
188
- }
189
- interface IChannel {
190
- channelID: string;
191
- serverID: string;
192
- name: string;
193
- }
194
- interface IPermission {
195
- permissionID: string;
196
- userID: string;
197
- resourceID: string;
198
- resourceType: string;
199
- powerLevel: number;
200
- }
201
- interface IIdentityKeys {
202
- keyID: string;
203
- userID: string;
204
- deviceID: string;
205
- privateKey?: string;
206
- publicKey: string;
207
- }
208
- interface IPreKeys {
209
- keyID: string;
210
- userID: string;
211
- deviceID: string;
212
- index: number;
213
- privateKey?: string;
214
- publicKey: string;
215
- signature: string;
216
- }
217
- interface ISession {
218
- sessionID: string;
219
- userID: string;
220
- deviceID: string;
221
- mode: "initiator" | "receiver";
222
- SK: string;
223
- publicKey: string;
224
- fingerprint: string;
225
- lastUsed: Date;
226
- verified: boolean;
227
- }
228
- }
2
+ export interface IXKeyRing {
3
+ identityKeys: nacl.BoxKeyPair;
4
+ ephemeralKeys: nacl.BoxKeyPair;
5
+ preKeys: IPreKeysCrypto;
6
+ }
7
+ export interface IPreKeysCrypto {
8
+ keyPair: nacl.BoxKeyPair;
9
+ signature: Uint8Array;
10
+ index?: number;
11
+ }
12
+ export interface ISessionCrypto {
13
+ sessionID: string;
14
+ userID: string;
15
+ mode: "initiator" | "receiver";
16
+ SK: Uint8Array;
17
+ publicKey: Uint8Array;
18
+ fingerprint: Uint8Array;
19
+ lastUsed: Date;
20
+ }
21
+ export declare enum TokenScopes {
22
+ Register = 0,
23
+ File = 1,
24
+ Avatar = 2,
25
+ Device = 3,
26
+ Invite = 4,
27
+ Emoji = 5,
28
+ Connect = 6
29
+ }
30
+ export interface IActionToken {
31
+ key: string;
32
+ time: Date;
33
+ scope: TokenScopes;
34
+ }
35
+ export interface IFilePayload {
36
+ owner: string;
37
+ signed: string;
38
+ nonce: string;
39
+ file?: string;
40
+ }
41
+ export interface IFileResponse {
42
+ details: IFileSQL;
43
+ data: Buffer;
44
+ }
45
+ export interface IDevicePayload {
46
+ username: string;
47
+ signKey: string;
48
+ preKey: string;
49
+ preKeySignature: string;
50
+ preKeyIndex: number;
51
+ signed: string;
52
+ deviceName: string;
53
+ }
54
+ export interface IRegistrationPayload extends IDevicePayload {
55
+ password: string;
56
+ }
57
+ export declare enum SocketAuthErrors {
58
+ BadSignature = 0,
59
+ InvalidToken = 1,
60
+ UserNotRegistered = 2
61
+ }
62
+ export declare enum MailType {
63
+ initial = 0,
64
+ subsequent = 1
65
+ }
66
+ export interface IBaseMsg {
67
+ transmissionID: string;
68
+ type: string;
69
+ }
70
+ export interface ISucessMsg extends IBaseMsg {
71
+ data: any;
72
+ timestamp?: string;
73
+ }
74
+ export interface IErrMsg extends IBaseMsg {
75
+ error: string;
76
+ data?: any;
77
+ }
78
+ export interface IChallMsg extends IBaseMsg {
79
+ type: "challenge";
80
+ challenge: Uint8Array;
81
+ }
82
+ export interface IRespMsg extends IBaseMsg {
83
+ type: "response";
84
+ signed: Uint8Array;
85
+ }
86
+ export interface IReceiptMsg extends IBaseMsg {
87
+ nonce: Uint8Array;
88
+ }
89
+ export interface IResourceMsg extends IBaseMsg {
90
+ resourceType: string;
91
+ action: string;
92
+ data?: any;
93
+ }
94
+ export interface INotifyMsg extends IBaseMsg {
95
+ event: string;
96
+ data?: any;
97
+ }
98
+ export interface IKeyBundle {
99
+ signKey: Uint8Array;
100
+ preKey: IPreKeysWS;
101
+ otk?: IPreKeysWS;
102
+ }
103
+ export interface IPreKeysWS {
104
+ deviceID: string;
105
+ publicKey: Uint8Array;
106
+ signature: Uint8Array;
107
+ index: number;
108
+ }
109
+ export interface IMailWS {
110
+ mailID: string;
111
+ mailType: MailType;
112
+ sender: string;
113
+ recipient: string;
114
+ cipher: Uint8Array;
115
+ nonce: Uint8Array;
116
+ extra: Uint8Array;
117
+ group: Uint8Array | null;
118
+ forward: boolean;
119
+ authorID: string;
120
+ readerID: string;
121
+ }
122
+ export interface IUser {
123
+ userID: string;
124
+ username: string;
125
+ lastSeen: Date;
126
+ passwordHash: string;
127
+ passwordSalt: string;
128
+ }
129
+ export interface IDevice {
130
+ deviceID: string;
131
+ owner: string;
132
+ signKey: string;
133
+ name: string;
134
+ lastLogin: string;
135
+ deleted: boolean;
136
+ }
137
+ export interface IInvite {
138
+ inviteID: string;
139
+ serverID: string;
140
+ owner: string;
141
+ expiration: string;
142
+ }
143
+ export interface IMailSQL {
144
+ mailID: string;
145
+ mailType: MailType;
146
+ header: string;
147
+ recipient: string;
148
+ sender: string;
149
+ cipher: string;
150
+ nonce: string;
151
+ extra: string;
152
+ time: Date;
153
+ group: string | null;
154
+ forward: boolean;
155
+ authorID: string;
156
+ readerID: string;
157
+ }
158
+ export interface IEmoji {
159
+ emojiID: string;
160
+ owner: string;
161
+ name: string;
162
+ }
163
+ export interface IFileSQL {
164
+ fileID: string;
165
+ owner: string;
166
+ nonce: string;
167
+ }
168
+ export interface IServer {
169
+ serverID: string;
170
+ name: string;
171
+ icon?: string;
172
+ }
173
+ export interface IChannel {
174
+ channelID: string;
175
+ serverID: string;
176
+ name: string;
177
+ }
178
+ export interface IPermission {
179
+ permissionID: string;
180
+ userID: string;
181
+ resourceID: string;
182
+ resourceType: string;
183
+ powerLevel: number;
184
+ }
185
+ export interface IIdentityKeys {
186
+ keyID: string;
187
+ userID: string;
188
+ deviceID: string;
189
+ privateKey?: string;
190
+ publicKey: string;
191
+ }
192
+ export interface IPreKeysSQL {
193
+ keyID: string;
194
+ userID: string;
195
+ deviceID: string;
196
+ index: number;
197
+ privateKey?: string;
198
+ publicKey: string;
199
+ signature: string;
200
+ }
201
+ export interface ISessionSQL {
202
+ sessionID: string;
203
+ userID: string;
204
+ deviceID: string;
205
+ mode: "initiator" | "receiver";
206
+ SK: string;
207
+ publicKey: string;
208
+ fingerprint: string;
209
+ lastUsed: Date;
210
+ verified: boolean;
229
211
  }
package/dist/index.js CHANGED
@@ -1,37 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.XTypes = void 0;
4
- // HTTP api
5
- // tslint:disable-next-line: no-namespace
6
- var XTypes;
7
- (function (XTypes) {
8
- // types for the HTTP API
9
- let HTTP;
10
- (function (HTTP) {
11
- let TokenScopes;
12
- (function (TokenScopes) {
13
- TokenScopes[TokenScopes["Register"] = 0] = "Register";
14
- TokenScopes[TokenScopes["File"] = 1] = "File";
15
- TokenScopes[TokenScopes["Avatar"] = 2] = "Avatar";
16
- TokenScopes[TokenScopes["Device"] = 3] = "Device";
17
- TokenScopes[TokenScopes["Invite"] = 4] = "Invite";
18
- TokenScopes[TokenScopes["Emoji"] = 5] = "Emoji";
19
- TokenScopes[TokenScopes["Connect"] = 6] = "Connect";
20
- })(TokenScopes = HTTP.TokenScopes || (HTTP.TokenScopes = {}));
21
- })(HTTP = XTypes.HTTP || (XTypes.HTTP = {}));
22
- // WS messages
23
- let WS;
24
- (function (WS) {
25
- let MailType;
26
- (function (MailType) {
27
- MailType[MailType["initial"] = 0] = "initial";
28
- MailType[MailType["subsequent"] = 1] = "subsequent";
29
- })(MailType = WS.MailType || (WS.MailType = {}));
30
- let SocketAuthErrors;
31
- (function (SocketAuthErrors) {
32
- SocketAuthErrors[SocketAuthErrors["BadSignature"] = 0] = "BadSignature";
33
- SocketAuthErrors[SocketAuthErrors["InvalidToken"] = 1] = "InvalidToken";
34
- SocketAuthErrors[SocketAuthErrors["UserNotRegistered"] = 2] = "UserNotRegistered";
35
- })(SocketAuthErrors = WS.SocketAuthErrors || (WS.SocketAuthErrors = {}));
36
- })(WS = XTypes.WS || (XTypes.WS = {}));
37
- })(XTypes = exports.XTypes || (exports.XTypes = {}));
3
+ exports.MailType = exports.SocketAuthErrors = exports.TokenScopes = void 0;
4
+ // ==========================================
5
+ // HTTP API TYPES
6
+ // ==========================================
7
+ var TokenScopes;
8
+ (function (TokenScopes) {
9
+ TokenScopes[TokenScopes["Register"] = 0] = "Register";
10
+ TokenScopes[TokenScopes["File"] = 1] = "File";
11
+ TokenScopes[TokenScopes["Avatar"] = 2] = "Avatar";
12
+ TokenScopes[TokenScopes["Device"] = 3] = "Device";
13
+ TokenScopes[TokenScopes["Invite"] = 4] = "Invite";
14
+ TokenScopes[TokenScopes["Emoji"] = 5] = "Emoji";
15
+ TokenScopes[TokenScopes["Connect"] = 6] = "Connect";
16
+ })(TokenScopes || (exports.TokenScopes = TokenScopes = {}));
17
+ // ==========================================
18
+ // WEBSOCKET TYPES (Network Layer)
19
+ // ==========================================
20
+ var SocketAuthErrors;
21
+ (function (SocketAuthErrors) {
22
+ SocketAuthErrors[SocketAuthErrors["BadSignature"] = 0] = "BadSignature";
23
+ SocketAuthErrors[SocketAuthErrors["InvalidToken"] = 1] = "InvalidToken";
24
+ SocketAuthErrors[SocketAuthErrors["UserNotRegistered"] = 2] = "UserNotRegistered";
25
+ })(SocketAuthErrors || (exports.SocketAuthErrors = SocketAuthErrors = {}));
26
+ var MailType;
27
+ (function (MailType) {
28
+ MailType[MailType["initial"] = 0] = "initial";
29
+ MailType[MailType["subsequent"] = 1] = "subsequent";
30
+ })(MailType || (exports.MailType = MailType = {}));
@@ -0,0 +1,14 @@
1
+ const ts = require("@typescript-eslint/eslint-plugin");
2
+ const parser = require("@typescript-eslint/parser");
3
+
4
+ module.exports = [
5
+ {
6
+ files: ["**/*.ts"],
7
+ languageOptions: { parser },
8
+ plugins: { "@typescript-eslint": ts },
9
+ rules: {
10
+ "@typescript-eslint/interface-name-prefix": "off",
11
+ "@typescript-eslint/no-explicit-any": "off"
12
+ }
13
+ }
14
+ ];
package/mise.toml ADDED
@@ -0,0 +1,3 @@
1
+ [tools]
2
+ node = "20"
3
+ "npm:yarn" = "latest"
package/package.json CHANGED
@@ -1,47 +1,48 @@
1
1
  {
2
- "name": "@vex-chat/types",
3
- "version": "0.10.18",
4
- "description": "Types for vex",
5
- "main": "./dist/index.js",
6
- "author": "Extra <extrahash@protonmail.com>",
7
- "license": "AGPL-3.0-or-later",
8
- "scripts": {
9
- "start": "node ./dist/index.js",
10
- "build": "rm -rf ./dist/*; node ./node_modules/typescript/bin/tsc",
11
- "prepack": "yarn build",
12
- "prettier": "node ./node_modules/prettier/bin-prettier.js '**/*.{ts,tsx,json,md}' --tab-width 4 --trailing-comma es5 --ignore-path .gitignore --arrow-parens always --write",
13
- "lint": "./node_modules/tslint/bin/tslint src/**/*.ts{,x}",
14
- "lint-fix": "./node_modules/tslint/bin/tslint src/**/*.ts{,x} --fix",
15
- "prepublish": "yarn build"
16
- },
17
- "devDependencies": {
18
- "husky": "^3.1.0",
19
- "lint-staged": "^9.5.0",
20
- "prettier": "^1.19.1",
21
- "tslint": "^5.20.1",
22
- "tslint-config-prettier": "^1.18.0",
23
- "typescript": "^3.7.2"
24
- },
25
- "lint-staged": {
26
- "src/**/*.{ts}": [
27
- "./node_modules/tslint/bin/tslint -c tslint.json --fix",
28
- "git add"
29
- ]
30
- },
31
- "husky": {
32
- "hooks": {
33
- "pre-commit": "yarn prettier; git add --all; lint-staged"
34
- }
35
- },
36
- "dependencies": {
37
- "tweetnacl": "^1.0.3"
38
- },
39
- "repository": {
40
- "type": "git",
41
- "url": "git+https://github.com/vex-chat/types-js.git"
42
- },
43
- "bugs": {
44
- "url": "https://github.com/vex-chat/types-js/issues"
45
- },
46
- "homepage": "https://github.com/vex-chat/types-js#readme"
2
+ "name": "@vex-chat/types",
3
+ "version": "0.11.0",
4
+ "description": "Types for vex",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "author": "Extra <extrahash@protonmail.com>",
8
+ "license": "AGPL-3.0-or-later",
9
+ "scripts": {
10
+ "start": "node ./dist/index.js",
11
+ "build": "rimraf dist && tsc",
12
+ "prepack": "yarn build",
13
+ "prettier": "prettier '**/*.{ts,tsx,json,md}' --ignore-path .gitignore --write",
14
+ "lint": "eslint src/**/*.ts",
15
+ "lint-fix": "eslint src/**/*.ts --fix",
16
+ "push": "yarn build && yalc push",
17
+ "prepare": "husky"
18
+ },
19
+ "dependencies": {
20
+ "tweetnacl": "^1.0.3"
21
+ },
22
+ "devDependencies": {
23
+ "@changesets/cli": "^2.29.8",
24
+ "@types/node": "^20.0.0",
25
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
26
+ "@typescript-eslint/parser": "^8.0.0",
27
+ "eslint": "^9.0.0",
28
+ "eslint-config-prettier": "^9.0.0",
29
+ "husky": "^9.0.0",
30
+ "lint-staged": "^15.2.0",
31
+ "prettier": "^3.2.0",
32
+ "rimraf": "^5.0.0",
33
+ "typescript": "^5.7.0"
34
+ },
35
+ "lint-staged": {
36
+ "src/**/*.{ts}": [
37
+ "eslint --fix"
38
+ ]
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/vex-chat/types-js.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/vex-chat/types-js/issues"
46
+ },
47
+ "homepage": "https://github.com/vex-chat/types-js#readme"
47
48
  }