@jd-data-limited/easy-fm 0.0.1
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/.idea/easy-fm.iml +8 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/LICENSE +21 -0
- package/README.md +64 -0
- package/decs.d.ts +4 -0
- package/fmErrors.json +1010 -0
- package/img.png +0 -0
- package/index.js +455 -0
- package/index.ts +533 -0
- package/package.json +34 -0
- package/tsconfig.json +8 -0
package/index.ts
ADDED
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
// const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
|
|
2
|
+
import fetch, {
|
|
3
|
+
Blob,
|
|
4
|
+
blobFrom,
|
|
5
|
+
blobFromSync,
|
|
6
|
+
File,
|
|
7
|
+
fileFrom,
|
|
8
|
+
fileFromSync,
|
|
9
|
+
FormData,
|
|
10
|
+
Headers,
|
|
11
|
+
Request,
|
|
12
|
+
Response
|
|
13
|
+
} from 'node-fetch';
|
|
14
|
+
import { EventEmitter } from "events";
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
import fs from "fs"
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
import path from "path"
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
import { fileURLToPath } from "url"
|
|
21
|
+
import btoa = require("btoa");
|
|
22
|
+
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
const errs = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'fmErrors.json')).toString())
|
|
25
|
+
|
|
26
|
+
interface Script {
|
|
27
|
+
name: string
|
|
28
|
+
parameter: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface recordObject {
|
|
32
|
+
recordId: number
|
|
33
|
+
modId: number,
|
|
34
|
+
fieldData: any
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default class FileMakerConnection {
|
|
38
|
+
public hostname: string;
|
|
39
|
+
public database: string;
|
|
40
|
+
public token: any;
|
|
41
|
+
private username: any;
|
|
42
|
+
private password: any;
|
|
43
|
+
private rejectUnauthroized: boolean;
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get endpoint(): string {
|
|
49
|
+
return `https://${this.hostname}/fmi/data/v2/databases/${encodeURI(this.database)}`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async login(hostname, database, username, password, rejectUnauthorized = true) {
|
|
53
|
+
if (this.token) throw new Error("Already logged in. Run logout() first")
|
|
54
|
+
|
|
55
|
+
this.username = username
|
|
56
|
+
this.password = password
|
|
57
|
+
this.hostname = hostname
|
|
58
|
+
this.database = database
|
|
59
|
+
this.rejectUnauthroized = rejectUnauthorized
|
|
60
|
+
|
|
61
|
+
return await this.createSession()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
logout(): Promise<void> {
|
|
65
|
+
return new Promise(async (resolve, reject) => {
|
|
66
|
+
if (!this.token) reject(new Error("Not logged in"))
|
|
67
|
+
|
|
68
|
+
let _fetch = await fetch(`${this.endpoint}/sessions/${this.token}`, {
|
|
69
|
+
method: "DELETE",
|
|
70
|
+
headers: {
|
|
71
|
+
"content-type": "application/json"
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
let data = await _fetch.json()
|
|
75
|
+
// console.log(data)
|
|
76
|
+
this.token = null
|
|
77
|
+
this.database = null
|
|
78
|
+
this.hostname = null
|
|
79
|
+
resolve()
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
importSession(hostname, database, token, rejectUnauthorized = true) {
|
|
84
|
+
this.token = token
|
|
85
|
+
this.database = database
|
|
86
|
+
this.hostname = hostname
|
|
87
|
+
this.rejectUnauthroized = rejectUnauthorized
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private createSession(): Promise<string> {
|
|
91
|
+
return new Promise(async (resolve, reject) => {
|
|
92
|
+
fetch(`${this.endpoint}/sessions`, {
|
|
93
|
+
hostname: this.hostname,
|
|
94
|
+
port: 443,
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: {
|
|
97
|
+
"Content-Type": "application/json",
|
|
98
|
+
"Authorization": "Basic " + btoa(this.username + ":" + this.password)
|
|
99
|
+
}
|
|
100
|
+
}).then(res => {
|
|
101
|
+
console.log(res)
|
|
102
|
+
return res.json()
|
|
103
|
+
})
|
|
104
|
+
.then(res => {
|
|
105
|
+
let _res = res as any
|
|
106
|
+
if (_res.messages[0].code === "0") {
|
|
107
|
+
this.token = _res.response.token
|
|
108
|
+
console.log(_res)
|
|
109
|
+
resolve(this.token)
|
|
110
|
+
} else {
|
|
111
|
+
reject(new FMError(_res.messages[0].code, _res.status, res))
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
.catch(e => {
|
|
115
|
+
reject(e)
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getLayout(name) {
|
|
121
|
+
return new layout(this, name)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async apiRequest(url, options): Promise<any> {
|
|
125
|
+
if (!options.headers) options.headers = {}
|
|
126
|
+
options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json"
|
|
127
|
+
options.headers["authorization"] = "Bearer " + this.token
|
|
128
|
+
options.rejectUnauthorized = this.rejectUnauthroized
|
|
129
|
+
|
|
130
|
+
let _fetch = await fetch(url, options)
|
|
131
|
+
let data = await _fetch.json()
|
|
132
|
+
return (data as any)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
setGlobals(globalFields): Promise<void> {
|
|
136
|
+
// console.log({globalFields})
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
this.apiRequest(`${this.endpoint}/globals`, {
|
|
139
|
+
method: "PATCH",
|
|
140
|
+
body: JSON.stringify({globalFields})
|
|
141
|
+
}).then(res => {
|
|
142
|
+
// console.log(res)
|
|
143
|
+
if (res.messages[0].code === "0") {
|
|
144
|
+
resolve()
|
|
145
|
+
} else {
|
|
146
|
+
reject(new FMError(res.messages[0].code, res.status, res))
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
.catch(e => {
|
|
150
|
+
reject(e)
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
script(name, parameter): Script {
|
|
156
|
+
return ({name, parameter} as Script)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
class layout {
|
|
161
|
+
readonly conn: FileMakerConnection;
|
|
162
|
+
protected name: string;
|
|
163
|
+
constructor(conn: FileMakerConnection, name: string) {
|
|
164
|
+
this.conn = conn
|
|
165
|
+
this.name = name
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
get endpoint() {
|
|
169
|
+
return `${this.conn.endpoint}/layouts/${this.name}`
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
getScript(script) {
|
|
173
|
+
return new script(this, script)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
createRecord(body = {}): Promise<record | Error> {
|
|
177
|
+
// console.log(fieldData)
|
|
178
|
+
return new Promise(async (resolve, reject) => {
|
|
179
|
+
this.conn.apiRequest(`${this.endpoint}/records`, {
|
|
180
|
+
port: 443,
|
|
181
|
+
method: "POST",
|
|
182
|
+
body: JSON.stringify(body)
|
|
183
|
+
})
|
|
184
|
+
.then(res => {
|
|
185
|
+
if (res.messages[0].code === "0") {
|
|
186
|
+
resolve(
|
|
187
|
+
new record(this, res.response.recordId, res.response.modId)
|
|
188
|
+
)
|
|
189
|
+
} else {
|
|
190
|
+
reject(new FMError(res.messages[0].code, res.status, res))
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
.catch(e => {
|
|
194
|
+
reject(e)
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
getRecord(recordId): record {
|
|
200
|
+
return new record(this, recordId)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
newFind(): find {
|
|
204
|
+
return new find(this)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
runScript(script): Promise<string | FMError | Error> {
|
|
208
|
+
return new Promise(async (resolve, reject) => {
|
|
209
|
+
let url = `${this.endpoint}/script/${encodeURI(script.name)}`
|
|
210
|
+
if (script.parameter) url += "?" + encodeURI(script.parameter)
|
|
211
|
+
this.conn.apiRequest(url, {
|
|
212
|
+
port: 443,
|
|
213
|
+
method: "GET"
|
|
214
|
+
})
|
|
215
|
+
.then(res => {
|
|
216
|
+
if (res.messages[0].code === "0") {
|
|
217
|
+
resolve(res.response)
|
|
218
|
+
} else {
|
|
219
|
+
// console.log(res)
|
|
220
|
+
reject(new FMError(res.messages[0].code, res.status, res))
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
.catch(e => {
|
|
224
|
+
reject(e)
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
class record extends EventEmitter {
|
|
231
|
+
readonly layout: layout;
|
|
232
|
+
readonly recordId: number;
|
|
233
|
+
modId: number;
|
|
234
|
+
fields: field[];
|
|
235
|
+
readonly portals: portal[];
|
|
236
|
+
private portalData: any[];
|
|
237
|
+
|
|
238
|
+
constructor(layout, recordId, modId = recordId, fieldData = {}, portalData = null) {
|
|
239
|
+
super();
|
|
240
|
+
this.layout = layout
|
|
241
|
+
this.recordId = recordId
|
|
242
|
+
this.modId = modId
|
|
243
|
+
this.fields = this.processFieldData(fieldData)
|
|
244
|
+
this.portals = []
|
|
245
|
+
if (portalData) {
|
|
246
|
+
this.processPortalData(portalData)
|
|
247
|
+
}
|
|
248
|
+
this.on("saved", () => {
|
|
249
|
+
for (let field of this.fields) field.edited = false
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
get endpoint(): string {
|
|
254
|
+
return `${this.layout.endpoint}/records/${this.recordId}`
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
get edited(): boolean {
|
|
258
|
+
return !!this.fields.find(i => i.edited)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private processPortalData(portalData): void {
|
|
262
|
+
for (let item of Object.keys(portalData)) {
|
|
263
|
+
this.portals.push(new portal(this, item, portalData[item].map(item => {
|
|
264
|
+
let fieldData = item
|
|
265
|
+
delete fieldData.recordId
|
|
266
|
+
delete fieldData.modId
|
|
267
|
+
return new portalItem(this, item.recordId, item.modId, fieldData)
|
|
268
|
+
})))
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
processFieldData(fieldData): field[] {
|
|
273
|
+
return Object.keys(fieldData).map(item => {
|
|
274
|
+
return new field(this, item, fieldData[item])
|
|
275
|
+
})
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
get() {
|
|
279
|
+
return new Promise(async (resolve, reject) => {
|
|
280
|
+
this.layout.conn.apiRequest(this.endpoint, {
|
|
281
|
+
port: 443,
|
|
282
|
+
method: "GET"
|
|
283
|
+
})
|
|
284
|
+
.then(res => {
|
|
285
|
+
if (res.messages[0].code === "0") {
|
|
286
|
+
// console.log(res, res.response.data)
|
|
287
|
+
this.modId = res.response.data[0].modId
|
|
288
|
+
this.fields = this.processFieldData(res.response.data[0].fieldData)
|
|
289
|
+
this.portalData = []
|
|
290
|
+
if (res.response.data[0].portalData) this.processPortalData(res.response.data[0].portalData)
|
|
291
|
+
resolve(this)
|
|
292
|
+
} else {
|
|
293
|
+
reject(new FMError(res.messages[0].code, res.status, res))
|
|
294
|
+
}
|
|
295
|
+
})
|
|
296
|
+
.catch(e => {
|
|
297
|
+
reject(e)
|
|
298
|
+
})
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
save(extraBody = {}) {
|
|
303
|
+
return new Promise(async (resolve, reject) => {
|
|
304
|
+
let data = this.toObject()
|
|
305
|
+
delete data.recordId
|
|
306
|
+
delete data.modId
|
|
307
|
+
|
|
308
|
+
for (let item of Object.keys(extraBody)) data[item] = extraBody[item]
|
|
309
|
+
this.layout.conn.apiRequest(this.endpoint, {
|
|
310
|
+
port: 443,
|
|
311
|
+
method: "PATCH",
|
|
312
|
+
body: JSON.stringify(data)
|
|
313
|
+
})
|
|
314
|
+
.then(res => {
|
|
315
|
+
if (res.messages[0].code === "0") {
|
|
316
|
+
this.modId = res.response.modId
|
|
317
|
+
this.emit("saved")
|
|
318
|
+
resolve(this)
|
|
319
|
+
} else {
|
|
320
|
+
reject(new FMError(res.messages[0].code, res.status, res))
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
.catch(e => {
|
|
324
|
+
reject(e)
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
getField(field) {
|
|
330
|
+
return this.fields.find(_field => _field.id === field)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
getPortal(portal) {
|
|
334
|
+
return this.portals.find(p => p.name === portal)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
toObject(filter = (a) => a.edited,
|
|
338
|
+
portalFilter = (a) => a.records.find(record => record.edited),
|
|
339
|
+
portalRowFilter = (a) => a.edited,
|
|
340
|
+
portalFieldFilter = (a) => a.edited
|
|
341
|
+
): recordObject {
|
|
342
|
+
let fields_processed = {}
|
|
343
|
+
for (let field of this.fields.filter(field => filter(field))) {
|
|
344
|
+
fields_processed[field.id] = field.value
|
|
345
|
+
}
|
|
346
|
+
let obj = {
|
|
347
|
+
"recordId": this.recordId,
|
|
348
|
+
"modId": this.modId,
|
|
349
|
+
"fieldData": fields_processed
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Check if there's been any edited portal information
|
|
353
|
+
let portals = this.portals.filter(a => portalFilter(a))
|
|
354
|
+
if (portals) {
|
|
355
|
+
obj["portalData"] = {}
|
|
356
|
+
for (let portal of portals) {
|
|
357
|
+
obj["portalData"][portal.name] = portal.records.filter(a => portalRowFilter(a)).map(record => {
|
|
358
|
+
return record.toObject(portalFieldFilter)
|
|
359
|
+
})
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return obj
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
class field {
|
|
367
|
+
record: record;
|
|
368
|
+
id: number;
|
|
369
|
+
value: string | number;
|
|
370
|
+
edited: boolean;
|
|
371
|
+
constructor(record, id, contents) {
|
|
372
|
+
this.record = record
|
|
373
|
+
this.id = id
|
|
374
|
+
this.value = contents
|
|
375
|
+
this.edited = false
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
set(content) {
|
|
379
|
+
this.value = content
|
|
380
|
+
this.edited = true
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
containerUpload(buffer, filename, mime): Promise<void | FMError> {
|
|
384
|
+
return new Promise(async (resolve, reject) => {
|
|
385
|
+
let form = new FormData()
|
|
386
|
+
form.append("upload", new File([buffer], filename, {type: mime}))
|
|
387
|
+
|
|
388
|
+
let _fetch = await fetch(`${this.record.endpoint}/containers/${this.id}/1`, {
|
|
389
|
+
method: "POST",
|
|
390
|
+
headers: {"Authorization": "Bearer " + this.record.layout.conn.token},
|
|
391
|
+
body: form
|
|
392
|
+
}).then(res => res.json())
|
|
393
|
+
.then(data => {
|
|
394
|
+
let _res = data as any
|
|
395
|
+
if (_res.messages[0].code === "0") {
|
|
396
|
+
resolve()
|
|
397
|
+
} else {
|
|
398
|
+
reject(new FMError(_res.messages[0].code, _res.status, data))
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
.catch(e => {reject(e)})
|
|
402
|
+
})
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
class portal {
|
|
407
|
+
readonly record: record;
|
|
408
|
+
readonly name: string;
|
|
409
|
+
public records: portalItem[];
|
|
410
|
+
|
|
411
|
+
constructor(record: record, name: string, records: portalItem[] = []) {
|
|
412
|
+
this.record = record
|
|
413
|
+
this.name = name
|
|
414
|
+
this.records = records
|
|
415
|
+
for (let item of this.records) item.attachPortal(this)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
class portalItem extends record {
|
|
420
|
+
protected portal: portal;
|
|
421
|
+
|
|
422
|
+
constructor(record, recordId, modId = recordId, fieldData = {}) {
|
|
423
|
+
super(record.layout, recordId, modId, fieldData);
|
|
424
|
+
record.on("saved", () => {
|
|
425
|
+
this.emit("saved")
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
attachPortal(portal) {
|
|
430
|
+
this.portal = portal
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
save(extraBody = {}) {
|
|
434
|
+
return this.portal.record.save(extraBody)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
toObject(fieldFilter): any {
|
|
438
|
+
super.toObject()
|
|
439
|
+
let res = {
|
|
440
|
+
recordId: this.recordId, modId: this.modId
|
|
441
|
+
} as recordObject
|
|
442
|
+
for (let field of this.fields.filter(a => fieldFilter(a))) res[field.id] = field.value
|
|
443
|
+
// console.log(res)
|
|
444
|
+
return res
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
class find {
|
|
449
|
+
protected layout: layout
|
|
450
|
+
protected queries: object[]
|
|
451
|
+
protected scripts: object
|
|
452
|
+
protected sort: object[]
|
|
453
|
+
|
|
454
|
+
constructor(layout) {
|
|
455
|
+
this.layout = layout
|
|
456
|
+
this.queries = []
|
|
457
|
+
this.scripts = {
|
|
458
|
+
"script": null, // Runs after everything
|
|
459
|
+
"script.prerequeset": null, // Runs before the request
|
|
460
|
+
"script.presort": null // Runs before the sort
|
|
461
|
+
}
|
|
462
|
+
this.sort = []
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
private toObject() {
|
|
466
|
+
let out = {query: this.queries, sort: undefined}
|
|
467
|
+
if (this.sort.length !== 0) out.sort = this.sort
|
|
468
|
+
|
|
469
|
+
for (let item of Object.keys(this.scripts)) {
|
|
470
|
+
if (this.scripts[item]) {
|
|
471
|
+
out[item] = this.scripts[item].name
|
|
472
|
+
if (this.scripts[item].parameter) out[item + ".param"] = this.scripts[item].parameter
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return out
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
addRequests(...requests) {
|
|
480
|
+
for (let item of requests) this.queries.push(item)
|
|
481
|
+
return this
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
addSort(fieldName, sortOrder) {
|
|
485
|
+
this.sort.push({fieldName, sortOrder})
|
|
486
|
+
return this
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
find() {
|
|
490
|
+
return new Promise((resolve, reject) => {
|
|
491
|
+
// console.log(this.#toObject())
|
|
492
|
+
this.layout.conn.apiRequest(`${this.layout.endpoint}/_find`, {
|
|
493
|
+
port: 443,
|
|
494
|
+
method: "POST",
|
|
495
|
+
body: JSON.stringify(this.toObject())
|
|
496
|
+
}).then(res => {
|
|
497
|
+
// // console.log(res)
|
|
498
|
+
if (res.messages[0].code === "0") {
|
|
499
|
+
// console.log("RESOLVING")
|
|
500
|
+
let data = res.response.data.map(item => {
|
|
501
|
+
return new record(this.layout, item.recordId, item.modId, item.fieldData, item.portalData)
|
|
502
|
+
})
|
|
503
|
+
resolve(data)
|
|
504
|
+
} else {
|
|
505
|
+
reject(new FMError(res.messages[0].code, res.status, res))
|
|
506
|
+
}
|
|
507
|
+
})
|
|
508
|
+
.catch(e => {
|
|
509
|
+
reject(e)
|
|
510
|
+
})
|
|
511
|
+
})
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export class FMError extends Error {
|
|
516
|
+
readonly httpStatus: number
|
|
517
|
+
readonly res: any
|
|
518
|
+
readonly code: number
|
|
519
|
+
readonly message: string
|
|
520
|
+
|
|
521
|
+
constructor(code, httpStatus, res) {
|
|
522
|
+
super(code);
|
|
523
|
+
this.httpStatus = httpStatus
|
|
524
|
+
this.res = res
|
|
525
|
+
this.code = typeof code === "string" ? parseInt(code) : code
|
|
526
|
+
this.message = errs.find(err => err.e === this.code) || "Unknown error"
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
//
|
|
531
|
+
// module.exports = {
|
|
532
|
+
// default: {FileMakerConnection}
|
|
533
|
+
// }
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jd-data-limited/easy-fm",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@types/btoa": "^1.2.3",
|
|
6
|
+
"@types/events": "^3.0.0",
|
|
7
|
+
"node-fetch": "^3.3.0",
|
|
8
|
+
"typescript": "^4.9.4"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "index.js",
|
|
12
|
+
"module": "es2022",
|
|
13
|
+
"homepage": "https://github.com/JD-Data-Limited/easy-fm",
|
|
14
|
+
"url": "https://github.com/JD-Data-Limited/easy-fm",
|
|
15
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
16
|
+
"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).",
|
|
17
|
+
"devDependencies": {},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/JD-Data-Limited/easy-fm.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"FileMaker",
|
|
27
|
+
"Data API",
|
|
28
|
+
"REST"
|
|
29
|
+
],
|
|
30
|
+
"author": "JD-Data Limited",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/JD-Data-Limited/easy-fm/issues"
|
|
33
|
+
}
|
|
34
|
+
}
|