@jd-data-limited/easy-fm 1.0.2-alpha2 → 1.0.2-alpha4
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/index.js +69 -75
- package/index.ts +20 -20
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -23,34 +23,17 @@ import * as https from "https";
|
|
|
23
23
|
// @ts-ignore
|
|
24
24
|
const errs = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'fmErrors.json')).toString());
|
|
25
25
|
class database {
|
|
26
|
-
constructor(
|
|
27
|
-
this.props = props;
|
|
28
|
-
this.name = this.props.database;
|
|
29
|
-
if (host)
|
|
30
|
-
this.host = host;
|
|
31
|
-
}
|
|
26
|
+
constructor() { }
|
|
32
27
|
get token() {
|
|
33
28
|
return this.host.token;
|
|
34
29
|
}
|
|
35
30
|
getLayout(name) {
|
|
36
31
|
return new layout(this, name);
|
|
37
32
|
}
|
|
38
|
-
apiRequest(url, options = {}) {
|
|
39
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
if (!options.headers)
|
|
41
|
-
options.headers = {};
|
|
42
|
-
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json";
|
|
43
|
-
options.headers["authorization"] = "Bearer " + this.host.token;
|
|
44
|
-
options.rejectUnauthorized = this.host.rejectUnauthroized;
|
|
45
|
-
let _fetch = yield fetch(url, options);
|
|
46
|
-
let data = yield _fetch.json();
|
|
47
|
-
return data;
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
33
|
setGlobals(globalFields) {
|
|
51
34
|
// console.log({globalFields})
|
|
52
35
|
return new Promise((resolve, reject) => {
|
|
53
|
-
this.apiRequest(`${this.endpoint}/globals`, {
|
|
36
|
+
this.host.apiRequest(`${this.endpoint}/globals`, {
|
|
54
37
|
method: "PATCH",
|
|
55
38
|
body: JSON.stringify({ globalFields })
|
|
56
39
|
}).then(res => {
|
|
@@ -71,42 +54,29 @@ class database {
|
|
|
71
54
|
return { name, parameter };
|
|
72
55
|
}
|
|
73
56
|
get endpoint() {
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
throw "Token logins cannot be used for connecting to external sources. Please either use no login method, or open a second connection.";
|
|
91
|
-
case "oauth":
|
|
92
|
-
out.oauthRequestId = this.props.oauth.requestId;
|
|
93
|
-
out.oauthIdentifier = this.props.oauth.requestIdentifier;
|
|
94
|
-
case "claris":
|
|
95
|
-
throw "Claris logins cannot be used for connecting to external sources. Please either use no login method, or open a second connection.";
|
|
57
|
+
return `${this.host.endpoint}/${encodeURI(this.name)}`;
|
|
58
|
+
}
|
|
59
|
+
pairHost(db, details, returnConDetails = true) {
|
|
60
|
+
this.host = db;
|
|
61
|
+
this.name = details.database;
|
|
62
|
+
if (returnConDetails) {
|
|
63
|
+
if (details.method === "filemaker") {
|
|
64
|
+
return {
|
|
65
|
+
database: this.name,
|
|
66
|
+
username: details.username,
|
|
67
|
+
password: details.password
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
throw `Authentication method used for '${this.name}' is not supported for external data source connections`;
|
|
72
|
+
}
|
|
96
73
|
}
|
|
97
|
-
return out;
|
|
98
74
|
}
|
|
99
75
|
}
|
|
100
|
-
export default class FileMakerConnection
|
|
101
|
-
constructor(conn,
|
|
102
|
-
super(conn.database);
|
|
103
|
-
this.host = this;
|
|
76
|
+
export default class FileMakerConnection {
|
|
77
|
+
constructor(conn, rejectUnauthorized = true) {
|
|
104
78
|
this.hostname = conn.hostname;
|
|
105
|
-
this.
|
|
106
|
-
let e = new database(i, this);
|
|
107
|
-
e.external = true;
|
|
108
|
-
return e;
|
|
109
|
-
});
|
|
79
|
+
this.databaseConDetails = conn.databases;
|
|
110
80
|
this.rejectUnauthroized = rejectUnauthorized;
|
|
111
81
|
}
|
|
112
82
|
logout() {
|
|
@@ -122,7 +92,6 @@ export default class FileMakerConnection extends database {
|
|
|
122
92
|
let data = yield _fetch.json();
|
|
123
93
|
// console.log(data)
|
|
124
94
|
this._token = null;
|
|
125
|
-
this.name = null;
|
|
126
95
|
this.hostname = null;
|
|
127
96
|
resolve();
|
|
128
97
|
}));
|
|
@@ -131,17 +100,25 @@ export default class FileMakerConnection extends database {
|
|
|
131
100
|
return new Promise((resolve, reject) => {
|
|
132
101
|
if (this.token)
|
|
133
102
|
throw new Error("Already logged in. Run logout() first");
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
103
|
+
this.databases = [new database()];
|
|
104
|
+
this.databases[0].pairHost(this, this.databaseConDetails[0], false);
|
|
105
|
+
let external_sources_cons = this.databaseConDetails.slice(1).map(con => {
|
|
106
|
+
let db = new database();
|
|
107
|
+
this.databases.push(db);
|
|
108
|
+
return db.pairHost(this, con);
|
|
109
|
+
});
|
|
110
|
+
if (this.databaseConDetails[0].method === "filemaker") {
|
|
137
111
|
fetch(`${this.endpoint}/sessions`, {
|
|
138
112
|
hostname: this.hostname,
|
|
139
113
|
port: 443,
|
|
140
114
|
method: "POST",
|
|
141
115
|
headers: {
|
|
142
116
|
"Content-Type": "application/json",
|
|
143
|
-
"Authorization": "Basic " + Buffer.from(this.username + ":" + this.
|
|
144
|
-
}
|
|
117
|
+
"Authorization": "Basic " + Buffer.from(this.databaseConDetails[0].username + ":" + this.databaseConDetails[0].password).toString("base64")
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify({
|
|
120
|
+
fmDataSource: external_sources_cons
|
|
121
|
+
})
|
|
145
122
|
}).then((res) => __awaiter(this, void 0, void 0, function* () {
|
|
146
123
|
if (res.status === 200) {
|
|
147
124
|
this._token = res.headers.get('x-fm-data-access-token');
|
|
@@ -156,21 +133,21 @@ export default class FileMakerConnection extends database {
|
|
|
156
133
|
reject(e);
|
|
157
134
|
});
|
|
158
135
|
}
|
|
159
|
-
else if (this.
|
|
160
|
-
this._token = this.
|
|
161
|
-
this.name = this.props.database;
|
|
136
|
+
else if (this.databaseConDetails[0].method === "token") {
|
|
137
|
+
this._token = this.databaseConDetails[0].token;
|
|
162
138
|
resolve(this.token);
|
|
163
139
|
}
|
|
164
|
-
else if (this.
|
|
165
|
-
this.name = this.props.database;
|
|
140
|
+
else if (this.databaseConDetails[0].method === "oauth") {
|
|
166
141
|
fetch(`${this.endpoint}/sessions`, {
|
|
167
142
|
method: "POST",
|
|
168
143
|
headers: {
|
|
169
144
|
"Content-Type": "application/json",
|
|
170
|
-
"X-FM-Data-OAuth-RequestId": this.
|
|
171
|
-
"X-FM-Data-OAuth-Identifier": this.
|
|
145
|
+
"X-FM-Data-OAuth-RequestId": this.databaseConDetails[0].oauth.requestId,
|
|
146
|
+
"X-FM-Data-OAuth-Identifier": this.databaseConDetails[0].oauth.requestIdentifier
|
|
172
147
|
},
|
|
173
|
-
body: "{}"
|
|
148
|
+
body: external_sources_cons.length === 0 ? "{}" : JSON.stringify({
|
|
149
|
+
fmDataSource: external_sources_cons
|
|
150
|
+
})
|
|
174
151
|
})
|
|
175
152
|
.then(res => res.json())
|
|
176
153
|
.then(res => {
|
|
@@ -179,13 +156,12 @@ export default class FileMakerConnection extends database {
|
|
|
179
156
|
resolve(this.token);
|
|
180
157
|
});
|
|
181
158
|
}
|
|
182
|
-
else if (this.
|
|
183
|
-
this.name = this.props.database;
|
|
159
|
+
else if (this.databaseConDetails[0].method === "claris") {
|
|
184
160
|
fetch(`${this.endpoint}/sessions`, {
|
|
185
161
|
method: "POST",
|
|
186
162
|
headers: {
|
|
187
163
|
"Content-Type": "application/json",
|
|
188
|
-
"Authorization": this.
|
|
164
|
+
"Authorization": this.databaseConDetails[0].claris.fmid,
|
|
189
165
|
},
|
|
190
166
|
body: "{}"
|
|
191
167
|
})
|
|
@@ -198,9 +174,27 @@ export default class FileMakerConnection extends database {
|
|
|
198
174
|
}
|
|
199
175
|
});
|
|
200
176
|
}
|
|
177
|
+
getDatabase(database_name) {
|
|
178
|
+
return this.databases.find(db => db.name === database_name);
|
|
179
|
+
}
|
|
201
180
|
get token() {
|
|
202
181
|
return this._token;
|
|
203
182
|
}
|
|
183
|
+
get endpoint() {
|
|
184
|
+
return `https://${this.hostname}/fmi/data/v2/databases/`;
|
|
185
|
+
}
|
|
186
|
+
apiRequest(url, options = {}) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
if (!options.headers)
|
|
189
|
+
options.headers = {};
|
|
190
|
+
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json";
|
|
191
|
+
options.headers["authorization"] = "Bearer " + this._token;
|
|
192
|
+
options.rejectUnauthorized = this.rejectUnauthroized;
|
|
193
|
+
let _fetch = yield fetch(url, options);
|
|
194
|
+
let data = yield _fetch.json();
|
|
195
|
+
return data;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
204
198
|
}
|
|
205
199
|
class layout {
|
|
206
200
|
constructor(database, name) {
|
|
@@ -236,7 +230,7 @@ class layout {
|
|
|
236
230
|
let url = `${this.endpoint}/script/${encodeURI(script.name)}`;
|
|
237
231
|
if (script.parameter)
|
|
238
232
|
url += "?" + encodeURI(script.parameter);
|
|
239
|
-
this.database.apiRequest(url, {
|
|
233
|
+
this.database.host.apiRequest(url, {
|
|
240
234
|
port: 443,
|
|
241
235
|
method: "GET"
|
|
242
236
|
})
|
|
@@ -256,7 +250,7 @@ class layout {
|
|
|
256
250
|
}
|
|
257
251
|
getLayoutMeta() {
|
|
258
252
|
return new Promise((resolve, reject) => {
|
|
259
|
-
this.database.apiRequest(this.endpoint).then(res => {
|
|
253
|
+
this.database.host.apiRequest(this.endpoint).then(res => {
|
|
260
254
|
this.metadata = res.response;
|
|
261
255
|
resolve(this);
|
|
262
256
|
})
|
|
@@ -308,7 +302,7 @@ class record extends EventEmitter {
|
|
|
308
302
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
309
303
|
if (!this.layout.metadata)
|
|
310
304
|
yield this.layout.getLayoutMeta();
|
|
311
|
-
this.layout.database.apiRequest(this.endpoint, {
|
|
305
|
+
this.layout.database.host.apiRequest(this.endpoint, {
|
|
312
306
|
port: 443,
|
|
313
307
|
method: "GET"
|
|
314
308
|
})
|
|
@@ -341,7 +335,7 @@ class record extends EventEmitter {
|
|
|
341
335
|
if (this.recordId === -1) {
|
|
342
336
|
// This is a new record
|
|
343
337
|
extraBody.fieldData = data.fieldData;
|
|
344
|
-
this.layout.database.apiRequest(`${this.layout.endpoint}/records`, {
|
|
338
|
+
this.layout.database.host.apiRequest(`${this.layout.endpoint}/records`, {
|
|
345
339
|
port: 443,
|
|
346
340
|
method: "POST",
|
|
347
341
|
body: JSON.stringify(extraBody)
|
|
@@ -367,7 +361,7 @@ class record extends EventEmitter {
|
|
|
367
361
|
}
|
|
368
362
|
for (let item of Object.keys(extraBody))
|
|
369
363
|
data[item] = extraBody[item];
|
|
370
|
-
this.layout.database.apiRequest(this.endpoint, {
|
|
364
|
+
this.layout.database.host.apiRequest(this.endpoint, {
|
|
371
365
|
port: 443,
|
|
372
366
|
method: "PATCH",
|
|
373
367
|
body: JSON.stringify(data)
|
|
@@ -574,7 +568,7 @@ class recordGetRange extends recordGetOperation {
|
|
|
574
568
|
run() {
|
|
575
569
|
return new Promise((resolve, reject) => {
|
|
576
570
|
// console.log(this.#toObject())
|
|
577
|
-
this.layout.database.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
|
|
571
|
+
this.layout.database.host.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
|
|
578
572
|
method: "GET"
|
|
579
573
|
}).then((res) => __awaiter(this, void 0, void 0, function* () {
|
|
580
574
|
// // console.log(res)
|
|
@@ -637,7 +631,7 @@ class find extends recordGetOperation {
|
|
|
637
631
|
run() {
|
|
638
632
|
return new Promise((resolve, reject) => {
|
|
639
633
|
// console.log(this.#toObject())
|
|
640
|
-
this.layout.database.apiRequest(`${this.layout.endpoint}/_find`, {
|
|
634
|
+
this.layout.database.host.apiRequest(`${this.layout.endpoint}/_find`, {
|
|
641
635
|
port: 443,
|
|
642
636
|
method: "POST",
|
|
643
637
|
body: JSON.stringify(this.toObject())
|
package/index.ts
CHANGED
|
@@ -91,7 +91,7 @@ class database {
|
|
|
91
91
|
external: boolean;
|
|
92
92
|
public name: string;
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
host: FileMakerConnection;
|
|
95
95
|
protected props: databaseOptions;
|
|
96
96
|
|
|
97
97
|
public hostname: string;
|
|
@@ -106,21 +106,10 @@ class database {
|
|
|
106
106
|
return new layout(this, name)
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
async apiRequest(url: string | Request, options: any = {}): Promise<any> {
|
|
110
|
-
if (!options.headers) options.headers = {}
|
|
111
|
-
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json"
|
|
112
|
-
options.headers["authorization"] = "Bearer " + this.host.token
|
|
113
|
-
options.rejectUnauthorized = this.host.rejectUnauthroized
|
|
114
|
-
|
|
115
|
-
let _fetch = await fetch(url, options)
|
|
116
|
-
let data = await _fetch.json()
|
|
117
|
-
return (data as any)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
109
|
setGlobals(globalFields): Promise<void> {
|
|
121
110
|
// console.log({globalFields})
|
|
122
111
|
return new Promise((resolve, reject) => {
|
|
123
|
-
this.apiRequest(`${this.endpoint}/globals`, {
|
|
112
|
+
this.host.apiRequest(`${this.endpoint}/globals`, {
|
|
124
113
|
method: "PATCH",
|
|
125
114
|
body: JSON.stringify({globalFields})
|
|
126
115
|
}).then(res => {
|
|
@@ -279,6 +268,17 @@ export default class FileMakerConnection {
|
|
|
279
268
|
get endpoint(): string {
|
|
280
269
|
return `https://${this.hostname}/fmi/data/v2/databases/`
|
|
281
270
|
}
|
|
271
|
+
|
|
272
|
+
async apiRequest(url: string | Request, options: any = {}): Promise<any> {
|
|
273
|
+
if (!options.headers) options.headers = {}
|
|
274
|
+
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json"
|
|
275
|
+
options.headers["authorization"] = "Bearer " + this._token
|
|
276
|
+
options.rejectUnauthorized = this.rejectUnauthroized
|
|
277
|
+
|
|
278
|
+
let _fetch = await fetch(url, options)
|
|
279
|
+
let data = await _fetch.json()
|
|
280
|
+
return (data as any)
|
|
281
|
+
}
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
class layout {
|
|
@@ -324,7 +324,7 @@ class layout {
|
|
|
324
324
|
return new Promise(async (resolve, reject) => {
|
|
325
325
|
let url = `${this.endpoint}/script/${encodeURI(script.name)}`
|
|
326
326
|
if (script.parameter) url += "?" + encodeURI(script.parameter)
|
|
327
|
-
this.database.apiRequest(url, {
|
|
327
|
+
this.database.host.apiRequest(url, {
|
|
328
328
|
port: 443,
|
|
329
329
|
method: "GET"
|
|
330
330
|
})
|
|
@@ -344,7 +344,7 @@ class layout {
|
|
|
344
344
|
|
|
345
345
|
public getLayoutMeta(): Promise<layout | FMError> {
|
|
346
346
|
return new Promise((resolve, reject) => {
|
|
347
|
-
this.database.apiRequest(this.endpoint).then(res => {
|
|
347
|
+
this.database.host.apiRequest(this.endpoint).then(res => {
|
|
348
348
|
this.metadata = res.response
|
|
349
349
|
resolve(this)
|
|
350
350
|
})
|
|
@@ -408,7 +408,7 @@ class record extends EventEmitter {
|
|
|
408
408
|
return new Promise(async (resolve, reject) => {
|
|
409
409
|
if (!this.layout.metadata) await this.layout.getLayoutMeta()
|
|
410
410
|
|
|
411
|
-
this.layout.database.apiRequest(this.endpoint, {
|
|
411
|
+
this.layout.database.host.apiRequest(this.endpoint, {
|
|
412
412
|
port: 443,
|
|
413
413
|
method: "GET"
|
|
414
414
|
})
|
|
@@ -442,7 +442,7 @@ class record extends EventEmitter {
|
|
|
442
442
|
// This is a new record
|
|
443
443
|
extraBody.fieldData = data.fieldData
|
|
444
444
|
|
|
445
|
-
this.layout.database.apiRequest(`${this.layout.endpoint}/records`, {
|
|
445
|
+
this.layout.database.host.apiRequest(`${this.layout.endpoint}/records`, {
|
|
446
446
|
port: 443,
|
|
447
447
|
method: "POST",
|
|
448
448
|
body: JSON.stringify(extraBody)
|
|
@@ -467,7 +467,7 @@ class record extends EventEmitter {
|
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
for (let item of Object.keys(extraBody)) data[item] = extraBody[item]
|
|
470
|
-
this.layout.database.apiRequest(this.endpoint, {
|
|
470
|
+
this.layout.database.host.apiRequest(this.endpoint, {
|
|
471
471
|
port: 443,
|
|
472
472
|
method: "PATCH",
|
|
473
473
|
body: JSON.stringify(data)
|
|
@@ -699,7 +699,7 @@ class recordGetRange extends recordGetOperation {
|
|
|
699
699
|
run() {
|
|
700
700
|
return new Promise((resolve, reject) => {
|
|
701
701
|
// console.log(this.#toObject())
|
|
702
|
-
this.layout.database.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
|
|
702
|
+
this.layout.database.host.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
|
|
703
703
|
method: "GET"
|
|
704
704
|
}).then(async res => {
|
|
705
705
|
// // console.log(res)
|
|
@@ -765,7 +765,7 @@ class find extends recordGetOperation {
|
|
|
765
765
|
run() {
|
|
766
766
|
return new Promise((resolve, reject) => {
|
|
767
767
|
// console.log(this.#toObject())
|
|
768
|
-
this.layout.database.apiRequest(`${this.layout.endpoint}/_find`, {
|
|
768
|
+
this.layout.database.host.apiRequest(`${this.layout.endpoint}/_find`, {
|
|
769
769
|
port: 443,
|
|
770
770
|
method: "POST",
|
|
771
771
|
body: JSON.stringify(this.toObject())
|