@proofkit/fmdapi 5.0.3-beta.0 → 5.1.0-beta.2

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 (47) hide show
  1. package/bin/intent.js +20 -0
  2. package/dist/esm/adapters/core.d.ts +4 -4
  3. package/dist/esm/adapters/fetch-base-types.d.ts +4 -4
  4. package/dist/esm/adapters/fetch-base.d.ts +2 -2
  5. package/dist/esm/adapters/fetch-base.js +36 -49
  6. package/dist/esm/adapters/fetch-base.js.map +1 -1
  7. package/dist/esm/adapters/fetch.d.ts +5 -5
  8. package/dist/esm/adapters/fetch.js +11 -10
  9. package/dist/esm/adapters/fetch.js.map +1 -1
  10. package/dist/esm/adapters/fm-http.d.ts +32 -0
  11. package/dist/esm/adapters/fm-http.js +170 -0
  12. package/dist/esm/adapters/fm-http.js.map +1 -0
  13. package/dist/esm/adapters/otto.d.ts +2 -2
  14. package/dist/esm/adapters/otto.js +3 -5
  15. package/dist/esm/adapters/otto.js.map +1 -1
  16. package/dist/esm/client-types.d.ts +41 -41
  17. package/dist/esm/client-types.js +1 -6
  18. package/dist/esm/client-types.js.map +1 -1
  19. package/dist/esm/client.d.ts +28 -44
  20. package/dist/esm/client.js +75 -80
  21. package/dist/esm/client.js.map +1 -1
  22. package/dist/esm/index.d.ts +5 -6
  23. package/dist/esm/index.js +7 -5
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/tokenStore/index.d.ts +1 -1
  26. package/dist/esm/tokenStore/memory.js.map +1 -1
  27. package/dist/esm/tokenStore/types.d.ts +2 -2
  28. package/dist/esm/tokenStore/upstash.d.ts +1 -1
  29. package/dist/esm/utils.d.ts +7 -7
  30. package/dist/esm/utils.js +6 -4
  31. package/dist/esm/utils.js.map +1 -1
  32. package/package.json +37 -26
  33. package/skills/fmdapi-client/SKILL.md +490 -0
  34. package/src/adapters/core.ts +6 -9
  35. package/src/adapters/fetch-base-types.ts +5 -3
  36. package/src/adapters/fetch-base.ts +53 -78
  37. package/src/adapters/fetch.ts +19 -24
  38. package/src/adapters/fm-http.ts +224 -0
  39. package/src/adapters/otto.ts +8 -8
  40. package/src/client-types.ts +59 -83
  41. package/src/client.ts +131 -167
  42. package/src/index.ts +5 -9
  43. package/src/tokenStore/file.ts +2 -4
  44. package/src/tokenStore/index.ts +1 -1
  45. package/src/tokenStore/types.ts +2 -2
  46. package/src/tokenStore/upstash.ts +2 -5
  47. package/src/utils.ts +16 -23
package/src/client.ts CHANGED
@@ -1,11 +1,12 @@
1
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
1
2
  import type { Adapter, ExecuteScriptOptions } from "./adapters/core.js";
2
3
  import type {
3
4
  CreateParams,
4
5
  CreateResponse,
5
6
  DeleteParams,
6
7
  DeleteResponse,
7
- FMRecord,
8
8
  FieldData,
9
+ FMRecord,
9
10
  GenericPortalData,
10
11
  GetParams,
11
12
  GetResponse,
@@ -17,13 +18,12 @@ import type {
17
18
  UpdateResponse,
18
19
  } from "./client-types.js";
19
20
  import { FileMakerError } from "./index.js";
20
- import type { StandardSchemaV1 } from "@standard-schema/spec";
21
21
 
22
22
  function asNumber(input: string | number): number {
23
- return typeof input === "string" ? parseInt(input) : input;
23
+ return typeof input === "string" ? Number.parseInt(input, 10) : input;
24
24
  }
25
25
 
26
- export type ClientObjectProps = {
26
+ export interface ClientObjectProps {
27
27
  /**
28
28
  * The layout to use by default for all requests. Can be overrridden on each request.
29
29
  */
@@ -38,11 +38,28 @@ export type ClientObjectProps = {
38
38
  */
39
39
  portalData?: Record<string, StandardSchemaV1<FieldData>>;
40
40
  };
41
- };
41
+ }
42
42
 
43
- type FetchOptions = {
43
+ interface FetchOptions {
44
44
  fetch?: RequestInit;
45
- };
45
+ }
46
+
47
+ export interface IgnoreEmptyResult {
48
+ /**
49
+ * If true, a find that returns no results will retun an empty array instead of throwing an error.
50
+ * @default false
51
+ */
52
+ ignoreEmptyResult?: boolean;
53
+ }
54
+
55
+ export interface ContainerUploadArgs<T extends FieldData = FieldData> {
56
+ containerFieldName: keyof T;
57
+ containerFieldRepetition?: string | number;
58
+ file: Blob;
59
+ recordId: number | string;
60
+ modId?: number;
61
+ timeout?: number;
62
+ }
46
63
 
47
64
  function DataApi<
48
65
  Fd extends FieldData = FieldData,
@@ -56,17 +73,13 @@ function DataApi<
56
73
  type InferredPortalData = Opts["schema"] extends object
57
74
  ? Opts["schema"]["portalData"] extends object
58
75
  ? {
59
- [K in keyof Opts["schema"]["portalData"]]: StandardSchemaV1.InferOutput<
60
- Opts["schema"]["portalData"][K]
61
- >;
76
+ [K in keyof Opts["schema"]["portalData"]]: StandardSchemaV1.InferOutput<Opts["schema"]["portalData"][K]>;
62
77
  }
63
78
  : Pd
64
79
  : Pd;
65
80
 
66
81
  if ("zodValidators" in options) {
67
- throw new Error(
68
- "zodValidators is no longer supported. Use schema instead, or re-run the typegen command",
69
- );
82
+ throw new Error("zodValidators is no longer supported. Use schema instead, or re-run the typegen command");
70
83
  }
71
84
 
72
85
  const schema = options.schema;
@@ -90,10 +103,9 @@ function DataApi<
90
103
  > = CreateParams<U> & {
91
104
  fieldData: Partial<T>;
92
105
  };
93
- type GetArgs<U extends InferredPortalData = InferredPortalData> =
94
- GetParams<U> & {
95
- recordId: number | string;
96
- };
106
+ type GetArgs<U extends InferredPortalData = InferredPortalData> = GetParams<U> & {
107
+ recordId: number | string;
108
+ };
97
109
  type UpdateArgs<
98
110
  T extends InferredFieldData = InferredFieldData,
99
111
  U extends InferredPortalData = InferredPortalData,
@@ -101,29 +113,14 @@ function DataApi<
101
113
  fieldData: Partial<T>;
102
114
  recordId: number | string;
103
115
  };
104
- type ContainerUploadArgs<T extends InferredFieldData = InferredFieldData> = {
105
- containerFieldName: keyof T;
106
- containerFieldRepetition?: string | number;
107
- file: Blob;
108
- recordId: number | string;
109
- modId?: number;
110
- timeout?: number;
111
- };
112
116
  type DeleteArgs = DeleteParams & {
113
117
  recordId: number | string;
114
118
  };
115
- type IgnoreEmptyResult = {
116
- /**
117
- * If true, a find that returns no results will retun an empty array instead of throwing an error.
118
- * @default false
119
- */
120
- ignoreEmptyResult?: boolean;
121
- };
122
119
  type FindArgs<
123
120
  T extends FieldData = InferredFieldData,
124
121
  U extends InferredPortalData = InferredPortalData,
125
122
  > = ListParams<T, U> & {
126
- query: Query<T> | Array<Query<T>>;
123
+ query: Query<T> | Query<T>[];
127
124
  timeout?: number;
128
125
  };
129
126
 
@@ -132,11 +129,8 @@ function DataApi<
132
129
  /**
133
130
  * List all records from a given layout, no find criteria applied.
134
131
  */
135
- async function _list(): Promise<
136
- GetResponse<InferredFieldData, InferredPortalData>
137
- >;
138
132
  async function _list(
139
- args: ListParams<InferredFieldData, InferredPortalData> & FetchOptions,
133
+ args?: ListParams<InferredFieldData, InferredPortalData> & FetchOptions,
140
134
  ): Promise<GetResponse<InferredFieldData, InferredPortalData>>;
141
135
  async function _list(
142
136
  args?: ListParams<InferredFieldData, InferredPortalData> & FetchOptions,
@@ -144,16 +138,21 @@ function DataApi<
144
138
  const { fetch, timeout, ...params } = args ?? {};
145
139
 
146
140
  // rename and refactor limit, offset, and sort keys for this request
147
- if ("limit" in params && params.limit !== undefined)
148
- delete Object.assign(params, { _limit: params.limit })["limit"];
141
+ if ("limit" in params && params.limit !== undefined) {
142
+ Object.assign(params, { _limit: params.limit }).limit = undefined;
143
+ }
149
144
  if ("offset" in params && params.offset !== undefined) {
150
- if (params.offset <= 1) delete params.offset;
151
- else delete Object.assign(params, { _offset: params.offset })["offset"];
145
+ if (params.offset <= 1) {
146
+ params.offset = undefined;
147
+ } else {
148
+ Object.assign(params, { _offset: params.offset }).offset = undefined;
149
+ }
152
150
  }
153
- if ("sort" in params && params.sort !== undefined)
154
- delete Object.assign(params, {
151
+ if ("sort" in params && params.sort !== undefined) {
152
+ Object.assign(params, {
155
153
  _sort: Array.isArray(params.sort) ? params.sort : [params.sort],
156
- })["sort"];
154
+ }).sort = undefined;
155
+ }
157
156
 
158
157
  const result = await list({
159
158
  layout,
@@ -162,52 +161,44 @@ function DataApi<
162
161
  timeout,
163
162
  });
164
163
 
165
- if (result.dataInfo.foundCount > result.dataInfo.returnedCount) {
166
- // more records found than returned
167
- if (args?.limit === undefined && args?.offset === undefined) {
168
- // and the user didn't specify a limit or offset, so we should warn them
169
- console.warn(
170
- `🚨 @proofkit/fmdapi: Loaded only ${result.dataInfo.returnedCount} of the ${result.dataInfo.foundCount} records from your "${layout}" layout. Use the "listAll" method to automatically paginate through all records, or specify a "limit" and "offset" to handle pagination yourself.`,
171
- );
172
- }
164
+ if (
165
+ result.dataInfo.foundCount > result.dataInfo.returnedCount &&
166
+ args?.limit === undefined &&
167
+ args?.offset === undefined
168
+ ) {
169
+ // more records found than returned and the user didn't specify a limit or offset, so we should warn them
170
+ console.warn(
171
+ `🚨 @proofkit/fmdapi: Loaded only ${result.dataInfo.returnedCount} of the ${result.dataInfo.foundCount} records from your "${layout}" layout. Use the "listAll" method to automatically paginate through all records, or specify a "limit" and "offset" to handle pagination yourself.`,
172
+ );
173
173
  }
174
174
 
175
- return await runSchemaValidationAndTransform(
176
- schema,
177
- result as GetResponse<InferredFieldData, InferredPortalData>,
178
- );
175
+ return await runSchemaValidationAndTransform(schema, result as GetResponse<InferredFieldData, InferredPortalData>);
179
176
  }
180
177
 
181
178
  /**
182
179
  * Paginate through all records from a given layout, no find criteria applied.
183
180
  * ⚠️ WARNING: Use this method with caution, as it can be slow with large datasets
184
181
  */
185
- async function listAll<
186
- T extends FieldData = InferredFieldData,
187
- U extends InferredPortalData = InferredPortalData,
188
- >(): Promise<FMRecord<T, U>[]>;
189
- async function listAll<
190
- T extends FieldData = InferredFieldData,
191
- U extends InferredPortalData = InferredPortalData,
192
- >(args: ListParams<T, U> & FetchOptions): Promise<FMRecord<T, U>[]>;
193
- async function listAll<
194
- T extends FieldData = InferredFieldData,
195
- U extends InferredPortalData = InferredPortalData,
196
- >(args?: ListParams<T, U> & FetchOptions): Promise<FMRecord<T, U>[]> {
197
- let runningData: GetResponse<T, U>["data"] = [];
182
+ async function listAll(
183
+ args?: ListParams<InferredFieldData, InferredPortalData> & FetchOptions,
184
+ ): Promise<FMRecord<InferredFieldData, InferredPortalData>[]>;
185
+ async function listAll(
186
+ args?: ListParams<InferredFieldData, InferredPortalData> & FetchOptions,
187
+ ): Promise<FMRecord<InferredFieldData, InferredPortalData>[]> {
188
+ let runningData: GetResponse<InferredFieldData, InferredPortalData>["data"] = [];
198
189
  const limit = args?.limit ?? 100;
199
190
  let offset = args?.offset ?? 1;
200
191
 
201
- // eslint-disable-next-line no-constant-condition
202
192
  while (true) {
203
- const data = (await _list({
193
+ const data = await _list({
204
194
  ...args,
205
195
  offset,
206
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
207
- } as any)) as unknown as GetResponse<T, U>;
196
+ });
208
197
  runningData = [...runningData, ...data.data];
209
- if (runningData.length >= data.dataInfo.foundCount) break;
210
- offset = offset + limit;
198
+ if (runningData.length >= data.dataInfo.foundCount) {
199
+ break;
200
+ }
201
+ offset += limit;
211
202
  }
212
203
  return runningData;
213
204
  }
@@ -243,10 +234,7 @@ function DataApi<
243
234
  fetch,
244
235
  timeout,
245
236
  });
246
- return await runSchemaValidationAndTransform(
247
- schema,
248
- result as GetResponse<InferredFieldData, InferredPortalData>,
249
- );
237
+ return await runSchemaValidationAndTransform(schema, result as GetResponse<InferredFieldData, InferredPortalData>);
250
238
  }
251
239
 
252
240
  /**
@@ -268,9 +256,7 @@ function DataApi<
268
256
  /**
269
257
  * Delete a single record by internal RecordId
270
258
  */
271
- async function deleteRecord(
272
- args: DeleteArgs & FetchOptions,
273
- ): Promise<DeleteResponse> {
259
+ function deleteRecord(args: DeleteArgs & FetchOptions): Promise<DeleteResponse> {
274
260
  args.recordId = asNumber(args.recordId);
275
261
  const { recordId, fetch, timeout, ...params } = args;
276
262
 
@@ -286,35 +272,29 @@ function DataApi<
286
272
  * Find records in a given layout
287
273
  */
288
274
  async function _find(
289
- args: FindArgs<InferredFieldData, InferredPortalData> &
290
- IgnoreEmptyResult &
291
- FetchOptions,
275
+ args: FindArgs<InferredFieldData, InferredPortalData> & IgnoreEmptyResult & FetchOptions,
292
276
  ): Promise<GetResponse<InferredFieldData, InferredPortalData>> {
293
- const {
294
- query: queryInput,
295
- ignoreEmptyResult = false,
296
- timeout,
297
- fetch,
298
- ...params
299
- } = args;
300
- const query = !Array.isArray(queryInput) ? [queryInput] : queryInput;
277
+ const { query: queryInput, ignoreEmptyResult = false, timeout, fetch, ...params } = args;
278
+ const query = Array.isArray(queryInput) ? queryInput : [queryInput];
301
279
 
302
280
  // rename and refactor limit, offset, and sort keys for this request
303
- if ("offset" in params && params.offset !== undefined) {
304
- if (params.offset <= 1) delete params.offset;
281
+ if ("offset" in params && params.offset !== undefined && params.offset <= 1) {
282
+ params.offset = undefined;
305
283
  }
306
284
  if ("dateformats" in params && params.dateformats !== undefined) {
307
285
  // reassign dateformats to match FileMaker's expected values
286
+ let dateFormatValue: number;
287
+ if (params.dateformats === "US") {
288
+ dateFormatValue = 0;
289
+ } else if (params.dateformats === "file_locale") {
290
+ dateFormatValue = 1;
291
+ } else if (params.dateformats === "ISO8601") {
292
+ dateFormatValue = 2;
293
+ } else {
294
+ dateFormatValue = 0;
295
+ }
308
296
  // @ts-expect-error FM wants a string, so this is fine
309
- params.dateformats = (
310
- params.dateformats === "US"
311
- ? 0
312
- : params.dateformats === "file_locale"
313
- ? 1
314
- : params.dateformats === "ISO8601"
315
- ? 2
316
- : 0
317
- ).toString();
297
+ params.dateformats = dateFormatValue.toString();
318
298
  }
319
299
  const result = (await find({
320
300
  data: { ...params, query },
@@ -322,18 +302,21 @@ function DataApi<
322
302
  fetch,
323
303
  timeout,
324
304
  }).catch((e: unknown) => {
325
- if (ignoreEmptyResult && e instanceof FileMakerError && e.code === "401")
305
+ if (ignoreEmptyResult && e instanceof FileMakerError && e.code === "401") {
326
306
  return { data: [], dataInfo: { foundCount: 0, returnedCount: 0 } };
307
+ }
327
308
  throw e;
328
309
  })) as GetResponse<InferredFieldData, InferredPortalData>;
329
310
 
330
- if (result.dataInfo.foundCount > result.dataInfo.returnedCount) {
331
- // more records found than returned
332
- if (args?.limit === undefined && args?.offset === undefined) {
333
- console.warn(
334
- `🚨 @proofkit/fmdapi: Loaded only ${result.dataInfo.returnedCount} of the ${result.dataInfo.foundCount} records from your "${layout}" layout. Use the "findAll" method to automatically paginate through all records, or specify a "limit" and "offset" to handle pagination yourself.`,
335
- );
336
- }
311
+ if (
312
+ result.dataInfo.foundCount > result.dataInfo.returnedCount &&
313
+ args?.limit === undefined &&
314
+ args?.offset === undefined
315
+ ) {
316
+ // more records found than returned and the user didn't specify a limit or offset
317
+ console.warn(
318
+ `🚨 @proofkit/fmdapi: Loaded only ${result.dataInfo.returnedCount} of the ${result.dataInfo.foundCount} records from your "${layout}" layout. Use the "findAll" method to automatically paginate through all records, or specify a "limit" and "offset" to handle pagination yourself.`,
319
+ );
337
320
  }
338
321
 
339
322
  return await runSchemaValidationAndTransform(schema, result);
@@ -346,15 +329,13 @@ function DataApi<
346
329
  args: FindArgs<InferredFieldData, InferredPortalData> & FetchOptions,
347
330
  ): Promise<GetResponseOne<InferredFieldData, InferredPortalData>> {
348
331
  const result = await _find(args);
349
- if (result.data.length !== 1)
350
- throw new Error(
351
- `${result.data.length} records found; expecting exactly 1`,
352
- );
353
- const transformedResult = await runSchemaValidationAndTransform(
354
- schema,
355
- result,
356
- );
357
- if (!transformedResult.data[0]) throw new Error("No data found");
332
+ if (result.data.length !== 1) {
333
+ throw new Error(`${result.data.length} records found; expecting exactly 1`);
334
+ }
335
+ const transformedResult = await runSchemaValidationAndTransform(schema, result);
336
+ if (!transformedResult.data[0]) {
337
+ throw new Error("No data found");
338
+ }
358
339
  return { ...transformedResult, data: transformedResult.data[0] };
359
340
  }
360
341
 
@@ -362,17 +343,14 @@ function DataApi<
362
343
  * Helper method for `find`. Will only return the first result instead of an array.
363
344
  */
364
345
  async function findFirst(
365
- args: FindArgs<InferredFieldData, InferredPortalData> &
366
- IgnoreEmptyResult &
367
- FetchOptions,
346
+ args: FindArgs<InferredFieldData, InferredPortalData> & IgnoreEmptyResult & FetchOptions,
368
347
  ): Promise<GetResponseOne<InferredFieldData, InferredPortalData>> {
369
348
  const result = await _find(args);
370
- const transformedResult = await runSchemaValidationAndTransform(
371
- schema,
372
- result,
373
- );
349
+ const transformedResult = await runSchemaValidationAndTransform(schema, result);
374
350
 
375
- if (!transformedResult.data[0]) throw new Error("No data found");
351
+ if (!transformedResult.data[0]) {
352
+ throw new Error("No data found");
353
+ }
376
354
  return { ...transformedResult, data: transformedResult.data[0] };
377
355
  }
378
356
 
@@ -380,16 +358,13 @@ function DataApi<
380
358
  * Helper method for `find`. Will return the first result or null if no results are found.
381
359
  */
382
360
  async function maybeFindFirst(
383
- args: FindArgs<InferredFieldData, InferredPortalData> &
384
- IgnoreEmptyResult &
385
- FetchOptions,
361
+ args: FindArgs<InferredFieldData, InferredPortalData> & IgnoreEmptyResult & FetchOptions,
386
362
  ): Promise<GetResponseOne<InferredFieldData, InferredPortalData> | null> {
387
363
  const result = await _find({ ...args, ignoreEmptyResult: true });
388
- const transformedResult = await runSchemaValidationAndTransform(
389
- schema,
390
- result,
391
- );
392
- if (!transformedResult.data[0]) return null;
364
+ const transformedResult = await runSchemaValidationAndTransform(schema, result);
365
+ if (!transformedResult.data[0]) {
366
+ return null;
367
+ }
393
368
  return { ...transformedResult, data: transformedResult.data[0] };
394
369
  }
395
370
 
@@ -400,13 +375,10 @@ function DataApi<
400
375
  async function findAll(
401
376
  args: FindArgs<InferredFieldData, InferredPortalData> & FetchOptions,
402
377
  ): Promise<FMRecord<InferredFieldData, InferredPortalData>[]> {
403
- let runningData: GetResponse<
404
- InferredFieldData,
405
- InferredPortalData
406
- >["data"] = [];
378
+ let runningData: GetResponse<InferredFieldData, InferredPortalData>["data"] = [];
407
379
  const limit = args.limit ?? 100;
408
380
  let offset = args.offset ?? 1;
409
- // eslint-disable-next-line no-constant-condition
381
+
410
382
  while (true) {
411
383
  const data = await _find({
412
384
  ...args,
@@ -414,12 +386,10 @@ function DataApi<
414
386
  ignoreEmptyResult: true,
415
387
  });
416
388
  runningData = [...runningData, ...data.data];
417
- if (
418
- runningData.length === 0 ||
419
- runningData.length >= data.dataInfo.foundCount
420
- )
389
+ if (runningData.length === 0 || runningData.length >= data.dataInfo.foundCount) {
421
390
  break;
422
- offset = offset + limit;
391
+ }
392
+ offset += limit;
423
393
  }
424
394
  return runningData;
425
395
  }
@@ -436,9 +406,7 @@ function DataApi<
436
406
  });
437
407
  }
438
408
 
439
- async function _containerUpload<
440
- T extends InferredFieldData = InferredFieldData,
441
- >(args: ContainerUploadArgs<T> & FetchOptions) {
409
+ async function _containerUpload(args: ContainerUploadArgs<InferredFieldData> & FetchOptions) {
442
410
  const { ...params } = args;
443
411
  return await containerUpload({
444
412
  layout,
@@ -459,14 +427,15 @@ function DataApi<
459
427
  const fieldDataIssues: StandardSchemaV1.Issue[] = [];
460
428
  const portalDataIssues: StandardSchemaV1.Issue[] = [];
461
429
 
462
- if (!schema) return result;
463
- const transformedData: FMRecord<InferredFieldData, InferredPortalData>[] =
464
- [];
430
+ if (!schema) {
431
+ return result;
432
+ }
433
+ const transformedData: FMRecord<InferredFieldData, InferredPortalData>[] = [];
465
434
  for (const record of result.data) {
466
- let fieldResult = schema.fieldData["~standard"].validate(
467
- record.fieldData,
468
- );
469
- if (fieldResult instanceof Promise) fieldResult = await fieldResult;
435
+ let fieldResult = schema.fieldData["~standard"].validate(record.fieldData);
436
+ if (fieldResult instanceof Promise) {
437
+ fieldResult = await fieldResult;
438
+ }
470
439
  if ("value" in fieldResult) {
471
440
  record.fieldData = fieldResult.value as InferredFieldData;
472
441
  } else {
@@ -474,18 +443,13 @@ function DataApi<
474
443
  }
475
444
 
476
445
  if (schema.portalData) {
477
- for (const [portalName, portalRecords] of Object.entries(
478
- record.portalData,
479
- )) {
480
- const validatedPortalRecords: PortalsWithIds<GenericPortalData>[] =
481
- [];
446
+ for (const [portalName, portalRecords] of Object.entries(record.portalData)) {
447
+ const validatedPortalRecords: PortalsWithIds<GenericPortalData>[] = [];
482
448
  for (const portalRecord of portalRecords) {
483
- let portalResult =
484
- schema.portalData[portalName]?.["~standard"].validate(
485
- portalRecord,
486
- );
487
- if (portalResult instanceof Promise)
449
+ let portalResult = schema.portalData[portalName]?.["~standard"].validate(portalRecord);
450
+ if (portalResult instanceof Promise) {
488
451
  portalResult = await portalResult;
452
+ }
489
453
  if (portalResult && "value" in portalResult) {
490
454
  validatedPortalRecords.push({
491
455
  ...portalResult.value,
package/src/index.ts CHANGED
@@ -1,11 +1,7 @@
1
- import { FileMakerError } from "./client-types.js";
2
- import { DataApi } from "./client.js";
3
-
4
- export { DataApi, FileMakerError };
5
- export * from "./utils.js";
6
- export * as clientTypes from "./client-types.js";
7
-
8
1
  export { FetchAdapter } from "./adapters/fetch.js";
2
+ export { FmHttpAdapter, type FmHttpAdapterOptions } from "./adapters/fm-http.js";
9
3
  export { OttoAdapter, type OttoAPIKey } from "./adapters/otto.js";
10
-
11
- export default DataApi;
4
+ export { DataApi, DataApi as default } from "./client.js";
5
+ export * as clientTypes from "./client-types.js";
6
+ export { FileMakerError } from "./client-types.js";
7
+ export * from "./utils.js";
@@ -1,5 +1,5 @@
1
- import type { TokenStoreDefinitions } from "./types.js";
2
1
  import fs from "fs-extra";
2
+ import type { TokenStoreDefinitions } from "./types.js";
3
3
 
4
4
  function getDataFromFile(devFileName: string): Record<string, string> {
5
5
  const data: Record<string, string> = {};
@@ -21,9 +21,7 @@ const getSharedData = (key: string, devFileName: string): string | null => {
21
21
  const data = getDataFromFile(devFileName);
22
22
  return data[key] ?? null;
23
23
  };
24
- export const fileTokenStore = (
25
- fileName = "shared.json",
26
- ): TokenStoreDefinitions => {
24
+ export const fileTokenStore = (fileName = "shared.json"): TokenStoreDefinitions => {
27
25
  return {
28
26
  setToken: (key, value) => setSharedData(key, value, fileName),
29
27
  getToken: (key) => getSharedData(key, fileName),
@@ -1,3 +1,3 @@
1
- export { default as upstashTokenStore } from "./upstash.js";
2
1
  export { default as fileStore } from "./file.js";
3
2
  export { default as memoryStore } from "./memory.js";
3
+ export { default as upstashTokenStore } from "./upstash.js";
@@ -1,7 +1,7 @@
1
1
  type MaybePromise<T> = Promise<T> | T;
2
- export type TokenStoreDefinitions = {
2
+ export interface TokenStoreDefinitions {
3
3
  getKey?: () => string;
4
4
  getToken: (key: string) => MaybePromise<string | null>;
5
5
  setToken: (key: string, value: string) => void;
6
6
  clearToken: (key: string) => void;
7
- };
7
+ }
@@ -1,10 +1,7 @@
1
- import type { TokenStoreDefinitions } from "./types.js";
2
1
  import type { RedisConfigNodejs } from "@upstash/redis";
2
+ import type { TokenStoreDefinitions } from "./types.js";
3
3
 
4
- export function upstashTokenStore(
5
- config: RedisConfigNodejs,
6
- options: { prefix?: string } = {},
7
- ): TokenStoreDefinitions {
4
+ export function upstashTokenStore(config: RedisConfigNodejs, options: { prefix?: string } = {}): TokenStoreDefinitions {
8
5
  const { prefix = "" } = options;
9
6
 
10
7
  const getRedis = async () => {
package/src/utils.ts CHANGED
@@ -1,39 +1,32 @@
1
- import type * as z3 from "zod/v3";
2
- import type * as z4 from "zod/v4/core";
3
-
4
- type StripFMTableName<K extends PropertyKey> = K extends `${string}::${infer R}`
5
- ? R
6
- : K;
1
+ type StripFMTableName<K extends PropertyKey> = K extends `${string}::${infer R}` ? R : K;
7
2
 
8
3
  type TransformedFields<T extends object> = {
9
4
  [K in keyof T as K extends string ? StripFMTableName<K> : K]: T[K];
10
5
  };
11
6
 
12
- export function removeFMTableNames<T extends object>(
13
- obj: T,
14
- ): TransformedFields<T> {
7
+ export function removeFMTableNames<T extends object>(obj: T): TransformedFields<T> {
15
8
  const newObj = {} as TransformedFields<T>;
16
9
  for (const key in obj) {
17
- const originalKey = key as keyof T;
18
- const value = obj[originalKey];
19
- const mappedKey = (
20
- typeof key === "string" && key.includes("::") ? key.split("::")[1] : key
21
- ) as keyof TransformedFields<T>;
10
+ if (Object.hasOwn(obj, key)) {
11
+ const originalKey = key as keyof T;
12
+ const value = obj[originalKey];
13
+ const mappedKey = (
14
+ typeof key === "string" && key.includes("::") ? key.split("::")[1] : key
15
+ ) as keyof TransformedFields<T>;
22
16
 
23
- // Use a temporary index signature cast to assign without any
24
- (newObj as unknown as Record<PropertyKey, unknown>)[
25
- mappedKey as unknown as PropertyKey
26
- ] = value as unknown;
17
+ // Use a temporary index signature cast to assign without any
18
+ (newObj as unknown as Record<PropertyKey, unknown>)[mappedKey as unknown as PropertyKey] = value as unknown;
19
+ }
27
20
  }
28
21
  return newObj;
29
22
  }
30
23
 
31
- export type InferZodPortals<T extends Record<string, any>> = {
32
- [K in keyof T]: T[K] extends { _def: any; parse: (...args: any[]) => any }
24
+ export type InferZodPortals<T extends Record<string, unknown>> = {
25
+ [K in keyof T]: T[K] extends { _def: unknown; parse: (...args: unknown[]) => unknown }
33
26
  ? ReturnType<T[K]["parse"]>
34
- : T[K] extends { _def: any; safeParse: (...args: any[]) => any }
35
- ? T[K] extends { parse: (...args: any[]) => any }
27
+ : T[K] extends { _def: unknown; safeParse: (...args: unknown[]) => unknown }
28
+ ? T[K] extends { parse: (...args: unknown[]) => unknown }
36
29
  ? ReturnType<T[K]["parse"]>
37
- : any
30
+ : unknown
38
31
  : never;
39
32
  };