@jd-data-limited/easy-fm 1.0.2-alpha5 → 1.1.2-alpha1

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 +61 -76
  2. package/index.ts +69 -95
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -22,63 +22,26 @@ import { fileURLToPath } from "url";
22
22
  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
- class database {
26
- constructor() { }
27
- get token() {
28
- return this.host.token;
29
- }
30
- getLayout(name) {
31
- return new layout(this, name);
32
- }
33
- setGlobals(globalFields) {
34
- // console.log({globalFields})
35
- return new Promise((resolve, reject) => {
36
- this.host.apiRequest(`${this.endpoint}/globals`, {
37
- method: "PATCH",
38
- body: JSON.stringify({ globalFields })
39
- }).then(res => {
40
- // console.log(res)
41
- if (res.messages[0].code === "0") {
42
- resolve();
43
- }
44
- else {
45
- reject(new FMError(res.messages[0].code, res.status, res));
46
- }
47
- })
48
- .catch(e => {
49
- reject(e);
50
- });
51
- });
52
- }
53
- script(name, parameter) {
54
- return { name, parameter };
55
- }
56
- get endpoint() {
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
- }
73
- }
74
- }
75
- }
76
25
  export default class FileMakerConnection {
77
26
  constructor(conn, rejectUnauthorized = true) {
78
27
  this.hostname = conn.hostname;
79
- this.databaseConDetails = conn.databases;
28
+ this.name = conn.database.database;
29
+ this.databaseConDetails = conn;
80
30
  this.rejectUnauthroized = rejectUnauthorized;
81
31
  }
32
+ generateExternalSourceLogin(data) {
33
+ if (data.method === "filemaker") {
34
+ let _data = data;
35
+ return {
36
+ database: _data.database,
37
+ username: _data.username,
38
+ password: _data.password
39
+ };
40
+ }
41
+ else {
42
+ throw "Not yet supported login method";
43
+ }
44
+ }
82
45
  logout() {
83
46
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
84
47
  if (!this.token)
@@ -100,15 +63,8 @@ export default class FileMakerConnection {
100
63
  return new Promise((resolve, reject) => {
101
64
  if (this.token)
102
65
  throw new Error("Already logged in. Run logout() first");
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
66
  if (this.databaseConDetails[0].method === "filemaker") {
111
- fetch(`${this.databases[0].endpoint}/sessions`, {
67
+ fetch(`${this.endpoint}/sessions`, {
112
68
  hostname: this.hostname,
113
69
  port: 443,
114
70
  method: "POST",
@@ -117,7 +73,10 @@ export default class FileMakerConnection {
117
73
  "Authorization": "Basic " + Buffer.from(this.databaseConDetails[0].username + ":" + this.databaseConDetails[0].password).toString("base64")
118
74
  },
119
75
  body: JSON.stringify({
120
- fmDataSource: external_sources_cons
76
+ fmDataSource: this.databaseConDetails.externalSources.map(i => {
77
+ let _i = i;
78
+ return this.generateExternalSourceLogin(_i);
79
+ })
121
80
  })
122
81
  }).then((res) => __awaiter(this, void 0, void 0, function* () {
123
82
  if (res.status === 200) {
@@ -138,15 +97,18 @@ export default class FileMakerConnection {
138
97
  resolve(this.token);
139
98
  }
140
99
  else if (this.databaseConDetails[0].method === "oauth") {
141
- fetch(`${this.databases[0].endpoint}/sessions`, {
100
+ fetch(`${this.endpoint}/sessions`, {
142
101
  method: "POST",
143
102
  headers: {
144
103
  "Content-Type": "application/json",
145
104
  "X-FM-Data-OAuth-RequestId": this.databaseConDetails[0].oauth.requestId,
146
105
  "X-FM-Data-OAuth-Identifier": this.databaseConDetails[0].oauth.requestIdentifier
147
106
  },
148
- body: external_sources_cons.length === 0 ? "{}" : JSON.stringify({
149
- fmDataSource: external_sources_cons
107
+ body: JSON.stringify({
108
+ fmDataSource: this.databaseConDetails.externalSources.map(i => {
109
+ let _i = i;
110
+ return this.generateExternalSourceLogin(_i);
111
+ })
150
112
  })
151
113
  })
152
114
  .then(res => res.json())
@@ -157,7 +119,7 @@ export default class FileMakerConnection {
157
119
  });
158
120
  }
159
121
  else if (this.databaseConDetails[0].method === "claris") {
160
- fetch(`${this.databases[0].endpoint}/sessions`, {
122
+ fetch(`${this.endpoint}/sessions`, {
161
123
  method: "POST",
162
124
  headers: {
163
125
  "Content-Type": "application/json",
@@ -174,14 +136,11 @@ export default class FileMakerConnection {
174
136
  }
175
137
  });
176
138
  }
177
- getDatabase(database_name) {
178
- return this.databases.find(db => db.name === database_name);
179
- }
180
139
  get token() {
181
140
  return this._token;
182
141
  }
183
142
  get endpoint() {
184
- return `https://${this.hostname}/fmi/data/v2/databases/`;
143
+ return `https://${this.hostname}/fmi/data/v2/databases/${this.name}`;
185
144
  }
186
145
  apiRequest(url, options = {}) {
187
146
  return __awaiter(this, void 0, void 0, function* () {
@@ -195,6 +154,32 @@ export default class FileMakerConnection {
195
154
  return data;
196
155
  });
197
156
  }
157
+ getLayout(name) {
158
+ return new layout(this, name);
159
+ }
160
+ setGlobals(globalFields) {
161
+ // console.log({globalFields})
162
+ return new Promise((resolve, reject) => {
163
+ this.apiRequest(`${this.endpoint}/globals`, {
164
+ method: "PATCH",
165
+ body: JSON.stringify({ globalFields })
166
+ }).then(res => {
167
+ // console.log(res)
168
+ if (res.messages[0].code === "0") {
169
+ resolve();
170
+ }
171
+ else {
172
+ reject(new FMError(res.messages[0].code, res.status, res));
173
+ }
174
+ })
175
+ .catch(e => {
176
+ reject(e);
177
+ });
178
+ });
179
+ }
180
+ script(name, parameter) {
181
+ return { name, parameter };
182
+ }
198
183
  }
199
184
  class layout {
200
185
  constructor(database, name) {
@@ -230,7 +215,7 @@ class layout {
230
215
  let url = `${this.endpoint}/script/${encodeURI(script.name)}`;
231
216
  if (script.parameter)
232
217
  url += "?" + encodeURI(script.parameter);
233
- this.database.host.apiRequest(url, {
218
+ this.database.apiRequest(url, {
234
219
  port: 443,
235
220
  method: "GET"
236
221
  })
@@ -250,7 +235,7 @@ class layout {
250
235
  }
251
236
  getLayoutMeta() {
252
237
  return new Promise((resolve, reject) => {
253
- this.database.host.apiRequest(this.endpoint).then(res => {
238
+ this.database.apiRequest(this.endpoint).then(res => {
254
239
  this.metadata = res.response;
255
240
  resolve(this);
256
241
  })
@@ -302,7 +287,7 @@ class record extends EventEmitter {
302
287
  return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
303
288
  if (!this.layout.metadata)
304
289
  yield this.layout.getLayoutMeta();
305
- this.layout.database.host.apiRequest(this.endpoint, {
290
+ this.layout.database.apiRequest(this.endpoint, {
306
291
  port: 443,
307
292
  method: "GET"
308
293
  })
@@ -335,7 +320,7 @@ class record extends EventEmitter {
335
320
  if (this.recordId === -1) {
336
321
  // This is a new record
337
322
  extraBody.fieldData = data.fieldData;
338
- this.layout.database.host.apiRequest(`${this.layout.endpoint}/records`, {
323
+ this.layout.database.apiRequest(`${this.layout.endpoint}/records`, {
339
324
  port: 443,
340
325
  method: "POST",
341
326
  body: JSON.stringify(extraBody)
@@ -361,7 +346,7 @@ class record extends EventEmitter {
361
346
  }
362
347
  for (let item of Object.keys(extraBody))
363
348
  data[item] = extraBody[item];
364
- this.layout.database.host.apiRequest(this.endpoint, {
349
+ this.layout.database.apiRequest(this.endpoint, {
365
350
  port: 443,
366
351
  method: "PATCH",
367
352
  body: JSON.stringify(data)
@@ -568,7 +553,7 @@ class recordGetRange extends recordGetOperation {
568
553
  run() {
569
554
  return new Promise((resolve, reject) => {
570
555
  // console.log(this.#toObject())
571
- this.layout.database.host.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
556
+ this.layout.database.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
572
557
  method: "GET"
573
558
  }).then((res) => __awaiter(this, void 0, void 0, function* () {
574
559
  // // console.log(res)
@@ -631,7 +616,7 @@ class find extends recordGetOperation {
631
616
  run() {
632
617
  return new Promise((resolve, reject) => {
633
618
  // console.log(this.#toObject())
634
- this.layout.database.host.apiRequest(`${this.layout.endpoint}/_find`, {
619
+ this.layout.database.apiRequest(`${this.layout.endpoint}/_find`, {
635
620
  port: 443,
636
621
  method: "POST",
637
622
  body: JSON.stringify(this.toObject())
package/index.ts CHANGED
@@ -33,7 +33,8 @@ interface connectionOptions {
33
33
 
34
34
  interface hostConnectionOptions {
35
35
  hostname: string
36
- databases: (loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken)[]
36
+ database: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken,
37
+ externalSources: (loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken)[]
37
38
  }
38
39
 
39
40
  interface databaseOptions {
@@ -87,83 +88,33 @@ interface recordObject {
87
88
  fieldData: any
88
89
  }
89
90
 
90
- class database {
91
- external: boolean;
92
- public name: string;
93
-
94
- host: FileMakerConnection;
95
- protected props: databaseOptions;
96
-
97
- public hostname: string;
98
-
99
- constructor() {}
100
-
101
- get token() {
102
- return this.host.token
103
- }
104
-
105
- getLayout(name): layout {
106
- return new layout(this, name)
107
- }
108
-
109
- setGlobals(globalFields): Promise<void> {
110
- // console.log({globalFields})
111
- return new Promise((resolve, reject) => {
112
- this.host.apiRequest(`${this.endpoint}/globals`, {
113
- method: "PATCH",
114
- body: JSON.stringify({globalFields})
115
- }).then(res => {
116
- // console.log(res)
117
- if (res.messages[0].code === "0") {
118
- resolve()
119
- } else {
120
- reject(new FMError(res.messages[0].code, res.status, res))
121
- }
122
- })
123
- .catch(e => {
124
- reject(e)
125
- })
126
- })
127
- }
128
-
129
- script(name, parameter): Script {
130
- return ({name, parameter} as Script)
131
- }
132
-
133
- get endpoint(): string {
134
- return `${this.host.endpoint}/${encodeURI(this.name)}`
135
- }
136
-
137
- pairHost(db: FileMakerConnection, details: databaseOptions, returnConDetails = true) {
138
- this.host = db
139
- this.name = details.database
140
- if (returnConDetails) {
141
- if (details.method === "filemaker") {
142
- return {
143
- database: this.name,
144
- username: (<loginOptionsFileMaker>details).username,
145
- password: (<loginOptionsFileMaker>details).password
146
- }
147
- } else {
148
- throw `Authentication method used for '${this.name}' is not supported for external data source connections`
149
- }
150
- }
151
- }
152
- }
153
-
154
91
  export default class FileMakerConnection {
155
92
  private _token: any;
156
93
  private hostname: string;
157
94
  public readonly rejectUnauthroized: boolean;
158
- private databases: database[]
159
- private databaseConDetails: (loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken)[];
95
+ private databaseConDetails: hostConnectionOptions
96
+ public name: string;
160
97
 
161
98
  constructor(conn: hostConnectionOptions, rejectUnauthorized = true) {
162
99
  this.hostname = conn.hostname
163
- this.databaseConDetails = conn.databases
100
+ this.name = conn.database.database
101
+ this.databaseConDetails = conn
164
102
  this.rejectUnauthroized = rejectUnauthorized
165
103
  }
166
104
 
105
+ private generateExternalSourceLogin(data: databaseOptions | loginOptionsFileMaker) {
106
+ if (data.method === "filemaker") {
107
+ let _data = <loginOptionsFileMaker>data
108
+ return {
109
+ database: _data.database,
110
+ username: _data.username,
111
+ password: _data.password
112
+ }
113
+ } else {
114
+ throw "Not yet supported login method"
115
+ }
116
+ }
117
+
167
118
  logout(): Promise<void> {
168
119
  return new Promise(async (resolve, reject) => {
169
120
  if (!this.token) reject(new Error("Not logged in"))
@@ -185,16 +136,9 @@ export default class FileMakerConnection {
185
136
  login() {
186
137
  return new Promise<string>((resolve, reject) => {
187
138
  if (this.token) throw new Error("Already logged in. Run logout() first")
188
- this.databases = [new database()]
189
- this.databases[0].pairHost(this, this.databaseConDetails[0], false)
190
- let external_sources_cons = this.databaseConDetails.slice(1).map(con => {
191
- let db = new database()
192
- this.databases.push(db)
193
- return db.pairHost(this, con)
194
- })
195
139
 
196
140
  if (this.databaseConDetails[0].method === "filemaker") {
197
- fetch(`${this.databases[0].endpoint}/sessions`, {
141
+ fetch(`${this.endpoint}/sessions`, {
198
142
  hostname: this.hostname,
199
143
  port: 443,
200
144
  method: "POST",
@@ -203,7 +147,10 @@ export default class FileMakerConnection {
203
147
  "Authorization": "Basic " + Buffer.from((<loginOptionsFileMaker>this.databaseConDetails[0]).username + ":" + (<loginOptionsFileMaker>this.databaseConDetails[0]).password).toString("base64")
204
148
  },
205
149
  body: JSON.stringify({
206
- fmDataSource: external_sources_cons
150
+ fmDataSource: this.databaseConDetails.externalSources.map(i => {
151
+ let _i = <databaseOptions>i
152
+ return this.generateExternalSourceLogin(_i)
153
+ })
207
154
  })
208
155
  }).then(async res => {
209
156
  if (res.status === 200) {
@@ -221,15 +168,18 @@ export default class FileMakerConnection {
221
168
  this._token = (<loginOptionsToken>this.databaseConDetails[0]).token
222
169
  resolve(this.token)
223
170
  } else if (this.databaseConDetails[0].method === "oauth") {
224
- fetch(`${this.databases[0].endpoint}/sessions`, {
171
+ fetch(`${this.endpoint}/sessions`, {
225
172
  method: "POST",
226
173
  headers: {
227
174
  "Content-Type": "application/json",
228
175
  "X-FM-Data-OAuth-RequestId": (<loginOptionsOAuth>this.databaseConDetails[0]).oauth.requestId,
229
176
  "X-FM-Data-OAuth-Identifier": (<loginOptionsOAuth>this.databaseConDetails[0]).oauth.requestIdentifier
230
177
  },
231
- body: external_sources_cons.length === 0 ? "{}" : JSON.stringify({
232
- fmDataSource: external_sources_cons
178
+ body: JSON.stringify({
179
+ fmDataSource: this.databaseConDetails.externalSources.map(i => {
180
+ let _i = <databaseOptions>i
181
+ return this.generateExternalSourceLogin(_i)
182
+ })
233
183
  })
234
184
  })
235
185
  .then(res => res.json())
@@ -239,7 +189,7 @@ export default class FileMakerConnection {
239
189
  resolve(this.token)
240
190
  })
241
191
  } else if (this.databaseConDetails[0].method === "claris") {
242
- fetch(`${this.databases[0].endpoint}/sessions`, {
192
+ fetch(`${this.endpoint}/sessions`, {
243
193
  method: "POST",
244
194
  headers: {
245
195
  "Content-Type": "application/json",
@@ -257,16 +207,12 @@ export default class FileMakerConnection {
257
207
  })
258
208
  }
259
209
 
260
- getDatabase(database_name) {
261
- return this.databases.find(db => db.name === database_name)
262
- }
263
-
264
210
  get token() {
265
211
  return this._token
266
212
  }
267
213
 
268
214
  get endpoint(): string {
269
- return `https://${this.hostname}/fmi/data/v2/databases/`
215
+ return `https://${this.hostname}/fmi/data/v2/databases/${this.name}`
270
216
  }
271
217
 
272
218
  async apiRequest(url: string | Request, options: any = {}): Promise<any> {
@@ -279,14 +225,42 @@ export default class FileMakerConnection {
279
225
  let data = await _fetch.json()
280
226
  return (data as any)
281
227
  }
228
+
229
+ getLayout(name): layout {
230
+ return new layout(this, name)
231
+ }
232
+
233
+ setGlobals(globalFields): Promise<void> {
234
+ // console.log({globalFields})
235
+ return new Promise((resolve, reject) => {
236
+ this.apiRequest(`${this.endpoint}/globals`, {
237
+ method: "PATCH",
238
+ body: JSON.stringify({globalFields})
239
+ }).then(res => {
240
+ // console.log(res)
241
+ if (res.messages[0].code === "0") {
242
+ resolve()
243
+ } else {
244
+ reject(new FMError(res.messages[0].code, res.status, res))
245
+ }
246
+ })
247
+ .catch(e => {
248
+ reject(e)
249
+ })
250
+ })
251
+ }
252
+
253
+ script(name, parameter): Script {
254
+ return ({name, parameter} as Script)
255
+ }
282
256
  }
283
257
 
284
258
  class layout {
285
- readonly database: database;
259
+ readonly database: FileMakerConnection;
286
260
  protected name: string;
287
261
  metadata: any;
288
262
 
289
- constructor(database: database, name: string) {
263
+ constructor(database: FileMakerConnection, name: string) {
290
264
  this.database = database
291
265
  this.name = name
292
266
  }
@@ -324,7 +298,7 @@ class layout {
324
298
  return new Promise(async (resolve, reject) => {
325
299
  let url = `${this.endpoint}/script/${encodeURI(script.name)}`
326
300
  if (script.parameter) url += "?" + encodeURI(script.parameter)
327
- this.database.host.apiRequest(url, {
301
+ this.database.apiRequest(url, {
328
302
  port: 443,
329
303
  method: "GET"
330
304
  })
@@ -344,7 +318,7 @@ class layout {
344
318
 
345
319
  public getLayoutMeta(): Promise<layout | FMError> {
346
320
  return new Promise((resolve, reject) => {
347
- this.database.host.apiRequest(this.endpoint).then(res => {
321
+ this.database.apiRequest(this.endpoint).then(res => {
348
322
  this.metadata = res.response
349
323
  resolve(this)
350
324
  })
@@ -408,7 +382,7 @@ class record extends EventEmitter {
408
382
  return new Promise(async (resolve, reject) => {
409
383
  if (!this.layout.metadata) await this.layout.getLayoutMeta()
410
384
 
411
- this.layout.database.host.apiRequest(this.endpoint, {
385
+ this.layout.database.apiRequest(this.endpoint, {
412
386
  port: 443,
413
387
  method: "GET"
414
388
  })
@@ -442,7 +416,7 @@ class record extends EventEmitter {
442
416
  // This is a new record
443
417
  extraBody.fieldData = data.fieldData
444
418
 
445
- this.layout.database.host.apiRequest(`${this.layout.endpoint}/records`, {
419
+ this.layout.database.apiRequest(`${this.layout.endpoint}/records`, {
446
420
  port: 443,
447
421
  method: "POST",
448
422
  body: JSON.stringify(extraBody)
@@ -467,7 +441,7 @@ class record extends EventEmitter {
467
441
  }
468
442
 
469
443
  for (let item of Object.keys(extraBody)) data[item] = extraBody[item]
470
- this.layout.database.host.apiRequest(this.endpoint, {
444
+ this.layout.database.apiRequest(this.endpoint, {
471
445
  port: 443,
472
446
  method: "PATCH",
473
447
  body: JSON.stringify(data)
@@ -699,7 +673,7 @@ class recordGetRange extends recordGetOperation {
699
673
  run() {
700
674
  return new Promise((resolve, reject) => {
701
675
  // console.log(this.#toObject())
702
- this.layout.database.host.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
676
+ this.layout.database.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
703
677
  method: "GET"
704
678
  }).then(async res => {
705
679
  // // console.log(res)
@@ -765,7 +739,7 @@ class find extends recordGetOperation {
765
739
  run() {
766
740
  return new Promise((resolve, reject) => {
767
741
  // console.log(this.#toObject())
768
- this.layout.database.host.apiRequest(`${this.layout.endpoint}/_find`, {
742
+ this.layout.database.apiRequest(`${this.layout.endpoint}/_find`, {
769
743
  port: 443,
770
744
  method: "POST",
771
745
  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.2alpha5",
3
+ "version": "1.1.2alpha1",
4
4
  "dependencies": {
5
5
  "@types/btoa": "^1.2.3",
6
6
  "@types/events": "^3.0.0",