@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 +21 -21
- package/README.md +229 -229
- package/dist/bin/cli.js +0 -0
- package/dist/bin/generateTypes.js +3 -3
- package/dist/records/getOperations/recordGetOperation.d.ts +12 -0
- package/dist/records/getOperations/recordGetOperation.js +17 -5
- package/dist/types.d.ts +2 -2
- package/package.json +73 -73
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
|
-
|
|
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
|
-
|
|
214
|
-
nextOffset
|
|
215
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
},
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"eslint": "^
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"
|
|
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
|
+
}
|