@proofkit/fmodata 0.1.0-alpha.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 (54) hide show
  1. package/README.md +37 -0
  2. package/dist/esm/client/base-table.d.ts +13 -0
  3. package/dist/esm/client/base-table.js +19 -0
  4. package/dist/esm/client/base-table.js.map +1 -0
  5. package/dist/esm/client/database.d.ts +49 -0
  6. package/dist/esm/client/database.js +90 -0
  7. package/dist/esm/client/database.js.map +1 -0
  8. package/dist/esm/client/delete-builder.d.ts +61 -0
  9. package/dist/esm/client/delete-builder.js +121 -0
  10. package/dist/esm/client/delete-builder.js.map +1 -0
  11. package/dist/esm/client/entity-set.d.ts +43 -0
  12. package/dist/esm/client/entity-set.js +120 -0
  13. package/dist/esm/client/entity-set.js.map +1 -0
  14. package/dist/esm/client/filemaker-odata.d.ts +26 -0
  15. package/dist/esm/client/filemaker-odata.js +85 -0
  16. package/dist/esm/client/filemaker-odata.js.map +1 -0
  17. package/dist/esm/client/insert-builder.d.ts +23 -0
  18. package/dist/esm/client/insert-builder.js +69 -0
  19. package/dist/esm/client/insert-builder.js.map +1 -0
  20. package/dist/esm/client/query-builder.d.ts +94 -0
  21. package/dist/esm/client/query-builder.js +649 -0
  22. package/dist/esm/client/query-builder.js.map +1 -0
  23. package/dist/esm/client/record-builder.d.ts +43 -0
  24. package/dist/esm/client/record-builder.js +121 -0
  25. package/dist/esm/client/record-builder.js.map +1 -0
  26. package/dist/esm/client/table-occurrence.d.ts +25 -0
  27. package/dist/esm/client/table-occurrence.js +47 -0
  28. package/dist/esm/client/table-occurrence.js.map +1 -0
  29. package/dist/esm/client/update-builder.d.ts +69 -0
  30. package/dist/esm/client/update-builder.js +134 -0
  31. package/dist/esm/client/update-builder.js.map +1 -0
  32. package/dist/esm/filter-types.d.ts +76 -0
  33. package/dist/esm/index.d.ts +4 -0
  34. package/dist/esm/index.js +10 -0
  35. package/dist/esm/index.js.map +1 -0
  36. package/dist/esm/types.d.ts +67 -0
  37. package/dist/esm/validation.d.ts +41 -0
  38. package/dist/esm/validation.js +270 -0
  39. package/dist/esm/validation.js.map +1 -0
  40. package/package.json +68 -0
  41. package/src/client/base-table.ts +25 -0
  42. package/src/client/database.ts +177 -0
  43. package/src/client/delete-builder.ts +193 -0
  44. package/src/client/entity-set.ts +310 -0
  45. package/src/client/filemaker-odata.ts +119 -0
  46. package/src/client/insert-builder.ts +93 -0
  47. package/src/client/query-builder.ts +1076 -0
  48. package/src/client/record-builder.ts +240 -0
  49. package/src/client/table-occurrence.ts +100 -0
  50. package/src/client/update-builder.ts +212 -0
  51. package/src/filter-types.ts +97 -0
  52. package/src/index.ts +17 -0
  53. package/src/types.ts +123 -0
  54. package/src/validation.ts +397 -0
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # @proofkit/fmodata
2
+
3
+ FileMaker OData API client
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @proofkit/fmodata
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { createODataClient } from "@proofkit/fmodata";
15
+
16
+ // Usage example coming soon
17
+ ```
18
+
19
+ ## Development
20
+
21
+ ```bash
22
+ # Install dependencies
23
+ pnpm install
24
+
25
+ # Build the package
26
+ pnpm build
27
+
28
+ # Run tests
29
+ pnpm test
30
+
31
+ # Watch mode for development
32
+ pnpm dev
33
+ ```
34
+
35
+ ## License
36
+
37
+ MIT
@@ -0,0 +1,13 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+ export declare class BaseTable<Schema extends Record<string, StandardSchemaV1> = any, IdField extends keyof Schema | undefined = undefined, InsertRequired extends readonly (keyof Schema)[] = readonly [], UpdateRequired extends readonly (keyof Schema)[] = readonly []> {
3
+ readonly schema: Schema;
4
+ readonly idField?: IdField;
5
+ readonly insertRequired?: InsertRequired;
6
+ readonly updateRequired?: UpdateRequired;
7
+ constructor(config: {
8
+ schema: Schema;
9
+ idField?: IdField;
10
+ insertRequired?: InsertRequired;
11
+ updateRequired?: UpdateRequired;
12
+ });
13
+ }
@@ -0,0 +1,19 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ class BaseTable {
5
+ constructor(config) {
6
+ __publicField(this, "schema");
7
+ __publicField(this, "idField");
8
+ __publicField(this, "insertRequired");
9
+ __publicField(this, "updateRequired");
10
+ this.schema = config.schema;
11
+ this.idField = config.idField;
12
+ this.insertRequired = config.insertRequired;
13
+ this.updateRequired = config.updateRequired;
14
+ }
15
+ }
16
+ export {
17
+ BaseTable
18
+ };
19
+ //# sourceMappingURL=base-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-table.js","sources":["../../../src/client/base-table.ts"],"sourcesContent":["import { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport class BaseTable<\n Schema extends Record<string, StandardSchemaV1> = any,\n IdField extends keyof Schema | undefined = undefined,\n InsertRequired extends readonly (keyof Schema)[] = readonly [],\n UpdateRequired extends readonly (keyof Schema)[] = readonly [],\n> {\n public readonly schema: Schema;\n public readonly idField?: IdField;\n public readonly insertRequired?: InsertRequired;\n public readonly updateRequired?: UpdateRequired;\n\n constructor(config: {\n schema: Schema;\n idField?: IdField;\n insertRequired?: InsertRequired;\n updateRequired?: UpdateRequired;\n }) {\n this.schema = config.schema;\n this.idField = config.idField;\n this.insertRequired = config.insertRequired;\n this.updateRequired = config.updateRequired;\n }\n}\n"],"names":[],"mappings":";;;AAEO,MAAM,UAKX;AAAA,EAMA,YAAY,QAKT;AAVa;AACA;AACA;AACA;AAQd,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,iBAAiB,OAAO;AAC7B,SAAK,iBAAiB,OAAO;AAAA,EAAA;AAEjC;"}
@@ -0,0 +1,49 @@
1
+ import { z } from 'zod/v4';
2
+ import { StandardSchemaV1 } from '@standard-schema/spec';
3
+ import { ExecutionContext } from '../types.js';
4
+ import { BaseTable } from './base-table.js';
5
+ import { TableOccurrence } from './table-occurrence.js';
6
+ import { EntitySet } from './entity-set.js';
7
+ type ExtractSchemaFromOccurrence<O> = O extends TableOccurrence<infer BT, any, any, any> ? BT extends BaseTable<infer S, any> ? S : never : never;
8
+ type FindOccurrenceByName<Occurrences extends readonly TableOccurrence<any, any, any, any>[], Name extends string> = Occurrences extends readonly [
9
+ infer First,
10
+ ...infer Rest extends readonly TableOccurrence<any, any, any, any>[]
11
+ ] ? First extends TableOccurrence<any, any, any, any> ? First["name"] extends Name ? First : FindOccurrenceByName<Rest, Name> : never : never;
12
+ type ExtractOccurrenceNames<Occurrences extends readonly TableOccurrence<any, any, any, any>[]> = Occurrences extends readonly [] ? string : Occurrences[number]["name"];
13
+ export declare class Database<Occurrences extends readonly TableOccurrence<any, any, any, any>[] = readonly []> {
14
+ private readonly databaseName;
15
+ private readonly context;
16
+ private occurrenceMap;
17
+ constructor(databaseName: string, context: ExecutionContext, config?: {
18
+ occurrences?: Occurrences;
19
+ });
20
+ from<Name extends ExtractOccurrenceNames<Occurrences> | (string & {})>(name: Name): Occurrences extends readonly [] ? EntitySet<Record<string, z.ZodTypeAny>, undefined> : Name extends ExtractOccurrenceNames<Occurrences> ? EntitySet<ExtractSchemaFromOccurrence<FindOccurrenceByName<Occurrences, Name>>, FindOccurrenceByName<Occurrences, Name>> : EntitySet<Record<string, z.ZodTypeAny>, undefined>;
21
+ getMetadata(): Promise<unknown>;
22
+ /**
23
+ * Lists all available tables (entity sets) in this database.
24
+ * @returns Promise resolving to an array of table names
25
+ */
26
+ listTableNames(): Promise<string[]>;
27
+ /**
28
+ * Executes a FileMaker script.
29
+ * @param scriptName - The name of the script to execute (must be valid according to OData rules)
30
+ * @param options - Optional script parameter and result schema
31
+ * @returns Promise resolving to script execution result
32
+ */
33
+ runScript<ResultSchema extends StandardSchemaV1<string, any> = never>(scriptName: string, options?: {
34
+ scriptParam?: string | number | Record<string, any>;
35
+ resultSchema?: ResultSchema;
36
+ }): Promise<[
37
+ ResultSchema
38
+ ] extends [never] ? {
39
+ resultCode: number;
40
+ result?: string;
41
+ } : ResultSchema extends StandardSchemaV1<string, infer Output> ? {
42
+ resultCode: number;
43
+ result: Output;
44
+ } : {
45
+ resultCode: number;
46
+ result?: string;
47
+ }>;
48
+ }
49
+ export {};
@@ -0,0 +1,90 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { EntitySet } from "./entity-set.js";
5
+ class Database {
6
+ constructor(databaseName, context, config) {
7
+ __publicField(this, "occurrenceMap");
8
+ this.databaseName = databaseName;
9
+ this.context = context;
10
+ this.occurrenceMap = /* @__PURE__ */ new Map();
11
+ if (config == null ? void 0 : config.occurrences) {
12
+ for (const occ of config.occurrences) {
13
+ this.occurrenceMap.set(occ.name, occ);
14
+ }
15
+ }
16
+ }
17
+ from(name) {
18
+ const occurrence = this.occurrenceMap.get(name);
19
+ if (occurrence) {
20
+ return EntitySet.create({
21
+ occurrence,
22
+ tableName: name,
23
+ databaseName: this.databaseName,
24
+ context: this.context
25
+ });
26
+ } else {
27
+ return new EntitySet({
28
+ tableName: name,
29
+ databaseName: this.databaseName,
30
+ context: this.context
31
+ });
32
+ }
33
+ }
34
+ // Example method showing how to use the request method
35
+ async getMetadata() {
36
+ return this.context._makeRequest(`/${this.databaseName}/$metadata`);
37
+ }
38
+ /**
39
+ * Lists all available tables (entity sets) in this database.
40
+ * @returns Promise resolving to an array of table names
41
+ */
42
+ async listTableNames() {
43
+ const response = await this.context._makeRequest(
44
+ `/${this.databaseName}`
45
+ );
46
+ if (response.value && Array.isArray(response.value)) {
47
+ return response.value.map((item) => item.name);
48
+ }
49
+ return [];
50
+ }
51
+ /**
52
+ * Executes a FileMaker script.
53
+ * @param scriptName - The name of the script to execute (must be valid according to OData rules)
54
+ * @param options - Optional script parameter and result schema
55
+ * @returns Promise resolving to script execution result
56
+ */
57
+ async runScript(scriptName, options) {
58
+ const body = {};
59
+ if ((options == null ? void 0 : options.scriptParam) !== void 0) {
60
+ body.scriptParameterValue = options.scriptParam;
61
+ }
62
+ const response = await this.context._makeRequest(`/${this.databaseName}/Script.${scriptName}`, {
63
+ method: "POST",
64
+ body: Object.keys(body).length > 0 ? JSON.stringify(body) : void 0
65
+ });
66
+ if ((options == null ? void 0 : options.resultSchema) && response.scriptResult !== void 0) {
67
+ const validationResult = options.resultSchema["~standard"].validate(
68
+ response.scriptResult.resultParameter
69
+ );
70
+ const result = validationResult instanceof Promise ? await validationResult : validationResult;
71
+ if (result.issues) {
72
+ throw new Error(
73
+ `Script result validation failed: ${JSON.stringify(result.issues)}`
74
+ );
75
+ }
76
+ return {
77
+ resultCode: response.scriptResult.code,
78
+ result: result.value
79
+ };
80
+ }
81
+ return {
82
+ resultCode: response.scriptResult.code,
83
+ result: response.scriptResult.resultParameter
84
+ };
85
+ }
86
+ }
87
+ export {
88
+ Database
89
+ };
90
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sources":["../../../src/client/database.ts"],"sourcesContent":["import { z } from \"zod/v4\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ExecutionContext } from \"../types\";\nimport type { BaseTable } from \"./base-table\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport { EntitySet } from \"./entity-set\";\n\n// Helper type to extract schema from a TableOccurrence\ntype ExtractSchemaFromOccurrence<O> =\n O extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<infer S, any>\n ? S\n : never\n : never;\n\n// Helper type to find an occurrence by name in the occurrences tuple\ntype FindOccurrenceByName<\n Occurrences extends readonly TableOccurrence<any, any, any, any>[],\n Name extends string,\n> = Occurrences extends readonly [\n infer First,\n ...infer Rest extends readonly TableOccurrence<any, any, any, any>[],\n]\n ? First extends TableOccurrence<any, any, any, any>\n ? First[\"name\"] extends Name\n ? First\n : FindOccurrenceByName<Rest, Name>\n : never\n : never;\n\n// Helper type to extract all occurrence names from the tuple\ntype ExtractOccurrenceNames<\n Occurrences extends readonly TableOccurrence<any, any, any, any>[],\n> = Occurrences extends readonly []\n ? string // If no occurrences, allow any string\n : Occurrences[number][\"name\"]; // Otherwise, extract union of names\n\nexport class Database<\n Occurrences extends readonly TableOccurrence<\n any,\n any,\n any,\n any\n >[] = readonly [],\n> {\n private occurrenceMap: Map<string, TableOccurrence<any, any, any, any>>;\n\n constructor(\n private readonly databaseName: string,\n private readonly context: ExecutionContext,\n config?: { occurrences?: Occurrences },\n ) {\n this.occurrenceMap = new Map();\n if (config?.occurrences) {\n for (const occ of config.occurrences) {\n this.occurrenceMap.set(occ.name, occ);\n }\n }\n }\n\n from<Name extends ExtractOccurrenceNames<Occurrences> | (string & {})>(\n name: Name,\n ): Occurrences extends readonly []\n ? EntitySet<Record<string, z.ZodTypeAny>, undefined>\n : Name extends ExtractOccurrenceNames<Occurrences>\n ? EntitySet<\n ExtractSchemaFromOccurrence<FindOccurrenceByName<Occurrences, Name>>,\n FindOccurrenceByName<Occurrences, Name>\n >\n : EntitySet<Record<string, z.ZodTypeAny>, undefined> {\n const occurrence = this.occurrenceMap.get(name as string);\n\n if (occurrence) {\n // Use EntitySet.create to preserve types better\n type OccType = FindOccurrenceByName<Occurrences, Name>;\n type SchemaType = ExtractSchemaFromOccurrence<OccType>;\n\n return EntitySet.create<SchemaType, OccType>({\n occurrence: occurrence as any,\n tableName: name as string,\n databaseName: this.databaseName,\n context: this.context,\n }) as any;\n } else {\n // Return untyped EntitySet for dynamic table access\n return new EntitySet<Record<string, z.ZodTypeAny>, undefined>({\n tableName: name as string,\n databaseName: this.databaseName,\n context: this.context,\n }) as any;\n }\n }\n\n // Example method showing how to use the request method\n async getMetadata() {\n return this.context._makeRequest(`/${this.databaseName}/$metadata`);\n }\n\n /**\n * Lists all available tables (entity sets) in this database.\n * @returns Promise resolving to an array of table names\n */\n async listTableNames(): Promise<string[]> {\n const response = (await this.context._makeRequest(\n `/${this.databaseName}`,\n )) as {\n value?: Array<{ name: string }>;\n };\n if (response.value && Array.isArray(response.value)) {\n return response.value.map((item) => item.name);\n }\n return [];\n }\n\n /**\n * Executes a FileMaker script.\n * @param scriptName - The name of the script to execute (must be valid according to OData rules)\n * @param options - Optional script parameter and result schema\n * @returns Promise resolving to script execution result\n */\n async runScript<ResultSchema extends StandardSchemaV1<string, any> = never>(\n scriptName: string,\n options?: {\n scriptParam?: string | number | Record<string, any>;\n resultSchema?: ResultSchema;\n },\n ): Promise<\n [ResultSchema] extends [never]\n ? { resultCode: number; result?: string }\n : ResultSchema extends StandardSchemaV1<string, infer Output>\n ? { resultCode: number; result: Output }\n : { resultCode: number; result?: string }\n > {\n const body: { scriptParameterValue?: unknown } = {};\n if (options?.scriptParam !== undefined) {\n body.scriptParameterValue = options.scriptParam;\n }\n\n const response = await this.context._makeRequest<{\n scriptResult: {\n code: number;\n resultParameter?: string;\n };\n }>(`/${this.databaseName}/Script.${scriptName}`, {\n method: \"POST\",\n body: Object.keys(body).length > 0 ? JSON.stringify(body) : undefined,\n });\n\n // If resultSchema is provided, validate the result through it\n if (options?.resultSchema && response.scriptResult !== undefined) {\n const validationResult = options.resultSchema[\"~standard\"].validate(\n response.scriptResult.resultParameter,\n );\n // Handle both sync and async validation\n const result =\n validationResult instanceof Promise\n ? await validationResult\n : validationResult;\n\n if (result.issues) {\n throw new Error(\n `Script result validation failed: ${JSON.stringify(result.issues)}`,\n );\n }\n\n return {\n resultCode: response.scriptResult.code,\n result: result.value,\n } as any;\n }\n\n return {\n resultCode: response.scriptResult.code,\n result: response.scriptResult.resultParameter,\n } as any;\n }\n}\n"],"names":[],"mappings":";;;;AAqCO,MAAM,SAOX;AAAA,EAGA,YACmB,cACA,SACjB,QACA;AANM;AAGW,SAAA,eAAA;AACA,SAAA,UAAA;AAGZ,SAAA,oCAAoB,IAAI;AAC7B,QAAI,iCAAQ,aAAa;AACZ,iBAAA,OAAO,OAAO,aAAa;AACpC,aAAK,cAAc,IAAI,IAAI,MAAM,GAAG;AAAA,MAAA;AAAA,IACtC;AAAA,EACF;AAAA,EAGF,KACE,MAQuD;AACvD,UAAM,aAAa,KAAK,cAAc,IAAI,IAAc;AAExD,QAAI,YAAY;AAKd,aAAO,UAAU,OAA4B;AAAA,QAC3C;AAAA,QACA,WAAW;AAAA,QACX,cAAc,KAAK;AAAA,QACnB,SAAS,KAAK;AAAA,MAAA,CACf;AAAA,IAAA,OACI;AAEL,aAAO,IAAI,UAAmD;AAAA,QAC5D,WAAW;AAAA,QACX,cAAc,KAAK;AAAA,QACnB,SAAS,KAAK;AAAA,MAAA,CACf;AAAA,IAAA;AAAA,EACH;AAAA;AAAA,EAIF,MAAM,cAAc;AAClB,WAAO,KAAK,QAAQ,aAAa,IAAI,KAAK,YAAY,YAAY;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpE,MAAM,iBAAoC;AAClC,UAAA,WAAY,MAAM,KAAK,QAAQ;AAAA,MACnC,IAAI,KAAK,YAAY;AAAA,IACvB;AAGA,QAAI,SAAS,SAAS,MAAM,QAAQ,SAAS,KAAK,GAAG;AACnD,aAAO,SAAS,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,IAAA;AAE/C,WAAO,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,MAAM,UACJ,YACA,SAUA;AACA,UAAM,OAA2C,CAAC;AAC9C,SAAA,mCAAS,iBAAgB,QAAW;AACtC,WAAK,uBAAuB,QAAQ;AAAA,IAAA;AAGhC,UAAA,WAAW,MAAM,KAAK,QAAQ,aAKjC,IAAI,KAAK,YAAY,WAAW,UAAU,IAAI;AAAA,MAC/C,QAAQ;AAAA,MACR,MAAM,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,KAAK,UAAU,IAAI,IAAI;AAAA,IAAA,CAC7D;AAGD,SAAI,mCAAS,iBAAgB,SAAS,iBAAiB,QAAW;AAChE,YAAM,mBAAmB,QAAQ,aAAa,WAAW,EAAE;AAAA,QACzD,SAAS,aAAa;AAAA,MACxB;AAEA,YAAM,SACJ,4BAA4B,UACxB,MAAM,mBACN;AAEN,UAAI,OAAO,QAAQ;AACjB,cAAM,IAAI;AAAA,UACR,oCAAoC,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,QACnE;AAAA,MAAA;AAGK,aAAA;AAAA,QACL,YAAY,SAAS,aAAa;AAAA,QAClC,QAAQ,OAAO;AAAA,MACjB;AAAA,IAAA;AAGK,WAAA;AAAA,MACL,YAAY,SAAS,aAAa;AAAA,MAClC,QAAQ,SAAS,aAAa;AAAA,IAChC;AAAA,EAAA;AAEJ;"}
@@ -0,0 +1,61 @@
1
+ import { ExecutionContext, ExecutableBuilder, Result, WithSystemFields } from '../types.js';
2
+ import { TableOccurrence } from './table-occurrence.js';
3
+ import { QueryBuilder } from './query-builder.js';
4
+ import { FFetchOptions } from '@fetchkit/ffetch';
5
+ /**
6
+ * Initial delete builder returned from EntitySet.delete()
7
+ * Requires calling .byId() or .where() before .execute() is available
8
+ */
9
+ export declare class DeleteBuilder<T extends Record<string, any>> {
10
+ private tableName;
11
+ private databaseName;
12
+ private context;
13
+ private occurrence?;
14
+ constructor(config: {
15
+ occurrence?: TableOccurrence<any, any, any, any>;
16
+ tableName: string;
17
+ databaseName: string;
18
+ context: ExecutionContext;
19
+ });
20
+ /**
21
+ * Delete a single record by ID
22
+ */
23
+ byId(id: string | number): ExecutableDeleteBuilder<T>;
24
+ /**
25
+ * Delete records matching a filter query
26
+ * @param fn Callback that receives a QueryBuilder for building the filter
27
+ */
28
+ where(fn: (q: QueryBuilder<WithSystemFields<T>>) => QueryBuilder<WithSystemFields<T>>): ExecutableDeleteBuilder<T>;
29
+ }
30
+ /**
31
+ * Executable delete builder - has execute() method
32
+ * Returned after calling .byId() or .where()
33
+ */
34
+ export declare class ExecutableDeleteBuilder<T extends Record<string, any>> implements ExecutableBuilder<{
35
+ deletedCount: number;
36
+ }> {
37
+ private tableName;
38
+ private databaseName;
39
+ private context;
40
+ private occurrence?;
41
+ private mode;
42
+ private recordId?;
43
+ private queryBuilder?;
44
+ constructor(config: {
45
+ occurrence?: TableOccurrence<any, any, any, any>;
46
+ tableName: string;
47
+ databaseName: string;
48
+ context: ExecutionContext;
49
+ mode: "byId" | "byFilter";
50
+ recordId?: string | number;
51
+ queryBuilder?: QueryBuilder<any>;
52
+ });
53
+ execute(options?: RequestInit & FFetchOptions): Promise<Result<{
54
+ deletedCount: number;
55
+ }>>;
56
+ getRequestConfig(): {
57
+ method: string;
58
+ url: string;
59
+ body?: any;
60
+ };
61
+ }
@@ -0,0 +1,121 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { QueryBuilder } from "./query-builder.js";
5
+ class DeleteBuilder {
6
+ constructor(config) {
7
+ __publicField(this, "tableName");
8
+ __publicField(this, "databaseName");
9
+ __publicField(this, "context");
10
+ __publicField(this, "occurrence");
11
+ this.occurrence = config.occurrence;
12
+ this.tableName = config.tableName;
13
+ this.databaseName = config.databaseName;
14
+ this.context = config.context;
15
+ }
16
+ /**
17
+ * Delete a single record by ID
18
+ */
19
+ byId(id) {
20
+ return new ExecutableDeleteBuilder({
21
+ occurrence: this.occurrence,
22
+ tableName: this.tableName,
23
+ databaseName: this.databaseName,
24
+ context: this.context,
25
+ mode: "byId",
26
+ recordId: id
27
+ });
28
+ }
29
+ /**
30
+ * Delete records matching a filter query
31
+ * @param fn Callback that receives a QueryBuilder for building the filter
32
+ */
33
+ where(fn) {
34
+ const queryBuilder = new QueryBuilder({
35
+ occurrence: void 0,
36
+ tableName: this.tableName,
37
+ databaseName: this.databaseName,
38
+ context: this.context
39
+ });
40
+ const configuredBuilder = fn(queryBuilder);
41
+ return new ExecutableDeleteBuilder({
42
+ occurrence: this.occurrence,
43
+ tableName: this.tableName,
44
+ databaseName: this.databaseName,
45
+ context: this.context,
46
+ mode: "byFilter",
47
+ queryBuilder: configuredBuilder
48
+ });
49
+ }
50
+ }
51
+ class ExecutableDeleteBuilder {
52
+ constructor(config) {
53
+ __publicField(this, "tableName");
54
+ __publicField(this, "databaseName");
55
+ __publicField(this, "context");
56
+ __publicField(this, "occurrence");
57
+ __publicField(this, "mode");
58
+ __publicField(this, "recordId");
59
+ __publicField(this, "queryBuilder");
60
+ this.occurrence = config.occurrence;
61
+ this.tableName = config.tableName;
62
+ this.databaseName = config.databaseName;
63
+ this.context = config.context;
64
+ this.mode = config.mode;
65
+ this.recordId = config.recordId;
66
+ this.queryBuilder = config.queryBuilder;
67
+ }
68
+ async execute(options) {
69
+ try {
70
+ let url;
71
+ if (this.mode === "byId") {
72
+ url = `/${this.databaseName}/${this.tableName}('${this.recordId}')`;
73
+ } else {
74
+ if (!this.queryBuilder) {
75
+ throw new Error("Query builder is required for filter-based delete");
76
+ }
77
+ const queryString = this.queryBuilder.getQueryString();
78
+ const queryParams = queryString.startsWith(`/${this.tableName}`) ? queryString.slice(`/${this.tableName}`.length) : queryString;
79
+ url = `/${this.databaseName}/${this.tableName}${queryParams}`;
80
+ }
81
+ const response = await this.context._makeRequest(url, {
82
+ method: "DELETE",
83
+ ...options
84
+ });
85
+ let deletedCount = 0;
86
+ if (typeof response === "number") {
87
+ deletedCount = response;
88
+ } else if (response && typeof response === "object") {
89
+ deletedCount = response.deletedCount || 0;
90
+ }
91
+ return { data: { deletedCount }, error: void 0 };
92
+ } catch (error) {
93
+ return {
94
+ data: void 0,
95
+ error: error instanceof Error ? error : new Error(String(error))
96
+ };
97
+ }
98
+ }
99
+ getRequestConfig() {
100
+ let url;
101
+ if (this.mode === "byId") {
102
+ url = `/${this.databaseName}/${this.tableName}('${this.recordId}')`;
103
+ } else {
104
+ if (!this.queryBuilder) {
105
+ throw new Error("Query builder is required for filter-based delete");
106
+ }
107
+ const queryString = this.queryBuilder.getQueryString();
108
+ const queryParams = queryString.startsWith(`/${this.tableName}`) ? queryString.slice(`/${this.tableName}`.length) : queryString;
109
+ url = `/${this.databaseName}/${this.tableName}${queryParams}`;
110
+ }
111
+ return {
112
+ method: "DELETE",
113
+ url
114
+ };
115
+ }
116
+ }
117
+ export {
118
+ DeleteBuilder,
119
+ ExecutableDeleteBuilder
120
+ };
121
+ //# sourceMappingURL=delete-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-builder.js","sources":["../../../src/client/delete-builder.ts"],"sourcesContent":["import type {\n ExecutionContext,\n ExecutableBuilder,\n Result,\n WithSystemFields,\n} from \"../types\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport { QueryBuilder } from \"./query-builder\";\nimport { type FFetchOptions } from \"@fetchkit/ffetch\";\nimport buildQuery from \"odata-query\";\n\n/**\n * Initial delete builder returned from EntitySet.delete()\n * Requires calling .byId() or .where() before .execute() is available\n */\nexport class DeleteBuilder<T extends Record<string, any>> {\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private occurrence?: TableOccurrence<any, any, any, any>;\n\n constructor(config: {\n occurrence?: TableOccurrence<any, any, any, any>;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n }\n\n /**\n * Delete a single record by ID\n */\n byId(id: string | number): ExecutableDeleteBuilder<T> {\n return new ExecutableDeleteBuilder<T>({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n mode: \"byId\",\n recordId: id,\n });\n }\n\n /**\n * Delete records matching a filter query\n * @param fn Callback that receives a QueryBuilder for building the filter\n */\n where(\n fn: (\n q: QueryBuilder<WithSystemFields<T>>,\n ) => QueryBuilder<WithSystemFields<T>>,\n ): ExecutableDeleteBuilder<T> {\n // Create a QueryBuilder for the user to configure\n const queryBuilder = new QueryBuilder<\n WithSystemFields<T>,\n keyof WithSystemFields<T>,\n false,\n false,\n undefined\n >({\n occurrence: undefined,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n });\n\n // Let the user configure it\n const configuredBuilder = fn(queryBuilder);\n\n return new ExecutableDeleteBuilder<T>({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n mode: \"byFilter\",\n queryBuilder: configuredBuilder,\n });\n }\n}\n\n/**\n * Executable delete builder - has execute() method\n * Returned after calling .byId() or .where()\n */\nexport class ExecutableDeleteBuilder<T extends Record<string, any>>\n implements ExecutableBuilder<{ deletedCount: number }>\n{\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private occurrence?: TableOccurrence<any, any, any, any>;\n private mode: \"byId\" | \"byFilter\";\n private recordId?: string | number;\n private queryBuilder?: QueryBuilder<any>;\n\n constructor(config: {\n occurrence?: TableOccurrence<any, any, any, any>;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n mode: \"byId\" | \"byFilter\";\n recordId?: string | number;\n queryBuilder?: QueryBuilder<any>;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n this.mode = config.mode;\n this.recordId = config.recordId;\n this.queryBuilder = config.queryBuilder;\n }\n\n async execute(\n options?: RequestInit & FFetchOptions,\n ): Promise<Result<{ deletedCount: number }>> {\n try {\n let url: string;\n\n if (this.mode === \"byId\") {\n // Delete single record by ID: DELETE /{database}/{table}('id')\n url = `/${this.databaseName}/${this.tableName}('${this.recordId}')`;\n } else {\n // Delete by filter: DELETE /{database}/{table}?$filter=...\n if (!this.queryBuilder) {\n throw new Error(\"Query builder is required for filter-based delete\");\n }\n\n // Get the query string from the configured QueryBuilder\n const queryString = this.queryBuilder.getQueryString();\n // Remove the leading \"/\" from the query string as we'll build our own URL\n const queryParams = queryString.startsWith(`/${this.tableName}`)\n ? queryString.slice(`/${this.tableName}`.length)\n : queryString;\n\n url = `/${this.databaseName}/${this.tableName}${queryParams}`;\n }\n\n // Make DELETE request\n const response = await this.context._makeRequest(url, {\n method: \"DELETE\",\n ...options,\n });\n\n // OData returns 204 No Content with fmodata.affected_rows header\n // The _makeRequest should handle extracting the header value\n // For now, we'll check if response contains the count\n let deletedCount = 0;\n\n if (typeof response === \"number\") {\n deletedCount = response;\n } else if (response && typeof response === \"object\") {\n // Check if the response has a count property (fallback)\n deletedCount = (response as any).deletedCount || 0;\n }\n\n return { data: { deletedCount }, error: undefined };\n } catch (error) {\n return {\n data: undefined,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n }\n\n getRequestConfig(): { method: string; url: string; body?: any } {\n let url: string;\n\n if (this.mode === \"byId\") {\n url = `/${this.databaseName}/${this.tableName}('${this.recordId}')`;\n } else {\n if (!this.queryBuilder) {\n throw new Error(\"Query builder is required for filter-based delete\");\n }\n\n const queryString = this.queryBuilder.getQueryString();\n const queryParams = queryString.startsWith(`/${this.tableName}`)\n ? queryString.slice(`/${this.tableName}`.length)\n : queryString;\n\n url = `/${this.databaseName}/${this.tableName}${queryParams}`;\n }\n\n return {\n method: \"DELETE\",\n url,\n };\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod/v4';
2
+ import { ExecutionContext, InferSchemaType, InsertData, UpdateData } from '../types.js';
3
+ import { BaseTable } from './base-table.js';
4
+ import { TableOccurrence } from './table-occurrence.js';
5
+ import { QueryBuilder } from './query-builder.js';
6
+ import { RecordBuilder } from './record-builder.js';
7
+ import { InsertBuilder } from './insert-builder.js';
8
+ import { DeleteBuilder } from './delete-builder.js';
9
+ import { UpdateBuilder } from './update-builder.js';
10
+ type ExtractNavigationNames<O extends TableOccurrence<any, any, any, any> | undefined> = O extends TableOccurrence<any, any, infer Nav, any> ? Nav extends Record<string, any> ? keyof Nav & string : never : never;
11
+ type ExtractSchemaFromOccurrence<O> = O extends TableOccurrence<infer BT, any, any, any> ? BT extends BaseTable<infer S, any> ? S : never : never;
12
+ type ExtractDefaultSelect<O> = O extends TableOccurrence<infer BT, any, any, infer DefSelect> ? BT extends BaseTable<infer S, any> ? DefSelect extends "all" ? keyof S : DefSelect extends "schema" ? keyof S : DefSelect extends readonly (infer K)[] ? K & keyof S : keyof S : never : never;
13
+ type ResolveNavigationItem<T> = T extends () => infer R ? R : T;
14
+ type FindNavigationTarget<O extends TableOccurrence<any, any, any, any> | undefined, Name extends string> = O extends TableOccurrence<any, any, infer Nav, any> ? Nav extends Record<string, any> ? Name extends keyof Nav ? ResolveNavigationItem<Nav[Name]> : TableOccurrence<BaseTable<Record<string, z.ZodTypeAny>, any>, any, any, any> : TableOccurrence<BaseTable<Record<string, z.ZodTypeAny>, any>, any, any, any> : TableOccurrence<BaseTable<Record<string, z.ZodTypeAny>, any>, any, any, any>;
15
+ export declare class EntitySet<Schema extends Record<string, z.ZodType> = any, Occ extends TableOccurrence<any, any, any, any> | undefined = undefined> {
16
+ private occurrence?;
17
+ private tableName;
18
+ private databaseName;
19
+ private context;
20
+ private isNavigateFromEntitySet?;
21
+ private navigateRelation?;
22
+ private navigateSourceTableName?;
23
+ constructor(config: {
24
+ occurrence?: Occ;
25
+ tableName: string;
26
+ databaseName: string;
27
+ context: ExecutionContext;
28
+ });
29
+ static create<OccurrenceSchema extends Record<string, z.ZodType>, Occ extends TableOccurrence<BaseTable<OccurrenceSchema, any>, any, any, any> | undefined = undefined>(config: {
30
+ occurrence?: Occ;
31
+ tableName: string;
32
+ databaseName: string;
33
+ context: ExecutionContext;
34
+ }): EntitySet<OccurrenceSchema, Occ>;
35
+ list(): QueryBuilder<InferSchemaType<Schema>, Occ extends TableOccurrence<any, any, any, any> ? ExtractDefaultSelect<Occ> : keyof InferSchemaType<Schema>, false, false, Occ>;
36
+ get(id: string | number): RecordBuilder<InferSchemaType<Schema>, false, keyof InferSchemaType<Schema>, Occ>;
37
+ insert(data: Occ extends TableOccurrence<infer BT, any, any, any> ? BT extends BaseTable<any, any, any, any> ? InsertData<BT> : Partial<InferSchemaType<Schema>> : Partial<InferSchemaType<Schema>>): InsertBuilder<InferSchemaType<Schema>, Occ>;
38
+ update(data: Occ extends TableOccurrence<infer BT, any, any, any> ? BT extends BaseTable<any, any, any, any> ? UpdateData<BT> : Partial<InferSchemaType<Schema>> : Partial<InferSchemaType<Schema>>): UpdateBuilder<InferSchemaType<Schema>, Occ extends TableOccurrence<infer BT, any, any, any> ? BT extends BaseTable<any, any, any, any> ? BT : BaseTable<Schema, any, any, any> : BaseTable<Schema, any, any, any>>;
39
+ delete(): DeleteBuilder<InferSchemaType<Schema>>;
40
+ navigate<RelationName extends ExtractNavigationNames<Occ>>(relationName: RelationName): EntitySet<ExtractSchemaFromOccurrence<FindNavigationTarget<Occ, RelationName>> extends Record<string, z.ZodType> ? ExtractSchemaFromOccurrence<FindNavigationTarget<Occ, RelationName>> : Record<string, z.ZodTypeAny>, FindNavigationTarget<Occ, RelationName>>;
41
+ navigate(relationName: string): EntitySet<Record<string, z.ZodTypeAny>, undefined>;
42
+ }
43
+ export {};
@@ -0,0 +1,120 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { QueryBuilder } from "./query-builder.js";
5
+ import { RecordBuilder } from "./record-builder.js";
6
+ import { InsertBuilder } from "./insert-builder.js";
7
+ import { DeleteBuilder } from "./delete-builder.js";
8
+ import { UpdateBuilder } from "./update-builder.js";
9
+ class EntitySet {
10
+ constructor(config) {
11
+ __publicField(this, "occurrence");
12
+ __publicField(this, "tableName");
13
+ __publicField(this, "databaseName");
14
+ __publicField(this, "context");
15
+ __publicField(this, "isNavigateFromEntitySet");
16
+ __publicField(this, "navigateRelation");
17
+ __publicField(this, "navigateSourceTableName");
18
+ this.occurrence = config.occurrence;
19
+ this.tableName = config.tableName;
20
+ this.databaseName = config.databaseName;
21
+ this.context = config.context;
22
+ }
23
+ // Type-only method to help TypeScript infer the schema from occurrence
24
+ static create(config) {
25
+ return new EntitySet({
26
+ occurrence: config.occurrence,
27
+ tableName: config.tableName,
28
+ databaseName: config.databaseName,
29
+ context: config.context
30
+ });
31
+ }
32
+ list() {
33
+ const builder = new QueryBuilder({
34
+ occurrence: this.occurrence,
35
+ tableName: this.tableName,
36
+ databaseName: this.databaseName,
37
+ context: this.context
38
+ });
39
+ if (this.occurrence) {
40
+ const defaultSelect = this.occurrence.defaultSelect;
41
+ if (defaultSelect === "schema") {
42
+ const schema = this.occurrence.baseTable.schema;
43
+ const fields = Object.keys(schema);
44
+ const uniqueFields = [...new Set(fields)];
45
+ return builder.select(...uniqueFields);
46
+ } else if (Array.isArray(defaultSelect)) {
47
+ const uniqueFields = [
48
+ ...new Set(defaultSelect)
49
+ ];
50
+ return builder.select(...uniqueFields);
51
+ }
52
+ }
53
+ if (this.isNavigateFromEntitySet) {
54
+ builder.isNavigate = true;
55
+ builder.navigateRelation = this.navigateRelation;
56
+ builder.navigateSourceTableName = this.navigateSourceTableName;
57
+ }
58
+ return builder;
59
+ }
60
+ get(id) {
61
+ const builder = new RecordBuilder({
62
+ occurrence: this.occurrence,
63
+ tableName: this.tableName,
64
+ databaseName: this.databaseName,
65
+ context: this.context,
66
+ recordId: id
67
+ });
68
+ if (this.isNavigateFromEntitySet) {
69
+ builder.isNavigateFromEntitySet = true;
70
+ builder.navigateRelation = this.navigateRelation;
71
+ builder.navigateSourceTableName = this.navigateSourceTableName;
72
+ }
73
+ return builder;
74
+ }
75
+ insert(data) {
76
+ return new InsertBuilder({
77
+ occurrence: this.occurrence,
78
+ tableName: this.tableName,
79
+ databaseName: this.databaseName,
80
+ context: this.context,
81
+ data
82
+ });
83
+ }
84
+ update(data) {
85
+ return new UpdateBuilder({
86
+ occurrence: this.occurrence,
87
+ tableName: this.tableName,
88
+ databaseName: this.databaseName,
89
+ context: this.context,
90
+ data
91
+ });
92
+ }
93
+ delete() {
94
+ return new DeleteBuilder({
95
+ occurrence: this.occurrence,
96
+ tableName: this.tableName,
97
+ databaseName: this.databaseName,
98
+ context: this.context
99
+ });
100
+ }
101
+ // Implementation
102
+ navigate(relationName) {
103
+ var _a;
104
+ const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[relationName];
105
+ const entitySet = new EntitySet({
106
+ occurrence: targetOccurrence,
107
+ tableName: (targetOccurrence == null ? void 0 : targetOccurrence.name) ?? relationName,
108
+ databaseName: this.databaseName,
109
+ context: this.context
110
+ });
111
+ entitySet.isNavigateFromEntitySet = true;
112
+ entitySet.navigateRelation = relationName;
113
+ entitySet.navigateSourceTableName = this.tableName;
114
+ return entitySet;
115
+ }
116
+ }
117
+ export {
118
+ EntitySet
119
+ };
120
+ //# sourceMappingURL=entity-set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-set.js","sources":["../../../src/client/entity-set.ts"],"sourcesContent":["import { z } from \"zod/v4\";\nimport type {\n ExecutionContext,\n InferSchemaType,\n WithSystemFields,\n InsertData,\n UpdateData,\n} from \"../types\";\nimport type { BaseTable } from \"./base-table\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport { QueryBuilder } from \"./query-builder\";\nimport { RecordBuilder } from \"./record-builder\";\nimport { InsertBuilder } from \"./insert-builder\";\nimport { DeleteBuilder } from \"./delete-builder\";\nimport { UpdateBuilder } from \"./update-builder\";\n\n// Helper type to extract navigation relation names from an occurrence\ntype ExtractNavigationNames<\n O extends TableOccurrence<any, any, any, any> | undefined,\n> =\n O extends TableOccurrence<any, any, infer Nav, any>\n ? Nav extends Record<string, any>\n ? keyof Nav & string\n : never\n : never;\n\n// Helper type to extract schema from a TableOccurrence\ntype ExtractSchemaFromOccurrence<O> =\n O extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<infer S, any>\n ? S\n : never\n : never;\n\n// Helper type to extract defaultSelect from a TableOccurrence\ntype ExtractDefaultSelect<O> =\n O extends TableOccurrence<infer BT, any, any, infer DefSelect>\n ? BT extends BaseTable<infer S, any>\n ? DefSelect extends \"all\"\n ? keyof S\n : DefSelect extends \"schema\"\n ? keyof S\n : DefSelect extends readonly (infer K)[]\n ? K & keyof S\n : keyof S\n : never\n : never;\n\n// Helper type to resolve a navigation item (handles both direct and lazy-loaded)\ntype ResolveNavigationItem<T> = T extends () => infer R ? R : T;\n\n// Helper type to find target occurrence by relation name\ntype FindNavigationTarget<\n O extends TableOccurrence<any, any, any, any> | undefined,\n Name extends string,\n> =\n O extends TableOccurrence<any, any, infer Nav, any>\n ? Nav extends Record<string, any>\n ? Name extends keyof Nav\n ? ResolveNavigationItem<Nav[Name]>\n : TableOccurrence<\n BaseTable<Record<string, z.ZodTypeAny>, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, z.ZodTypeAny>, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, z.ZodTypeAny>, any>,\n any,\n any,\n any\n >;\n\n// Helper type to get the inferred schema type from a target occurrence\ntype GetTargetSchemaType<\n O extends TableOccurrence<any, any, any, any> | undefined,\n Rel extends string,\n> = [FindNavigationTarget<O, Rel>] extends [\n TableOccurrence<infer BT, any, any, any>,\n]\n ? [BT] extends [BaseTable<infer S, any>]\n ? [S] extends [Record<string, z.ZodType>]\n ? InferSchemaType<S>\n : Record<string, any>\n : Record<string, any>\n : Record<string, any>;\n\nexport class EntitySet<\n Schema extends Record<string, z.ZodType> = any,\n Occ extends TableOccurrence<any, any, any, any> | undefined = undefined,\n> {\n private occurrence?: Occ;\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private isNavigateFromEntitySet?: boolean;\n private navigateRelation?: string;\n private navigateSourceTableName?: string;\n\n constructor(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n }\n\n // Type-only method to help TypeScript infer the schema from occurrence\n static create<\n OccurrenceSchema extends Record<string, z.ZodType>,\n Occ extends\n | TableOccurrence<BaseTable<OccurrenceSchema, any>, any, any, any>\n | undefined = undefined,\n >(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n }): EntitySet<OccurrenceSchema, Occ> {\n return new EntitySet<OccurrenceSchema, Occ>({\n occurrence: config.occurrence,\n tableName: config.tableName,\n databaseName: config.databaseName,\n context: config.context,\n });\n }\n\n list(): QueryBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<any, any, any, any>\n ? ExtractDefaultSelect<Occ>\n : keyof InferSchemaType<Schema>,\n false,\n false,\n Occ\n > {\n const builder = new QueryBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<any, any, any, any>\n ? ExtractDefaultSelect<Occ>\n : keyof InferSchemaType<Schema>,\n false,\n false,\n Occ\n >({\n occurrence: this.occurrence as Occ,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n });\n\n // Apply defaultSelect if occurrence exists and select hasn't been called\n if (this.occurrence) {\n const defaultSelect = this.occurrence.defaultSelect;\n\n if (defaultSelect === \"schema\") {\n // Extract field names from schema\n const schema = this.occurrence.baseTable.schema;\n const fields = Object.keys(schema) as (keyof InferSchemaType<Schema>)[];\n // Deduplicate fields (same as select method)\n const uniqueFields = [...new Set(fields)];\n return builder.select(...uniqueFields);\n } else if (Array.isArray(defaultSelect)) {\n // Use the provided field names, deduplicated\n const uniqueFields = [\n ...new Set(defaultSelect),\n ] as (keyof InferSchemaType<Schema>)[];\n return builder.select(...uniqueFields);\n }\n // If defaultSelect is \"all\", no changes needed (current behavior)\n }\n\n // Propagate navigation context if present\n if (this.isNavigateFromEntitySet) {\n (builder as any).isNavigate = true;\n (builder as any).navigateRelation = this.navigateRelation;\n (builder as any).navigateSourceTableName = this.navigateSourceTableName;\n // navigateRecordId is intentionally not set (undefined) to indicate navigation from EntitySet\n }\n return builder;\n }\n\n get(\n id: string | number,\n ): RecordBuilder<\n InferSchemaType<Schema>,\n false,\n keyof InferSchemaType<Schema>,\n Occ\n > {\n const builder = new RecordBuilder<\n InferSchemaType<Schema>,\n false,\n keyof InferSchemaType<Schema>,\n Occ\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n recordId: id,\n });\n // Propagate navigation context if present\n if (this.isNavigateFromEntitySet) {\n (builder as any).isNavigateFromEntitySet = true;\n (builder as any).navigateRelation = this.navigateRelation;\n (builder as any).navigateSourceTableName = this.navigateSourceTableName;\n }\n return builder;\n }\n\n insert(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? InsertData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n ): InsertBuilder<InferSchemaType<Schema>, Occ> {\n return new InsertBuilder<InferSchemaType<Schema>, Occ>({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n data: data as Partial<InferSchemaType<Schema>>,\n });\n }\n\n update(\n data: Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? UpdateData<BT>\n : Partial<InferSchemaType<Schema>>\n : Partial<InferSchemaType<Schema>>,\n ): UpdateBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? BT\n : BaseTable<Schema, any, any, any>\n : BaseTable<Schema, any, any, any>\n > {\n return new UpdateBuilder<\n InferSchemaType<Schema>,\n Occ extends TableOccurrence<infer BT, any, any, any>\n ? BT extends BaseTable<any, any, any, any>\n ? BT\n : BaseTable<Schema, any, any, any>\n : BaseTable<Schema, any, any, any>\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n data: data as Partial<InferSchemaType<Schema>>,\n });\n }\n\n delete(): DeleteBuilder<InferSchemaType<Schema>> {\n return new DeleteBuilder<InferSchemaType<Schema>>({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n });\n }\n\n // Overload for valid relation names - returns typed EntitySet\n navigate<RelationName extends ExtractNavigationNames<Occ>>(\n relationName: RelationName,\n ): EntitySet<\n ExtractSchemaFromOccurrence<\n FindNavigationTarget<Occ, RelationName>\n > extends Record<string, z.ZodType>\n ? ExtractSchemaFromOccurrence<FindNavigationTarget<Occ, RelationName>>\n : Record<string, z.ZodTypeAny>,\n FindNavigationTarget<Occ, RelationName>\n >;\n // Overload for arbitrary strings - returns generic EntitySet\n navigate(\n relationName: string,\n ): EntitySet<Record<string, z.ZodTypeAny>, undefined>;\n // Implementation\n navigate(relationName: string): EntitySet<any, any> {\n // Use the target occurrence if available, otherwise allow untyped navigation\n // (useful when types might be incomplete)\n const targetOccurrence = this.occurrence?.navigation[relationName];\n const entitySet = new EntitySet<any, any>({\n occurrence: targetOccurrence,\n tableName: targetOccurrence?.name ?? relationName,\n databaseName: this.databaseName,\n context: this.context,\n });\n // Store the navigation info in the EntitySet\n // We'll need to pass this through when creating QueryBuilders\n (entitySet as any).isNavigateFromEntitySet = true;\n (entitySet as any).navigateRelation = relationName;\n (entitySet as any).navigateSourceTableName = this.tableName;\n return entitySet;\n }\n}\n"],"names":[],"mappings":";;;;;;;;AA6FO,MAAM,UAGX;AAAA,EASA,YAAY,QAKT;AAbK;AACA;AACA;AACA;AACA;AACA;AACA;AAQN,SAAK,aAAa,OAAO;AACzB,SAAK,YAAY,OAAO;AACxB,SAAK,eAAe,OAAO;AAC3B,SAAK,UAAU,OAAO;AAAA,EAAA;AAAA;AAAA,EAIxB,OAAO,OAKL,QAKmC;AACnC,WAAO,IAAI,UAAiC;AAAA,MAC1C,YAAY,OAAO;AAAA,MACnB,WAAW,OAAO;AAAA,MAClB,cAAc,OAAO;AAAA,MACrB,SAAS,OAAO;AAAA,IAAA,CACjB;AAAA,EAAA;AAAA,EAGH,OAQE;AACM,UAAA,UAAU,IAAI,aAQlB;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,IAAA,CACf;AAGD,QAAI,KAAK,YAAY;AACb,YAAA,gBAAgB,KAAK,WAAW;AAEtC,UAAI,kBAAkB,UAAU;AAExB,cAAA,SAAS,KAAK,WAAW,UAAU;AACnC,cAAA,SAAS,OAAO,KAAK,MAAM;AAEjC,cAAM,eAAe,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AACjC,eAAA,QAAQ,OAAO,GAAG,YAAY;AAAA,MAC5B,WAAA,MAAM,QAAQ,aAAa,GAAG;AAEvC,cAAM,eAAe;AAAA,UACnB,GAAG,IAAI,IAAI,aAAa;AAAA,QAC1B;AACO,eAAA,QAAQ,OAAO,GAAG,YAAY;AAAA,MAAA;AAAA,IACvC;AAKF,QAAI,KAAK,yBAAyB;AAC/B,cAAgB,aAAa;AAC7B,cAAgB,mBAAmB,KAAK;AACxC,cAAgB,0BAA0B,KAAK;AAAA,IAAA;AAG3C,WAAA;AAAA,EAAA;AAAA,EAGT,IACE,IAMA;AACM,UAAA,UAAU,IAAI,cAKlB;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,UAAU;AAAA,IAAA,CACX;AAED,QAAI,KAAK,yBAAyB;AAC/B,cAAgB,0BAA0B;AAC1C,cAAgB,mBAAmB,KAAK;AACxC,cAAgB,0BAA0B,KAAK;AAAA,IAAA;AAE3C,WAAA;AAAA,EAAA;AAAA,EAGT,OACE,MAK6C;AAC7C,WAAO,IAAI,cAA4C;AAAA,MACrD,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd;AAAA,IAAA,CACD;AAAA,EAAA;AAAA,EAGH,OACE,MAYA;AACA,WAAO,IAAI,cAOT;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd;AAAA,IAAA,CACD;AAAA,EAAA;AAAA,EAGH,SAAiD;AAC/C,WAAO,IAAI,cAAuC;AAAA,MAChD,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,IAAA,CACf;AAAA,EAAA;AAAA;AAAA,EAmBH,SAAS,cAA2C;;AAGlD,UAAM,oBAAmB,UAAK,eAAL,mBAAiB,WAAW;AAC/C,UAAA,YAAY,IAAI,UAAoB;AAAA,MACxC,YAAY;AAAA,MACZ,YAAW,qDAAkB,SAAQ;AAAA,MACrC,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,IAAA,CACf;AAGA,cAAkB,0BAA0B;AAC5C,cAAkB,mBAAmB;AACrC,cAAkB,0BAA0B,KAAK;AAC3C,WAAA;AAAA,EAAA;AAEX;"}