@proofkit/fmdapi 5.0.2 → 5.0.3-beta.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/dist/esm/adapters/core.d.ts +4 -4
- package/dist/esm/adapters/fetch-base-types.d.ts +4 -4
- package/dist/esm/adapters/fetch-base.d.ts +2 -2
- package/dist/esm/adapters/fetch-base.js +36 -49
- package/dist/esm/adapters/fetch-base.js.map +1 -1
- package/dist/esm/adapters/fetch.d.ts +5 -5
- package/dist/esm/adapters/fetch.js +11 -10
- package/dist/esm/adapters/fetch.js.map +1 -1
- package/dist/esm/adapters/otto.d.ts +2 -2
- package/dist/esm/adapters/otto.js +3 -5
- package/dist/esm/adapters/otto.js.map +1 -1
- package/dist/esm/client-types.d.ts +41 -41
- package/dist/esm/client-types.js +1 -6
- package/dist/esm/client-types.js.map +1 -1
- package/dist/esm/client.d.ts +27 -43
- package/dist/esm/client.js +75 -80
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +4 -6
- package/dist/esm/index.js +5 -5
- package/dist/esm/tokenStore/index.d.ts +1 -1
- package/dist/esm/tokenStore/types.d.ts +2 -2
- package/dist/esm/tokenStore/upstash.d.ts +1 -1
- package/dist/esm/utils.d.ts +12 -14
- package/dist/esm/utils.js +5 -5
- package/dist/esm/utils.js.map +1 -1
- package/package.json +11 -13
- package/src/adapters/core.ts +6 -9
- package/src/adapters/fetch-base-types.ts +5 -3
- package/src/adapters/fetch-base.ts +53 -78
- package/src/adapters/fetch.ts +19 -24
- package/src/adapters/otto.ts +8 -8
- package/src/client-types.ts +59 -83
- package/src/client.ts +131 -167
- package/src/index.ts +4 -9
- package/src/tokenStore/file.ts +2 -4
- package/src/tokenStore/index.ts +1 -1
- package/src/tokenStore/types.ts +2 -2
- package/src/tokenStore/upstash.ts +2 -5
- package/src/utils.ts +20 -29
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CreateParams, CreateResponse, DeleteParams, DeleteResponse, FieldData, GetParams, GetResponse,
|
|
2
|
-
export
|
|
1
|
+
import { CreateParams, CreateResponse, DeleteParams, DeleteResponse, FieldData, GetParams, GetResponse, LayoutMetadataResponse, ListParamsRaw, Query, ScriptResponse, UpdateParams, UpdateResponse } from '../client-types.js';
|
|
2
|
+
export interface BaseRequest {
|
|
3
3
|
layout: string;
|
|
4
4
|
fetch?: RequestInit;
|
|
5
5
|
timeout?: number;
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
7
|
export type ListOptions = BaseRequest & {
|
|
8
8
|
data: ListParamsRaw;
|
|
9
9
|
};
|
|
@@ -14,7 +14,7 @@ export type GetOptions = BaseRequest & {
|
|
|
14
14
|
};
|
|
15
15
|
export type FindOptions = BaseRequest & {
|
|
16
16
|
data: ListParamsRaw & {
|
|
17
|
-
query:
|
|
17
|
+
query: Query[];
|
|
18
18
|
};
|
|
19
19
|
};
|
|
20
20
|
export type CreateOptions = BaseRequest & {
|
|
@@ -4,12 +4,12 @@ import { BaseFetchAdapterOptions, GetTokenArguments } from './fetch-base-types.j
|
|
|
4
4
|
export declare class BaseFetchAdapter implements Adapter {
|
|
5
5
|
protected server: string;
|
|
6
6
|
protected db: string;
|
|
7
|
-
private refreshToken;
|
|
7
|
+
private readonly refreshToken;
|
|
8
8
|
baseUrl: URL;
|
|
9
9
|
constructor(options: BaseFetchAdapterOptions & {
|
|
10
10
|
refreshToken?: boolean;
|
|
11
11
|
});
|
|
12
|
-
protected getToken: (
|
|
12
|
+
protected getToken: (_args?: GetTokenArguments) => Promise<string>;
|
|
13
13
|
protected request: (params: {
|
|
14
14
|
url: string;
|
|
15
15
|
body?: object | FormData;
|
|
@@ -8,33 +8,22 @@ class BaseFetchAdapter {
|
|
|
8
8
|
__publicField(this, "db");
|
|
9
9
|
__publicField(this, "refreshToken");
|
|
10
10
|
__publicField(this, "baseUrl");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
throw new Error("getToken method not implemented by Fetch Adapter");
|
|
11
|
+
__publicField(this, "getToken", (_args) => {
|
|
12
|
+
return Promise.reject(new Error("getToken method not implemented by Fetch Adapter"));
|
|
14
13
|
});
|
|
15
14
|
__publicField(this, "request", async (params) => {
|
|
16
15
|
var _a, _b;
|
|
17
|
-
const {
|
|
18
|
-
query,
|
|
19
|
-
body,
|
|
20
|
-
method = "GET",
|
|
21
|
-
retry = false,
|
|
22
|
-
fetchOptions = {}
|
|
23
|
-
} = params;
|
|
16
|
+
const { query, body, method = "GET", retry = false, fetchOptions = {} } = params;
|
|
24
17
|
const url = new URL(`${this.baseUrl}${params.url}`);
|
|
25
18
|
if (query) {
|
|
26
19
|
const { _sort, ...rest } = query;
|
|
27
|
-
const
|
|
20
|
+
const filteredRest = Object.fromEntries(Object.entries(rest).filter(([, v]) => v !== void 0 && v !== null));
|
|
21
|
+
const searchParams = new URLSearchParams(filteredRest);
|
|
28
22
|
if (query.portalRanges && typeof query.portalRanges === "object") {
|
|
29
|
-
for (const [portalName, value] of Object.entries(
|
|
30
|
-
query.portalRanges
|
|
31
|
-
)) {
|
|
23
|
+
for (const [portalName, value] of Object.entries(query.portalRanges)) {
|
|
32
24
|
if (value) {
|
|
33
25
|
if (value.offset && value.offset > 0) {
|
|
34
|
-
searchParams.set(
|
|
35
|
-
`_offset.${portalName}`,
|
|
36
|
-
value.offset.toString()
|
|
37
|
-
);
|
|
26
|
+
searchParams.set(`_offset.${portalName}`, value.offset.toString());
|
|
38
27
|
}
|
|
39
28
|
if (value.limit) {
|
|
40
29
|
searchParams.set(`_limit.${portalName}`, value.limit.toString());
|
|
@@ -49,46 +38,47 @@ class BaseFetchAdapter {
|
|
|
49
38
|
url.search = searchParams.toString();
|
|
50
39
|
}
|
|
51
40
|
if (body && "portalRanges" in body) {
|
|
52
|
-
for (const [portalName, value] of Object.entries(
|
|
53
|
-
body.portalRanges
|
|
54
|
-
)) {
|
|
41
|
+
for (const [portalName, value] of Object.entries(body.portalRanges)) {
|
|
55
42
|
if (value) {
|
|
56
43
|
if (value.offset && value.offset > 0) {
|
|
57
|
-
url.searchParams.set(
|
|
58
|
-
`_offset.${portalName}`,
|
|
59
|
-
value.offset.toString()
|
|
60
|
-
);
|
|
44
|
+
url.searchParams.set(`_offset.${portalName}`, value.offset.toString());
|
|
61
45
|
}
|
|
62
46
|
if (value.limit) {
|
|
63
|
-
url.searchParams.set(
|
|
64
|
-
`_limit.${portalName}`,
|
|
65
|
-
value.limit.toString()
|
|
66
|
-
);
|
|
47
|
+
url.searchParams.set(`_limit.${portalName}`, value.limit.toString());
|
|
67
48
|
}
|
|
68
49
|
}
|
|
69
50
|
}
|
|
70
|
-
|
|
51
|
+
body.portalRanges = void 0;
|
|
71
52
|
}
|
|
72
53
|
const controller = new AbortController();
|
|
73
54
|
let timeout = null;
|
|
74
|
-
if (params.timeout)
|
|
55
|
+
if (params.timeout) {
|
|
75
56
|
timeout = setTimeout(() => controller.abort(), params.timeout);
|
|
57
|
+
}
|
|
76
58
|
const token = await this.getToken({ refresh: retry });
|
|
77
59
|
const headers = new Headers(fetchOptions == null ? void 0 : fetchOptions.headers);
|
|
78
60
|
headers.set("Authorization", `Bearer ${token}`);
|
|
79
61
|
if (!(body instanceof FormData)) {
|
|
80
62
|
headers.set("Content-Type", "application/json");
|
|
81
63
|
}
|
|
64
|
+
let requestBody;
|
|
65
|
+
if (body instanceof FormData) {
|
|
66
|
+
requestBody = body;
|
|
67
|
+
} else if (body) {
|
|
68
|
+
requestBody = JSON.stringify(body);
|
|
69
|
+
} else {
|
|
70
|
+
requestBody = void 0;
|
|
71
|
+
}
|
|
82
72
|
const res = await fetch(url.toString(), {
|
|
83
73
|
...fetchOptions,
|
|
84
74
|
method,
|
|
85
|
-
body:
|
|
75
|
+
body: requestBody,
|
|
86
76
|
headers,
|
|
87
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
88
|
-
// @ts-ignore
|
|
89
77
|
signal: controller.signal
|
|
90
78
|
});
|
|
91
|
-
if (timeout)
|
|
79
|
+
if (timeout) {
|
|
80
|
+
clearTimeout(timeout);
|
|
81
|
+
}
|
|
92
82
|
let respData;
|
|
93
83
|
try {
|
|
94
84
|
respData = await res.json();
|
|
@@ -98,16 +88,11 @@ class BaseFetchAdapter {
|
|
|
98
88
|
if (!res.ok) {
|
|
99
89
|
if (((_a = respData == null ? void 0 : respData.messages) == null ? void 0 : _a[0].code) === "952" && !retry && this.refreshToken) {
|
|
100
90
|
return this.request({ ...params, retry: true });
|
|
101
|
-
} else {
|
|
102
|
-
throw new FileMakerError(
|
|
103
|
-
((_b = respData == null ? void 0 : respData.messages) == null ? void 0 : _b[0].code) ?? "500",
|
|
104
|
-
`Filemaker Data API failed with (${res.status}): ${JSON.stringify(
|
|
105
|
-
respData,
|
|
106
|
-
null,
|
|
107
|
-
2
|
|
108
|
-
)}`
|
|
109
|
-
);
|
|
110
91
|
}
|
|
92
|
+
throw new FileMakerError(
|
|
93
|
+
((_b = respData == null ? void 0 : respData.messages) == null ? void 0 : _b[0].code) ?? "500",
|
|
94
|
+
`Filemaker Data API failed with (${res.status}): ${JSON.stringify(respData, null, 2)}`
|
|
95
|
+
);
|
|
111
96
|
}
|
|
112
97
|
return respData.response;
|
|
113
98
|
});
|
|
@@ -218,7 +203,9 @@ class BaseFetchAdapter {
|
|
|
218
203
|
});
|
|
219
204
|
__publicField(this, "containerUpload", async (opts) => {
|
|
220
205
|
let url = `/layouts/${opts.layout}/records/${opts.data.recordId}/containers/${opts.data.containerFieldName}`;
|
|
221
|
-
if (opts.data.repetition)
|
|
206
|
+
if (opts.data.repetition) {
|
|
207
|
+
url += `/${opts.data.repetition}`;
|
|
208
|
+
}
|
|
222
209
|
const formData = new FormData();
|
|
223
210
|
formData.append("upload", opts.data.file);
|
|
224
211
|
await this.request({
|
|
@@ -244,10 +231,10 @@ class BaseFetchAdapter {
|
|
|
244
231
|
this.server = options.server;
|
|
245
232
|
this.db = options.db;
|
|
246
233
|
this.refreshToken = options.refreshToken ?? false;
|
|
247
|
-
this.baseUrl = new URL(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
234
|
+
this.baseUrl = new URL(`${this.server}/fmi/data/vLatest/databases/${this.db}`);
|
|
235
|
+
if (this.db === "") {
|
|
236
|
+
throw new Error("Database name is required");
|
|
237
|
+
}
|
|
251
238
|
}
|
|
252
239
|
}
|
|
253
240
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-base.js","sources":["../../../src/adapters/fetch-base.ts"],"sourcesContent":["import type {\n AllLayoutsMetadataResponse,\n CreateResponse,\n DeleteResponse,\n GetResponse,\n LayoutMetadataResponse,\n PortalRanges,\n RawFMResponse,\n ScriptResponse,\n ScriptsMetadataResponse,\n UpdateResponse,\n} from \"../client-types.js\";\nimport { FileMakerError } from \"../client-types.js\";\nimport type {\n Adapter,\n BaseRequest,\n ContainerUploadOptions,\n CreateOptions,\n DeleteOptions,\n ExecuteScriptOptions,\n FindOptions,\n GetOptions,\n LayoutMetadataOptions,\n ListOptions,\n UpdateOptions,\n} from \"./core.js\";\nimport type {\n BaseFetchAdapterOptions,\n GetTokenArguments,\n} from \"./fetch-base-types.js\";\n\nexport class BaseFetchAdapter implements Adapter {\n protected server: string;\n protected db: string;\n private refreshToken: boolean;\n baseUrl: URL;\n\n constructor(options: BaseFetchAdapterOptions & { refreshToken?: boolean }) {\n this.server = options.server;\n this.db = options.db;\n this.refreshToken = options.refreshToken ?? false;\n this.baseUrl = new URL(\n `${this.server}/fmi/data/vLatest/databases/${this.db}`,\n );\n\n if (this.db === \"\") throw new Error(\"Database name is required\");\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected getToken = async (args?: GetTokenArguments): Promise<string> => {\n // method must be implemented in subclass\n throw new Error(\"getToken method not implemented by Fetch Adapter\");\n };\n\n protected request = async (params: {\n url: string;\n body?: object | FormData;\n query?: Record<string, string>;\n method?: string;\n retry?: boolean;\n portalRanges?: PortalRanges;\n timeout?: number;\n fetchOptions?: RequestInit;\n }): Promise<unknown> => {\n const {\n query,\n body,\n method = \"GET\",\n retry = false,\n fetchOptions = {},\n } = params;\n\n const url = new URL(`${this.baseUrl}${params.url}`);\n\n if (query) {\n const { _sort, ...rest } = query;\n const searchParams = new URLSearchParams(rest);\n if (query.portalRanges && typeof query.portalRanges === \"object\") {\n for (const [portalName, value] of Object.entries(\n query.portalRanges as PortalRanges,\n )) {\n if (value) {\n if (value.offset && value.offset > 0) {\n searchParams.set(\n `_offset.${portalName}`,\n value.offset.toString(),\n );\n }\n if (value.limit) {\n searchParams.set(`_limit.${portalName}`, value.limit.toString());\n }\n }\n }\n }\n if (_sort) {\n searchParams.set(\"_sort\", JSON.stringify(_sort));\n }\n searchParams.delete(\"portalRanges\");\n url.search = searchParams.toString();\n }\n\n if (body && \"portalRanges\" in body) {\n for (const [portalName, value] of Object.entries(\n body.portalRanges as PortalRanges,\n )) {\n if (value) {\n if (value.offset && value.offset > 0) {\n url.searchParams.set(\n `_offset.${portalName}`,\n value.offset.toString(),\n );\n }\n if (value.limit) {\n url.searchParams.set(\n `_limit.${portalName}`,\n value.limit.toString(),\n );\n }\n }\n }\n delete body.portalRanges;\n }\n\n const controller = new AbortController();\n let timeout: NodeJS.Timeout | null = null;\n if (params.timeout)\n timeout = setTimeout(() => controller.abort(), params.timeout);\n\n const token = await this.getToken({ refresh: retry });\n\n const headers = new Headers(fetchOptions?.headers);\n headers.set(\"Authorization\", `Bearer ${token}`);\n\n // Only set Content-Type for JSON bodies\n if (!(body instanceof FormData)) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n const res = await fetch(url.toString(), {\n ...fetchOptions,\n method,\n body:\n body instanceof FormData\n ? body\n : body\n ? JSON.stringify(body)\n : undefined,\n headers,\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n signal: controller.signal,\n });\n\n if (timeout) clearTimeout(timeout);\n\n let respData: RawFMResponse;\n try {\n respData = await res.json();\n } catch {\n respData = {};\n }\n\n if (!res.ok) {\n if (\n respData?.messages?.[0].code === \"952\" &&\n !retry &&\n this.refreshToken\n ) {\n // token expired, get new token and retry once\n return this.request({ ...params, retry: true });\n } else {\n throw new FileMakerError(\n respData?.messages?.[0].code ?? \"500\",\n `Filemaker Data API failed with (${res.status}): ${JSON.stringify(\n respData,\n null,\n 2,\n )}`,\n );\n }\n }\n\n return respData.response;\n };\n\n public list = async (opts: ListOptions): Promise<GetResponse> => {\n const { data, layout } = opts;\n\n const resp = await this.request({\n url: `/layouts/${layout}/records`,\n query: data as Record<string, string>,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as GetResponse;\n };\n\n public get = async (opts: GetOptions): Promise<GetResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records/${data.recordId}`,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as GetResponse;\n };\n\n public find = async (opts: FindOptions): Promise<GetResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/_find`,\n body: data,\n method: \"POST\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as GetResponse;\n };\n\n public create = async (opts: CreateOptions): Promise<CreateResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records`,\n body: data,\n method: \"POST\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as CreateResponse;\n };\n\n public update = async (opts: UpdateOptions): Promise<UpdateResponse> => {\n const {\n data: { recordId, ...data },\n layout,\n } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records/${recordId}`,\n body: data,\n method: \"PATCH\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as UpdateResponse;\n };\n\n public delete = async (opts: DeleteOptions): Promise<DeleteResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records/${data.recordId}`,\n method: \"DELETE\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as DeleteResponse;\n };\n\n public layoutMetadata = async (\n opts: LayoutMetadataOptions,\n ): Promise<LayoutMetadataResponse> => {\n return (await this.request({\n url: `/layouts/${opts.layout}`,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n })) as LayoutMetadataResponse;\n };\n\n /**\n * Execute a script within the database\n */\n public executeScript = async (opts: ExecuteScriptOptions) => {\n const { script, scriptParam, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/script/${script}`,\n query: scriptParam ? { \"script.param\": scriptParam } : undefined,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as ScriptResponse;\n };\n\n /**\n * Returns a list of available layouts on the database.\n */\n public layouts = async (opts?: Omit<BaseRequest, \"layout\">) => {\n return (await this.request({\n url: \"/layouts\",\n fetchOptions: opts?.fetch,\n timeout: opts?.timeout,\n })) as AllLayoutsMetadataResponse;\n };\n\n /**\n * Returns a list of available scripts on the database.\n */\n public scripts = async (opts?: Omit<BaseRequest, \"layout\">) => {\n return (await this.request({\n url: \"/scripts\",\n fetchOptions: opts?.fetch,\n timeout: opts?.timeout,\n })) as ScriptsMetadataResponse;\n };\n\n public containerUpload = async (opts: ContainerUploadOptions) => {\n let url = `/layouts/${opts.layout}/records/${opts.data.recordId}/containers/${opts.data.containerFieldName}`;\n if (opts.data.repetition) url += `/${opts.data.repetition}`;\n const formData = new FormData();\n formData.append(\"upload\", opts.data.file);\n\n await this.request({\n url,\n method: \"POST\",\n body: formData,\n timeout: opts.timeout,\n fetchOptions: opts.fetch,\n });\n };\n\n /**\n * Set global fields for the current session\n */\n public globals = async (\n opts: Omit<BaseRequest, \"layout\"> & {\n globalFields: Record<string, string | number>;\n },\n ) => {\n return (await this.request({\n url: \"/globals\",\n method: \"PATCH\",\n body: { globalFields: opts.globalFields },\n fetchOptions: opts?.fetch,\n timeout: opts?.timeout,\n })) as Record<string, never>;\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetch-base.js","sources":["../../../src/adapters/fetch-base.ts"],"sourcesContent":["import type {\n AllLayoutsMetadataResponse,\n CreateResponse,\n DeleteResponse,\n GetResponse,\n LayoutMetadataResponse,\n PortalRanges,\n RawFMResponse,\n ScriptResponse,\n ScriptsMetadataResponse,\n UpdateResponse,\n} from \"../client-types.js\";\nimport { FileMakerError } from \"../client-types.js\";\nimport type {\n Adapter,\n BaseRequest,\n ContainerUploadOptions,\n CreateOptions,\n DeleteOptions,\n ExecuteScriptOptions,\n FindOptions,\n GetOptions,\n LayoutMetadataOptions,\n ListOptions,\n UpdateOptions,\n} from \"./core.js\";\nimport type { BaseFetchAdapterOptions, GetTokenArguments } from \"./fetch-base-types.js\";\n\nexport class BaseFetchAdapter implements Adapter {\n protected server: string;\n protected db: string;\n private readonly refreshToken: boolean;\n baseUrl: URL;\n\n constructor(options: BaseFetchAdapterOptions & { refreshToken?: boolean }) {\n this.server = options.server;\n this.db = options.db;\n this.refreshToken = options.refreshToken ?? false;\n this.baseUrl = new URL(`${this.server}/fmi/data/vLatest/databases/${this.db}`);\n\n if (this.db === \"\") {\n throw new Error(\"Database name is required\");\n }\n }\n\n protected getToken = (_args?: GetTokenArguments): Promise<string> => {\n // method must be implemented in subclass\n return Promise.reject(new Error(\"getToken method not implemented by Fetch Adapter\"));\n };\n\n protected request = async (params: {\n url: string;\n body?: object | FormData;\n query?: Record<string, string>;\n method?: string;\n retry?: boolean;\n portalRanges?: PortalRanges;\n timeout?: number;\n fetchOptions?: RequestInit;\n }): Promise<unknown> => {\n const { query, body, method = \"GET\", retry = false, fetchOptions = {} } = params;\n\n const url = new URL(`${this.baseUrl}${params.url}`);\n\n if (query) {\n const { _sort, ...rest } = query;\n // Filter out undefined/null values before creating URLSearchParams\n const filteredRest = Object.fromEntries(Object.entries(rest).filter(([, v]) => v !== undefined && v !== null));\n const searchParams = new URLSearchParams(filteredRest as Record<string, string>);\n if (query.portalRanges && typeof query.portalRanges === \"object\") {\n for (const [portalName, value] of Object.entries(query.portalRanges as PortalRanges)) {\n if (value) {\n if (value.offset && value.offset > 0) {\n searchParams.set(`_offset.${portalName}`, value.offset.toString());\n }\n if (value.limit) {\n searchParams.set(`_limit.${portalName}`, value.limit.toString());\n }\n }\n }\n }\n if (_sort) {\n searchParams.set(\"_sort\", JSON.stringify(_sort));\n }\n searchParams.delete(\"portalRanges\");\n url.search = searchParams.toString();\n }\n\n if (body && \"portalRanges\" in body) {\n for (const [portalName, value] of Object.entries(body.portalRanges as PortalRanges)) {\n if (value) {\n if (value.offset && value.offset > 0) {\n url.searchParams.set(`_offset.${portalName}`, value.offset.toString());\n }\n if (value.limit) {\n url.searchParams.set(`_limit.${portalName}`, value.limit.toString());\n }\n }\n }\n body.portalRanges = undefined;\n }\n\n const controller = new AbortController();\n let timeout: NodeJS.Timeout | null = null;\n if (params.timeout) {\n timeout = setTimeout(() => controller.abort(), params.timeout);\n }\n\n const token = await this.getToken({ refresh: retry });\n\n const headers = new Headers(fetchOptions?.headers);\n headers.set(\"Authorization\", `Bearer ${token}`);\n\n // Only set Content-Type for JSON bodies\n if (!(body instanceof FormData)) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n let requestBody: string | FormData | undefined;\n if (body instanceof FormData) {\n requestBody = body;\n } else if (body) {\n requestBody = JSON.stringify(body);\n } else {\n requestBody = undefined;\n }\n\n const res = await fetch(url.toString(), {\n ...fetchOptions,\n method,\n body: requestBody,\n headers,\n signal: controller.signal,\n });\n\n if (timeout) {\n clearTimeout(timeout);\n }\n\n let respData: RawFMResponse;\n try {\n respData = await res.json();\n } catch {\n respData = {};\n }\n\n if (!res.ok) {\n if (respData?.messages?.[0].code === \"952\" && !retry && this.refreshToken) {\n // token expired, get new token and retry once\n return this.request({ ...params, retry: true });\n }\n throw new FileMakerError(\n respData?.messages?.[0].code ?? \"500\",\n `Filemaker Data API failed with (${res.status}): ${JSON.stringify(respData, null, 2)}`,\n );\n }\n\n return respData.response;\n };\n\n list = async (opts: ListOptions): Promise<GetResponse> => {\n const { data, layout } = opts;\n\n const resp = await this.request({\n url: `/layouts/${layout}/records`,\n query: data as Record<string, string>,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as GetResponse;\n };\n\n get = async (opts: GetOptions): Promise<GetResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records/${data.recordId}`,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as GetResponse;\n };\n\n find = async (opts: FindOptions): Promise<GetResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/_find`,\n body: data,\n method: \"POST\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as GetResponse;\n };\n\n create = async (opts: CreateOptions): Promise<CreateResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records`,\n body: data,\n method: \"POST\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as CreateResponse;\n };\n\n update = async (opts: UpdateOptions): Promise<UpdateResponse> => {\n const {\n data: { recordId, ...data },\n layout,\n } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records/${recordId}`,\n body: data,\n method: \"PATCH\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as UpdateResponse;\n };\n\n delete = async (opts: DeleteOptions): Promise<DeleteResponse> => {\n const { data, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/records/${data.recordId}`,\n method: \"DELETE\",\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as DeleteResponse;\n };\n\n layoutMetadata = async (opts: LayoutMetadataOptions): Promise<LayoutMetadataResponse> => {\n return (await this.request({\n url: `/layouts/${opts.layout}`,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n })) as LayoutMetadataResponse;\n };\n\n /**\n * Execute a script within the database\n */\n executeScript = async (opts: ExecuteScriptOptions) => {\n const { script, scriptParam, layout } = opts;\n const resp = await this.request({\n url: `/layouts/${layout}/script/${script}`,\n query: scriptParam ? { \"script.param\": scriptParam } : undefined,\n fetchOptions: opts.fetch,\n timeout: opts.timeout,\n });\n return resp as ScriptResponse;\n };\n\n /**\n * Returns a list of available layouts on the database.\n */\n layouts = async (opts?: Omit<BaseRequest, \"layout\">) => {\n return (await this.request({\n url: \"/layouts\",\n fetchOptions: opts?.fetch,\n timeout: opts?.timeout,\n })) as AllLayoutsMetadataResponse;\n };\n\n /**\n * Returns a list of available scripts on the database.\n */\n scripts = async (opts?: Omit<BaseRequest, \"layout\">) => {\n return (await this.request({\n url: \"/scripts\",\n fetchOptions: opts?.fetch,\n timeout: opts?.timeout,\n })) as ScriptsMetadataResponse;\n };\n\n containerUpload = async (opts: ContainerUploadOptions) => {\n let url = `/layouts/${opts.layout}/records/${opts.data.recordId}/containers/${opts.data.containerFieldName}`;\n if (opts.data.repetition) {\n url += `/${opts.data.repetition}`;\n }\n const formData = new FormData();\n formData.append(\"upload\", opts.data.file);\n\n await this.request({\n url,\n method: \"POST\",\n body: formData,\n timeout: opts.timeout,\n fetchOptions: opts.fetch,\n });\n };\n\n /**\n * Set global fields for the current session\n */\n globals = async (\n opts: Omit<BaseRequest, \"layout\"> & {\n globalFields: Record<string, string | number>;\n },\n ) => {\n return (await this.request({\n url: \"/globals\",\n method: \"PATCH\",\n body: { globalFields: opts.globalFields },\n fetchOptions: opts?.fetch,\n timeout: opts?.timeout,\n })) as Record<string, never>;\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TokenStoreDefinitions } from '../tokenStore/types.js';
|
|
2
|
-
import { BaseFetchAdapterOptions, GetTokenArguments } from './fetch-base-types.js';
|
|
3
2
|
import { BaseFetchAdapter } from './fetch-base.js';
|
|
3
|
+
import { BaseFetchAdapterOptions, GetTokenArguments } from './fetch-base-types.js';
|
|
4
4
|
export interface FetchAdapterOptions extends BaseFetchAdapterOptions {
|
|
5
5
|
auth: {
|
|
6
6
|
username: string;
|
|
@@ -9,10 +9,10 @@ export interface FetchAdapterOptions extends BaseFetchAdapterOptions {
|
|
|
9
9
|
tokenStore?: TokenStoreDefinitions;
|
|
10
10
|
}
|
|
11
11
|
export declare class FetchAdapter extends BaseFetchAdapter {
|
|
12
|
-
private username;
|
|
13
|
-
private password;
|
|
14
|
-
private tokenStore;
|
|
15
|
-
private getTokenKey;
|
|
12
|
+
private readonly username;
|
|
13
|
+
private readonly password;
|
|
14
|
+
private readonly tokenStore;
|
|
15
|
+
private readonly getTokenKey;
|
|
16
16
|
constructor(args: FetchAdapterOptions);
|
|
17
17
|
/**
|
|
18
18
|
* Gets a FileMaker Data API token for authentication.
|
|
@@ -31,20 +31,17 @@ class FetchAdapter extends BaseFetchAdapter {
|
|
|
31
31
|
method: "POST",
|
|
32
32
|
headers: {
|
|
33
33
|
"Content-Type": "application/json",
|
|
34
|
-
Authorization: `Basic ${Buffer.from(
|
|
35
|
-
`${this.username}:${this.password}`
|
|
36
|
-
).toString("base64")}`
|
|
34
|
+
Authorization: `Basic ${Buffer.from(`${this.username}:${this.password}`).toString("base64")}`
|
|
37
35
|
}
|
|
38
36
|
});
|
|
39
37
|
if (!res.ok) {
|
|
40
38
|
const data = await res.json();
|
|
41
|
-
throw new FileMakerError(
|
|
42
|
-
data.messages[0].code,
|
|
43
|
-
data.messages[0].message
|
|
44
|
-
);
|
|
39
|
+
throw new FileMakerError(data.messages[0].code, data.messages[0].message);
|
|
45
40
|
}
|
|
46
41
|
token = res.headers.get("X-FM-Data-Access-Token");
|
|
47
|
-
if (!token)
|
|
42
|
+
if (!token) {
|
|
43
|
+
throw new Error("Could not get token");
|
|
44
|
+
}
|
|
48
45
|
this.tokenStore.setToken(this.getTokenKey(), token);
|
|
49
46
|
}
|
|
50
47
|
return token;
|
|
@@ -69,8 +66,12 @@ class FetchAdapter extends BaseFetchAdapter {
|
|
|
69
66
|
this.password = args.auth.password;
|
|
70
67
|
this.tokenStore = args.tokenStore ?? memoryStore();
|
|
71
68
|
this.getTokenKey = ((_a = args.tokenStore) == null ? void 0 : _a.getKey) ?? (() => `${args.server}/${args.db}`);
|
|
72
|
-
if (this.username === "")
|
|
73
|
-
|
|
69
|
+
if (this.username === "") {
|
|
70
|
+
throw new Error("Username is required");
|
|
71
|
+
}
|
|
72
|
+
if (this.password === "") {
|
|
73
|
+
throw new Error("Password is required");
|
|
74
|
+
}
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sources":["../../../src/adapters/fetch.ts"],"sourcesContent":["import { FileMakerError } from \"../client-types.js\";\nimport memoryStore from \"../tokenStore/memory.js\";\nimport type { TokenStoreDefinitions } from \"../tokenStore/types.js\";\nimport
|
|
1
|
+
{"version":3,"file":"fetch.js","sources":["../../../src/adapters/fetch.ts"],"sourcesContent":["import { FileMakerError } from \"../client-types.js\";\nimport memoryStore from \"../tokenStore/memory.js\";\nimport type { TokenStoreDefinitions } from \"../tokenStore/types.js\";\nimport { BaseFetchAdapter } from \"./fetch-base.js\";\nimport type { BaseFetchAdapterOptions, GetTokenArguments } from \"./fetch-base-types.js\";\n\nexport interface FetchAdapterOptions extends BaseFetchAdapterOptions {\n auth: {\n username: string;\n password: string;\n };\n tokenStore?: TokenStoreDefinitions;\n}\n\nexport class FetchAdapter extends BaseFetchAdapter {\n private readonly username: string;\n private readonly password: string;\n private readonly tokenStore: Omit<TokenStoreDefinitions, \"getKey\">;\n private readonly getTokenKey: Required<TokenStoreDefinitions>[\"getKey\"];\n\n constructor(args: FetchAdapterOptions) {\n super({ ...args, refreshToken: true });\n this.username = args.auth.username;\n this.password = args.auth.password;\n this.tokenStore = args.tokenStore ?? memoryStore();\n this.getTokenKey = args.tokenStore?.getKey ?? (() => `${args.server}/${args.db}`);\n\n if (this.username === \"\") {\n throw new Error(\"Username is required\");\n }\n if (this.password === \"\") {\n throw new Error(\"Password is required\");\n }\n }\n\n /**\n * Gets a FileMaker Data API token for authentication.\n *\n * This token is **NOT** guaranteed to be valid, since it expires 15 minutes after the last use. Pass `refresh=true` to forcibly get a fresh token\n *\n * @param args.refresh - If true, forces getting a new token instead of using cached token\n * @internal This method is intended for internal use, you should not need to use it in most cases.\n */\n override getToken = async (args?: GetTokenArguments): Promise<string> => {\n const { refresh = false } = args ?? {};\n let token: string | null = null;\n if (!refresh) {\n token = await this.tokenStore.getToken(this.getTokenKey());\n }\n\n if (!token) {\n const res = await fetch(`${this.baseUrl}/sessions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${Buffer.from(`${this.username}:${this.password}`).toString(\"base64\")}`,\n },\n });\n\n if (!res.ok) {\n const data = await res.json();\n throw new FileMakerError(data.messages[0].code, data.messages[0].message);\n }\n token = res.headers.get(\"X-FM-Data-Access-Token\");\n if (!token) {\n throw new Error(\"Could not get token\");\n }\n this.tokenStore.setToken(this.getTokenKey(), token);\n }\n\n return token;\n };\n\n disconnect = async (): Promise<void> => {\n const token = await this.tokenStore.getToken(this.getTokenKey());\n if (token) {\n await this.request({\n url: `/sessions/${token}`,\n method: \"DELETE\",\n fetchOptions: {\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n },\n });\n this.tokenStore.clearToken(this.getTokenKey());\n }\n };\n}\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,qBAAqB,iBAAiB;AAAA,EAMjD,YAAY,MAA2B;;AACrC,UAAM,EAAE,GAAG,MAAM,cAAc,MAAM;AANtB;AACA;AACA;AACA;AAyBR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAW,OAAO,SAA8C;AACvE,YAAM,EAAE,UAAU,MAAM,IAAI,QAAQ,CAAC;AACrC,UAAI,QAAuB;AAC3B,UAAI,CAAC,SAAS;AACZ,gBAAQ,MAAM,KAAK,WAAW,SAAS,KAAK,aAAa;AAAA,MAAA;AAG3D,UAAI,CAAC,OAAO;AACV,cAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,aAAa;AAAA,UAClD,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,SAAS,OAAO,KAAK,GAAG,KAAK,QAAQ,IAAI,KAAK,QAAQ,EAAE,EAAE,SAAS,QAAQ,CAAC;AAAA,UAAA;AAAA,QAC7F,CACD;AAEG,YAAA,CAAC,IAAI,IAAI;AACL,gBAAA,OAAO,MAAM,IAAI,KAAK;AACtB,gBAAA,IAAI,eAAe,KAAK,SAAS,CAAC,EAAE,MAAM,KAAK,SAAS,CAAC,EAAE,OAAO;AAAA,QAAA;AAElE,gBAAA,IAAI,QAAQ,IAAI,wBAAwB;AAChD,YAAI,CAAC,OAAO;AACJ,gBAAA,IAAI,MAAM,qBAAqB;AAAA,QAAA;AAEvC,aAAK,WAAW,SAAS,KAAK,YAAA,GAAe,KAAK;AAAA,MAAA;AAG7C,aAAA;AAAA,IACT;AAEA,sCAAa,YAA2B;AACtC,YAAM,QAAQ,MAAM,KAAK,WAAW,SAAS,KAAK,aAAa;AAC/D,UAAI,OAAO;AACT,cAAM,KAAK,QAAQ;AAAA,UACjB,KAAK,aAAa,KAAK;AAAA,UACvB,QAAQ;AAAA,UACR,cAAc;AAAA,YACZ,SAAS;AAAA,cACP,eAAe,UAAU,KAAK;AAAA,cAC9B,gBAAgB;AAAA,YAAA;AAAA,UAClB;AAAA,QACF,CACD;AACD,aAAK,WAAW,WAAW,KAAK,YAAA,CAAa;AAAA,MAAA;AAAA,IAEjD;AAlEO,SAAA,WAAW,KAAK,KAAK;AACrB,SAAA,WAAW,KAAK,KAAK;AACrB,SAAA,aAAa,KAAK,cAAc,YAAY;AAC5C,SAAA,gBAAc,UAAK,eAAL,mBAAiB,YAAW,MAAM,GAAG,KAAK,MAAM,IAAI,KAAK,EAAE;AAE1E,QAAA,KAAK,aAAa,IAAI;AAClB,YAAA,IAAI,MAAM,sBAAsB;AAAA,IAAA;AAEpC,QAAA,KAAK,aAAa,IAAI;AAClB,YAAA,IAAI,MAAM,sBAAsB;AAAA,IAAA;AAAA,EACxC;AAyDJ;"}
|
|
@@ -18,8 +18,8 @@ export type OttoAdapterOptions = BaseFetchAdapterOptions & {
|
|
|
18
18
|
auth: OttoAuth;
|
|
19
19
|
};
|
|
20
20
|
export declare class OttoAdapter extends BaseFetchAdapter {
|
|
21
|
-
private apiKey;
|
|
22
|
-
private port;
|
|
21
|
+
private readonly apiKey;
|
|
22
|
+
private readonly port;
|
|
23
23
|
constructor(options: OttoAdapterOptions);
|
|
24
24
|
protected getToken: () => Promise<string>;
|
|
25
25
|
}
|
|
@@ -7,8 +7,8 @@ class OttoAdapter extends BaseFetchAdapter {
|
|
|
7
7
|
super({ ...options, refreshToken: false });
|
|
8
8
|
__publicField(this, "apiKey");
|
|
9
9
|
__publicField(this, "port");
|
|
10
|
-
__publicField(this, "getToken",
|
|
11
|
-
return this.apiKey;
|
|
10
|
+
__publicField(this, "getToken", () => {
|
|
11
|
+
return Promise.resolve(this.apiKey);
|
|
12
12
|
});
|
|
13
13
|
this.apiKey = options.auth.apiKey;
|
|
14
14
|
this.port = options.auth.ottoPort;
|
|
@@ -17,9 +17,7 @@ class OttoAdapter extends BaseFetchAdapter {
|
|
|
17
17
|
} else if (this.apiKey.startsWith("dk_")) {
|
|
18
18
|
this.baseUrl.pathname = `otto/${this.baseUrl.pathname.replace(/^\/+|\/+$/g, "")}`;
|
|
19
19
|
} else {
|
|
20
|
-
throw new Error(
|
|
21
|
-
"Invalid Otto API key format. Must start with 'KEY_' (Otto v3) or 'dk_' (OttoFMS)"
|
|
22
|
-
);
|
|
20
|
+
throw new Error("Invalid Otto API key format. Must start with 'KEY_' (Otto v3) or 'dk_' (OttoFMS)");
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otto.js","sources":["../../../src/adapters/otto.ts"],"sourcesContent":["import { BaseFetchAdapter } from \"./fetch-base.js\";\nimport type { BaseFetchAdapterOptions } from \"./fetch-base-types.js\";\n\nexport type Otto3APIKey = `KEY_${string}`;\nexport type OttoFMSAPIKey = `dk_${string}`;\nexport type OttoAPIKey = Otto3APIKey | OttoFMSAPIKey;\n\nexport function isOtto3APIKey(key: string): key is Otto3APIKey {\n return key.startsWith(\"KEY_\");\n}\nexport function isOttoFMSAPIKey(key: string): key is OttoFMSAPIKey {\n return key.startsWith(\"dk_\");\n}\nexport function isOttoAPIKey(key: string): key is OttoAPIKey {\n return isOtto3APIKey(key) || isOttoFMSAPIKey(key);\n}\n\nexport function isOttoAuth(auth: unknown): auth is OttoAuth {\n if (typeof auth !== \"object\" || auth === null) return false;\n return \"apiKey\" in auth;\n}\n\ntype OttoAuth =\n | {\n apiKey: Otto3APIKey;\n ottoPort?: number;\n }\n | { apiKey: OttoFMSAPIKey; ottoPort?: never };\n\nexport type OttoAdapterOptions = BaseFetchAdapterOptions & {\n auth: OttoAuth;\n};\n\nexport class OttoAdapter extends BaseFetchAdapter {\n private apiKey: OttoAPIKey | Otto3APIKey;\n private port: number | undefined;\n\n constructor(options: OttoAdapterOptions) {\n super({ ...options, refreshToken: false });\n this.apiKey = options.auth.apiKey;\n this.port = options.auth.ottoPort;\n\n if (this.apiKey.startsWith(\"KEY_\")) {\n // otto v3 uses port 3030\n this.baseUrl.port = (this.port ?? 3030).toString();\n } else if (this.apiKey.startsWith(\"dk_\")) {\n // otto v4 uses default port, but with /otto prefix\n this.baseUrl.pathname = `otto/${this.baseUrl.pathname.replace(/^\\/+|\\/+$/g, \"\")}`;\n } else {\n throw new Error(\
|
|
1
|
+
{"version":3,"file":"otto.js","sources":["../../../src/adapters/otto.ts"],"sourcesContent":["import { BaseFetchAdapter } from \"./fetch-base.js\";\nimport type { BaseFetchAdapterOptions } from \"./fetch-base-types.js\";\n\nexport type Otto3APIKey = `KEY_${string}`;\nexport type OttoFMSAPIKey = `dk_${string}`;\nexport type OttoAPIKey = Otto3APIKey | OttoFMSAPIKey;\n\nexport function isOtto3APIKey(key: string): key is Otto3APIKey {\n return key.startsWith(\"KEY_\");\n}\nexport function isOttoFMSAPIKey(key: string): key is OttoFMSAPIKey {\n return key.startsWith(\"dk_\");\n}\nexport function isOttoAPIKey(key: string): key is OttoAPIKey {\n return isOtto3APIKey(key) || isOttoFMSAPIKey(key);\n}\n\nexport function isOttoAuth(auth: unknown): auth is OttoAuth {\n if (typeof auth !== \"object\" || auth === null) {\n return false;\n }\n return \"apiKey\" in auth;\n}\n\ntype OttoAuth =\n | {\n apiKey: Otto3APIKey;\n ottoPort?: number;\n }\n | { apiKey: OttoFMSAPIKey; ottoPort?: never };\n\nexport type OttoAdapterOptions = BaseFetchAdapterOptions & {\n auth: OttoAuth;\n};\n\nexport class OttoAdapter extends BaseFetchAdapter {\n private readonly apiKey: OttoAPIKey | Otto3APIKey;\n private readonly port: number | undefined;\n\n constructor(options: OttoAdapterOptions) {\n super({ ...options, refreshToken: false });\n this.apiKey = options.auth.apiKey;\n this.port = options.auth.ottoPort;\n\n if (this.apiKey.startsWith(\"KEY_\")) {\n // otto v3 uses port 3030\n this.baseUrl.port = (this.port ?? 3030).toString();\n } else if (this.apiKey.startsWith(\"dk_\")) {\n // otto v4 uses default port, but with /otto prefix\n this.baseUrl.pathname = `otto/${this.baseUrl.pathname.replace(/^\\/+|\\/+$/g, \"\")}`;\n } else {\n throw new Error(\"Invalid Otto API key format. Must start with 'KEY_' (Otto v3) or 'dk_' (OttoFMS)\");\n }\n }\n\n protected override getToken = (): Promise<string> => {\n return Promise.resolve(this.apiKey);\n };\n}\n"],"names":[],"mappings":";;;;AAmCO,MAAM,oBAAoB,iBAAiB;AAAA,EAIhD,YAAY,SAA6B;AACvC,UAAM,EAAE,GAAG,SAAS,cAAc,OAAO;AAJ1B;AACA;AAkBE,oCAAW,MAAuB;AAC5C,aAAA,QAAQ,QAAQ,KAAK,MAAM;AAAA,IACpC;AAhBO,SAAA,SAAS,QAAQ,KAAK;AACtB,SAAA,OAAO,QAAQ,KAAK;AAEzB,QAAI,KAAK,OAAO,WAAW,MAAM,GAAG;AAElC,WAAK,QAAQ,QAAQ,KAAK,QAAQ,MAAM,SAAS;AAAA,IACxC,WAAA,KAAK,OAAO,WAAW,KAAK,GAAG;AAEnC,WAAA,QAAQ,WAAW,QAAQ,KAAK,QAAQ,SAAS,QAAQ,cAAc,EAAE,CAAC;AAAA,IAAA,OAC1E;AACC,YAAA,IAAI,MAAM,kFAAkF;AAAA,IAAA;AAAA,EACpG;AAMJ;"}
|
|
@@ -3,11 +3,11 @@ export declare const ZFieldValue: z.ZodUnion<readonly [z.ZodString, z.ZodNumber,
|
|
|
3
3
|
export type FieldValue = z.infer<typeof ZFieldValue>;
|
|
4
4
|
export declare const ZFieldData: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodNull, z.ZodUnknown]>>;
|
|
5
5
|
export type FieldData = Record<string, unknown>;
|
|
6
|
-
export
|
|
6
|
+
export interface GenericPortalData {
|
|
7
7
|
[key: string]: {
|
|
8
8
|
[x: string]: string | number | null | unknown;
|
|
9
9
|
};
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
export type PortalsWithIds<U extends GenericPortalData = GenericPortalData> = {
|
|
12
12
|
[key in keyof U]: Array<U[key] & {
|
|
13
13
|
recordId: string;
|
|
@@ -20,13 +20,13 @@ export type UpdatePortalsWithIds<U extends GenericPortalData = GenericPortalData
|
|
|
20
20
|
modId?: string;
|
|
21
21
|
}>;
|
|
22
22
|
};
|
|
23
|
-
export
|
|
23
|
+
export interface FMRecord<T extends FieldData = FieldData, U extends GenericPortalData = GenericPortalData> {
|
|
24
24
|
fieldData: T;
|
|
25
25
|
recordId: string;
|
|
26
26
|
modId: string;
|
|
27
27
|
portalData: PortalsWithIds<U>;
|
|
28
|
-
}
|
|
29
|
-
export
|
|
28
|
+
}
|
|
29
|
+
export interface ScriptParams {
|
|
30
30
|
script?: string;
|
|
31
31
|
"script.param"?: string;
|
|
32
32
|
"script.prerequest"?: string;
|
|
@@ -34,7 +34,7 @@ export type ScriptParams = {
|
|
|
34
34
|
"script.presort"?: string;
|
|
35
35
|
"script.presort.param"?: string;
|
|
36
36
|
timeout?: number;
|
|
37
|
-
}
|
|
37
|
+
}
|
|
38
38
|
declare const ZScriptResponse: z.ZodObject<{
|
|
39
39
|
scriptResult: z.ZodOptional<z.ZodString>;
|
|
40
40
|
scriptError: z.ZodOptional<z.ZodString>;
|
|
@@ -68,36 +68,36 @@ export type UpdateResponse = ScriptResponse & {
|
|
|
68
68
|
};
|
|
69
69
|
export type DeleteParams = ScriptParams;
|
|
70
70
|
export type DeleteResponse = ScriptResponse;
|
|
71
|
-
export
|
|
71
|
+
export interface RangeParams {
|
|
72
72
|
offset?: number;
|
|
73
73
|
limit?: number;
|
|
74
|
-
}
|
|
75
|
-
export
|
|
74
|
+
}
|
|
75
|
+
export interface RangeParamsRaw {
|
|
76
76
|
_offset?: number;
|
|
77
77
|
_limit?: number;
|
|
78
|
-
}
|
|
78
|
+
}
|
|
79
79
|
export type PortalRanges<U extends GenericPortalData = GenericPortalData> = Partial<{
|
|
80
80
|
[key in keyof U]: RangeParams;
|
|
81
81
|
}>;
|
|
82
|
-
export
|
|
82
|
+
export interface PortalRangesParams<U extends GenericPortalData = GenericPortalData> {
|
|
83
83
|
portalRanges?: PortalRanges<U>;
|
|
84
|
-
}
|
|
84
|
+
}
|
|
85
85
|
export type GetParams<U extends GenericPortalData = GenericPortalData> = ScriptParams & PortalRangesParams<U> & {
|
|
86
86
|
"layout.response"?: string;
|
|
87
87
|
dateformats?: "US" | "file_locale" | "ISO8601";
|
|
88
88
|
};
|
|
89
|
-
export
|
|
89
|
+
export interface Sort<T extends FieldData = FieldData> {
|
|
90
90
|
fieldName: keyof T;
|
|
91
91
|
sortOrder?: "ascend" | "descend" | (string & {});
|
|
92
|
-
}
|
|
92
|
+
}
|
|
93
93
|
export type ListParams<T extends FieldData = FieldData, U extends GenericPortalData = GenericPortalData> = GetParams<U> & RangeParams & {
|
|
94
|
-
sort?: Sort<T> |
|
|
94
|
+
sort?: Sort<T> | Sort<T>[];
|
|
95
95
|
};
|
|
96
96
|
export type ListParamsRaw<T extends FieldData = FieldData, U extends GenericPortalData = GenericPortalData> = GetParams<U> & RangeParamsRaw & {
|
|
97
|
-
_sort?:
|
|
97
|
+
_sort?: Sort<T>[];
|
|
98
98
|
};
|
|
99
99
|
export type GetResponse<T extends FieldData = FieldData, U extends GenericPortalData = GenericPortalData> = ScriptResponse & {
|
|
100
|
-
data:
|
|
100
|
+
data: FMRecord<T, U>[];
|
|
101
101
|
dataInfo: DataInfo;
|
|
102
102
|
};
|
|
103
103
|
export type GetResponseOne<T extends FieldData = FieldData, U extends GenericPortalData = GenericPortalData> = ScriptResponse & {
|
|
@@ -114,25 +114,25 @@ export type Query<T extends FieldData = FieldData, U extends GenericPortalData =
|
|
|
114
114
|
}> & {
|
|
115
115
|
omit?: "true";
|
|
116
116
|
};
|
|
117
|
-
export
|
|
117
|
+
export interface LayoutMetadataResponse {
|
|
118
118
|
fieldMetaData: FieldMetaData[];
|
|
119
119
|
portalMetaData: {
|
|
120
120
|
[key: string]: FieldMetaData[];
|
|
121
121
|
};
|
|
122
122
|
valueLists?: ValueList[];
|
|
123
|
-
}
|
|
124
|
-
export
|
|
123
|
+
}
|
|
124
|
+
export interface ProductInfoMetadataResponse {
|
|
125
125
|
name: string;
|
|
126
126
|
dateFormat: string;
|
|
127
127
|
timeFormat: string;
|
|
128
128
|
timeStampFormat: string;
|
|
129
|
-
}
|
|
130
|
-
export
|
|
129
|
+
}
|
|
130
|
+
export interface DatabaseMetadataResponse {
|
|
131
131
|
databases: Array<{
|
|
132
132
|
name: string;
|
|
133
133
|
}>;
|
|
134
|
-
}
|
|
135
|
-
export
|
|
134
|
+
}
|
|
135
|
+
export interface FieldMetaData {
|
|
136
136
|
name: string;
|
|
137
137
|
type: "normal" | "calculation" | "summary";
|
|
138
138
|
displayType: "editText" | "popupList" | "popupMenu" | "checkBox" | "calendar" | "radioButtons" | "secureText";
|
|
@@ -147,28 +147,28 @@ export type FieldMetaData = {
|
|
|
147
147
|
repetitions: number;
|
|
148
148
|
timeOfDay: boolean;
|
|
149
149
|
valueList?: string;
|
|
150
|
-
}
|
|
151
|
-
|
|
150
|
+
}
|
|
151
|
+
interface ValueList {
|
|
152
152
|
name: string;
|
|
153
153
|
type: "customList" | "byField";
|
|
154
154
|
values: Array<{
|
|
155
155
|
value: string;
|
|
156
156
|
displayValue: string;
|
|
157
157
|
}>;
|
|
158
|
-
}
|
|
158
|
+
}
|
|
159
159
|
/**
|
|
160
160
|
* Represents the data returned by a call to the Data API `layouts` endpoint.
|
|
161
161
|
*/
|
|
162
|
-
export
|
|
162
|
+
export interface AllLayoutsMetadataResponse {
|
|
163
163
|
/**
|
|
164
164
|
* A list of `Layout` or `LayoutsFolder` objects.
|
|
165
165
|
*/
|
|
166
166
|
layouts: LayoutOrFolder[];
|
|
167
|
-
}
|
|
167
|
+
}
|
|
168
168
|
/**
|
|
169
169
|
* Represents a FileMaker layout.
|
|
170
170
|
*/
|
|
171
|
-
export
|
|
171
|
+
export interface Layout {
|
|
172
172
|
/**
|
|
173
173
|
* The name of the layout
|
|
174
174
|
*/
|
|
@@ -178,11 +178,11 @@ export type Layout = {
|
|
|
178
178
|
* the layout is associated with.
|
|
179
179
|
*/
|
|
180
180
|
table: string;
|
|
181
|
-
}
|
|
181
|
+
}
|
|
182
182
|
/**
|
|
183
183
|
* Represents a folder of `Layout` or `LayoutsFolder` objects.
|
|
184
184
|
*/
|
|
185
|
-
export
|
|
185
|
+
export interface LayoutsFolder {
|
|
186
186
|
/**
|
|
187
187
|
* The name of the folder
|
|
188
188
|
*/
|
|
@@ -192,33 +192,33 @@ export type LayoutsFolder = {
|
|
|
192
192
|
* A list of the Layout or LayoutsFolder objects in the folder.
|
|
193
193
|
*/
|
|
194
194
|
folderLayoutNames?: LayoutOrFolder[];
|
|
195
|
-
}
|
|
195
|
+
}
|
|
196
196
|
export type LayoutOrFolder = Layout | LayoutsFolder;
|
|
197
197
|
/**
|
|
198
198
|
* Represents the data returned by a call to the Data API `scripts` endpoint.
|
|
199
199
|
*/
|
|
200
|
-
export
|
|
200
|
+
export interface ScriptsMetadataResponse {
|
|
201
201
|
/**
|
|
202
202
|
* A list of `Layout` or `LayoutsFolder` objects.
|
|
203
203
|
*/
|
|
204
204
|
scripts: ScriptOrFolder[];
|
|
205
|
-
}
|
|
206
|
-
|
|
205
|
+
}
|
|
206
|
+
interface Script {
|
|
207
207
|
name: string;
|
|
208
208
|
isFolder: false;
|
|
209
|
-
}
|
|
210
|
-
|
|
209
|
+
}
|
|
210
|
+
interface ScriptFolder {
|
|
211
211
|
name: string;
|
|
212
212
|
isFolder: true;
|
|
213
213
|
folderScriptNames: ScriptOrFolder[];
|
|
214
|
-
}
|
|
214
|
+
}
|
|
215
215
|
export type ScriptOrFolder = Script | ScriptFolder;
|
|
216
|
-
export
|
|
216
|
+
export interface RawFMResponse<T = unknown> {
|
|
217
217
|
response?: T;
|
|
218
218
|
messages?: [{
|
|
219
219
|
code: string;
|
|
220
220
|
}];
|
|
221
|
-
}
|
|
221
|
+
}
|
|
222
222
|
export declare class FileMakerError extends Error {
|
|
223
223
|
readonly code: string;
|
|
224
224
|
constructor(code: string, message: string);
|
package/dist/esm/client-types.js
CHANGED
|
@@ -2,12 +2,7 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { z } from "zod/v4";
|
|
5
|
-
const ZFieldValue = z.union([
|
|
6
|
-
z.string(),
|
|
7
|
-
z.number(),
|
|
8
|
-
z.null(),
|
|
9
|
-
z.unknown()
|
|
10
|
-
]);
|
|
5
|
+
const ZFieldValue = z.union([z.string(), z.number(), z.null(), z.unknown()]);
|
|
11
6
|
const ZFieldData = z.record(z.string(), ZFieldValue);
|
|
12
7
|
z.object({
|
|
13
8
|
scriptResult: z.string().optional(),
|