@proofkit/fmodata 0.1.0-alpha.11 → 0.1.0-alpha.13
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/LICENSE.md +21 -0
- package/dist/esm/client/batch-builder.d.ts +1 -1
- package/dist/esm/client/batch-builder.js +2 -2
- package/dist/esm/client/batch-builder.js.map +1 -1
- package/dist/esm/client/delete-builder.d.ts +1 -1
- package/dist/esm/client/delete-builder.js +3 -2
- package/dist/esm/client/delete-builder.js.map +1 -1
- package/dist/esm/client/entity-set.d.ts +1 -1
- package/dist/esm/client/entity-set.js +26 -0
- package/dist/esm/client/entity-set.js.map +1 -1
- package/dist/esm/client/filemaker-odata.js +25 -9
- package/dist/esm/client/filemaker-odata.js.map +1 -1
- package/dist/esm/client/insert-builder.d.ts +1 -5
- package/dist/esm/client/insert-builder.js +7 -23
- package/dist/esm/client/insert-builder.js.map +1 -1
- package/dist/esm/client/query-builder.d.ts +1 -5
- package/dist/esm/client/query-builder.js +63 -70
- package/dist/esm/client/query-builder.js.map +1 -1
- package/dist/esm/client/record-builder.d.ts +1 -5
- package/dist/esm/client/record-builder.js +41 -27
- package/dist/esm/client/record-builder.js.map +1 -1
- package/dist/esm/client/response-processor.d.ts +0 -5
- package/dist/esm/client/sanitize-json.d.ts +35 -0
- package/dist/esm/client/sanitize-json.js +27 -0
- package/dist/esm/client/sanitize-json.js.map +1 -0
- package/dist/esm/client/update-builder.d.ts +1 -1
- package/dist/esm/client/update-builder.js +3 -2
- package/dist/esm/client/update-builder.js.map +1 -1
- package/dist/esm/errors.d.ts +11 -1
- package/dist/esm/errors.js +15 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/types.d.ts +8 -1
- package/dist/esm/types.js +7 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/validation.js +3 -4
- package/dist/esm/validation.js.map +1 -1
- package/package.json +19 -18
- package/src/client/batch-builder.ts +2 -2
- package/src/client/delete-builder.ts +3 -2
- package/src/client/entity-set.ts +40 -2
- package/src/client/filemaker-odata.ts +39 -10
- package/src/client/insert-builder.ts +8 -33
- package/src/client/query-builder.ts +81 -91
- package/src/client/record-builder.ts +54 -40
- package/src/client/response-processor.ts +0 -13
- package/src/client/sanitize-json.ts +66 -0
- package/src/client/update-builder.ts +3 -2
- package/src/errors.ts +24 -1
- package/src/index.ts +2 -0
- package/src/types.ts +13 -1
- package/src/validation.ts +4 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-builder.js","sources":["../../../src/client/query-builder.ts"],"sourcesContent":["import { QueryOptions } from \"odata-query\";\nimport buildQuery from \"odata-query\";\nimport type {\n ExecutionContext,\n ExecutableBuilder,\n WithSystemFields,\n Result,\n InferSchemaType,\n ExecuteOptions,\n ConditionallyWithODataAnnotations,\n ExtractSchemaFromOccurrence,\n} from \"../types\";\nimport type { Filter } from \"../filter-types\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport type { BaseTable } from \"./base-table\";\nimport { validateListResponse, validateSingleResponse } from \"../validation\";\nimport { RecordCountMismatchError } from \"../errors\";\nimport { type FFetchOptions } from \"@fetchkit/ffetch\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n transformFieldNamesArray,\n transformFieldName,\n transformOrderByField,\n transformResponseFields,\n getTableIdentifiers,\n} from \"../transform\";\n\n/**\n * Default maximum number of records to return in a list query.\n * This prevents stack overflow issues with large datasets while still\n * allowing substantial data retrieval. Users can override with .top().\n */\nconst DEFAULT_TOP = 1000;\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 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 ? Nav[Name]\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, 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, any, any>]\n ? [S] extends [Record<string, StandardSchemaV1>]\n ? InferSchemaType<S>\n : Record<string, any>\n : Record<string, any>\n : Record<string, any>;\n\n// Internal type for expand configuration\ntype ExpandConfig = {\n relation: string;\n options?: Partial<QueryOptions<any>>;\n};\n\n// Type to represent expanded relations\nexport type ExpandedRelations = Record<string, { schema: any; selected: any }>;\n\nexport type QueryReturnType<\n T extends Record<string, any>,\n Selected extends keyof T,\n SingleMode extends \"exact\" | \"maybe\" | false,\n IsCount extends boolean,\n Expands extends ExpandedRelations,\n> = IsCount extends true\n ? number\n : SingleMode extends \"exact\"\n ? Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n }\n : SingleMode extends \"maybe\"\n ?\n | (Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n })\n | null\n : (Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n })[];\n\nexport class QueryBuilder<\n T extends Record<string, any>,\n Selected extends keyof T = keyof T,\n SingleMode extends \"exact\" | \"maybe\" | false = false,\n IsCount extends boolean = false,\n Occ extends TableOccurrence<any, any, any, any> | undefined = undefined,\n Expands extends ExpandedRelations = {},\n> implements\n ExecutableBuilder<\n QueryReturnType<T, Selected, SingleMode, IsCount, Expands>\n >\n{\n private queryOptions: Partial<QueryOptions<T>> = {};\n private expandConfigs: ExpandConfig[] = [];\n private singleMode: SingleMode = false as SingleMode;\n private isCountMode = false as IsCount;\n private occurrence?: Occ;\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private isNavigate?: boolean;\n private navigateRecordId?: string | number;\n private navigateRelation?: string;\n private navigateSourceTableName?: string;\n private navigateBaseRelation?: string;\n private navigateBasePath?: string; // Full base path for chained entity set navigations\n private databaseUseEntityIds: boolean;\n\n constructor(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n databaseUseEntityIds?: boolean;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n this.databaseUseEntityIds = config.databaseUseEntityIds ?? false;\n }\n\n /**\n * Helper to merge database-level useEntityIds with per-request options\n */\n private mergeExecuteOptions(\n options?: RequestInit & FFetchOptions & ExecuteOptions,\n ): RequestInit & FFetchOptions & { useEntityIds?: boolean } {\n // If useEntityIds is not set in options, use the database-level setting\n return {\n ...options,\n useEntityIds:\n options?.useEntityIds === undefined\n ? this.databaseUseEntityIds\n : options.useEntityIds,\n };\n }\n\n /**\n * Helper to conditionally strip OData annotations based on options\n */\n private stripODataAnnotationsIfNeeded<T extends Record<string, any>>(\n data: T,\n options?: ExecuteOptions,\n ): T {\n // Only include annotations if explicitly requested\n if (options?.includeODataAnnotations === true) {\n return data;\n }\n\n // Strip OData annotations\n const { \"@id\": _id, \"@editLink\": _editLink, ...rest } = data;\n return rest as T;\n }\n\n /**\n * Gets the table ID (FMTID) if using entity IDs, otherwise returns the table name\n * @param useEntityIds - Optional override for entity ID usage\n */\n private getTableId(useEntityIds?: boolean): string {\n if (!this.occurrence) {\n return this.tableName;\n }\n\n const contextDefault = this.context._getUseEntityIds?.() ?? false;\n const shouldUseIds = useEntityIds ?? contextDefault;\n\n if (shouldUseIds) {\n const identifiers = getTableIdentifiers(this.occurrence);\n if (!identifiers.id) {\n throw new Error(\n `useEntityIds is true but TableOccurrence \"${identifiers.name}\" does not have an fmtId defined`,\n );\n }\n return identifiers.id;\n }\n\n return this.occurrence.getTableName();\n }\n\n select<K extends keyof T>(\n ...fields: K[]\n ): QueryBuilder<T, K, SingleMode, IsCount, Occ, Expands> {\n const uniqueFields = [...new Set(fields)];\n const newBuilder = new QueryBuilder<\n T,\n K,\n SingleMode,\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = {\n ...this.queryOptions,\n select: uniqueFields as string[],\n };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = this.singleMode;\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n /**\n * Transforms our filter format to odata-query's expected format\n * - Arrays of operators are converted to AND conditions\n * - Single operator objects pass through as-is\n * - Shorthand values are handled by odata-query\n */\n private transformFilter(\n filter: Filter<ExtractSchemaFromOccurrence<Occ>>,\n ): QueryOptions<T>[\"filter\"] {\n if (typeof filter === \"string\") {\n // Raw string filters pass through\n return filter;\n }\n\n if (Array.isArray(filter)) {\n // Array of filters - odata-query handles this as implicit AND\n return filter.map((f) => this.transformFilter(f as any)) as any;\n }\n\n // Check if it's a logical filter (and/or/not)\n if (\"and\" in filter || \"or\" in filter || \"not\" in filter) {\n const result: any = {};\n if (\"and\" in filter && Array.isArray(filter.and)) {\n result.and = filter.and.map((f: any) => this.transformFilter(f));\n }\n if (\"or\" in filter && Array.isArray(filter.or)) {\n result.or = filter.or.map((f: any) => this.transformFilter(f));\n }\n if (\"not\" in filter && filter.not) {\n result.not = this.transformFilter(filter.not as any);\n }\n return result;\n }\n\n // Transform field filters\n const result: any = {};\n const andConditions: any[] = [];\n\n for (const [field, value] of Object.entries(filter)) {\n // Transform field name to FMFID if using entity IDs\n const fieldId = this.occurrence?.baseTable\n ? transformFieldName(field, this.occurrence.baseTable)\n : field;\n\n if (Array.isArray(value)) {\n // Array of operators - convert to AND conditions\n if (value.length === 1) {\n // Single operator in array - unwrap it\n result[fieldId] = value[0];\n } else {\n // Multiple operators - combine with AND\n // Create separate conditions for each operator\n for (const op of value) {\n andConditions.push({ [fieldId]: op });\n }\n }\n } else if (\n value &&\n typeof value === \"object\" &&\n !(value instanceof Date) &&\n !Array.isArray(value)\n ) {\n // Check if it's an operator object (has operator keys like eq, gt, etc.)\n const operatorKeys = [\n \"eq\",\n \"ne\",\n \"gt\",\n \"ge\",\n \"lt\",\n \"le\",\n \"contains\",\n \"startswith\",\n \"endswith\",\n \"in\",\n ];\n const isOperatorObject = operatorKeys.some((key) => key in value);\n\n if (isOperatorObject) {\n // Single operator object - pass through\n result[fieldId] = value;\n } else {\n // Regular object - might be nested filter, pass through\n result[fieldId] = value;\n }\n } else {\n // Primitive value (shorthand) - pass through\n result[fieldId] = value;\n }\n }\n\n // If we have AND conditions from arrays, combine them\n if (andConditions.length > 0) {\n if (Object.keys(result).length > 0) {\n // We have both regular fields and array-derived AND conditions\n // Combine everything with AND\n return { and: [...andConditions, result] };\n } else {\n // Only array-derived AND conditions\n return { and: andConditions };\n }\n }\n\n return result;\n }\n\n filter(\n filter: Filter<ExtractSchemaFromOccurrence<Occ>>,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n // Transform our filter format to odata-query's expected format\n this.queryOptions.filter = this.transformFilter(filter) as any;\n return this;\n }\n\n orderBy(\n orderBy: QueryOptions<T>[\"orderBy\"],\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n // Transform field names to FMFIDs if using entity IDs\n if (this.occurrence?.baseTable && orderBy) {\n if (Array.isArray(orderBy)) {\n this.queryOptions.orderBy = orderBy.map((field) =>\n transformOrderByField(String(field), this.occurrence!.baseTable),\n );\n } else {\n this.queryOptions.orderBy = transformOrderByField(\n String(orderBy),\n this.occurrence.baseTable,\n );\n }\n } else {\n this.queryOptions.orderBy = orderBy;\n }\n return this;\n }\n\n top(\n count: number,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n this.queryOptions.top = count;\n return this;\n }\n\n skip(\n count: number,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n this.queryOptions.skip = count;\n return this;\n }\n\n /**\n * Formats select fields for use in query strings.\n * - Transforms field names to FMFIDs if using entity IDs\n * - Wraps \"id\" fields in double quotes\n * - URL-encodes special characters but preserves spaces\n */\n private formatSelectFields(\n select: QueryOptions<any>[\"select\"],\n baseTable?: BaseTable<any, any, any, any>,\n ): string {\n if (!select) return \"\";\n const selectFieldsArray = Array.isArray(select) ? select : [select];\n\n // Transform to field IDs if using entity IDs\n const transformedFields = baseTable\n ? transformFieldNamesArray(\n selectFieldsArray.map((f) => String(f)),\n baseTable,\n )\n : selectFieldsArray.map((f) => String(f));\n\n return transformedFields\n .map((field) => {\n if (field === \"id\") return `\"id\"`;\n const encodedField = encodeURIComponent(String(field));\n return encodedField.replace(/%20/g, \" \");\n })\n .join(\",\");\n }\n\n /**\n * Builds expand validation configs from internal expand configurations.\n * These are used to validate expanded navigation properties.\n */\n private buildExpandValidationConfigs(\n configs: ExpandConfig[],\n ): import(\"../validation\").ExpandValidationConfig[] {\n return configs.map((config) => {\n // Look up target occurrence from navigation\n const targetOccurrence = this.occurrence?.navigation[config.relation];\n const targetSchema = targetOccurrence?.baseTable?.schema;\n\n // Extract selected fields from options\n const selectedFields = config.options?.select\n ? Array.isArray(config.options.select)\n ? config.options.select.map((f) => String(f))\n : [String(config.options.select)]\n : undefined;\n\n return {\n relation: config.relation,\n targetSchema: targetSchema,\n targetOccurrence: targetOccurrence,\n targetBaseTable: targetOccurrence?.baseTable,\n occurrence: targetOccurrence, // Add occurrence for transformation\n selectedFields: selectedFields,\n nestedExpands: undefined, // TODO: Handle nested expands if needed\n };\n });\n }\n\n /**\n * Builds OData expand query string from expand configurations.\n * Handles nested expands recursively.\n * Transforms relation names to FMTIDs if using entity IDs.\n */\n private buildExpandString(configs: ExpandConfig[]): string {\n if (configs.length === 0) {\n return \"\";\n }\n\n return configs\n .map((config) => {\n // Get target occurrence for this relation\n const targetOccurrence = this.occurrence?.navigation[config.relation];\n\n // When using entity IDs, use the target table's FMTID in the expand parameter\n // FileMaker expects FMTID in $expand when Prefer header is set\n const relationName =\n targetOccurrence && targetOccurrence.isUsingTableId()\n ? targetOccurrence.getTableId()\n : config.relation;\n\n if (!config.options || Object.keys(config.options).length === 0) {\n // Simple expand without options\n return relationName;\n }\n\n // Build query options for this expand\n const parts: string[] = [];\n\n if (config.options.select) {\n // Pass target base table for field transformation\n const selectFields = this.formatSelectFields(\n config.options.select,\n targetOccurrence?.baseTable,\n );\n parts.push(`$select=${selectFields}`);\n }\n\n if (config.options.filter) {\n // Filter should already be transformed by the nested builder\n // Use odata-query to build filter string\n const filterQuery = buildQuery({ filter: config.options.filter });\n const filterMatch = filterQuery.match(/\\$filter=([^&]+)/);\n if (filterMatch) {\n parts.push(`$filter=${filterMatch[1]}`);\n }\n }\n\n if (config.options.orderBy) {\n // OrderBy should already be transformed by the nested builder\n const orderByValue = Array.isArray(config.options.orderBy)\n ? config.options.orderBy.join(\",\")\n : config.options.orderBy;\n parts.push(`$orderby=${String(orderByValue)}`);\n }\n\n if (config.options.top !== undefined) {\n parts.push(`$top=${config.options.top}`);\n }\n\n if (config.options.skip !== undefined) {\n parts.push(`$skip=${config.options.skip}`);\n }\n\n // Handle nested expands (from expand configs)\n if (config.options.expand) {\n // If expand is a string, it's already been built\n if (typeof config.options.expand === \"string\") {\n parts.push(`$expand=${config.options.expand}`);\n }\n }\n\n if (parts.length === 0) {\n return relationName;\n }\n\n return `${relationName}(${parts.join(\";\")})`;\n })\n .join(\",\");\n }\n\n expand<\n Rel extends ExtractNavigationNames<Occ> | (string & {}),\n TargetOcc extends FindNavigationTarget<Occ, Rel> = FindNavigationTarget<\n Occ,\n Rel\n >,\n TargetSchema extends GetTargetSchemaType<Occ, Rel> = GetTargetSchemaType<\n Occ,\n Rel\n >,\n TargetSelected extends keyof TargetSchema = keyof TargetSchema,\n >(\n relation: Rel,\n callback?: (\n builder: QueryBuilder<\n TargetSchema,\n keyof TargetSchema,\n false,\n false,\n TargetOcc extends TableOccurrence<any, any, any, any>\n ? TargetOcc\n : undefined\n >,\n ) => QueryBuilder<\n WithSystemFields<TargetSchema>,\n TargetSelected,\n any,\n any,\n any\n >,\n ): QueryBuilder<\n T,\n Selected,\n SingleMode,\n IsCount,\n Occ,\n Expands & {\n [K in Rel]: { schema: TargetSchema; selected: TargetSelected };\n }\n > {\n // Look up target occurrence from navigation\n const targetOccurrence = this.occurrence?.navigation[relation as string];\n\n if (callback) {\n // Create a new QueryBuilder for the target occurrence\n const targetBuilder = new QueryBuilder<any>({\n occurrence: targetOccurrence,\n tableName: targetOccurrence?.name ?? (relation as string),\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n\n // Cast to the expected type for the callback\n // At runtime, the builder is untyped (any), but at compile-time we enforce proper types\n const typedBuilder = targetBuilder as QueryBuilder<\n TargetSchema,\n keyof TargetSchema,\n false,\n false,\n TargetOcc extends TableOccurrence<any, any, any, any>\n ? TargetOcc\n : undefined\n >;\n\n // Pass to callback and get configured builder\n const configuredBuilder = callback(typedBuilder);\n\n // Extract the builder's query options\n const expandOptions: Partial<QueryOptions<any>> = {\n ...configuredBuilder.queryOptions,\n };\n\n // If the configured builder has nested expands, we need to include them\n if (configuredBuilder.expandConfigs.length > 0) {\n // Build nested expand string from the configured builder's expand configs\n const nestedExpandString = this.buildExpandString(\n configuredBuilder.expandConfigs,\n );\n if (nestedExpandString) {\n // Add nested expand to options\n expandOptions.expand = nestedExpandString as any;\n }\n }\n\n const expandConfig: ExpandConfig = {\n relation: relation as string,\n options: expandOptions,\n };\n\n this.expandConfigs.push(expandConfig);\n } else {\n // Simple expand without callback\n this.expandConfigs.push({ relation: relation as string });\n }\n\n return this as any;\n }\n\n single(): QueryBuilder<T, Selected, \"exact\", IsCount, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n \"exact\",\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = \"exact\";\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n maybeSingle(): QueryBuilder<T, Selected, \"maybe\", IsCount, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n \"maybe\",\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = \"maybe\";\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n count(): QueryBuilder<T, Selected, SingleMode, true, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n SingleMode,\n true,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions, count: true };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = this.singleMode;\n newBuilder.isCountMode = true as true;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n async execute<EO extends ExecuteOptions>(\n options?: RequestInit & FFetchOptions & EO,\n ): Promise<\n Result<\n IsCount extends true\n ? number\n : SingleMode extends \"exact\"\n ? ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n >\n : SingleMode extends \"maybe\"\n ? ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n > | null\n : ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n >[]\n >\n > {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n const mergedOptions = this.mergeExecuteOptions(options);\n\n // Format select fields before building query\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryString = buildQuery(queryOptionsWithoutExpand);\n\n // Build custom expand string\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryString.includes(\"?\") ? \"&\" : \"?\";\n queryString = `${queryString}${separator}$expand=${expandString}`;\n }\n\n // Handle navigation from RecordBuilder\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let url: string;\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n } else {\n // Normal navigation: /sourceTable('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n }\n const result = await this.context._makeRequest(url, mergedOptions);\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n const stripped = this.stripODataAnnotationsIfNeeded(record, options);\n return { data: stripped as any, error: undefined };\n } else {\n const records = resp.value ?? [];\n const stripped = records.map((record: any) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as\n | (keyof T)[]\n | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n const stripped = validation.data\n ? this.stripODataAnnotationsIfNeeded(validation.data, options)\n : null;\n return { data: stripped as any, error: undefined };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n const stripped = validation.data.map((record) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Handle navigation from EntitySet (without record ID)\n if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n const stripped = this.stripODataAnnotationsIfNeeded(record, options);\n return { data: stripped as any, error: undefined };\n } else {\n const records = resp.value ?? [];\n const stripped = records.map((record: any) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as\n | (keyof T)[]\n | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n const stripped = validation.data\n ? this.stripODataAnnotationsIfNeeded(validation.data, options)\n : null;\n return { data: stripped as any, error: undefined };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n const stripped = validation.data.map((record) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Handle $count endpoint\n if (this.isCountMode) {\n const tableId = this.getTableId(mergedOptions.useEntityIds);\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${tableId}/$count${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n // OData returns count as a string, convert to number\n const count =\n typeof result.data === \"string\" ? Number(result.data) : result.data;\n return { data: count as number, error: undefined } as any;\n }\n\n const tableId = this.getTableId(mergedOptions.useEntityIds);\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${tableId}${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n const stripped = this.stripODataAnnotationsIfNeeded(record, options);\n return { data: stripped as any, error: undefined };\n } else {\n // Handle list response structure\n const records = resp.value ?? [];\n const stripped = records.map((record: any) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as (keyof T)[] | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n const stripped = validation.data\n ? this.stripODataAnnotationsIfNeeded(validation.data, options)\n : null;\n return {\n data: stripped as any,\n error: undefined,\n };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n const stripped = validation.data.map((record) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return {\n data: stripped as any,\n error: undefined,\n };\n }\n }\n\n getQueryString(): string {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n // Format select fields before building query - buildQuery treats & as separator,\n // so we need to pre-encode special characters. buildQuery preserves encoded values.\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryParams = buildQuery(queryOptionsWithoutExpand);\n\n // Post-process: buildQuery encodes spaces as %20, but we want to preserve spaces\n // Replace %20 with spaces in the $select part\n if (this.queryOptions.select) {\n queryParams = queryParams.replace(\n /\\$select=([^&]*)/,\n (match, selectValue) => {\n return `$select=${selectValue.replace(/%20/g, \" \")}`;\n },\n );\n }\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryParams.includes(\"?\") ? \"&\" : \"?\";\n queryParams = `${queryParams}${separator}$expand=${expandString}`;\n }\n\n // Handle navigation from RecordBuilder (with record ID)\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let path: string;\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n path = `/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}`;\n } else {\n // Normal navigation: /sourceTableName('recordId')/relationName\n path = `/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}`;\n }\n // Append query params if any exist\n return queryParams ? `${path}${queryParams}` : path;\n }\n\n // Handle navigation from EntitySet (without record ID)\n if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let path: string;\n if (this.navigateBasePath) {\n // Chained navigation: /basePath/relationName (basePath already includes intermediate segments)\n path = `/${this.navigateBasePath}/${this.navigateRelation}`;\n } else {\n // Single navigation: /sourceTableName/relationName\n path = `/${this.navigateSourceTableName}/${this.navigateRelation}`;\n }\n // Append query params if any exist\n return queryParams ? `${path}${queryParams}` : path;\n }\n\n // Default case: return table name with query params\n return `/${this.tableName}${queryParams}`;\n }\n\n getRequestConfig(): { method: string; url: string; body?: any } {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n // Format select fields before building query\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryString = buildQuery(queryOptionsWithoutExpand);\n\n // Build custom expand string\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryString.includes(\"?\") ? \"&\" : \"?\";\n queryString = `${queryString}${separator}$expand=${expandString}`;\n }\n\n let url: string;\n\n // Handle navigation from RecordBuilder (with record ID)\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n } else {\n // Normal navigation: /sourceTable('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n }\n } else if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n // Handle navigation from EntitySet (without record ID)\n if (this.navigateBasePath) {\n // Chained navigation: /basePath/relationName (basePath already includes intermediate segments)\n url = `/${this.databaseName}/${this.navigateBasePath}/${this.navigateRelation}${queryString}`;\n } else {\n // Single navigation: /sourceTableName/relationName\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`;\n }\n } else if (this.isCountMode) {\n url = `/${this.databaseName}/${this.tableName}/$count${queryString}`;\n } else {\n url = `/${this.databaseName}/${this.tableName}${queryString}`;\n }\n\n return {\n method: \"GET\",\n url,\n };\n }\n\n toRequest(baseUrl: string): Request {\n const config = this.getRequestConfig();\n const fullUrl = `${baseUrl}${config.url}`;\n\n return new Request(fullUrl, {\n method: config.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n });\n }\n\n async processResponse(\n response: Response,\n options?: ExecuteOptions,\n ): Promise<\n Result<QueryReturnType<T, Selected, SingleMode, IsCount, Expands>>\n > {\n // Handle 204 No Content (shouldn't happen for queries, but handle it gracefully)\n if (response.status === 204) {\n // Return empty list for list queries, null for single queries\n if (this.singleMode !== false) {\n if (this.singleMode === \"maybe\") {\n return { data: null as any, error: undefined };\n }\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: [] as any, error: undefined };\n }\n\n // Parse the response body\n let rawData;\n try {\n rawData = await response.json();\n } catch (err) {\n // Check if it's an empty body error (common with 204 responses)\n if (err instanceof SyntaxError && response.status === 204) {\n // Handled above, but just in case\n return { data: [] as any, error: undefined };\n }\n return {\n data: undefined,\n error: {\n name: \"ResponseParseError\",\n message: `Failed to parse response JSON: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n timestamp: new Date(),\n } as any,\n };\n }\n\n if (!rawData) {\n return {\n data: undefined,\n error: {\n name: \"ResponseError\",\n message: \"Response body was empty or null\",\n timestamp: new Date(),\n } as any,\n };\n }\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = options?.useEntityIds ?? this.databaseUseEntityIds;\n\n let transformedData = rawData;\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n transformedData = transformResponseFields(\n rawData,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = transformedData as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n const stripped = this.stripODataAnnotationsIfNeeded(record, options);\n return { data: stripped as any, error: undefined };\n } else {\n // Handle list response structure\n const records = resp.value ?? [];\n const stripped = records.map((record: any) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as (keyof T)[] | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n // Single mode (one() or oneOrNull())\n const validation = await validateSingleResponse<T>(\n transformedData,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n\n if (validation.data === null) {\n return { data: null as any, error: undefined };\n }\n\n const stripped = this.stripODataAnnotationsIfNeeded(\n validation.data,\n options,\n );\n return { data: stripped as any, error: undefined };\n }\n\n // List mode\n const validation = await validateListResponse<T>(\n transformedData,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n\n const stripped = validation.data.map((record) =>\n this.stripODataAnnotationsIfNeeded(record, options),\n );\n return { data: stripped as any, error: undefined };\n }\n}\n"],"names":["result","response","shouldUseIds","expandValidationConfigs","schema","selectedFields","tableId","stripped","validation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-builder.js","sources":["../../../src/client/query-builder.ts"],"sourcesContent":["import { QueryOptions } from \"odata-query\";\nimport buildQuery from \"odata-query\";\nimport type {\n ExecutionContext,\n ExecutableBuilder,\n WithSystemFields,\n Result,\n InferSchemaType,\n ExecuteOptions,\n ConditionallyWithODataAnnotations,\n ExtractSchemaFromOccurrence,\n} from \"../types\";\nimport { getAcceptHeader } from \"../types\";\nimport type { Filter } from \"../filter-types\";\nimport type { TableOccurrence } from \"./table-occurrence\";\nimport type { BaseTable } from \"./base-table\";\nimport { validateListResponse, validateSingleResponse } from \"../validation\";\nimport { RecordCountMismatchError } from \"../errors\";\nimport { type FFetchOptions } from \"@fetchkit/ffetch\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n transformFieldNamesArray,\n transformFieldName,\n transformOrderByField,\n transformResponseFields,\n getTableIdentifiers,\n} from \"../transform\";\nimport { safeJsonParse } from \"./sanitize-json\";\n\n/**\n * Default maximum number of records to return in a list query.\n * This prevents stack overflow issues with large datasets while still\n * allowing substantial data retrieval. Users can override with .top().\n */\nconst DEFAULT_TOP = 1000;\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 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 ? Nav[Name]\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, any>,\n any,\n any,\n any\n >\n : TableOccurrence<\n BaseTable<Record<string, StandardSchemaV1>, any, any, 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, any, any>]\n ? [S] extends [Record<string, StandardSchemaV1>]\n ? InferSchemaType<S>\n : Record<string, any>\n : Record<string, any>\n : Record<string, any>;\n\n// Internal type for expand configuration\ntype ExpandConfig = {\n relation: string;\n options?: Partial<QueryOptions<any>>;\n};\n\n// Type to represent expanded relations\nexport type ExpandedRelations = Record<string, { schema: any; selected: any }>;\n\nexport type QueryReturnType<\n T extends Record<string, any>,\n Selected extends keyof T,\n SingleMode extends \"exact\" | \"maybe\" | false,\n IsCount extends boolean,\n Expands extends ExpandedRelations,\n> = IsCount extends true\n ? number\n : SingleMode extends \"exact\"\n ? Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n }\n : SingleMode extends \"maybe\"\n ?\n | (Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n })\n | null\n : (Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n })[];\n\nexport class QueryBuilder<\n T extends Record<string, any>,\n Selected extends keyof T = keyof T,\n SingleMode extends \"exact\" | \"maybe\" | false = false,\n IsCount extends boolean = false,\n Occ extends TableOccurrence<any, any, any, any> | undefined = undefined,\n Expands extends ExpandedRelations = {},\n> implements\n ExecutableBuilder<\n QueryReturnType<T, Selected, SingleMode, IsCount, Expands>\n >\n{\n private queryOptions: Partial<QueryOptions<T>> = {};\n private expandConfigs: ExpandConfig[] = [];\n private singleMode: SingleMode = false as SingleMode;\n private isCountMode = false as IsCount;\n private occurrence?: Occ;\n private tableName: string;\n private databaseName: string;\n private context: ExecutionContext;\n private isNavigate?: boolean;\n private navigateRecordId?: string | number;\n private navigateRelation?: string;\n private navigateSourceTableName?: string;\n private navigateBaseRelation?: string;\n private navigateBasePath?: string; // Full base path for chained entity set navigations\n private databaseUseEntityIds: boolean;\n\n constructor(config: {\n occurrence?: Occ;\n tableName: string;\n databaseName: string;\n context: ExecutionContext;\n databaseUseEntityIds?: boolean;\n }) {\n this.occurrence = config.occurrence;\n this.tableName = config.tableName;\n this.databaseName = config.databaseName;\n this.context = config.context;\n this.databaseUseEntityIds = config.databaseUseEntityIds ?? false;\n }\n\n /**\n * Helper to merge database-level useEntityIds with per-request options\n */\n private mergeExecuteOptions(\n options?: RequestInit & FFetchOptions & ExecuteOptions,\n ): RequestInit & FFetchOptions & { useEntityIds?: boolean } {\n // If useEntityIds is not set in options, use the database-level setting\n return {\n ...options,\n useEntityIds:\n options?.useEntityIds === undefined\n ? this.databaseUseEntityIds\n : options.useEntityIds,\n };\n }\n\n /**\n * Gets the table ID (FMTID) if using entity IDs, otherwise returns the table name\n * @param useEntityIds - Optional override for entity ID usage\n */\n private getTableId(useEntityIds?: boolean): string {\n if (!this.occurrence) {\n return this.tableName;\n }\n\n const contextDefault = this.context._getUseEntityIds?.() ?? false;\n const shouldUseIds = useEntityIds ?? contextDefault;\n\n if (shouldUseIds) {\n const identifiers = getTableIdentifiers(this.occurrence);\n if (!identifiers.id) {\n throw new Error(\n `useEntityIds is true but TableOccurrence \"${identifiers.name}\" does not have an fmtId defined`,\n );\n }\n return identifiers.id;\n }\n\n return this.occurrence.getTableName();\n }\n\n select<K extends keyof T>(\n ...fields: K[]\n ): QueryBuilder<T, K, SingleMode, IsCount, Occ, Expands> {\n const uniqueFields = [...new Set(fields)];\n const newBuilder = new QueryBuilder<\n T,\n K,\n SingleMode,\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = {\n ...this.queryOptions,\n select: uniqueFields as string[],\n };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = this.singleMode;\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n /**\n * Transforms our filter format to odata-query's expected format\n * - Arrays of operators are converted to AND conditions\n * - Single operator objects pass through as-is\n * - Shorthand values are handled by odata-query\n */\n private transformFilter(\n filter: Filter<ExtractSchemaFromOccurrence<Occ>>,\n ): QueryOptions<T>[\"filter\"] {\n if (typeof filter === \"string\") {\n // Raw string filters pass through\n return filter;\n }\n\n if (Array.isArray(filter)) {\n // Array of filters - odata-query handles this as implicit AND\n return filter.map((f) => this.transformFilter(f as any)) as any;\n }\n\n // Check if it's a logical filter (and/or/not)\n if (\"and\" in filter || \"or\" in filter || \"not\" in filter) {\n const result: any = {};\n if (\"and\" in filter && Array.isArray(filter.and)) {\n result.and = filter.and.map((f: any) => this.transformFilter(f));\n }\n if (\"or\" in filter && Array.isArray(filter.or)) {\n result.or = filter.or.map((f: any) => this.transformFilter(f));\n }\n if (\"not\" in filter && filter.not) {\n result.not = this.transformFilter(filter.not as any);\n }\n return result;\n }\n\n // Transform field filters\n const result: any = {};\n const andConditions: any[] = [];\n\n for (const [field, value] of Object.entries(filter)) {\n // Transform field name to FMFID if using entity IDs AND the feature is enabled\n const shouldTransform =\n this.occurrence?.baseTable && this.databaseUseEntityIds;\n const fieldId = shouldTransform\n ? transformFieldName(field, this.occurrence!.baseTable)\n : field;\n\n if (Array.isArray(value)) {\n // Array of operators - convert to AND conditions\n if (value.length === 1) {\n // Single operator in array - unwrap it\n result[fieldId] = value[0];\n } else {\n // Multiple operators - combine with AND\n // Create separate conditions for each operator\n for (const op of value) {\n andConditions.push({ [fieldId]: op });\n }\n }\n } else if (\n value &&\n typeof value === \"object\" &&\n !(value instanceof Date) &&\n !Array.isArray(value)\n ) {\n // Check if it's an operator object (has operator keys like eq, gt, etc.)\n const operatorKeys = [\n \"eq\",\n \"ne\",\n \"gt\",\n \"ge\",\n \"lt\",\n \"le\",\n \"contains\",\n \"startswith\",\n \"endswith\",\n \"in\",\n ];\n const isOperatorObject = operatorKeys.some((key) => key in value);\n\n if (isOperatorObject) {\n // Single operator object - pass through\n result[fieldId] = value;\n } else {\n // Regular object - might be nested filter, pass through\n result[fieldId] = value;\n }\n } else {\n // Primitive value (shorthand) - pass through\n result[fieldId] = value;\n }\n }\n\n // If we have AND conditions from arrays, combine them\n if (andConditions.length > 0) {\n if (Object.keys(result).length > 0) {\n // We have both regular fields and array-derived AND conditions\n // Combine everything with AND\n return { and: [...andConditions, result] };\n } else {\n // Only array-derived AND conditions\n return { and: andConditions };\n }\n }\n\n return result;\n }\n\n filter(\n filter: Filter<ExtractSchemaFromOccurrence<Occ>>,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n // Transform our filter format to odata-query's expected format\n this.queryOptions.filter = this.transformFilter(filter) as any;\n return this;\n }\n\n orderBy(\n orderBy: QueryOptions<T>[\"orderBy\"],\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n // Transform field names to FMFIDs if using entity IDs\n if (this.occurrence?.baseTable && orderBy) {\n if (Array.isArray(orderBy)) {\n this.queryOptions.orderBy = orderBy.map((field) =>\n transformOrderByField(String(field), this.occurrence!.baseTable),\n );\n } else {\n this.queryOptions.orderBy = transformOrderByField(\n String(orderBy),\n this.occurrence.baseTable,\n );\n }\n } else {\n this.queryOptions.orderBy = orderBy;\n }\n return this;\n }\n\n top(\n count: number,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n this.queryOptions.top = count;\n return this;\n }\n\n skip(\n count: number,\n ): QueryBuilder<T, Selected, SingleMode, IsCount, Occ, Expands> {\n this.queryOptions.skip = count;\n return this;\n }\n\n /**\n * Formats select fields for use in query strings.\n * - Transforms field names to FMFIDs if using entity IDs\n * - Wraps \"id\" fields in double quotes\n * - URL-encodes special characters but preserves spaces\n */\n private formatSelectFields(\n select: QueryOptions<any>[\"select\"],\n baseTable?: BaseTable<any, any, any, any>,\n useEntityIds?: boolean,\n ): string {\n if (!select) return \"\";\n const selectFieldsArray = Array.isArray(select) ? select : [select];\n\n // Transform to field IDs if using entity IDs AND the feature is enabled\n const shouldTransform =\n baseTable && (useEntityIds ?? this.databaseUseEntityIds);\n const transformedFields = shouldTransform\n ? transformFieldNamesArray(\n selectFieldsArray.map((f) => String(f)),\n baseTable,\n )\n : selectFieldsArray.map((f) => String(f));\n\n return transformedFields\n .map((field) => {\n if (field === \"id\") return `\"id\"`;\n const encodedField = encodeURIComponent(String(field));\n return encodedField.replace(/%20/g, \" \");\n })\n .join(\",\");\n }\n\n /**\n * Builds expand validation configs from internal expand configurations.\n * These are used to validate expanded navigation properties.\n */\n private buildExpandValidationConfigs(\n configs: ExpandConfig[],\n ): import(\"../validation\").ExpandValidationConfig[] {\n return configs.map((config) => {\n // Look up target occurrence from navigation\n const targetOccurrence = this.occurrence?.navigation[config.relation];\n const targetSchema = targetOccurrence?.baseTable?.schema;\n\n // Extract selected fields from options\n const selectedFields = config.options?.select\n ? Array.isArray(config.options.select)\n ? config.options.select.map((f) => String(f))\n : [String(config.options.select)]\n : undefined;\n\n return {\n relation: config.relation,\n targetSchema: targetSchema,\n targetOccurrence: targetOccurrence,\n targetBaseTable: targetOccurrence?.baseTable,\n occurrence: targetOccurrence, // Add occurrence for transformation\n selectedFields: selectedFields,\n nestedExpands: undefined, // TODO: Handle nested expands if needed\n };\n });\n }\n\n /**\n * Builds OData expand query string from expand configurations.\n * Handles nested expands recursively.\n * Transforms relation names to FMTIDs if using entity IDs.\n */\n private buildExpandString(configs: ExpandConfig[]): string {\n if (configs.length === 0) {\n return \"\";\n }\n\n return configs\n .map((config) => {\n // Get target occurrence for this relation\n const targetOccurrence = this.occurrence?.navigation[config.relation];\n\n // When using entity IDs, use the target table's FMTID in the expand parameter\n // FileMaker expects FMTID in $expand when Prefer header is set\n // Only use FMTID if databaseUseEntityIds is enabled\n const shouldUseTableId =\n this.databaseUseEntityIds && targetOccurrence?.isUsingTableId();\n const relationName = shouldUseTableId\n ? targetOccurrence!.getTableId()\n : config.relation;\n\n if (!config.options || Object.keys(config.options).length === 0) {\n // Simple expand without options\n return relationName;\n }\n\n // Build query options for this expand\n const parts: string[] = [];\n\n if (config.options.select) {\n // Pass target base table for field transformation\n const selectFields = this.formatSelectFields(\n config.options.select,\n targetOccurrence?.baseTable,\n );\n parts.push(`$select=${selectFields}`);\n }\n\n if (config.options.filter) {\n // Filter should already be transformed by the nested builder\n // Use odata-query to build filter string\n const filterQuery = buildQuery({ filter: config.options.filter });\n const filterMatch = filterQuery.match(/\\$filter=([^&]+)/);\n if (filterMatch) {\n parts.push(`$filter=${filterMatch[1]}`);\n }\n }\n\n if (config.options.orderBy) {\n // OrderBy should already be transformed by the nested builder\n const orderByValue = Array.isArray(config.options.orderBy)\n ? config.options.orderBy.join(\",\")\n : config.options.orderBy;\n parts.push(`$orderby=${String(orderByValue)}`);\n }\n\n if (config.options.top !== undefined) {\n parts.push(`$top=${config.options.top}`);\n }\n\n if (config.options.skip !== undefined) {\n parts.push(`$skip=${config.options.skip}`);\n }\n\n // Handle nested expands (from expand configs)\n if (config.options.expand) {\n // If expand is a string, it's already been built\n if (typeof config.options.expand === \"string\") {\n parts.push(`$expand=${config.options.expand}`);\n }\n }\n\n if (parts.length === 0) {\n return relationName;\n }\n\n return `${relationName}(${parts.join(\";\")})`;\n })\n .join(\",\");\n }\n\n expand<\n Rel extends ExtractNavigationNames<Occ> | (string & {}),\n TargetOcc extends FindNavigationTarget<Occ, Rel> = FindNavigationTarget<\n Occ,\n Rel\n >,\n TargetSchema extends GetTargetSchemaType<Occ, Rel> = GetTargetSchemaType<\n Occ,\n Rel\n >,\n TargetSelected extends keyof TargetSchema = keyof TargetSchema,\n >(\n relation: Rel,\n callback?: (\n builder: QueryBuilder<\n TargetSchema,\n keyof TargetSchema,\n false,\n false,\n TargetOcc extends TableOccurrence<any, any, any, any>\n ? TargetOcc\n : undefined\n >,\n ) => QueryBuilder<\n WithSystemFields<TargetSchema>,\n TargetSelected,\n any,\n any,\n any\n >,\n ): QueryBuilder<\n T,\n Selected,\n SingleMode,\n IsCount,\n Occ,\n Expands & {\n [K in Rel]: { schema: TargetSchema; selected: TargetSelected };\n }\n > {\n // Look up target occurrence from navigation\n const targetOccurrence = this.occurrence?.navigation[relation as string];\n\n // Helper function to get defaultSelect fields from target occurrence\n const getDefaultSelectFields = (): string[] | undefined => {\n if (!targetOccurrence) return undefined;\n const defaultSelect = targetOccurrence.defaultSelect;\n if (defaultSelect === \"schema\") {\n const schema = targetOccurrence.baseTable?.schema;\n if (schema) {\n return [...new Set(Object.keys(schema))];\n }\n } else if (Array.isArray(defaultSelect)) {\n return [...new Set(defaultSelect)];\n }\n // If \"all\", return undefined (no select restriction)\n return undefined;\n };\n\n if (callback) {\n // Create a new QueryBuilder for the target occurrence\n const targetBuilder = new QueryBuilder<any>({\n occurrence: targetOccurrence,\n tableName: targetOccurrence?.name ?? (relation as string),\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n\n // Cast to the expected type for the callback\n // At runtime, the builder is untyped (any), but at compile-time we enforce proper types\n const typedBuilder = targetBuilder as QueryBuilder<\n TargetSchema,\n keyof TargetSchema,\n false,\n false,\n TargetOcc extends TableOccurrence<any, any, any, any>\n ? TargetOcc\n : undefined\n >;\n\n // Pass to callback and get configured builder\n const configuredBuilder = callback(typedBuilder);\n\n // Extract the builder's query options\n const expandOptions: Partial<QueryOptions<any>> = {\n ...configuredBuilder.queryOptions,\n };\n\n // If callback didn't provide select, apply defaultSelect from target occurrence\n if (!expandOptions.select) {\n const defaultFields = getDefaultSelectFields();\n if (defaultFields) {\n expandOptions.select = defaultFields;\n }\n }\n\n // If the configured builder has nested expands, we need to include them\n if (configuredBuilder.expandConfigs.length > 0) {\n // Build nested expand string from the configured builder's expand configs\n const nestedExpandString = this.buildExpandString(\n configuredBuilder.expandConfigs,\n );\n if (nestedExpandString) {\n // Add nested expand to options\n expandOptions.expand = nestedExpandString as any;\n }\n }\n\n const expandConfig: ExpandConfig = {\n relation: relation as string,\n options: expandOptions,\n };\n\n this.expandConfigs.push(expandConfig);\n } else {\n // Simple expand without callback - apply defaultSelect if available\n const defaultFields = getDefaultSelectFields();\n if (defaultFields) {\n this.expandConfigs.push({\n relation: relation as string,\n options: { select: defaultFields },\n });\n } else {\n this.expandConfigs.push({ relation: relation as string });\n }\n }\n\n return this as any;\n }\n\n single(): QueryBuilder<T, Selected, \"exact\", IsCount, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n \"exact\",\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = \"exact\";\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n maybeSingle(): QueryBuilder<T, Selected, \"maybe\", IsCount, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n \"maybe\",\n IsCount,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = \"maybe\";\n newBuilder.isCountMode = this.isCountMode;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n count(): QueryBuilder<T, Selected, SingleMode, true, Occ, Expands> {\n const newBuilder = new QueryBuilder<\n T,\n Selected,\n SingleMode,\n true,\n Occ,\n Expands\n >({\n occurrence: this.occurrence,\n tableName: this.tableName,\n databaseName: this.databaseName,\n context: this.context,\n databaseUseEntityIds: this.databaseUseEntityIds,\n });\n newBuilder.queryOptions = { ...this.queryOptions, count: true };\n newBuilder.expandConfigs = [...this.expandConfigs];\n newBuilder.singleMode = this.singleMode;\n newBuilder.isCountMode = true as true;\n // Preserve navigation metadata\n newBuilder.isNavigate = this.isNavigate;\n newBuilder.navigateRecordId = this.navigateRecordId;\n newBuilder.navigateRelation = this.navigateRelation;\n newBuilder.navigateSourceTableName = this.navigateSourceTableName;\n newBuilder.navigateBaseRelation = this.navigateBaseRelation;\n return newBuilder;\n }\n\n async execute<EO extends ExecuteOptions>(\n options?: RequestInit & FFetchOptions & EO,\n ): Promise<\n Result<\n IsCount extends true\n ? number\n : SingleMode extends \"exact\"\n ? ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n >\n : SingleMode extends \"maybe\"\n ? ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n > | null\n : ConditionallyWithODataAnnotations<\n Pick<T, Selected> & {\n [K in keyof Expands]: Pick<\n Expands[K][\"schema\"],\n Expands[K][\"selected\"]\n >[];\n },\n EO[\"includeODataAnnotations\"] extends true ? true : false\n >[]\n >\n > {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n const mergedOptions = this.mergeExecuteOptions(options);\n\n // Format select fields before building query\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryString = buildQuery(queryOptionsWithoutExpand);\n\n // Build custom expand string\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryString.includes(\"?\") ? \"&\" : \"?\";\n queryString = `${queryString}${separator}$expand=${expandString}`;\n }\n\n // Handle navigation from RecordBuilder\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let url: string;\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n } else {\n // Normal navigation: /sourceTable('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n }\n const result = await this.context._makeRequest(url, mergedOptions);\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n const records = resp.value ?? [];\n const stripped = records.map((record: any) => record);\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as\n | (keyof T)[]\n | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n }\n }\n\n // Handle navigation from EntitySet (without record ID)\n if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n const records = resp.value ?? [];\n const stripped = records.map((record: any) => record);\n return { data: stripped as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as\n | (keyof T)[]\n | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return { data: validation.data as any, error: undefined };\n }\n }\n\n // Handle $count endpoint\n if (this.isCountMode) {\n const tableId = this.getTableId(mergedOptions.useEntityIds);\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${tableId}/$count${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n // OData returns count as a string, convert to number\n const count =\n typeof result.data === \"string\" ? Number(result.data) : result.data;\n return { data: count as number, error: undefined } as any;\n }\n\n const tableId = this.getTableId(mergedOptions.useEntityIds);\n const result = await this.context._makeRequest(\n `/${this.databaseName}/${tableId}${queryString}`,\n mergedOptions,\n );\n\n if (result.error) {\n return { data: undefined, error: result.error };\n }\n\n let response = result.data;\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = mergedOptions.useEntityIds ?? false;\n\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n response = transformResponseFields(\n response,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = response as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n // Handle list response structure\n const records = resp.value ?? [];\n return { data: records as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as (keyof T)[] | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n const validation = await validateSingleResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return {\n data: validation.data as any,\n error: undefined,\n };\n } else {\n const validation = await validateListResponse<T>(\n response,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n return {\n data: validation.data as any,\n error: undefined,\n };\n }\n }\n\n getQueryString(): string {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n // Format select fields before building query - buildQuery treats & as separator,\n // so we need to pre-encode special characters. buildQuery preserves encoded values.\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryParams = buildQuery(queryOptionsWithoutExpand);\n\n // Post-process: buildQuery encodes spaces as %20, but we want to preserve spaces\n // Replace %20 with spaces in the $select part\n if (this.queryOptions.select) {\n queryParams = queryParams.replace(\n /\\$select=([^&]*)/,\n (match, selectValue) => {\n return `$select=${selectValue.replace(/%20/g, \" \")}`;\n },\n );\n }\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryParams.includes(\"?\") ? \"&\" : \"?\";\n queryParams = `${queryParams}${separator}$expand=${expandString}`;\n }\n\n // Handle navigation from RecordBuilder (with record ID)\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let path: string;\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n path = `/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}`;\n } else {\n // Normal navigation: /sourceTableName('recordId')/relationName\n path = `/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}`;\n }\n // Append query params if any exist\n return queryParams ? `${path}${queryParams}` : path;\n }\n\n // Handle navigation from EntitySet (without record ID)\n if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n let path: string;\n if (this.navigateBasePath) {\n // Chained navigation: /basePath/relationName (basePath already includes intermediate segments)\n path = `/${this.navigateBasePath}/${this.navigateRelation}`;\n } else {\n // Single navigation: /sourceTableName/relationName\n path = `/${this.navigateSourceTableName}/${this.navigateRelation}`;\n }\n // Append query params if any exist\n return queryParams ? `${path}${queryParams}` : path;\n }\n\n // Default case: return table ID (respects entity ID settings) with query params\n const tableId = this.getTableId(this.databaseUseEntityIds);\n return `/${tableId}${queryParams}`;\n }\n\n getRequestConfig(): { method: string; url: string; body?: any } {\n // Build query without expand (we'll add it manually)\n const queryOptionsWithoutExpand = { ...this.queryOptions };\n delete queryOptionsWithoutExpand.expand;\n\n // Format select fields before building query\n if (queryOptionsWithoutExpand.select) {\n queryOptionsWithoutExpand.select = this.formatSelectFields(\n queryOptionsWithoutExpand.select,\n this.occurrence?.baseTable,\n ) as any;\n }\n\n let queryString = buildQuery(queryOptionsWithoutExpand);\n\n // Build custom expand string\n const expandString = this.buildExpandString(this.expandConfigs);\n if (expandString) {\n const separator = queryString.includes(\"?\") ? \"&\" : \"?\";\n queryString = `${queryString}${separator}$expand=${expandString}`;\n }\n\n let url: string;\n\n // Handle navigation from RecordBuilder (with record ID)\n if (\n this.isNavigate &&\n this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n if (this.navigateBaseRelation) {\n // Navigation from a navigated EntitySet: /sourceTable/baseRelation('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateBaseRelation}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n } else {\n // Normal navigation: /sourceTable('recordId')/relation\n url = `/${this.databaseName}/${this.navigateSourceTableName}('${this.navigateRecordId}')/${this.navigateRelation}${queryString}`;\n }\n } else if (\n this.isNavigate &&\n !this.navigateRecordId &&\n this.navigateRelation &&\n this.navigateSourceTableName\n ) {\n // Handle navigation from EntitySet (without record ID)\n if (this.navigateBasePath) {\n // Chained navigation: /basePath/relationName (basePath already includes intermediate segments)\n url = `/${this.databaseName}/${this.navigateBasePath}/${this.navigateRelation}${queryString}`;\n } else {\n // Single navigation: /sourceTableName/relationName\n url = `/${this.databaseName}/${this.navigateSourceTableName}/${this.navigateRelation}${queryString}`;\n }\n } else if (this.isCountMode) {\n // Use getTableId to respect entity ID settings (for batch operations)\n const tableId = this.getTableId(this.databaseUseEntityIds);\n url = `/${this.databaseName}/${tableId}/$count${queryString}`;\n } else {\n // Use getTableId to respect entity ID settings (for batch operations)\n const tableId = this.getTableId(this.databaseUseEntityIds);\n url = `/${this.databaseName}/${tableId}${queryString}`;\n }\n\n return {\n method: \"GET\",\n url,\n };\n }\n\n toRequest(baseUrl: string, options?: ExecuteOptions): Request {\n const config = this.getRequestConfig();\n const fullUrl = `${baseUrl}${config.url}`;\n\n return new Request(fullUrl, {\n method: config.method,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: getAcceptHeader(options?.includeODataAnnotations),\n },\n });\n }\n\n async processResponse(\n response: Response,\n options?: ExecuteOptions,\n ): Promise<\n Result<QueryReturnType<T, Selected, SingleMode, IsCount, Expands>>\n > {\n // Handle 204 No Content (shouldn't happen for queries, but handle it gracefully)\n if (response.status === 204) {\n // Return empty list for list queries, null for single queries\n if (this.singleMode !== false) {\n if (this.singleMode === \"maybe\") {\n return { data: null as any, error: undefined };\n }\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: [] as any, error: undefined };\n }\n\n // Parse the response body (using safeJsonParse to handle FileMaker's invalid JSON with unquoted ? values)\n let rawData;\n try {\n rawData = await safeJsonParse(response);\n } catch (err) {\n // Check if it's an empty body error (common with 204 responses)\n if (err instanceof SyntaxError && response.status === 204) {\n // Handled above, but just in case\n return { data: [] as any, error: undefined };\n }\n return {\n data: undefined,\n error: {\n name: \"ResponseParseError\",\n message: `Failed to parse response JSON: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n timestamp: new Date(),\n } as any,\n };\n }\n\n if (!rawData) {\n return {\n data: undefined,\n error: {\n name: \"ResponseError\",\n message: \"Response body was empty or null\",\n timestamp: new Date(),\n } as any,\n };\n }\n\n // Transform response field IDs back to names if using entity IDs\n // Only transform if useEntityIds resolves to true (respects per-request override)\n const shouldUseIds = options?.useEntityIds ?? this.databaseUseEntityIds;\n\n let transformedData = rawData;\n if (this.occurrence?.baseTable && shouldUseIds) {\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n transformedData = transformResponseFields(\n rawData,\n this.occurrence.baseTable,\n expandValidationConfigs,\n );\n }\n\n // Skip validation if requested\n if (options?.skipValidation === true) {\n const resp = transformedData as any;\n if (this.singleMode !== false) {\n const records = resp.value ?? [resp];\n const count = Array.isArray(records) ? records.length : 1;\n\n if (count > 1) {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\n this.singleMode === \"exact\" ? \"one\" : \"at-most-one\",\n count,\n ),\n };\n }\n\n if (count === 0) {\n if (this.singleMode === \"exact\") {\n return {\n data: undefined,\n error: new RecordCountMismatchError(\"one\", 0),\n };\n }\n return { data: null as any, error: undefined };\n }\n\n const record = Array.isArray(records) ? records[0] : records;\n return { data: record as any, error: undefined };\n } else {\n // Handle list response structure\n const records = resp.value ?? [];\n return { data: records as any, error: undefined };\n }\n }\n\n // Get schema from occurrence if available\n const schema = this.occurrence?.baseTable?.schema;\n const selectedFields = this.queryOptions.select as (keyof T)[] | undefined;\n const expandValidationConfigs = this.buildExpandValidationConfigs(\n this.expandConfigs,\n );\n\n if (this.singleMode !== false) {\n // Single mode (one() or oneOrNull())\n const validation = await validateSingleResponse<T>(\n transformedData,\n schema,\n selectedFields,\n expandValidationConfigs,\n this.singleMode,\n );\n\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n\n if (validation.data === null) {\n return { data: null as any, error: undefined };\n }\n\n return { data: validation.data as any, error: undefined };\n }\n\n // List mode\n const validation = await validateListResponse<T>(\n transformedData,\n schema,\n selectedFields,\n expandValidationConfigs,\n );\n\n if (!validation.valid) {\n return { data: undefined, error: validation.error };\n }\n\n return { data: validation.data as any, error: undefined };\n }\n}\n"],"names":["result","_a","response","shouldUseIds","expandValidationConfigs","schema","selectedFields","tableId","validation"],"mappings":"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"}
|
|
@@ -109,10 +109,6 @@ export declare class RecordBuilder<T extends Record<string, any>, IsSingleField
|
|
|
109
109
|
* Builds the complete query string including $select and $expand parameters.
|
|
110
110
|
*/
|
|
111
111
|
private buildQueryString;
|
|
112
|
-
/**
|
|
113
|
-
* Helper to conditionally strip OData annotations based on options
|
|
114
|
-
*/
|
|
115
|
-
private stripODataAnnotationsIfNeeded;
|
|
116
112
|
execute<EO extends ExecuteOptions>(options?: RequestInit & FFetchOptions & EO): Promise<Result<ConditionallyWithODataAnnotations<RecordReturnType<T, IsSingleField, FieldKey, Selected, Expands>, EO["includeODataAnnotations"] extends true ? true : false>>>;
|
|
117
113
|
getRequestConfig(): {
|
|
118
114
|
method: string;
|
|
@@ -123,7 +119,7 @@ export declare class RecordBuilder<T extends Record<string, any>, IsSingleField
|
|
|
123
119
|
* Returns the query string for this record builder (for testing purposes).
|
|
124
120
|
*/
|
|
125
121
|
getQueryString(): string;
|
|
126
|
-
toRequest(baseUrl: string): Request;
|
|
122
|
+
toRequest(baseUrl: string, options?: ExecuteOptions): Request;
|
|
127
123
|
processResponse(response: Response, options?: ExecuteOptions): Promise<Result<RecordReturnType<T, IsSingleField, FieldKey, Selected, Expands>>>;
|
|
128
124
|
}
|
|
129
125
|
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { getAcceptHeader } from "../types.js";
|
|
4
5
|
import { getTableIdentifiers, transformTableName, transformFieldNamesArray, transformResponseFields } from "../transform.js";
|
|
6
|
+
import { safeJsonParse } from "./sanitize-json.js";
|
|
5
7
|
import { QueryBuilder } from "./query-builder.js";
|
|
6
8
|
import { validateSingleResponse } from "../validation.js";
|
|
7
9
|
import buildQuery from "odata-query";
|
|
@@ -120,6 +122,20 @@ class RecordBuilder {
|
|
|
120
122
|
expand(relation, callback) {
|
|
121
123
|
var _a, _b;
|
|
122
124
|
const targetOccurrence = (_a = this.occurrence) == null ? void 0 : _a.navigation[relation];
|
|
125
|
+
const getDefaultSelectFields = () => {
|
|
126
|
+
var _a2;
|
|
127
|
+
if (!targetOccurrence) return void 0;
|
|
128
|
+
const defaultSelect = targetOccurrence.defaultSelect;
|
|
129
|
+
if (defaultSelect === "schema") {
|
|
130
|
+
const schema = (_a2 = targetOccurrence.baseTable) == null ? void 0 : _a2.schema;
|
|
131
|
+
if (schema) {
|
|
132
|
+
return [...new Set(Object.keys(schema))];
|
|
133
|
+
}
|
|
134
|
+
} else if (Array.isArray(defaultSelect)) {
|
|
135
|
+
return [...new Set(defaultSelect)];
|
|
136
|
+
}
|
|
137
|
+
return void 0;
|
|
138
|
+
};
|
|
123
139
|
const newBuilder = new RecordBuilder({
|
|
124
140
|
occurrence: this.occurrence,
|
|
125
141
|
tableName: this.tableName,
|
|
@@ -146,6 +162,12 @@ class RecordBuilder {
|
|
|
146
162
|
const expandOptions = {
|
|
147
163
|
...configuredBuilder.queryOptions
|
|
148
164
|
};
|
|
165
|
+
if (!expandOptions.select) {
|
|
166
|
+
const defaultFields = getDefaultSelectFields();
|
|
167
|
+
if (defaultFields) {
|
|
168
|
+
expandOptions.select = defaultFields;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
149
171
|
if (((_b = configuredBuilder.expandConfigs) == null ? void 0 : _b.length) > 0) {
|
|
150
172
|
const nestedExpandString = this.buildExpandString(
|
|
151
173
|
configuredBuilder.expandConfigs
|
|
@@ -160,7 +182,15 @@ class RecordBuilder {
|
|
|
160
182
|
};
|
|
161
183
|
newBuilder.expandConfigs.push(expandConfig);
|
|
162
184
|
} else {
|
|
163
|
-
|
|
185
|
+
const defaultFields = getDefaultSelectFields();
|
|
186
|
+
if (defaultFields) {
|
|
187
|
+
newBuilder.expandConfigs.push({
|
|
188
|
+
relation,
|
|
189
|
+
options: { select: defaultFields }
|
|
190
|
+
});
|
|
191
|
+
} else {
|
|
192
|
+
newBuilder.expandConfigs.push({ relation });
|
|
193
|
+
}
|
|
164
194
|
}
|
|
165
195
|
return newBuilder;
|
|
166
196
|
}
|
|
@@ -193,9 +223,10 @@ class RecordBuilder {
|
|
|
193
223
|
* - Wraps "id" fields in double quotes
|
|
194
224
|
* - URL-encodes special characters but preserves spaces
|
|
195
225
|
*/
|
|
196
|
-
formatSelectFields(select, baseTable) {
|
|
226
|
+
formatSelectFields(select, baseTable, useEntityIds) {
|
|
197
227
|
if (!select || select.length === 0) return "";
|
|
198
|
-
const
|
|
228
|
+
const shouldTransform = baseTable && (useEntityIds ?? this.databaseUseEntityIds);
|
|
229
|
+
const transformedFields = shouldTransform ? transformFieldNamesArray(select, baseTable) : select;
|
|
199
230
|
return transformedFields.map((field) => {
|
|
200
231
|
if (field === "id") return `"id"`;
|
|
201
232
|
const encodedField = encodeURIComponent(String(field));
|
|
@@ -302,16 +333,6 @@ class RecordBuilder {
|
|
|
302
333
|
}
|
|
303
334
|
return `?${parts.join("&")}`;
|
|
304
335
|
}
|
|
305
|
-
/**
|
|
306
|
-
* Helper to conditionally strip OData annotations based on options
|
|
307
|
-
*/
|
|
308
|
-
stripODataAnnotationsIfNeeded(data, options) {
|
|
309
|
-
if ((options == null ? void 0 : options.includeODataAnnotations) === true) {
|
|
310
|
-
return data;
|
|
311
|
-
}
|
|
312
|
-
const { "@id": _id, "@editLink": _editLink, ...rest } = data;
|
|
313
|
-
return rest;
|
|
314
|
-
}
|
|
315
336
|
async execute(options) {
|
|
316
337
|
var _a, _b, _c;
|
|
317
338
|
let url;
|
|
@@ -363,11 +384,7 @@ class RecordBuilder {
|
|
|
363
384
|
if (validation.data === null) {
|
|
364
385
|
return { data: null, error: void 0 };
|
|
365
386
|
}
|
|
366
|
-
|
|
367
|
-
validation.data,
|
|
368
|
-
options
|
|
369
|
-
);
|
|
370
|
-
return { data: stripped, error: void 0 };
|
|
387
|
+
return { data: validation.data, error: void 0 };
|
|
371
388
|
}
|
|
372
389
|
getRequestConfig() {
|
|
373
390
|
let url;
|
|
@@ -396,7 +413,8 @@ class RecordBuilder {
|
|
|
396
413
|
if (this.isNavigateFromEntitySet && this.navigateSourceTableName && this.navigateRelation) {
|
|
397
414
|
path = `/${this.navigateSourceTableName}/${this.navigateRelation}('${this.recordId}')`;
|
|
398
415
|
} else {
|
|
399
|
-
|
|
416
|
+
const tableId = this.getTableId(this.databaseUseEntityIds);
|
|
417
|
+
path = `/${tableId}('${this.recordId}')`;
|
|
400
418
|
}
|
|
401
419
|
if (this.operation === "getSingleField" && this.operationParam) {
|
|
402
420
|
return `${path}/${this.operationParam}`;
|
|
@@ -404,20 +422,20 @@ class RecordBuilder {
|
|
|
404
422
|
const queryString = this.buildQueryString();
|
|
405
423
|
return `${path}${queryString}`;
|
|
406
424
|
}
|
|
407
|
-
toRequest(baseUrl) {
|
|
425
|
+
toRequest(baseUrl, options) {
|
|
408
426
|
const config = this.getRequestConfig();
|
|
409
427
|
const fullUrl = `${baseUrl}${config.url}`;
|
|
410
428
|
return new Request(fullUrl, {
|
|
411
429
|
method: config.method,
|
|
412
430
|
headers: {
|
|
413
431
|
"Content-Type": "application/json",
|
|
414
|
-
Accept:
|
|
432
|
+
Accept: getAcceptHeader(options == null ? void 0 : options.includeODataAnnotations)
|
|
415
433
|
}
|
|
416
434
|
});
|
|
417
435
|
}
|
|
418
436
|
async processResponse(response, options) {
|
|
419
437
|
var _a, _b, _c;
|
|
420
|
-
const rawResponse = await response
|
|
438
|
+
const rawResponse = await safeJsonParse(response);
|
|
421
439
|
if (this.operation === "getSingleField") {
|
|
422
440
|
const fieldResponse = rawResponse;
|
|
423
441
|
return { data: fieldResponse.value, error: void 0 };
|
|
@@ -447,11 +465,7 @@ class RecordBuilder {
|
|
|
447
465
|
if (validation.data === null) {
|
|
448
466
|
return { data: null, error: void 0 };
|
|
449
467
|
}
|
|
450
|
-
|
|
451
|
-
validation.data,
|
|
452
|
-
options
|
|
453
|
-
);
|
|
454
|
-
return { data: stripped, error: void 0 };
|
|
468
|
+
return { data: validation.data, error: void 0 };
|
|
455
469
|
}
|
|
456
470
|
}
|
|
457
471
|
export {
|