@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.
Files changed (3) hide show
  1. package/index.js +69 -75
  2. package/index.ts +20 -20
  3. 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(props, host = null) {
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 `https://${this.hostname || this.host.hostname}/fmi/data/v2/databases/${encodeURI(this.name)}`;
75
- }
76
- get externalLoginInfo() {
77
- // Returns an object that can be used when using this database object as an external source
78
- let out = {
79
- database: this.name,
80
- username: undefined,
81
- password: undefined,
82
- oauthRequestId: undefined,
83
- oauthIdentifier: undefined
84
- };
85
- switch (this.props.method) {
86
- case "filemaker":
87
- out.username = this.props.username;
88
- out.password = this.props.password;
89
- case "token":
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 extends database {
101
- constructor(conn, externalDataSources = [], rejectUnauthorized = true) {
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.externalSources = externalDataSources.map(i => {
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
- if (this.props.method === "filemaker") {
135
- this.username = this.props.username;
136
- this.name = this.props.database;
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.props.password).toString("base64")
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.props.method === "token") {
160
- this._token = this.props.token;
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.props.method === "oauth") {
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.props.oauth.requestId,
171
- "X-FM-Data-OAuth-Identifier": this.props.oauth.requestIdentifier
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.props.method === "claris") {
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.props.claris.fmid,
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
- protected host: FileMakerConnection;
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())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jd-data-limited/easy-fm",
3
- "version": "1.0.2alpha2",
3
+ "version": "1.0.2alpha4",
4
4
  "dependencies": {
5
5
  "@types/btoa": "^1.2.3",
6
6
  "@types/events": "^3.0.0",