@sonoransoftware/sonoran.js 1.0.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.
- package/.eslintrc.js +11 -0
- package/.prettierrc.js +7 -0
- package/docs/CAD-Methods-and-Usage.md +59 -0
- package/docs/CMS-Methods-and-Usage.md +212 -0
- package/docs/REST-Methods-and-Usage.md +47 -0
- package/package.json +42 -0
- package/readme.md +54 -0
- package/src/builders/cad/DispatchCall.ts +159 -0
- package/src/builders/cad/index.ts +1 -0
- package/src/builders/index.ts +3 -0
- package/src/constants.ts +174 -0
- package/src/errors/LibraryErrors.ts +43 -0
- package/src/errors/Messages.ts +7 -0
- package/src/errors/index.ts +2 -0
- package/src/index.ts +12 -0
- package/src/instance/Instance.ts +118 -0
- package/src/instance/instance.types.ts +17 -0
- package/src/libs/rest/src/index.ts +6 -0
- package/src/libs/rest/src/lib/REST.ts +201 -0
- package/src/libs/rest/src/lib/RequestManager.ts +256 -0
- package/src/libs/rest/src/lib/errors/APIError.ts +15 -0
- package/src/libs/rest/src/lib/errors/HTTPError.ts +22 -0
- package/src/libs/rest/src/lib/errors/RateLimitError.ts +21 -0
- package/src/libs/rest/src/lib/errors/index.ts +4 -0
- package/src/libs/rest/src/lib/handlers/IHandler.ts +13 -0
- package/src/libs/rest/src/lib/handlers/SequentialHandler.ts +157 -0
- package/src/libs/rest/src/lib/utils/constants.ts +919 -0
- package/src/libs/rest/src/lib/utils/utils.ts +18 -0
- package/src/managers/BaseManager.ts +15 -0
- package/src/managers/CADActiveUnitsManager.ts +50 -0
- package/src/managers/CADManager.ts +58 -0
- package/src/managers/CADServerManager.ts +27 -0
- package/src/managers/CMSManager.ts +133 -0
- package/src/managers/CMSServerManager.ts +27 -0
- package/src/managers/CacheManager.ts +38 -0
- package/src/managers/DataManager.ts +64 -0
- package/src/structures/Base.ts +28 -0
- package/src/structures/CADActiveUnit.ts +85 -0
- package/src/structures/CADServer.ts +37 -0
- package/src/structures/CMSServer.ts +26 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/utils.ts +75 -0
- package/tsconfig.json +71 -0
package/src/constants.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import Collection from '@discordjs/collection';
|
|
2
|
+
import { CADDispatchOriginEnums, CADDispatchStatusEnums } from './libs/rest/src';
|
|
3
|
+
import { DataManager } from './managers/DataManager';
|
|
4
|
+
import { CADActiveUnitsManager } from './managers/CADActiveUnitsManager';
|
|
5
|
+
import { CADActiveUnit } from './structures/CADActiveUnit';
|
|
6
|
+
|
|
7
|
+
export enum productEnums {
|
|
8
|
+
CAD,
|
|
9
|
+
CMS
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CADNewDispatchBuilderOptions {
|
|
13
|
+
serverId?: number;
|
|
14
|
+
origin?: CADDispatchOriginEnums;
|
|
15
|
+
status?: CADDispatchStatusEnums;
|
|
16
|
+
priority?: 1 | 2 | 3;
|
|
17
|
+
block?: string;
|
|
18
|
+
address?: string;
|
|
19
|
+
postal?: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
code?: string;
|
|
22
|
+
primary?: number;
|
|
23
|
+
trackPrimary?: boolean;
|
|
24
|
+
description?: string;
|
|
25
|
+
metaData?: Record<string, string>;
|
|
26
|
+
units?: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type Constructable<T> = abstract new (...args: any[]) => T;
|
|
30
|
+
|
|
31
|
+
export interface Caches {
|
|
32
|
+
CADActiveUnitsManager: [manager: typeof CADActiveUnitsManager, holds: CADActiveUnit];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type CacheConstructors = {
|
|
36
|
+
[K in keyof Caches]: Caches[K][0] & { name: K };
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type CacheFactory = (
|
|
40
|
+
manager: CacheConstructors[keyof Caches],
|
|
41
|
+
holds: Caches[typeof manager['name']][1],
|
|
42
|
+
) => typeof manager['prototype'] extends DataManager<infer K, infer V, any> ? Collection<K, V> : never;
|
|
43
|
+
|
|
44
|
+
export interface CADActiveUnitFetchOptions {
|
|
45
|
+
id?: number | number[];
|
|
46
|
+
accId?: string | string[];
|
|
47
|
+
apiId?: string | string[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export enum CADSubscriptionVersionEnum {
|
|
51
|
+
FREE = 0,
|
|
52
|
+
STARTER = 1,
|
|
53
|
+
STANDARD = 2,
|
|
54
|
+
PLUS = 3,
|
|
55
|
+
PRO = 4,
|
|
56
|
+
ONE = 6
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export enum CMSSubscriptionVersionEnum {
|
|
60
|
+
FREE = 0,
|
|
61
|
+
STARTER = 1,
|
|
62
|
+
STANDARD = 2,
|
|
63
|
+
PLUS = 3,
|
|
64
|
+
PRO = 4,
|
|
65
|
+
ONE = 6
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type Mutable<T> = {
|
|
69
|
+
-readonly [k in keyof T]: T[k];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export interface CMSVerifyWhitelistPromiseResult {
|
|
73
|
+
success: boolean;
|
|
74
|
+
reason?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface CMSGetComAccountPromiseResult {
|
|
78
|
+
success: boolean;
|
|
79
|
+
reason?: string;
|
|
80
|
+
data?: {
|
|
81
|
+
accId: string;
|
|
82
|
+
active: boolean;
|
|
83
|
+
accName: string;
|
|
84
|
+
comName: string;
|
|
85
|
+
primaryIdentifier: string;
|
|
86
|
+
secondaryIdentifiers: string[];
|
|
87
|
+
primaryRank: string;
|
|
88
|
+
secondaryRanks: string[];
|
|
89
|
+
primaryDepartment: string;
|
|
90
|
+
secondaryDepartments: string[];
|
|
91
|
+
joinDate: string;
|
|
92
|
+
totalRankPower: number;
|
|
93
|
+
comOwner: boolean;
|
|
94
|
+
isBanned: boolean;
|
|
95
|
+
lastLogin: string;
|
|
96
|
+
activeApiIds: string[];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const uuidRegex = /[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}/i;
|
|
101
|
+
|
|
102
|
+
export interface CMSClockInOutPromiseResult {
|
|
103
|
+
success: boolean;
|
|
104
|
+
reason?: string;
|
|
105
|
+
clockedIn?: boolean;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface CMSClockInOutParams {
|
|
109
|
+
accId?: string;
|
|
110
|
+
apiId?: string;
|
|
111
|
+
forceClockIn?: boolean;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface CMSCheckComApiIdPromiseResult {
|
|
115
|
+
success: boolean;
|
|
116
|
+
reason?: string;
|
|
117
|
+
username?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface CADGetAccountPromiseResult {
|
|
121
|
+
success: boolean;
|
|
122
|
+
reason?: string;
|
|
123
|
+
data?: {
|
|
124
|
+
uuid: string;
|
|
125
|
+
username: string;
|
|
126
|
+
status: number;
|
|
127
|
+
joined: string;
|
|
128
|
+
lastLogin: string;
|
|
129
|
+
permissions: {
|
|
130
|
+
civilian: boolean;
|
|
131
|
+
lawyer: boolean;
|
|
132
|
+
dmv: boolean;
|
|
133
|
+
police: boolean;
|
|
134
|
+
fire: boolean;
|
|
135
|
+
ems: boolean;
|
|
136
|
+
dispatch: boolean;
|
|
137
|
+
admin: boolean;
|
|
138
|
+
polRecAdd: boolean;
|
|
139
|
+
polRecEdit: boolean;
|
|
140
|
+
polRecRemove: boolean;
|
|
141
|
+
polSuper: boolean;
|
|
142
|
+
polEditUnit: boolean;
|
|
143
|
+
polEditOtherUnit: boolean;
|
|
144
|
+
selfDispatch: boolean;
|
|
145
|
+
medRecAdd: boolean;
|
|
146
|
+
medRecEdit: boolean;
|
|
147
|
+
medRecRemove: boolean;
|
|
148
|
+
medSuper: boolean;
|
|
149
|
+
fireRecAdd: boolean;
|
|
150
|
+
fireRecEdit: boolean;
|
|
151
|
+
fireRecRemove: boolean;
|
|
152
|
+
fireSuper: boolean;
|
|
153
|
+
dmvRecAdd: boolean;
|
|
154
|
+
dmvRecEdit: boolean;
|
|
155
|
+
dmvRecRemove: boolean;
|
|
156
|
+
dmvSuper: boolean;
|
|
157
|
+
lawRecAdd: boolean;
|
|
158
|
+
lawRecEdit: boolean;
|
|
159
|
+
lawRecRemove: boolean;
|
|
160
|
+
lawSuper: boolean;
|
|
161
|
+
adminAccounts: boolean;
|
|
162
|
+
adminPermissionKeys: boolean;
|
|
163
|
+
adminCustomization: boolean;
|
|
164
|
+
adminDepartments: boolean;
|
|
165
|
+
adminTenCodes: boolean;
|
|
166
|
+
adminPenalCodes: boolean;
|
|
167
|
+
adminInGameIntegration: boolean;
|
|
168
|
+
adminDiscordIntegration: boolean;
|
|
169
|
+
adminLimits: boolean;
|
|
170
|
+
adminLogs: boolean;
|
|
171
|
+
},
|
|
172
|
+
apiIds: string[];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const messages = new Map();
|
|
2
|
+
|
|
3
|
+
export class GenericError extends Error {
|
|
4
|
+
private readonly errCode: string;
|
|
5
|
+
constructor(key: string, ...args: Array<any>) {
|
|
6
|
+
super(GenericError.message(key, args));
|
|
7
|
+
this.errCode = key;
|
|
8
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, GenericError);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get name(): string {
|
|
12
|
+
return `${super.name} [${this.errCode}]`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get code(): string {
|
|
16
|
+
return this.errCode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Format the message for an error.
|
|
21
|
+
* @param {string} key Error key
|
|
22
|
+
* @param {Array<any>} args Arguments to pass for util format or as function args
|
|
23
|
+
* @returns {string} Formatted string
|
|
24
|
+
*/
|
|
25
|
+
private static message(key: string, args: Array<any>): string {
|
|
26
|
+
if (typeof key !== 'string') throw new Error('Error message key must be a string');
|
|
27
|
+
const msg = messages.get(key);
|
|
28
|
+
if (!msg) throw new Error(`An invalid error message key was used: ${key}.`);
|
|
29
|
+
if (typeof msg === 'function') return msg(...args);
|
|
30
|
+
if (!args?.length) return msg;
|
|
31
|
+
args.unshift(msg);
|
|
32
|
+
return String(...args);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Register an error code and message.
|
|
38
|
+
* @param {string} sym Unique name for the error
|
|
39
|
+
* @param {*} val Value of the error
|
|
40
|
+
*/
|
|
41
|
+
export function register(sym: symbol, val: any): void {
|
|
42
|
+
messages.set(sym, typeof val === 'function' ? val : String(val));
|
|
43
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { register } from './LibraryErrors';
|
|
2
|
+
|
|
3
|
+
const Messages: Record<string | number | symbol, any> = {
|
|
4
|
+
NOT_IMPLEMENTED: (what: string, name: string) => `Method ${what} not implemented on ${name}.`
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
for (const [name, message] of Object.entries(Messages)) register(Symbol(name), message);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './instance/Instance';
|
|
2
|
+
export * from './builders';
|
|
3
|
+
export * from './libs/rest/src';
|
|
4
|
+
|
|
5
|
+
import { productEnums, CADNewDispatchBuilderOptions, CADSubscriptionVersionEnum, CMSSubscriptionVersionEnum } from './constants';
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
productEnums,
|
|
9
|
+
CADNewDispatchBuilderOptions,
|
|
10
|
+
CADSubscriptionVersionEnum,
|
|
11
|
+
CMSSubscriptionVersionEnum
|
|
12
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
|
|
3
|
+
import * as globalTypes from '../constants';
|
|
4
|
+
import * as InstanceTypes from './instance.types';
|
|
5
|
+
import { CADManager } from '../managers/CADManager';
|
|
6
|
+
import { CMSManager } from '../managers/CMSManager';
|
|
7
|
+
import { debugLog } from '../utils';
|
|
8
|
+
|
|
9
|
+
export default class Instance extends EventEmitter {
|
|
10
|
+
public cadCommunityId: string | undefined;
|
|
11
|
+
public cadApiKey: string | undefined;
|
|
12
|
+
public cadApiUrl: string = 'https://api.sonorancad.com';
|
|
13
|
+
public cadDefaultServerId: number = 1;
|
|
14
|
+
public isCADSuccessful: boolean = false;
|
|
15
|
+
public cmsCommunityId: string | undefined;
|
|
16
|
+
public cmsApiKey: string | undefined;
|
|
17
|
+
public cmsApiUrl: string = 'https://api.sonorancms.com';
|
|
18
|
+
public cmsDefaultServerId: number = 1;
|
|
19
|
+
public isCMSSuccessful: boolean = false;
|
|
20
|
+
|
|
21
|
+
public cad: CADManager | undefined;
|
|
22
|
+
public cms: CMSManager | undefined;
|
|
23
|
+
|
|
24
|
+
public debug: boolean = false;
|
|
25
|
+
|
|
26
|
+
constructor(options: InstanceTypes.InstanceOptions) {
|
|
27
|
+
super({ captureRejections: true });
|
|
28
|
+
if (options.debug) {
|
|
29
|
+
this.debug = options.debug;
|
|
30
|
+
}
|
|
31
|
+
if (Object.prototype.hasOwnProperty.call(options, 'apiKey') && Object.prototype.hasOwnProperty.call(options, 'communityId')) {
|
|
32
|
+
if (Object.prototype.hasOwnProperty.call(options, 'product')) {
|
|
33
|
+
switch (options.product) {
|
|
34
|
+
case globalTypes.productEnums.CAD: {
|
|
35
|
+
this.cadCommunityId = options.communityId;
|
|
36
|
+
this.cadApiKey = options.apiKey;
|
|
37
|
+
if (options.serverId !== undefined) {
|
|
38
|
+
this._debugLog(`Overriding default server id... ${options.serverId}`);
|
|
39
|
+
this.cadDefaultServerId = options.serverId;
|
|
40
|
+
}
|
|
41
|
+
if (Object.prototype.hasOwnProperty.call(options, 'cadApiUrl') && typeof options.cadApiUrl === 'string') {
|
|
42
|
+
this._debugLog(`Overriding CAD API Url... ${options.cadApiUrl}`);
|
|
43
|
+
this.cadApiUrl = options.cadApiUrl;
|
|
44
|
+
}
|
|
45
|
+
this._debugLog('About to initialize instance.');
|
|
46
|
+
this.initialize();
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case globalTypes.productEnums.CMS: {
|
|
50
|
+
this.cmsCommunityId = options.communityId;
|
|
51
|
+
this.cmsApiKey = options.apiKey;
|
|
52
|
+
if (options.serverId !== undefined) {
|
|
53
|
+
this._debugLog(`Overriding default server id... ${options.serverId}`);
|
|
54
|
+
this.cmsDefaultServerId = options.serverId;
|
|
55
|
+
}
|
|
56
|
+
if (Object.prototype.hasOwnProperty.call(options, 'cmsApiUrl') && typeof options.cmsApiUrl === 'string') {
|
|
57
|
+
this._debugLog(`Overriding CMS API URL... ${options.cmsApiUrl}`);
|
|
58
|
+
this.cmsApiUrl = options.cmsApiUrl;
|
|
59
|
+
}
|
|
60
|
+
this.initialize();
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
default: {
|
|
64
|
+
throw new Error('Invalid product enum given for constructor.');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
throw new Error('No product enum given when instancing.');
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
this.cadCommunityId = options.cadCommunityId;
|
|
72
|
+
this.cadApiKey = options.cadApiKey;
|
|
73
|
+
this.cmsCommunityId = options.cmsCommunityId;
|
|
74
|
+
this.cmsApiKey = options.cmsApiKey;
|
|
75
|
+
|
|
76
|
+
if (options.cadDefaultServerId !== undefined) {
|
|
77
|
+
this._debugLog(`Overriding default CAD server id... ${options.serverId}`);
|
|
78
|
+
this.cadDefaultServerId = options.cadDefaultServerId;
|
|
79
|
+
}
|
|
80
|
+
if (options.cmsDefaultServerId !== undefined) {
|
|
81
|
+
this._debugLog(`Overriding default CMS server id... ${options.serverId}`);
|
|
82
|
+
this.cmsDefaultServerId = options.cmsDefaultServerId;
|
|
83
|
+
}
|
|
84
|
+
if (Object.prototype.hasOwnProperty.call(options, 'cadApiUrl') && typeof options.cadApiUrl === 'string') {
|
|
85
|
+
this._debugLog(`Overriding CAD API Url... ${options.cadApiUrl}`);
|
|
86
|
+
this.cadApiUrl = options.cadApiUrl;
|
|
87
|
+
}
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(options, 'cmsApiUrl') && typeof options.cmsApiUrl === 'string') {
|
|
89
|
+
this._debugLog(`Overriding CMS API URL... ${options.cmsApiUrl}`);
|
|
90
|
+
this.cmsApiUrl = options.cmsApiUrl;
|
|
91
|
+
}
|
|
92
|
+
this.initialize();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
private initialize() {
|
|
99
|
+
if (this.cadCommunityId && this.cadApiKey && this.cadApiUrl) {
|
|
100
|
+
this._debugLog('About to initialize CAD Manager');
|
|
101
|
+
this.cad = new CADManager(this);
|
|
102
|
+
} else {
|
|
103
|
+
this._debugLog('Not initializing CAD Manager due to a missing community id, api key, or api url.');
|
|
104
|
+
}
|
|
105
|
+
if (this.cmsCommunityId && this.cmsApiKey && this.cmsApiUrl) {
|
|
106
|
+
this._debugLog('About to initialize CMS Manager');
|
|
107
|
+
this.cms = new CMSManager(this);
|
|
108
|
+
} else {
|
|
109
|
+
this._debugLog('Not initializing CMS Manager due to a missing community id, api key, or api url.');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public _debugLog(message: string): void {
|
|
114
|
+
if (this.debug) {
|
|
115
|
+
debugLog(message);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as globalTypes from '../constants';
|
|
2
|
+
|
|
3
|
+
export type InstanceOptions = {
|
|
4
|
+
communityId?: string;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
product?: globalTypes.productEnums;
|
|
7
|
+
serverId?: number;
|
|
8
|
+
cadCommunityId?: string;
|
|
9
|
+
cadApiKey?: string;
|
|
10
|
+
cadApiUrl?: string;
|
|
11
|
+
cadDefaultServerId?: number;
|
|
12
|
+
cmsCommunityId?: string;
|
|
13
|
+
cmsApiKey?: string;
|
|
14
|
+
cmsApiUrl?: string;
|
|
15
|
+
cmsDefaultServerId?: number;
|
|
16
|
+
debug?: boolean;
|
|
17
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import {
|
|
3
|
+
InternalRequestData,
|
|
4
|
+
// RequestMethod,
|
|
5
|
+
RequestData,
|
|
6
|
+
RequestManager,
|
|
7
|
+
// RouteLike
|
|
8
|
+
} from './RequestManager';
|
|
9
|
+
import { AllAPITypes, AllAPITypesType, RESTEvents, RESTTypedAPIDataStructs } from './utils/constants';
|
|
10
|
+
import { productEnums, uuidRegex } from '../../../../constants';
|
|
11
|
+
import type { AgentOptions } from 'node:https';
|
|
12
|
+
import type { RequestInit, Response } from 'node-fetch';
|
|
13
|
+
// import type Collection from '@discordjs/collection';
|
|
14
|
+
import Instance from '../../../../instance/Instance';
|
|
15
|
+
import { CADManager } from '../../../../managers/CADManager';
|
|
16
|
+
import { convertSubNumToName } from './utils/Utils';
|
|
17
|
+
import { CMSManager } from '../../../../managers/CMSManager';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Options to be passed when creating the REST instance
|
|
21
|
+
*/
|
|
22
|
+
export interface RESTOptions {
|
|
23
|
+
/**
|
|
24
|
+
* HTTPS Agent options
|
|
25
|
+
* @default {}
|
|
26
|
+
*/
|
|
27
|
+
agent: Omit<AgentOptions, 'keepAlive'>;
|
|
28
|
+
/**
|
|
29
|
+
* The base api path, without version
|
|
30
|
+
*/
|
|
31
|
+
api: string;
|
|
32
|
+
/**
|
|
33
|
+
* Additional headers to send for all API requests
|
|
34
|
+
* @default {}
|
|
35
|
+
*/
|
|
36
|
+
headers: Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Wether the request should be queued if there's a current ratelimit or to reject.
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
rejectOnRateLimit: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Data emitted on `RESTEvents.RateLimited`
|
|
46
|
+
*/
|
|
47
|
+
export interface RateLimitData {
|
|
48
|
+
product: productEnums;
|
|
49
|
+
type: string;
|
|
50
|
+
timeTill: NodeJS.Timer;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface APIRequest {
|
|
54
|
+
/**
|
|
55
|
+
* The HTTP method used in this request
|
|
56
|
+
*/
|
|
57
|
+
type: AllAPITypesType;
|
|
58
|
+
/**
|
|
59
|
+
* Additional HTTP options for this request
|
|
60
|
+
*/
|
|
61
|
+
options: RequestInit;
|
|
62
|
+
/**
|
|
63
|
+
* The data that was used to form the body of this request
|
|
64
|
+
*/
|
|
65
|
+
data: RequestData;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface InvalidRequestWarningData {
|
|
69
|
+
/**
|
|
70
|
+
* Number of invalid requests that have been made in the window
|
|
71
|
+
*/
|
|
72
|
+
count: number;
|
|
73
|
+
/**
|
|
74
|
+
* API request type which the request is for
|
|
75
|
+
*/
|
|
76
|
+
type: string;
|
|
77
|
+
/**
|
|
78
|
+
* Product which the invalid request is for
|
|
79
|
+
*/
|
|
80
|
+
product: productEnums;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface RestEvents {
|
|
84
|
+
invalidRequestWarning: [invalidRequestInfo: InvalidRequestWarningData];
|
|
85
|
+
restDebug: [info: string];
|
|
86
|
+
rateLimited: [rateLimitInfo: RateLimitData];
|
|
87
|
+
request: [request: APIRequest];
|
|
88
|
+
response: [request: APIRequest, response: Response];
|
|
89
|
+
newListener: [name: string, listener: (...args: any) => void];
|
|
90
|
+
removeListener: [name: string, listener: (...args: any) => void];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface REST {
|
|
94
|
+
on: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) &
|
|
95
|
+
(<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
|
96
|
+
|
|
97
|
+
once: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) &
|
|
98
|
+
(<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
|
99
|
+
|
|
100
|
+
emit: (<K extends keyof RestEvents>(event: K, ...args: RestEvents[K]) => boolean) &
|
|
101
|
+
(<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, ...args: any[]) => boolean);
|
|
102
|
+
|
|
103
|
+
off: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) &
|
|
104
|
+
(<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
|
105
|
+
|
|
106
|
+
removeAllListeners: (<K extends keyof RestEvents>(event?: K) => this) &
|
|
107
|
+
(<S extends string | symbol>(event?: Exclude<S, keyof RestEvents>) => this);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export type RestManagerTypes = CADManager | CMSManager;
|
|
111
|
+
|
|
112
|
+
export class REST extends EventEmitter {
|
|
113
|
+
public readonly requestManager: RequestManager;
|
|
114
|
+
public readonly instance: Instance;
|
|
115
|
+
public readonly manager: RestManagerTypes;
|
|
116
|
+
|
|
117
|
+
public constructor(_instance: Instance, _manager: RestManagerTypes,_product: productEnums, options: RESTOptions) {
|
|
118
|
+
super();
|
|
119
|
+
this.instance = _instance;
|
|
120
|
+
this.manager = _manager;
|
|
121
|
+
this.requestManager = new RequestManager(_instance, _product, options)
|
|
122
|
+
.on(RESTEvents.Debug, this.emit.bind(this, RESTEvents.Debug))
|
|
123
|
+
.on(RESTEvents.RateLimited, this.emit.bind(this, RESTEvents.RateLimited))
|
|
124
|
+
.on(RESTEvents.InvalidRequestWarning, this.emit.bind(this, RESTEvents.InvalidRequestWarning));
|
|
125
|
+
|
|
126
|
+
this.on('newListener', (name, listener) => {
|
|
127
|
+
if (name === RESTEvents.Request || name === RESTEvents.Response) this.requestManager.on(name, listener);
|
|
128
|
+
});
|
|
129
|
+
this.on('removeListener', (name, listener) => {
|
|
130
|
+
if (name === RESTEvents.Request || name === RESTEvents.Response) this.requestManager.off(name, listener);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Runs a request from the api
|
|
136
|
+
* @param type API Type Enum
|
|
137
|
+
*/
|
|
138
|
+
public request<K extends keyof RESTTypedAPIDataStructs>(type: K, ...args: RESTTypedAPIDataStructs[K]) {
|
|
139
|
+
const apiType = AllAPITypes.find((aT) => aT.type === type);
|
|
140
|
+
if (!apiType) throw new Error('Invalid API Type given for request.');
|
|
141
|
+
let communityId: string | undefined;
|
|
142
|
+
let apiKey: string | undefined;
|
|
143
|
+
switch (apiType.product) {
|
|
144
|
+
case productEnums.CAD: {
|
|
145
|
+
communityId = this.instance.cadCommunityId;
|
|
146
|
+
apiKey = this.instance.cadApiKey;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case productEnums.CMS: {
|
|
150
|
+
communityId = this.instance.cmsCommunityId;
|
|
151
|
+
apiKey = this.instance.cmsApiKey;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!communityId || !apiKey) throw new Error(`Community ID or API Key could not be found for request. P${apiType.product}`);
|
|
156
|
+
if (apiType.minVersion > this.manager.version) throw new Error(`[${type}] Subscription version too low for this API type request. Current Version: ${convertSubNumToName(this.manager.version)} Needed Version: ${convertSubNumToName(apiType.minVersion)}`);
|
|
157
|
+
const formattedData = this.formatDataArguments(apiType.type, args);
|
|
158
|
+
const options: InternalRequestData = {
|
|
159
|
+
id: communityId,
|
|
160
|
+
key: apiKey,
|
|
161
|
+
type,
|
|
162
|
+
data: formattedData,
|
|
163
|
+
product: apiType.product
|
|
164
|
+
};
|
|
165
|
+
return this.requestManager.queueRequest(options);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private formatDataArguments(type: string, args: any) {
|
|
169
|
+
switch (type) {
|
|
170
|
+
case 'VERIFY_WHITELIST': {
|
|
171
|
+
return {
|
|
172
|
+
apiId: args[0],
|
|
173
|
+
accId: uuidRegex.test(args[1]) ? args[1] : undefined,
|
|
174
|
+
serverId: args[2]
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
case 'GET_COM_ACCOUNT': {
|
|
178
|
+
return {
|
|
179
|
+
apiId: args[0],
|
|
180
|
+
username: args[1],
|
|
181
|
+
accId: args[2]
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
case 'CLOCK_IN_OUT': {
|
|
185
|
+
return {
|
|
186
|
+
apiId: args[0],
|
|
187
|
+
accId: args[1],
|
|
188
|
+
forceClockIn: args[2]
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
case 'CHECK_COM_APIID': {
|
|
192
|
+
return {
|
|
193
|
+
apiId: args[0]
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
default: {
|
|
197
|
+
return args;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|