@proofkit/fmodata 0.1.0-alpha.15 → 0.1.0-alpha.16
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/README.md +4 -165
- package/dist/esm/client/builders/select-mixin.d.ts +2 -2
- package/dist/esm/client/builders/select-mixin.js.map +1 -1
- package/dist/esm/client/entity-set.d.ts +2 -12
- package/dist/esm/client/entity-set.js.map +1 -1
- package/dist/esm/client/error-parser.js.map +1 -1
- package/dist/esm/client/query/query-builder.d.ts +9 -16
- package/dist/esm/client/query/query-builder.js +7 -76
- package/dist/esm/client/query/query-builder.js.map +1 -1
- package/dist/esm/client/query/types.d.ts +5 -5
- package/dist/esm/client/record-builder.d.ts +5 -5
- package/dist/esm/client/record-builder.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/orm/column.d.ts +21 -4
- package/dist/esm/orm/column.js +5 -2
- package/dist/esm/orm/column.js.map +1 -1
- package/dist/esm/orm/field-builders.d.ts +1 -1
- package/dist/esm/orm/field-builders.js +1 -1
- package/dist/esm/orm/field-builders.js.map +1 -1
- package/dist/esm/orm/operators.d.ts +19 -19
- package/dist/esm/orm/operators.js +31 -12
- package/dist/esm/orm/operators.js.map +1 -1
- package/dist/esm/orm/table.d.ts +10 -9
- package/dist/esm/orm/table.js +5 -3
- package/dist/esm/orm/table.js.map +1 -1
- package/dist/esm/transform.js +1 -5
- package/dist/esm/transform.js.map +1 -1
- package/dist/esm/types.d.ts +9 -43
- package/dist/esm/types.js.map +1 -1
- package/package.json +1 -1
- package/src/client/builders/select-mixin.ts +2 -3
- package/src/client/entity-set.ts +25 -7
- package/src/client/error-parser.ts +3 -0
- package/src/client/query/query-builder.ts +14 -123
- package/src/client/query/types.ts +6 -5
- package/src/client/record-builder.ts +9 -6
- package/src/index.ts +3 -15
- package/src/orm/column.ts +33 -5
- package/src/orm/field-builders.ts +1 -1
- package/src/orm/operators.ts +105 -51
- package/src/orm/table.ts +21 -13
- package/src/types.ts +10 -51
- package/dist/esm/filter-types.d.ts +0 -76
- package/src/filter-types.ts +0 -97
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","sources":["../../src/transform.ts"],"sourcesContent":["import type { FMTable } from \"./orm/table\";\nimport {\n getBaseTableConfig,\n getFieldId,\n getFieldName,\n getTableId,\n getTableName,\n isUsingEntityIds,\n} from \"./orm/table\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Transforms field names to FileMaker field IDs (FMFID) in an object\n * @param data - Object with field names as keys\n * @param table - FMTable instance to get field IDs from\n * @returns Object with FMFID keys instead of field names\n */\nexport function transformFieldNamesToIds<T extends Record<string, any>>(\n data: T,\n table: FMTable<any, any>,\n): Record<string, any> {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return data;\n }\n\n const transformed: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(data)) {\n const fieldId = getFieldId(table, fieldName);\n transformed[fieldId] = value;\n }\n return transformed;\n}\n\n/**\n * Transforms FileMaker field IDs (FMFID) to field names in an object\n * @param data - Object with FMFID keys\n * @param table - FMTable instance to get field names from\n * @returns Object with field names as keys instead of FMFIDs\n */\nexport function transformFieldIdsToNames<T extends Record<string, any>>(\n data: T,\n table: FMTable<any, any>,\n): Record<string, any> {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return data;\n }\n\n const transformed: Record<string, any> = {};\n for (const [key, value] of Object.entries(data)) {\n // Check if this is an OData metadata field (starts with @)\n if (key.startsWith(\"@\")) {\n transformed[key] = value;\n continue;\n }\n\n const fieldName = getFieldName(table, key);\n transformed[fieldName] = value;\n }\n return transformed;\n}\n\n/**\n * Transforms a field name to FMFID or returns the field name if not using IDs\n * @param fieldName - The field name to transform\n * @param table - FMTable instance to get field ID from\n * @returns The FMFID or field name\n */\nexport function transformFieldName(\n fieldName: string,\n table: FMTable<any, any>,\n): string {\n return getFieldId(table, fieldName);\n}\n\n/**\n * Transforms a table name to FMTID or returns the name if not using IDs\n * @param table - FMTable instance to get table ID from\n * @returns The FMTID or table name\n */\nexport function transformTableName(table: FMTable<any, any>): string {\n return getTableId(table);\n}\n\n/**\n * Gets both table name and ID from a table\n * @param table - FMTable instance\n * @returns Object with name (always present) and id (may be undefined if not using IDs)\n */\nexport function getTableIdentifiers(\n table: FMTable<any, any>,\n): { name: string; id: string | undefined } {\n return {\n name: getTableName(table),\n id: isUsingEntityIds(table) ? getTableId(table) : undefined,\n };\n}\n\n/**\n * Transforms response data by converting field IDs back to field names recursively.\n * Handles both single records and arrays of records, as well as nested expand relationships.\n *\n * @param data - Response data from FileMaker (can be single record, array, or wrapped in value property)\n * @param table - FMTable instance for the main table\n * @param expandConfigs - Configuration for expanded relations (optional)\n * @returns Transformed data with field names instead of IDs\n */\nexport function transformResponseFields(\n data: any,\n table: FMTable<any, any>,\n expandConfigs?: Array<{\n relation: string;\n table?: FMTable<any, any>;\n }>,\n): any {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return data;\n }\n\n // Handle null/undefined\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle OData list response with value array\n if (data.value && Array.isArray(data.value)) {\n return {\n ...data,\n value: data.value.map((record: any) =>\n transformSingleRecord(record, table, expandConfigs),\n ),\n };\n }\n\n // Handle array of records\n if (Array.isArray(data)) {\n return data.map((record) =>\n transformSingleRecord(record, table, expandConfigs),\n );\n }\n\n // Handle single record\n return transformSingleRecord(data, table, expandConfigs);\n}\n\n/**\n * Transforms a single record, converting field IDs to names and handling nested expands\n */\nfunction transformSingleRecord(\n record: any,\n table: FMTable<any, any>,\n expandConfigs?: Array<{\n relation: string;\n table?: FMTable<any, any>;\n }>,\n): any {\n if (!record || typeof record !== \"object\") {\n return record;\n }\n\n const transformed: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(record)) {\n // Preserve OData metadata fields\n if (key.startsWith(\"@\")) {\n transformed[key] = value;\n continue;\n }\n\n // Check if this is an expanded relation (by relation name)\n let expandConfig = expandConfigs?.find((ec) => ec.relation === key);\n\n // If not found by relation name, check if this key is a FMTID\n // (FileMaker returns expanded relations with FMTID keys when using entity IDs)\n if (!expandConfig && key.startsWith(\"FMTID:\")) {\n expandConfig = expandConfigs?.find(\n (ec) =>\n ec.table && isUsingEntityIds(ec.table) && getTableId(ec.table) === key,\n );\n }\n\n if (expandConfig && expandConfig.table) {\n // Transform the expanded relation data recursively\n // Use the relation name (not the FMTID) as the key\n const relationKey = expandConfig.relation;\n\n if (Array.isArray(value)) {\n transformed[relationKey] = value.map((nestedRecord) =>\n transformSingleRecord(\n nestedRecord,\n expandConfig.table!,\n undefined, // Don't pass nested expand configs for now\n ),\n );\n } else if (value && typeof value === \"object\") {\n transformed[relationKey] = transformSingleRecord(\n value,\n expandConfig.table,\n undefined,\n );\n } else {\n transformed[relationKey] = value;\n }\n continue;\n }\n\n // Transform field ID to field name\n const fieldName = getFieldName(table, key);\n transformed[fieldName] = value;\n }\n\n return transformed;\n}\n\n/**\n * Transforms an array of field names to FMFIDs\n * @param fieldNames - Array of field names\n * @param table - FMTable instance to get field IDs from\n * @returns Array of FMFIDs or field names\n */\nexport function transformFieldNamesArray(\n fieldNames: string[],\n table: FMTable<any, any>,\n): string[] {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return fieldNames;\n }\n\n return fieldNames.map((fieldName) => getFieldId(table, fieldName));\n}\n\n/**\n * Transforms a field name in an orderBy string (e.g., \"name desc\" -> \"FMFID:1 desc\")\n * @param orderByString - The orderBy string (field name with optional asc/desc)\n * @param table - FMTable instance to get field ID from\n * @returns Transformed orderBy string with FMFID\n */\nexport function transformOrderByField(\n orderByString: string,\n table: FMTable<any, any> | undefined,\n): string {\n if (!table) {\n return orderByString;\n }\n const config = getBaseTableConfig(table);\n if (!config || !config.fmfIds) {\n return orderByString;\n }\n\n // Parse the orderBy string to extract field name and direction\n const parts = orderByString.trim().split(/\\s+/);\n const fieldName = parts[0];\n if (!fieldName) {\n return orderByString;\n }\n const direction = parts[1]; // \"asc\" or \"desc\" or undefined\n\n const fieldId = getFieldId(table, fieldName);\n return direction ? `${fieldId} ${direction}` : fieldId;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform.js","sources":["../../src/transform.ts"],"sourcesContent":["import type { FMTable } from \"./orm/table\";\nimport {\n getBaseTableConfig,\n getFieldId,\n getFieldName,\n getTableId,\n getTableName,\n isUsingEntityIds,\n} from \"./orm/table\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Transforms field names to FileMaker field IDs (FMFID) in an object\n * @param data - Object with field names as keys\n * @param table - FMTable instance to get field IDs from\n * @returns Object with FMFID keys instead of field names\n */\nexport function transformFieldNamesToIds<T extends Record<string, any>>(\n data: T,\n table: FMTable<any, any>,\n): Record<string, any> {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return data;\n }\n\n const transformed: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(data)) {\n const fieldId = getFieldId(table, fieldName);\n transformed[fieldId] = value;\n }\n return transformed;\n}\n\n/**\n * Transforms FileMaker field IDs (FMFID) to field names in an object\n * @param data - Object with FMFID keys\n * @param table - FMTable instance to get field names from\n * @returns Object with field names as keys instead of FMFIDs\n */\nexport function transformFieldIdsToNames<T extends Record<string, any>>(\n data: T,\n table: FMTable<any, any>,\n): Record<string, any> {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return data;\n }\n\n const transformed: Record<string, any> = {};\n for (const [key, value] of Object.entries(data)) {\n // Check if this is an OData metadata field (starts with @)\n if (key.startsWith(\"@\")) {\n transformed[key] = value;\n continue;\n }\n\n const fieldName = getFieldName(table, key);\n transformed[fieldName] = value;\n }\n return transformed;\n}\n\n/**\n * Transforms a field name to FMFID or returns the field name if not using IDs\n * @param fieldName - The field name to transform\n * @param table - FMTable instance to get field ID from\n * @returns The FMFID or field name\n */\nexport function transformFieldName(\n fieldName: string,\n table: FMTable<any, any>,\n): string {\n return getFieldId(table, fieldName);\n}\n\n/**\n * Transforms a table name to FMTID or returns the name if not using IDs\n * @param table - FMTable instance to get table ID from\n * @returns The FMTID or table name\n */\nexport function transformTableName(table: FMTable<any, any>): string {\n return getTableId(table);\n}\n\n/**\n * Gets both table name and ID from a table\n * @param table - FMTable instance\n * @returns Object with name (always present) and id (may be undefined if not using IDs)\n */\nexport function getTableIdentifiers(\n table: FMTable<any, any>,\n): { name: string; id: string | undefined } {\n return {\n name: getTableName(table),\n id: isUsingEntityIds(table) ? getTableId(table) : undefined,\n };\n}\n\n/**\n * Transforms response data by converting field IDs back to field names recursively.\n * Handles both single records and arrays of records, as well as nested expand relationships.\n *\n * @param data - Response data from FileMaker (can be single record, array, or wrapped in value property)\n * @param table - FMTable instance for the main table\n * @param expandConfigs - Configuration for expanded relations (optional)\n * @returns Transformed data with field names instead of IDs\n */\nexport function transformResponseFields(\n data: any,\n table: FMTable<any, any>,\n expandConfigs?: Array<{\n relation: string;\n table?: FMTable<any, any>;\n }>,\n): any {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return data;\n }\n\n // Handle null/undefined\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle OData list response with value array\n if (data.value && Array.isArray(data.value)) {\n return {\n ...data,\n value: data.value.map((record: any) =>\n transformSingleRecord(record, table, expandConfigs),\n ),\n };\n }\n\n // Handle array of records\n if (Array.isArray(data)) {\n return data.map((record) =>\n transformSingleRecord(record, table, expandConfigs),\n );\n }\n\n // Handle single record\n return transformSingleRecord(data, table, expandConfigs);\n}\n\n/**\n * Transforms a single record, converting field IDs to names and handling nested expands\n */\nfunction transformSingleRecord(\n record: any,\n table: FMTable<any, any>,\n expandConfigs?: Array<{\n relation: string;\n table?: FMTable<any, any>;\n }>,\n): any {\n if (!record || typeof record !== \"object\") {\n return record;\n }\n\n const transformed: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(record)) {\n // Preserve OData metadata fields\n if (key.startsWith(\"@\")) {\n transformed[key] = value;\n continue;\n }\n\n // Check if this is an expanded relation (by relation name)\n let expandConfig = expandConfigs?.find((ec) => ec.relation === key);\n\n // If not found by relation name, check if this key is a FMTID\n // (FileMaker returns expanded relations with FMTID keys when using entity IDs)\n if (!expandConfig && key.startsWith(\"FMTID:\")) {\n expandConfig = expandConfigs?.find(\n (ec) =>\n ec.table && isUsingEntityIds(ec.table) && getTableId(ec.table) === key,\n );\n }\n\n if (expandConfig && expandConfig.table) {\n // Transform the expanded relation data recursively\n // Use the relation name (not the FMTID) as the key\n const relationKey = expandConfig.relation;\n\n if (Array.isArray(value)) {\n transformed[relationKey] = value.map((nestedRecord) =>\n transformSingleRecord(\n nestedRecord,\n expandConfig.table!,\n undefined, // Don't pass nested expand configs for now\n ),\n );\n } else if (value && typeof value === \"object\") {\n transformed[relationKey] = transformSingleRecord(\n value,\n expandConfig.table,\n undefined,\n );\n } else {\n transformed[relationKey] = value;\n }\n continue;\n }\n\n // Transform field ID to field name\n const fieldName = getFieldName(table, key);\n transformed[fieldName] = value;\n }\n\n return transformed;\n}\n\n/**\n * Transforms an array of field names to FMFIDs\n * @param fieldNames - Array of field names\n * @param table - FMTable instance to get field IDs from\n * @returns Array of FMFIDs or field names\n */\nexport function transformFieldNamesArray(\n fieldNames: string[],\n table: FMTable<any, any>,\n): string[] {\n const config = getBaseTableConfig(table);\n if (!config.fmfIds) {\n return fieldNames;\n }\n\n return fieldNames.map((fieldName) => getFieldId(table, fieldName));\n}\n\n/**\n * Transforms a field name in an orderBy string (e.g., \"name desc\" -> \"FMFID:1 desc\")\n * @param orderByString - The orderBy string (field name with optional asc/desc)\n * @param table - FMTable instance to get field ID from\n * @returns Transformed orderBy string with FMFID\n */\nexport function transformOrderByField(\n orderByString: string,\n table: FMTable<any, any> | undefined,\n): string {\n if (!table) {\n return orderByString;\n }\n const config = getBaseTableConfig(table);\n if (!config || !config.fmfIds) {\n return orderByString;\n }\n\n // Parse the orderBy string to extract field name and direction\n const parts = orderByString.trim().split(/\\s+/);\n const fieldName = parts[0];\n if (!fieldName) {\n return orderByString;\n }\n const direction = parts[1]; // \"asc\" or \"desc\" or undefined\n\n const fieldId = getFieldId(table, fieldName);\n return direction ? `${fieldId} ${direction}` : fieldId;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -87,8 +87,6 @@ export type AutoRequiredKeys<Schema extends Record<string, StandardSchemaV1>> =
|
|
|
87
87
|
[K in keyof Schema]: Extract<StandardSchemaV1.InferOutput<Schema[K]>, null | undefined> extends never ? K : never;
|
|
88
88
|
}[keyof Schema];
|
|
89
89
|
export type ExcludedFields<IdField extends keyof any | undefined, ReadOnly extends readonly any[]> = IdField extends keyof any ? IdField | ReadOnly[number] : ReadOnly[number];
|
|
90
|
-
export type InsertData<BT> = Partial<Record<string, any>>;
|
|
91
|
-
export type UpdateData<BT> = Partial<Record<string, any>>;
|
|
92
90
|
export type ExecuteOptions = {
|
|
93
91
|
includeODataAnnotations?: boolean;
|
|
94
92
|
skipValidation?: boolean;
|
|
@@ -99,61 +97,30 @@ export type ExecuteOptions = {
|
|
|
99
97
|
};
|
|
100
98
|
/**
|
|
101
99
|
* Type for the fetchHandler callback function.
|
|
102
|
-
* This
|
|
103
|
-
*
|
|
104
|
-
* **Usage Note**: Due to TypeScript limitations with optional properties in intersection types,
|
|
105
|
-
* you may need to explicitly type fetchHandler parameters when using the built package:
|
|
100
|
+
* This is a convenience type export that matches the fetchHandler signature in FFetchOptions.
|
|
106
101
|
*
|
|
107
102
|
* @example
|
|
108
103
|
* ```typescript
|
|
109
104
|
* import type { FetchHandler } from '@proofkit/fmodata';
|
|
110
105
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* }) as FetchHandler
|
|
116
|
-
* });
|
|
106
|
+
* const myFetchHandler: FetchHandler = (input, init) => {
|
|
107
|
+
* console.log('Custom fetch:', input);
|
|
108
|
+
* return fetch(input, init);
|
|
109
|
+
* };
|
|
117
110
|
*
|
|
118
|
-
* // Or with explicit parameters:
|
|
119
111
|
* await query.execute({
|
|
120
|
-
* fetchHandler:
|
|
121
|
-
* return fetch(input, init);
|
|
122
|
-
* }
|
|
112
|
+
* fetchHandler: myFetchHandler
|
|
123
113
|
* });
|
|
124
114
|
* ```
|
|
125
115
|
*/
|
|
126
116
|
export type FetchHandler = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
127
|
-
/**
|
|
128
|
-
* Extended execute options that includes fetchHandler with proper typing.
|
|
129
|
-
* This ensures the fetchHandler parameter types are preserved in generated declaration files.
|
|
130
|
-
*/
|
|
131
|
-
export type ExecuteOptionsWithFetch = ExecuteOptions & {
|
|
132
|
-
fetchHandler?: FetchHandler;
|
|
133
|
-
};
|
|
134
|
-
/**
|
|
135
|
-
* Local re-export of key FFetchOptions properties to ensure type preservation.
|
|
136
|
-
* This avoids relying on external package type resolution in the built package.
|
|
137
|
-
*/
|
|
138
|
-
type LocalFFetchOptions = {
|
|
139
|
-
timeout?: number;
|
|
140
|
-
retries?: number;
|
|
141
|
-
throwOnHttpError?: boolean;
|
|
142
|
-
hooks?: any;
|
|
143
|
-
/**
|
|
144
|
-
* Custom fetch handler function.
|
|
145
|
-
* The parameter types are explicitly defined inline to ensure proper type inference.
|
|
146
|
-
*/
|
|
147
|
-
fetchHandler?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
148
|
-
dedupe?: boolean;
|
|
149
|
-
};
|
|
150
117
|
/**
|
|
151
118
|
* Combined type for execute() method options.
|
|
152
119
|
*
|
|
153
|
-
* Uses
|
|
154
|
-
*
|
|
120
|
+
* Uses FFetchOptions from @fetchkit/ffetch to ensure proper type inference.
|
|
121
|
+
* FFetchOptions is re-exported in the package to ensure type availability in consuming packages.
|
|
155
122
|
*/
|
|
156
|
-
export type ExecuteMethodOptions<EO extends ExecuteOptions = ExecuteOptions> = RequestInit &
|
|
123
|
+
export type ExecuteMethodOptions<EO extends ExecuteOptions = ExecuteOptions> = RequestInit & FFetchOptions & ExecuteOptions & EO;
|
|
157
124
|
/**
|
|
158
125
|
* Get the Accept header value based on includeODataAnnotations option
|
|
159
126
|
* @param includeODataAnnotations - Whether to include OData annotations
|
|
@@ -216,4 +183,3 @@ export type EntitySet = {
|
|
|
216
183
|
$Type: string;
|
|
217
184
|
};
|
|
218
185
|
export type Metadata = Record<string, EntityType | EntitySet>;
|
|
219
|
-
export {};
|
package/dist/esm/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../src/types.ts"],"sourcesContent":["import { type FFetchOptions } from \"@fetchkit/ffetch\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport type Auth = { username: string; password: string } | { apiKey: string };\n\nexport interface ExecutableBuilder<T> {\n execute(): Promise<Result<T>>;\n getRequestConfig(): { method: string; url: string; body?: any };\n\n /**\n * Convert this builder to a native Request object for batch processing.\n * @param baseUrl - The base URL for the OData service\n * @param options - Optional execution options (e.g., includeODataAnnotations)\n * @returns A native Request object\n */\n toRequest(baseUrl: string, options?: ExecuteOptions): Request;\n\n /**\n * Process a raw Response object into a typed Result.\n * This allows builders to apply their own validation and transformation logic.\n * @param response - The native Response object from the batch operation\n * @param options - Optional execution options (e.g., skipValidation, includeODataAnnotations)\n * @returns A typed Result with the builder's expected return type\n */\n processResponse(\n response: Response,\n options?: ExecuteOptions,\n ): Promise<Result<T>>;\n}\n\nexport interface ExecutionContext {\n _makeRequest<T>(\n url: string,\n options?: RequestInit & FFetchOptions & { useEntityIds?: boolean },\n ): Promise<Result<T>>;\n _setUseEntityIds?(useEntityIds: boolean): void;\n _getUseEntityIds?(): boolean;\n _getBaseUrl?(): string;\n}\n\nexport type InferSchemaType<Schema extends Record<string, StandardSchemaV1>> = {\n [K in keyof Schema]: Schema[K] extends StandardSchemaV1<any, infer Output>\n ? Output\n : never;\n};\n\nexport type WithSystemFields<T> =\n T extends Record<string, any>\n ? T & {\n ROWID: number;\n ROWMODID: number;\n }\n : never;\n\n// Helper type to exclude system fields from a union of keys\nexport type ExcludeSystemFields<T extends keyof any> = Exclude<\n T,\n \"ROWID\" | \"ROWMODID\"\n>;\n\n// Helper type to omit system fields from an object type\nexport type OmitSystemFields<T> = Omit<T, \"ROWID\" | \"ROWMODID\">;\n\n// OData record metadata fields (present on each record)\nexport type ODataRecordMetadata = {\n \"@id\": string;\n \"@editLink\": string;\n};\n\n// OData response wrapper (top-level, internal use only)\nexport type ODataListResponse<T> = {\n \"@context\": string;\n value: (T & ODataRecordMetadata)[];\n};\n\nexport type ODataSingleResponse<T> = T &\n ODataRecordMetadata & {\n \"@context\": string;\n };\n\n// OData response for single field values\nexport type ODataFieldResponse<T> = {\n \"@context\": string;\n value: T;\n};\n\n// Result pattern for execute responses\nexport type Result<T, E = import(\"./errors\").FMODataErrorType> =\n | { data: T; error: undefined }\n | { data: undefined; error: E };\n\n// Batch operation result types\nexport type BatchItemResult<T> = {\n data: T | undefined;\n error: import(\"./errors\").FMODataErrorType | undefined;\n status: number; // HTTP status code (0 for truncated)\n};\n\nexport type BatchResult<T extends readonly any[]> = {\n results: { [K in keyof T]: BatchItemResult<T[K]> };\n successCount: number;\n errorCount: number;\n truncated: boolean;\n firstErrorIndex: number | null;\n};\n\n// Make specific keys required, rest optional\nexport type MakeFieldsRequired<T, Keys extends keyof T> = Partial<T> &\n Required<Pick<T, Keys>>;\n\n// Extract keys from schema where validator doesn't allow null/undefined (auto-required fields)\nexport type AutoRequiredKeys<Schema extends Record<string, StandardSchemaV1>> =\n {\n [K in keyof Schema]: Extract<\n StandardSchemaV1.InferOutput<Schema[K]>,\n null | undefined\n > extends never\n ? K\n : never;\n }[keyof Schema];\n\n// Helper type to compute excluded fields (readOnly fields + idField)\nexport type ExcludedFields<\n IdField extends keyof any | undefined,\n ReadOnly extends readonly any[],\n> = IdField extends keyof any ? IdField | ReadOnly[number] : ReadOnly[number];\n\n// Helper type for InsertData computation\ntype ComputeInsertData<\n Schema extends Record<string, StandardSchemaV1>,\n IdField extends keyof Schema | undefined,\n Required extends readonly any[],\n ReadOnly extends readonly any[],\n> = [Required[number]] extends [keyof InferSchemaType<Schema>]\n ? Required extends readonly (keyof InferSchemaType<Schema>)[]\n ? MakeFieldsRequired<\n Omit<InferSchemaType<Schema>, ExcludedFields<IdField, ReadOnly>>,\n Exclude<\n AutoRequiredKeys<Schema> | Required[number],\n ExcludedFields<IdField, ReadOnly>\n >\n >\n : MakeFieldsRequired<\n Omit<InferSchemaType<Schema>, ExcludedFields<IdField, ReadOnly>>,\n Exclude<AutoRequiredKeys<Schema>, ExcludedFields<IdField, ReadOnly>>\n >\n : MakeFieldsRequired<\n Omit<InferSchemaType<Schema>, ExcludedFields<IdField, ReadOnly>>,\n Exclude<AutoRequiredKeys<Schema>, ExcludedFields<IdField, ReadOnly>>\n >;\n\n// Legacy types for backward compatibility\n// Note: These types are deprecated. Use InsertDataFromFMTable and UpdateDataFromFMTable from the ORM API instead.\nexport type InsertData<BT> = Partial<Record<string, any>>;\nexport type UpdateData<BT> = Partial<Record<string, any>>;\n\nexport type ExecuteOptions = {\n includeODataAnnotations?: boolean;\n skipValidation?: boolean;\n /**\n * Overrides the default behavior of the database to use entity IDs (rather than field names) in THIS REQUEST ONLY\n */\n useEntityIds?: boolean;\n};\n\n/**\n * Type for the fetchHandler callback function.\n * This type is re-exported to ensure proper type preservation in generated .d.ts files.\n *\n * **Usage Note**: Due to TypeScript limitations with optional properties in intersection types,\n * you may need to explicitly type fetchHandler parameters when using the built package:\n *\n * @example\n * ```typescript\n * import type { FetchHandler } from '@proofkit/fmodata';\n *\n * await query.execute({\n * fetchHandler: ((input, init) => {\n * // TypeScript will infer types here\n * return fetch(input, init);\n * }) as FetchHandler\n * });\n *\n * // Or with explicit parameters:\n * await query.execute({\n * fetchHandler: (input: RequestInfo | URL, init?: RequestInit) => {\n * return fetch(input, init);\n * }\n * });\n * ```\n */\nexport type FetchHandler = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Promise<Response>;\n\n/**\n * Extended execute options that includes fetchHandler with proper typing.\n * This ensures the fetchHandler parameter types are preserved in generated declaration files.\n */\nexport type ExecuteOptionsWithFetch = ExecuteOptions & {\n fetchHandler?: FetchHandler;\n};\n\n/**\n * Local re-export of key FFetchOptions properties to ensure type preservation.\n * This avoids relying on external package type resolution in the built package.\n */\ntype LocalFFetchOptions = {\n timeout?: number;\n retries?: number;\n throwOnHttpError?: boolean;\n hooks?: any; // Simplified for now\n /**\n * Custom fetch handler function.\n * The parameter types are explicitly defined inline to ensure proper type inference.\n */\n fetchHandler?: (\n input: RequestInfo | URL,\n init?: RequestInit,\n ) => Promise<Response>;\n dedupe?: boolean;\n};\n\n/**\n * Combined type for execute() method options.\n *\n * Uses LocalFFetchOptions instead of importing from @fetchkit/ffetch to ensure\n * proper type inference in generated declaration files.\n */\nexport type ExecuteMethodOptions<EO extends ExecuteOptions = ExecuteOptions> =\n RequestInit & LocalFFetchOptions & ExecuteOptions & EO;\n\n/**\n * Get the Accept header value based on includeODataAnnotations option\n * @param includeODataAnnotations - Whether to include OData annotations\n * @returns Accept header value\n */\nexport function getAcceptHeader(includeODataAnnotations?: boolean): string {\n return includeODataAnnotations === true\n ? \"application/json\"\n : \"application/json;odata.metadata=none\";\n}\n\nexport type ConditionallyWithODataAnnotations<\n T,\n IncludeODataAnnotations extends boolean,\n> = IncludeODataAnnotations extends true\n ? T & {\n \"@id\": string;\n \"@editLink\": string;\n }\n : T;\n\n// Helper type to extract schema from a TableOccurrence (legacy) or FMTable\nexport type ExtractSchemaFromOccurrence<Occ> = Occ extends {\n baseTable: { schema: infer S };\n}\n ? S extends Record<string, StandardSchemaV1>\n ? S\n : Record<string, StandardSchemaV1>\n : Record<string, StandardSchemaV1>;\n\nexport type GenericFieldMetadata = {\n $Nullable?: boolean;\n \"@Index\"?: boolean;\n \"@Calculation\"?: boolean;\n \"@Summary\"?: boolean;\n \"@Global\"?: boolean;\n \"@Org.OData.Core.V1.Permissions\"?: \"Org.OData.Core.V1.Permission@Read\";\n};\n\nexport type StringFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.String\";\n $DefaultValue?: \"USER\" | \"USERNAME\" | \"CURRENT_USER\";\n $MaxLength?: number;\n};\n\nexport type DecimalFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.Decimal\";\n \"@AutoGenerated\"?: boolean;\n};\n\nexport type DateFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.Date\";\n $DefaultValue?: \"CURDATE\" | \"CURRENT_DATE\";\n};\n\nexport type TimeOfDayFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.TimeOfDay\";\n $DefaultValue?: \"CURTIME\" | \"CURRENT_TIME\";\n};\n\nexport type DateTimeOffsetFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.Date\";\n $DefaultValue?: \"CURTIMESTAMP\" | \"CURRENT_TIMESTAMP\";\n \"@VersionId\"?: boolean;\n};\n\nexport type StreamFieldMetadata = {\n $Type: \"Edm.Stream\";\n $Nullable?: boolean;\n \"@EnclosedPath\": string;\n \"@ExternalOpenPath\": string;\n \"@ExternalSecurePath\"?: string;\n};\n\nexport type FieldMetadata =\n | StringFieldMetadata\n | DecimalFieldMetadata\n | DateFieldMetadata\n | TimeOfDayFieldMetadata\n | DateTimeOffsetFieldMetadata\n | StreamFieldMetadata;\n\nexport type EntityType = {\n $Kind: \"EntityType\";\n $Key: string[];\n} & Record<string, FieldMetadata>;\n\nexport type EntitySet = {\n $Kind: \"EntitySet\";\n $Type: string;\n};\n\nexport type Metadata = Record<string, EntityType | EntitySet>;\n"],"names":[],"mappings":"AA8OO,SAAS,gBAAgB,yBAA2C;AAClE,SAAA,4BAA4B,OAC/B,qBACA;AACN;"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../src/types.ts"],"sourcesContent":["import { type FFetchOptions } from \"@fetchkit/ffetch\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport type Auth = { username: string; password: string } | { apiKey: string };\n\nexport interface ExecutableBuilder<T> {\n execute(): Promise<Result<T>>;\n getRequestConfig(): { method: string; url: string; body?: any };\n\n /**\n * Convert this builder to a native Request object for batch processing.\n * @param baseUrl - The base URL for the OData service\n * @param options - Optional execution options (e.g., includeODataAnnotations)\n * @returns A native Request object\n */\n toRequest(baseUrl: string, options?: ExecuteOptions): Request;\n\n /**\n * Process a raw Response object into a typed Result.\n * This allows builders to apply their own validation and transformation logic.\n * @param response - The native Response object from the batch operation\n * @param options - Optional execution options (e.g., skipValidation, includeODataAnnotations)\n * @returns A typed Result with the builder's expected return type\n */\n processResponse(\n response: Response,\n options?: ExecuteOptions,\n ): Promise<Result<T>>;\n}\n\nexport interface ExecutionContext {\n _makeRequest<T>(\n url: string,\n options?: RequestInit & FFetchOptions & { useEntityIds?: boolean },\n ): Promise<Result<T>>;\n _setUseEntityIds?(useEntityIds: boolean): void;\n _getUseEntityIds?(): boolean;\n _getBaseUrl?(): string;\n}\n\nexport type InferSchemaType<Schema extends Record<string, StandardSchemaV1>> = {\n [K in keyof Schema]: Schema[K] extends StandardSchemaV1<any, infer Output>\n ? Output\n : never;\n};\n\nexport type WithSystemFields<T> =\n T extends Record<string, any>\n ? T & {\n ROWID: number;\n ROWMODID: number;\n }\n : never;\n\n// Helper type to exclude system fields from a union of keys\nexport type ExcludeSystemFields<T extends keyof any> = Exclude<\n T,\n \"ROWID\" | \"ROWMODID\"\n>;\n\n// Helper type to omit system fields from an object type\nexport type OmitSystemFields<T> = Omit<T, \"ROWID\" | \"ROWMODID\">;\n\n// OData record metadata fields (present on each record)\nexport type ODataRecordMetadata = {\n \"@id\": string;\n \"@editLink\": string;\n};\n\n// OData response wrapper (top-level, internal use only)\nexport type ODataListResponse<T> = {\n \"@context\": string;\n value: (T & ODataRecordMetadata)[];\n};\n\nexport type ODataSingleResponse<T> = T &\n ODataRecordMetadata & {\n \"@context\": string;\n };\n\n// OData response for single field values\nexport type ODataFieldResponse<T> = {\n \"@context\": string;\n value: T;\n};\n\n// Result pattern for execute responses\nexport type Result<T, E = import(\"./errors\").FMODataErrorType> =\n | { data: T; error: undefined }\n | { data: undefined; error: E };\n\n// Batch operation result types\nexport type BatchItemResult<T> = {\n data: T | undefined;\n error: import(\"./errors\").FMODataErrorType | undefined;\n status: number; // HTTP status code (0 for truncated)\n};\n\nexport type BatchResult<T extends readonly any[]> = {\n results: { [K in keyof T]: BatchItemResult<T[K]> };\n successCount: number;\n errorCount: number;\n truncated: boolean;\n firstErrorIndex: number | null;\n};\n\n// Make specific keys required, rest optional\nexport type MakeFieldsRequired<T, Keys extends keyof T> = Partial<T> &\n Required<Pick<T, Keys>>;\n\n// Extract keys from schema where validator doesn't allow null/undefined (auto-required fields)\nexport type AutoRequiredKeys<Schema extends Record<string, StandardSchemaV1>> =\n {\n [K in keyof Schema]: Extract<\n StandardSchemaV1.InferOutput<Schema[K]>,\n null | undefined\n > extends never\n ? K\n : never;\n }[keyof Schema];\n\n// Helper type to compute excluded fields (readOnly fields + idField)\nexport type ExcludedFields<\n IdField extends keyof any | undefined,\n ReadOnly extends readonly any[],\n> = IdField extends keyof any ? IdField | ReadOnly[number] : ReadOnly[number];\n\n// Helper type for InsertData computation\ntype ComputeInsertData<\n Schema extends Record<string, StandardSchemaV1>,\n IdField extends keyof Schema | undefined,\n Required extends readonly any[],\n ReadOnly extends readonly any[],\n> = [Required[number]] extends [keyof InferSchemaType<Schema>]\n ? Required extends readonly (keyof InferSchemaType<Schema>)[]\n ? MakeFieldsRequired<\n Omit<InferSchemaType<Schema>, ExcludedFields<IdField, ReadOnly>>,\n Exclude<\n AutoRequiredKeys<Schema> | Required[number],\n ExcludedFields<IdField, ReadOnly>\n >\n >\n : MakeFieldsRequired<\n Omit<InferSchemaType<Schema>, ExcludedFields<IdField, ReadOnly>>,\n Exclude<AutoRequiredKeys<Schema>, ExcludedFields<IdField, ReadOnly>>\n >\n : MakeFieldsRequired<\n Omit<InferSchemaType<Schema>, ExcludedFields<IdField, ReadOnly>>,\n Exclude<AutoRequiredKeys<Schema>, ExcludedFields<IdField, ReadOnly>>\n >;\n\nexport type ExecuteOptions = {\n includeODataAnnotations?: boolean;\n skipValidation?: boolean;\n /**\n * Overrides the default behavior of the database to use entity IDs (rather than field names) in THIS REQUEST ONLY\n */\n useEntityIds?: boolean;\n};\n\n/**\n * Type for the fetchHandler callback function.\n * This is a convenience type export that matches the fetchHandler signature in FFetchOptions.\n *\n * @example\n * ```typescript\n * import type { FetchHandler } from '@proofkit/fmodata';\n *\n * const myFetchHandler: FetchHandler = (input, init) => {\n * console.log('Custom fetch:', input);\n * return fetch(input, init);\n * };\n *\n * await query.execute({\n * fetchHandler: myFetchHandler\n * });\n * ```\n */\nexport type FetchHandler = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Promise<Response>;\n\n/**\n * Combined type for execute() method options.\n *\n * Uses FFetchOptions from @fetchkit/ffetch to ensure proper type inference.\n * FFetchOptions is re-exported in the package to ensure type availability in consuming packages.\n */\nexport type ExecuteMethodOptions<EO extends ExecuteOptions = ExecuteOptions> =\n RequestInit & FFetchOptions & ExecuteOptions & EO;\n\n/**\n * Get the Accept header value based on includeODataAnnotations option\n * @param includeODataAnnotations - Whether to include OData annotations\n * @returns Accept header value\n */\nexport function getAcceptHeader(includeODataAnnotations?: boolean): string {\n return includeODataAnnotations === true\n ? \"application/json\"\n : \"application/json;odata.metadata=none\";\n}\n\nexport type ConditionallyWithODataAnnotations<\n T,\n IncludeODataAnnotations extends boolean,\n> = IncludeODataAnnotations extends true\n ? T & {\n \"@id\": string;\n \"@editLink\": string;\n }\n : T;\n\n// Helper type to extract schema from a FMTable\nexport type ExtractSchemaFromOccurrence<Occ> = Occ extends {\n baseTable: { schema: infer S };\n}\n ? S extends Record<string, StandardSchemaV1>\n ? S\n : Record<string, StandardSchemaV1>\n : Record<string, StandardSchemaV1>;\n\nexport type GenericFieldMetadata = {\n $Nullable?: boolean;\n \"@Index\"?: boolean;\n \"@Calculation\"?: boolean;\n \"@Summary\"?: boolean;\n \"@Global\"?: boolean;\n \"@Org.OData.Core.V1.Permissions\"?: \"Org.OData.Core.V1.Permission@Read\";\n};\n\nexport type StringFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.String\";\n $DefaultValue?: \"USER\" | \"USERNAME\" | \"CURRENT_USER\";\n $MaxLength?: number;\n};\n\nexport type DecimalFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.Decimal\";\n \"@AutoGenerated\"?: boolean;\n};\n\nexport type DateFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.Date\";\n $DefaultValue?: \"CURDATE\" | \"CURRENT_DATE\";\n};\n\nexport type TimeOfDayFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.TimeOfDay\";\n $DefaultValue?: \"CURTIME\" | \"CURRENT_TIME\";\n};\n\nexport type DateTimeOffsetFieldMetadata = GenericFieldMetadata & {\n $Type: \"Edm.Date\";\n $DefaultValue?: \"CURTIMESTAMP\" | \"CURRENT_TIMESTAMP\";\n \"@VersionId\"?: boolean;\n};\n\nexport type StreamFieldMetadata = {\n $Type: \"Edm.Stream\";\n $Nullable?: boolean;\n \"@EnclosedPath\": string;\n \"@ExternalOpenPath\": string;\n \"@ExternalSecurePath\"?: string;\n};\n\nexport type FieldMetadata =\n | StringFieldMetadata\n | DecimalFieldMetadata\n | DateFieldMetadata\n | TimeOfDayFieldMetadata\n | DateTimeOffsetFieldMetadata\n | StreamFieldMetadata;\n\nexport type EntityType = {\n $Kind: \"EntityType\";\n $Key: string[];\n} & Record<string, FieldMetadata>;\n\nexport type EntitySet = {\n $Kind: \"EntitySet\";\n $Type: string;\n};\n\nexport type Metadata = Record<string, EntityType | EntitySet>;\n"],"names":[],"mappings":"AAqMO,SAAS,gBAAgB,yBAA2C;AAClE,SAAA,4BAA4B,OAC/B,qBACA;AACN;"}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ import { isColumn, type Column } from "../../orm/column";
|
|
|
8
8
|
* @returns Object with selectedFields array
|
|
9
9
|
*/
|
|
10
10
|
export function processSelectFields(
|
|
11
|
-
...fields: (string | Column<any, string>)[]
|
|
11
|
+
...fields: (string | Column<any, any, string>)[]
|
|
12
12
|
): { selectedFields: string[] } {
|
|
13
13
|
const fieldNames = fields.map((field) => {
|
|
14
14
|
if (isColumn(field)) {
|
|
@@ -29,7 +29,7 @@ export function processSelectFields(
|
|
|
29
29
|
* @returns Object with selectedFields array and fieldMapping for renamed fields
|
|
30
30
|
*/
|
|
31
31
|
export function processSelectWithRenames<TTableName extends string>(
|
|
32
|
-
fields: Record<string, Column<any, TTableName>>,
|
|
32
|
+
fields: Record<string, Column<any, any, TTableName>>,
|
|
33
33
|
tableName: string,
|
|
34
34
|
): { selectedFields: string[]; fieldMapping: Record<string, string> } {
|
|
35
35
|
const selectedFields: string[] = [];
|
|
@@ -71,4 +71,3 @@ export function processSelectWithRenames<TTableName extends string>(
|
|
|
71
71
|
export class SelectMixin {
|
|
72
72
|
static processSelect = processSelectFields;
|
|
73
73
|
}
|
|
74
|
-
|
package/src/client/entity-set.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
ExtractTableName,
|
|
17
17
|
FMTableWithColumns,
|
|
18
18
|
InferFieldOutput,
|
|
19
|
+
ColumnMap,
|
|
19
20
|
} from "../orm/table";
|
|
20
21
|
import {
|
|
21
22
|
FMTable as FMTableClass,
|
|
@@ -42,7 +43,7 @@ type ExtractDefaultSelect<O> =
|
|
|
42
43
|
type ExtractColumnsFromOcc<T> =
|
|
43
44
|
T extends FMTable<infer TFields, infer TName, any>
|
|
44
45
|
? TFields extends Record<string, FieldBuilder<any, any, any, any>>
|
|
45
|
-
?
|
|
46
|
+
? ColumnMap<TFields, TName>
|
|
46
47
|
: never
|
|
47
48
|
: never;
|
|
48
49
|
|
|
@@ -87,7 +88,13 @@ export class EntitySet<Occ extends FMTable<any, any>> {
|
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
list()
|
|
91
|
+
list(): QueryBuilder<
|
|
92
|
+
Occ,
|
|
93
|
+
keyof InferSchemaOutputFromFMTable<Occ>,
|
|
94
|
+
false,
|
|
95
|
+
false,
|
|
96
|
+
{}
|
|
97
|
+
> {
|
|
91
98
|
const builder = new QueryBuilder<Occ>({
|
|
92
99
|
occurrence: this.occurrence as Occ,
|
|
93
100
|
databaseName: this.databaseName,
|
|
@@ -117,18 +124,29 @@ export class EntitySet<Occ extends FMTable<any, any>> {
|
|
|
117
124
|
if (defaultSelectValue === "schema") {
|
|
118
125
|
// Use getTableColumns to get all columns and select them
|
|
119
126
|
// This is equivalent to select(getTableColumns(occurrence))
|
|
120
|
-
//
|
|
127
|
+
// Cast to the declared return type - runtime behavior handles the actual selection
|
|
121
128
|
const allColumns = getTableColumns(
|
|
122
129
|
this.occurrence as any,
|
|
123
130
|
) as ExtractColumnsFromOcc<Occ>;
|
|
124
|
-
return builder.select(allColumns).top(1000)
|
|
131
|
+
return builder.select(allColumns).top(1000) as QueryBuilder<
|
|
132
|
+
Occ,
|
|
133
|
+
keyof InferSchemaOutputFromFMTable<Occ>,
|
|
134
|
+
false,
|
|
135
|
+
false,
|
|
136
|
+
{}
|
|
137
|
+
>;
|
|
125
138
|
} else if (typeof defaultSelectValue === "object") {
|
|
126
139
|
// defaultSelectValue is a select object (Record<string, Column>)
|
|
127
|
-
//
|
|
128
|
-
// Use ExtractColumnsFromOcc to preserve the properly-typed column types
|
|
140
|
+
// Cast to the declared return type - runtime behavior handles the actual selection
|
|
129
141
|
return builder
|
|
130
142
|
.select(defaultSelectValue as ExtractColumnsFromOcc<Occ>)
|
|
131
|
-
.top(1000)
|
|
143
|
+
.top(1000) as QueryBuilder<
|
|
144
|
+
Occ,
|
|
145
|
+
keyof InferSchemaOutputFromFMTable<Occ>,
|
|
146
|
+
false,
|
|
147
|
+
false,
|
|
148
|
+
{}
|
|
149
|
+
>;
|
|
132
150
|
}
|
|
133
151
|
// If defaultSelect is "all", no changes needed (current behavior)
|
|
134
152
|
}
|
|
@@ -9,11 +9,9 @@ import type {
|
|
|
9
9
|
ExtractSchemaFromOccurrence,
|
|
10
10
|
ExecuteMethodOptions,
|
|
11
11
|
} from "../../types";
|
|
12
|
-
import type { Filter } from "../../filter-types";
|
|
13
12
|
import { RecordCountMismatchError } from "../../errors";
|
|
14
13
|
import { type FFetchOptions } from "@fetchkit/ffetch";
|
|
15
14
|
import {
|
|
16
|
-
transformFieldName,
|
|
17
15
|
transformFieldNamesArray,
|
|
18
16
|
transformOrderByField,
|
|
19
17
|
} from "../../transform";
|
|
@@ -66,7 +64,7 @@ export class QueryBuilder<
|
|
|
66
64
|
| keyof InferSchemaOutputFromFMTable<Occ>
|
|
67
65
|
| Record<
|
|
68
66
|
string,
|
|
69
|
-
Column<any, ExtractTableName<Occ>>
|
|
67
|
+
Column<any, any, ExtractTableName<Occ>>
|
|
70
68
|
> = keyof InferSchemaOutputFromFMTable<Occ>,
|
|
71
69
|
SingleMode extends "exact" | "maybe" | false = false,
|
|
72
70
|
IsCount extends boolean = false,
|
|
@@ -152,7 +150,7 @@ export class QueryBuilder<
|
|
|
152
150
|
private cloneWithChanges<
|
|
153
151
|
NewSelected extends
|
|
154
152
|
| keyof InferSchemaOutputFromFMTable<Occ>
|
|
155
|
-
| Record<string, Column<any, ExtractTableName<Occ>>> = Selected,
|
|
153
|
+
| Record<string, Column<any, any, ExtractTableName<Occ>>> = Selected,
|
|
156
154
|
NewSingle extends "exact" | "maybe" | false = SingleMode,
|
|
157
155
|
NewCount extends boolean = IsCount,
|
|
158
156
|
>(changes: {
|
|
@@ -207,7 +205,7 @@ export class QueryBuilder<
|
|
|
207
205
|
* @returns QueryBuilder with updated selected fields
|
|
208
206
|
*/
|
|
209
207
|
select<
|
|
210
|
-
TSelect extends Record<string, Column<any, ExtractTableName<Occ>, false>>,
|
|
208
|
+
TSelect extends Record<string, Column<any, any, ExtractTableName<Occ>, false>>,
|
|
211
209
|
>(fields: TSelect): QueryBuilder<Occ, TSelect, SingleMode, IsCount, Expands> {
|
|
212
210
|
const tableName = getTableName(this.occurrence);
|
|
213
211
|
const { selectedFields, fieldMapping } = processSelectWithRenames(
|
|
@@ -225,131 +223,24 @@ export class QueryBuilder<
|
|
|
225
223
|
});
|
|
226
224
|
}
|
|
227
225
|
|
|
228
|
-
/**
|
|
229
|
-
* Transforms our filter format to odata-query's expected format
|
|
230
|
-
* - Arrays of operators are converted to AND conditions
|
|
231
|
-
* - Single operator objects pass through as-is
|
|
232
|
-
* - Shorthand values are handled by odata-query
|
|
233
|
-
*/
|
|
234
|
-
private transformFilter(
|
|
235
|
-
filter: Filter<ExtractSchemaFromOccurrence<Occ>>,
|
|
236
|
-
): QueryOptions<InferSchemaOutputFromFMTable<Occ>>["filter"] {
|
|
237
|
-
if (typeof filter === "string") {
|
|
238
|
-
// Raw string filters pass through
|
|
239
|
-
return filter;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (Array.isArray(filter)) {
|
|
243
|
-
// Array of filters - odata-query handles this as implicit AND
|
|
244
|
-
return filter.map((f) => this.transformFilter(f as any)) as any;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Check if it's a logical filter (and/or/not)
|
|
248
|
-
if ("and" in filter || "or" in filter || "not" in filter) {
|
|
249
|
-
const result: any = {};
|
|
250
|
-
if ("and" in filter && Array.isArray(filter.and)) {
|
|
251
|
-
result.and = filter.and.map((f: any) => this.transformFilter(f));
|
|
252
|
-
}
|
|
253
|
-
if ("or" in filter && Array.isArray(filter.or)) {
|
|
254
|
-
result.or = filter.or.map((f: any) => this.transformFilter(f));
|
|
255
|
-
}
|
|
256
|
-
if ("not" in filter && filter.not) {
|
|
257
|
-
result.not = this.transformFilter(filter.not as any);
|
|
258
|
-
}
|
|
259
|
-
return result;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Transform field filters
|
|
263
|
-
const result: any = {};
|
|
264
|
-
const andConditions: any[] = [];
|
|
265
|
-
|
|
266
|
-
for (const [field, value] of Object.entries(filter)) {
|
|
267
|
-
// Transform field name to FMFID if using entity IDs AND the feature is enabled
|
|
268
|
-
const shouldTransform = this.occurrence && this.databaseUseEntityIds;
|
|
269
|
-
const fieldId = shouldTransform
|
|
270
|
-
? transformFieldName(field, this.occurrence!)
|
|
271
|
-
: field;
|
|
272
|
-
|
|
273
|
-
if (Array.isArray(value)) {
|
|
274
|
-
// Array of operators - convert to AND conditions
|
|
275
|
-
if (value.length === 1) {
|
|
276
|
-
// Single operator in array - unwrap it
|
|
277
|
-
result[fieldId] = value[0];
|
|
278
|
-
} else {
|
|
279
|
-
// Multiple operators - combine with AND
|
|
280
|
-
// Create separate conditions for each operator
|
|
281
|
-
for (const op of value) {
|
|
282
|
-
andConditions.push({ [fieldId]: op });
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
} else if (
|
|
286
|
-
value &&
|
|
287
|
-
typeof value === "object" &&
|
|
288
|
-
!(value instanceof Date) &&
|
|
289
|
-
!Array.isArray(value)
|
|
290
|
-
) {
|
|
291
|
-
// Check if it's an operator object (has operator keys like eq, gt, etc.)
|
|
292
|
-
const operatorKeys = [
|
|
293
|
-
"eq",
|
|
294
|
-
"ne",
|
|
295
|
-
"gt",
|
|
296
|
-
"ge",
|
|
297
|
-
"lt",
|
|
298
|
-
"le",
|
|
299
|
-
"contains",
|
|
300
|
-
"startswith",
|
|
301
|
-
"endswith",
|
|
302
|
-
"in",
|
|
303
|
-
];
|
|
304
|
-
const isOperatorObject = operatorKeys.some((key) => key in value);
|
|
305
|
-
|
|
306
|
-
if (isOperatorObject) {
|
|
307
|
-
// Single operator object - pass through
|
|
308
|
-
result[fieldId] = value;
|
|
309
|
-
} else {
|
|
310
|
-
// Regular object - might be nested filter, pass through
|
|
311
|
-
result[fieldId] = value;
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
// Primitive value (shorthand) - pass through
|
|
315
|
-
result[fieldId] = value;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// If we have AND conditions from arrays, combine them
|
|
320
|
-
if (andConditions.length > 0) {
|
|
321
|
-
if (Object.keys(result).length > 0) {
|
|
322
|
-
// We have both regular fields and array-derived AND conditions
|
|
323
|
-
// Combine everything with AND
|
|
324
|
-
return { and: [...andConditions, result] };
|
|
325
|
-
} else {
|
|
326
|
-
// Only array-derived AND conditions
|
|
327
|
-
return { and: andConditions };
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
return result;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
filter(
|
|
335
|
-
filter: Filter<ExtractSchemaFromOccurrence<Occ>>,
|
|
336
|
-
): QueryBuilder<Occ, Selected, SingleMode, IsCount, Expands> {
|
|
337
|
-
// Transform our filter format to odata-query's expected format
|
|
338
|
-
this.queryOptions.filter = this.transformFilter(filter) as any;
|
|
339
|
-
return this;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
226
|
/**
|
|
343
227
|
* Filter results using operator expressions (new ORM-style API).
|
|
344
228
|
* Supports eq, gt, lt, and, or, etc. operators with Column references.
|
|
229
|
+
* Also supports raw OData filter strings as an escape hatch.
|
|
345
230
|
*
|
|
346
231
|
* @example
|
|
347
232
|
* .where(eq(users.hobby, "reading"))
|
|
348
233
|
* .where(and(eq(users.active, true), gt(users.age, 18)))
|
|
234
|
+
* .where("status eq 'active'") // Raw OData string escape hatch
|
|
349
235
|
*/
|
|
350
236
|
where(
|
|
351
|
-
expression: FilterExpression,
|
|
237
|
+
expression: FilterExpression | string,
|
|
352
238
|
): QueryBuilder<Occ, Selected, SingleMode, IsCount, Expands> {
|
|
239
|
+
// Handle raw string filters (escape hatch)
|
|
240
|
+
if (typeof expression === "string") {
|
|
241
|
+
this.queryOptions.filter = expression;
|
|
242
|
+
return this;
|
|
243
|
+
}
|
|
353
244
|
// Convert FilterExpression to OData filter string
|
|
354
245
|
const filterString = expression.toODataFilter(this.databaseUseEntityIds);
|
|
355
246
|
this.queryOptions.filter = filterString;
|
|
@@ -384,13 +275,13 @@ export class QueryBuilder<
|
|
|
384
275
|
...orderByArgs:
|
|
385
276
|
| [
|
|
386
277
|
| TypeSafeOrderBy<InferSchemaOutputFromFMTable<Occ>>
|
|
387
|
-
| Column<any, ExtractTableName<Occ>>
|
|
278
|
+
| Column<any, any, ExtractTableName<Occ>>
|
|
388
279
|
| OrderByExpression<ExtractTableName<Occ>>,
|
|
389
280
|
]
|
|
390
281
|
| [
|
|
391
|
-
Column<any, ExtractTableName<Occ>>,
|
|
282
|
+
Column<any, any, ExtractTableName<Occ>>,
|
|
392
283
|
...Array<
|
|
393
|
-
| Column<any, ExtractTableName<Occ>>
|
|
284
|
+
| Column<any, any, ExtractTableName<Occ>>
|
|
394
285
|
| OrderByExpression<ExtractTableName<Occ>>
|
|
395
286
|
>,
|
|
396
287
|
]
|
|
@@ -28,16 +28,17 @@ export type ExpandedRelations = Record<string, { schema: any; selected: any }>;
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Extract the value type from a Column.
|
|
31
|
-
* This uses the phantom type stored in Column to get the actual value type.
|
|
31
|
+
* This uses the phantom type stored in Column to get the actual value type (output type for reading).
|
|
32
32
|
*/
|
|
33
|
-
type ExtractColumnType<C> =
|
|
33
|
+
type ExtractColumnType<C> =
|
|
34
|
+
C extends Column<infer T, any, any, any> ? T : never;
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Map a select object to its return type.
|
|
37
38
|
* For each key in the select object, extract the type from the corresponding Column.
|
|
38
39
|
*/
|
|
39
40
|
type MapSelectToReturnType<
|
|
40
|
-
TSelect extends Record<string, Column<any, any>>,
|
|
41
|
+
TSelect extends Record<string, Column<any, any, any, any>>,
|
|
41
42
|
TSchema extends Record<string, any>,
|
|
42
43
|
> = {
|
|
43
44
|
[K in keyof TSelect]: ExtractColumnType<TSelect[K]>;
|
|
@@ -45,14 +46,14 @@ type MapSelectToReturnType<
|
|
|
45
46
|
|
|
46
47
|
export type QueryReturnType<
|
|
47
48
|
T extends Record<string, any>,
|
|
48
|
-
Selected extends keyof T | Record<string, Column<any, any>>,
|
|
49
|
+
Selected extends keyof T | Record<string, Column<any, any, any, any>>,
|
|
49
50
|
SingleMode extends "exact" | "maybe" | false,
|
|
50
51
|
IsCount extends boolean,
|
|
51
52
|
Expands extends ExpandedRelations,
|
|
52
53
|
> = IsCount extends true
|
|
53
54
|
? number
|
|
54
55
|
: // Use tuple wrapping [Selected] extends [...] to prevent distribution over unions
|
|
55
|
-
[Selected] extends [Record<string, Column<any, any>>]
|
|
56
|
+
[Selected] extends [Record<string, Column<any, any, any, any>>]
|
|
56
57
|
? SingleMode extends "exact"
|
|
57
58
|
? MapSelectToReturnType<Selected, T> & {
|
|
58
59
|
[K in keyof Expands]: Pick<
|
|
@@ -44,7 +44,7 @@ type ExtractColumnType<C> = C extends Column<infer T, any> ? T : never;
|
|
|
44
44
|
* For each key in the select object, extract the type from the corresponding Column.
|
|
45
45
|
*/
|
|
46
46
|
type MapSelectToReturnType<
|
|
47
|
-
TSelect extends Record<string, Column<any, any>>,
|
|
47
|
+
TSelect extends Record<string, Column<any, any, any, any>>,
|
|
48
48
|
TSchema extends Record<string, any>,
|
|
49
49
|
> = {
|
|
50
50
|
[K in keyof TSelect]: ExtractColumnType<TSelect[K]>;
|
|
@@ -57,12 +57,12 @@ export type RecordReturnType<
|
|
|
57
57
|
FieldKey extends keyof Schema,
|
|
58
58
|
Selected extends
|
|
59
59
|
| keyof Schema
|
|
60
|
-
| Record<string, Column<any, ExtractTableName<FMTable<any, any>>>>,
|
|
60
|
+
| Record<string, Column<any, any, ExtractTableName<FMTable<any, any>>>>,
|
|
61
61
|
Expands extends ExpandedRelations,
|
|
62
62
|
> = IsSingleField extends true
|
|
63
63
|
? Schema[FieldKey]
|
|
64
64
|
: // Use tuple wrapping [Selected] extends [...] to prevent distribution over unions
|
|
65
|
-
[Selected] extends [Record<string, Column<any, any>>]
|
|
65
|
+
[Selected] extends [Record<string, Column<any, any, any, any>>]
|
|
66
66
|
? MapSelectToReturnType<Selected, Schema> & {
|
|
67
67
|
[K in keyof Expands]: Pick<
|
|
68
68
|
Expands[K]["schema"],
|
|
@@ -89,7 +89,7 @@ export class RecordBuilder<
|
|
|
89
89
|
| keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>
|
|
90
90
|
| Record<
|
|
91
91
|
string,
|
|
92
|
-
Column<any, ExtractTableName<NonNullable<Occ>>>
|
|
92
|
+
Column<any, any, ExtractTableName<NonNullable<Occ>>>
|
|
93
93
|
> = keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>,
|
|
94
94
|
Expands extends ExpandedRelations = {},
|
|
95
95
|
> implements
|
|
@@ -169,7 +169,7 @@ export class RecordBuilder<
|
|
|
169
169
|
| keyof InferSchemaOutputFromFMTable<NonNullable<Occ>>
|
|
170
170
|
| Record<
|
|
171
171
|
string,
|
|
172
|
-
Column<any, ExtractTableName<NonNullable<Occ>>>
|
|
172
|
+
Column<any, any, ExtractTableName<NonNullable<Occ>>>
|
|
173
173
|
> = Selected,
|
|
174
174
|
>(changes: {
|
|
175
175
|
selectedFields?: string[];
|
|
@@ -246,7 +246,10 @@ export class RecordBuilder<
|
|
|
246
246
|
* @returns RecordBuilder with updated selected fields
|
|
247
247
|
*/
|
|
248
248
|
select<
|
|
249
|
-
TSelect extends Record<
|
|
249
|
+
TSelect extends Record<
|
|
250
|
+
string,
|
|
251
|
+
Column<any, any, ExtractTableName<Occ>, false>
|
|
252
|
+
>,
|
|
250
253
|
>(fields: TSelect): RecordBuilder<Occ, false, FieldKey, TSelect, Expands> {
|
|
251
254
|
const tableName = getTableName(this.table);
|
|
252
255
|
const { selectedFields, fieldMapping } = processSelectWithRenames(
|
package/src/index.ts
CHANGED
|
@@ -74,8 +74,6 @@ export type {
|
|
|
74
74
|
BatchResult,
|
|
75
75
|
BatchItemResult,
|
|
76
76
|
InferSchemaType,
|
|
77
|
-
InsertData,
|
|
78
|
-
UpdateData,
|
|
79
77
|
ODataRecordMetadata,
|
|
80
78
|
Metadata,
|
|
81
79
|
FetchHandler,
|
|
@@ -83,19 +81,7 @@ export type {
|
|
|
83
81
|
ExecuteOptions,
|
|
84
82
|
} from "./types";
|
|
85
83
|
|
|
86
|
-
//
|
|
87
|
-
export type {
|
|
88
|
-
Filter,
|
|
89
|
-
TypedFilter,
|
|
90
|
-
FieldFilter,
|
|
91
|
-
StringOperators,
|
|
92
|
-
NumberOperators,
|
|
93
|
-
BooleanOperators,
|
|
94
|
-
DateOperators,
|
|
95
|
-
LogicalFilter,
|
|
96
|
-
} from "./filter-types";
|
|
97
|
-
|
|
98
|
-
// Re-export ffetch errors
|
|
84
|
+
// Re-export ffetch errors and types
|
|
99
85
|
export {
|
|
100
86
|
TimeoutError,
|
|
101
87
|
AbortError,
|
|
@@ -104,6 +90,8 @@ export {
|
|
|
104
90
|
CircuitOpenError,
|
|
105
91
|
} from "@fetchkit/ffetch";
|
|
106
92
|
|
|
93
|
+
export type { FFetchOptions } from "@fetchkit/ffetch";
|
|
94
|
+
|
|
107
95
|
// Export our errors
|
|
108
96
|
export {
|
|
109
97
|
FMODataError,
|