@jd-data-limited/easy-fm 4.1.12 → 4.1.14

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 JD-Data-Limited
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2022 JD-Data-Limited
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,229 +1,229 @@
1
- # Introduction
2
-
3
- A FileMaker Data API client for NodeJS
4
-
5
- easy-fm is a Node.js module that allows you to interact with
6
- a FileMaker database stored on a FileMaker server
7
- or FileMaker Cloud. This module interacts with your server using the
8
- FileMaker Data API.
9
-
10
- # Contents
11
-
12
- <!-- TOC -->
13
- * [Introduction](#introduction)
14
- * [Contents](#contents)
15
- * [Installation](#installation)
16
- * [Usage](#usage)
17
- * [Connecting to a database](#connecting-to-a-database)
18
- * [An important note about timezones](#an-important-note-about-timezones)
19
- * [Getting records](#getting-records)
20
- * [Fetch a range of records](#fetch-a-range-of-records)
21
- * [Searching for records](#searching-for-records)
22
- * [Fetch a record using its record ID (NOT RECOMMENDED)](#fetch-a-record-using-its-record-id-not-recommended)
23
- * [Create a record](#create-a-record)
24
- * [Modify a record](#modify-a-record)
25
- * [Field names](#field-names)
26
- * [Portal names](#portal-names)
27
- * [Typescript Implementation](#typescript-implementation)
28
- <!-- TOC -->
29
-
30
- # Installation
31
-
32
- ```npm
33
- npm install @jd-data-limited/easy-fm --save
34
- ```
35
-
36
- easy-fm also requires the following to be configured within your FileMaker enviroment:
37
-
38
- 1. Enable the FileMaker Data API from the server's admin console. This setting is located
39
- in `Connectors > FileMaker Data API`.
40
- 2. Create a FileMaker database account for easy-fm to use. This account must have the 'Access via FileMaker Data API (
41
- fmrest)' extended privilege
42
-
43
- ---
44
-
45
- # Usage
46
-
47
- ## Connecting to a database
48
-
49
- ```javascript
50
- import FMHost from "easy-fm"; // Import the module
51
- const host = new FMHost("https://<your-servers-address>")
52
- const database = host.database({
53
- database: "your_database.fmp12",
54
- credentials: {
55
- method: "filemaker",
56
- username: "<username>",
57
- password: "<password>"
58
- },
59
- externalSources: []
60
- })
61
-
62
- // OPTIONAL - EasyFM will automatically attempt a login anyway when you perform your first operation
63
- database.login().then(() => {
64
-
65
- })
66
- ```
67
-
68
- > **NOTE:** A connection will only give you access to the layouts in the database you are connected to, and not the
69
- > layouts
70
- > in
71
- > any external sources that you have specified.
72
- >
73
- > If you need to interact with layouts on multiple databases, you need to open a separate connection for each.
74
-
75
- ## An important note about timezones
76
-
77
- Although it is recommended, timestamps in FileMaker databases are not always stored in UTC time. To account for this,
78
- EasyFM allows you to specify a function/method that determines the server's current timezone.
79
- EasyFM will use this timezone offset to convert timestamps to and from JavaScript Date objects.
80
-
81
- ```typescript
82
- import FMHost from "easy-fm";
83
- import {type Moment} from 'moment'
84
-
85
- const host = new FMHost("https://<your-servers-address>", (moment: Moment) => {
86
-
87
- })
88
- ```
89
-
90
- ## Getting records
91
-
92
- One of (if not the) most common interactions you'll need to use is fetching records.
93
-
94
- ### Fetch a range of records
95
-
96
- ```javascript
97
- let layout = database.getLayout("Your layout name")
98
- let query = layout.records.list({
99
- portals: {
100
- test: {limit: 10, offset: 1} // Include results from the 'test' portal
101
- },
102
- limit: 10, // Limit result set to 10 records...
103
- offset: 30 // ...starting from the 30th record
104
- })
105
-
106
- let records = await query.fetch()
107
- console.log(records)
108
- ```
109
-
110
- ### Searching for records
111
-
112
- Searching for records uses the same syntax as above, but with additional steps to add your search parameters.
113
-
114
- ```javascript
115
- let layout = database.getLayout("Your layout name")
116
- let query = layout.records.list({
117
- portals: {
118
- test: {limit: 10, offset: 1} // Include results from the 'test' portal
119
- },
120
- limit: 10, // Limit result set to 10 records...
121
- offset: 30 // ...starting from the 30th record
122
- })
123
-
124
- query.addRequest({"GroupID": "=abc"}) // Add a filter
125
-
126
- let records = await query.fetch()
127
- console.log(records)
128
- ```
129
-
130
- ### Fetch a record using its record ID (NOT RECOMMENDED)
131
-
132
- > Please note: When in FileMaker Pro, a record's ID is returned when using Get(RecordID). If you need to fetch a record
133
- > using a different ID, use the search method above.
134
-
135
- ```javascript
136
- let layout = database.getLayout("Your layout name")
137
- let record = await layout.records.get(164)
138
- console.log(record)
139
- ```
140
-
141
- ### Create a record
142
-
143
- ```javascript
144
- let layout = database.getLayout("Your layout name")
145
- let record = await layout.records.create()
146
-
147
- record.fields["Field1"].value = "Value here"
148
- record.fields["Field2"].value = "Value here"
149
- record.fields["Field3"].value = "Value here"
150
-
151
- await record.commit()
152
- ```
153
-
154
- ### Modify a record
155
-
156
- ```javascript
157
- let layout = database.getLayout("Your layout name")
158
- let record = await layout.records.get(164)
159
-
160
- record.fields["Field1"].value = "Value here"
161
- record.fields["Field2"].value = "Value here"
162
- record.fields["Field3"].value = "Value here"
163
-
164
- await record.commit()
165
- ```
166
-
167
- # Field names
168
-
169
- When interacting with FileMaker, it is important to remember how FileMaker field names work.
170
-
171
- | Field name format | Use when.... |
172
- |-------------------------------|-----------------------------------------------------------------------------------------------------|
173
- | `FieldName` | Use this when the field you are accessing is in the same table that the layout has been assigned to |
174
- | `RelatedTableName::FieldName` | Use this when the field **is not** in the same table that the layout has been assigned to |
175
-
176
- > **NOTE:** You will not be able to access any fields that are not on the layout.
177
-
178
- # Portal names
179
-
180
- > Please read this section carefully if you are working with portals
181
-
182
- It is important to note that a portal's name **is not** the same as the name of the table that it links to. The name of
183
- a
184
- portal matches the object name it was assigned in FileMaker's layout editor.
185
-
186
- > **NOTE**: When no name has been manually assigned to it, it will default to the name of the related table.
187
-
188
- # Typescript Implementation
189
-
190
- `easy-fm` supports the use of TypeScript. Here's an example of how this works with `easy-fm`:
191
-
192
- ```typescript
193
- import FMHost, {Portal, Field, Container} from "@jd-data-limited/easy-fm";
194
-
195
- interface UsersLayout {
196
- fields: {
197
- // Map each field on the layout to a field type.
198
- first_name: Field<string>
199
- age: Field<number>
200
- birthdate: Field<Date>
201
- profile_picture: Field<Container>
202
- "MyRelatedTable::MyRelatedField": Field<string>
203
- },
204
- portals: {
205
- Files: {
206
- "Files::Field1": Field<string>
207
- }
208
- }
209
- }
210
-
211
- interface DatabaseStructure {
212
- layouts: {
213
- users: UsersLayout
214
- }
215
- }
216
-
217
- const host = new FMHost("https://example_filemaker_server.com")
218
- const database = host.database<DatabaseStructure>({
219
- database: "ExampleDatabase.fmp12",
220
- credentials: {method: "filemaker", username: "test", passsword: "test"},
221
- externalSources: []
222
- })
223
- await database.login()
224
-
225
- const layout = database.getLayout("users") // The UsersLayout interface will be automatically applied to all records within this layout
226
- const record = await layout.records.create()
227
- record.fields["first_name"].value = "Joe"
228
- record.fields["age"].value = 38
229
- ```
1
+ # Introduction
2
+
3
+ A FileMaker Data API client for NodeJS
4
+
5
+ easy-fm is a Node.js module that allows you to interact with
6
+ a FileMaker database stored on a FileMaker server
7
+ or FileMaker Cloud. This module interacts with your server using the
8
+ FileMaker Data API.
9
+
10
+ # Contents
11
+
12
+ <!-- TOC -->
13
+ * [Introduction](#introduction)
14
+ * [Contents](#contents)
15
+ * [Installation](#installation)
16
+ * [Usage](#usage)
17
+ * [Connecting to a database](#connecting-to-a-database)
18
+ * [An important note about timezones](#an-important-note-about-timezones)
19
+ * [Getting records](#getting-records)
20
+ * [Fetch a range of records](#fetch-a-range-of-records)
21
+ * [Searching for records](#searching-for-records)
22
+ * [Fetch a record using its record ID (NOT RECOMMENDED)](#fetch-a-record-using-its-record-id-not-recommended)
23
+ * [Create a record](#create-a-record)
24
+ * [Modify a record](#modify-a-record)
25
+ * [Field names](#field-names)
26
+ * [Portal names](#portal-names)
27
+ * [Typescript Implementation](#typescript-implementation)
28
+ <!-- TOC -->
29
+
30
+ # Installation
31
+
32
+ ```npm
33
+ npm install @jd-data-limited/easy-fm --save
34
+ ```
35
+
36
+ easy-fm also requires the following to be configured within your FileMaker enviroment:
37
+
38
+ 1. Enable the FileMaker Data API from the server's admin console. This setting is located
39
+ in `Connectors > FileMaker Data API`.
40
+ 2. Create a FileMaker database account for easy-fm to use. This account must have the 'Access via FileMaker Data API (
41
+ fmrest)' extended privilege
42
+
43
+ ---
44
+
45
+ # Usage
46
+
47
+ ## Connecting to a database
48
+
49
+ ```javascript
50
+ import FMHost from "easy-fm"; // Import the module
51
+ const host = new FMHost("https://<your-servers-address>")
52
+ const database = host.database({
53
+ database: "your_database.fmp12",
54
+ credentials: {
55
+ method: "filemaker",
56
+ username: "<username>",
57
+ password: "<password>"
58
+ },
59
+ externalSources: []
60
+ })
61
+
62
+ // OPTIONAL - EasyFM will automatically attempt a login anyway when you perform your first operation
63
+ database.login().then(() => {
64
+
65
+ })
66
+ ```
67
+
68
+ > **NOTE:** A connection will only give you access to the layouts in the database you are connected to, and not the
69
+ > layouts
70
+ > in
71
+ > any external sources that you have specified.
72
+ >
73
+ > If you need to interact with layouts on multiple databases, you need to open a separate connection for each.
74
+
75
+ ## An important note about timezones
76
+
77
+ Although it is recommended, timestamps in FileMaker databases are not always stored in UTC time. To account for this,
78
+ EasyFM allows you to specify a function/method that determines the server's current timezone.
79
+ EasyFM will use this timezone offset to convert timestamps to and from JavaScript Date objects.
80
+
81
+ ```typescript
82
+ import FMHost from "easy-fm";
83
+ import {type Moment} from 'moment'
84
+
85
+ const host = new FMHost("https://<your-servers-address>", (moment: Moment) => {
86
+
87
+ })
88
+ ```
89
+
90
+ ## Getting records
91
+
92
+ One of (if not the) most common interactions you'll need to use is fetching records.
93
+
94
+ ### Fetch a range of records
95
+
96
+ ```javascript
97
+ let layout = database.getLayout("Your layout name")
98
+ let query = layout.records.list({
99
+ portals: {
100
+ test: {limit: 10, offset: 1} // Include results from the 'test' portal
101
+ },
102
+ limit: 10, // Limit result set to 10 records...
103
+ offset: 30 // ...starting from the 30th record
104
+ })
105
+
106
+ let records = await query.fetch()
107
+ console.log(records)
108
+ ```
109
+
110
+ ### Searching for records
111
+
112
+ Searching for records uses the same syntax as above, but with additional steps to add your search parameters.
113
+
114
+ ```javascript
115
+ let layout = database.getLayout("Your layout name")
116
+ let query = layout.records.list({
117
+ portals: {
118
+ test: {limit: 10, offset: 1} // Include results from the 'test' portal
119
+ },
120
+ limit: 10, // Limit result set to 10 records...
121
+ offset: 30 // ...starting from the 30th record
122
+ })
123
+
124
+ query.addRequest({"GroupID": "=abc"}) // Add a filter
125
+
126
+ let records = await query.fetch()
127
+ console.log(records)
128
+ ```
129
+
130
+ ### Fetch a record using its record ID (NOT RECOMMENDED)
131
+
132
+ > Please note: When in FileMaker Pro, a record's ID is returned when using Get(RecordID). If you need to fetch a record
133
+ > using a different ID, use the search method above.
134
+
135
+ ```javascript
136
+ let layout = database.getLayout("Your layout name")
137
+ let record = await layout.records.get(164)
138
+ console.log(record)
139
+ ```
140
+
141
+ ### Create a record
142
+
143
+ ```javascript
144
+ let layout = database.getLayout("Your layout name")
145
+ let record = await layout.records.create()
146
+
147
+ record.fields["Field1"].value = "Value here"
148
+ record.fields["Field2"].value = "Value here"
149
+ record.fields["Field3"].value = "Value here"
150
+
151
+ await record.commit()
152
+ ```
153
+
154
+ ### Modify a record
155
+
156
+ ```javascript
157
+ let layout = database.getLayout("Your layout name")
158
+ let record = await layout.records.get(164)
159
+
160
+ record.fields["Field1"].value = "Value here"
161
+ record.fields["Field2"].value = "Value here"
162
+ record.fields["Field3"].value = "Value here"
163
+
164
+ await record.commit()
165
+ ```
166
+
167
+ # Field names
168
+
169
+ When interacting with FileMaker, it is important to remember how FileMaker field names work.
170
+
171
+ | Field name format | Use when.... |
172
+ |-------------------------------|-----------------------------------------------------------------------------------------------------|
173
+ | `FieldName` | Use this when the field you are accessing is in the same table that the layout has been assigned to |
174
+ | `RelatedTableName::FieldName` | Use this when the field **is not** in the same table that the layout has been assigned to |
175
+
176
+ > **NOTE:** You will not be able to access any fields that are not on the layout.
177
+
178
+ # Portal names
179
+
180
+ > Please read this section carefully if you are working with portals
181
+
182
+ It is important to note that a portal's name **is not** the same as the name of the table that it links to. The name of
183
+ a
184
+ portal matches the object name it was assigned in FileMaker's layout editor.
185
+
186
+ > **NOTE**: When no name has been manually assigned to it, it will default to the name of the related table.
187
+
188
+ # Typescript Implementation
189
+
190
+ `easy-fm` supports the use of TypeScript. Here's an example of how this works with `easy-fm`:
191
+
192
+ ```typescript
193
+ import FMHost, {Portal, Field, Container} from "@jd-data-limited/easy-fm";
194
+
195
+ interface UsersLayout {
196
+ fields: {
197
+ // Map each field on the layout to a field type.
198
+ first_name: Field<string>
199
+ age: Field<number>
200
+ birthdate: Field<Date>
201
+ profile_picture: Field<Container>
202
+ "MyRelatedTable::MyRelatedField": Field<string>
203
+ },
204
+ portals: {
205
+ Files: {
206
+ "Files::Field1": Field<string>
207
+ }
208
+ }
209
+ }
210
+
211
+ interface DatabaseStructure {
212
+ layouts: {
213
+ users: UsersLayout
214
+ }
215
+ }
216
+
217
+ const host = new FMHost("https://example_filemaker_server.com")
218
+ const database = host.database<DatabaseStructure>({
219
+ database: "ExampleDatabase.fmp12",
220
+ credentials: {method: "filemaker", username: "test", passsword: "test"},
221
+ externalSources: []
222
+ })
223
+ await database.login()
224
+
225
+ const layout = database.getLayout("users") // The UsersLayout interface will be automatically applied to all records within this layout
226
+ const record = await layout.records.create()
227
+ record.fields["first_name"].value = "Joe"
228
+ record.fields["age"].value = 38
229
+ ```
package/dist/bin/cli.js CHANGED
File without changes
@@ -129,9 +129,9 @@ export async function generateTypesCLI() {
129
129
  const interfaceName = substituteName + 'LayoutInterface';
130
130
  layoutInterfaces.set(layout.name, {
131
131
  interfaceName,
132
- interface: `export interface ${interfaceName} extends LayoutInterface {
133
- fields: {${fields.join(',\n ')}},
134
- portals: {${portalsProcessed.join(',\n ')}}
132
+ interface: `export interface ${interfaceName} extends LayoutInterface {
133
+ fields: {${fields.join(',\n ')}},
134
+ portals: {${portalsProcessed.join(',\n ')}}
135
135
  }`
136
136
  });
137
137
  }
@@ -75,11 +75,23 @@ export declare class RecordGetOperation<T extends LayoutInterface, OPTIONS exten
75
75
  */
76
76
  fetch(): Promise<LayoutRecord<PickPortals<T, keyof OPTIONS["portals"]>>[]>;
77
77
  private performFind;
78
+ /**
79
+ * Creates an iterator that iterates throguh all results
80
+ * @param pageSize min: 1, max: 999
81
+ */
82
+ iterate(pageSize?: number): {
83
+ next: () => Promise<{
84
+ done: boolean;
85
+ value: LayoutRecord<PickPortals<T, keyof OPTIONS["portals"]>> | undefined;
86
+ }>;
87
+ [Symbol.asyncIterator](): /*elided*/ any;
88
+ };
78
89
  [Symbol.asyncIterator](): {
79
90
  next: () => Promise<{
80
91
  done: boolean;
81
92
  value: LayoutRecord<PickPortals<T, keyof OPTIONS["portals"]>> | undefined;
82
93
  }>;
94
+ [Symbol.asyncIterator](): /*elided*/ any;
83
95
  };
84
96
  }
85
97
  export {};
@@ -197,7 +197,11 @@ export class RecordGetOperation {
197
197
  throw e;
198
198
  }
199
199
  }
200
- [Symbol.asyncIterator]() {
200
+ /**
201
+ * Creates an iterator that iterates throguh all results
202
+ * @param pageSize min: 1, max: 999
203
+ */
204
+ iterate(pageSize = 100) {
201
205
  let nextOffset = this.offset;
202
206
  const startOffset = JSON.parse(JSON.stringify(this.offset));
203
207
  const limit = this.limit;
@@ -210,12 +214,13 @@ export class RecordGetOperation {
210
214
  records = [];
211
215
  return;
212
216
  }
213
- records = await this.performFind(nextOffset, theoreticalLimit < 100 ? theoreticalLimit : 100);
214
- nextOffset += 100;
215
- if (records.length < 100)
217
+ const requestLimit = Math.min(theoreticalLimit, pageSize);
218
+ records = await this.performFind(nextOffset, requestLimit);
219
+ nextOffset += pageSize;
220
+ if (records.length < requestLimit)
216
221
  exitAfterLastRecord = true;
217
222
  };
218
- return {
223
+ const iterator = {
219
224
  next: async () => {
220
225
  if (records.length === 0 && !exitAfterLastRecord) {
221
226
  await fetch();
@@ -227,7 +232,14 @@ export class RecordGetOperation {
227
232
  const record = records.shift();
228
233
  return { done: false, value: record };
229
234
  }
235
+ },
236
+ [Symbol.asyncIterator]() {
237
+ return this;
230
238
  }
231
239
  };
240
+ return iterator;
241
+ }
242
+ [Symbol.asyncIterator]() {
243
+ return this.iterate();
232
244
  }
233
245
  }
package/dist/types.d.ts CHANGED
@@ -61,8 +61,8 @@ export interface extraBodyOptions {
61
61
  * user (default) - Follow this rule
62
62
  * script - Ignore this rule
63
63
  */
64
- prohibitMode?: 'user' | 'script';
65
- };
64
+ prohibitmode?: 'user' | 'script';
65
+ } & Record<string, any>;
66
66
  deleteRelatedRecords?: Array<{
67
67
  table: string;
68
68
  recordId: number;
package/package.json CHANGED
@@ -1,73 +1,73 @@
1
- {
2
- "name": "@jd-data-limited/easy-fm",
3
- "version": "4.1.12",
4
- "dependencies": {
5
- "@types/follow-redirects": "^1.14.4",
6
- "@types/node": "^22.7.7",
7
- "commander": "^14.0.0",
8
- "follow-redirects": "^1.15.5",
9
- "moment": "^2.29.4",
10
- "node-fetch": "^3.3.2",
11
- "node-fetch-cookies": "^2.1.1"
12
- },
13
- "type": "module",
14
- "main": "dist/index.js",
15
- "module": "es2022",
16
- "homepage": "https://jd-data.com/project/easyfm/",
17
- "url": "https://github.com/JD-Data-Limited/easy-fm",
18
- "license": "SEE LICENSE IN LICENSE",
19
- "description": "easy-fm is a Node.js module that allows you to interact with\r a [FileMaker database stored](https://www.claris.com/filemaker/) on\r a [FileMaker server](https://www.claris.com/filemaker/server/). This module interacts with your server using the\r [FileMaker Data API](https://help.claris.com/en/data-api-guide/content/index.html).",
20
- "files": [
21
- "./dist/**/*"
22
- ],
23
- "scripts": {
24
- "build": "tsc",
25
- "test": "npm run build && jest"
26
- },
27
- "repository": {
28
- "type": "git",
29
- "url": "git+https://github.com/JD-Data-Limited/easy-fm.git"
30
- },
31
- "keywords": [
32
- "FileMaker",
33
- "Data",
34
- "API",
35
- "REST",
36
- "simplicity",
37
- "business"
38
- ],
39
- "author": "JD-Data Limited",
40
- "bugs": {
41
- "url": "https://github.com/JD-Data-Limited/easy-fm/issues"
42
- },
43
- "engines": {
44
- "node": ">=20.9.0"
45
- },
46
- "devDependencies": {
47
- "@babel/cli": "^7.25.7",
48
- "@babel/core": "^7.25.8",
49
- "@babel/preset-env": "^7.25.8",
50
- "@babel/preset-typescript": "^7.25.7",
51
- "@types/btoa": "^1.2.3",
52
- "@types/events": "^3.0.0",
53
- "@types/inquirer": "^9.0.7",
54
- "@types/jest": "^29.5.13",
55
- "@typescript-eslint/eslint-plugin": "^6.21.0",
56
- "babel-jest": "^29.7.0",
57
- "dotenv": "^16.3.1",
58
- "eslint": "^8.57.0",
59
- "eslint-config-standard-with-typescript": "^43.0.1",
60
- "eslint-plugin-import": "^2.29.1",
61
- "eslint-plugin-n": "^16.6.2",
62
- "eslint-plugin-promise": "^6.1.1",
63
- "inquirer": "^9.2.13",
64
- "jest": "^29.7.0",
65
- "ts-jest": "^29.2.5",
66
- "ts-morph": "^21.0.1",
67
- "tsx": "^4.19.4",
68
- "typescript": "^5.6.3"
69
- },
70
- "bin": {
71
- "easyfm": "dist/bin/cli.js"
72
- }
73
- }
1
+ {
2
+ "name": "@jd-data-limited/easy-fm",
3
+ "version": "4.1.14",
4
+ "dependencies": {
5
+ "@types/follow-redirects": "^1.14.4",
6
+ "@types/node": "^22.7.7",
7
+ "commander": "^14.0.0",
8
+ "follow-redirects": "^1.15.5",
9
+ "moment": "^2.29.4",
10
+ "node-fetch": "^3.3.2",
11
+ "node-fetch-cookies": "^2.1.1"
12
+ },
13
+ "type": "module",
14
+ "main": "dist/index.js",
15
+ "module": "es2022",
16
+ "homepage": "https://jd-data.com/project/easyfm/",
17
+ "url": "https://github.com/JD-Data-Limited/easy-fm",
18
+ "license": "SEE LICENSE IN LICENSE",
19
+ "description": "easy-fm is a Node.js module that allows you to interact with\r a [FileMaker database stored](https://www.claris.com/filemaker/) on\r a [FileMaker server](https://www.claris.com/filemaker/server/). This module interacts with your server using the\r [FileMaker Data API](https://help.claris.com/en/data-api-guide/content/index.html).",
20
+ "files": [
21
+ "./dist/**/*"
22
+ ],
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/JD-Data-Limited/easy-fm.git"
26
+ },
27
+ "keywords": [
28
+ "FileMaker",
29
+ "Data",
30
+ "API",
31
+ "REST",
32
+ "simplicity",
33
+ "business"
34
+ ],
35
+ "author": "JD-Data Limited",
36
+ "bugs": {
37
+ "url": "https://github.com/JD-Data-Limited/easy-fm/issues"
38
+ },
39
+ "engines": {
40
+ "node": ">=20.9.0"
41
+ },
42
+ "devDependencies": {
43
+ "@babel/cli": "^7.25.7",
44
+ "@babel/core": "^7.25.8",
45
+ "@babel/preset-env": "^7.25.8",
46
+ "@babel/preset-typescript": "^7.25.7",
47
+ "@types/btoa": "^1.2.3",
48
+ "@types/events": "^3.0.0",
49
+ "@types/inquirer": "^9.0.7",
50
+ "@types/jest": "^29.5.13",
51
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
52
+ "babel-jest": "^29.7.0",
53
+ "dotenv": "^16.3.1",
54
+ "eslint": "^8.57.0",
55
+ "eslint-config-standard-with-typescript": "^43.0.1",
56
+ "eslint-plugin-import": "^2.29.1",
57
+ "eslint-plugin-n": "^16.6.2",
58
+ "eslint-plugin-promise": "^6.1.1",
59
+ "inquirer": "^9.2.13",
60
+ "jest": "^29.7.0",
61
+ "ts-jest": "^29.2.5",
62
+ "ts-morph": "^21.0.1",
63
+ "tsx": "^4.19.4",
64
+ "typescript": "^5.6.3"
65
+ },
66
+ "bin": {
67
+ "easyfm": "dist/bin/cli.js"
68
+ },
69
+ "scripts": {
70
+ "build": "tsc",
71
+ "test": "npm run build && jest"
72
+ }
73
+ }