@jd-data-limited/easy-fm 3.0.10 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.idea/compiler.xml +7 -0
  2. package/.idea/discord.xml +7 -0
  3. package/dist/index.min.js +2 -0
  4. package/dist/index.min.js.LICENSE.txt +3 -0
  5. package/examples/test.js +7 -0
  6. package/img.png +0 -0
  7. package/package.json +1 -1
  8. package/src/FMError.d.ts +12 -0
  9. package/src/FMError.js +1028 -0
  10. package/src/FMError.ts +1035 -0
  11. package/src/connection/FMHost.d.ts +12 -0
  12. package/src/connection/FMHost.js +68 -0
  13. package/src/connection/FMHost.ts +75 -0
  14. package/src/connection/database.d.ts +26 -0
  15. package/src/connection/database.js +195 -0
  16. package/src/connection/database.ts +216 -0
  17. package/src/connection/generateAuthorizationHeaders.d.ts +2 -0
  18. package/src/connection/generateAuthorizationHeaders.js +23 -0
  19. package/src/connection/generateAuthorizationHeaders.ts +32 -0
  20. package/src/index.d.ts +2 -0
  21. package/src/index.js +5 -2076
  22. package/src/index.ts +3 -2324
  23. package/src/layouts/layout.d.ts +29 -0
  24. package/src/layouts/layout.js +84 -0
  25. package/src/layouts/layout.ts +92 -0
  26. package/src/layouts/layoutInterface.d.ts +13 -0
  27. package/src/layouts/layoutInterface.js +4 -0
  28. package/src/layouts/layoutInterface.ts +21 -0
  29. package/src/layouts/layoutRecordManager.d.ts +13 -0
  30. package/src/layouts/layoutRecordManager.js +50 -0
  31. package/src/layouts/layoutRecordManager.ts +59 -0
  32. package/src/records/field.d.ts +21 -0
  33. package/src/records/field.js +177 -0
  34. package/src/records/field.ts +189 -0
  35. package/src/records/getOperations/find.d.ts +15 -0
  36. package/src/records/getOperations/find.js +90 -0
  37. package/src/records/getOperations/find.ts +88 -0
  38. package/src/records/getOperations/recordGetOperation.d.ts +17 -0
  39. package/src/records/getOperations/recordGetOperation.js +43 -0
  40. package/src/records/getOperations/recordGetOperation.ts +54 -0
  41. package/src/records/getOperations/recordGetRange.d.ts +13 -0
  42. package/src/records/getOperations/recordGetRange.js +95 -0
  43. package/src/records/getOperations/recordGetRange.ts +84 -0
  44. package/src/records/layoutRecord.d.ts +16 -0
  45. package/src/records/layoutRecord.js +211 -0
  46. package/src/records/layoutRecord.ts +220 -0
  47. package/src/records/portal.d.ts +10 -0
  48. package/src/records/portal.js +19 -0
  49. package/src/records/portal.ts +28 -0
  50. package/src/records/portalRecord.d.ts +12 -0
  51. package/src/records/portalRecord.js +32 -0
  52. package/src/records/portalRecord.ts +43 -0
  53. package/src/records/recordBase.d.ts +20 -0
  54. package/src/records/recordBase.js +95 -0
  55. package/src/records/recordBase.ts +121 -0
  56. package/src/types.d.ts +117 -0
  57. package/src/types.js +8 -0
  58. package/src/types.ts +151 -0
  59. package/test.d.ts +1 -0
  60. package/test.js +4 -0
  61. package/tsconfig.json +4 -0
  62. package/TEMP/FILEMAKER.txt +0 -218
  63. package/TEMP/WEBAPP.txt +0 -92
  64. package/TEMP/config.yaml +0 -40
  65. package/TEMP/data.json +0 -19837
  66. package/temp2/1.19.2-forge-43.2.8.json +0 -347
  67. package/temp2/Quinn-1.19.2-forge-43.2.8.json +0 -347
@@ -0,0 +1,12 @@
1
+ import { Database } from "./database";
2
+ import { databaseOptionsWithExternalSources, FMHostMetadata, loginOptionsClaris, loginOptionsFileMaker, loginOptionsOAuth } from "../types.js";
3
+ export default class FMHost {
4
+ readonly hostname: string;
5
+ readonly timezoneOffset: number;
6
+ readonly verify: boolean;
7
+ metadata: FMHostMetadata;
8
+ constructor(_hostname: string, timezoneOffset?: number, verify?: boolean);
9
+ listDatabases(credentials?: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris): Promise<any>;
10
+ database(data: databaseOptionsWithExternalSources): Database;
11
+ getMetadata(): Promise<any>;
12
+ }
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Copyright (c) 2023. See LICENSE file for more information
3
+ */
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
13
+ import { generateAuthorizationHeaders } from "./generateAuthorizationHeaders";
14
+ import fetch from "node-fetch";
15
+ import { FMError } from "../FMError";
16
+ import { Database } from "./database";
17
+ export default class FMHost {
18
+ constructor(_hostname, timezoneOffset = 0 - (new Date()).getTimezoneOffset(), verify = true) {
19
+ if (!(/^https?:\/\//).test(_hostname))
20
+ throw "hostname MUST begin with either http:// or https://";
21
+ this.hostname = _hostname;
22
+ this.timezoneOffset = timezoneOffset;
23
+ this.verify = verify;
24
+ }
25
+ listDatabases(credentials) {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ let headers = {};
28
+ if (credentials) {
29
+ headers = generateAuthorizationHeaders(credentials);
30
+ }
31
+ let _fetch = yield fetch(`${this.hostname}/fmi/data/v2/databases`, {
32
+ method: "GET",
33
+ headers
34
+ });
35
+ let data = yield _fetch.json();
36
+ // console.log(data.messages[0])
37
+ if (data.messages[0].code === "0") {
38
+ return data.response.databases;
39
+ }
40
+ else {
41
+ // @ts-ignore
42
+ throw new FMError(data.messages[0].code, data.status, data);
43
+ }
44
+ });
45
+ }
46
+ database(data) {
47
+ return new Database(this, data);
48
+ }
49
+ getMetadata() {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ if (this.metadata)
52
+ return this.metadata;
53
+ let _fetch = yield fetch(`${this.hostname}/fmi/data/v2/productInfo`, {
54
+ method: "GET",
55
+ });
56
+ let data = yield _fetch.json();
57
+ // console.log(data.messages[0])
58
+ if (data.messages[0].code === "0") {
59
+ this.metadata = data.response;
60
+ return data.response;
61
+ }
62
+ else {
63
+ // @ts-ignore
64
+ throw new FMError(data.messages[0].code, data.status, data);
65
+ }
66
+ });
67
+ }
68
+ }
@@ -0,0 +1,75 @@
1
+ /*
2
+ * Copyright (c) 2023. See LICENSE file for more information
3
+ */
4
+
5
+ import {generateAuthorizationHeaders} from "./generateAuthorizationHeaders";
6
+ import fetch from "node-fetch";
7
+ import {FMError} from "../FMError";
8
+ import {Database} from "./database";
9
+ import {
10
+ databaseOptionsWithExternalSources,
11
+ fileMakerResponse,
12
+ FMHostMetadata,
13
+ loginOptionsClaris,
14
+ loginOptionsFileMaker,
15
+ loginOptionsOAuth
16
+ } from "../types.js";
17
+
18
+ export default class FMHost {
19
+ readonly hostname: string
20
+ readonly timezoneOffset: number
21
+ readonly verify: boolean
22
+ metadata: FMHostMetadata
23
+
24
+ constructor(_hostname: string, timezoneOffset = 0 - (new Date()).getTimezoneOffset(), verify = true) {
25
+ if (!(/^https?:\/\//).test(_hostname)) throw "hostname MUST begin with either http:// or https://"
26
+ this.hostname = _hostname
27
+ this.timezoneOffset = timezoneOffset
28
+ this.verify = verify
29
+ }
30
+
31
+ async listDatabases(credentials?: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris) {
32
+ let headers = {}
33
+ if (credentials) {
34
+ headers = generateAuthorizationHeaders(credentials)
35
+ }
36
+
37
+ let _fetch = await fetch(`${this.hostname}/fmi/data/v2/databases`, {
38
+ method: "GET",
39
+ headers
40
+ })
41
+ let data = await _fetch.json() as fileMakerResponse
42
+ // console.log(data.messages[0])
43
+
44
+ if (data.messages[0].code === "0") {
45
+ return data.response.databases
46
+ }
47
+ else {
48
+ // @ts-ignore
49
+ throw new FMError(data.messages[0].code, data.status, data)
50
+ }
51
+ }
52
+
53
+ database(data: databaseOptionsWithExternalSources) {
54
+ return new Database(this, data)
55
+ }
56
+
57
+ async getMetadata() {
58
+ if (this.metadata) return this.metadata
59
+
60
+ let _fetch = await fetch(`${this.hostname}/fmi/data/v2/productInfo`, {
61
+ method: "GET",
62
+ })
63
+ let data = await _fetch.json() as fileMakerResponse
64
+ // console.log(data.messages[0])
65
+
66
+ if (data.messages[0].code === "0") {
67
+ this.metadata = data.response
68
+ return data.response
69
+ }
70
+ else {
71
+ // @ts-ignore
72
+ throw new FMError(data.messages[0].code, data.status, data)
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,26 @@
1
+ import { EventEmitter } from "events";
2
+ import { Request } from "node-fetch";
3
+ import { LayoutInterface } from "../layouts/layoutInterface";
4
+ import { Layout } from "../layouts/layout";
5
+ import * as http from "http";
6
+ import { databaseOptionsWithExternalSources, Script } from "../types.js";
7
+ import FMHost from "./FMHost";
8
+ export declare class Database extends EventEmitter {
9
+ private _token;
10
+ readonly host: FMHost;
11
+ private connection_details;
12
+ private cookies;
13
+ readonly name: string;
14
+ constructor(host: FMHost, conn: databaseOptionsWithExternalSources);
15
+ private generateExternalSourceLogin;
16
+ logout(): Promise<void>;
17
+ login(): Promise<string>;
18
+ get token(): any;
19
+ get endpoint(): string;
20
+ apiRequest(url: string | Request, options?: any, autoRelogin?: boolean): Promise<any>;
21
+ getLayout<T extends LayoutInterface>(name: any): Layout<T>;
22
+ setGlobals(globalFields: any): Promise<void>;
23
+ script(name: any, parameter?: string): Script;
24
+ _tokenExpired(): void;
25
+ streamContainer(field: any, url: any): Promise<http.IncomingMessage>;
26
+ }
@@ -0,0 +1,195 @@
1
+ /*
2
+ * Copyright (c) 2023. See LICENSE file for more information
3
+ */
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
13
+ import { EventEmitter } from "events";
14
+ import fetch from "node-fetch";
15
+ import { generateAuthorizationHeaders } from "./generateAuthorizationHeaders";
16
+ import { FMError } from "../FMError";
17
+ import { Layout } from "../layouts/layout";
18
+ import * as http from "http";
19
+ import * as https from "https";
20
+ export class Database extends EventEmitter {
21
+ constructor(host, conn) {
22
+ super();
23
+ this.cookies = {};
24
+ this.host = host;
25
+ this.name = conn.database;
26
+ this.connection_details = conn;
27
+ }
28
+ generateExternalSourceLogin(data) {
29
+ if (data.credentials.method === "filemaker") {
30
+ let _data = data.credentials;
31
+ return {
32
+ database: data.database,
33
+ username: _data.username,
34
+ password: _data.password
35
+ };
36
+ }
37
+ else {
38
+ throw "Not yet supported login method";
39
+ }
40
+ }
41
+ logout() {
42
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
43
+ if (!this.token)
44
+ reject(new Error("Not logged in"));
45
+ let _fetch = yield fetch(`${this.endpoint}/sessions/${this.token}`, {
46
+ method: "DELETE",
47
+ headers: {
48
+ "content-type": "application/json"
49
+ }
50
+ });
51
+ let data = yield _fetch.json();
52
+ // console.log(data)
53
+ this._token = null;
54
+ resolve();
55
+ }));
56
+ }
57
+ login() {
58
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
59
+ // Reset cookies
60
+ this.cookies = {};
61
+ try {
62
+ yield this.host.getMetadata();
63
+ }
64
+ catch (e) {
65
+ reject(e);
66
+ return;
67
+ }
68
+ if (this.token)
69
+ throw new Error("Already logged in. Run logout() first");
70
+ if (this.connection_details.credentials.method === "token") {
71
+ this._token = this.connection_details.credentials.token;
72
+ resolve(this.token);
73
+ }
74
+ else {
75
+ fetch(`${this.endpoint}/sessions`, {
76
+ hostname: this.host.hostname,
77
+ port: 443,
78
+ method: "POST",
79
+ headers: generateAuthorizationHeaders(this.connection_details.credentials),
80
+ body: JSON.stringify({
81
+ fmDataSource: this.connection_details.externalSources.map(i => {
82
+ let _i = i;
83
+ return this.generateExternalSourceLogin(_i);
84
+ })
85
+ })
86
+ }).then((res) => __awaiter(this, void 0, void 0, function* () {
87
+ let _res = (yield res.json());
88
+ if (res.status === 200) {
89
+ this._token = res.headers.get('x-fm-data-access-token');
90
+ resolve(this._token);
91
+ }
92
+ else {
93
+ reject(new FMError(_res.messages[0].code, _res.status, res));
94
+ }
95
+ }))
96
+ .catch(e => {
97
+ reject(e);
98
+ });
99
+ }
100
+ }));
101
+ }
102
+ get token() {
103
+ return this._token;
104
+ }
105
+ get endpoint() {
106
+ return `${this.host.hostname}/fmi/data/v2/databases/${this.name}`;
107
+ }
108
+ apiRequest(url, options = {}, autoRelogin = true) {
109
+ return __awaiter(this, void 0, void 0, function* () {
110
+ if (!options.headers)
111
+ options.headers = {};
112
+ options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json";
113
+ options.headers["authorization"] = "Bearer " + this._token;
114
+ options.rejectUnauthorized = this.host.verify;
115
+ let _fetch = yield fetch(url, options);
116
+ if (_fetch.headers.get('set-cookie')) {
117
+ for (let cookie of _fetch.headers.get('set-cookie')) {
118
+ let cookie_split = cookie.split("=");
119
+ this.cookies[cookie_split[0]] = cookie_split[1];
120
+ }
121
+ }
122
+ let data = yield _fetch.json();
123
+ // console.log(data.messages[0])
124
+ if (data.messages[0].code == 952 && autoRelogin) {
125
+ this._token = null;
126
+ yield this.login();
127
+ return yield this.apiRequest(url, options, false);
128
+ }
129
+ return data;
130
+ });
131
+ }
132
+ getLayout(name) {
133
+ return new Layout(this, name);
134
+ }
135
+ setGlobals(globalFields) {
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
+ }
146
+ else {
147
+ reject((res.messages[0].code, res.status, res));
148
+ }
149
+ })
150
+ .catch(e => {
151
+ reject(e);
152
+ });
153
+ });
154
+ }
155
+ script(name, parameter = "") {
156
+ return { name, parameter };
157
+ }
158
+ _tokenExpired() {
159
+ this.emit("token_expired");
160
+ }
161
+ streamContainer(field, url) {
162
+ return new Promise((resolve, reject) => {
163
+ if (field.metadata.result !== "container") {
164
+ reject("Cannot stream the field " + field.id + " as it is not a container");
165
+ return;
166
+ }
167
+ if (!url || typeof url !== "string") {
168
+ reject("Container is empty, or has invalid value");
169
+ return;
170
+ }
171
+ let headers = {};
172
+ if (Object.keys(this.cookies).length !== 0) {
173
+ headers["Cookie"] = Object.keys(this.cookies)
174
+ .map(key => {
175
+ return key + "=" + this.cookies[key];
176
+ })
177
+ .join("; ");
178
+ }
179
+ // Automatically switch between the http and https modules, based on which is needed
180
+ (url.startsWith("https") ? https : http).get(url, {
181
+ headers
182
+ }, (res) => {
183
+ // Check for the 'set-cookie' header. If it exists, remember it and strip it for better security.
184
+ if (res.headers['set-cookie']) {
185
+ for (let cookie of res.headers['set-cookie']) {
186
+ let cookie_split = cookie.split("=");
187
+ this.cookies[cookie_split[0]] = cookie_split[1];
188
+ }
189
+ res.headers['set-cookie'] = null;
190
+ }
191
+ resolve(res);
192
+ });
193
+ });
194
+ }
195
+ }
@@ -0,0 +1,216 @@
1
+ /*
2
+ * Copyright (c) 2023. See LICENSE file for more information
3
+ */
4
+
5
+ import {EventEmitter} from "events";
6
+ import fetch, {HeadersInit, Request} from "node-fetch";
7
+ import {generateAuthorizationHeaders} from "./generateAuthorizationHeaders";
8
+ import {FMError} from "../FMError";
9
+ import {LayoutInterface} from "../layouts/layoutInterface";
10
+ import {Layout} from "../layouts/layout";
11
+ import * as http from "http";
12
+ import * as https from "https";
13
+ import {
14
+ databaseOptionsBase,
15
+ databaseOptionsWithExternalSources,
16
+ fileMakerResponse,
17
+ loginOptionsFileMaker,
18
+ loginOptionsToken,
19
+ Script
20
+ } from "../types.js";
21
+ import FMHost from "./FMHost";
22
+
23
+ export class Database extends EventEmitter {
24
+ private _token: any;
25
+ readonly host: FMHost;
26
+ private connection_details: databaseOptionsWithExternalSources
27
+ private cookies: { [key: string]: string } = {}
28
+ readonly name: string;
29
+
30
+ constructor(host: FMHost, conn: databaseOptionsWithExternalSources) {
31
+ super()
32
+ this.host = host
33
+ this.name = conn.database
34
+ this.connection_details = conn
35
+ }
36
+
37
+ private generateExternalSourceLogin(data: databaseOptionsBase) {
38
+ if (data.credentials.method === "filemaker") {
39
+ let _data = <loginOptionsFileMaker>data.credentials
40
+ return {
41
+ database: data.database,
42
+ username: _data.username,
43
+ password: _data.password
44
+ }
45
+ }
46
+ else {
47
+ throw "Not yet supported login method"
48
+ }
49
+ }
50
+
51
+ logout(): Promise<void> {
52
+ return new Promise(async (resolve, reject) => {
53
+ if (!this.token) reject(new Error("Not logged in"))
54
+
55
+ let _fetch = await fetch(`${this.endpoint}/sessions/${this.token}`, {
56
+ method: "DELETE",
57
+ headers: {
58
+ "content-type": "application/json"
59
+ }
60
+ })
61
+ let data = await _fetch.json()
62
+ // console.log(data)
63
+ this._token = null
64
+ resolve()
65
+ })
66
+ }
67
+
68
+ login() {
69
+ return new Promise<string>(async (resolve, reject) => {
70
+ // Reset cookies
71
+ this.cookies = {}
72
+
73
+ try {
74
+ await this.host.getMetadata()
75
+ } catch (e) {
76
+ reject(e)
77
+ return
78
+ }
79
+ if (this.token) throw new Error("Already logged in. Run logout() first")
80
+
81
+ if (this.connection_details.credentials.method === "token") {
82
+ this._token = (<loginOptionsToken>this.connection_details.credentials).token
83
+ resolve(this.token)
84
+ }
85
+ else {
86
+ fetch(`${this.endpoint}/sessions`, {
87
+ hostname: this.host.hostname,
88
+ port: 443,
89
+ method: "POST",
90
+ headers: generateAuthorizationHeaders(this.connection_details.credentials) as unknown as HeadersInit,
91
+ body: JSON.stringify({
92
+ fmDataSource: this.connection_details.externalSources.map(i => {
93
+ let _i = <databaseOptionsBase>i
94
+ return this.generateExternalSourceLogin(_i)
95
+ })
96
+ })
97
+ }).then(async res => {
98
+ let _res = <any>(await res.json())
99
+ if (res.status === 200) {
100
+ this._token = res.headers.get('x-fm-data-access-token')
101
+ resolve(this._token)
102
+ }
103
+ else {
104
+ reject(new FMError(_res.messages[0].code, _res.status, res))
105
+ }
106
+ })
107
+ .catch(e => {
108
+ reject(e)
109
+ })
110
+ }
111
+ })
112
+ }
113
+
114
+ get token() {
115
+ return this._token
116
+ }
117
+
118
+ get endpoint(): string {
119
+ return `${this.host.hostname}/fmi/data/v2/databases/${this.name}`
120
+ }
121
+
122
+ async apiRequest(url: string | Request, options: any = {}, autoRelogin = true): Promise<any> {
123
+ if (!options.headers) options.headers = {}
124
+ options.headers["content-type"] = options.headers["content-type"] ? options.headers["content-type"] : "application/json"
125
+ options.headers["authorization"] = "Bearer " + this._token
126
+ options.rejectUnauthorized = this.host.verify
127
+
128
+ let _fetch = await fetch(url, options)
129
+ if (_fetch.headers.get('set-cookie')) {
130
+ for (let cookie of _fetch.headers.get('set-cookie')) {
131
+ let cookie_split = cookie.split("=")
132
+ this.cookies[cookie_split[0]] = cookie_split[1]
133
+ }
134
+ }
135
+ let data = await _fetch.json() as fileMakerResponse
136
+ // console.log(data.messages[0])
137
+ if (data.messages[0].code == 952 && autoRelogin) {
138
+ this._token = null
139
+ await this.login()
140
+ return await this.apiRequest(url, options, false)
141
+ }
142
+ return (data as any)
143
+ }
144
+
145
+ getLayout<T extends LayoutInterface>(name): Layout<T> {
146
+ return new Layout(this, name)
147
+ }
148
+
149
+ setGlobals(globalFields): Promise<void> {
150
+ // console.log({globalFields})
151
+ return new Promise((resolve, reject) => {
152
+ this.apiRequest(`${this.endpoint}/globals`, {
153
+ method: "PATCH",
154
+ body: JSON.stringify({globalFields})
155
+ }).then(res => {
156
+ // console.log(res)
157
+ if (res.messages[0].code === "0") {
158
+ resolve()
159
+ }
160
+ else {
161
+ reject(
162
+ (res.messages[0].code, res.status, res))
163
+ }
164
+ })
165
+ .catch(e => {
166
+ reject(e)
167
+ })
168
+ })
169
+ }
170
+
171
+ script(name, parameter = ""): Script {
172
+ return ({name, parameter} as Script)
173
+ }
174
+
175
+ _tokenExpired() {
176
+ this.emit("token_expired")
177
+ }
178
+
179
+ streamContainer(field, url): Promise<http.IncomingMessage> {
180
+ return new Promise((resolve, reject) => {
181
+ if (field.metadata.result !== "container") {
182
+ reject("Cannot stream the field " + field.id + " as it is not a container")
183
+ return
184
+ }
185
+ if (!url || typeof url !== "string") {
186
+ reject("Container is empty, or has invalid value")
187
+ return
188
+ }
189
+
190
+ let headers = {}
191
+ if (Object.keys(this.cookies).length !== 0) {
192
+ headers["Cookie"] = Object.keys(this.cookies)
193
+ .map(key => {
194
+ return key + "=" + this.cookies[key]
195
+ })
196
+ .join("; ")
197
+ }
198
+
199
+ // Automatically switch between the http and https modules, based on which is needed
200
+ (url.startsWith("https") ? https : http).get(url, {
201
+ headers
202
+ }, (res) => {
203
+ // Check for the 'set-cookie' header. If it exists, remember it and strip it for better security.
204
+ if (res.headers['set-cookie']) {
205
+ for (let cookie of res.headers['set-cookie']) {
206
+ let cookie_split = cookie.split("=")
207
+ this.cookies[cookie_split[0]] = cookie_split[1]
208
+ }
209
+ res.headers['set-cookie'] = null
210
+ }
211
+
212
+ resolve(res)
213
+ })
214
+ })
215
+ }
216
+ }
@@ -0,0 +1,2 @@
1
+ import { AuthorizationHeaders, AuthorizationHeadersOAuth, loginOptionsClaris, loginOptionsFileMaker, loginOptionsOAuth } from "../types.js";
2
+ export declare function generateAuthorizationHeaders(credentials: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris): AuthorizationHeaders | AuthorizationHeadersOAuth;
@@ -0,0 +1,23 @@
1
+ /*
2
+ * Copyright (c) 2023. See LICENSE file for more information
3
+ */
4
+ export function generateAuthorizationHeaders(credentials) {
5
+ switch (credentials.method) {
6
+ case "filemaker":
7
+ return {
8
+ "Content-Type": "application/json",
9
+ "Authorization": "Basic " + Buffer.from(credentials.username + ":" + credentials.password).toString("base64")
10
+ };
11
+ case "claris":
12
+ return {
13
+ "Content-Type": "application/json",
14
+ "Authorization": credentials.claris.fmid,
15
+ };
16
+ case "oauth":
17
+ return {
18
+ "Content-Type": "application/json",
19
+ "X-FM-Data-OAuth-RequestId": credentials.oauth.requestId,
20
+ "X-FM-Data-OAuth-Identifier": credentials.oauth.requestIdentifier
21
+ };
22
+ }
23
+ }
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (c) 2023. See LICENSE file for more information
3
+ */
4
+
5
+ import {
6
+ AuthorizationHeaders,
7
+ AuthorizationHeadersOAuth,
8
+ loginOptionsClaris,
9
+ loginOptionsFileMaker,
10
+ loginOptionsOAuth
11
+ } from "../types.js";
12
+
13
+ export function generateAuthorizationHeaders(credentials: loginOptionsOAuth | loginOptionsFileMaker | loginOptionsClaris): AuthorizationHeaders | AuthorizationHeadersOAuth {
14
+ switch (credentials.method) {
15
+ case "filemaker":
16
+ return {
17
+ "Content-Type": "application/json",
18
+ "Authorization": "Basic " + Buffer.from((<loginOptionsFileMaker>credentials).username + ":" + (<loginOptionsFileMaker>credentials).password).toString("base64")
19
+ } as AuthorizationHeaders
20
+ case "claris":
21
+ return {
22
+ "Content-Type": "application/json",
23
+ "Authorization": (<loginOptionsClaris>credentials).claris.fmid,
24
+ } as AuthorizationHeaders
25
+ case "oauth":
26
+ return {
27
+ "Content-Type": "application/json",
28
+ "X-FM-Data-OAuth-RequestId": (<loginOptionsOAuth>credentials).oauth.requestId,
29
+ "X-FM-Data-OAuth-Identifier": (<loginOptionsOAuth>credentials).oauth.requestIdentifier
30
+ } as AuthorizationHeadersOAuth
31
+ }
32
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import FMHost from "./connection/FMHost";
2
+ export default FMHost;