@jd-data-limited/easy-fm 3.2.7 → 3.2.9
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/package.json +11 -7
- package/src/FMError.d.ts +1 -1
- package/src/FMError.ts +1 -1
- package/src/connection/FMHost.d.ts +1 -1
- package/src/connection/FMHost.ts +3 -3
- package/src/connection/database.d.ts +5 -3
- package/src/connection/database.js +42 -49
- package/src/connection/database.ts +70 -82
- package/src/connection/databaseBase.d.ts +4 -1
- package/src/connection/databaseBase.ts +4 -1
- package/src/layouts/layout.d.ts +3 -3
- package/src/layouts/layout.js +15 -29
- package/src/layouts/layout.ts +22 -39
- package/src/layouts/layoutBase.d.ts +2 -2
- package/src/layouts/layoutBase.ts +2 -1
- package/src/layouts/layoutRecordManager.d.ts +1 -1
- package/src/layouts/layoutRecordManager.js +24 -27
- package/src/layouts/layoutRecordManager.ts +14 -30
- package/src/models/apiResults.d.ts +103 -0
- package/src/models/apiResults.js +28 -0
- package/src/models/apiResults.ts +112 -0
- package/src/records/field.d.ts +3 -2
- package/src/records/field.js +28 -43
- package/src/records/field.ts +46 -64
- package/src/records/getOperations/find.js +18 -28
- package/src/records/getOperations/find.ts +17 -28
- package/src/records/getOperations/recordGetRange.js +15 -22
- package/src/records/getOperations/recordGetRange.ts +17 -24
- package/src/records/layoutRecord.js +73 -102
- package/src/records/layoutRecord.ts +101 -133
- package/src/types.d.ts +0 -4
- package/src/types.ts +0 -5
- package/.expo/README.md +0 -15
- package/.expo/settings.json +0 -8
- package/.idea/compiler.xml +0 -7
- package/.idea/copyright/JD_Data.xml +0 -6
- package/.idea/copyright/profiles_settings.xml +0 -7
- package/.idea/discord.xml +0 -7
- package/.idea/easy-fm.iml +0 -8
- package/.idea/jsLibraryMappings.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/php.xml +0 -18
- package/.idea/vcs.xml +0 -6
- package/decs.d.ts +0 -7
- package/dist/index.min.js +0 -2
- package/dist/index.min.js.LICENSE.txt +0 -3
- package/docs/classes/FileMakerConnection.md +0 -86
- package/docs/classes/layout.md +0 -0
- package/examples/test.js +0 -7
- package/fmErrors.json +0 -1010
- package/img.png +0 -0
- package/test.d.ts +0 -2
- package/test.js +0 -30
- package/test.ts +0 -33
- package/test2.d.ts +0 -1
- package/test2.js +0 -15
- package/tsconfig.json +0 -16
- package/webpack.config.cjs +0 -20
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jd-data-limited/easy-fm",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.9",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"
|
|
6
|
-
"@types/events": "^3.0.0",
|
|
5
|
+
"follow-redirects": "^1.15.5",
|
|
7
6
|
"moment": "^2.29.4",
|
|
8
|
-
"node-fetch": "3.2
|
|
9
|
-
"typescript": "^5.2.2",
|
|
10
|
-
"ytdl-core": "^4.11.4"
|
|
7
|
+
"node-fetch": "3.3.2"
|
|
11
8
|
},
|
|
12
9
|
"type": "module",
|
|
13
10
|
"main": "src/index.js",
|
|
@@ -16,8 +13,11 @@
|
|
|
16
13
|
"url": "https://github.com/JD-Data-Limited/easy-fm",
|
|
17
14
|
"license": "SEE LICENSE IN LICENSE",
|
|
18
15
|
"description": "easy-fm is a Node.js module that allows you to interact with\r a [FileMaker database stored](https://www.claris.com/filemaker/) on\r a [FileMaker server](https://www.claris.com/filemaker/server/). This module interacts with your server using the\r [FileMaker Data API](https://help.claris.com/en/data-api-guide/content/index.html).",
|
|
16
|
+
"files": [
|
|
17
|
+
"./src/**/*"
|
|
18
|
+
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"test": "
|
|
20
|
+
"test": "node --test tests/login.js",
|
|
21
21
|
"build": "webpack"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"url": "https://github.com/JD-Data-Limited/easy-fm/issues"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
+
"@types/btoa": "^1.2.3",
|
|
38
|
+
"@types/events": "^3.0.0",
|
|
39
|
+
"dotenv": "^16.3.1",
|
|
40
|
+
"typescript": "^5.2.2",
|
|
37
41
|
"webpack": "^5.81.0",
|
|
38
42
|
"webpack-cli": "^5.0.2"
|
|
39
43
|
}
|
package/src/FMError.d.ts
CHANGED
|
@@ -8,5 +8,5 @@ export declare class FMError extends Error {
|
|
|
8
8
|
readonly code: number;
|
|
9
9
|
readonly message: string;
|
|
10
10
|
readonly messages: string;
|
|
11
|
-
constructor(code:
|
|
11
|
+
constructor(code: string | number, httpStatus: number, res: any, trace?: Error);
|
|
12
12
|
}
|
package/src/FMError.ts
CHANGED
|
@@ -1021,7 +1021,7 @@ export class FMError extends Error {
|
|
|
1021
1021
|
readonly message: string
|
|
1022
1022
|
readonly messages: string
|
|
1023
1023
|
|
|
1024
|
-
constructor(code, httpStatus, res, trace?: Error) {
|
|
1024
|
+
constructor(code: string | number, httpStatus: number, res: any, trace?: Error) {
|
|
1025
1025
|
if (typeof code === "string") code = parseInt(code)
|
|
1026
1026
|
super(errs.find(err => err.e === code).d || "Unknown error");
|
|
1027
1027
|
this.httpStatus = httpStatus
|
|
@@ -9,5 +9,5 @@ export default class FMHost implements HostBase {
|
|
|
9
9
|
constructor(_hostname: string, timezoneOffset?: number, verify?: boolean);
|
|
10
10
|
listDatabases(credentials?: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris): Promise<any>;
|
|
11
11
|
database<T extends DatabaseStructure>(data: databaseOptionsWithExternalSources): Database<T>;
|
|
12
|
-
getMetadata(): Promise<
|
|
12
|
+
getMetadata(): Promise<FMHostMetadata>;
|
|
13
13
|
}
|
package/src/connection/FMHost.ts
CHANGED
|
@@ -9,12 +9,12 @@ import {Database} from "./database.js";
|
|
|
9
9
|
import {HostBase} from "./HostBase.js"
|
|
10
10
|
import {
|
|
11
11
|
databaseOptionsWithExternalSources, DatabaseStructure,
|
|
12
|
-
fileMakerResponse,
|
|
13
12
|
FMHostMetadata,
|
|
14
13
|
loginOptionsClaris,
|
|
15
14
|
loginOptionsFileMaker,
|
|
16
15
|
loginOptionsOAuth
|
|
17
16
|
} from "../types.js";
|
|
17
|
+
import {ApiResults} from "../models/apiResults";
|
|
18
18
|
|
|
19
19
|
export default class FMHost implements HostBase {
|
|
20
20
|
readonly hostname: string
|
|
@@ -39,7 +39,7 @@ export default class FMHost implements HostBase {
|
|
|
39
39
|
method: "GET",
|
|
40
40
|
headers
|
|
41
41
|
})
|
|
42
|
-
let data = await _fetch.json() as
|
|
42
|
+
let data = await _fetch.json() as ApiResults<{databases: any}>
|
|
43
43
|
// console.log(data.messages[0])
|
|
44
44
|
|
|
45
45
|
if (data.messages[0].code === "0") {
|
|
@@ -61,7 +61,7 @@ export default class FMHost implements HostBase {
|
|
|
61
61
|
let _fetch = await fetch(`${this.hostname}/fmi/data/v2/productInfo`, {
|
|
62
62
|
method: "GET",
|
|
63
63
|
})
|
|
64
|
-
let data = await _fetch.json() as
|
|
64
|
+
let data = await _fetch.json() as ApiResults<FMHostMetadata>
|
|
65
65
|
// console.log(data.messages[0])
|
|
66
66
|
|
|
67
67
|
if (data.messages[0].code === "0") {
|
|
@@ -7,6 +7,7 @@ import HTTP_REDIRECT from "follow-redirects";
|
|
|
7
7
|
import { databaseOptionsWithExternalSources, DatabaseStructure, Script } from "../types.js";
|
|
8
8
|
import { HostBase } from "./HostBase.js";
|
|
9
9
|
import { DatabaseBase } from "./databaseBase";
|
|
10
|
+
import { ApiResults } from "../models/apiResults";
|
|
10
11
|
export declare class Database<T extends DatabaseStructure> extends EventEmitter implements DatabaseBase {
|
|
11
12
|
private _token;
|
|
12
13
|
readonly host: HostBase;
|
|
@@ -16,14 +17,15 @@ export declare class Database<T extends DatabaseStructure> extends EventEmitter
|
|
|
16
17
|
constructor(host: HostBase, conn: databaseOptionsWithExternalSources);
|
|
17
18
|
private generateExternalSourceLogin;
|
|
18
19
|
logout(): Promise<void>;
|
|
19
|
-
login(): Promise<
|
|
20
|
+
login(): Promise<any>;
|
|
20
21
|
get token(): any;
|
|
21
22
|
get endpoint(): string;
|
|
22
|
-
apiRequest<T = any>(url: string | Request, options?: any, autoRelogin?: boolean): Promise<T
|
|
23
|
+
apiRequest<T = any>(url: string | Request, options?: any, autoRelogin?: boolean): Promise<ApiResults<T>>;
|
|
24
|
+
listLayouts(): Promise<Layout<LayoutInterface>[]>;
|
|
23
25
|
getLayout<R extends string>(name: R): Layout<T["layouts"][R]>;
|
|
24
26
|
getLayout<R extends LayoutInterface>(name: string): Layout<R>;
|
|
25
27
|
setGlobals(globalFields: any): Promise<void>;
|
|
26
28
|
script(name: any, parameter?: string): Script;
|
|
27
29
|
_tokenExpired(): void;
|
|
28
|
-
|
|
30
|
+
streamURL(url: string): Promise<HTTP_REDIRECT.http.IncomingMessage>;
|
|
29
31
|
}
|
|
@@ -38,9 +38,9 @@ export class Database extends EventEmitter {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
logout() {
|
|
41
|
-
return
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
42
|
if (!this.token)
|
|
43
|
-
|
|
43
|
+
throw new Error("Not logged in");
|
|
44
44
|
let _fetch = yield fetch(`${this.endpoint}/sessions/${this.token}`, {
|
|
45
45
|
method: "DELETE",
|
|
46
46
|
headers: {
|
|
@@ -50,28 +50,22 @@ export class Database extends EventEmitter {
|
|
|
50
50
|
let data = yield _fetch.json();
|
|
51
51
|
// console.log(data)
|
|
52
52
|
this._token = null;
|
|
53
|
-
|
|
54
|
-
}));
|
|
53
|
+
});
|
|
55
54
|
}
|
|
56
55
|
login() {
|
|
57
|
-
return
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
57
|
// Reset cookies
|
|
59
58
|
this.cookies = {};
|
|
60
|
-
|
|
61
|
-
yield this.host.getMetadata();
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
reject(e);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
59
|
+
yield this.host.getMetadata();
|
|
67
60
|
if (this.token)
|
|
68
61
|
throw new Error("Already logged in. Run logout() first");
|
|
69
62
|
if (this.connection_details.credentials.method === "token") {
|
|
70
63
|
this._token = this.connection_details.credentials.token;
|
|
71
|
-
|
|
64
|
+
return this.token;
|
|
72
65
|
}
|
|
73
66
|
else {
|
|
74
|
-
|
|
67
|
+
console.time();
|
|
68
|
+
let res = yield fetch(`${this.endpoint}/sessions`, {
|
|
75
69
|
hostname: this.host.hostname,
|
|
76
70
|
port: 443,
|
|
77
71
|
method: "POST",
|
|
@@ -82,21 +76,18 @@ export class Database extends EventEmitter {
|
|
|
82
76
|
return this.generateExternalSourceLogin(_i);
|
|
83
77
|
})
|
|
84
78
|
})
|
|
85
|
-
}).then((res) => __awaiter(this, void 0, void 0, function* () {
|
|
86
|
-
let _res = (yield res.json());
|
|
87
|
-
if (res.status === 200) {
|
|
88
|
-
this._token = res.headers.get('x-fm-data-access-token');
|
|
89
|
-
resolve(this._token);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
reject(new FMError(_res.messages[0].code, _res.status, res));
|
|
93
|
-
}
|
|
94
|
-
}))
|
|
95
|
-
.catch(e => {
|
|
96
|
-
reject(e);
|
|
97
79
|
});
|
|
80
|
+
console.time();
|
|
81
|
+
let _res = (yield res.json());
|
|
82
|
+
if (res.status === 200) {
|
|
83
|
+
this._token = res.headers.get('x-fm-data-access-token');
|
|
84
|
+
return this._token;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
throw new FMError(_res.messages[0].code, _res.status, res);
|
|
88
|
+
}
|
|
98
89
|
}
|
|
99
|
-
})
|
|
90
|
+
});
|
|
100
91
|
}
|
|
101
92
|
get token() {
|
|
102
93
|
return this._token;
|
|
@@ -119,35 +110,42 @@ export class Database extends EventEmitter {
|
|
|
119
110
|
}
|
|
120
111
|
}
|
|
121
112
|
let data = yield _fetch.json();
|
|
113
|
+
// Remove response if it is empty. This makes checking for an empty response easier
|
|
114
|
+
if (Object.keys(data.response).length === 0)
|
|
115
|
+
delete data.response;
|
|
122
116
|
// console.log(data.messages[0])
|
|
123
|
-
if (data.messages[0].code
|
|
117
|
+
if (data.messages[0].code === "952" && autoRelogin) {
|
|
124
118
|
this._token = null;
|
|
125
119
|
yield this.login();
|
|
126
120
|
return yield this.apiRequest(url, options, false);
|
|
127
121
|
}
|
|
122
|
+
else if (data.messages[0].code !== "0") {
|
|
123
|
+
throw new FMError(data.messages[0].code, _fetch.status, data);
|
|
124
|
+
}
|
|
125
|
+
data.httpStatus = _fetch.status;
|
|
128
126
|
return data;
|
|
129
127
|
});
|
|
130
128
|
}
|
|
129
|
+
listLayouts() {
|
|
130
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
let req = yield this.apiRequest(`${this.endpoint}/layouts`);
|
|
132
|
+
if (!req.response)
|
|
133
|
+
throw new FMError(req.messages[0].code, req.httpStatus, req.messages[0].message);
|
|
134
|
+
return req.response.layouts.filter(i => !i.isFolder).map(layout => new Layout(this, layout.name));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
131
137
|
getLayout(name) {
|
|
132
138
|
return new Layout(this, name);
|
|
133
139
|
}
|
|
140
|
+
/*
|
|
141
|
+
@deprecated
|
|
142
|
+
*/
|
|
134
143
|
setGlobals(globalFields) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
this.apiRequest(`${this.endpoint}/globals`, {
|
|
144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
// console.log({globalFields})
|
|
146
|
+
yield this.apiRequest(`${this.endpoint}/globals`, {
|
|
138
147
|
method: "PATCH",
|
|
139
148
|
body: JSON.stringify({ globalFields })
|
|
140
|
-
}).then(res => {
|
|
141
|
-
// console.log(res)
|
|
142
|
-
if (res.messages[0].code === "0") {
|
|
143
|
-
resolve();
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
reject((res.messages[0].code, res.status, res));
|
|
147
|
-
}
|
|
148
|
-
})
|
|
149
|
-
.catch(e => {
|
|
150
|
-
reject(e);
|
|
151
149
|
});
|
|
152
150
|
});
|
|
153
151
|
}
|
|
@@ -157,15 +155,10 @@ export class Database extends EventEmitter {
|
|
|
157
155
|
_tokenExpired() {
|
|
158
156
|
this.emit("token_expired");
|
|
159
157
|
}
|
|
160
|
-
|
|
158
|
+
streamURL(url) {
|
|
161
159
|
return new Promise((resolve, reject) => {
|
|
162
|
-
if (field.metadata.result !== "container") {
|
|
163
|
-
reject("Cannot stream the field " + field.id + " as it is not a container");
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
160
|
if (!url || typeof url !== "string") {
|
|
167
|
-
|
|
168
|
-
return;
|
|
161
|
+
throw new Error("URL is empty, or has invalid value");
|
|
169
162
|
}
|
|
170
163
|
let headers = {};
|
|
171
164
|
if (Object.keys(this.cookies).length !== 0) {
|
|
@@ -12,13 +12,13 @@ import HTTP_REDIRECT from "follow-redirects"
|
|
|
12
12
|
import {
|
|
13
13
|
databaseOptionsBase,
|
|
14
14
|
databaseOptionsWithExternalSources, DatabaseStructure,
|
|
15
|
-
fileMakerResponse,
|
|
16
15
|
loginOptionsFileMaker,
|
|
17
16
|
loginOptionsToken,
|
|
18
17
|
Script
|
|
19
18
|
} from "../types.js";
|
|
20
19
|
import {HostBase} from "./HostBase.js"
|
|
21
20
|
import {DatabaseBase} from "./databaseBase";
|
|
21
|
+
import {ApiLayout, ApiResults} from "../models/apiResults";
|
|
22
22
|
|
|
23
23
|
type GetLayoutReturnType<T extends DatabaseStructure, R extends LayoutInterface | string> = R extends string ? T["layouts"][R] : R
|
|
24
24
|
|
|
@@ -50,67 +50,55 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
logout(): Promise<void> {
|
|
54
|
-
|
|
55
|
-
if (!this.token) reject(new Error("Not logged in"))
|
|
53
|
+
async logout(): Promise<void> {
|
|
54
|
+
if (!this.token) throw new Error("Not logged in")
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
})
|
|
63
|
-
let data = await _fetch.json()
|
|
64
|
-
// console.log(data)
|
|
65
|
-
this._token = null
|
|
66
|
-
resolve()
|
|
56
|
+
let _fetch = await fetch(`${this.endpoint}/sessions/${this.token}`, {
|
|
57
|
+
method: "DELETE",
|
|
58
|
+
headers: {
|
|
59
|
+
"content-type": "application/json"
|
|
60
|
+
}
|
|
67
61
|
})
|
|
62
|
+
let data = await _fetch.json()
|
|
63
|
+
// console.log(data)
|
|
64
|
+
this._token = null
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
login() {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.cookies = {}
|
|
67
|
+
async login() {
|
|
68
|
+
// Reset cookies
|
|
69
|
+
this.cookies = {}
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} catch (e) {
|
|
78
|
-
reject(e)
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
if (this.token) throw new Error("Already logged in. Run logout() first")
|
|
71
|
+
await this.host.getMetadata()
|
|
72
|
+
if (this.token) throw new Error("Already logged in. Run logout() first")
|
|
82
73
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
74
|
+
if (this.connection_details.credentials.method === "token") {
|
|
75
|
+
this._token = (<loginOptionsToken>this.connection_details.credentials).token
|
|
76
|
+
return this.token
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.time()
|
|
80
|
+
let res = await fetch(`${this.endpoint}/sessions`, {
|
|
81
|
+
hostname: this.host.hostname,
|
|
82
|
+
port: 443,
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: generateAuthorizationHeaders(this.connection_details.credentials) as unknown as HeadersInit,
|
|
85
|
+
body: JSON.stringify({
|
|
86
|
+
fmDataSource: this.connection_details.externalSources.map(i => {
|
|
87
|
+
let _i = <databaseOptionsBase>i
|
|
88
|
+
return this.generateExternalSourceLogin(_i)
|
|
98
89
|
})
|
|
99
|
-
}).then(async res => {
|
|
100
|
-
let _res = <any>(await res.json())
|
|
101
|
-
if (res.status === 200) {
|
|
102
|
-
this._token = res.headers.get('x-fm-data-access-token')
|
|
103
|
-
resolve(this._token)
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
reject(new FMError(_res.messages[0].code, _res.status, res))
|
|
107
|
-
}
|
|
108
90
|
})
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
91
|
+
})
|
|
92
|
+
console.time()
|
|
93
|
+
let _res = <any>(await res.json())
|
|
94
|
+
if (res.status === 200) {
|
|
95
|
+
this._token = res.headers.get('x-fm-data-access-token')
|
|
96
|
+
return this._token
|
|
112
97
|
}
|
|
113
|
-
|
|
98
|
+
else {
|
|
99
|
+
throw new FMError(_res.messages[0].code, _res.status, res)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
114
102
|
}
|
|
115
103
|
|
|
116
104
|
get token() {
|
|
@@ -121,7 +109,7 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
121
109
|
return `${this.host.hostname}/fmi/data/v2/databases/${this.name}`
|
|
122
110
|
}
|
|
123
111
|
|
|
124
|
-
async apiRequest<T = any>(url: string | Request, options: any = {}, autoRelogin = true): Promise<T
|
|
112
|
+
async apiRequest<T = any>(url: string | Request, options: any = {}, autoRelogin = true): Promise<ApiResults<T>> {
|
|
125
113
|
if (!options.headers) options.headers = {}
|
|
126
114
|
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json"
|
|
127
115
|
options.headers["authorization"] = "Bearer " + this._token
|
|
@@ -134,14 +122,30 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
134
122
|
this.cookies[cookie_split[0]] = cookie_split[1]
|
|
135
123
|
}
|
|
136
124
|
}
|
|
137
|
-
let data = await _fetch.json() as
|
|
125
|
+
let data = await _fetch.json() as ApiResults<T>
|
|
126
|
+
|
|
127
|
+
// Remove response if it is empty. This makes checking for an empty response easier
|
|
128
|
+
if (Object.keys(data.response).length === 0) delete data.response
|
|
129
|
+
|
|
138
130
|
// console.log(data.messages[0])
|
|
139
|
-
if (data.messages[0].code
|
|
131
|
+
if (data.messages[0].code === "952" && autoRelogin) {
|
|
140
132
|
this._token = null
|
|
141
133
|
await this.login()
|
|
142
134
|
return await this.apiRequest(url, options, false)
|
|
143
135
|
}
|
|
144
|
-
|
|
136
|
+
else if (data.messages[0].code !== "0") {
|
|
137
|
+
throw new FMError(data.messages[0].code, _fetch.status, data)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
data.httpStatus = _fetch.status
|
|
141
|
+
return data
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async listLayouts() {
|
|
145
|
+
let req = await this.apiRequest<{layouts: ApiLayout[]}>(`${this.endpoint}/layouts`)
|
|
146
|
+
if (!req.response) throw new FMError(req.messages[0].code, req.httpStatus, req.messages[0].message)
|
|
147
|
+
|
|
148
|
+
return req.response.layouts.filter(i => !i.isFolder).map(layout => new Layout(this, layout.name))
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
getLayout<R extends string>(name: R): Layout<T["layouts"][R]>
|
|
@@ -150,25 +154,14 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
150
154
|
return new Layout<LayoutInterface>(this, name)
|
|
151
155
|
}
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
/*
|
|
158
|
+
@deprecated
|
|
159
|
+
*/
|
|
160
|
+
async setGlobals(globalFields) {
|
|
154
161
|
// console.log({globalFields})
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
body: JSON.stringify({globalFields})
|
|
159
|
-
}).then(res => {
|
|
160
|
-
// console.log(res)
|
|
161
|
-
if (res.messages[0].code === "0") {
|
|
162
|
-
resolve()
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
reject(
|
|
166
|
-
(res.messages[0].code, res.status, res))
|
|
167
|
-
}
|
|
168
|
-
})
|
|
169
|
-
.catch(e => {
|
|
170
|
-
reject(e)
|
|
171
|
-
})
|
|
162
|
+
await this.apiRequest(`${this.endpoint}/globals`, {
|
|
163
|
+
method: "PATCH",
|
|
164
|
+
body: JSON.stringify({globalFields})
|
|
172
165
|
})
|
|
173
166
|
}
|
|
174
167
|
|
|
@@ -180,15 +173,10 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
180
173
|
this.emit("token_expired")
|
|
181
174
|
}
|
|
182
175
|
|
|
183
|
-
|
|
176
|
+
streamURL(url: string): Promise<HTTP_REDIRECT.http.IncomingMessage> {
|
|
184
177
|
return new Promise((resolve, reject) => {
|
|
185
|
-
if (field.metadata.result !== "container") {
|
|
186
|
-
reject("Cannot stream the field " + field.id + " as it is not a container")
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
178
|
if (!url || typeof url !== "string") {
|
|
190
|
-
|
|
191
|
-
return
|
|
179
|
+
throw new Error("URL is empty, or has invalid value")
|
|
192
180
|
}
|
|
193
181
|
|
|
194
182
|
let headers = {}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { HostBase } from "./HostBase.js";
|
|
2
2
|
import { Request } from "node-fetch";
|
|
3
|
+
import { ApiResults } from "../models/apiResults";
|
|
4
|
+
import HTTP_REDIRECT from "follow-redirects";
|
|
3
5
|
export interface DatabaseBase {
|
|
4
6
|
host: HostBase;
|
|
5
7
|
readonly name: string;
|
|
6
8
|
endpoint: string;
|
|
7
|
-
apiRequest(url: string | Request, options?: any, autoRelogin?: boolean): Promise<
|
|
9
|
+
apiRequest<T = unknown>(url: string | Request, options?: any, autoRelogin?: boolean): Promise<ApiResults<T>>;
|
|
10
|
+
streamURL(url: string): Promise<HTTP_REDIRECT.http.IncomingMessage>;
|
|
8
11
|
}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
import {HostBase} from "./HostBase.js"
|
|
6
6
|
import {Request} from "node-fetch";
|
|
7
7
|
import {DatabaseStructure} from "../types";
|
|
8
|
+
import {ApiResults} from "../models/apiResults";
|
|
9
|
+
import HTTP_REDIRECT from "follow-redirects"
|
|
8
10
|
|
|
9
11
|
export interface DatabaseBase {
|
|
10
12
|
host: HostBase,
|
|
@@ -13,5 +15,6 @@ export interface DatabaseBase {
|
|
|
13
15
|
|
|
14
16
|
// layouts: DatabaseStructure["layouts"]
|
|
15
17
|
|
|
16
|
-
apiRequest(url: string | Request, options?: any, autoRelogin?: boolean): Promise<
|
|
18
|
+
apiRequest<T = unknown>(url: string | Request, options?: any, autoRelogin?: boolean): Promise<ApiResults<T>>
|
|
19
|
+
streamURL(url: string): Promise<HTTP_REDIRECT.http.IncomingMessage>
|
|
17
20
|
}
|
package/src/layouts/layout.d.ts
CHANGED
|
@@ -3,14 +3,14 @@ import { LayoutRecord } from "../records/layoutRecord.js";
|
|
|
3
3
|
import { Script, ScriptResult } from "../types.js";
|
|
4
4
|
import { LayoutInterface } from "./layoutInterface.js";
|
|
5
5
|
import { Find } from "../records/getOperations/find.js";
|
|
6
|
-
import { FMError } from "../FMError.js";
|
|
7
6
|
import { LayoutBase } from "./layoutBase.js";
|
|
8
7
|
import { DatabaseBase } from "../connection/databaseBase";
|
|
8
|
+
import { ApiLayoutMetadata } from "../models/apiResults";
|
|
9
9
|
export declare class Layout<T extends LayoutInterface> implements LayoutBase {
|
|
10
10
|
readonly database: DatabaseBase;
|
|
11
11
|
readonly records: LayoutRecordManager<T>;
|
|
12
12
|
readonly name: string;
|
|
13
|
-
metadata:
|
|
13
|
+
metadata: ApiLayoutMetadata;
|
|
14
14
|
constructor(database: DatabaseBase, name: string);
|
|
15
15
|
get endpoint(): string;
|
|
16
16
|
/**
|
|
@@ -26,5 +26,5 @@ export declare class Layout<T extends LayoutInterface> implements LayoutBase {
|
|
|
26
26
|
*/
|
|
27
27
|
newFind(): Find<T>;
|
|
28
28
|
runScript(script: Script): Promise<ScriptResult>;
|
|
29
|
-
getLayoutMeta(): Promise<
|
|
29
|
+
getLayoutMeta(): Promise<ApiLayoutMetadata>;
|
|
30
30
|
}
|
package/src/layouts/layout.js
CHANGED
|
@@ -40,45 +40,31 @@ export class Layout {
|
|
|
40
40
|
return this.records.find();
|
|
41
41
|
}
|
|
42
42
|
runScript(script) {
|
|
43
|
-
|
|
44
|
-
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
44
|
let url = `${this.endpoint}/script/${encodeURIComponent(script.name)}`;
|
|
46
45
|
if (script.parameter)
|
|
47
46
|
url += "?script.param=" + encodeURIComponent(script.parameter);
|
|
48
|
-
this.database.apiRequest(url, {
|
|
47
|
+
let res = yield this.database.apiRequest(url, {
|
|
49
48
|
port: 443,
|
|
50
49
|
method: "GET"
|
|
51
|
-
})
|
|
52
|
-
.then(res => {
|
|
53
|
-
if (res.messages[0].code === "0") {
|
|
54
|
-
let error = parseInt(res.response.scriptError);
|
|
55
|
-
let msg = {
|
|
56
|
-
scriptError: error ? new FMError(error, 200, res, trace) : undefined,
|
|
57
|
-
scriptResult: res.response.scriptResult
|
|
58
|
-
};
|
|
59
|
-
resolve(msg);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
// console.log(res)
|
|
63
|
-
reject(new FMError(res.messages[0].code, res.status, res, trace));
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
.catch(e => {
|
|
67
|
-
reject(e);
|
|
68
50
|
});
|
|
69
|
-
|
|
51
|
+
if (res.messages[0].code === "0") {
|
|
52
|
+
let error = parseInt(res.response.scriptError);
|
|
53
|
+
return {
|
|
54
|
+
scriptError: error ? new FMError(error, 200, res) : undefined,
|
|
55
|
+
scriptResult: res.response.scriptResult
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
});
|
|
70
59
|
}
|
|
71
60
|
getLayoutMeta() {
|
|
72
|
-
return
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
62
|
if (this.metadata) {
|
|
74
|
-
|
|
75
|
-
return;
|
|
63
|
+
return this.metadata;
|
|
76
64
|
}
|
|
77
|
-
this.database.apiRequest(this.endpoint)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
})
|
|
81
|
-
.catch(e => reject(e));
|
|
65
|
+
let res = yield this.database.apiRequest(this.endpoint);
|
|
66
|
+
this.metadata = res.response;
|
|
67
|
+
return this.metadata;
|
|
82
68
|
});
|
|
83
69
|
}
|
|
84
70
|
}
|