@proofkit/fmodata 0.1.0-alpha.7 → 0.1.0-alpha.8

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.
@@ -19,7 +19,7 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
19
19
  // Helper type to extract schema from a TableOccurrence
20
20
  type ExtractSchemaFromOccurrence<O> =
21
21
  O extends TableOccurrence<infer BT, any, any, any>
22
- ? BT extends BaseTable<infer S, any>
22
+ ? BT extends BaseTable<infer S, any, any, any>
23
23
  ? S
24
24
  : never
25
25
  : never;
@@ -1,4 +1,4 @@
1
- import { BaseTable, BaseTableWithIds } from "./base-table";
1
+ import { BaseTable } from "./base-table";
2
2
 
3
3
  // Helper type to extract schema from BaseTable
4
4
  type ExtractSchema<BT> =
@@ -51,16 +51,19 @@ export class TableOccurrence<
51
51
  protected _navigationConfig: Nav;
52
52
  public readonly navigation: ResolveNavigation<Nav>;
53
53
  public readonly defaultSelect: DefSelect;
54
+ public readonly fmtId?: `FMTID:${string}`;
54
55
  constructor(config: {
55
56
  readonly name: Name;
56
57
  readonly baseTable: BT;
57
58
  readonly navigation?: Nav;
58
59
  readonly defaultSelect?: DefSelect;
60
+ readonly fmtId?: `FMTID:${string}`;
59
61
  }) {
60
62
  this.name = config.name;
61
63
  this.baseTable = config.baseTable;
62
64
  this._navigationConfig = (config.navigation ?? {}) as Nav;
63
65
  this.defaultSelect = (config.defaultSelect ?? "schema") as DefSelect;
66
+ this.fmtId = config.fmtId;
64
67
  // Create navigation getters that lazily resolve functions
65
68
  this.navigation = createNavigationGetters(this._navigationConfig);
66
69
  }
@@ -77,6 +80,7 @@ export class TableOccurrence<
77
80
  baseTable: this.baseTable,
78
81
  navigation: { ...this._navigationConfig, ...nav } as Nav & NewNav,
79
82
  defaultSelect: this.defaultSelect,
83
+ fmtId: this.fmtId,
80
84
  });
81
85
  }
82
86
 
@@ -85,10 +89,7 @@ export class TableOccurrence<
85
89
  * @returns The FMTID string or the table name
86
90
  */
87
91
  getTableId(): string {
88
- // Check if fmtId exists (only on TableOccurrenceWithIds)
89
- return "fmtId" in this && (this as any).fmtId
90
- ? (this as any).fmtId
91
- : this.name;
92
+ return this.fmtId ?? this.name;
92
93
  }
93
94
 
94
95
  /**
@@ -103,7 +104,7 @@ export class TableOccurrence<
103
104
  * Returns true if this TableOccurrence is using FileMaker table occurrence IDs.
104
105
  */
105
106
  isUsingTableId(): boolean {
106
- return "fmtId" in this && this.fmtId !== undefined;
107
+ return this.fmtId !== undefined;
107
108
  }
108
109
  }
109
110
 
@@ -119,96 +120,56 @@ export function createTableOccurrence<
119
120
  name: Name;
120
121
  baseTable: BT;
121
122
  defaultSelect?: DefSelect;
123
+ fmtId?: `FMTID:${string}`;
122
124
  }): TableOccurrence<BT, Name, {}, DefSelect> {
123
125
  return new TableOccurrence(config);
124
126
  }
125
127
 
126
- // Helper type to validate that all navigation values are TableOccurrenceWithIds
127
- type ValidateNavWithIds<Nav> =
128
- Nav extends Record<
129
- string,
130
- | TableOccurrenceWithIds<any, any, any, any>
131
- | (() => TableOccurrenceWithIds<any, any, any, any>)
132
- >
133
- ? Nav
134
- : "Error: All navigation table occurrences must be TableOccurrenceWithIds when using TableOccurrenceWithIds";
135
-
136
128
  /**
137
- * TableOccurrenceWithIds extends TableOccurrence to require:
138
- * 1. A BaseTableWithIds (which has fmfIds defined)
139
- * 2. A required fmtId for this table occurrence
140
- * 3. All navigation relationships must also be TableOccurrenceWithIds
141
- *
142
- * This ensures bidirectional type-level enforcement: if you use FileMaker IDs,
143
- * they must be defined on both the BaseTable (fmfIds) and TableOccurrence (fmtId),
144
- * and all related table occurrences in navigation must also have IDs.
129
+ * Creates a TableOccurrence with proper TypeScript type inference.
145
130
  *
146
- * @template BT - Must be a BaseTableWithIds (enforced at type level)
147
- * @template Name - The name of this table occurrence
148
- * @template Nav - Navigation relationships (must all be TableOccurrenceWithIds)
149
- * @template DefSelect - Default select behavior
131
+ * Use this function instead of `new TableOccurrence()` to ensure
132
+ * field names are properly typed.
150
133
  *
151
- * @example
134
+ * @example Without entity IDs
152
135
  * ```ts
153
- * const usersBaseWithIds = new BaseTableWithIds({
154
- * schema: { id: z.string(), name: z.string() },
155
- * idField: "id",
156
- * fmfIds: { id: "FMFID:1", name: "FMFID:2" },
136
+ * const users = defineTableOccurrence({
137
+ * name: "users",
138
+ * baseTable: usersBase,
157
139
  * });
140
+ * ```
158
141
  *
159
- * const usersTO = new TableOccurrenceWithIds({
160
- * name: "users",
161
- * baseTable: usersBaseWithIds,
162
- * fmtId: "FMTID:100",
163
- * navigation: {
164
- * contacts: () => contactsTO, // Must also be TableOccurrenceWithIds
165
- * },
142
+ * @example With entity IDs
143
+ * ```ts
144
+ * const products = defineTableOccurrence({
145
+ * name: "products",
146
+ * baseTable: productsBase,
147
+ * fmtId: "FMTID:12345",
166
148
  * });
167
149
  * ```
168
150
  */
169
- export class TableOccurrenceWithIds<
170
- BT extends BaseTableWithIds<any, any, any, any> = any,
171
- Name extends string = string,
172
- Nav extends Record<
173
- string,
174
- | TableOccurrence<any, any, any, any>
175
- | (() => TableOccurrence<any, any, any, any>)
176
- > = {},
177
- DefSelect extends
178
- | "all"
179
- | "schema"
180
- | readonly (keyof ExtractSchema<BT>)[] = "schema",
181
- > extends TableOccurrence<BT, Name, Nav, DefSelect> {
182
- public readonly fmtId: `FMTID:${string}`;
183
-
184
- constructor(config: {
185
- readonly name: Name;
186
- readonly baseTable: BT;
187
- readonly fmtId: `FMTID:${string}`;
188
- readonly navigation?: ValidateNavWithIds<Nav>;
189
- readonly defaultSelect?: DefSelect;
190
- }) {
191
- super({
192
- ...config,
193
- navigation: config.navigation as Nav,
194
- });
195
- this.fmtId = config.fmtId;
196
- }
197
- }
198
-
199
- // Helper function to create TableOccurrenceWithIds with proper type inference
200
- export function createTableOccurrenceWithIds<
151
+ export function defineTableOccurrence<
201
152
  const Name extends string,
202
- BT extends BaseTableWithIds<any, any, any, any>,
203
- DefSelect extends
153
+ BT extends BaseTable<any, any, any, any>,
154
+ const DefSelect extends
204
155
  | "all"
205
156
  | "schema"
206
157
  | readonly (keyof ExtractSchema<BT>)[] = "schema",
207
158
  >(config: {
208
- name: Name;
209
- baseTable: BT;
210
- fmtId: `FMTID:${string}`;
211
- defaultSelect?: DefSelect;
212
- }): TableOccurrenceWithIds<BT, Name, {}, DefSelect> {
213
- return new TableOccurrenceWithIds(config);
159
+ readonly name: Name;
160
+ readonly baseTable: BT;
161
+ readonly fmtId?: `FMTID:${string}`;
162
+ readonly defaultSelect?: DefSelect;
163
+ readonly navigation?: Record<
164
+ string,
165
+ | TableOccurrence<any, any, any, any>
166
+ | (() => TableOccurrence<any, any, any, any>)
167
+ >;
168
+ }): TableOccurrence<BT, Name, {}, DefSelect> {
169
+ return new TableOccurrence(config) as TableOccurrence<
170
+ BT,
171
+ Name,
172
+ {},
173
+ DefSelect
174
+ >;
214
175
  }
package/src/index.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  // Barrel file - exports all public API from the client folder
2
- export { BaseTable, BaseTableWithIds } from "./client/base-table";
2
+ export { BaseTable, defineBaseTable } from "./client/base-table";
3
3
  export {
4
4
  TableOccurrence,
5
5
  createTableOccurrence,
6
- TableOccurrenceWithIds,
7
- createTableOccurrenceWithIds,
6
+ defineTableOccurrence,
8
7
  } from "./client/table-occurrence";
9
8
  export { FMServerConnection } from "./client/filemaker-odata";
10
9