@jd-data-limited/easy-fm 3.2.7 → 4.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/README.md +36 -24
- package/package.json +15 -8
- package/src/FMError.d.ts +1 -1
- package/src/FMError.js +7 -2
- package/src/FMError.ts +3 -3
- package/src/connection/FMHost.d.ts +3 -2
- package/src/connection/FMHost.js +37 -47
- package/src/connection/FMHost.ts +6 -6
- package/src/connection/HostBase.d.ts +1 -1
- package/src/connection/HostBase.js +1 -1
- package/src/connection/HostBase.ts +2 -4
- package/src/connection/database.d.ts +12 -9
- package/src/connection/database.js +93 -116
- package/src/connection/database.ts +79 -90
- package/src/connection/databaseBase.d.ts +5 -2
- package/src/connection/databaseBase.js +1 -1
- package/src/connection/databaseBase.ts +5 -4
- package/src/databaseStructure.d.ts +6 -0
- package/src/databaseStructure.js +4 -0
- package/src/databaseStructure.ts +12 -0
- package/src/index.d.ts +3 -6
- package/src/index.js +3 -5
- package/src/index.ts +4 -9
- package/src/layouts/layout.d.ts +5 -19
- package/src/layouts/layout.js +27 -69
- package/src/layouts/layout.ts +26 -65
- package/src/layouts/layoutBase.d.ts +4 -4
- package/src/layouts/layoutBase.js +1 -1
- package/src/layouts/layoutBase.ts +5 -5
- package/src/layouts/layoutInterface.d.ts +1 -1
- package/src/layouts/layoutInterface.js +1 -1
- package/src/layouts/layoutInterface.ts +2 -2
- package/src/layouts/layoutRecordManager.d.ts +5 -6
- package/src/layouts/layoutRecordManager.js +20 -39
- package/src/layouts/layoutRecordManager.ts +20 -41
- package/src/layouts/recordFieldsMap.d.ts +2 -2
- package/src/layouts/recordFieldsMap.js +1 -1
- package/src/layouts/recordFieldsMap.ts +3 -3
- 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 -22
- package/src/records/field.js +4 -177
- package/src/records/field.ts +4 -187
- package/src/records/fieldBase.d.ts +30 -0
- package/src/records/fieldBase.js +154 -0
- package/src/records/fieldBase.ts +174 -0
- package/src/records/getOperations/recordGetOperation.d.ts +47 -11
- package/src/records/getOperations/recordGetOperation.js +144 -30
- package/src/records/getOperations/recordGetOperation.ts +172 -30
- package/src/records/layoutRecord.d.ts +8 -7
- package/src/records/layoutRecord.js +107 -153
- package/src/records/layoutRecord.ts +117 -141
- package/src/records/portal.d.ts +6 -5
- package/src/records/portal.js +4 -1
- package/src/records/portal.ts +7 -7
- package/src/records/portalBase.d.ts +5 -4
- package/src/records/portalBase.js +1 -1
- package/src/records/portalBase.ts +6 -6
- package/src/records/portalRecord.d.ts +6 -6
- package/src/records/portalRecord.js +5 -3
- package/src/records/portalRecord.ts +5 -5
- package/src/records/recordBase.d.ts +7 -12
- package/src/records/recordBase.js +12 -11
- package/src/records/recordBase.ts +10 -15
- package/src/types.d.ts +18 -19
- package/src/types.js +7 -1
- package/src/types.ts +20 -21
- 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/src/records/getOperations/find.d.ts +0 -15
- package/src/records/getOperations/find.js +0 -90
- package/src/records/getOperations/find.ts +0 -88
- package/src/records/getOperations/recordGetRange.d.ts +0 -13
- package/src/records/getOperations/recordGetRange.js +0 -95
- package/src/records/getOperations/recordGetRange.ts +0 -84
- package/src/records/portalRecordBase.d.ts +0 -4
- package/src/records/portalRecordBase.js +0 -6
- 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
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2023. See LICENSE file for more information
|
|
2
|
+
* Copyright (c) 2023-2024. See LICENSE file for more information
|
|
3
3
|
*/
|
|
4
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
7
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
8
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
|
-
});
|
|
12
|
-
};
|
|
13
4
|
import { EventEmitter } from "events";
|
|
14
|
-
import fetch from "node-fetch";
|
|
15
5
|
import { generateAuthorizationHeaders } from "./generateAuthorizationHeaders.js";
|
|
16
6
|
import { FMError } from "../FMError.js";
|
|
17
7
|
import { Layout } from "../layouts/layout.js";
|
|
18
|
-
import HTTP_REDIRECT from "follow-redirects";
|
|
8
|
+
import * as HTTP_REDIRECT from "follow-redirects";
|
|
19
9
|
export class Database extends EventEmitter {
|
|
10
|
+
_token;
|
|
11
|
+
host;
|
|
12
|
+
connection_details;
|
|
13
|
+
cookies = {};
|
|
14
|
+
name;
|
|
20
15
|
constructor(host, conn) {
|
|
21
16
|
super();
|
|
22
|
-
this.cookies = {};
|
|
23
17
|
this.host = host;
|
|
24
18
|
this.name = conn.database;
|
|
25
19
|
this.connection_details = conn;
|
|
@@ -37,66 +31,53 @@ export class Database extends EventEmitter {
|
|
|
37
31
|
throw "Not yet supported login method";
|
|
38
32
|
}
|
|
39
33
|
}
|
|
40
|
-
logout() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"content-type": "application/json"
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
let data = yield _fetch.json();
|
|
51
|
-
// console.log(data)
|
|
52
|
-
this._token = null;
|
|
53
|
-
resolve();
|
|
54
|
-
}));
|
|
55
|
-
}
|
|
56
|
-
login() {
|
|
57
|
-
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
-
// Reset cookies
|
|
59
|
-
this.cookies = {};
|
|
60
|
-
try {
|
|
61
|
-
yield this.host.getMetadata();
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
reject(e);
|
|
65
|
-
return;
|
|
34
|
+
async logout() {
|
|
35
|
+
if (!this.token)
|
|
36
|
+
throw new Error("Not logged in");
|
|
37
|
+
let _fetch = await fetch(`${this.endpoint}/sessions/${this.token}`, {
|
|
38
|
+
method: "DELETE",
|
|
39
|
+
headers: {
|
|
40
|
+
"content-type": "application/json"
|
|
66
41
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
42
|
+
});
|
|
43
|
+
let data = await _fetch.json();
|
|
44
|
+
// console.log(data)
|
|
45
|
+
this._token = null;
|
|
46
|
+
}
|
|
47
|
+
async login() {
|
|
48
|
+
// Reset cookies
|
|
49
|
+
this.cookies = {};
|
|
50
|
+
await this.host.getMetadata();
|
|
51
|
+
if (this.token)
|
|
52
|
+
throw new Error("Already logged in. Run logout() first");
|
|
53
|
+
if (this.connection_details.credentials.method === "token") {
|
|
54
|
+
this._token = this.connection_details.credentials.token;
|
|
55
|
+
return this.token;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.time();
|
|
59
|
+
let url = new URL(`${this.endpoint}/sessions`);
|
|
60
|
+
url.hostname = this.host.hostname;
|
|
61
|
+
let res = await fetch(url, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: generateAuthorizationHeaders(this.connection_details.credentials),
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
fmDataSource: this.connection_details.externalSources.map(i => {
|
|
66
|
+
let _i = i;
|
|
67
|
+
return this.generateExternalSourceLogin(_i);
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
console.time();
|
|
72
|
+
let _res = (await res.json());
|
|
73
|
+
if (res.status === 200) {
|
|
74
|
+
this._token = res.headers.get('x-fm-data-access-token');
|
|
75
|
+
return this._token;
|
|
72
76
|
}
|
|
73
77
|
else {
|
|
74
|
-
|
|
75
|
-
hostname: this.host.hostname,
|
|
76
|
-
port: 443,
|
|
77
|
-
method: "POST",
|
|
78
|
-
headers: generateAuthorizationHeaders(this.connection_details.credentials),
|
|
79
|
-
body: JSON.stringify({
|
|
80
|
-
fmDataSource: this.connection_details.externalSources.map(i => {
|
|
81
|
-
let _i = i;
|
|
82
|
-
return this.generateExternalSourceLogin(_i);
|
|
83
|
-
})
|
|
84
|
-
})
|
|
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
|
-
});
|
|
78
|
+
throw new FMError(_res.messages[0].code, _res.status, res);
|
|
98
79
|
}
|
|
99
|
-
}
|
|
80
|
+
}
|
|
100
81
|
}
|
|
101
82
|
get token() {
|
|
102
83
|
return this._token;
|
|
@@ -104,51 +85,52 @@ export class Database extends EventEmitter {
|
|
|
104
85
|
get endpoint() {
|
|
105
86
|
return `${this.host.hostname}/fmi/data/v2/databases/${this.name}`;
|
|
106
87
|
}
|
|
107
|
-
apiRequest(url, options = {}, autoRelogin = true) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.cookies[cookie_split[0]] = cookie_split[1];
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
let data = yield _fetch.json();
|
|
122
|
-
// console.log(data.messages[0])
|
|
123
|
-
if (data.messages[0].code == 952 && autoRelogin) {
|
|
124
|
-
this._token = null;
|
|
125
|
-
yield this.login();
|
|
126
|
-
return yield this.apiRequest(url, options, false);
|
|
88
|
+
async apiRequest(url, options = {}, autoRelogin = true) {
|
|
89
|
+
if (!options.headers)
|
|
90
|
+
options.headers = {};
|
|
91
|
+
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json";
|
|
92
|
+
options.headers["authorization"] = "Bearer " + this._token;
|
|
93
|
+
options.rejectUnauthorized = this.host.verify;
|
|
94
|
+
let _fetch = await fetch(url, options);
|
|
95
|
+
if (_fetch.headers.get('set-cookie')) {
|
|
96
|
+
for (let cookie of _fetch.headers.get('set-cookie')) {
|
|
97
|
+
let cookie_split = cookie.split("=");
|
|
98
|
+
this.cookies[cookie_split[0]] = cookie_split[1];
|
|
127
99
|
}
|
|
128
|
-
|
|
129
|
-
|
|
100
|
+
}
|
|
101
|
+
let data = await _fetch.json();
|
|
102
|
+
// Remove response if it is empty. This makes checking for an empty response easier
|
|
103
|
+
if (Object.keys(data.response).length === 0)
|
|
104
|
+
delete data.response;
|
|
105
|
+
// console.log(data.messages[0])
|
|
106
|
+
if (data.messages[0].code === "952" && autoRelogin) {
|
|
107
|
+
this._token = null;
|
|
108
|
+
await this.login();
|
|
109
|
+
return await this.apiRequest(url, options, false);
|
|
110
|
+
}
|
|
111
|
+
else if (data.messages[0].code !== "0") {
|
|
112
|
+
throw new FMError(data.messages[0].code, _fetch.status, data);
|
|
113
|
+
}
|
|
114
|
+
data.httpStatus = _fetch.status;
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
async listLayouts() {
|
|
118
|
+
let req = await this.apiRequest(`${this.endpoint}/layouts`);
|
|
119
|
+
if (!req.response)
|
|
120
|
+
throw new FMError(req.messages[0].code, req.httpStatus, req.messages[0].message);
|
|
121
|
+
return req.response.layouts.filter(i => !i.isFolder).map(layout => new Layout(this, layout.name));
|
|
130
122
|
}
|
|
131
123
|
getLayout(name) {
|
|
132
124
|
return new Layout(this, name);
|
|
133
125
|
}
|
|
134
|
-
|
|
126
|
+
/*
|
|
127
|
+
@deprecated
|
|
128
|
+
*/
|
|
129
|
+
async setGlobals(globalFields) {
|
|
135
130
|
// console.log({globalFields})
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
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
|
-
});
|
|
131
|
+
await this.apiRequest(`${this.endpoint}/globals`, {
|
|
132
|
+
method: "PATCH",
|
|
133
|
+
body: JSON.stringify({ globalFields })
|
|
152
134
|
});
|
|
153
135
|
}
|
|
154
136
|
script(name, parameter = "") {
|
|
@@ -157,15 +139,10 @@ export class Database extends EventEmitter {
|
|
|
157
139
|
_tokenExpired() {
|
|
158
140
|
this.emit("token_expired");
|
|
159
141
|
}
|
|
160
|
-
|
|
142
|
+
streamURL(url) {
|
|
161
143
|
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
144
|
if (!url || typeof url !== "string") {
|
|
167
|
-
|
|
168
|
-
return;
|
|
145
|
+
throw new Error("URL is empty, or has invalid value");
|
|
169
146
|
}
|
|
170
147
|
let headers = {};
|
|
171
148
|
if (Object.keys(this.cookies).length !== 0) {
|
|
@@ -188,7 +165,7 @@ export class Database extends EventEmitter {
|
|
|
188
165
|
// Automatically switch between the http and https modules, based on which is needed
|
|
189
166
|
(url.startsWith("https") ? HTTP_REDIRECT.https : HTTP_REDIRECT.http).get(url, {
|
|
190
167
|
headers,
|
|
191
|
-
beforeRedirect: (options, res
|
|
168
|
+
beforeRedirect: (options, res) => check_for_cookies(res)
|
|
192
169
|
}, (res) => {
|
|
193
170
|
check_for_cookies(res);
|
|
194
171
|
resolve(res);
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2023. See LICENSE file for more information
|
|
2
|
+
* Copyright (c) 2023-2024. See LICENSE file for more information
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {EventEmitter} from "events";
|
|
6
|
-
import fetch, {HeadersInit, Request} from "node-fetch";
|
|
7
6
|
import {generateAuthorizationHeaders} from "./generateAuthorizationHeaders.js";
|
|
8
7
|
import {FMError} from "../FMError.js";
|
|
9
8
|
import {LayoutInterface} from "../layouts/layoutInterface.js";
|
|
10
9
|
import {Layout} from "../layouts/layout.js";
|
|
11
|
-
import HTTP_REDIRECT
|
|
10
|
+
import * as HTTP_REDIRECT from "follow-redirects"
|
|
12
11
|
import {
|
|
13
12
|
databaseOptionsBase,
|
|
14
|
-
databaseOptionsWithExternalSources,
|
|
15
|
-
fileMakerResponse,
|
|
13
|
+
databaseOptionsWithExternalSources,
|
|
16
14
|
loginOptionsFileMaker,
|
|
17
15
|
loginOptionsToken,
|
|
18
16
|
Script
|
|
19
17
|
} from "../types.js";
|
|
20
18
|
import {HostBase} from "./HostBase.js"
|
|
21
|
-
import {DatabaseBase} from "./databaseBase";
|
|
19
|
+
import {DatabaseBase} from "./databaseBase.js";
|
|
20
|
+
import {ApiLayout, ApiResults} from "../models/apiResults.js";
|
|
21
|
+
import {DatabaseStructure} from "../databaseStructure.js";
|
|
22
|
+
import {IncomingMessage} from "http";
|
|
22
23
|
|
|
23
24
|
type GetLayoutReturnType<T extends DatabaseStructure, R extends LayoutInterface | string> = R extends string ? T["layouts"][R] : R
|
|
24
25
|
|
|
@@ -50,67 +51,55 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
logout(): Promise<void> {
|
|
54
|
-
|
|
55
|
-
if (!this.token) reject(new Error("Not logged in"))
|
|
54
|
+
async logout(): Promise<void> {
|
|
55
|
+
if (!this.token) throw new Error("Not logged in")
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
})
|
|
63
|
-
let data = await _fetch.json()
|
|
64
|
-
// console.log(data)
|
|
65
|
-
this._token = null
|
|
66
|
-
resolve()
|
|
57
|
+
let _fetch = await fetch(`${this.endpoint}/sessions/${this.token}`, {
|
|
58
|
+
method: "DELETE",
|
|
59
|
+
headers: {
|
|
60
|
+
"content-type": "application/json"
|
|
61
|
+
}
|
|
67
62
|
})
|
|
63
|
+
let data = await _fetch.json()
|
|
64
|
+
// console.log(data)
|
|
65
|
+
this._token = null
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
login() {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.cookies = {}
|
|
68
|
+
async login() {
|
|
69
|
+
// Reset cookies
|
|
70
|
+
this.cookies = {}
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} catch (e) {
|
|
78
|
-
reject(e)
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
if (this.token) throw new Error("Already logged in. Run logout() first")
|
|
72
|
+
await this.host.getMetadata()
|
|
73
|
+
if (this.token) throw new Error("Already logged in. Run logout() first")
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
75
|
+
if (this.connection_details.credentials.method === "token") {
|
|
76
|
+
this._token = (<loginOptionsToken>this.connection_details.credentials).token
|
|
77
|
+
return this.token
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.time()
|
|
81
|
+
let url = new URL(`${this.endpoint}/sessions`)
|
|
82
|
+
url.hostname = this.host.hostname
|
|
83
|
+
let res = await fetch(url, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: generateAuthorizationHeaders(this.connection_details.credentials) as unknown as HeadersInit,
|
|
86
|
+
body: JSON.stringify({
|
|
87
|
+
fmDataSource: this.connection_details.externalSources.map(i => {
|
|
88
|
+
let _i = <databaseOptionsBase>i
|
|
89
|
+
return this.generateExternalSourceLogin(_i)
|
|
98
90
|
})
|
|
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
91
|
})
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
})
|
|
93
|
+
console.time()
|
|
94
|
+
let _res = <any>(await res.json())
|
|
95
|
+
if (res.status === 200) {
|
|
96
|
+
this._token = res.headers.get('x-fm-data-access-token')
|
|
97
|
+
return this._token
|
|
112
98
|
}
|
|
113
|
-
|
|
99
|
+
else {
|
|
100
|
+
throw new FMError(_res.messages[0].code, _res.status, res)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
114
103
|
}
|
|
115
104
|
|
|
116
105
|
get token() {
|
|
@@ -121,7 +110,7 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
121
110
|
return `${this.host.hostname}/fmi/data/v2/databases/${this.name}`
|
|
122
111
|
}
|
|
123
112
|
|
|
124
|
-
async apiRequest<T = any>(url: string | Request, options: any = {}, autoRelogin = true): Promise<T
|
|
113
|
+
async apiRequest<T = any>(url: string | Request, options: any = {}, autoRelogin = true): Promise<ApiResults<T>> {
|
|
125
114
|
if (!options.headers) options.headers = {}
|
|
126
115
|
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json"
|
|
127
116
|
options.headers["authorization"] = "Bearer " + this._token
|
|
@@ -134,41 +123,46 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
134
123
|
this.cookies[cookie_split[0]] = cookie_split[1]
|
|
135
124
|
}
|
|
136
125
|
}
|
|
137
|
-
let data = await _fetch.json() as
|
|
126
|
+
let data = await _fetch.json() as ApiResults<T>
|
|
127
|
+
|
|
128
|
+
// Remove response if it is empty. This makes checking for an empty response easier
|
|
129
|
+
if (Object.keys(data.response).length === 0) delete data.response
|
|
130
|
+
|
|
138
131
|
// console.log(data.messages[0])
|
|
139
|
-
if (data.messages[0].code
|
|
132
|
+
if (data.messages[0].code === "952" && autoRelogin) {
|
|
140
133
|
this._token = null
|
|
141
134
|
await this.login()
|
|
142
135
|
return await this.apiRequest(url, options, false)
|
|
143
136
|
}
|
|
144
|
-
|
|
137
|
+
else if (data.messages[0].code !== "0") {
|
|
138
|
+
throw new FMError(data.messages[0].code, _fetch.status, data)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
data.httpStatus = _fetch.status
|
|
142
|
+
return data
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
|
|
145
|
+
async listLayouts() {
|
|
146
|
+
let req = await this.apiRequest<{layouts: ApiLayout[]}>(`${this.endpoint}/layouts`)
|
|
147
|
+
if (!req.response) throw new FMError(req.messages[0].code, req.httpStatus, req.messages[0].message)
|
|
148
|
+
|
|
149
|
+
return req.response.layouts.filter(i => !i.isFolder).map(layout => new Layout(this, layout.name))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
getLayout<R extends keyof T["layouts"]>(name: R): Layout<T["layouts"][R]>
|
|
148
153
|
getLayout<R extends LayoutInterface>(name: string): Layout<R>
|
|
149
|
-
getLayout(name: string): Layout<
|
|
154
|
+
getLayout(name: string): Layout<any> {
|
|
150
155
|
return new Layout<LayoutInterface>(this, name)
|
|
151
156
|
}
|
|
152
157
|
|
|
153
|
-
|
|
158
|
+
/*
|
|
159
|
+
@deprecated
|
|
160
|
+
*/
|
|
161
|
+
async setGlobals(globalFields) {
|
|
154
162
|
// 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
|
-
})
|
|
163
|
+
await this.apiRequest(`${this.endpoint}/globals`, {
|
|
164
|
+
method: "PATCH",
|
|
165
|
+
body: JSON.stringify({globalFields})
|
|
172
166
|
})
|
|
173
167
|
}
|
|
174
168
|
|
|
@@ -180,15 +174,10 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
180
174
|
this.emit("token_expired")
|
|
181
175
|
}
|
|
182
176
|
|
|
183
|
-
|
|
177
|
+
streamURL(url: string): Promise<IncomingMessage> {
|
|
184
178
|
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
179
|
if (!url || typeof url !== "string") {
|
|
190
|
-
|
|
191
|
-
return
|
|
180
|
+
throw new Error("URL is empty, or has invalid value")
|
|
192
181
|
}
|
|
193
182
|
|
|
194
183
|
let headers = {}
|
|
@@ -214,7 +203,7 @@ export class Database<T extends DatabaseStructure> extends EventEmitter implemen
|
|
|
214
203
|
// Automatically switch between the http and https modules, based on which is needed
|
|
215
204
|
(url.startsWith("https") ? HTTP_REDIRECT.https : HTTP_REDIRECT.http).get(url, {
|
|
216
205
|
headers,
|
|
217
|
-
beforeRedirect: (options, res
|
|
206
|
+
beforeRedirect: (options, res) => check_for_cookies(res)
|
|
218
207
|
}, (res) => {
|
|
219
208
|
check_for_cookies(res)
|
|
220
209
|
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
1
2
|
import { HostBase } from "./HostBase.js";
|
|
2
|
-
import {
|
|
3
|
+
import { ApiResults } from "../models/apiResults.js";
|
|
4
|
+
import { IncomingMessage } from "http";
|
|
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<IncomingMessage>;
|
|
8
11
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2023. See LICENSE file for more information
|
|
2
|
+
* Copyright (c) 2023-2024. See LICENSE file for more information
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {HostBase} from "./HostBase.js"
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import {ApiResults} from "../models/apiResults.js";
|
|
7
|
+
import {IncomingMessage} from "http";
|
|
8
8
|
|
|
9
9
|
export interface DatabaseBase {
|
|
10
10
|
host: HostBase,
|
|
@@ -13,5 +13,6 @@ export interface DatabaseBase {
|
|
|
13
13
|
|
|
14
14
|
// layouts: DatabaseStructure["layouts"]
|
|
15
15
|
|
|
16
|
-
apiRequest(url: string | Request, options?: any, autoRelogin?: boolean): Promise<
|
|
16
|
+
apiRequest<T = unknown>(url: string | Request, options?: any, autoRelogin?: boolean): Promise<ApiResults<T>>
|
|
17
|
+
streamURL(url: string): Promise<IncomingMessage>
|
|
17
18
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024. See LICENSE file for more information
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// import * as btoa from "btoa";
|
|
6
|
+
import {LayoutInterface} from "./layouts/layoutInterface.js";
|
|
7
|
+
|
|
8
|
+
export interface DatabaseStructure {
|
|
9
|
+
layouts: {
|
|
10
|
+
[key: string]: LayoutInterface
|
|
11
|
+
}
|
|
12
|
+
}
|
package/src/index.d.ts
CHANGED
|
@@ -8,12 +8,9 @@ import { LayoutRecord } from "./records/layoutRecord.js";
|
|
|
8
8
|
import { LayoutInterface, PortalInterface } from "./layouts/layoutInterface.js";
|
|
9
9
|
import { PortalRecord } from "./records/portalRecord.js";
|
|
10
10
|
import { Portal } from "./records/portal.js";
|
|
11
|
-
import {
|
|
12
|
-
import { Find } from "./records/getOperations/find.js";
|
|
11
|
+
import { Container, FieldBase } from "./records/fieldBase.js";
|
|
13
12
|
import { RecordGetOperation } from "./records/getOperations/recordGetOperation.js";
|
|
14
|
-
import { RecordGetRange } from "./records/getOperations/recordGetRange.js";
|
|
15
13
|
import { LayoutRecordManager } from "./layouts/layoutRecordManager.js";
|
|
16
|
-
import { RecordFieldsMap } from "./layouts/recordFieldsMap";
|
|
17
|
-
import { Container } from "./records/field.js";
|
|
14
|
+
import { RecordFieldsMap } from "./layouts/recordFieldsMap.js";
|
|
18
15
|
export default FMHost;
|
|
19
|
-
export { FMError, TYPES, Database, Layout, RecordBase, LayoutRecord, LayoutInterface, RecordFieldsMap, PortalInterface, PortalRecord, Portal,
|
|
16
|
+
export { FMError, TYPES, Database, Layout, RecordBase, LayoutRecord, LayoutInterface, RecordFieldsMap, PortalInterface, PortalRecord, Portal, FieldBase, RecordGetOperation, LayoutRecordManager, Container };
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2023. See LICENSE file for more information
|
|
2
|
+
* Copyright (c) 2023-2024. See LICENSE file for more information
|
|
3
3
|
*/
|
|
4
4
|
import FMHost from "./connection/FMHost.js";
|
|
5
5
|
import { FMError } from "./FMError.js";
|
|
@@ -10,10 +10,8 @@ import { RecordBase } from "./records/recordBase.js";
|
|
|
10
10
|
import { LayoutRecord } from "./records/layoutRecord.js";
|
|
11
11
|
import { PortalRecord } from "./records/portalRecord.js";
|
|
12
12
|
import { Portal } from "./records/portal.js";
|
|
13
|
-
import {
|
|
14
|
-
import { Find } from "./records/getOperations/find.js";
|
|
13
|
+
import { FieldBase } from "./records/fieldBase.js";
|
|
15
14
|
import { RecordGetOperation } from "./records/getOperations/recordGetOperation.js";
|
|
16
|
-
import { RecordGetRange } from "./records/getOperations/recordGetRange.js";
|
|
17
15
|
import { LayoutRecordManager } from "./layouts/layoutRecordManager.js";
|
|
18
16
|
export default FMHost;
|
|
19
|
-
export { FMError, TYPES, Database, Layout, RecordBase, LayoutRecord, PortalRecord, Portal,
|
|
17
|
+
export { FMError, TYPES, Database, Layout, RecordBase, LayoutRecord, PortalRecord, Portal, FieldBase, RecordGetOperation, LayoutRecordManager };
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2023. See LICENSE file for more information
|
|
2
|
+
* Copyright (c) 2023-2024. See LICENSE file for more information
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import FMHost from "./connection/FMHost.js";
|
|
@@ -12,13 +12,10 @@ import {LayoutRecord} from "./records/layoutRecord.js";
|
|
|
12
12
|
import {LayoutInterface, PortalInterface} from "./layouts/layoutInterface.js";
|
|
13
13
|
import {PortalRecord} from "./records/portalRecord.js";
|
|
14
14
|
import {Portal} from "./records/portal.js";
|
|
15
|
-
import {
|
|
16
|
-
import {Find} from "./records/getOperations/find.js";
|
|
15
|
+
import {Container, FieldBase} from "./records/fieldBase.js";
|
|
17
16
|
import {RecordGetOperation} from "./records/getOperations/recordGetOperation.js";
|
|
18
|
-
import {RecordGetRange} from "./records/getOperations/recordGetRange.js";
|
|
19
17
|
import {LayoutRecordManager} from "./layouts/layoutRecordManager.js";
|
|
20
|
-
import {RecordFieldsMap} from "./layouts/recordFieldsMap";
|
|
21
|
-
import {Container} from "./records/field.js";
|
|
18
|
+
import {RecordFieldsMap} from "./layouts/recordFieldsMap.js";
|
|
22
19
|
|
|
23
20
|
export default FMHost
|
|
24
21
|
export {
|
|
@@ -33,10 +30,8 @@ export {
|
|
|
33
30
|
PortalInterface,
|
|
34
31
|
PortalRecord,
|
|
35
32
|
Portal,
|
|
36
|
-
|
|
37
|
-
Find,
|
|
33
|
+
FieldBase,
|
|
38
34
|
RecordGetOperation,
|
|
39
|
-
RecordGetRange,
|
|
40
35
|
LayoutRecordManager,
|
|
41
36
|
Container
|
|
42
37
|
}
|