@jd-data-limited/easy-fm 1.0.1-alpha1 → 1.0.2-alpha2

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.
@@ -0,0 +1,15 @@
1
+ > Why do I have a folder named ".expo" in my project?
2
+
3
+ The ".expo" folder is created when an Expo project is started using "expo start" command.
4
+
5
+ > What do the files contain?
6
+
7
+ - "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
8
+ - "packager-info.json": contains port numbers and process PIDs that are used to serve the application to the mobile device/simulator.
9
+ - "settings.json": contains the server configuration that is used to serve the application manifest.
10
+
11
+ > Should I commit the ".expo" folder?
12
+
13
+ No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
14
+
15
+ Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
@@ -0,0 +1,8 @@
1
+ {
2
+ "hostType": "lan",
3
+ "lanType": "ip",
4
+ "dev": true,
5
+ "minify": false,
6
+ "urlRandomness": null,
7
+ "https": false
8
+ }
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2022. See LICENSE file for more information
2
+ * Copyright (c) 2022-2023. See LICENSE file for more information
3
3
  */
4
4
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
5
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -102,7 +102,11 @@ export default class FileMakerConnection extends database {
102
102
  super(conn.database);
103
103
  this.host = this;
104
104
  this.hostname = conn.hostname;
105
- this.externalSources = externalDataSources.map(i => { let e = new database(i, this); e.external = true; return e; });
105
+ this.externalSources = externalDataSources.map(i => {
106
+ let e = new database(i, this);
107
+ e.external = true;
108
+ return e;
109
+ });
106
110
  this.rejectUnauthroized = rejectUnauthorized;
107
111
  }
108
112
  logout() {
@@ -459,7 +463,9 @@ class field {
459
463
  reject(new FMError(_res.messages[0].code, _res.status, data));
460
464
  }
461
465
  })
462
- .catch(e => { reject(e); });
466
+ .catch(e => {
467
+ reject(e);
468
+ });
463
469
  }));
464
470
  }
465
471
  download() {
@@ -503,10 +509,12 @@ class portalItem extends record {
503
509
  return res;
504
510
  }
505
511
  }
506
- class find {
512
+ class recordGetOperation {
507
513
  constructor(layout) {
514
+ this.limit = 100;
515
+ this.limitPortals = [];
516
+ this.offset = 0;
508
517
  this.layout = layout;
509
- this.queries = [];
510
518
  this.scripts = {
511
519
  "script": null,
512
520
  "script.prerequeset": null,
@@ -514,6 +522,86 @@ class find {
514
522
  };
515
523
  this.sort = [];
516
524
  }
525
+ /*
526
+ addToPortalLimit() will adjust the results of the get request so that if a layout has multiple portals in it,
527
+ only data from the specified ones will be read. This may help reduce load on your FileMaker API
528
+ */
529
+ addToPortalLimit(portal, offset = 0, limit = 100) {
530
+ if (offset < 0)
531
+ throw "Portal offset cannot be less than 0";
532
+ this.limitPortals.push({ portal, offset, limit });
533
+ }
534
+ setLimit(limit) {
535
+ if (limit < 1)
536
+ throw "Record limit too low";
537
+ this.limit = limit;
538
+ }
539
+ addSort(fieldName, sortOrder) {
540
+ this.sort.push({ fieldName, sortOrder });
541
+ return this;
542
+ }
543
+ setOffset(offset) {
544
+ if (offset < 0)
545
+ throw "Record offset too low";
546
+ this.limit = offset;
547
+ }
548
+ }
549
+ class recordGetRange extends recordGetOperation {
550
+ constructor(layout) {
551
+ super(layout);
552
+ }
553
+ generateQueryParams() {
554
+ let params = [];
555
+ if (this.limit !== 100)
556
+ params.push("_limit=" + this.limit);
557
+ if (this.offset !== 0)
558
+ params.push("_offset=" + this.offset);
559
+ if (this.sort.length > 0)
560
+ params.push("_sort=" + encodeURI(JSON.stringify(this.sort)));
561
+ if (this.limitPortals.length > 0) {
562
+ params.push("portal=" + encodeURI(JSON.stringify(this.limitPortals.map(p => p.portal.name))));
563
+ for (let item of this.limitPortals) {
564
+ if (item.offset !== 0)
565
+ params.push("_offset." + item.portal.name.replace(/[^0-9A-z]/g, "") + "=" + item.offset);
566
+ if (item.limit !== 100)
567
+ params.push("_limit." + item.portal.name.replace(/[^0-9A-z]/g, "") + "=" + item.limit);
568
+ }
569
+ }
570
+ if (params.length === 0)
571
+ return "";
572
+ return "?" + params.join("&");
573
+ }
574
+ run() {
575
+ return new Promise((resolve, reject) => {
576
+ // console.log(this.#toObject())
577
+ this.layout.database.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
578
+ method: "GET"
579
+ }).then((res) => __awaiter(this, void 0, void 0, function* () {
580
+ // // console.log(res)
581
+ if (res.messages[0].code === "0") {
582
+ // console.log("RESOLVING")
583
+ if (!this.layout.metadata)
584
+ yield this.layout.getLayoutMeta();
585
+ let data = res.response.data.map(item => {
586
+ return new record(this.layout, item.recordId, item.modId, item.fieldData, item.portalData);
587
+ });
588
+ resolve(data);
589
+ }
590
+ else {
591
+ reject(new FMError(res.messages[0].code, res.status, res));
592
+ }
593
+ }))
594
+ .catch(e => {
595
+ reject(e);
596
+ });
597
+ });
598
+ }
599
+ }
600
+ class find extends recordGetOperation {
601
+ constructor(layout) {
602
+ super(layout);
603
+ this.queries = [];
604
+ }
517
605
  toObject() {
518
606
  let out = { query: this.queries, sort: undefined };
519
607
  if (this.sort.length !== 0)
@@ -525,6 +613,17 @@ class find {
525
613
  out[item + ".param"] = this.scripts[item].parameter;
526
614
  }
527
615
  }
616
+ if (this.limit !== 100)
617
+ out["limit"] = this.limit;
618
+ if (this.offset !== 0)
619
+ out["offset"] = this.offset;
620
+ if (this.limitPortals.length > 0) {
621
+ out["portal"] = this.limitPortals.map(p => p.portal.name);
622
+ for (let item of this.limitPortals) {
623
+ out["offset." + item.portal.name.replace(/[^0-9A-z]/g, "")] = item.offset;
624
+ out["limit." + item.portal.name.replace(/[^0-9A-z]/g, "")] = item.limit;
625
+ }
626
+ }
528
627
  return out;
529
628
  }
530
629
  addRequests(...requests) {
@@ -532,11 +631,10 @@ class find {
532
631
  this.queries.push(item);
533
632
  return this;
534
633
  }
535
- addSort(fieldName, sortOrder) {
536
- this.sort.push({ fieldName, sortOrder });
537
- return this;
538
- }
539
634
  find() {
635
+ return this.run();
636
+ }
637
+ run() {
540
638
  return new Promise((resolve, reject) => {
541
639
  // console.log(this.#toObject())
542
640
  this.layout.database.apiRequest(`${this.layout.endpoint}/_find`, {
package/index.ts CHANGED
@@ -15,14 +15,15 @@ import fetch, {
15
15
  Request,
16
16
  Response
17
17
  } from 'node-fetch';
18
- import { EventEmitter } from "events";
18
+ import {EventEmitter} from "events";
19
19
  // @ts-ignore
20
20
  import fs from "fs"
21
21
  // @ts-ignore
22
22
  import path from "path"
23
23
  // @ts-ignore
24
- import { fileURLToPath } from "url"
24
+ import {fileURLToPath} from "url"
25
25
  import * as https from "https";
26
+
26
27
  // import * as btoa from "btoa";
27
28
 
28
29
  interface connectionOptions {
@@ -32,7 +33,7 @@ interface connectionOptions {
32
33
 
33
34
  interface hostConnectionOptions {
34
35
  hostname: string
35
- database: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken
36
+ databases: (loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken)[]
36
37
  }
37
38
 
38
39
  interface databaseOptions {
@@ -66,6 +67,12 @@ interface loginOptionsClaris extends databaseOptions {
66
67
  }
67
68
  }
68
69
 
70
+ interface limitPortalsInterface {
71
+ portal: portal,
72
+ offset: number,
73
+ limit: number
74
+ }
75
+
69
76
  // @ts-ignore
70
77
  const errs = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'fmErrors.json')).toString())
71
78
 
@@ -89,11 +96,7 @@ class database {
89
96
 
90
97
  public hostname: string;
91
98
 
92
- constructor(props: databaseOptions, host: FileMakerConnection = null) {
93
- this.props = props
94
- this.name = this.props.database
95
- if (host) this.host = host
96
- }
99
+ constructor() {}
97
100
 
98
101
  get token() {
99
102
  return this.host.token
@@ -139,47 +142,36 @@ class database {
139
142
  }
140
143
 
141
144
  get endpoint(): string {
142
- return `https://${this.hostname || this.host.hostname}/fmi/data/v2/databases/${encodeURI(this.name)}`
143
- }
144
-
145
- get externalLoginInfo() {
146
- // Returns an object that can be used when using this database object as an external source
147
- let out = {
148
- database: this.name,
149
- username: undefined,
150
- password: undefined,
151
- oauthRequestId: undefined,
152
- oauthIdentifier: undefined
153
- }
154
- switch (this.props.method) {
155
- case "filemaker":
156
- out.username = (<loginOptionsFileMaker>this.props).username
157
- out.password = (<loginOptionsFileMaker>this.props).password
158
- case "token":
159
- throw "Token logins cannot be used for connecting to external sources. Please either use no login method, or open a second connection."
160
- case "oauth":
161
- out.oauthRequestId = (<loginOptionsOAuth>this.props).oauth.requestId
162
- out.oauthIdentifier = (<loginOptionsOAuth>this.props).oauth.requestIdentifier
163
-
164
- case "claris":
165
- throw "Claris logins cannot be used for connecting to external sources. Please either use no login method, or open a second connection."
145
+ return `${this.host.endpoint}/${encodeURI(this.name)}`
146
+ }
147
+
148
+ pairHost(db: FileMakerConnection, details: databaseOptions, returnConDetails = true) {
149
+ this.host = db
150
+ this.name = details.database
151
+ if (returnConDetails) {
152
+ if (details.method === "filemaker") {
153
+ return {
154
+ database: this.name,
155
+ username: (<loginOptionsFileMaker>details).username,
156
+ password: (<loginOptionsFileMaker>details).password
157
+ }
158
+ } else {
159
+ throw `Authentication method used for '${this.name}' is not supported for external data source connections`
160
+ }
166
161
  }
167
- return out
168
162
  }
169
163
  }
170
164
 
171
- export default class FileMakerConnection extends database{
165
+ export default class FileMakerConnection {
172
166
  private _token: any;
173
- private username: any;
174
- private password: any;
167
+ private hostname: string;
175
168
  public readonly rejectUnauthroized: boolean;
176
- externalSources: database[];
169
+ private databases: database[]
170
+ private databaseConDetails: (loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris | loginOptionsToken)[];
177
171
 
178
- constructor(conn: hostConnectionOptions, externalDataSources:databaseOptions[] = [], rejectUnauthorized = true) {
179
- super(conn.database);
180
- this.host = this
172
+ constructor(conn: hostConnectionOptions, rejectUnauthorized = true) {
181
173
  this.hostname = conn.hostname
182
- this.externalSources = externalDataSources.map(i => {let e = new database(i, this); e.external = true; return e;})
174
+ this.databaseConDetails = conn.databases
183
175
  this.rejectUnauthroized = rejectUnauthorized
184
176
  }
185
177
 
@@ -196,7 +188,6 @@ export default class FileMakerConnection extends database{
196
188
  let data = await _fetch.json()
197
189
  // console.log(data)
198
190
  this._token = null
199
- this.name = null
200
191
  this.hostname = null
201
192
  resolve()
202
193
  })
@@ -205,19 +196,26 @@ export default class FileMakerConnection extends database{
205
196
  login() {
206
197
  return new Promise<string>((resolve, reject) => {
207
198
  if (this.token) throw new Error("Already logged in. Run logout() first")
199
+ this.databases = [new database()]
200
+ this.databases[0].pairHost(this, this.databaseConDetails[0], false)
201
+ let external_sources_cons = this.databaseConDetails.slice(1).map(con => {
202
+ let db = new database()
203
+ this.databases.push(db)
204
+ return db.pairHost(this, con)
205
+ })
208
206
 
209
- if (this.props.method === "filemaker") {
210
- this.username = (<loginOptionsFileMaker>this.props).username
211
- this.name = this.props.database
212
-
207
+ if (this.databaseConDetails[0].method === "filemaker") {
213
208
  fetch(`${this.endpoint}/sessions`, {
214
209
  hostname: this.hostname,
215
210
  port: 443,
216
211
  method: "POST",
217
212
  headers: {
218
213
  "Content-Type": "application/json",
219
- "Authorization": "Basic " + Buffer.from(this.username + ":" + (<loginOptionsFileMaker>this.props).password).toString("base64")
220
- }
214
+ "Authorization": "Basic " + Buffer.from((<loginOptionsFileMaker>this.databaseConDetails[0]).username + ":" + (<loginOptionsFileMaker>this.databaseConDetails[0]).password).toString("base64")
215
+ },
216
+ body: JSON.stringify({
217
+ fmDataSource: external_sources_cons
218
+ })
221
219
  }).then(async res => {
222
220
  if (res.status === 200) {
223
221
  this._token = res.headers.get('x-fm-data-access-token')
@@ -230,22 +228,20 @@ export default class FileMakerConnection extends database{
230
228
  .catch(e => {
231
229
  reject(e)
232
230
  })
233
- }
234
- else if (this.props.method === "token") {
235
- this._token = (<loginOptionsToken>this.props).token
236
- this.name = this.props.database
231
+ } else if (this.databaseConDetails[0].method === "token") {
232
+ this._token = (<loginOptionsToken>this.databaseConDetails[0]).token
237
233
  resolve(this.token)
238
- }
239
- else if (this.props.method === "oauth") {
240
- this.name = this.props.database
234
+ } else if (this.databaseConDetails[0].method === "oauth") {
241
235
  fetch(`${this.endpoint}/sessions`, {
242
236
  method: "POST",
243
237
  headers: {
244
238
  "Content-Type": "application/json",
245
- "X-FM-Data-OAuth-RequestId": (<loginOptionsOAuth>this.props).oauth.requestId,
246
- "X-FM-Data-OAuth-Identifier": (<loginOptionsOAuth>this.props).oauth.requestIdentifier
239
+ "X-FM-Data-OAuth-RequestId": (<loginOptionsOAuth>this.databaseConDetails[0]).oauth.requestId,
240
+ "X-FM-Data-OAuth-Identifier": (<loginOptionsOAuth>this.databaseConDetails[0]).oauth.requestIdentifier
247
241
  },
248
- body: "{}"
242
+ body: external_sources_cons.length === 0 ? "{}" : JSON.stringify({
243
+ fmDataSource: external_sources_cons
244
+ })
249
245
  })
250
246
  .then(res => res.json())
251
247
  .then(res => {
@@ -253,14 +249,12 @@ export default class FileMakerConnection extends database{
253
249
  this._token = _res.headers["x-fm-data-access-token"]
254
250
  resolve(this.token)
255
251
  })
256
- }
257
- else if (this.props.method === "claris") {
258
- this.name = this.props.database
252
+ } else if (this.databaseConDetails[0].method === "claris") {
259
253
  fetch(`${this.endpoint}/sessions`, {
260
254
  method: "POST",
261
255
  headers: {
262
256
  "Content-Type": "application/json",
263
- "Authorization": (<loginOptionsClaris>this.props).claris.fmid,
257
+ "Authorization": (<loginOptionsClaris>this.databaseConDetails[0]).claris.fmid,
264
258
  },
265
259
  body: "{}"
266
260
  })
@@ -274,15 +268,24 @@ export default class FileMakerConnection extends database{
274
268
  })
275
269
  }
276
270
 
271
+ getDatabase(database_name) {
272
+ return this.databases.find(db => db.name === database_name)
273
+ }
274
+
277
275
  get token() {
278
276
  return this._token
279
277
  }
278
+
279
+ get endpoint(): string {
280
+ return `https://${this.hostname}/fmi/data/v2/databases/`
281
+ }
280
282
  }
281
283
 
282
284
  class layout {
283
285
  readonly database: database;
284
286
  protected name: string;
285
287
  metadata: any;
288
+
286
289
  constructor(database: database, name: string) {
287
290
  this.database = database
288
291
  this.name = name
@@ -357,7 +360,7 @@ class record extends EventEmitter {
357
360
  fields: field[];
358
361
  readonly portals: portal[];
359
362
  private portalData: any[];
360
-
363
+
361
364
  constructor(layout, recordId, modId = recordId, fieldData = {}, portalData = null) {
362
365
  super();
363
366
  this.layout = layout
@@ -399,7 +402,9 @@ class record extends EventEmitter {
399
402
  }
400
403
 
401
404
  get() {
402
- if (this.recordId === -1) {throw "Cannot get this record until a commit() is done."}
405
+ if (this.recordId === -1) {
406
+ throw "Cannot get this record until a commit() is done."
407
+ }
403
408
  return new Promise(async (resolve, reject) => {
404
409
  if (!this.layout.metadata) await this.layout.getLayoutMeta()
405
410
 
@@ -445,8 +450,7 @@ class record extends EventEmitter {
445
450
  .then(res => {
446
451
  if (typeof res.response.scriptError !== "undefined" && res.response.scriptError !== '0') {
447
452
  reject(new FMError(res.response.scriptError, res.status, res))
448
- }
449
- else if (res.messages[0].code === "0") {
453
+ } else if (res.messages[0].code === "0") {
450
454
  console.log(res)
451
455
  this.recordId = parseInt(res.response.recordId)
452
456
  this.modId = parseInt(res.response.modId)
@@ -455,7 +459,7 @@ class record extends EventEmitter {
455
459
  reject(new FMError(res.messages[0].code, res.status, res))
456
460
  }
457
461
  })
458
- sh .catch(e => {
462
+ .catch(e => {
459
463
  reject(e)
460
464
  })
461
465
 
@@ -471,8 +475,7 @@ class record extends EventEmitter {
471
475
  .then(res => {
472
476
  if (typeof res.response.scriptError !== "undefined" && res.response.scriptError !== '0') {
473
477
  reject(new FMError(res.response.scriptError, res.status, res))
474
- }
475
- else if (res.messages[0].code === "0") {
478
+ } else if (res.messages[0].code === "0") {
476
479
  console.log(res)
477
480
  this.modId = res.response.modId
478
481
  this.emit("saved")
@@ -529,6 +532,7 @@ class field {
529
532
  id: number;
530
533
  value: string | number;
531
534
  edited: boolean;
535
+
532
536
  constructor(record, id, contents) {
533
537
  this.record = record
534
538
  this.id = id
@@ -570,9 +574,12 @@ class field {
570
574
  reject(new FMError(_res.messages[0].code, _res.status, data))
571
575
  }
572
576
  })
573
- .catch(e => {reject(e)})
577
+ .catch(e => {
578
+ reject(e)
579
+ })
574
580
  })
575
581
  }
582
+
576
583
  download() {
577
584
  return new Promise((resolve, reject) => {
578
585
  https.get(this.value.toString(), (res) => {
@@ -624,15 +631,16 @@ class portalItem extends record {
624
631
  }
625
632
  }
626
633
 
627
- class find {
634
+ class recordGetOperation {
628
635
  protected layout: layout
629
- protected queries: object[]
636
+ protected limit: number = 100
630
637
  protected scripts: object
631
638
  protected sort: object[]
639
+ protected limitPortals: limitPortalsInterface[] = []
640
+ protected offset: number = 0
632
641
 
633
642
  constructor(layout) {
634
643
  this.layout = layout
635
- this.queries = []
636
644
  this.scripts = {
637
645
  "script": null, // Runs after everything
638
646
  "script.prerequeset": null, // Runs before the request
@@ -641,6 +649,86 @@ class find {
641
649
  this.sort = []
642
650
  }
643
651
 
652
+ /*
653
+ addToPortalLimit() will adjust the results of the get request so that if a layout has multiple portals in it,
654
+ only data from the specified ones will be read. This may help reduce load on your FileMaker API
655
+ */
656
+ addToPortalLimit(portal: portal, offset = 0, limit = 100) {
657
+ if (offset < 0) throw "Portal offset cannot be less than 0"
658
+ this.limitPortals.push({portal, offset, limit})
659
+ }
660
+
661
+ setLimit(limit: number) {
662
+ if (limit < 1) throw "Record limit too low"
663
+ this.limit = limit
664
+ }
665
+
666
+ addSort(fieldName, sortOrder) {
667
+ this.sort.push({fieldName, sortOrder})
668
+ return this
669
+ }
670
+
671
+ setOffset(offset: number) {
672
+ if (offset < 0) throw "Record offset too low"
673
+ this.limit = offset
674
+ }
675
+ }
676
+
677
+ class recordGetRange extends recordGetOperation {
678
+ constructor(layout) {
679
+ super(layout)
680
+ }
681
+
682
+ private generateQueryParams() {
683
+ let params = []
684
+ if (this.limit !== 100) params.push("_limit=" + this.limit)
685
+ if (this.offset !== 0) params.push("_offset=" + this.offset)
686
+ if (this.sort.length > 0) params.push("_sort=" + encodeURI(JSON.stringify(this.sort)))
687
+ if (this.limitPortals.length > 0) {
688
+ params.push("portal=" + encodeURI(JSON.stringify(this.limitPortals.map(p => p.portal.name))))
689
+ for (let item of this.limitPortals) {
690
+ if (item.offset !== 0) params.push("_offset." + item.portal.name.replace(/[^0-9A-z]/g, "") + "=" + item.offset)
691
+ if (item.limit !== 100) params.push("_limit." + item.portal.name.replace(/[^0-9A-z]/g, "") + "=" + item.limit)
692
+ }
693
+ }
694
+
695
+ if (params.length === 0) return ""
696
+ return "?" + params.join("&")
697
+ }
698
+
699
+ run() {
700
+ return new Promise((resolve, reject) => {
701
+ // console.log(this.#toObject())
702
+ this.layout.database.apiRequest(`${this.layout.endpoint}/records${this.generateQueryParams()}`, {
703
+ method: "GET"
704
+ }).then(async res => {
705
+ // // console.log(res)
706
+ if (res.messages[0].code === "0") {
707
+ // console.log("RESOLVING")
708
+ if (!this.layout.metadata) await this.layout.getLayoutMeta()
709
+ let data = res.response.data.map(item => {
710
+ return new record(this.layout, item.recordId, item.modId, item.fieldData, item.portalData)
711
+ })
712
+ resolve(data)
713
+ } else {
714
+ reject(new FMError(res.messages[0].code, res.status, res))
715
+ }
716
+ })
717
+ .catch(e => {
718
+ reject(e)
719
+ })
720
+ })
721
+ }
722
+ }
723
+
724
+ class find extends recordGetOperation {
725
+ protected queries: object[]
726
+
727
+ constructor(layout) {
728
+ super(layout)
729
+ this.queries = []
730
+ }
731
+
644
732
  private toObject() {
645
733
  let out = {query: this.queries, sort: undefined}
646
734
  if (this.sort.length !== 0) out.sort = this.sort
@@ -652,6 +740,16 @@ class find {
652
740
  }
653
741
  }
654
742
 
743
+ if (this.limit !== 100) out["limit"] = this.limit
744
+ if (this.offset !== 0) out["offset"] = this.offset
745
+ if (this.limitPortals.length > 0) {
746
+ out["portal"] = this.limitPortals.map(p => p.portal.name)
747
+ for (let item of this.limitPortals) {
748
+ out["offset." + item.portal.name.replace(/[^0-9A-z]/g, "")] = item.offset
749
+ out["limit." + item.portal.name.replace(/[^0-9A-z]/g, "")] = item.limit
750
+ }
751
+ }
752
+
655
753
  return out
656
754
  }
657
755
 
@@ -660,12 +758,11 @@ class find {
660
758
  return this
661
759
  }
662
760
 
663
- addSort(fieldName, sortOrder) {
664
- this.sort.push({fieldName, sortOrder})
665
- return this
761
+ find() {
762
+ return this.run()
666
763
  }
667
764
 
668
- find() {
765
+ run() {
669
766
  return new Promise((resolve, reject) => {
670
767
  // console.log(this.#toObject())
671
768
  this.layout.database.apiRequest(`${this.layout.endpoint}/_find`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jd-data-limited/easy-fm",
3
- "version": "1.0.1alpha1",
3
+ "version": "1.0.2alpha2",
4
4
  "dependencies": {
5
5
  "@types/btoa": "^1.2.3",
6
6
  "@types/events": "^3.0.0",