@osdk/client 2.7.1 → 2.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/build/browser/Client.js +1 -1
  3. package/build/browser/Client.js.map +1 -1
  4. package/build/browser/observable/ObservableClient.js.map +1 -1
  5. package/build/browser/observable/internal/BulkObjectLoader.js +71 -9
  6. package/build/browser/observable/internal/BulkObjectLoader.js.map +1 -1
  7. package/build/browser/observable/internal/BulkObjectLoader.test.js +79 -0
  8. package/build/browser/observable/internal/BulkObjectLoader.test.js.map +1 -1
  9. package/build/browser/observable/internal/ObservableClientImpl.js +104 -17
  10. package/build/browser/observable/internal/ObservableClientImpl.js.map +1 -1
  11. package/build/browser/observable/internal/PivotCanonicalizer.js +4 -4
  12. package/build/browser/observable/internal/PivotCanonicalizer.js.map +1 -1
  13. package/build/browser/observable/internal/Store.test.js +185 -1
  14. package/build/browser/observable/internal/Store.test.js.map +1 -1
  15. package/build/browser/observable/internal/list/InterfaceListQuery.js +49 -3
  16. package/build/browser/observable/internal/list/InterfaceListQuery.js.map +1 -1
  17. package/build/browser/observable/internal/list/ListQuery.test.js +154 -0
  18. package/build/browser/observable/internal/list/ListQuery.test.js.map +1 -1
  19. package/build/browser/observable/internal/list/ListsHelper.js +1 -1
  20. package/build/browser/observable/internal/list/ListsHelper.js.map +1 -1
  21. package/build/browser/observable/internal/list/ObjectListQuery.js +22 -21
  22. package/build/browser/observable/internal/list/ObjectListQuery.js.map +1 -1
  23. package/build/browser/observable/internal/object/ObjectQuery.js +23 -6
  24. package/build/browser/observable/internal/object/ObjectQuery.js.map +1 -1
  25. package/build/browser/observable/internal/object/ObjectsHelper.js +3 -1
  26. package/build/browser/observable/internal/object/ObjectsHelper.js.map +1 -1
  27. package/build/browser/util/UserAgent.js +2 -2
  28. package/build/browser/util/interfaceUtils.js +7 -0
  29. package/build/browser/util/interfaceUtils.js.map +1 -1
  30. package/build/cjs/{chunk-OZNDU7AU.cjs → chunk-EHWB7KEN.cjs} +2 -2
  31. package/build/cjs/{chunk-OZNDU7AU.cjs.map → chunk-EHWB7KEN.cjs.map} +1 -1
  32. package/build/cjs/{chunk-OVZCGOMG.cjs → chunk-O3SKYLBQ.cjs} +69 -65
  33. package/build/cjs/chunk-O3SKYLBQ.cjs.map +1 -0
  34. package/build/cjs/index.cjs +8 -8
  35. package/build/cjs/public/internal.cjs +8 -8
  36. package/build/cjs/public/unstable-do-not-use.cjs +323 -112
  37. package/build/cjs/public/unstable-do-not-use.cjs.map +1 -1
  38. package/build/cjs/public/unstable-do-not-use.d.cts +9 -9
  39. package/build/esm/Client.js +1 -1
  40. package/build/esm/Client.js.map +1 -1
  41. package/build/esm/observable/ObservableClient.js.map +1 -1
  42. package/build/esm/observable/internal/BulkObjectLoader.js +71 -9
  43. package/build/esm/observable/internal/BulkObjectLoader.js.map +1 -1
  44. package/build/esm/observable/internal/BulkObjectLoader.test.js +79 -0
  45. package/build/esm/observable/internal/BulkObjectLoader.test.js.map +1 -1
  46. package/build/esm/observable/internal/ObservableClientImpl.js +104 -17
  47. package/build/esm/observable/internal/ObservableClientImpl.js.map +1 -1
  48. package/build/esm/observable/internal/PivotCanonicalizer.js +4 -4
  49. package/build/esm/observable/internal/PivotCanonicalizer.js.map +1 -1
  50. package/build/esm/observable/internal/Store.test.js +185 -1
  51. package/build/esm/observable/internal/Store.test.js.map +1 -1
  52. package/build/esm/observable/internal/list/InterfaceListQuery.js +49 -3
  53. package/build/esm/observable/internal/list/InterfaceListQuery.js.map +1 -1
  54. package/build/esm/observable/internal/list/ListQuery.test.js +154 -0
  55. package/build/esm/observable/internal/list/ListQuery.test.js.map +1 -1
  56. package/build/esm/observable/internal/list/ListsHelper.js +1 -1
  57. package/build/esm/observable/internal/list/ListsHelper.js.map +1 -1
  58. package/build/esm/observable/internal/list/ObjectListQuery.js +22 -21
  59. package/build/esm/observable/internal/list/ObjectListQuery.js.map +1 -1
  60. package/build/esm/observable/internal/object/ObjectQuery.js +23 -6
  61. package/build/esm/observable/internal/object/ObjectQuery.js.map +1 -1
  62. package/build/esm/observable/internal/object/ObjectsHelper.js +3 -1
  63. package/build/esm/observable/internal/object/ObjectsHelper.js.map +1 -1
  64. package/build/esm/util/UserAgent.js +2 -2
  65. package/build/esm/util/interfaceUtils.js +7 -0
  66. package/build/esm/util/interfaceUtils.js.map +1 -1
  67. package/build/types/Client.d.ts +1 -1
  68. package/build/types/observable/ObservableClient.d.ts +12 -12
  69. package/build/types/observable/ObservableClient.d.ts.map +1 -1
  70. package/build/types/observable/internal/BulkObjectLoader.d.ts +2 -1
  71. package/build/types/observable/internal/BulkObjectLoader.d.ts.map +1 -1
  72. package/build/types/observable/internal/PivotCanonicalizer.d.ts +2 -2
  73. package/build/types/observable/internal/PivotCanonicalizer.d.ts.map +1 -1
  74. package/build/types/observable/internal/Store.test.d.ts.map +1 -1
  75. package/build/types/observable/internal/list/InterfaceListQuery.d.ts.map +1 -1
  76. package/build/types/observable/internal/list/ObjectListQuery.d.ts.map +1 -1
  77. package/build/types/observable/internal/object/ObjectQuery.d.ts +2 -1
  78. package/build/types/observable/internal/object/ObjectQuery.d.ts.map +1 -1
  79. package/build/types/observable/internal/object/ObjectsHelper.d.ts.map +1 -1
  80. package/build/types/util/interfaceUtils.d.ts +2 -1
  81. package/build/types/util/interfaceUtils.d.ts.map +1 -1
  82. package/package.json +9 -9
  83. package/build/cjs/chunk-OVZCGOMG.cjs.map +0 -1
@@ -157,7 +157,7 @@ interface OptimisticBuilder {
157
157
  deleteObject: <T extends ObjectTypeDefinition>(value: Osdk.Instance<T>) => this;
158
158
  }
159
159
 
160
- type OrderBy<Q extends ObjectTypeDefinition | InterfaceDefinition> = {
160
+ type OrderBy<Q extends ObjectOrInterfaceDefinition> = {
161
161
  [K in PropertyKeys<Q>]?: "asc" | "desc" | undefined;
162
162
  };
163
163
  interface ObserveListOptions<Q extends ObjectOrInterfaceDefinition, RDPs extends Record<string, SimplePropertyDef> = {}> extends CommonObserveOptions, ObserveOptions {
@@ -208,13 +208,13 @@ interface ObserveListOptions<Q extends ObjectOrInterfaceDefinition, RDPs extends
208
208
  }>;
209
209
  pivotTo?: string;
210
210
  }
211
- interface ObserveObjectCallbackArgs<T extends ObjectTypeDefinition> {
211
+ interface ObserveObjectCallbackArgs<T extends ObjectOrInterfaceDefinition> {
212
212
  object: Osdk.Instance<T> | undefined;
213
213
  isOptimistic: boolean;
214
214
  status: Status;
215
215
  lastUpdated: number;
216
216
  }
217
- interface ObserveObjectsCallbackArgs<T extends ObjectTypeDefinition | InterfaceDefinition, RDPs extends Record<string, WirePropertyTypes | undefined | Array<WirePropertyTypes>> = {}> {
217
+ interface ObserveObjectsCallbackArgs<T extends ObjectOrInterfaceDefinition, RDPs extends Record<string, WirePropertyTypes | undefined | Array<WirePropertyTypes>> = {}> {
218
218
  resolvedList: Array<Osdk.Instance<T, "$allBaseProperties", PropertyKeys<T>, RDPs>>;
219
219
  isOptimistic: boolean;
220
220
  lastUpdated: number;
@@ -223,7 +223,7 @@ interface ObserveObjectsCallbackArgs<T extends ObjectTypeDefinition | InterfaceD
223
223
  status: Status;
224
224
  totalCount?: string;
225
225
  }
226
- interface ObserveObjectSetArgs<T extends ObjectTypeDefinition | InterfaceDefinition, RDPs extends Record<string, WirePropertyTypes | undefined | Array<WirePropertyTypes>> = {}> {
226
+ interface ObserveObjectSetArgs<T extends ObjectOrInterfaceDefinition, RDPs extends Record<string, WirePropertyTypes | undefined | Array<WirePropertyTypes>> = {}> {
227
227
  resolvedList: Array<Osdk.Instance<T, "$allBaseProperties", PropertyKeys<T>, RDPs>>;
228
228
  isOptimistic: boolean;
229
229
  lastUpdated: number;
@@ -283,9 +283,9 @@ declare namespace ObservableClient {
283
283
  */
284
284
  interface ObservableClient extends ObserveLinks {
285
285
  /**
286
- * Observe a single object with automatic updates when it changes.
286
+ * Observe a single object or interface instance with automatic updates when it changes.
287
287
  *
288
- * @param apiName - The object type definition or name
288
+ * @param apiName - The object type or interface definition, or its API name
289
289
  * @param pk - The object's primary key
290
290
  * @param options - Observation options including deduplication interval
291
291
  * @param subFn - Observer that receives object state updates
@@ -297,7 +297,7 @@ interface ObservableClient extends ObserveLinks {
297
297
  * - Updates when the object changes
298
298
  * - Error state if fetch fails
299
299
  */
300
- observeObject<T extends ObjectTypeDefinition>(apiName: T["apiName"] | T, pk: PrimaryKeyType<T>, options: ObserveOptions, subFn: Observer<ObserveObjectCallbackArgs<T>>): Unsubscribable;
300
+ observeObject<T extends ObjectOrInterfaceDefinition>(apiName: T["apiName"] | T, pk: PrimaryKeyType<T>, options: ObserveOptions, subFn: Observer<ObserveObjectCallbackArgs<T>>): Unsubscribable;
301
301
  /**
302
302
  * Observe a filtered and sorted collection of objects.
303
303
  *
@@ -311,7 +311,7 @@ interface ObservableClient extends ObserveLinks {
311
311
  * - Pagination via fetchMore() in the payload
312
312
  * - Automatic updates when any matching object changes
313
313
  */
314
- observeList<T extends ObjectTypeDefinition | InterfaceDefinition, RDPs extends Record<string, SimplePropertyDef> = {}>(options: ObserveListOptions<T, RDPs>, subFn: Observer<ObserveObjectsCallbackArgs<T, RDPs>>): Unsubscribable;
314
+ observeList<T extends ObjectOrInterfaceDefinition, RDPs extends Record<string, SimplePropertyDef> = {}>(options: ObserveListOptions<T, RDPs>, subFn: Observer<ObserveObjectsCallbackArgs<T, RDPs>>): Unsubscribable;
315
315
  /**
316
316
  * Observe an ObjectSet with automatic updates when matching objects change.
317
317
  *
@@ -424,7 +424,7 @@ interface ObservableClient extends ObserveLinks {
424
424
  * @param primaryKey - Object primary key
425
425
  */
426
426
  invalidateFunctionsByObject(apiName: string, primaryKey: string | number): Promise<void>;
427
- canonicalizeWhereClause: <T extends ObjectTypeDefinition | InterfaceDefinition, RDPs extends Record<string, SimplePropertyDef> = {}>(where: WhereClause<T, RDPs>) => Canonical<WhereClause<T, RDPs>>;
427
+ canonicalizeWhereClause: <T extends ObjectOrInterfaceDefinition, RDPs extends Record<string, SimplePropertyDef> = {}>(where: WhereClause<T, RDPs>) => Canonical<WhereClause<T, RDPs>>;
428
428
  }
429
429
  declare function createObservableClient(client: Client): ObservableClient;
430
430
  interface Unsubscribable {
@@ -21,7 +21,7 @@
21
21
  export const additionalContext = Symbol("additionalContext");
22
22
 
23
23
  // BEGIN: THIS IS GENERATED CODE. DO NOT EDIT.
24
- const MaxOsdkVersion = "2.7.1";
24
+ const MaxOsdkVersion = "2.7.3";
25
25
  // END: THIS IS GENERATED CODE. DO NOT EDIT.
26
26
 
27
27
  const ErrorMessage = Symbol("ErrorMessage");
@@ -1 +1 @@
1
- {"version":3,"file":"Client.js","names":["additionalContext","Symbol","MaxOsdkVersion","ErrorMessage"],"sources":["Client.ts"],"sourcesContent":["/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n ActionDefinition,\n ActionMetadata,\n CompileTimeMetadata,\n InterfaceDefinition,\n InterfaceMetadata,\n ObjectMetadata,\n ObjectSet,\n ObjectTypeDefinition,\n QueryDefinition,\n QueryMetadata,\n VersionBound,\n} from \"@osdk/api\";\nimport type {\n Experiment,\n ExperimentFns,\n MinimalObjectSet,\n} from \"@osdk/api/unstable\";\nimport type { SharedClient } from \"@osdk/shared.client2\";\nimport type { ActionSignatureFromDef } from \"./actions/applyAction.js\";\nimport type { MinimalClient } from \"./MinimalClientContext.js\";\nimport type { QuerySignatureFromDef } from \"./queries/types.js\";\nimport type { SatisfiesSemver } from \"./SatisfiesSemver.js\";\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\ntype OldSharedClient = import(\"@osdk/shared.client\").SharedClient;\n\nexport type CheckVersionBound<Q> = Q extends VersionBound<infer V> ? (\n SatisfiesSemver<V, MaxOsdkVersion> extends true ? Q\n : Q & {\n [ErrorMessage]:\n `Your SDK requires a semver compatible version with ${V}. You have ${MaxOsdkVersion}. Update your package.json`;\n }\n )\n : Q;\n\nexport interface Client extends SharedClient, OldSharedClient {\n <Q extends ObjectTypeDefinition>(\n o: Q,\n ): unknown extends CompileTimeMetadata<Q>[\"objectSet\"] ? ObjectSet<Q>\n : CompileTimeMetadata<Q>[\"objectSet\"];\n\n <Q extends (InterfaceDefinition)>(\n o: Q,\n ): unknown extends CompileTimeMetadata<Q>[\"objectSet\"] ? MinimalObjectSet<Q>\n : CompileTimeMetadata<Q>[\"objectSet\"];\n\n <Q extends ActionDefinition<any>>(\n o: Q,\n ): ActionSignatureFromDef<Q>;\n\n <Q extends QueryDefinition<any>>(\n o: Q,\n ): QuerySignatureFromDef<Q>;\n\n <Q extends Experiment<\"2.0.8\"> | Experiment<\"2.1.0\"> | Experiment<\"2.2.0\">>(\n experiment: Q,\n ): ExperimentFns<Q>;\n\n fetchMetadata<\n Q extends (\n | ObjectTypeDefinition\n | InterfaceDefinition\n | ActionDefinition<any>\n | QueryDefinition<any>\n ),\n >(o: Q): Promise<\n Q extends ObjectTypeDefinition ? ObjectMetadata\n : Q extends InterfaceDefinition ? InterfaceMetadata\n : Q extends ActionDefinition<any> ? ActionMetadata\n : Q extends QueryDefinition<any> ? QueryMetadata\n : never\n >;\n\n /** @internal */\n [additionalContext]: MinimalClient;\n}\n\n// DO NOT EXPORT FROM PACKAGE\n/** @internal */\nexport const additionalContext: unique symbol = Symbol(\"additionalContext\");\n\n// BEGIN: THIS IS GENERATED CODE. DO NOT EDIT.\nconst MaxOsdkVersion = \"2.7.1\";\n// END: THIS IS GENERATED CODE. DO NOT EDIT.\nexport type MaxOsdkVersion = typeof MaxOsdkVersion;\nconst ErrorMessage: unique symbol = Symbol(\"ErrorMessage\");\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA0BA;;AAsDA;AACA;AACA,OAAO,MAAMA,iBAAgC,GAAGC,MAAM,CAAC,mBAAmB,CAAC;;AAE3E;AACA,MAAMC,cAAc,GAAG,OAAO;AAC9B;;AAEA,MAAMC,YAA2B,GAAGF,MAAM,CAAC,cAAc,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"Client.js","names":["additionalContext","Symbol","MaxOsdkVersion","ErrorMessage"],"sources":["Client.ts"],"sourcesContent":["/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n ActionDefinition,\n ActionMetadata,\n CompileTimeMetadata,\n InterfaceDefinition,\n InterfaceMetadata,\n ObjectMetadata,\n ObjectSet,\n ObjectTypeDefinition,\n QueryDefinition,\n QueryMetadata,\n VersionBound,\n} from \"@osdk/api\";\nimport type {\n Experiment,\n ExperimentFns,\n MinimalObjectSet,\n} from \"@osdk/api/unstable\";\nimport type { SharedClient } from \"@osdk/shared.client2\";\nimport type { ActionSignatureFromDef } from \"./actions/applyAction.js\";\nimport type { MinimalClient } from \"./MinimalClientContext.js\";\nimport type { QuerySignatureFromDef } from \"./queries/types.js\";\nimport type { SatisfiesSemver } from \"./SatisfiesSemver.js\";\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\ntype OldSharedClient = import(\"@osdk/shared.client\").SharedClient;\n\nexport type CheckVersionBound<Q> = Q extends VersionBound<infer V> ? (\n SatisfiesSemver<V, MaxOsdkVersion> extends true ? Q\n : Q & {\n [ErrorMessage]:\n `Your SDK requires a semver compatible version with ${V}. You have ${MaxOsdkVersion}. Update your package.json`;\n }\n )\n : Q;\n\nexport interface Client extends SharedClient, OldSharedClient {\n <Q extends ObjectTypeDefinition>(\n o: Q,\n ): unknown extends CompileTimeMetadata<Q>[\"objectSet\"] ? ObjectSet<Q>\n : CompileTimeMetadata<Q>[\"objectSet\"];\n\n <Q extends (InterfaceDefinition)>(\n o: Q,\n ): unknown extends CompileTimeMetadata<Q>[\"objectSet\"] ? MinimalObjectSet<Q>\n : CompileTimeMetadata<Q>[\"objectSet\"];\n\n <Q extends ActionDefinition<any>>(\n o: Q,\n ): ActionSignatureFromDef<Q>;\n\n <Q extends QueryDefinition<any>>(\n o: Q,\n ): QuerySignatureFromDef<Q>;\n\n <Q extends Experiment<\"2.0.8\"> | Experiment<\"2.1.0\"> | Experiment<\"2.2.0\">>(\n experiment: Q,\n ): ExperimentFns<Q>;\n\n fetchMetadata<\n Q extends (\n | ObjectTypeDefinition\n | InterfaceDefinition\n | ActionDefinition<any>\n | QueryDefinition<any>\n ),\n >(o: Q): Promise<\n Q extends ObjectTypeDefinition ? ObjectMetadata\n : Q extends InterfaceDefinition ? InterfaceMetadata\n : Q extends ActionDefinition<any> ? ActionMetadata\n : Q extends QueryDefinition<any> ? QueryMetadata\n : never\n >;\n\n /** @internal */\n [additionalContext]: MinimalClient;\n}\n\n// DO NOT EXPORT FROM PACKAGE\n/** @internal */\nexport const additionalContext: unique symbol = Symbol(\"additionalContext\");\n\n// BEGIN: THIS IS GENERATED CODE. DO NOT EDIT.\nconst MaxOsdkVersion = \"2.7.3\";\n// END: THIS IS GENERATED CODE. DO NOT EDIT.\nexport type MaxOsdkVersion = typeof MaxOsdkVersion;\nconst ErrorMessage: unique symbol = Symbol(\"ErrorMessage\");\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA0BA;;AAsDA;AACA;AACA,OAAO,MAAMA,iBAAgC,GAAGC,MAAM,CAAC,mBAAmB,CAAC;;AAE3E;AACA,MAAMC,cAAc,GAAG,OAAO;AAC9B;;AAEA,MAAMC,YAA2B,GAAGF,MAAM,CAAC,cAAc,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableClient.js","names":["createFetchHeaderMutator","additionalContext","createClientFromContext","OBSERVABLE_USER_AGENT","ObservableClientImpl","Store","ObservableClient","createObservableClient","client","tweakedClient","fetch","headers","set","get","filter","x","length","join"],"sources":["ObservableClient.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n ActionDefinition,\n ActionEditResponse,\n ActionValidationResponse,\n AggregateOpts,\n AggregationsResults,\n CompileTimeMetadata,\n DerivedProperty,\n InterfaceDefinition,\n ObjectOrInterfaceDefinition,\n ObjectSet,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n PropertyKeys,\n QueryDefinition,\n SimplePropertyDef,\n WhereClause,\n WirePropertyTypes,\n} from \"@osdk/api\";\nimport { createFetchHeaderMutator } from \"@osdk/shared.net.fetch\";\nimport type { ActionSignatureFromDef } from \"../actions/applyAction.js\";\nimport { additionalContext, type Client } from \"../Client.js\";\nimport { createClientFromContext } from \"../createClient.js\";\nimport type { QueryReturnType } from \"../queries/types.js\";\nimport { OBSERVABLE_USER_AGENT } from \"../util/UserAgent.js\";\nimport type { Canonical } from \"./internal/Canonical.js\";\nimport type { ObserveObjectSetOptions } from \"./internal/objectset/ObjectSetQueryOptions.js\";\nimport { ObservableClientImpl } from \"./internal/ObservableClientImpl.js\";\nimport { Store } from \"./internal/Store.js\";\nimport type {\n CommonObserveOptions,\n InvalidationMode,\n ObserveOptions,\n Observer,\n Status,\n} from \"./ObservableClient/common.js\";\nimport type { ObserveLinks } from \"./ObservableClient/ObserveLink.js\";\nimport type { OptimisticBuilder } from \"./OptimisticBuilder.js\";\n\nexport namespace ObservableClient {\n export interface ApplyActionOptions {\n optimisticUpdate?: (ctx: OptimisticBuilder) => void;\n }\n}\n\nexport interface ObserveObjectOptions<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n> extends ObserveOptions {\n apiName: T[\"apiName\"] | T;\n pk: PrimaryKeyType<T>;\n select?: PropertyKeys<T>[];\n}\n\nexport type OrderBy<Q extends ObjectTypeDefinition | InterfaceDefinition> = {\n [K in PropertyKeys<Q>]?: \"asc\" | \"desc\" | undefined;\n};\n\nexport interface ObserveListOptions<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> extends CommonObserveOptions, ObserveOptions {\n type: Pick<Q, \"apiName\" | \"type\">;\n where?: WhereClause<Q, RDPs>;\n pageSize?: number;\n orderBy?: OrderBy<Q>;\n invalidationMode?: InvalidationMode;\n expectedLength?: number;\n streamUpdates?: boolean;\n withProperties?: DerivedProperty.Clause<Q>;\n\n /**\n * Fetch objects by their Resource Identifiers (RIDs).\n * When provided, starts with a static objectset containing these RIDs.\n * Can be combined with `where` to filter the RID set, and with `orderBy` to sort results.\n *\n * @example\n * // Fetch specific objects by RID\n * observeList({ type: Employee, rids: ['ri.foo.123', 'ri.foo.456'] }, observer)\n *\n * @example\n * // Fetch specific objects by RID, filtered by status\n * observeList({\n * type: Employee,\n * rids: ['ri.foo.123', 'ri.foo.456', 'ri.foo.789'],\n * where: { status: 'active' }\n * }, observer)\n */\n rids?: readonly string[];\n\n /**\n * Automatically fetch additional pages on initial load.\n *\n * - `true`: Fetch all available pages automatically\n * - `number`: Fetch pages until at least this many items are loaded\n * - `undefined` (default): Only fetch the first page, user must call fetchMore()\n *\n * @example\n * // Fetch all todos at once\n * observeList({ type: Todo, autoFetchMore: true }, observer)\n *\n * @example\n * // Fetch at least 100 todos\n * observeList({ type: Todo, autoFetchMore: 100, pageSize: 25 }, observer)\n */\n autoFetchMore?: boolean | number;\n intersectWith?: Array<{\n where: WhereClause<Q, RDPs>;\n }>;\n pivotTo?: string;\n}\n\nexport interface ObserveObjectCallbackArgs<T extends ObjectTypeDefinition> {\n object: Osdk.Instance<T> | undefined;\n isOptimistic: boolean;\n status: Status;\n lastUpdated: number;\n}\n\nexport interface ObserveObjectsCallbackArgs<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n> {\n resolvedList: Array<\n Osdk.Instance<T, \"$allBaseProperties\", PropertyKeys<T>, RDPs>\n >;\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\n totalCount?: string;\n}\n\nexport interface ObserveObjectSetArgs<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n> {\n resolvedList: Array<\n Osdk.Instance<T, \"$allBaseProperties\", PropertyKeys<T>, RDPs>\n >;\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\n objectSet: ObjectSet<T, RDPs>;\n totalCount?: string;\n}\n\nexport interface ObserveAggregationOptions<\n T extends ObjectOrInterfaceDefinition,\n A extends AggregateOpts<T>,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> extends CommonObserveOptions, ObserveOptions {\n type: T;\n where?: WhereClause<T, RDPs>;\n withProperties?: DerivedProperty.Clause<T>;\n intersectWith?: Array<{\n where: WhereClause<T, RDPs>;\n }>;\n aggregate: A;\n}\n\nexport interface ObserveAggregationArgs<\n T extends ObjectOrInterfaceDefinition,\n A extends AggregateOpts<T>,\n> {\n result: AggregationsResults<T, A> | undefined;\n status: Status;\n lastUpdated: number;\n error?: Error;\n}\n\nexport interface ObserveFunctionOptions extends CommonObserveOptions {\n /**\n * Object types this function depends on.\n * When actions modify these types, the function will refetch.\n */\n dependsOn?: Array<ObjectTypeDefinition | string>;\n\n /**\n * Specific object instances this function depends on.\n * When these objects change, the function will refetch.\n */\n dependsOnObjects?: Array<Osdk.Instance<ObjectTypeDefinition>>;\n}\n\nexport interface ObserveFunctionCallbackArgs<\n Q extends QueryDefinition<unknown>,\n> {\n result: QueryReturnType<CompileTimeMetadata<Q>[\"output\"]> | undefined;\n status: Status;\n lastUpdated: number;\n error?: Error;\n}\n\n/**\n * User facing callback args for `observeLink`\n */\nexport interface ObserveLinkCallbackArgs<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n> {\n resolvedList: Osdk.Instance<T>[];\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\n totalCount?: string;\n}\n\n/**\n * Public interface for reactive data management with automatic updates.\n *\n * The ObservableClient provides a reactive data layer with:\n * - Real-time object and collection observation\n * - Automatic cache updates when data changes\n * - Optimistic updates for immediate UI feedback\n * - Pagination support for large collections\n * - Link traversal for relationship navigation\n */\nexport interface ObservableClient extends ObserveLinks {\n /**\n * Observe a single object with automatic updates when it changes.\n *\n * @param apiName - The object type definition or name\n * @param pk - The object's primary key\n * @param options - Observation options including deduplication interval\n * @param subFn - Observer that receives object state updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * The observer will receive:\n * - Initial loading state if data not cached\n * - Loaded state with the object data\n * - Updates when the object changes\n * - Error state if fetch fails\n */\n observeObject<T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n pk: PrimaryKeyType<T>,\n options: ObserveOptions,\n subFn: Observer<ObserveObjectCallbackArgs<T>>,\n ): Unsubscribable;\n\n /**\n * Observe a filtered and sorted collection of objects.\n *\n * @param options - Filter, sort, and pagination options\n * @param subFn - Observer that receives collection state updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports:\n * - Filtering with where clauses\n * - Sorting with orderBy\n * - Pagination via fetchMore() in the payload\n * - Automatic updates when any matching object changes\n */\n observeList<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n >(\n options: ObserveListOptions<T, RDPs>,\n subFn: Observer<ObserveObjectsCallbackArgs<T, RDPs>>,\n ): Unsubscribable;\n\n /**\n * Observe an ObjectSet with automatic updates when matching objects change.\n *\n * @param baseObjectSet - The base ObjectSet to observe\n * @param options - Options for transforming and observing the ObjectSet\n * @param subFn - Observer that receives ObjectSet state updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports all ObjectSet operations:\n * - Filtering with where clauses\n * - Derived properties with withProperties\n * - Set operations (union, intersect, subtract)\n * - Link traversal with pivotTo\n * - Sorting and pagination\n */\n observeObjectSet<\n T extends ObjectTypeDefinition,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n >(\n baseObjectSet: ObjectSet<T>,\n options: ObserveObjectSetOptions<T, RDPs>,\n subFn: Observer<ObserveObjectSetArgs<T, RDPs>>,\n ): Unsubscribable;\n\n /**\n * Observe an aggregation query with automatic updates when underlying data changes.\n *\n * @param options - Aggregation configuration including where, aggregate spec, and derived properties\n * @param subFn - Observer that receives aggregation result updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports:\n * - Filtering with where clauses\n * - Derived properties (RDPs) via withProperties\n * - Set intersections\n * - GroupBy and metric aggregations\n * - Automatic updates when source data changes\n */\n observeAggregation<\n T extends ObjectOrInterfaceDefinition,\n A extends AggregateOpts<T>,\n RDPs extends Record<string, SimplePropertyDef> = {},\n >(\n options: ObserveAggregationOptions<T, A, RDPs>,\n subFn: Observer<ObserveAggregationArgs<T, A>>,\n ): Unsubscribable;\n\n /**\n * Observe a function execution with automatic updates.\n *\n * @param queryDef - The QueryDefinition to execute\n * @param params - Parameters to pass to the function (undefined if no params)\n * @param options - Observation options including invalidation configuration\n * @param subFn - Observer that receives function result updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports:\n * - Automatic caching and deduplication\n * - Dependency-based invalidation (dependsOn object types)\n * - Instance-based invalidation (dependsOnObjects)\n * - Manual refetch via invalidateFunction()\n */\n observeFunction<Q extends QueryDefinition<unknown>>(\n queryDef: Q,\n params: Record<string, unknown> | undefined,\n options: ObserveFunctionOptions,\n subFn: Observer<ObserveFunctionCallbackArgs<Q>>,\n ): Unsubscribable;\n\n /**\n * Execute an action with optional optimistic updates.\n *\n * @param action - Action definition to execute\n * @param args - Arguments for the action\n * @param opts - Options including optimistic updates\n * @returns Promise that resolves when the action completes\n *\n * When providing optimistic updates:\n * - Changes appear immediately in the UI\n * - Server request still happens in background\n * - On success, server data replaces optimistic data\n * - On failure, optimistic changes automatically roll back\n */\n applyAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args:\n | Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0]\n | Array<Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0]>,\n opts?: ObservableClient.ApplyActionOptions,\n ) => Promise<ActionEditResponse>;\n\n /**\n * Validate action parameters without executing the action.\n *\n * @param action - Action definition to validate\n * @param args - Arguments to validate\n * @returns Promise with validation result\n *\n * Use this to:\n * - Pre-validate forms before submission\n * - Display warnings or errors in the UI\n * - Enable/disable action buttons based on validity\n */\n validateAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n ) => Promise<ActionValidationResponse>;\n\n /**\n * Invalidates the entire cache, forcing all queries to refetch.\n * Use sparingly as this can cause significant network traffic.\n */\n invalidateAll(): Promise<void>;\n\n /**\n * Invalidates specific objects in the cache.\n * @param objects - Single object or array of objects to invalidate\n */\n invalidateObjects(\n objects:\n | Osdk.Instance<ObjectTypeDefinition>\n | ReadonlyArray<Osdk.Instance<ObjectTypeDefinition>>,\n ): Promise<void>;\n\n /**\n * Invalidates all cached data for a specific object type.\n * This includes:\n * - All objects of the specified type\n * - All lists containing objects of this type\n * - All links where the source is of this type\n *\n * @param type - Object type definition or API name string\n * @returns Promise that resolves when invalidation is complete\n */\n invalidateObjectType<T extends ObjectTypeDefinition>(\n type: T | T[\"apiName\"],\n ): Promise<void>;\n\n /**\n * Invalidate function queries.\n * - If params undefined, invalidates ALL queries for this function\n * - If params provided, invalidates only the query with exact params match\n *\n * @param apiName - Function API name string or QueryDefinition\n * @param params - Optional params for exact match\n */\n invalidateFunction(\n apiName: string | QueryDefinition<unknown>,\n params?: Record<string, unknown>,\n ): Promise<void>;\n\n /**\n * Invalidate functions that depend on a specific object instance.\n *\n * @param apiName - Object type API name\n * @param primaryKey - Object primary key\n */\n invalidateFunctionsByObject(\n apiName: string,\n primaryKey: string | number,\n ): Promise<void>;\n\n canonicalizeWhereClause: <\n T extends ObjectTypeDefinition | InterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n >(\n where: WhereClause<T, RDPs>,\n ) => Canonical<WhereClause<T, RDPs>>;\n}\n\nexport function createObservableClient(client: Client): ObservableClient {\n // First we need a modified client that adds an extra header so we know its\n // an observable client\n const tweakedClient = createClientFromContext({\n ...client[additionalContext],\n\n fetch: createFetchHeaderMutator(\n client[additionalContext].fetch,\n (headers) => {\n headers.set(\n \"Fetch-User-Agent\",\n [\n headers.get(\"Fetch-User-Agent\"),\n OBSERVABLE_USER_AGENT,\n ].filter(x => x && x?.length > 0).join(\" \"),\n );\n return headers;\n },\n ),\n });\n\n // Then we use that client instead. Because the `client` does not hold\n // any real state, this whole thing works.\n return new ObservableClientImpl(new Store(tweakedClient));\n}\n\nexport interface Unsubscribable {\n unsubscribe: () => void;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAsBA,SAASA,wBAAwB,QAAQ,wBAAwB;AAEjE,SAASC,iBAAiB,QAAqB,cAAc;AAC7D,SAASC,uBAAuB,QAAQ,oBAAoB;AAE5D,SAASC,qBAAqB,QAAQ,sBAAsB;AAG5D,SAASC,oBAAoB,QAAQ,oCAAoC;AACzE,SAASC,KAAK,QAAQ,qBAAqB;AAAC,WAW3BC,gBAAgB;AAmKjC;AACA;AACA;;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA0NA,OAAO,SAASC,sBAAsBA,CAACC,MAAc,EAAoB;EACvE;EACA;EACA,MAAMC,aAAa,GAAGP,uBAAuB,CAAC;IAC5C,GAAGM,MAAM,CAACP,iBAAiB,CAAC;IAE5BS,KAAK,EAAEV,wBAAwB,CAC7BQ,MAAM,CAACP,iBAAiB,CAAC,CAACS,KAAK,EAC9BC,OAAO,IAAK;MACXA,OAAO,CAACC,GAAG,CACT,kBAAkB,EAClB,CACED,OAAO,CAACE,GAAG,CAAC,kBAAkB,CAAC,EAC/BV,qBAAqB,CACtB,CAACW,MAAM,CAACC,CAAC,IAAIA,CAAC,IAAIA,CAAC,EAAEC,MAAM,GAAG,CAAC,CAAC,CAACC,IAAI,CAAC,GAAG,CAC5C,CAAC;MACD,OAAON,OAAO;IAChB,CACF;EACF,CAAC,CAAC;;EAEF;EACA;EACA,OAAO,IAAIP,oBAAoB,CAAC,IAAIC,KAAK,CAACI,aAAa,CAAC,CAAC;AAC3D","ignoreList":[]}
1
+ {"version":3,"file":"ObservableClient.js","names":["createFetchHeaderMutator","additionalContext","createClientFromContext","OBSERVABLE_USER_AGENT","ObservableClientImpl","Store","ObservableClient","createObservableClient","client","tweakedClient","fetch","headers","set","get","filter","x","length","join"],"sources":["ObservableClient.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n ActionDefinition,\n ActionEditResponse,\n ActionValidationResponse,\n AggregateOpts,\n AggregationsResults,\n CompileTimeMetadata,\n DerivedProperty,\n ObjectOrInterfaceDefinition,\n ObjectSet,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n PropertyKeys,\n QueryDefinition,\n SimplePropertyDef,\n WhereClause,\n WirePropertyTypes,\n} from \"@osdk/api\";\nimport { createFetchHeaderMutator } from \"@osdk/shared.net.fetch\";\nimport type { ActionSignatureFromDef } from \"../actions/applyAction.js\";\nimport { additionalContext, type Client } from \"../Client.js\";\nimport { createClientFromContext } from \"../createClient.js\";\nimport type { QueryReturnType } from \"../queries/types.js\";\nimport { OBSERVABLE_USER_AGENT } from \"../util/UserAgent.js\";\nimport type { Canonical } from \"./internal/Canonical.js\";\nimport type { ObserveObjectSetOptions } from \"./internal/objectset/ObjectSetQueryOptions.js\";\nimport { ObservableClientImpl } from \"./internal/ObservableClientImpl.js\";\nimport { Store } from \"./internal/Store.js\";\nimport type {\n CommonObserveOptions,\n InvalidationMode,\n ObserveOptions,\n Observer,\n Status,\n} from \"./ObservableClient/common.js\";\nimport type { ObserveLinks } from \"./ObservableClient/ObserveLink.js\";\nimport type { OptimisticBuilder } from \"./OptimisticBuilder.js\";\n\nexport namespace ObservableClient {\n export interface ApplyActionOptions {\n optimisticUpdate?: (ctx: OptimisticBuilder) => void;\n }\n}\n\nexport interface ObserveObjectOptions<\n T extends ObjectOrInterfaceDefinition,\n> extends ObserveOptions {\n apiName: T[\"apiName\"] | T;\n pk: PrimaryKeyType<T>;\n select?: PropertyKeys<T>[];\n}\n\nexport type OrderBy<Q extends ObjectOrInterfaceDefinition> = {\n [K in PropertyKeys<Q>]?: \"asc\" | \"desc\" | undefined;\n};\n\nexport interface ObserveListOptions<\n Q extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> extends CommonObserveOptions, ObserveOptions {\n type: Pick<Q, \"apiName\" | \"type\">;\n where?: WhereClause<Q, RDPs>;\n pageSize?: number;\n orderBy?: OrderBy<Q>;\n invalidationMode?: InvalidationMode;\n expectedLength?: number;\n streamUpdates?: boolean;\n withProperties?: DerivedProperty.Clause<Q>;\n\n /**\n * Fetch objects by their Resource Identifiers (RIDs).\n * When provided, starts with a static objectset containing these RIDs.\n * Can be combined with `where` to filter the RID set, and with `orderBy` to sort results.\n *\n * @example\n * // Fetch specific objects by RID\n * observeList({ type: Employee, rids: ['ri.foo.123', 'ri.foo.456'] }, observer)\n *\n * @example\n * // Fetch specific objects by RID, filtered by status\n * observeList({\n * type: Employee,\n * rids: ['ri.foo.123', 'ri.foo.456', 'ri.foo.789'],\n * where: { status: 'active' }\n * }, observer)\n */\n rids?: readonly string[];\n\n /**\n * Automatically fetch additional pages on initial load.\n *\n * - `true`: Fetch all available pages automatically\n * - `number`: Fetch pages until at least this many items are loaded\n * - `undefined` (default): Only fetch the first page, user must call fetchMore()\n *\n * @example\n * // Fetch all todos at once\n * observeList({ type: Todo, autoFetchMore: true }, observer)\n *\n * @example\n * // Fetch at least 100 todos\n * observeList({ type: Todo, autoFetchMore: 100, pageSize: 25 }, observer)\n */\n autoFetchMore?: boolean | number;\n intersectWith?: Array<{\n where: WhereClause<Q, RDPs>;\n }>;\n pivotTo?: string;\n}\n\nexport interface ObserveObjectCallbackArgs<\n T extends ObjectOrInterfaceDefinition,\n> {\n object: Osdk.Instance<T> | undefined;\n isOptimistic: boolean;\n status: Status;\n lastUpdated: number;\n}\n\nexport interface ObserveObjectsCallbackArgs<\n T extends ObjectOrInterfaceDefinition,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n> {\n resolvedList: Array<\n Osdk.Instance<T, \"$allBaseProperties\", PropertyKeys<T>, RDPs>\n >;\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\n totalCount?: string;\n}\n\nexport interface ObserveObjectSetArgs<\n T extends ObjectOrInterfaceDefinition,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n> {\n resolvedList: Array<\n Osdk.Instance<T, \"$allBaseProperties\", PropertyKeys<T>, RDPs>\n >;\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\n objectSet: ObjectSet<T, RDPs>;\n totalCount?: string;\n}\n\nexport interface ObserveAggregationOptions<\n T extends ObjectOrInterfaceDefinition,\n A extends AggregateOpts<T>,\n RDPs extends Record<string, SimplePropertyDef> = {},\n> extends CommonObserveOptions, ObserveOptions {\n type: T;\n where?: WhereClause<T, RDPs>;\n withProperties?: DerivedProperty.Clause<T>;\n intersectWith?: Array<{\n where: WhereClause<T, RDPs>;\n }>;\n aggregate: A;\n}\n\nexport interface ObserveAggregationArgs<\n T extends ObjectOrInterfaceDefinition,\n A extends AggregateOpts<T>,\n> {\n result: AggregationsResults<T, A> | undefined;\n status: Status;\n lastUpdated: number;\n error?: Error;\n}\n\nexport interface ObserveFunctionOptions extends CommonObserveOptions {\n /**\n * Object types this function depends on.\n * When actions modify these types, the function will refetch.\n */\n dependsOn?: Array<ObjectTypeDefinition | string>;\n\n /**\n * Specific object instances this function depends on.\n * When these objects change, the function will refetch.\n */\n dependsOnObjects?: Array<Osdk.Instance<ObjectTypeDefinition>>;\n}\n\nexport interface ObserveFunctionCallbackArgs<\n Q extends QueryDefinition<unknown>,\n> {\n result: QueryReturnType<CompileTimeMetadata<Q>[\"output\"]> | undefined;\n status: Status;\n lastUpdated: number;\n error?: Error;\n}\n\n/**\n * User facing callback args for `observeLink`\n */\nexport interface ObserveLinkCallbackArgs<\n T extends ObjectOrInterfaceDefinition,\n> {\n resolvedList: Osdk.Instance<T>[];\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\n totalCount?: string;\n}\n\n/**\n * Public interface for reactive data management with automatic updates.\n *\n * The ObservableClient provides a reactive data layer with:\n * - Real-time object and collection observation\n * - Automatic cache updates when data changes\n * - Optimistic updates for immediate UI feedback\n * - Pagination support for large collections\n * - Link traversal for relationship navigation\n */\nexport interface ObservableClient extends ObserveLinks {\n /**\n * Observe a single object or interface instance with automatic updates when it changes.\n *\n * @param apiName - The object type or interface definition, or its API name\n * @param pk - The object's primary key\n * @param options - Observation options including deduplication interval\n * @param subFn - Observer that receives object state updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * The observer will receive:\n * - Initial loading state if data not cached\n * - Loaded state with the object data\n * - Updates when the object changes\n * - Error state if fetch fails\n */\n observeObject<T extends ObjectOrInterfaceDefinition>(\n apiName: T[\"apiName\"] | T,\n pk: PrimaryKeyType<T>,\n options: ObserveOptions,\n subFn: Observer<ObserveObjectCallbackArgs<T>>,\n ): Unsubscribable;\n\n /**\n * Observe a filtered and sorted collection of objects.\n *\n * @param options - Filter, sort, and pagination options\n * @param subFn - Observer that receives collection state updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports:\n * - Filtering with where clauses\n * - Sorting with orderBy\n * - Pagination via fetchMore() in the payload\n * - Automatic updates when any matching object changes\n */\n observeList<\n T extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n >(\n options: ObserveListOptions<T, RDPs>,\n subFn: Observer<ObserveObjectsCallbackArgs<T, RDPs>>,\n ): Unsubscribable;\n\n /**\n * Observe an ObjectSet with automatic updates when matching objects change.\n *\n * @param baseObjectSet - The base ObjectSet to observe\n * @param options - Options for transforming and observing the ObjectSet\n * @param subFn - Observer that receives ObjectSet state updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports all ObjectSet operations:\n * - Filtering with where clauses\n * - Derived properties with withProperties\n * - Set operations (union, intersect, subtract)\n * - Link traversal with pivotTo\n * - Sorting and pagination\n */\n observeObjectSet<\n T extends ObjectTypeDefinition,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n >(\n baseObjectSet: ObjectSet<T>,\n options: ObserveObjectSetOptions<T, RDPs>,\n subFn: Observer<ObserveObjectSetArgs<T, RDPs>>,\n ): Unsubscribable;\n\n /**\n * Observe an aggregation query with automatic updates when underlying data changes.\n *\n * @param options - Aggregation configuration including where, aggregate spec, and derived properties\n * @param subFn - Observer that receives aggregation result updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports:\n * - Filtering with where clauses\n * - Derived properties (RDPs) via withProperties\n * - Set intersections\n * - GroupBy and metric aggregations\n * - Automatic updates when source data changes\n */\n observeAggregation<\n T extends ObjectOrInterfaceDefinition,\n A extends AggregateOpts<T>,\n RDPs extends Record<string, SimplePropertyDef> = {},\n >(\n options: ObserveAggregationOptions<T, A, RDPs>,\n subFn: Observer<ObserveAggregationArgs<T, A>>,\n ): Unsubscribable;\n\n /**\n * Observe a function execution with automatic updates.\n *\n * @param queryDef - The QueryDefinition to execute\n * @param params - Parameters to pass to the function (undefined if no params)\n * @param options - Observation options including invalidation configuration\n * @param subFn - Observer that receives function result updates\n * @returns Subscription that can be unsubscribed to stop updates\n *\n * Supports:\n * - Automatic caching and deduplication\n * - Dependency-based invalidation (dependsOn object types)\n * - Instance-based invalidation (dependsOnObjects)\n * - Manual refetch via invalidateFunction()\n */\n observeFunction<Q extends QueryDefinition<unknown>>(\n queryDef: Q,\n params: Record<string, unknown> | undefined,\n options: ObserveFunctionOptions,\n subFn: Observer<ObserveFunctionCallbackArgs<Q>>,\n ): Unsubscribable;\n\n /**\n * Execute an action with optional optimistic updates.\n *\n * @param action - Action definition to execute\n * @param args - Arguments for the action\n * @param opts - Options including optimistic updates\n * @returns Promise that resolves when the action completes\n *\n * When providing optimistic updates:\n * - Changes appear immediately in the UI\n * - Server request still happens in background\n * - On success, server data replaces optimistic data\n * - On failure, optimistic changes automatically roll back\n */\n applyAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args:\n | Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0]\n | Array<Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0]>,\n opts?: ObservableClient.ApplyActionOptions,\n ) => Promise<ActionEditResponse>;\n\n /**\n * Validate action parameters without executing the action.\n *\n * @param action - Action definition to validate\n * @param args - Arguments to validate\n * @returns Promise with validation result\n *\n * Use this to:\n * - Pre-validate forms before submission\n * - Display warnings or errors in the UI\n * - Enable/disable action buttons based on validity\n */\n validateAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n ) => Promise<ActionValidationResponse>;\n\n /**\n * Invalidates the entire cache, forcing all queries to refetch.\n * Use sparingly as this can cause significant network traffic.\n */\n invalidateAll(): Promise<void>;\n\n /**\n * Invalidates specific objects in the cache.\n * @param objects - Single object or array of objects to invalidate\n */\n invalidateObjects(\n objects:\n | Osdk.Instance<ObjectTypeDefinition>\n | ReadonlyArray<Osdk.Instance<ObjectTypeDefinition>>,\n ): Promise<void>;\n\n /**\n * Invalidates all cached data for a specific object type.\n * This includes:\n * - All objects of the specified type\n * - All lists containing objects of this type\n * - All links where the source is of this type\n *\n * @param type - Object type definition or API name string\n * @returns Promise that resolves when invalidation is complete\n */\n invalidateObjectType<T extends ObjectTypeDefinition>(\n type: T | T[\"apiName\"],\n ): Promise<void>;\n\n /**\n * Invalidate function queries.\n * - If params undefined, invalidates ALL queries for this function\n * - If params provided, invalidates only the query with exact params match\n *\n * @param apiName - Function API name string or QueryDefinition\n * @param params - Optional params for exact match\n */\n invalidateFunction(\n apiName: string | QueryDefinition<unknown>,\n params?: Record<string, unknown>,\n ): Promise<void>;\n\n /**\n * Invalidate functions that depend on a specific object instance.\n *\n * @param apiName - Object type API name\n * @param primaryKey - Object primary key\n */\n invalidateFunctionsByObject(\n apiName: string,\n primaryKey: string | number,\n ): Promise<void>;\n\n canonicalizeWhereClause: <\n T extends ObjectOrInterfaceDefinition,\n RDPs extends Record<string, SimplePropertyDef> = {},\n >(\n where: WhereClause<T, RDPs>,\n ) => Canonical<WhereClause<T, RDPs>>;\n}\n\nexport function createObservableClient(client: Client): ObservableClient {\n // First we need a modified client that adds an extra header so we know its\n // an observable client\n const tweakedClient = createClientFromContext({\n ...client[additionalContext],\n\n fetch: createFetchHeaderMutator(\n client[additionalContext].fetch,\n (headers) => {\n headers.set(\n \"Fetch-User-Agent\",\n [\n headers.get(\"Fetch-User-Agent\"),\n OBSERVABLE_USER_AGENT,\n ].filter(x => x && x?.length > 0).join(\" \"),\n );\n return headers;\n },\n ),\n });\n\n // Then we use that client instead. Because the `client` does not hold\n // any real state, this whole thing works.\n return new ObservableClientImpl(new Store(tweakedClient));\n}\n\nexport interface Unsubscribable {\n unsubscribe: () => void;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAqBA,SAASA,wBAAwB,QAAQ,wBAAwB;AAEjE,SAASC,iBAAiB,QAAqB,cAAc;AAC7D,SAASC,uBAAuB,QAAQ,oBAAoB;AAE5D,SAASC,qBAAqB,QAAQ,sBAAsB;AAG5D,SAASC,oBAAoB,QAAQ,oCAAoC;AACzE,SAASC,KAAK,QAAQ,qBAAqB;AAAC,WAW3BC,gBAAgB;AAqKjC;AACA;AACA;;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA0NA,OAAO,SAASC,sBAAsBA,CAACC,MAAc,EAAoB;EACvE;EACA;EACA,MAAMC,aAAa,GAAGP,uBAAuB,CAAC;IAC5C,GAAGM,MAAM,CAACP,iBAAiB,CAAC;IAE5BS,KAAK,EAAEV,wBAAwB,CAC7BQ,MAAM,CAACP,iBAAiB,CAAC,CAACS,KAAK,EAC9BC,OAAO,IAAK;MACXA,OAAO,CAACC,GAAG,CACT,kBAAkB,EAClB,CACED,OAAO,CAACE,GAAG,CAAC,kBAAkB,CAAC,EAC/BV,qBAAqB,CACtB,CAACW,MAAM,CAACC,CAAC,IAAIA,CAAC,IAAIA,CAAC,EAAEC,MAAM,GAAG,CAAC,CAAC,CAACC,IAAI,CAAC,GAAG,CAC5C,CAAC;MACD,OAAON,OAAO;IAChB,CACF;EACF,CAAC,CAAC;;EAEF;EACA;EACA,OAAO,IAAIP,oBAAoB,CAAC,IAAIC,KAAK,CAACI,aAAa,CAAC,CAAC;AAC3D","ignoreList":[]}
@@ -37,36 +37,50 @@ export class BulkObjectLoader {
37
37
  this.#maxWait = maxWait;
38
38
  this.#maxEntries = maxEntries;
39
39
  }
40
- async fetch(apiName, primaryKey) {
40
+ async fetch(apiName, primaryKey, defType = "object") {
41
41
  const deferred = pDefer();
42
42
  const entry = this.#m.get(apiName);
43
43
  entry.data.push({
44
44
  primaryKey: primaryKey,
45
45
  deferred
46
46
  });
47
+ if (entry.defType === undefined) {
48
+ entry.defType = defType;
49
+ } else if (entry.defType !== defType) {
50
+ deferred.reject(new PalantirApiError(`Conflicting defType for ${apiName}: existing=${entry.defType}, new=${defType}`));
51
+ return deferred.promise;
52
+ }
47
53
  if (!entry.timer) {
48
54
  entry.timer = setTimeout(() => {
49
- this.#loadObjects(apiName, entry.data);
55
+ this.#loadObjects(apiName, entry.data, entry.defType ?? "object");
50
56
  }, this.#maxWait);
51
57
  }
52
58
  if (entry.data.length >= this.#maxEntries) {
53
59
  clearTimeout(entry.timer);
54
- this.#loadObjects(apiName, entry.data);
60
+ this.#loadObjects(apiName, entry.data, entry.defType ?? "object");
55
61
  }
56
62
  return await deferred.promise;
57
63
  }
58
- #loadObjects(apiName, arr) {
64
+ #loadObjects(apiName, arr, defType) {
59
65
  this.#m.delete(apiName);
60
- this.#reallyLoadObjects(apiName, arr).catch(e => {
66
+ const loadFn = defType === "interface" ? this.#loadInterfaceObjects(apiName, arr) : this.#loadObjectTypeObjects(apiName, arr);
67
+ loadFn.catch(e => {
61
68
  this.#logger?.error("Unhandled exception", e);
69
+ for (const {
70
+ primaryKey,
71
+ deferred
72
+ } of arr) {
73
+ const errorMessage = e instanceof Error ? e.message : String(e);
74
+ deferred.reject(new PalantirApiError(`Failed to load ${apiName} with pk ${primaryKey}: ${errorMessage}`));
75
+ }
62
76
  });
63
77
  }
64
- async #reallyLoadObjects(apiName, arr) {
65
- const miniDef = {
78
+ async #loadObjectTypeObjects(apiName, arr) {
79
+ const objectDef = {
66
80
  type: "object",
67
81
  apiName
68
82
  };
69
- const objMetadata = await this.#client.fetchMetadata(miniDef);
83
+ const objMetadata = await this.#client.fetchMetadata(objectDef);
70
84
  const pks = arr.map(x => x.primaryKey);
71
85
 
72
86
  // Use $eq for single object fetches (this is for public app compatibility)
@@ -82,7 +96,7 @@ export class BulkObjectLoader {
82
96
  };
83
97
  const {
84
98
  data
85
- } = await this.#client(miniDef).where(whereClause).fetchPage({
99
+ } = await this.#client(objectDef).where(whereClause).fetchPage({
86
100
  $pageSize: pks.length,
87
101
  $includeRid: true
88
102
  });
@@ -98,5 +112,53 @@ export class BulkObjectLoader {
98
112
  }
99
113
  }
100
114
  }
115
+ async #loadInterfaceObjects(apiName, arr) {
116
+ const pks = arr.map(x => x.primaryKey);
117
+ const interfaceMetadata = await this.#client.fetchMetadata({
118
+ type: "interface",
119
+ apiName
120
+ });
121
+ const implementingTypes = interfaceMetadata.implementedBy ?? [];
122
+ const foundObjects = new Map();
123
+ for (const objectTypeName of implementingTypes) {
124
+ const objectDef = {
125
+ type: "object",
126
+ apiName: objectTypeName
127
+ };
128
+ const objMetadata = await this.#client.fetchMetadata(objectDef);
129
+ const remainingPks = pks.filter(pk => !foundObjects.has(pk));
130
+ if (remainingPks.length === 0) {
131
+ break;
132
+ }
133
+ const whereClause = remainingPks.length === 1 ? {
134
+ [objMetadata.primaryKeyApiName]: {
135
+ $eq: remainingPks[0]
136
+ }
137
+ } : {
138
+ [objMetadata.primaryKeyApiName]: {
139
+ $in: remainingPks
140
+ }
141
+ };
142
+ const {
143
+ data
144
+ } = await this.#client(objectDef).where(whereClause).fetchPage({
145
+ $pageSize: remainingPks.length
146
+ });
147
+ for (const obj of data) {
148
+ foundObjects.set(obj.$primaryKey, obj);
149
+ }
150
+ }
151
+ for (const {
152
+ primaryKey,
153
+ deferred
154
+ } of arr) {
155
+ const object = foundObjects.get(primaryKey);
156
+ if (object) {
157
+ deferred.resolve(object);
158
+ } else {
159
+ deferred.reject(new PalantirApiError(`Interface ${apiName} object not found: ${primaryKey}`));
160
+ }
161
+ }
162
+ }
101
163
  }
102
164
  //# sourceMappingURL=BulkObjectLoader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BulkObjectLoader.js","names":["PalantirApiError","DefaultMap","DefaultWeakMap","pDefer","additionalContext","weakCache","c","BulkObjectLoader","getBulkObjectLoader","client","get","m","data","timer","undefined","logger","maxWait","maxEntries","constructor","fetch","apiName","primaryKey","deferred","entry","push","setTimeout","loadObjects","length","clearTimeout","promise","#loadObjects","arr","delete","reallyLoadObjects","catch","e","error","#reallyLoadObjects","miniDef","type","objMetadata","fetchMetadata","pks","map","x","whereClause","primaryKeyApiName","$eq","$in","where","fetchPage","$pageSize","$includeRid","object","find","$primaryKey","resolve","reject"],"sources":["BulkObjectLoader.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Logger, ObjectTypeDefinition } from \"@osdk/api\";\nimport { PalantirApiError } from \"@osdk/shared.net.errors\";\nimport { DefaultMap, DefaultWeakMap } from \"mnemonist\";\nimport type { DeferredPromise } from \"p-defer\";\nimport pDefer from \"p-defer\";\nimport { additionalContext, type Client } from \"../../Client.js\";\nimport type {\n ObjectHolder,\n} from \"../../object/convertWireToOsdkObjects/ObjectHolder.js\";\n\ninterface InternalValue {\n primaryKey: string;\n deferred: DeferredPromise<ObjectHolder>;\n}\n\ninterface Accumulator {\n data: InternalValue[];\n timer?: ReturnType<typeof setTimeout>;\n}\n\nconst weakCache = new DefaultWeakMap<Client, BulkObjectLoader>(c =>\n new BulkObjectLoader(c)\n);\n\nexport function getBulkObjectLoader(client: Client): BulkObjectLoader {\n return weakCache.get(client);\n}\n\nexport class BulkObjectLoader {\n #client: Client;\n\n #m = new DefaultMap<string, Accumulator>(() => ({\n data: [],\n timer: undefined,\n }));\n #logger: Logger | undefined;\n #maxWait: number;\n #maxEntries: number;\n\n constructor(client: Client, maxWait = 25, maxEntries = 100) {\n this.#client = client;\n this.#logger = client[additionalContext].logger;\n this.#maxWait = maxWait;\n this.#maxEntries = maxEntries;\n }\n\n public async fetch(\n apiName: string,\n primaryKey: string | number | boolean,\n ): Promise<ObjectHolder> {\n const deferred = pDefer<ObjectHolder>();\n\n const entry = this.#m.get(apiName);\n entry.data.push({\n primaryKey: primaryKey as string,\n deferred,\n });\n\n if (!entry.timer) {\n entry.timer = setTimeout(() => {\n this.#loadObjects(apiName, entry.data);\n }, this.#maxWait);\n }\n\n if (entry.data.length >= this.#maxEntries) {\n clearTimeout(entry.timer);\n this.#loadObjects(apiName, entry.data);\n }\n\n return await deferred.promise;\n }\n\n #loadObjects(apiName: string, arr: InternalValue[]) {\n this.#m.delete(apiName);\n\n this.#reallyLoadObjects(apiName, arr).catch((e: unknown) => {\n this.#logger?.error(\"Unhandled exception\", e);\n });\n }\n\n async #reallyLoadObjects(apiName: string, arr: InternalValue[]) {\n const miniDef = { type: \"object\", apiName } as ObjectTypeDefinition;\n const objMetadata = await this.#client.fetchMetadata(miniDef);\n\n const pks = arr.map(x => x.primaryKey);\n\n // Use $eq for single object fetches (this is for public app compatibility)\n // Use $in for batch fetches\n const whereClause = pks.length === 1\n ? { [objMetadata.primaryKeyApiName]: { $eq: pks[0] } }\n : { [objMetadata.primaryKeyApiName]: { $in: pks } };\n\n const { data } = await this.#client(miniDef)\n .where(whereClause).fetchPage({\n $pageSize: pks.length,\n $includeRid: true,\n });\n\n for (const { primaryKey, deferred } of arr) {\n const object = data.find(x => x.$primaryKey === primaryKey) as\n | ObjectHolder\n | undefined;\n if (object) {\n deferred.resolve(object);\n } else {\n deferred.reject(\n new PalantirApiError(`Object not found: ${primaryKey}`),\n );\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"BulkObjectLoader.js","names":["PalantirApiError","DefaultMap","DefaultWeakMap","pDefer","additionalContext","weakCache","c","BulkObjectLoader","getBulkObjectLoader","client","get","m","data","timer","undefined","logger","maxWait","maxEntries","constructor","fetch","apiName","primaryKey","defType","deferred","entry","push","reject","promise","setTimeout","loadObjects","length","clearTimeout","#loadObjects","arr","delete","loadFn","loadInterfaceObjects","loadObjectTypeObjects","catch","e","error","errorMessage","Error","message","String","#loadObjectTypeObjects","objectDef","type","objMetadata","fetchMetadata","pks","map","x","whereClause","primaryKeyApiName","$eq","$in","where","fetchPage","$pageSize","$includeRid","object","find","$primaryKey","resolve","#loadInterfaceObjects","interfaceMetadata","implementingTypes","implementedBy","foundObjects","Map","objectTypeName","remainingPks","filter","pk","has","obj","set"],"sources":["BulkObjectLoader.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n InterfaceDefinition,\n Logger,\n ObjectTypeDefinition,\n} from \"@osdk/api\";\nimport { PalantirApiError } from \"@osdk/shared.net.errors\";\nimport { DefaultMap, DefaultWeakMap } from \"mnemonist\";\nimport type { DeferredPromise } from \"p-defer\";\nimport pDefer from \"p-defer\";\nimport { additionalContext, type Client } from \"../../Client.js\";\nimport type {\n ObjectHolder,\n} from \"../../object/convertWireToOsdkObjects/ObjectHolder.js\";\nimport type { DefType } from \"../../util/interfaceUtils.js\";\n\ninterface InternalValue {\n primaryKey: string;\n deferred: DeferredPromise<ObjectHolder>;\n}\n\ninterface Accumulator {\n data: InternalValue[];\n timer?: ReturnType<typeof setTimeout>;\n defType?: DefType;\n}\n\nconst weakCache = new DefaultWeakMap<Client, BulkObjectLoader>(c =>\n new BulkObjectLoader(c)\n);\n\nexport function getBulkObjectLoader(client: Client): BulkObjectLoader {\n return weakCache.get(client);\n}\n\nexport class BulkObjectLoader {\n #client: Client;\n\n #m = new DefaultMap<string, Accumulator>(() => ({\n data: [],\n timer: undefined,\n }));\n #logger: Logger | undefined;\n #maxWait: number;\n #maxEntries: number;\n\n constructor(client: Client, maxWait = 25, maxEntries = 100) {\n this.#client = client;\n this.#logger = client[additionalContext].logger;\n this.#maxWait = maxWait;\n this.#maxEntries = maxEntries;\n }\n\n public async fetch(\n apiName: string,\n primaryKey: string | number | boolean,\n defType: DefType = \"object\",\n ): Promise<ObjectHolder> {\n const deferred = pDefer<ObjectHolder>();\n\n const entry = this.#m.get(apiName);\n entry.data.push({\n primaryKey: primaryKey as string,\n deferred,\n });\n\n if (entry.defType === undefined) {\n entry.defType = defType;\n } else if (entry.defType !== defType) {\n deferred.reject(\n new PalantirApiError(\n `Conflicting defType for ${apiName}: existing=${entry.defType}, new=${defType}`,\n ),\n );\n return deferred.promise;\n }\n\n if (!entry.timer) {\n entry.timer = setTimeout(() => {\n this.#loadObjects(apiName, entry.data, entry.defType ?? \"object\");\n }, this.#maxWait);\n }\n\n if (entry.data.length >= this.#maxEntries) {\n clearTimeout(entry.timer);\n this.#loadObjects(apiName, entry.data, entry.defType ?? \"object\");\n }\n\n return await deferred.promise;\n }\n\n #loadObjects(\n apiName: string,\n arr: InternalValue[],\n defType: DefType,\n ) {\n this.#m.delete(apiName);\n\n const loadFn = defType === \"interface\"\n ? this.#loadInterfaceObjects(apiName, arr)\n : this.#loadObjectTypeObjects(apiName, arr);\n\n loadFn.catch((e: unknown) => {\n this.#logger?.error(\"Unhandled exception\", e);\n for (const { primaryKey, deferred } of arr) {\n const errorMessage = e instanceof Error ? e.message : String(e);\n deferred.reject(\n new PalantirApiError(\n `Failed to load ${apiName} with pk ${primaryKey}: ${errorMessage}`,\n ),\n );\n }\n });\n }\n\n async #loadObjectTypeObjects(apiName: string, arr: InternalValue[]) {\n const objectDef = { type: \"object\", apiName } as ObjectTypeDefinition;\n const objMetadata = await this.#client.fetchMetadata(objectDef);\n\n const pks = arr.map(x => x.primaryKey);\n\n // Use $eq for single object fetches (this is for public app compatibility)\n // Use $in for batch fetches\n const whereClause = pks.length === 1\n ? { [objMetadata.primaryKeyApiName]: { $eq: pks[0] } }\n : { [objMetadata.primaryKeyApiName]: { $in: pks } };\n\n const { data } = await this.#client(objectDef)\n .where(whereClause).fetchPage({\n $pageSize: pks.length,\n $includeRid: true,\n });\n\n for (const { primaryKey, deferred } of arr) {\n const object = data.find(x => x.$primaryKey === primaryKey) as\n | ObjectHolder\n | undefined;\n if (object) {\n deferred.resolve(object);\n } else {\n deferred.reject(\n new PalantirApiError(`Object not found: ${primaryKey}`),\n );\n }\n }\n }\n\n async #loadInterfaceObjects(apiName: string, arr: InternalValue[]) {\n const pks = arr.map(x => x.primaryKey);\n\n const interfaceDef = {\n type: \"interface\",\n apiName,\n } as InterfaceDefinition;\n\n const interfaceMetadata = await this.#client.fetchMetadata(interfaceDef);\n const implementingTypes = interfaceMetadata.implementedBy ?? [];\n\n const foundObjects = new Map<string | number, ObjectHolder>();\n\n for (const objectTypeName of implementingTypes) {\n const objectDef = {\n type: \"object\",\n apiName: objectTypeName,\n } as ObjectTypeDefinition;\n const objMetadata = await this.#client.fetchMetadata(objectDef);\n\n const remainingPks = pks.filter(pk => !foundObjects.has(pk));\n if (remainingPks.length === 0) {\n break;\n }\n\n const whereClause = remainingPks.length === 1\n ? { [objMetadata.primaryKeyApiName]: { $eq: remainingPks[0] } }\n : { [objMetadata.primaryKeyApiName]: { $in: remainingPks } };\n\n const { data } = await this.#client(objectDef)\n .where(whereClause).fetchPage({\n $pageSize: remainingPks.length,\n });\n\n for (const obj of data) {\n foundObjects.set(obj.$primaryKey, obj as ObjectHolder);\n }\n }\n\n for (const { primaryKey, deferred } of arr) {\n const object = foundObjects.get(primaryKey);\n if (object) {\n deferred.resolve(object);\n } else {\n deferred.reject(\n new PalantirApiError(\n `Interface ${apiName} object not found: ${primaryKey}`,\n ),\n );\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -156,5 +156,84 @@ describe(BulkObjectLoader, () => {
156
156
  });
157
157
  vi.useRealTimers();
158
158
  });
159
+ describe("interface loading", () => {
160
+ const mockObjectSet = data => {
161
+ const os = {
162
+ where: () => os,
163
+ fetchPage: vi.fn().mockResolvedValue({
164
+ data
165
+ })
166
+ };
167
+ return os;
168
+ };
169
+ it("loads interface objects by querying implementing types", async () => {
170
+ const loader = new BulkObjectLoader(client, 25, 100);
171
+ vi.useFakeTimers();
172
+
173
+ // eslint-disable-next-line @typescript-eslint/unbound-method
174
+ vi.mocked(client.fetchMetadata).mockResolvedValueOnce({
175
+ type: "interface",
176
+ implementedBy: ["Employee"],
177
+ links: {},
178
+ apiName: "FooInterface",
179
+ displayName: "FooInterface",
180
+ description: undefined,
181
+ properties: {},
182
+ rid: "ri.test"
183
+ }).mockResolvedValueOnce({
184
+ primaryKeyApiName: "employeeId"
185
+ });
186
+ client.mockReturnValueOnce(mockObjectSet([{
187
+ $apiName: "Employee",
188
+ $objectType: "Employee",
189
+ $primaryKey: 1
190
+ }]));
191
+ const loadPromise = loader.fetch("FooInterface", 1, "interface");
192
+ vi.advanceTimersByTime(26);
193
+ await expect(loadPromise).resolves.toMatchObject({
194
+ $primaryKey: 1
195
+ });
196
+ vi.useRealTimers();
197
+ });
198
+ it("rejects when interface object is not found in any implementing type", async () => {
199
+ const loader = new BulkObjectLoader(client, 25, 100);
200
+ vi.useFakeTimers();
201
+
202
+ // eslint-disable-next-line @typescript-eslint/unbound-method
203
+ vi.mocked(client.fetchMetadata).mockResolvedValueOnce({
204
+ type: "interface",
205
+ implementedBy: ["Employee"],
206
+ links: {},
207
+ apiName: "FooInterface",
208
+ displayName: "FooInterface",
209
+ description: undefined,
210
+ properties: {},
211
+ rid: "ri.test"
212
+ }).mockResolvedValueOnce({
213
+ primaryKeyApiName: "employeeId"
214
+ });
215
+ client.mockReturnValueOnce(mockObjectSet([]));
216
+ const loadPromise = loader.fetch("FooInterface", 1, "interface");
217
+ vi.advanceTimersByTime(26);
218
+ await expect(loadPromise).rejects.toThrow("Interface FooInterface object not found: 1");
219
+ vi.useRealTimers();
220
+ });
221
+ it("loads object type when defType='object' (default)", async () => {
222
+ const loader = new BulkObjectLoader(client, 25, 100);
223
+ vi.useFakeTimers();
224
+ const firstRequest = mockClient.mockFetchPageOnce();
225
+ const loadPromise = loader.fetch("Employee", 1);
226
+ vi.advanceTimersByTime(26);
227
+ firstRequest.resolve({
228
+ data: [employees[1]],
229
+ nextPageToken: undefined,
230
+ totalCount: "1"
231
+ });
232
+ await expect(loadPromise).resolves.toMatchObject({
233
+ $primaryKey: 1
234
+ });
235
+ vi.useRealTimers();
236
+ });
237
+ });
159
238
  });
160
239
  //# sourceMappingURL=BulkObjectLoader.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BulkObjectLoader.test.js","names":["beforeEach","describe","expect","it","vi","BulkObjectLoader","createClientMockHelper","client","mockClient","mocked","fetchMetadata","mockReturnValue","Promise","resolve","primaryKeyApiName","employees","$apiName","$objectType","$primaryKey","loader","firstRequest","mockFetchPageOnce","secondRequest","load0","fetch","load1","load2","data","nextPageToken","undefined","totalCount","resolves","toMatchObject","mock","fn","then","not","toHaveBeenCalled","useFakeTimers","advanceTimersByTime","runOnlyPendingTimers","mockThen","useRealTimers","whereClauses","mockObjectSet","where","clause","push","fetchPage","mockResolvedValue","mockReturnValueOnce","toEqual","id","$eq","length","mockObjectSet2","all","$in"],"sources":["BulkObjectLoader.test.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n ObjectMetadata,\n ObjectSet,\n ObjectTypeDefinition,\n WhereClause,\n} from \"@osdk/api\";\nimport type { Mock } from \"vitest\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport type { Client } from \"../../Client.js\";\nimport { BulkObjectLoader } from \"./BulkObjectLoader.js\";\nimport { createClientMockHelper, type MockClientHelper } from \"./testUtils.js\";\n\ndescribe(BulkObjectLoader, () => {\n let client: Mock<Client> & Client;\n let mockClient: MockClientHelper;\n\n beforeEach(async () => {\n mockClient = createClientMockHelper();\n client = mockClient.client;\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n vi.mocked(client.fetchMetadata).mockReturnValue(\n Promise.resolve(\n {\n primaryKeyApiName: \"id\",\n } satisfies Pick<ObjectMetadata, \"primaryKeyApiName\"> as ObjectMetadata,\n ),\n );\n });\n\n const employees = [\n {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 0,\n },\n {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 1,\n },\n {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 2,\n },\n ];\n\n it(\"splits up work by count\", async () => {\n const loader = new BulkObjectLoader(client, 25, /*ms*/ 2 /*entries*/);\n\n const firstRequest = mockClient.mockFetchPageOnce();\n const secondRequest = mockClient.mockFetchPageOnce();\n\n const load0 = loader.fetch(\"Employee\", 0);\n const load1 = loader.fetch(\"Employee\", 1);\n const load2 = loader.fetch(\"Employee\", 2);\n\n firstRequest.resolve({\n data: [employees[0], employees[1]],\n nextPageToken: undefined,\n totalCount: \"2\",\n });\n\n await expect(load0).resolves.toMatchObject({\n $primaryKey: 0,\n });\n\n await expect(load1).resolves.toMatchObject({\n $primaryKey: 1,\n });\n\n const mock = vi.fn();\n void load2.then(mock);\n expect(mock).not.toHaveBeenCalled();\n\n secondRequest.resolve({\n data: [employees[2]],\n nextPageToken: undefined,\n totalCount: \"1\",\n });\n\n await expect(load2).resolves.toMatchObject({\n $primaryKey: 2,\n });\n\n expect(mock).toHaveBeenCalled();\n });\n\n it(\"splits up work by time\", async () => {\n const loader = new BulkObjectLoader(client, /*ms*/ 25, /*entries*/ 100);\n\n const firstRequest = mockClient.mockFetchPageOnce();\n const secondRequest = mockClient.mockFetchPageOnce();\n\n vi.useFakeTimers();\n\n const load0 = loader.fetch(\"Employee\", 0);\n\n vi.advanceTimersByTime(26);\n\n const load1 = loader.fetch(\"Employee\", 1);\n const load2 = loader.fetch(\"Employee\", 2);\n\n firstRequest.resolve({\n data: [employees[0]],\n nextPageToken: undefined,\n totalCount: \"1\",\n });\n\n vi.runOnlyPendingTimers();\n\n await expect(load0).resolves.toMatchObject({\n $primaryKey: 0,\n });\n\n const mockThen = vi.fn();\n void load2.then(mockThen);\n\n expect(mockThen).not.toHaveBeenCalled();\n\n secondRequest.resolve({\n data: [\n employees[1],\n employees[2],\n ],\n nextPageToken: undefined,\n totalCount: \"2\",\n });\n\n await expect(load1).resolves.toMatchObject({\n $primaryKey: 1,\n });\n\n await expect(load2).resolves.toMatchObject({\n $primaryKey: 2,\n });\n\n expect(mockThen).toHaveBeenCalled();\n\n vi.useRealTimers();\n });\n\n it(\"uses $eq for single object and $in for multiple objects\", async () => {\n const loader = new BulkObjectLoader(client, 25, 100);\n\n vi.useFakeTimers();\n\n const whereClauses: WhereClause<ObjectTypeDefinition>[] = [];\n\n const mockObjectSet: ObjectSet<ObjectTypeDefinition> = {\n where: (clause) => {\n whereClauses.push(clause);\n return mockObjectSet;\n },\n fetchPage: vi.fn().mockResolvedValue({\n data: [employees[0]],\n nextPageToken: undefined,\n totalCount: \"1\",\n }),\n } as Pick<\n ObjectSet<ObjectTypeDefinition>,\n \"fetchPage\" | \"where\"\n > as ObjectSet<ObjectTypeDefinition>;\n\n client.mockReturnValueOnce(mockObjectSet);\n const load0 = loader.fetch(\"Employee\", 0);\n\n vi.advanceTimersByTime(26);\n\n await load0;\n\n expect(whereClauses[0]).toEqual({\n id: { $eq: 0 },\n });\n\n whereClauses.length = 0;\n\n const mockObjectSet2: ObjectSet<ObjectTypeDefinition> = {\n where: (clause) => {\n whereClauses.push(clause);\n return mockObjectSet2;\n },\n fetchPage: vi.fn().mockResolvedValue({\n data: [employees[1], employees[2]],\n nextPageToken: undefined,\n totalCount: \"2\",\n }),\n } as Pick<\n ObjectSet<ObjectTypeDefinition>,\n \"fetchPage\" | \"where\"\n > as ObjectSet<ObjectTypeDefinition>;\n\n client.mockReturnValueOnce(mockObjectSet2);\n\n const load1 = loader.fetch(\"Employee\", 1);\n const load2 = loader.fetch(\"Employee\", 2);\n\n vi.advanceTimersByTime(26);\n\n await Promise.all([load1, load2]);\n\n expect(whereClauses[0]).toEqual({\n id: { $in: [1, 2] },\n });\n\n vi.useRealTimers();\n });\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"BulkObjectLoader.test.js","names":["beforeEach","describe","expect","it","vi","BulkObjectLoader","createClientMockHelper","client","mockClient","mocked","fetchMetadata","mockReturnValue","Promise","resolve","primaryKeyApiName","employees","$apiName","$objectType","$primaryKey","loader","firstRequest","mockFetchPageOnce","secondRequest","load0","fetch","load1","load2","data","nextPageToken","undefined","totalCount","resolves","toMatchObject","mock","fn","then","not","toHaveBeenCalled","useFakeTimers","advanceTimersByTime","runOnlyPendingTimers","mockThen","useRealTimers","whereClauses","mockObjectSet","where","clause","push","fetchPage","mockResolvedValue","mockReturnValueOnce","toEqual","id","$eq","length","mockObjectSet2","all","$in","os","mockResolvedValueOnce","type","implementedBy","links","apiName","displayName","description","properties","rid","loadPromise","rejects","toThrow"],"sources":["BulkObjectLoader.test.ts"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n InterfaceMetadata,\n ObjectMetadata,\n ObjectSet,\n ObjectTypeDefinition,\n WhereClause,\n} from \"@osdk/api\";\nimport type { Mock } from \"vitest\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport type { Client } from \"../../Client.js\";\nimport { BulkObjectLoader } from \"./BulkObjectLoader.js\";\nimport { createClientMockHelper, type MockClientHelper } from \"./testUtils.js\";\n\ndescribe(BulkObjectLoader, () => {\n let client: Mock<Client> & Client;\n let mockClient: MockClientHelper;\n\n beforeEach(async () => {\n mockClient = createClientMockHelper();\n client = mockClient.client;\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n vi.mocked(client.fetchMetadata).mockReturnValue(\n Promise.resolve(\n {\n primaryKeyApiName: \"id\",\n } satisfies Pick<ObjectMetadata, \"primaryKeyApiName\"> as ObjectMetadata,\n ),\n );\n });\n\n const employees = [\n {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 0,\n },\n {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 1,\n },\n {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 2,\n },\n ];\n\n it(\"splits up work by count\", async () => {\n const loader = new BulkObjectLoader(client, 25, /*ms*/ 2 /*entries*/);\n\n const firstRequest = mockClient.mockFetchPageOnce();\n const secondRequest = mockClient.mockFetchPageOnce();\n\n const load0 = loader.fetch(\"Employee\", 0);\n const load1 = loader.fetch(\"Employee\", 1);\n const load2 = loader.fetch(\"Employee\", 2);\n\n firstRequest.resolve({\n data: [employees[0], employees[1]],\n nextPageToken: undefined,\n totalCount: \"2\",\n });\n\n await expect(load0).resolves.toMatchObject({\n $primaryKey: 0,\n });\n\n await expect(load1).resolves.toMatchObject({\n $primaryKey: 1,\n });\n\n const mock = vi.fn();\n void load2.then(mock);\n expect(mock).not.toHaveBeenCalled();\n\n secondRequest.resolve({\n data: [employees[2]],\n nextPageToken: undefined,\n totalCount: \"1\",\n });\n\n await expect(load2).resolves.toMatchObject({\n $primaryKey: 2,\n });\n\n expect(mock).toHaveBeenCalled();\n });\n\n it(\"splits up work by time\", async () => {\n const loader = new BulkObjectLoader(client, /*ms*/ 25, /*entries*/ 100);\n\n const firstRequest = mockClient.mockFetchPageOnce();\n const secondRequest = mockClient.mockFetchPageOnce();\n\n vi.useFakeTimers();\n\n const load0 = loader.fetch(\"Employee\", 0);\n\n vi.advanceTimersByTime(26);\n\n const load1 = loader.fetch(\"Employee\", 1);\n const load2 = loader.fetch(\"Employee\", 2);\n\n firstRequest.resolve({\n data: [employees[0]],\n nextPageToken: undefined,\n totalCount: \"1\",\n });\n\n vi.runOnlyPendingTimers();\n\n await expect(load0).resolves.toMatchObject({\n $primaryKey: 0,\n });\n\n const mockThen = vi.fn();\n void load2.then(mockThen);\n\n expect(mockThen).not.toHaveBeenCalled();\n\n secondRequest.resolve({\n data: [\n employees[1],\n employees[2],\n ],\n nextPageToken: undefined,\n totalCount: \"2\",\n });\n\n await expect(load1).resolves.toMatchObject({\n $primaryKey: 1,\n });\n\n await expect(load2).resolves.toMatchObject({\n $primaryKey: 2,\n });\n\n expect(mockThen).toHaveBeenCalled();\n\n vi.useRealTimers();\n });\n\n it(\"uses $eq for single object and $in for multiple objects\", async () => {\n const loader = new BulkObjectLoader(client, 25, 100);\n\n vi.useFakeTimers();\n\n const whereClauses: WhereClause<ObjectTypeDefinition>[] = [];\n\n const mockObjectSet: ObjectSet<ObjectTypeDefinition> = {\n where: (clause) => {\n whereClauses.push(clause);\n return mockObjectSet;\n },\n fetchPage: vi.fn().mockResolvedValue({\n data: [employees[0]],\n nextPageToken: undefined,\n totalCount: \"1\",\n }),\n } as Pick<\n ObjectSet<ObjectTypeDefinition>,\n \"fetchPage\" | \"where\"\n > as ObjectSet<ObjectTypeDefinition>;\n\n client.mockReturnValueOnce(mockObjectSet);\n const load0 = loader.fetch(\"Employee\", 0);\n\n vi.advanceTimersByTime(26);\n\n await load0;\n\n expect(whereClauses[0]).toEqual({\n id: { $eq: 0 },\n });\n\n whereClauses.length = 0;\n\n const mockObjectSet2: ObjectSet<ObjectTypeDefinition> = {\n where: (clause) => {\n whereClauses.push(clause);\n return mockObjectSet2;\n },\n fetchPage: vi.fn().mockResolvedValue({\n data: [employees[1], employees[2]],\n nextPageToken: undefined,\n totalCount: \"2\",\n }),\n } as Pick<\n ObjectSet<ObjectTypeDefinition>,\n \"fetchPage\" | \"where\"\n > as ObjectSet<ObjectTypeDefinition>;\n\n client.mockReturnValueOnce(mockObjectSet2);\n\n const load1 = loader.fetch(\"Employee\", 1);\n const load2 = loader.fetch(\"Employee\", 2);\n\n vi.advanceTimersByTime(26);\n\n await Promise.all([load1, load2]);\n\n expect(whereClauses[0]).toEqual({\n id: { $in: [1, 2] },\n });\n\n vi.useRealTimers();\n });\n\n describe(\"interface loading\", () => {\n const mockObjectSet = (data: unknown[]) => {\n const os: ObjectSet<ObjectTypeDefinition> = {\n where: () => os,\n fetchPage: vi.fn().mockResolvedValue({ data }),\n } as Pick<\n ObjectSet<ObjectTypeDefinition>,\n \"fetchPage\" | \"where\"\n > as ObjectSet<ObjectTypeDefinition>;\n return os;\n };\n\n it(\"loads interface objects by querying implementing types\", async () => {\n const loader = new BulkObjectLoader(client, 25, 100);\n vi.useFakeTimers();\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n vi.mocked(client.fetchMetadata)\n .mockResolvedValueOnce(\n {\n type: \"interface\",\n implementedBy: [\"Employee\"],\n links: {},\n apiName: \"FooInterface\",\n displayName: \"FooInterface\",\n description: undefined,\n properties: {},\n rid: \"ri.test\",\n } satisfies InterfaceMetadata,\n )\n .mockResolvedValueOnce(\n { primaryKeyApiName: \"employeeId\" } as ObjectMetadata,\n );\n\n const fullObj = {\n $apiName: \"Employee\",\n $objectType: \"Employee\",\n $primaryKey: 1,\n };\n\n client.mockReturnValueOnce(mockObjectSet([fullObj]));\n\n const loadPromise = loader.fetch(\"FooInterface\", 1, \"interface\");\n vi.advanceTimersByTime(26);\n\n await expect(loadPromise).resolves.toMatchObject({ $primaryKey: 1 });\n vi.useRealTimers();\n });\n\n it(\"rejects when interface object is not found in any implementing type\", async () => {\n const loader = new BulkObjectLoader(client, 25, 100);\n vi.useFakeTimers();\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n vi.mocked(client.fetchMetadata)\n .mockResolvedValueOnce(\n {\n type: \"interface\",\n implementedBy: [\"Employee\"],\n links: {},\n apiName: \"FooInterface\",\n displayName: \"FooInterface\",\n description: undefined,\n properties: {},\n rid: \"ri.test\",\n } satisfies InterfaceMetadata,\n )\n .mockResolvedValueOnce(\n { primaryKeyApiName: \"employeeId\" } as ObjectMetadata,\n );\n\n client.mockReturnValueOnce(mockObjectSet([]));\n\n const loadPromise = loader.fetch(\"FooInterface\", 1, \"interface\");\n vi.advanceTimersByTime(26);\n\n await expect(loadPromise).rejects.toThrow(\n \"Interface FooInterface object not found: 1\",\n );\n vi.useRealTimers();\n });\n\n it(\"loads object type when defType='object' (default)\", async () => {\n const loader = new BulkObjectLoader(client, 25, 100);\n vi.useFakeTimers();\n\n const firstRequest = mockClient.mockFetchPageOnce();\n\n const loadPromise = loader.fetch(\"Employee\", 1);\n vi.advanceTimersByTime(26);\n\n firstRequest.resolve({\n data: [employees[1]],\n nextPageToken: undefined,\n totalCount: \"1\",\n });\n\n await expect(loadPromise).resolves.toMatchObject({ $primaryKey: 1 });\n vi.useRealTimers();\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}