@osdk/client 2.5.0-beta.10 → 2.5.0-beta.11
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/CHANGELOG.md +13 -0
- package/build/browser/observable/ObjectSetPayload.js +2 -0
- package/build/browser/observable/ObjectSetPayload.js.map +1 -0
- package/build/browser/observable/ObservableClient.js.map +1 -1
- package/build/browser/observable/computeObjectSetCacheKey.js +64 -0
- package/build/browser/observable/computeObjectSetCacheKey.js.map +1 -0
- package/build/browser/observable/internal/Changes.js +3 -0
- package/build/browser/observable/internal/Changes.js.map +1 -1
- package/build/browser/observable/internal/KnownCacheKey.js.map +1 -1
- package/build/browser/observable/internal/ObservableClientImpl.js +8 -0
- package/build/browser/observable/internal/ObservableClientImpl.js.map +1 -1
- package/build/browser/observable/internal/Query.js +18 -1
- package/build/browser/observable/internal/Query.js.map +1 -1
- package/build/browser/observable/internal/Store.js +2 -0
- package/build/browser/observable/internal/Store.js.map +1 -1
- package/build/browser/observable/internal/objectset/ObjectSetCacheKey.js +2 -0
- package/build/browser/observable/internal/objectset/ObjectSetCacheKey.js.map +1 -0
- package/build/browser/observable/internal/objectset/ObjectSetHelper.js +69 -0
- package/build/browser/observable/internal/objectset/ObjectSetHelper.js.map +1 -0
- package/build/browser/observable/internal/objectset/ObjectSetQuery.js +151 -0
- package/build/browser/observable/internal/objectset/ObjectSetQuery.js.map +1 -0
- package/build/browser/observable/internal/objectset/ObjectSetQueryOptions.js +2 -0
- package/build/browser/observable/internal/objectset/ObjectSetQueryOptions.js.map +1 -0
- package/build/browser/public/unstable-do-not-use.js +1 -0
- package/build/browser/public/unstable-do-not-use.js.map +1 -1
- package/build/browser/util/UserAgent.js +2 -2
- package/build/cjs/{chunk-YADG7KA6.cjs → chunk-3LPXQHP5.cjs} +4 -4
- package/build/cjs/{chunk-YADG7KA6.cjs.map → chunk-3LPXQHP5.cjs.map} +1 -1
- package/build/cjs/index.cjs +6 -6
- package/build/cjs/public/unstable-do-not-use.cjs +389 -143
- package/build/cjs/public/unstable-do-not-use.cjs.map +1 -1
- package/build/cjs/public/unstable-do-not-use.d.cts +57 -6
- package/build/esm/observable/ObjectSetPayload.js +2 -0
- package/build/esm/observable/ObjectSetPayload.js.map +1 -0
- package/build/esm/observable/ObservableClient.js.map +1 -1
- package/build/esm/observable/computeObjectSetCacheKey.js +64 -0
- package/build/esm/observable/computeObjectSetCacheKey.js.map +1 -0
- package/build/esm/observable/internal/Changes.js +3 -0
- package/build/esm/observable/internal/Changes.js.map +1 -1
- package/build/esm/observable/internal/KnownCacheKey.js.map +1 -1
- package/build/esm/observable/internal/ObservableClientImpl.js +8 -0
- package/build/esm/observable/internal/ObservableClientImpl.js.map +1 -1
- package/build/esm/observable/internal/Query.js +18 -1
- package/build/esm/observable/internal/Query.js.map +1 -1
- package/build/esm/observable/internal/Store.js +2 -0
- package/build/esm/observable/internal/Store.js.map +1 -1
- package/build/esm/observable/internal/objectset/ObjectSetCacheKey.js +2 -0
- package/build/esm/observable/internal/objectset/ObjectSetCacheKey.js.map +1 -0
- package/build/esm/observable/internal/objectset/ObjectSetHelper.js +69 -0
- package/build/esm/observable/internal/objectset/ObjectSetHelper.js.map +1 -0
- package/build/esm/observable/internal/objectset/ObjectSetQuery.js +151 -0
- package/build/esm/observable/internal/objectset/ObjectSetQuery.js.map +1 -0
- package/build/esm/observable/internal/objectset/ObjectSetQueryOptions.js +2 -0
- package/build/esm/observable/internal/objectset/ObjectSetQueryOptions.js.map +1 -0
- package/build/esm/public/unstable-do-not-use.js +1 -0
- package/build/esm/public/unstable-do-not-use.js.map +1 -1
- package/build/esm/util/UserAgent.js +2 -2
- package/build/types/observable/ObjectSetPayload.d.ts +5 -0
- package/build/types/observable/ObjectSetPayload.d.ts.map +1 -0
- package/build/types/observable/ObservableClient.d.ts +33 -1
- package/build/types/observable/ObservableClient.d.ts.map +1 -1
- package/build/types/observable/computeObjectSetCacheKey.d.ts +16 -0
- package/build/types/observable/computeObjectSetCacheKey.d.ts.map +1 -0
- package/build/types/observable/internal/Changes.d.ts +5 -3
- package/build/types/observable/internal/Changes.d.ts.map +1 -1
- package/build/types/observable/internal/KnownCacheKey.d.ts +2 -1
- package/build/types/observable/internal/KnownCacheKey.d.ts.map +1 -1
- package/build/types/observable/internal/Query.d.ts.map +1 -1
- package/build/types/observable/internal/Store.d.ts +2 -0
- package/build/types/observable/internal/Store.d.ts.map +1 -1
- package/build/types/observable/internal/objectset/ObjectSetCacheKey.d.ts +16 -0
- package/build/types/observable/internal/objectset/ObjectSetCacheKey.d.ts.map +1 -0
- package/build/types/observable/internal/objectset/ObjectSetHelper.d.ts +19 -0
- package/build/types/observable/internal/objectset/ObjectSetHelper.d.ts.map +1 -0
- package/build/types/observable/internal/objectset/ObjectSetQuery.d.ts +34 -0
- package/build/types/observable/internal/objectset/ObjectSetQuery.d.ts.map +1 -0
- package/build/types/observable/internal/objectset/ObjectSetQueryOptions.d.ts +18 -0
- package/build/types/observable/internal/objectset/ObjectSetQueryOptions.d.ts.map +1 -0
- package/build/types/public/unstable-do-not-use.d.ts +2 -1
- package/build/types/public/unstable-do-not-use.d.ts.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @osdk/client
|
|
2
2
|
|
|
3
|
+
## 2.5.0-beta.11
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7b97128: add useObjectSet hook
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [7b97128]
|
|
12
|
+
- @osdk/api@2.5.0-beta.11
|
|
13
|
+
- @osdk/client.unstable@2.5.0-beta.11
|
|
14
|
+
- @osdk/generator-converters@2.5.0-beta.11
|
|
15
|
+
|
|
3
16
|
## 2.5.0-beta.10
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectSetPayload.js","names":[],"sources":["ObjectSetPayload.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 { ObjectSet } from \"@osdk/api\";\nimport type { BaseCollectionPayload } from \"./internal/base-list/BaseCollectionQuery.js\";\n\nexport interface ObjectSetPayload extends BaseCollectionPayload {\n objectSet: ObjectSet<any, any>;\n}\n"],"mappings":"","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 ActionValidationResponse,\n InterfaceDefinition,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n PropertyKeys,\n WhereClause,\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 { OBSERVABLE_USER_AGENT } from \"../util/UserAgent.js\";\nimport type { Canonical } from \"./internal/Canonical.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 ObjectTypeDefinition | InterfaceDefinition,\n> extends CommonObserveOptions, ObserveOptions {\n type: Pick<Q, \"apiName\" | \"type\">;\n where?: WhereClause<Q>;\n pageSize?: number;\n orderBy?: OrderBy<Q>;\n invalidationMode?: InvalidationMode;\n expectedLength?: number;\n streamUpdates?: boolean;\n}\n\n// TODO: Rename this from `ObserveObjectArgs` => `ObserveObjectCallbackArgs`. Not doing it now to reduce churn\n// in repo.\nexport interface ObserveObjectArgs<T extends ObjectTypeDefinition> {\n object: Osdk.Instance<T> | undefined;\n isOptimistic: boolean;\n status: Status;\n lastUpdated: number;\n}\n\n// TODO: Rename this from `ObserveObjectsArgs` => `ObserveObjectsCallbackArgs`. Not doing it now to reduce churn\nexport interface ObserveObjectsArgs<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n> {\n resolvedList: Array<Osdk.Instance<T>>;\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\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}\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<ObserveObjectArgs<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<T extends ObjectTypeDefinition | InterfaceDefinition>(\n options: ObserveListOptions<T>,\n subFn: Observer<ObserveObjectsArgs<T>>,\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<unknown>;\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 canonicalizeWhereClause: <\n T extends ObjectTypeDefinition | InterfaceDefinition,\n >(\n where: WhereClause<T>,\n ) => Canonical<WhereClause<T>>;\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;;AAYA,SAASA,wBAAwB,QAAQ,wBAAwB;AAEjE,SAASC,iBAAiB,QAAqB,cAAc;AAC7D,SAASC,uBAAuB,QAAQ,oBAAoB;AAC5D,SAASC,qBAAqB,QAAQ,sBAAsB;AAE5D,SAASC,oBAAoB,QAAQ,oCAAoC;AACzE,SAASC,KAAK,QAAQ,qBAAqB;AAAC,WAW3BC,gBAAgB;AA8BjC;AACA;;AAQA;;AAYA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAsHA,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 ActionValidationResponse,\n InterfaceDefinition,\n ObjectSet,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n PropertyKeys,\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 { 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 ObjectTypeDefinition | InterfaceDefinition,\n> extends CommonObserveOptions, ObserveOptions {\n type: Pick<Q, \"apiName\" | \"type\">;\n where?: WhereClause<Q>;\n pageSize?: number;\n orderBy?: OrderBy<Q>;\n invalidationMode?: InvalidationMode;\n expectedLength?: number;\n streamUpdates?: boolean;\n}\n\n// TODO: Rename this from `ObserveObjectArgs` => `ObserveObjectCallbackArgs`. Not doing it now to reduce churn\n// in repo.\nexport interface ObserveObjectArgs<T extends ObjectTypeDefinition> {\n object: Osdk.Instance<T> | undefined;\n isOptimistic: boolean;\n status: Status;\n lastUpdated: number;\n}\n\n// TODO: Rename this from `ObserveObjectsArgs` => `ObserveObjectsCallbackArgs`. Not doing it now to reduce churn\nexport interface ObserveObjectsArgs<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n> {\n resolvedList: Array<Osdk.Instance<T>>;\n isOptimistic: boolean;\n lastUpdated: number;\n fetchMore: () => Promise<void>;\n hasMore: boolean;\n status: Status;\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}\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}\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<ObserveObjectArgs<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<T extends ObjectTypeDefinition | InterfaceDefinition>(\n options: ObserveListOptions<T>,\n subFn: Observer<ObserveObjectsArgs<T>>,\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 * 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<unknown>;\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 canonicalizeWhereClause: <\n T extends ObjectTypeDefinition | InterfaceDefinition,\n >(\n where: WhereClause<T>,\n ) => Canonical<WhereClause<T>>;\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;;AAcA,SAASA,wBAAwB,QAAQ,wBAAwB;AAEjE,SAASC,iBAAiB,QAAqB,cAAc;AAC7D,SAASC,uBAAuB,QAAQ,oBAAoB;AAC5D,SAASC,qBAAqB,QAAQ,sBAAsB;AAG5D,SAASC,oBAAoB,QAAQ,oCAAoC;AACzE,SAASC,KAAK,QAAQ,qBAAqB;AAAC,WAW3BC,gBAAgB;AA8BjC;AACA;;AAQA;;AA8BA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAiJA,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":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { getWireObjectSet } from "../objectSet/createObjectSet.js";
|
|
18
|
+
import { OrderByCanonicalizer } from "./internal/OrderByCanonicalizer.js";
|
|
19
|
+
import { WhereClauseCanonicalizer } from "./internal/WhereClauseCanonicalizer.js";
|
|
20
|
+
const whereCanonicalizer = new WhereClauseCanonicalizer();
|
|
21
|
+
const orderByCanonicalizer = new OrderByCanonicalizer();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Computes a stable cache key for an ObjectSet with options.
|
|
25
|
+
*
|
|
26
|
+
* Note: dedupeInterval is excluded as it doesn't affect the data, only the refresh rate.
|
|
27
|
+
*
|
|
28
|
+
* @param objectSet - The base ObjectSet
|
|
29
|
+
* @param options - Optional observation options (where, orderBy, etc.)
|
|
30
|
+
* @returns A stable string key representing the ObjectSet and options
|
|
31
|
+
*/
|
|
32
|
+
export function computeObjectSetCacheKey(objectSet, options) {
|
|
33
|
+
const keyParts = ["objectSet", getWireObjectSet(objectSet)];
|
|
34
|
+
if (!options) {
|
|
35
|
+
return JSON.stringify(keyParts);
|
|
36
|
+
}
|
|
37
|
+
if (options.where) {
|
|
38
|
+
keyParts.push("where", whereCanonicalizer.canonicalize(options.where));
|
|
39
|
+
}
|
|
40
|
+
if (options.withProperties) {
|
|
41
|
+
const propKeys = Object.keys(options.withProperties).sort();
|
|
42
|
+
keyParts.push("props", propKeys);
|
|
43
|
+
}
|
|
44
|
+
if (options.union && options.union.length > 0) {
|
|
45
|
+
keyParts.push("union", options.union.map(os => getWireObjectSet(os)));
|
|
46
|
+
}
|
|
47
|
+
if (options.intersect && options.intersect.length > 0) {
|
|
48
|
+
keyParts.push("intersect", options.intersect.map(os => getWireObjectSet(os)));
|
|
49
|
+
}
|
|
50
|
+
if (options.subtract && options.subtract.length > 0) {
|
|
51
|
+
keyParts.push("subtract", options.subtract.map(os => getWireObjectSet(os)));
|
|
52
|
+
}
|
|
53
|
+
if (options.pivotTo) {
|
|
54
|
+
keyParts.push("pivotTo", options.pivotTo);
|
|
55
|
+
}
|
|
56
|
+
if (options.orderBy) {
|
|
57
|
+
keyParts.push("orderBy", orderByCanonicalizer.canonicalize(options.orderBy));
|
|
58
|
+
}
|
|
59
|
+
if (options.pageSize) {
|
|
60
|
+
keyParts.push("pageSize", options.pageSize);
|
|
61
|
+
}
|
|
62
|
+
return JSON.stringify(keyParts);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=computeObjectSetCacheKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computeObjectSetCacheKey.js","names":["getWireObjectSet","OrderByCanonicalizer","WhereClauseCanonicalizer","whereCanonicalizer","orderByCanonicalizer","computeObjectSetCacheKey","objectSet","options","keyParts","JSON","stringify","where","push","canonicalize","withProperties","propKeys","Object","keys","sort","union","length","map","os","intersect","subtract","pivotTo","orderBy","pageSize"],"sources":["computeObjectSetCacheKey.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 BaseObjectSet,\n ObjectSet,\n ObjectTypeDefinition,\n WirePropertyTypes,\n} from \"@osdk/api\";\nimport { getWireObjectSet } from \"../objectSet/createObjectSet.js\";\nimport type { ObserveObjectSetOptions } from \"./internal/objectset/ObjectSetQueryOptions.js\";\nimport { OrderByCanonicalizer } from \"./internal/OrderByCanonicalizer.js\";\nimport { WhereClauseCanonicalizer } from \"./internal/WhereClauseCanonicalizer.js\";\n\nconst whereCanonicalizer = new WhereClauseCanonicalizer();\nconst orderByCanonicalizer = new OrderByCanonicalizer();\n\n/**\n * Computes a stable cache key for an ObjectSet with options.\n *\n * Note: dedupeInterval is excluded as it doesn't affect the data, only the refresh rate.\n *\n * @param objectSet - The base ObjectSet\n * @param options - Optional observation options (where, orderBy, etc.)\n * @returns A stable string key representing the ObjectSet and options\n */\nexport function computeObjectSetCacheKey<\n T extends ObjectTypeDefinition,\n BaseRDPs extends\n | Record<string, WirePropertyTypes | undefined | Array<WirePropertyTypes>>\n | BaseObjectSet<T> = never,\n RDPs extends Record<\n string,\n WirePropertyTypes | undefined | Array<WirePropertyTypes>\n > = {},\n>(\n objectSet: ObjectSet<T, BaseRDPs>,\n options?: ObserveObjectSetOptions<T, RDPs>,\n): string {\n const keyParts: Array<unknown> = [\n \"objectSet\",\n getWireObjectSet(objectSet as unknown as ObjectSet<any>),\n ];\n\n if (!options) {\n return JSON.stringify(keyParts);\n }\n\n if (options.where) {\n keyParts.push(\"where\", whereCanonicalizer.canonicalize(options.where));\n }\n\n if (options.withProperties) {\n const propKeys = Object.keys(options.withProperties).sort();\n keyParts.push(\"props\", propKeys);\n }\n\n if (options.union && options.union.length > 0) {\n keyParts.push(\n \"union\",\n options.union.map((os: ObjectSet<T>) =>\n getWireObjectSet(os as unknown as ObjectSet<any>)\n ),\n );\n }\n\n if (options.intersect && options.intersect.length > 0) {\n keyParts.push(\n \"intersect\",\n options.intersect.map((os: ObjectSet<T>) =>\n getWireObjectSet(os as unknown as ObjectSet<any>)\n ),\n );\n }\n\n if (options.subtract && options.subtract.length > 0) {\n keyParts.push(\n \"subtract\",\n options.subtract.map((os: ObjectSet<T>) =>\n getWireObjectSet(os as unknown as ObjectSet<any>)\n ),\n );\n }\n\n if (options.pivotTo) {\n keyParts.push(\"pivotTo\", options.pivotTo);\n }\n\n if (options.orderBy) {\n keyParts.push(\n \"orderBy\",\n orderByCanonicalizer.canonicalize(options.orderBy),\n );\n }\n\n if (options.pageSize) {\n keyParts.push(\"pageSize\", options.pageSize);\n }\n\n return JSON.stringify(keyParts);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA,SAASA,gBAAgB,QAAQ,iCAAiC;AAElE,SAASC,oBAAoB,QAAQ,oCAAoC;AACzE,SAASC,wBAAwB,QAAQ,wCAAwC;AAEjF,MAAMC,kBAAkB,GAAG,IAAID,wBAAwB,CAAC,CAAC;AACzD,MAAME,oBAAoB,GAAG,IAAIH,oBAAoB,CAAC,CAAC;;AAEvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,wBAAwBA,CAUtCC,SAAiC,EACjCC,OAA0C,EAClC;EACR,MAAMC,QAAwB,GAAG,CAC/B,WAAW,EACXR,gBAAgB,CAACM,SAAsC,CAAC,CACzD;EAED,IAAI,CAACC,OAAO,EAAE;IACZ,OAAOE,IAAI,CAACC,SAAS,CAACF,QAAQ,CAAC;EACjC;EAEA,IAAID,OAAO,CAACI,KAAK,EAAE;IACjBH,QAAQ,CAACI,IAAI,CAAC,OAAO,EAAET,kBAAkB,CAACU,YAAY,CAACN,OAAO,CAACI,KAAK,CAAC,CAAC;EACxE;EAEA,IAAIJ,OAAO,CAACO,cAAc,EAAE;IAC1B,MAAMC,QAAQ,GAAGC,MAAM,CAACC,IAAI,CAACV,OAAO,CAACO,cAAc,CAAC,CAACI,IAAI,CAAC,CAAC;IAC3DV,QAAQ,CAACI,IAAI,CAAC,OAAO,EAAEG,QAAQ,CAAC;EAClC;EAEA,IAAIR,OAAO,CAACY,KAAK,IAAIZ,OAAO,CAACY,KAAK,CAACC,MAAM,GAAG,CAAC,EAAE;IAC7CZ,QAAQ,CAACI,IAAI,CACX,OAAO,EACPL,OAAO,CAACY,KAAK,CAACE,GAAG,CAAEC,EAAgB,IACjCtB,gBAAgB,CAACsB,EAA+B,CAClD,CACF,CAAC;EACH;EAEA,IAAIf,OAAO,CAACgB,SAAS,IAAIhB,OAAO,CAACgB,SAAS,CAACH,MAAM,GAAG,CAAC,EAAE;IACrDZ,QAAQ,CAACI,IAAI,CACX,WAAW,EACXL,OAAO,CAACgB,SAAS,CAACF,GAAG,CAAEC,EAAgB,IACrCtB,gBAAgB,CAACsB,EAA+B,CAClD,CACF,CAAC;EACH;EAEA,IAAIf,OAAO,CAACiB,QAAQ,IAAIjB,OAAO,CAACiB,QAAQ,CAACJ,MAAM,GAAG,CAAC,EAAE;IACnDZ,QAAQ,CAACI,IAAI,CACX,UAAU,EACVL,OAAO,CAACiB,QAAQ,CAACH,GAAG,CAAEC,EAAgB,IACpCtB,gBAAgB,CAACsB,EAA+B,CAClD,CACF,CAAC;EACH;EAEA,IAAIf,OAAO,CAACkB,OAAO,EAAE;IACnBjB,QAAQ,CAACI,IAAI,CAAC,SAAS,EAAEL,OAAO,CAACkB,OAAO,CAAC;EAC3C;EAEA,IAAIlB,OAAO,CAACmB,OAAO,EAAE;IACnBlB,QAAQ,CAACI,IAAI,CACX,SAAS,EACTR,oBAAoB,CAACS,YAAY,CAACN,OAAO,CAACmB,OAAO,CACnD,CAAC;EACH;EAEA,IAAInB,OAAO,CAACoB,QAAQ,EAAE;IACpBnB,QAAQ,CAACI,IAAI,CAAC,UAAU,EAAEL,OAAO,CAACoB,QAAQ,CAAC;EAC7C;EAEA,OAAOlB,IAAI,CAACC,SAAS,CAACF,QAAQ,CAAC;AACjC","ignoreList":[]}
|
|
@@ -38,6 +38,9 @@ export class Changes {
|
|
|
38
38
|
deleteLink = cacheKey => {
|
|
39
39
|
this.deleted.add(cacheKey);
|
|
40
40
|
};
|
|
41
|
+
registerObjectSet = key => {
|
|
42
|
+
this.modified.add(key);
|
|
43
|
+
};
|
|
41
44
|
isEmpty() {
|
|
42
45
|
return this.modifiedObjects.size === 0 && this.addedObjects.size === 0 && this.added.size === 0 && this.modified.size === 0 && this.deleted.size === 0;
|
|
43
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Changes.js","names":["MultiMap","DEBUG_ONLY__cacheKeyToString","Changes","modifiedObjects","addedObjects","added","Set","modified","deleted","registerObject","cacheKey","data","isNew","set","$apiName","add","deleteObject","registerList","key","registerLink","deleteLink","isEmpty","size","createChangedObjects","DEBUG_ONLY__changesToString","changes","process","env","NODE_ENV","JSON","stringify","multimapHelper","listHelper","Error","Array","from","map","multimap","Object","fromEntries","associations","type","objects","o","$primaryKey"],"sources":["Changes.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 { MultiMap } from \"mnemonist\";\nimport type { ObjectHolder } from \"../../object/convertWireToOsdkObjects/ObjectHolder.js\";\nimport type { CacheKey } from \"./CacheKey.js\";\nimport { DEBUG_ONLY__cacheKeyToString } from \"./CacheKey.js\";\nimport type { SpecificLinkCacheKey } from \"./links/SpecificLinkCacheKey.js\";\nimport type { ListCacheKey } from \"./list/ListCacheKey.js\";\nimport type { ObjectCacheKey } from \"./object/ObjectCacheKey.js\";\n\nexport class Changes {\n modifiedObjects: MultiMap<string, ObjectHolder> = new MultiMap();\n addedObjects: MultiMap<string, ObjectHolder> = new MultiMap();\n\n added: Set
|
|
1
|
+
{"version":3,"file":"Changes.js","names":["MultiMap","DEBUG_ONLY__cacheKeyToString","Changes","modifiedObjects","addedObjects","added","Set","modified","deleted","registerObject","cacheKey","data","isNew","set","$apiName","add","deleteObject","registerList","key","registerLink","deleteLink","registerObjectSet","isEmpty","size","createChangedObjects","DEBUG_ONLY__changesToString","changes","process","env","NODE_ENV","JSON","stringify","multimapHelper","listHelper","Error","Array","from","map","multimap","Object","fromEntries","associations","type","objects","o","$primaryKey"],"sources":["Changes.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 { MultiMap } from \"mnemonist\";\nimport type { ObjectHolder } from \"../../object/convertWireToOsdkObjects/ObjectHolder.js\";\nimport type { CacheKey } from \"./CacheKey.js\";\nimport { DEBUG_ONLY__cacheKeyToString } from \"./CacheKey.js\";\nimport type { SpecificLinkCacheKey } from \"./links/SpecificLinkCacheKey.js\";\nimport type { ListCacheKey } from \"./list/ListCacheKey.js\";\nimport type { ObjectCacheKey } from \"./object/ObjectCacheKey.js\";\nimport type { ObjectSetCacheKey } from \"./objectset/ObjectSetCacheKey.js\";\n\nexport class Changes {\n modifiedObjects: MultiMap<string, ObjectHolder> = new MultiMap();\n addedObjects: MultiMap<string, ObjectHolder> = new MultiMap();\n\n added: Set<\n ListCacheKey | ObjectCacheKey | SpecificLinkCacheKey | ObjectSetCacheKey\n > = new Set();\n modified: Set<\n ListCacheKey | ObjectCacheKey | SpecificLinkCacheKey | ObjectSetCacheKey\n > = new Set();\n deleted: Set<\n ListCacheKey | ObjectCacheKey | SpecificLinkCacheKey | ObjectSetCacheKey\n > = new Set();\n\n registerObject = (\n cacheKey: ObjectCacheKey,\n data: ObjectHolder,\n isNew: boolean,\n ): void => {\n this[isNew ? \"addedObjects\" : \"modifiedObjects\"].set(data.$apiName, data);\n this[isNew ? \"added\" : \"modified\"].add(cacheKey);\n };\n\n deleteObject = (cacheKey: ObjectCacheKey): void => {\n this.deleted.add(cacheKey);\n };\n\n registerList = (key: ListCacheKey): void => {\n this.modified.add(key);\n };\n\n registerLink = (cacheKey: SpecificLinkCacheKey): void => {\n this.modified.add(cacheKey);\n };\n\n deleteLink = (cacheKey: SpecificLinkCacheKey): void => {\n this.deleted.add(cacheKey);\n };\n\n registerObjectSet = (key: ObjectSetCacheKey): void => {\n this.modified.add(key);\n };\n\n isEmpty(): boolean {\n return (\n this.modifiedObjects.size === 0\n && this.addedObjects.size === 0\n && this.added.size === 0\n && this.modified.size === 0\n && this.deleted.size === 0\n );\n }\n}\n\nexport function createChangedObjects(): Changes {\n return new Changes();\n}\n\nexport function DEBUG_ONLY__changesToString(changes: Changes): string {\n if (process.env.NODE_ENV !== \"production\") {\n return JSON.stringify(\n {\n modifiedObjects: multimapHelper(changes.modifiedObjects),\n addedObjects: multimapHelper(changes.addedObjects),\n added: listHelper(changes.added),\n modified: listHelper(changes.modified),\n },\n null,\n 2,\n );\n } else {\n throw new Error(\"not implemented\");\n }\n}\n\nfunction listHelper(set: Set<CacheKey>) {\n return Array.from(set).map(DEBUG_ONLY__cacheKeyToString);\n}\n\nfunction multimapHelper(\n multimap: MultiMap<string, ObjectHolder>,\n) {\n return Object.fromEntries(\n Array.from(multimap.associations()).map(\n ([type, objects]) => {\n return [type, objects.map(o => o.$primaryKey)];\n },\n ),\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KnownCacheKey.js","names":[],"sources":["KnownCacheKey.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 { SpecificLinkCacheKey } from \"./links/SpecificLinkCacheKey.js\";\nimport type { ListCacheKey } from \"./list/ListCacheKey.js\";\nimport type { ObjectCacheKey } from \"./object/ObjectCacheKey.js\";\n\nexport type KnownCacheKey =\n | ObjectCacheKey\n | SpecificLinkCacheKey\n | ListCacheKey;\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"KnownCacheKey.js","names":[],"sources":["KnownCacheKey.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 { SpecificLinkCacheKey } from \"./links/SpecificLinkCacheKey.js\";\nimport type { ListCacheKey } from \"./list/ListCacheKey.js\";\nimport type { ObjectCacheKey } from \"./object/ObjectCacheKey.js\";\nimport type { ObjectSetCacheKey } from \"./objectset/ObjectSetCacheKey.js\";\n\nexport type KnownCacheKey =\n | ObjectCacheKey\n | SpecificLinkCacheKey\n | ListCacheKey\n | ObjectSetCacheKey;\n"],"mappings":"","ignoreList":[]}
|
|
@@ -65,6 +65,14 @@ export class ObservableClientImpl {
|
|
|
65
65
|
}
|
|
66
66
|
return new UnsubscribableWrapper(parentSub);
|
|
67
67
|
};
|
|
68
|
+
observeObjectSet(baseObjectSet, options, subFn) {
|
|
69
|
+
return this.__experimentalStore.objectSets.observe({
|
|
70
|
+
baseObjectSet,
|
|
71
|
+
...options
|
|
72
|
+
},
|
|
73
|
+
// cast to cross typed to untyped barrier
|
|
74
|
+
subFn);
|
|
75
|
+
}
|
|
68
76
|
invalidateAll() {
|
|
69
77
|
return this.__experimentalStore.invalidateAll();
|
|
70
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObservableClientImpl.js","names":["Subscription","UnsubscribableWrapper","ObservableClientImpl","constructor","store","__experimentalStore","applyAction","bind","validateAction","observeObject","apiName","pk","options","subFn","objects","observe","observeList","lists","observeLinks","linkName","objectsArray","Array","isArray","parentSub","obj","querySubscription","links","srcType","type","$apiName","$primaryKey","add","invalidateAll","invalidateObjects","invalidateObjectType","undefined","canonicalizeWhereClause","where","whereCanonicalizer","canonicalize"],"sources":["ObservableClientImpl.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 ActionValidationResponse,\n CompileTimeMetadata,\n InterfaceDefinition,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n WhereClause,\n} from \"@osdk/api\";\nimport { Subscription } from \"rxjs\";\nimport type { ActionSignatureFromDef } from \"../../actions/applyAction.js\";\nimport type { SpecificLinkPayload } from \"../LinkPayload.js\";\nimport type { ListPayload } from \"../ListPayload.js\";\nimport type { ObjectPayload } from \"../ObjectPayload.js\";\nimport type {\n ObservableClient,\n ObserveListOptions,\n ObserveObjectArgs,\n ObserveObjectOptions,\n ObserveObjectsArgs,\n Unsubscribable,\n} from \"../ObservableClient.js\";\nimport type { Observer } from \"../ObservableClient/common.js\";\nimport type { ObserveLinks } from \"../ObservableClient/ObserveLink.js\";\nimport type { Canonical } from \"./Canonical.js\";\nimport type { Store } from \"./Store.js\";\nimport { UnsubscribableWrapper } from \"./UnsubscribableWrapper.js\";\n\n/**\n * Implementation of the public ObservableClient interface.\n * - Delegates all operations to the Store for consistency\n * - Serves as the entry point for reactive data management\n * - Ensures proper method binding and API exposure\n *\n * @internal\n */\nexport class ObservableClientImpl implements ObservableClient {\n __experimentalStore: Store;\n\n constructor(store: Store) {\n this.__experimentalStore = store;\n\n this.applyAction = store.applyAction.bind(store);\n this.validateAction = store.validateAction.bind(store);\n }\n\n public observeObject: <T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n pk: PrimaryKeyType<T>,\n options: Omit<ObserveObjectOptions<T>, \"apiName\" | \"pk\">,\n subFn: Observer<ObserveObjectArgs<T>>,\n ) => Unsubscribable = (apiName, pk, options, subFn) => {\n return this.__experimentalStore.objects.observe(\n {\n ...options,\n apiName,\n pk,\n },\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<ObjectPayload>,\n );\n };\n\n public observeList: <T extends ObjectTypeDefinition | InterfaceDefinition>(\n options: ObserveListOptions<T>,\n subFn: Observer<ObserveObjectsArgs<T>>,\n ) => Unsubscribable = (options, subFn) => {\n return this.__experimentalStore.lists.observe(\n options,\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<ListPayload>,\n );\n };\n\n public observeLinks: <\n T extends ObjectTypeDefinition | InterfaceDefinition,\n L extends keyof CompileTimeMetadata<T>[\"links\"] & string,\n >(\n objects: Osdk.Instance<T> | Array<Osdk.Instance<T>>,\n linkName: L,\n options: ObserveLinks.Options<T, L>,\n subFn: Observer<\n ObserveLinks.CallbackArgs<\n CompileTimeMetadata<T>[\"links\"][L][\"targetType\"]\n >\n >,\n ) => Unsubscribable = (objects, linkName, options, subFn) => {\n // Convert to array if single object provided\n const objectsArray = Array.isArray(objects) ? objects : [objects];\n\n const parentSub = new Subscription();\n\n for (const obj of objectsArray) {\n const querySubscription = this.__experimentalStore.links\n .observe(\n {\n ...options,\n srcType: {\n type: \"object\",\n apiName: obj.$apiName,\n },\n linkName,\n pk: obj.$primaryKey,\n },\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<SpecificLinkPayload>,\n );\n\n parentSub.add(querySubscription);\n }\n\n return new UnsubscribableWrapper(parentSub);\n };\n\n public applyAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n opts?: ObservableClient.ApplyActionOptions,\n ) => Promise<unknown>;\n\n public validateAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n ) => Promise<ActionValidationResponse>;\n\n public invalidateAll(): Promise<void> {\n return this.__experimentalStore.invalidateAll();\n }\n\n public invalidateObjects(\n objects:\n | Osdk.Instance<ObjectTypeDefinition>\n | ReadonlyArray<Osdk.Instance<ObjectTypeDefinition>>,\n ): Promise<void> {\n return this.__experimentalStore.invalidateObjects(objects);\n }\n\n public invalidateObjectType<T extends ObjectTypeDefinition>(\n type: T | T[\"apiName\"],\n ): Promise<void> {\n return this.__experimentalStore.invalidateObjectType(type, undefined);\n }\n\n public canonicalizeWhereClause<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n >(where: WhereClause<T>): Canonical<WhereClause<T>> {\n return this.__experimentalStore.whereCanonicalizer\n .canonicalize(where) as Canonical<WhereClause<T>>;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"file":"ObservableClientImpl.js","names":["Subscription","UnsubscribableWrapper","ObservableClientImpl","constructor","store","__experimentalStore","applyAction","bind","validateAction","observeObject","apiName","pk","options","subFn","objects","observe","observeList","lists","observeLinks","linkName","objectsArray","Array","isArray","parentSub","obj","querySubscription","links","srcType","type","$apiName","$primaryKey","add","observeObjectSet","baseObjectSet","objectSets","invalidateAll","invalidateObjects","invalidateObjectType","undefined","canonicalizeWhereClause","where","whereCanonicalizer","canonicalize"],"sources":["ObservableClientImpl.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 ActionValidationResponse,\n CompileTimeMetadata,\n InterfaceDefinition,\n ObjectSet,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n WhereClause,\n WirePropertyTypes,\n} from \"@osdk/api\";\nimport { Subscription } from \"rxjs\";\nimport type { ActionSignatureFromDef } from \"../../actions/applyAction.js\";\nimport type { SpecificLinkPayload } from \"../LinkPayload.js\";\nimport type { ListPayload } from \"../ListPayload.js\";\nimport type { ObjectPayload } from \"../ObjectPayload.js\";\nimport type { ObjectSetPayload } from \"../ObjectSetPayload.js\";\nimport type {\n ObservableClient,\n ObserveListOptions,\n ObserveObjectArgs,\n ObserveObjectOptions,\n ObserveObjectsArgs,\n ObserveObjectSetArgs,\n Unsubscribable,\n} from \"../ObservableClient.js\";\nimport type { Observer } from \"../ObservableClient/common.js\";\nimport type { ObserveLinks } from \"../ObservableClient/ObserveLink.js\";\nimport type { Canonical } from \"./Canonical.js\";\nimport type { ObserveObjectSetOptions } from \"./objectset/ObjectSetQueryOptions.js\";\nimport type { Store } from \"./Store.js\";\nimport { UnsubscribableWrapper } from \"./UnsubscribableWrapper.js\";\n\n/**\n * Implementation of the public ObservableClient interface.\n * - Delegates all operations to the Store for consistency\n * - Serves as the entry point for reactive data management\n * - Ensures proper method binding and API exposure\n *\n * @internal\n */\nexport class ObservableClientImpl implements ObservableClient {\n __experimentalStore: Store;\n\n constructor(store: Store) {\n this.__experimentalStore = store;\n\n this.applyAction = store.applyAction.bind(store);\n this.validateAction = store.validateAction.bind(store);\n }\n\n public observeObject: <T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n pk: PrimaryKeyType<T>,\n options: Omit<ObserveObjectOptions<T>, \"apiName\" | \"pk\">,\n subFn: Observer<ObserveObjectArgs<T>>,\n ) => Unsubscribable = (apiName, pk, options, subFn) => {\n return this.__experimentalStore.objects.observe(\n {\n ...options,\n apiName,\n pk,\n },\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<ObjectPayload>,\n );\n };\n\n public observeList: <T extends ObjectTypeDefinition | InterfaceDefinition>(\n options: ObserveListOptions<T>,\n subFn: Observer<ObserveObjectsArgs<T>>,\n ) => Unsubscribable = (options, subFn) => {\n return this.__experimentalStore.lists.observe(\n options,\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<ListPayload>,\n );\n };\n\n public observeLinks: <\n T extends ObjectTypeDefinition | InterfaceDefinition,\n L extends keyof CompileTimeMetadata<T>[\"links\"] & string,\n >(\n objects: Osdk.Instance<T> | Array<Osdk.Instance<T>>,\n linkName: L,\n options: ObserveLinks.Options<T, L>,\n subFn: Observer<\n ObserveLinks.CallbackArgs<\n CompileTimeMetadata<T>[\"links\"][L][\"targetType\"]\n >\n >,\n ) => Unsubscribable = (objects, linkName, options, subFn) => {\n // Convert to array if single object provided\n const objectsArray = Array.isArray(objects) ? objects : [objects];\n\n const parentSub = new Subscription();\n\n for (const obj of objectsArray) {\n const querySubscription = this.__experimentalStore.links\n .observe(\n {\n ...options,\n srcType: {\n type: \"object\",\n apiName: obj.$apiName,\n },\n linkName,\n pk: obj.$primaryKey,\n },\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<SpecificLinkPayload>,\n );\n\n parentSub.add(querySubscription);\n }\n\n return new UnsubscribableWrapper(parentSub);\n };\n\n public applyAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n opts?: ObservableClient.ApplyActionOptions,\n ) => Promise<unknown>;\n\n public validateAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n ) => Promise<ActionValidationResponse>;\n\n public 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 return this.__experimentalStore.objectSets.observe(\n { baseObjectSet, ...options },\n // cast to cross typed to untyped barrier\n subFn as unknown as Observer<ObjectSetPayload>,\n );\n }\n\n public invalidateAll(): Promise<void> {\n return this.__experimentalStore.invalidateAll();\n }\n\n public invalidateObjects(\n objects:\n | Osdk.Instance<ObjectTypeDefinition>\n | ReadonlyArray<Osdk.Instance<ObjectTypeDefinition>>,\n ): Promise<void> {\n return this.__experimentalStore.invalidateObjects(objects);\n }\n\n public invalidateObjectType<T extends ObjectTypeDefinition>(\n type: T | T[\"apiName\"],\n ): Promise<void> {\n return this.__experimentalStore.invalidateObjectType(type, undefined);\n }\n\n public canonicalizeWhereClause<\n T extends ObjectTypeDefinition | InterfaceDefinition,\n >(where: WhereClause<T>): Canonical<WhereClause<T>> {\n return this.__experimentalStore.whereCanonicalizer\n .canonicalize(where) as Canonical<WhereClause<T>>;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAcA,SAASA,YAAY,QAAQ,MAAM;AAoBnC,SAASC,qBAAqB,QAAQ,4BAA4B;;AAElE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,oBAAoB,CAA6B;EAG5DC,WAAWA,CAACC,KAAY,EAAE;IACxB,IAAI,CAACC,mBAAmB,GAAGD,KAAK;IAEhC,IAAI,CAACE,WAAW,GAAGF,KAAK,CAACE,WAAW,CAACC,IAAI,CAACH,KAAK,CAAC;IAChD,IAAI,CAACI,cAAc,GAAGJ,KAAK,CAACI,cAAc,CAACD,IAAI,CAACH,KAAK,CAAC;EACxD;EAEOK,aAAa,GAKEA,CAACC,OAAO,EAAEC,EAAE,EAAEC,OAAO,EAAEC,KAAK,KAAK;IACrD,OAAO,IAAI,CAACR,mBAAmB,CAACS,OAAO,CAACC,OAAO,CAC7C;MACE,GAAGH,OAAO;MACVF,OAAO;MACPC;IACF,CAAC;IACD;IACAE,KACF,CAAC;EACH,CAAC;EAEMG,WAAW,GAGIA,CAACJ,OAAO,EAAEC,KAAK,KAAK;IACxC,OAAO,IAAI,CAACR,mBAAmB,CAACY,KAAK,CAACF,OAAO,CAC3CH,OAAO;IACP;IACAC,KACF,CAAC;EACH,CAAC;EAEMK,YAAY,GAYGA,CAACJ,OAAO,EAAEK,QAAQ,EAAEP,OAAO,EAAEC,KAAK,KAAK;IAC3D;IACA,MAAMO,YAAY,GAAGC,KAAK,CAACC,OAAO,CAACR,OAAO,CAAC,GAAGA,OAAO,GAAG,CAACA,OAAO,CAAC;IAEjE,MAAMS,SAAS,GAAG,IAAIvB,YAAY,CAAC,CAAC;IAEpC,KAAK,MAAMwB,GAAG,IAAIJ,YAAY,EAAE;MAC9B,MAAMK,iBAAiB,GAAG,IAAI,CAACpB,mBAAmB,CAACqB,KAAK,CACrDX,OAAO,CACN;QACE,GAAGH,OAAO;QACVe,OAAO,EAAE;UACPC,IAAI,EAAE,QAAQ;UACdlB,OAAO,EAAEc,GAAG,CAACK;QACf,CAAC;QACDV,QAAQ;QACRR,EAAE,EAAEa,GAAG,CAACM;MACV,CAAC;MACD;MACAjB,KACF,CAAC;MAEHU,SAAS,CAACQ,GAAG,CAACN,iBAAiB,CAAC;IAClC;IAEA,OAAO,IAAIxB,qBAAqB,CAACsB,SAAS,CAAC;EAC7C,CAAC;EAaMS,gBAAgBA,CAOrBC,aAA2B,EAC3BrB,OAAyC,EACzCC,KAA8C,EAC9B;IAChB,OAAO,IAAI,CAACR,mBAAmB,CAAC6B,UAAU,CAACnB,OAAO,CAChD;MAAEkB,aAAa;MAAE,GAAGrB;IAAQ,CAAC;IAC7B;IACAC,KACF,CAAC;EACH;EAEOsB,aAAaA,CAAA,EAAkB;IACpC,OAAO,IAAI,CAAC9B,mBAAmB,CAAC8B,aAAa,CAAC,CAAC;EACjD;EAEOC,iBAAiBA,CACtBtB,OAEsD,EACvC;IACf,OAAO,IAAI,CAACT,mBAAmB,CAAC+B,iBAAiB,CAACtB,OAAO,CAAC;EAC5D;EAEOuB,oBAAoBA,CACzBT,IAAsB,EACP;IACf,OAAO,IAAI,CAACvB,mBAAmB,CAACgC,oBAAoB,CAACT,IAAI,EAAEU,SAAS,CAAC;EACvE;EAEOC,uBAAuBA,CAE5BC,KAAqB,EAA6B;IAClD,OAAO,IAAI,CAACnC,mBAAmB,CAACoC,kBAAkB,CAC/CC,YAAY,CAACF,KAAK,CAAC;EACxB;AACF","ignoreList":[]}
|
|
@@ -37,7 +37,24 @@ export class Query {
|
|
|
37
37
|
subscribe(observer) {
|
|
38
38
|
this.#connectable ??= this._createConnectable(this.#subject);
|
|
39
39
|
this.#subscription = this.#connectable.connect();
|
|
40
|
-
|
|
40
|
+
const sub = this.#connectable.subscribe({
|
|
41
|
+
next: value => {
|
|
42
|
+
if (observer.next) {
|
|
43
|
+
observer.next(value);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
error: err => {
|
|
47
|
+
if (observer.error) {
|
|
48
|
+
observer.error(err);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
complete: () => {
|
|
52
|
+
if (observer.complete) {
|
|
53
|
+
observer.complete();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return sub;
|
|
41
58
|
}
|
|
42
59
|
|
|
43
60
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Query.js","names":["additionalContext","Query","retainCount","connectable","subscription","subject","subscriptionDedupeIntervals","Map","constructor","store","observable","opts","cacheKey","logger","options","cacheKeys","process","env","NODE_ENV","client","child","msgPrefix","type","otherKeys","map","x","JSON","stringify","join","subscribe","observer","_createConnectable","connect","registerSubscriptionDedupeInterval","subscriptionId","dedupeInterval","set","unregisterSubscriptionDedupeInterval","delete","getMinimumDedupeInterval","size","Math","min","values","revalidate","force","methodName","abortController","abort","pendingFetch","debug","minDedupeInterval","lastFetchStarted","Date","now","Promise","resolve","batch","setStatus","_preFetch","_fetchAndStore","finally","undefined","status","existing","read","write","value","dispose","unsubscribe","_dispose"],"sources":["Query.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 } from \"@osdk/api\";\nimport type {\n Connectable,\n Observable,\n Observer,\n Subscribable,\n Subscription,\n} from \"rxjs\";\nimport { additionalContext } from \"../../Client.js\";\nimport type {\n CommonObserveOptions,\n Status,\n} from \"../ObservableClient/common.js\";\nimport type { BatchContext } from \"./BatchContext.js\";\nimport type { CacheKeys } from \"./CacheKeys.js\";\nimport type { Changes } from \"./Changes.js\";\nimport type { KnownCacheKey } from \"./KnownCacheKey.js\";\nimport type { Entry } from \"./Layer.js\";\nimport type { OptimisticId } from \"./OptimisticId.js\";\nimport type { Store } from \"./Store.js\";\nimport type { SubjectPayload } from \"./SubjectPayload.js\";\n\nexport abstract class Query<\n KEY extends KnownCacheKey,\n PAYLOAD,\n O extends CommonObserveOptions,\n> implements Subscribable<PAYLOAD> {\n lastFetchStarted?: number;\n pendingFetch?: Promise<void>;\n retainCount: number = 0;\n options: O;\n cacheKey: KEY;\n store: Store;\n abortController?: AbortController;\n #connectable?: Connectable<PAYLOAD>;\n #subscription?: Subscription;\n #subject: Observable<SubjectPayload<KEY>>;\n #subscriptionDedupeIntervals: Map<string, number> = new Map();\n\n /** @internal */\n protected logger: Logger | undefined;\n\n protected readonly cacheKeys: CacheKeys<KnownCacheKey>;\n\n constructor(\n store: Store,\n observable: Observable<SubjectPayload<KEY>>,\n opts: O,\n cacheKey: KEY,\n logger?: Logger,\n ) {\n this.options = opts;\n this.cacheKey = cacheKey;\n this.store = store;\n this.cacheKeys = store.cacheKeys;\n this.#subject = observable;\n\n this.logger = logger ?? (\n process.env.NODE_ENV === \"production\"\n ? store.client[additionalContext].logger\n : store.client[additionalContext].logger?.child({}, {\n msgPrefix: process.env.NODE_ENV !== \"production\"\n ? (`Query<${cacheKey.type}, ${\n cacheKey.otherKeys.map(x => JSON.stringify(x)).join(\", \")\n }>`)\n : \"Query\",\n })\n );\n }\n\n protected abstract _createConnectable(\n subject: Observable<SubjectPayload<KEY>>,\n ): Connectable<PAYLOAD>;\n\n public subscribe(\n observer: Observer<PAYLOAD>,\n ): Subscription {\n this.#connectable ??= this._createConnectable(this.#subject);\n this.#subscription = this.#connectable.connect();\n return this.#connectable.subscribe(observer);\n }\n\n /**\n * Register a subscription's dedupeInterval value\n */\n registerSubscriptionDedupeInterval(\n subscriptionId: string,\n dedupeInterval: number | undefined,\n ): void {\n if (dedupeInterval != null && dedupeInterval > 0) {\n this.#subscriptionDedupeIntervals.set(subscriptionId, dedupeInterval);\n }\n }\n\n /**\n * Unregister a subscription's dedupeInterval value\n */\n unregisterSubscriptionDedupeInterval(subscriptionId: string): void {\n this.#subscriptionDedupeIntervals.delete(subscriptionId);\n }\n\n /**\n * Get the minimum dedupeInterval from all active subscriptions\n */\n private getMinimumDedupeInterval(): number {\n if (this.#subscriptionDedupeIntervals.size === 0) {\n return this.options.dedupeInterval ?? 0;\n }\n\n return Math.min(...this.#subscriptionDedupeIntervals.values());\n }\n\n /**\n * Causes the query to revalidate. This will cause the query to fetch\n * the latest data from the server and update the store if it is deemed\n * \"stale\" or if `force` is true.\n *\n * @param force\n * @returns\n */\n async revalidate(force?: boolean): Promise<void> {\n const logger = process.env.NODE_ENV !== \"production\"\n ? this.logger?.child({ methodName: \"revalidate\" })\n : this.logger;\n\n if (force) {\n this.abortController?.abort();\n }\n\n // n.b. I think this isn't quite right since we may require multiple\n // pages to properly \"revalidate\" for someone. This only really works if you\n // have a single page/object. It needs to be redone. FIXME\n\n // if we are pending the first page/object we can just ignore this\n if (this.pendingFetch) {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"Fetch is already pending, using it\");\n }\n await this.pendingFetch;\n return;\n }\n\n const minDedupeInterval = this.getMinimumDedupeInterval();\n if (\n minDedupeInterval > 0 && (\n this.lastFetchStarted != null\n && Date.now() - this.lastFetchStarted < minDedupeInterval\n )\n ) {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"Within dupeInterval, aborting revalidate\");\n }\n\n return Promise.resolve();\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"Starting actual revalidate\");\n }\n\n this.store.batch({}, (batch) => {\n // make sure the truth layer knows we are loading\n\n // this will not trigger an update to `changes` so it cannot trigger an\n // update of a list either. This may not be the behavior we want.\n this.setStatus(\"loading\", batch);\n });\n\n this._preFetch();\n\n this.lastFetchStarted = Date.now();\n\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"calling _fetchAndStore()\");\n }\n this.pendingFetch = this._fetchAndStore()\n .finally(() => {\n logger?.debug(\"promise's finally for _fetchAndStore()\");\n this.pendingFetch = undefined;\n });\n\n await this.pendingFetch;\n return;\n }\n\n protected _preFetch(): void {}\n\n protected abstract _fetchAndStore(): Promise<void>;\n\n /**\n * Sets the status of the query in the store (but does not store that in `changes`).\n *\n * @param status\n * @param batch\n * @returns\n */\n setStatus(\n status: Status,\n batch: BatchContext,\n ): void {\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"setStatus\" }).debug(\n `Attempting to set status to '${status}'`,\n );\n }\n const existing = batch.read(this.cacheKey);\n if (existing?.status === status) {\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"setStatus\" }).debug(\n `Status is already set to '${status}'; aborting`,\n );\n }\n return;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"setStatus\" }).debug(\n `Writing status '${status}' to cache`,\n );\n }\n batch.write(this.cacheKey, existing?.value, status);\n }\n\n dispose(): void {\n if (this.abortController) {\n this.abortController.abort();\n }\n this.#subscription?.unsubscribe();\n this._dispose();\n }\n\n /**\n * Per query type dispose functionality\n */\n protected _dispose(): void {}\n\n /**\n * The purpose of this method is to provide a way for others to write\n * directly into the store for this query.\n *\n * @param data\n * @param status\n * @param batch\n */\n abstract writeToStore(\n data: KEY[\"__cacheKey\"][\"value\"],\n status: Status,\n batch: BatchContext,\n ): Entry<KEY>;\n\n /**\n * @param changes\n * @param optimisticId\n * @returns If revalidation is needed, a promise that resolves after the\n * revalidation is complete. Otherwise, undefined.\n */\n maybeUpdateAndRevalidate?: (\n changes: Changes,\n optimisticId: OptimisticId | undefined,\n ) => Promise<void> | undefined;\n\n abstract invalidateObjectType(\n objectType: string,\n changes: Changes | undefined,\n ): Promise<void>;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Query.js","names":["additionalContext","Query","retainCount","connectable","subscription","subject","subscriptionDedupeIntervals","Map","constructor","store","observable","opts","cacheKey","logger","options","cacheKeys","process","env","NODE_ENV","client","child","msgPrefix","type","otherKeys","map","x","JSON","stringify","join","subscribe","observer","_createConnectable","connect","sub","next","value","error","err","complete","registerSubscriptionDedupeInterval","subscriptionId","dedupeInterval","set","unregisterSubscriptionDedupeInterval","delete","getMinimumDedupeInterval","size","Math","min","values","revalidate","force","methodName","abortController","abort","pendingFetch","debug","minDedupeInterval","lastFetchStarted","Date","now","Promise","resolve","batch","setStatus","_preFetch","_fetchAndStore","finally","undefined","status","existing","read","write","dispose","unsubscribe","_dispose"],"sources":["Query.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 } from \"@osdk/api\";\nimport type {\n Connectable,\n Observable,\n Observer,\n Subscribable,\n Subscription,\n} from \"rxjs\";\nimport { additionalContext } from \"../../Client.js\";\nimport type {\n CommonObserveOptions,\n Status,\n} from \"../ObservableClient/common.js\";\nimport type { BatchContext } from \"./BatchContext.js\";\nimport type { CacheKeys } from \"./CacheKeys.js\";\nimport type { Changes } from \"./Changes.js\";\nimport type { KnownCacheKey } from \"./KnownCacheKey.js\";\nimport type { Entry } from \"./Layer.js\";\nimport type { OptimisticId } from \"./OptimisticId.js\";\nimport type { Store } from \"./Store.js\";\nimport type { SubjectPayload } from \"./SubjectPayload.js\";\n\nexport abstract class Query<\n KEY extends KnownCacheKey,\n PAYLOAD,\n O extends CommonObserveOptions,\n> implements Subscribable<PAYLOAD> {\n lastFetchStarted?: number;\n pendingFetch?: Promise<void>;\n retainCount: number = 0;\n options: O;\n cacheKey: KEY;\n store: Store;\n abortController?: AbortController;\n #connectable?: Connectable<PAYLOAD>;\n #subscription?: Subscription;\n #subject: Observable<SubjectPayload<KEY>>;\n #subscriptionDedupeIntervals: Map<string, number> = new Map();\n\n /** @internal */\n protected logger: Logger | undefined;\n\n protected readonly cacheKeys: CacheKeys<KnownCacheKey>;\n\n constructor(\n store: Store,\n observable: Observable<SubjectPayload<KEY>>,\n opts: O,\n cacheKey: KEY,\n logger?: Logger,\n ) {\n this.options = opts;\n this.cacheKey = cacheKey;\n this.store = store;\n this.cacheKeys = store.cacheKeys;\n this.#subject = observable;\n\n this.logger = logger ?? (\n process.env.NODE_ENV === \"production\"\n ? store.client[additionalContext].logger\n : store.client[additionalContext].logger?.child({}, {\n msgPrefix: process.env.NODE_ENV !== \"production\"\n ? (`Query<${cacheKey.type}, ${\n cacheKey.otherKeys.map(x => JSON.stringify(x)).join(\", \")\n }>`)\n : \"Query\",\n })\n );\n }\n\n protected abstract _createConnectable(\n subject: Observable<SubjectPayload<KEY>>,\n ): Connectable<PAYLOAD>;\n\n public subscribe(\n observer: Observer<PAYLOAD>,\n ): Subscription {\n this.#connectable ??= this._createConnectable(this.#subject);\n this.#subscription = this.#connectable.connect();\n const sub = this.#connectable.subscribe({\n next: (value) => {\n if (observer.next) {\n observer.next(value);\n }\n },\n error: (err) => {\n if (observer.error) {\n observer.error(err);\n }\n },\n complete: () => {\n if (observer.complete) {\n observer.complete();\n }\n },\n });\n return sub;\n }\n\n /**\n * Register a subscription's dedupeInterval value\n */\n registerSubscriptionDedupeInterval(\n subscriptionId: string,\n dedupeInterval: number | undefined,\n ): void {\n if (dedupeInterval != null && dedupeInterval > 0) {\n this.#subscriptionDedupeIntervals.set(subscriptionId, dedupeInterval);\n }\n }\n\n /**\n * Unregister a subscription's dedupeInterval value\n */\n unregisterSubscriptionDedupeInterval(subscriptionId: string): void {\n this.#subscriptionDedupeIntervals.delete(subscriptionId);\n }\n\n /**\n * Get the minimum dedupeInterval from all active subscriptions\n */\n private getMinimumDedupeInterval(): number {\n if (this.#subscriptionDedupeIntervals.size === 0) {\n return this.options.dedupeInterval ?? 0;\n }\n\n return Math.min(...this.#subscriptionDedupeIntervals.values());\n }\n\n /**\n * Causes the query to revalidate. This will cause the query to fetch\n * the latest data from the server and update the store if it is deemed\n * \"stale\" or if `force` is true.\n *\n * @param force\n * @returns\n */\n async revalidate(force?: boolean): Promise<void> {\n const logger = process.env.NODE_ENV !== \"production\"\n ? this.logger?.child({ methodName: \"revalidate\" })\n : this.logger;\n\n if (force) {\n this.abortController?.abort();\n }\n\n // n.b. I think this isn't quite right since we may require multiple\n // pages to properly \"revalidate\" for someone. This only really works if you\n // have a single page/object. It needs to be redone. FIXME\n\n // if we are pending the first page/object we can just ignore this\n if (this.pendingFetch) {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"Fetch is already pending, using it\");\n }\n await this.pendingFetch;\n return;\n }\n\n const minDedupeInterval = this.getMinimumDedupeInterval();\n if (\n minDedupeInterval > 0 && (\n this.lastFetchStarted != null\n && Date.now() - this.lastFetchStarted < minDedupeInterval\n )\n ) {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"Within dupeInterval, aborting revalidate\");\n }\n\n return Promise.resolve();\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"Starting actual revalidate\");\n }\n\n this.store.batch({}, (batch) => {\n // make sure the truth layer knows we are loading\n\n // this will not trigger an update to `changes` so it cannot trigger an\n // update of a list either. This may not be the behavior we want.\n this.setStatus(\"loading\", batch);\n });\n\n this._preFetch();\n\n this.lastFetchStarted = Date.now();\n\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"calling _fetchAndStore()\");\n }\n this.pendingFetch = this._fetchAndStore()\n .finally(() => {\n logger?.debug(\"promise's finally for _fetchAndStore()\");\n this.pendingFetch = undefined;\n });\n\n await this.pendingFetch;\n return;\n }\n\n protected _preFetch(): void {}\n\n protected abstract _fetchAndStore(): Promise<void>;\n\n /**\n * Sets the status of the query in the store (but does not store that in `changes`).\n *\n * @param status\n * @param batch\n * @returns\n */\n setStatus(\n status: Status,\n batch: BatchContext,\n ): void {\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"setStatus\" }).debug(\n `Attempting to set status to '${status}'`,\n );\n }\n const existing = batch.read(this.cacheKey);\n if (existing?.status === status) {\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"setStatus\" }).debug(\n `Status is already set to '${status}'; aborting`,\n );\n }\n return;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"setStatus\" }).debug(\n `Writing status '${status}' to cache`,\n );\n }\n batch.write(this.cacheKey, existing?.value, status);\n }\n\n dispose(): void {\n if (this.abortController) {\n this.abortController.abort();\n }\n this.#subscription?.unsubscribe();\n this._dispose();\n }\n\n /**\n * Per query type dispose functionality\n */\n protected _dispose(): void {}\n\n /**\n * The purpose of this method is to provide a way for others to write\n * directly into the store for this query.\n *\n * @param data\n * @param status\n * @param batch\n */\n abstract writeToStore(\n data: KEY[\"__cacheKey\"][\"value\"],\n status: Status,\n batch: BatchContext,\n ): Entry<KEY>;\n\n /**\n * @param changes\n * @param optimisticId\n * @returns If revalidation is needed, a promise that resolves after the\n * revalidation is complete. Otherwise, undefined.\n */\n maybeUpdateAndRevalidate?: (\n changes: Changes,\n optimisticId: OptimisticId | undefined,\n ) => Promise<void> | undefined;\n\n abstract invalidateObjectType(\n objectType: string,\n changes: Changes | undefined,\n ): Promise<void>;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAUA,SAASA,iBAAiB,QAAQ,iBAAiB;AAcnD,OAAO,MAAeC,KAAK,CAIQ;EAGjCC,WAAW,GAAW,CAAC;EAKvB,CAACC,WAAW;EACZ,CAACC,YAAY;EACb,CAACC,OAAO;EACR,CAACC,2BAA2B,GAAwB,IAAIC,GAAG,CAAC,CAAC;;EAE7D;;EAKAC,WAAWA,CACTC,KAAY,EACZC,UAA2C,EAC3CC,IAAO,EACPC,QAAa,EACbC,MAAe,EACf;IACA,IAAI,CAACC,OAAO,GAAGH,IAAI;IACnB,IAAI,CAACC,QAAQ,GAAGA,QAAQ;IACxB,IAAI,CAACH,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACM,SAAS,GAAGN,KAAK,CAACM,SAAS;IAChC,IAAI,CAAC,CAACV,OAAO,GAAGK,UAAU;IAE1B,IAAI,CAACG,MAAM,GAAGA,MAAM,KAClBG,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GACjCT,KAAK,CAACU,MAAM,CAACnB,iBAAiB,CAAC,CAACa,MAAM,GACtCJ,KAAK,CAACU,MAAM,CAACnB,iBAAiB,CAAC,CAACa,MAAM,EAAEO,KAAK,CAAC,CAAC,CAAC,EAAE;MAClDC,SAAS,EAAEL,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAC3C,SAASN,QAAQ,CAACU,IAAI,KACvBV,QAAQ,CAACW,SAAS,CAACC,GAAG,CAACC,CAAC,IAAIC,IAAI,CAACC,SAAS,CAACF,CAAC,CAAC,CAAC,CAACG,IAAI,CAAC,IAAI,CAAC,GACxD,GACD;IACN,CAAC,CAAC,CACL;EACH;EAMOC,SAASA,CACdC,QAA2B,EACb;IACd,IAAI,CAAC,CAAC3B,WAAW,KAAK,IAAI,CAAC4B,kBAAkB,CAAC,IAAI,CAAC,CAAC1B,OAAO,CAAC;IAC5D,IAAI,CAAC,CAACD,YAAY,GAAG,IAAI,CAAC,CAACD,WAAW,CAAC6B,OAAO,CAAC,CAAC;IAChD,MAAMC,GAAG,GAAG,IAAI,CAAC,CAAC9B,WAAW,CAAC0B,SAAS,CAAC;MACtCK,IAAI,EAAGC,KAAK,IAAK;QACf,IAAIL,QAAQ,CAACI,IAAI,EAAE;UACjBJ,QAAQ,CAACI,IAAI,CAACC,KAAK,CAAC;QACtB;MACF,CAAC;MACDC,KAAK,EAAGC,GAAG,IAAK;QACd,IAAIP,QAAQ,CAACM,KAAK,EAAE;UAClBN,QAAQ,CAACM,KAAK,CAACC,GAAG,CAAC;QACrB;MACF,CAAC;MACDC,QAAQ,EAAEA,CAAA,KAAM;QACd,IAAIR,QAAQ,CAACQ,QAAQ,EAAE;UACrBR,QAAQ,CAACQ,QAAQ,CAAC,CAAC;QACrB;MACF;IACF,CAAC,CAAC;IACF,OAAOL,GAAG;EACZ;;EAEA;AACF;AACA;EACEM,kCAAkCA,CAChCC,cAAsB,EACtBC,cAAkC,EAC5B;IACN,IAAIA,cAAc,IAAI,IAAI,IAAIA,cAAc,GAAG,CAAC,EAAE;MAChD,IAAI,CAAC,CAACnC,2BAA2B,CAACoC,GAAG,CAACF,cAAc,EAAEC,cAAc,CAAC;IACvE;EACF;;EAEA;AACF;AACA;EACEE,oCAAoCA,CAACH,cAAsB,EAAQ;IACjE,IAAI,CAAC,CAAClC,2BAA2B,CAACsC,MAAM,CAACJ,cAAc,CAAC;EAC1D;;EAEA;AACF;AACA;EACUK,wBAAwBA,CAAA,EAAW;IACzC,IAAI,IAAI,CAAC,CAACvC,2BAA2B,CAACwC,IAAI,KAAK,CAAC,EAAE;MAChD,OAAO,IAAI,CAAChC,OAAO,CAAC2B,cAAc,IAAI,CAAC;IACzC;IAEA,OAAOM,IAAI,CAACC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC1C,2BAA2B,CAAC2C,MAAM,CAAC,CAAC,CAAC;EAChE;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE,MAAMC,UAAUA,CAACC,KAAe,EAAiB;IAC/C,MAAMtC,MAAM,GAAGG,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAChD,IAAI,CAACL,MAAM,EAAEO,KAAK,CAAC;MAAEgC,UAAU,EAAE;IAAa,CAAC,CAAC,GAChD,IAAI,CAACvC,MAAM;IAEf,IAAIsC,KAAK,EAAE;MACT,IAAI,CAACE,eAAe,EAAEC,KAAK,CAAC,CAAC;IAC/B;;IAEA;IACA;IACA;;IAEA;IACA,IAAI,IAAI,CAACC,YAAY,EAAE;MACrB,IAAIvC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACzCL,MAAM,EAAE2C,KAAK,CAAC,oCAAoC,CAAC;MACrD;MACA,MAAM,IAAI,CAACD,YAAY;MACvB;IACF;IAEA,MAAME,iBAAiB,GAAG,IAAI,CAACZ,wBAAwB,CAAC,CAAC;IACzD,IACEY,iBAAiB,GAAG,CAAC,IACnB,IAAI,CAACC,gBAAgB,IAAI,IAAI,IAC1BC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAACF,gBAAgB,GAAGD,iBACzC,EACD;MACA,IAAIzC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACzCL,MAAM,EAAE2C,KAAK,CAAC,0CAA0C,CAAC;MAC3D;MAEA,OAAOK,OAAO,CAACC,OAAO,CAAC,CAAC;IAC1B;IAEA,IAAI9C,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzCL,MAAM,EAAE2C,KAAK,CAAC,4BAA4B,CAAC;IAC7C;IAEA,IAAI,CAAC/C,KAAK,CAACsD,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MAC9B;;MAEA;MACA;MACA,IAAI,CAACC,SAAS,CAAC,SAAS,EAAED,KAAK,CAAC;IAClC,CAAC,CAAC;IAEF,IAAI,CAACE,SAAS,CAAC,CAAC;IAEhB,IAAI,CAACP,gBAAgB,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;IAElC,IAAI5C,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzCL,MAAM,EAAE2C,KAAK,CAAC,0BAA0B,CAAC;IAC3C;IACA,IAAI,CAACD,YAAY,GAAG,IAAI,CAACW,cAAc,CAAC,CAAC,CACtCC,OAAO,CAAC,MAAM;MACbtD,MAAM,EAAE2C,KAAK,CAAC,wCAAwC,CAAC;MACvD,IAAI,CAACD,YAAY,GAAGa,SAAS;IAC/B,CAAC,CAAC;IAEJ,MAAM,IAAI,CAACb,YAAY;EAEzB;EAEUU,SAASA,CAAA,EAAS,CAAC;EAI7B;AACF;AACA;AACA;AACA;AACA;AACA;EACED,SAASA,CACPK,MAAc,EACdN,KAAmB,EACb;IACN,IAAI/C,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAACL,MAAM,EAAEO,KAAK,CAAC;QAAEgC,UAAU,EAAE;MAAY,CAAC,CAAC,CAACI,KAAK,CACnD,gCAAgCa,MAAM,GACxC,CAAC;IACH;IACA,MAAMC,QAAQ,GAAGP,KAAK,CAACQ,IAAI,CAAC,IAAI,CAAC3D,QAAQ,CAAC;IAC1C,IAAI0D,QAAQ,EAAED,MAAM,KAAKA,MAAM,EAAE;MAC/B,IAAIrD,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACzC,IAAI,CAACL,MAAM,EAAEO,KAAK,CAAC;UAAEgC,UAAU,EAAE;QAAY,CAAC,CAAC,CAACI,KAAK,CACnD,6BAA6Ba,MAAM,aACrC,CAAC;MACH;MACA;IACF;IAEA,IAAIrD,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAACL,MAAM,EAAEO,KAAK,CAAC;QAAEgC,UAAU,EAAE;MAAY,CAAC,CAAC,CAACI,KAAK,CACnD,mBAAmBa,MAAM,YAC3B,CAAC;IACH;IACAN,KAAK,CAACS,KAAK,CAAC,IAAI,CAAC5D,QAAQ,EAAE0D,QAAQ,EAAEnC,KAAK,EAAEkC,MAAM,CAAC;EACrD;EAEAI,OAAOA,CAAA,EAAS;IACd,IAAI,IAAI,CAACpB,eAAe,EAAE;MACxB,IAAI,CAACA,eAAe,CAACC,KAAK,CAAC,CAAC;IAC9B;IACA,IAAI,CAAC,CAAClD,YAAY,EAAEsE,WAAW,CAAC,CAAC;IACjC,IAAI,CAACC,QAAQ,CAAC,CAAC;EACjB;;EAEA;AACF;AACA;EACYA,QAAQA,CAAA,EAAS,CAAC;;EAE5B;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;EAOE;AACF;AACA;AACA;AACA;AACA;AAUA","ignoreList":[]}
|
|
@@ -24,6 +24,7 @@ import { Layers } from "./Layers.js";
|
|
|
24
24
|
import { LinksHelper } from "./links/LinksHelper.js";
|
|
25
25
|
import { ListsHelper } from "./list/ListsHelper.js";
|
|
26
26
|
import { ObjectsHelper } from "./object/ObjectsHelper.js";
|
|
27
|
+
import { ObjectSetHelper } from "./objectset/ObjectSetHelper.js";
|
|
27
28
|
import { OrderByCanonicalizer } from "./OrderByCanonicalizer.js";
|
|
28
29
|
import { Queries } from "./Queries.js";
|
|
29
30
|
import { WhereClauseCanonicalizer } from "./WhereClauseCanonicalizer.js";
|
|
@@ -65,6 +66,7 @@ export class Store {
|
|
|
65
66
|
this.lists = new ListsHelper(this, this.cacheKeys, this.whereCanonicalizer, this.orderByCanonicalizer);
|
|
66
67
|
this.objects = new ObjectsHelper(this, this.cacheKeys);
|
|
67
68
|
this.links = new LinksHelper(this, this.cacheKeys, this.whereCanonicalizer, this.orderByCanonicalizer);
|
|
69
|
+
this.objectSets = new ObjectSetHelper(this, this.cacheKeys, this.whereCanonicalizer, this.orderByCanonicalizer);
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Store.js","names":["invariant","additionalContext","DEBUG_REFCOUNTS","ActionApplication","CacheKeys","createChangedObjects","DEBUG_ONLY__changesToString","Layers","LinksHelper","ListsHelper","ObjectsHelper","OrderByCanonicalizer","Queries","WhereClauseCanonicalizer","Store","whereCanonicalizer","orderByCanonicalizer","queries","layers","logger","onRevalidate","maybeRevalidateQueries","bind","subjects","constructor","client","child","msgPrefix","cacheKeys","onDestroy","cleanupCacheKey","lists","objects","links","key","subject","peek","console","log","JSON","stringify","closed","observed","type","otherKeys","process","env","NODE_ENV","delete","applyAction","action","args","opts","validateAction","result","$validateOnly","$returnEdits","getValue","cacheKey","top","get","batch","optimisticId","changes","batchFn","invalidateObject","apiName","pk","getQuery","revalidate","#maybeRevalidateQueries","methodName","undefined","isEmpty","debug","promises","keys","promise","maybeUpdateAndRevalidate","push","Promise","all","invalidateObjectType","info","truth","modified","has","query","allSettled","then","invalidateAll","invalidateObjects","objectsArray","Array","isArray","obj","$objectType","$primaryKey"],"sources":["Store.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 Logger,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n} from \"@osdk/api\";\nimport invariant from \"tiny-invariant\";\nimport type { ActionSignatureFromDef } from \"../../actions/applyAction.js\";\nimport { additionalContext, type Client } from \"../../Client.js\";\nimport { DEBUG_REFCOUNTS } from \"../DebugFlags.js\";\nimport type { OptimisticBuilder } from \"../OptimisticBuilder.js\";\nimport { ActionApplication } from \"./actions/ActionApplication.js\";\nimport type { BatchContext } from \"./BatchContext.js\";\nimport { CacheKeys } from \"./CacheKeys.js\";\nimport {\n type Changes,\n createChangedObjects,\n DEBUG_ONLY__changesToString,\n} from \"./Changes.js\";\nimport type { KnownCacheKey } from \"./KnownCacheKey.js\";\nimport type { Entry } from \"./Layer.js\";\nimport { Layers } from \"./Layers.js\";\nimport { LinksHelper } from \"./links/LinksHelper.js\";\nimport { ListsHelper } from \"./list/ListsHelper.js\";\nimport { ObjectsHelper } from \"./object/ObjectsHelper.js\";\nimport { type OptimisticId } from \"./OptimisticId.js\";\nimport { OrderByCanonicalizer } from \"./OrderByCanonicalizer.js\";\nimport { Queries } from \"./Queries.js\";\nimport type { Subjects } from \"./Subjects.js\";\nimport { WhereClauseCanonicalizer } from \"./WhereClauseCanonicalizer.js\";\n\nexport namespace Store {\n export interface ApplyActionOptions {\n optimisticUpdate?: (ctx: OptimisticBuilder) => void;\n }\n}\n\n/*\n Notes:\n - Subjects are one per type per store (by cache key)\n - Data is one per layer per cache key\n*/\n\n/**\n * Central data store with layered cache architecture.\n * - Truth layer: server state | Optimistic layers: pending changes\n * - Reference counting prevents memory leaks\n * - Batch operations ensure consistency\n */\nexport class Store {\n readonly whereCanonicalizer: WhereClauseCanonicalizer =\n new WhereClauseCanonicalizer();\n readonly orderByCanonicalizer: OrderByCanonicalizer =\n new OrderByCanonicalizer();\n\n readonly client: Client;\n\n /** @internal */\n readonly logger?: Logger;\n\n readonly cacheKeys: CacheKeys<KnownCacheKey>;\n readonly queries: Queries = new Queries();\n\n readonly layers: Layers = new Layers({\n logger: this.logger,\n onRevalidate: this.#maybeRevalidateQueries.bind(this),\n });\n readonly subjects: Subjects = this.layers.subjects;\n\n // these are hopefully temporary\n readonly lists: ListsHelper;\n readonly objects: ObjectsHelper;\n readonly links: LinksHelper;\n\n constructor(client: Client) {\n this.logger = client[additionalContext].logger?.child({}, {\n msgPrefix: \"Store\",\n });\n this.client = client;\n\n this.cacheKeys = new CacheKeys<KnownCacheKey>({\n onDestroy: this.#cleanupCacheKey,\n });\n\n this.lists = new ListsHelper(\n this,\n this.cacheKeys,\n this.whereCanonicalizer,\n this.orderByCanonicalizer,\n );\n this.objects = new ObjectsHelper(this, this.cacheKeys);\n this.links = new LinksHelper(\n this,\n this.cacheKeys,\n this.whereCanonicalizer,\n this.orderByCanonicalizer,\n );\n }\n\n /**\n * Called after a key is no longer retained and the timeout has elapsed\n * @param key\n */\n #cleanupCacheKey = (key: KnownCacheKey) => {\n const subject = this.subjects.peek(key);\n\n if (DEBUG_REFCOUNTS) {\n // eslint-disable-next-line no-console\n console.log(\n `CacheKey cleaning up (${\n JSON.stringify({\n closed: subject?.closed,\n observed: subject?.observed,\n })\n })`,\n JSON.stringify([key.type, ...key.otherKeys], null, 2),\n );\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n invariant(subject);\n }\n\n this.subjects.delete(key);\n this.queries.delete(key);\n };\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?: Store.ApplyActionOptions,\n ) => Promise<ActionEditResponse> = async (action, args, opts) => {\n return await new ActionApplication(this).applyAction(action, args, opts);\n };\n\n validateAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n ) => Promise<ActionValidationResponse> = async (action, args) => {\n const result = await this.client(action).applyAction(args as any, {\n $validateOnly: true,\n $returnEdits: false,\n });\n return result as ActionValidationResponse;\n };\n\n public getValue<K extends KnownCacheKey>(\n cacheKey: K,\n ): Entry<K> | undefined {\n return this.layers.top.get(cacheKey);\n }\n\n batch<X>(\n { optimisticId, changes = createChangedObjects() }: {\n optimisticId?: OptimisticId;\n changes?: Changes;\n },\n batchFn: (batchContext: BatchContext) => X,\n ): {\n batchResult: BatchContext;\n retVal: X;\n changes: Changes;\n } {\n return this.layers.batch({ optimisticId, changes }, batchFn);\n }\n\n public invalidateObject<T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n pk: PrimaryKeyType<T>,\n ): Promise<unknown> {\n if (typeof apiName !== \"string\") {\n apiName = apiName.apiName;\n }\n\n return this.objects.getQuery({\n apiName,\n pk,\n }).revalidate(/* force */ true);\n }\n\n async #maybeRevalidateQueries(\n changes: Changes,\n optimisticId?: OptimisticId | undefined,\n ): Promise<void> {\n const logger = process.env.NODE_ENV !== \"production\"\n ? this.logger?.child({ methodName: \"maybeRevalidateQueries\" })\n : undefined;\n\n if (changes.isEmpty()) {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"No changes, aborting\");\n }\n return;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(DEBUG_ONLY__changesToString(changes), { optimisticId });\n }\n\n try {\n const promises: Array<Promise<unknown>> = [];\n for (const cacheKey of this.queries.keys()) {\n const promise = this.queries.peek(cacheKey)?.maybeUpdateAndRevalidate?.(\n changes,\n optimisticId,\n );\n if (promise) promises.push(promise);\n }\n await Promise.all(promises);\n } finally {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"in finally\", DEBUG_ONLY__changesToString(changes));\n }\n }\n }\n\n /**\n * Invalidates all cache entries for a specific object type.\n * This will revalidate:\n * 1. All objects of the specified type\n * 2. All lists of the specified type\n * 3. All links where the source object is of the specified type\n *\n * @param apiName - The API name of the object type to invalidate\n * @param changes - Optional changes object to track what has been modified\n * @returns Promise that resolves when all invalidations are complete\n */\n public invalidateObjectType<T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n changes: Changes | undefined,\n ): Promise<void> {\n if (typeof apiName !== \"string\") {\n apiName = apiName.apiName;\n }\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"invalidateObjectType\" }).info(\n changes ? DEBUG_ONLY__changesToString(changes) : void 0,\n );\n }\n\n const promises: Array<Promise<void>> = [];\n\n for (const cacheKey of this.layers.truth.keys()) {\n if (changes && changes.modified.has(cacheKey)) {\n continue;\n }\n const query = this.queries.peek(cacheKey);\n if (!query) continue;\n\n promises.push(query.invalidateObjectType(apiName, changes));\n }\n\n // we use allSettled here because we don't care if it succeeds or fails, just that they all complete.\n return Promise.allSettled(promises).then(() => void 0);\n }\n\n public async invalidateAll(): Promise<void> {\n const promises: Array<Promise<unknown>> = [];\n for (const cacheKey of this.queries.keys()) {\n const query = this.queries.peek(cacheKey);\n if (query) {\n promises.push(query.revalidate(true));\n }\n }\n // we use allSettled here because we don't care if it succeeds or fails, just that they all complete.\n return Promise.allSettled(promises).then(() => void 0);\n }\n\n public async invalidateObjects(\n objects:\n | Osdk.Instance<ObjectTypeDefinition>\n | ReadonlyArray<Osdk.Instance<ObjectTypeDefinition>>,\n ): Promise<void> {\n const objectsArray = Array.isArray(objects) ? objects : [objects];\n const promises: Array<Promise<unknown>> = [];\n\n for (const obj of objectsArray) {\n promises.push(this.invalidateObject(obj.$objectType, obj.$primaryKey));\n }\n\n // we use allSettled here because we don't care if it succeeds or fails, just that they all complete.\n return Promise.allSettled(promises).then(() => void 0);\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAWA,OAAOA,SAAS,MAAM,gBAAgB;AAEtC,SAASC,iBAAiB,QAAqB,iBAAiB;AAChE,SAASC,eAAe,QAAQ,kBAAkB;AAElD,SAASC,iBAAiB,QAAQ,gCAAgC;AAElE,SAASC,SAAS,QAAQ,gBAAgB;AAC1C,SAEEC,oBAAoB,EACpBC,2BAA2B,QACtB,cAAc;AAGrB,SAASC,MAAM,QAAQ,aAAa;AACpC,SAASC,WAAW,QAAQ,wBAAwB;AACpD,SAASC,WAAW,QAAQ,uBAAuB;AACnD,SAASC,aAAa,QAAQ,2BAA2B;AAEzD,SAASC,oBAAoB,QAAQ,2BAA2B;AAChE,SAASC,OAAO,QAAQ,cAAc;AAEtC,SAASC,wBAAwB,QAAQ,+BAA+B;AAQxE;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,KAAK,CAAC;EACRC,kBAAkB,GACzB,IAAIF,wBAAwB,CAAC,CAAC;EACvBG,oBAAoB,GAC3B,IAAIL,oBAAoB,CAAC,CAAC;;EAI5B;;EAISM,OAAO,GAAY,IAAIL,OAAO,CAAC,CAAC;EAEhCM,MAAM,GAAW,IAAIX,MAAM,CAAC;IACnCY,MAAM,EAAE,IAAI,CAACA,MAAM;IACnBC,YAAY,EAAE,IAAI,CAAC,CAACC,sBAAsB,CAACC,IAAI,CAAC,IAAI;EACtD,CAAC,CAAC;EACOC,QAAQ,GAAa,IAAI,CAACL,MAAM,CAACK,QAAQ;;EAElD;;EAKAC,WAAWA,CAACC,MAAc,EAAE;IAC1B,IAAI,CAACN,MAAM,GAAGM,MAAM,CAACxB,iBAAiB,CAAC,CAACkB,MAAM,EAAEO,KAAK,CAAC,CAAC,CAAC,EAAE;MACxDC,SAAS,EAAE;IACb,CAAC,CAAC;IACF,IAAI,CAACF,MAAM,GAAGA,MAAM;IAEpB,IAAI,CAACG,SAAS,GAAG,IAAIxB,SAAS,CAAgB;MAC5CyB,SAAS,EAAE,IAAI,CAAC,CAACC;IACnB,CAAC,CAAC;IAEF,IAAI,CAACC,KAAK,GAAG,IAAItB,WAAW,CAC1B,IAAI,EACJ,IAAI,CAACmB,SAAS,EACd,IAAI,CAACb,kBAAkB,EACvB,IAAI,CAACC,oBACP,CAAC;IACD,IAAI,CAACgB,OAAO,GAAG,IAAItB,aAAa,CAAC,IAAI,EAAE,IAAI,CAACkB,SAAS,CAAC;IACtD,IAAI,CAACK,KAAK,GAAG,IAAIzB,WAAW,CAC1B,IAAI,EACJ,IAAI,CAACoB,SAAS,EACd,IAAI,CAACb,kBAAkB,EACvB,IAAI,CAACC,oBACP,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACE,CAACc,eAAe,GAAII,GAAkB,IAAK;IACzC,MAAMC,OAAO,GAAG,IAAI,CAACZ,QAAQ,CAACa,IAAI,CAACF,GAAG,CAAC;IAEvC,IAAIhC,eAAe,EAAE;MACnB;MACAmC,OAAO,CAACC,GAAG,CACT,yBACEC,IAAI,CAACC,SAAS,CAAC;QACbC,MAAM,EAAEN,OAAO,EAAEM,MAAM;QACvBC,QAAQ,EAAEP,OAAO,EAAEO;MACrB,CAAC,CAAC,GACD,EACHH,IAAI,CAACC,SAAS,CAAC,CAACN,GAAG,CAACS,IAAI,EAAE,GAAGT,GAAG,CAACU,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,CACtD,CAAC;IACH;IAEA,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC,CAAUZ,OAAO,GAAAU,OAAA,CAAAC,GAAA,CAAAC,QAAA,oBAAjB/C,SAAS,UAATA,SAAS;IACX;IAEA,IAAI,CAACuB,QAAQ,CAACyB,MAAM,CAACd,GAAG,CAAC;IACzB,IAAI,CAACjB,OAAO,CAAC+B,MAAM,CAACd,GAAG,CAAC;EAC1B,CAAC;EAEDe,WAAW,GAMwB,MAAAA,CAAOC,MAAM,EAAEC,IAAI,EAAEC,IAAI,KAAK;IAC/D,OAAO,MAAM,IAAIjD,iBAAiB,CAAC,IAAI,CAAC,CAAC8C,WAAW,CAACC,MAAM,EAAEC,IAAI,EAAEC,IAAI,CAAC;EAC1E,CAAC;EAEDC,cAAc,GAG2B,MAAAA,CAAOH,MAAM,EAAEC,IAAI,KAAK;IAC/D,MAAMG,MAAM,GAAG,MAAM,IAAI,CAAC7B,MAAM,CAACyB,MAAM,CAAC,CAACD,WAAW,CAACE,IAAI,EAAS;MAChEI,aAAa,EAAE,IAAI;MACnBC,YAAY,EAAE;IAChB,CAAC,CAAC;IACF,OAAOF,MAAM;EACf,CAAC;EAEMG,QAAQA,CACbC,QAAW,EACW;IACtB,OAAO,IAAI,CAACxC,MAAM,CAACyC,GAAG,CAACC,GAAG,CAACF,QAAQ,CAAC;EACtC;EAEAG,KAAKA,CACH;IAAEC,YAAY;IAAEC,OAAO,GAAG1D,oBAAoB,CAAC;EAG/C,CAAC,EACD2D,OAA0C,EAK1C;IACA,OAAO,IAAI,CAAC9C,MAAM,CAAC2C,KAAK,CAAC;MAAEC,YAAY;MAAEC;IAAQ,CAAC,EAAEC,OAAO,CAAC;EAC9D;EAEOC,gBAAgBA,CACrBC,OAAyB,EACzBC,EAAqB,EACH;IAClB,IAAI,OAAOD,OAAO,KAAK,QAAQ,EAAE;MAC/BA,OAAO,GAAGA,OAAO,CAACA,OAAO;IAC3B;IAEA,OAAO,IAAI,CAAClC,OAAO,CAACoC,QAAQ,CAAC;MAC3BF,OAAO;MACPC;IACF,CAAC,CAAC,CAACE,UAAU,CAAC,WAAY,IAAI,CAAC;EACjC;EAEA,MAAM,CAAChD,sBAAsBiD,CAC3BP,OAAgB,EAChBD,YAAuC,EACxB;IACf,MAAM3C,MAAM,GAAG0B,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAChD,IAAI,CAAC5B,MAAM,EAAEO,KAAK,CAAC;MAAE6C,UAAU,EAAE;IAAyB,CAAC,CAAC,GAC5DC,SAAS;IAEb,IAAIT,OAAO,CAACU,OAAO,CAAC,CAAC,EAAE;MACrB,IAAI5B,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACzC5B,MAAM,EAAEuD,KAAK,CAAC,sBAAsB,CAAC;MACvC;MACA;IACF;IAEA,IAAI7B,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC5B,MAAM,EAAEuD,KAAK,CAACpE,2BAA2B,CAACyD,OAAO,CAAC,EAAE;QAAED;MAAa,CAAC,CAAC;IACvE;IAEA,IAAI;MACF,MAAMa,QAAiC,GAAG,EAAE;MAC5C,KAAK,MAAMjB,QAAQ,IAAI,IAAI,CAACzC,OAAO,CAAC2D,IAAI,CAAC,CAAC,EAAE;QAC1C,MAAMC,OAAO,GAAG,IAAI,CAAC5D,OAAO,CAACmB,IAAI,CAACsB,QAAQ,CAAC,EAAEoB,wBAAwB,GACnEf,OAAO,EACPD,YACF,CAAC;QACD,IAAIe,OAAO,EAAEF,QAAQ,CAACI,IAAI,CAACF,OAAO,CAAC;MACrC;MACA,MAAMG,OAAO,CAACC,GAAG,CAACN,QAAQ,CAAC;IAC7B,CAAC,SAAS;MACR,IAAI9B,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACzC5B,MAAM,EAAEuD,KAAK,CAAC,YAAY,EAAEpE,2BAA2B,CAACyD,OAAO,CAAC,CAAC;MACnE;IACF;EACF;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACSmB,oBAAoBA,CACzBhB,OAAyB,EACzBH,OAA4B,EACb;IACf,IAAI,OAAOG,OAAO,KAAK,QAAQ,EAAE;MAC/BA,OAAO,GAAGA,OAAO,CAACA,OAAO;IAC3B;IACA,IAAIrB,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC5B,MAAM,EAAEO,KAAK,CAAC;QAAE6C,UAAU,EAAE;MAAuB,CAAC,CAAC,CAACY,IAAI,CAC7DpB,OAAO,GAAGzD,2BAA2B,CAACyD,OAAO,CAAC,GAAG,KAAK,CACxD,CAAC;IACH;IAEA,MAAMY,QAA8B,GAAG,EAAE;IAEzC,KAAK,MAAMjB,QAAQ,IAAI,IAAI,CAACxC,MAAM,CAACkE,KAAK,CAACR,IAAI,CAAC,CAAC,EAAE;MAC/C,IAAIb,OAAO,IAAIA,OAAO,CAACsB,QAAQ,CAACC,GAAG,CAAC5B,QAAQ,CAAC,EAAE;QAC7C;MACF;MACA,MAAM6B,KAAK,GAAG,IAAI,CAACtE,OAAO,CAACmB,IAAI,CAACsB,QAAQ,CAAC;MACzC,IAAI,CAAC6B,KAAK,EAAE;MAEZZ,QAAQ,CAACI,IAAI,CAACQ,KAAK,CAACL,oBAAoB,CAAChB,OAAO,EAAEH,OAAO,CAAC,CAAC;IAC7D;;IAEA;IACA,OAAOiB,OAAO,CAACQ,UAAU,CAACb,QAAQ,CAAC,CAACc,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;EACxD;EAEA,MAAaC,aAAaA,CAAA,EAAkB;IAC1C,MAAMf,QAAiC,GAAG,EAAE;IAC5C,KAAK,MAAMjB,QAAQ,IAAI,IAAI,CAACzC,OAAO,CAAC2D,IAAI,CAAC,CAAC,EAAE;MAC1C,MAAMW,KAAK,GAAG,IAAI,CAACtE,OAAO,CAACmB,IAAI,CAACsB,QAAQ,CAAC;MACzC,IAAI6B,KAAK,EAAE;QACTZ,QAAQ,CAACI,IAAI,CAACQ,KAAK,CAAClB,UAAU,CAAC,IAAI,CAAC,CAAC;MACvC;IACF;IACA;IACA,OAAOW,OAAO,CAACQ,UAAU,CAACb,QAAQ,CAAC,CAACc,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;EACxD;EAEA,MAAaE,iBAAiBA,CAC5B3D,OAEsD,EACvC;IACf,MAAM4D,YAAY,GAAGC,KAAK,CAACC,OAAO,CAAC9D,OAAO,CAAC,GAAGA,OAAO,GAAG,CAACA,OAAO,CAAC;IACjE,MAAM2C,QAAiC,GAAG,EAAE;IAE5C,KAAK,MAAMoB,GAAG,IAAIH,YAAY,EAAE;MAC9BjB,QAAQ,CAACI,IAAI,CAAC,IAAI,CAACd,gBAAgB,CAAC8B,GAAG,CAACC,WAAW,EAAED,GAAG,CAACE,WAAW,CAAC,CAAC;IACxE;;IAEA;IACA,OAAOjB,OAAO,CAACQ,UAAU,CAACb,QAAQ,CAAC,CAACc,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;EACxD;AACF","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Store.js","names":["invariant","additionalContext","DEBUG_REFCOUNTS","ActionApplication","CacheKeys","createChangedObjects","DEBUG_ONLY__changesToString","Layers","LinksHelper","ListsHelper","ObjectsHelper","ObjectSetHelper","OrderByCanonicalizer","Queries","WhereClauseCanonicalizer","Store","whereCanonicalizer","orderByCanonicalizer","queries","layers","logger","onRevalidate","maybeRevalidateQueries","bind","subjects","constructor","client","child","msgPrefix","cacheKeys","onDestroy","cleanupCacheKey","lists","objects","links","objectSets","key","subject","peek","console","log","JSON","stringify","closed","observed","type","otherKeys","process","env","NODE_ENV","delete","applyAction","action","args","opts","validateAction","result","$validateOnly","$returnEdits","getValue","cacheKey","top","get","batch","optimisticId","changes","batchFn","invalidateObject","apiName","pk","getQuery","revalidate","#maybeRevalidateQueries","methodName","undefined","isEmpty","debug","promises","keys","promise","maybeUpdateAndRevalidate","push","Promise","all","invalidateObjectType","info","truth","modified","has","query","allSettled","then","invalidateAll","invalidateObjects","objectsArray","Array","isArray","obj","$objectType","$primaryKey"],"sources":["Store.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 Logger,\n ObjectTypeDefinition,\n Osdk,\n PrimaryKeyType,\n} from \"@osdk/api\";\nimport invariant from \"tiny-invariant\";\nimport type { ActionSignatureFromDef } from \"../../actions/applyAction.js\";\nimport { additionalContext, type Client } from \"../../Client.js\";\nimport { DEBUG_REFCOUNTS } from \"../DebugFlags.js\";\nimport type { OptimisticBuilder } from \"../OptimisticBuilder.js\";\nimport { ActionApplication } from \"./actions/ActionApplication.js\";\nimport type { BatchContext } from \"./BatchContext.js\";\nimport { CacheKeys } from \"./CacheKeys.js\";\nimport {\n type Changes,\n createChangedObjects,\n DEBUG_ONLY__changesToString,\n} from \"./Changes.js\";\nimport type { KnownCacheKey } from \"./KnownCacheKey.js\";\nimport type { Entry } from \"./Layer.js\";\nimport { Layers } from \"./Layers.js\";\nimport { LinksHelper } from \"./links/LinksHelper.js\";\nimport { ListsHelper } from \"./list/ListsHelper.js\";\nimport { ObjectsHelper } from \"./object/ObjectsHelper.js\";\nimport { ObjectSetHelper } from \"./objectset/ObjectSetHelper.js\";\nimport { type OptimisticId } from \"./OptimisticId.js\";\nimport { OrderByCanonicalizer } from \"./OrderByCanonicalizer.js\";\nimport { Queries } from \"./Queries.js\";\nimport type { Subjects } from \"./Subjects.js\";\nimport { WhereClauseCanonicalizer } from \"./WhereClauseCanonicalizer.js\";\n\nexport namespace Store {\n export interface ApplyActionOptions {\n optimisticUpdate?: (ctx: OptimisticBuilder) => void;\n }\n}\n\n/*\n Notes:\n - Subjects are one per type per store (by cache key)\n - Data is one per layer per cache key\n*/\n\n/**\n * Central data store with layered cache architecture.\n * - Truth layer: server state | Optimistic layers: pending changes\n * - Reference counting prevents memory leaks\n * - Batch operations ensure consistency\n */\nexport class Store {\n readonly whereCanonicalizer: WhereClauseCanonicalizer =\n new WhereClauseCanonicalizer();\n readonly orderByCanonicalizer: OrderByCanonicalizer =\n new OrderByCanonicalizer();\n\n readonly client: Client;\n\n /** @internal */\n readonly logger?: Logger;\n\n readonly cacheKeys: CacheKeys<KnownCacheKey>;\n readonly queries: Queries = new Queries();\n\n readonly layers: Layers = new Layers({\n logger: this.logger,\n onRevalidate: this.#maybeRevalidateQueries.bind(this),\n });\n readonly subjects: Subjects = this.layers.subjects;\n\n // these are hopefully temporary\n readonly lists: ListsHelper;\n readonly objects: ObjectsHelper;\n readonly links: LinksHelper;\n readonly objectSets: ObjectSetHelper;\n\n constructor(client: Client) {\n this.logger = client[additionalContext].logger?.child({}, {\n msgPrefix: \"Store\",\n });\n this.client = client;\n\n this.cacheKeys = new CacheKeys<KnownCacheKey>({\n onDestroy: this.#cleanupCacheKey,\n });\n\n this.lists = new ListsHelper(\n this,\n this.cacheKeys,\n this.whereCanonicalizer,\n this.orderByCanonicalizer,\n );\n this.objects = new ObjectsHelper(this, this.cacheKeys);\n this.links = new LinksHelper(\n this,\n this.cacheKeys,\n this.whereCanonicalizer,\n this.orderByCanonicalizer,\n );\n this.objectSets = new ObjectSetHelper(\n this,\n this.cacheKeys,\n this.whereCanonicalizer,\n this.orderByCanonicalizer,\n );\n }\n\n /**\n * Called after a key is no longer retained and the timeout has elapsed\n * @param key\n */\n #cleanupCacheKey = (key: KnownCacheKey) => {\n const subject = this.subjects.peek(key);\n\n if (DEBUG_REFCOUNTS) {\n // eslint-disable-next-line no-console\n console.log(\n `CacheKey cleaning up (${\n JSON.stringify({\n closed: subject?.closed,\n observed: subject?.observed,\n })\n })`,\n JSON.stringify([key.type, ...key.otherKeys], null, 2),\n );\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n invariant(subject);\n }\n\n this.subjects.delete(key);\n this.queries.delete(key);\n };\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?: Store.ApplyActionOptions,\n ) => Promise<ActionEditResponse> = async (action, args, opts) => {\n return await new ActionApplication(this).applyAction(action, args, opts);\n };\n\n validateAction: <Q extends ActionDefinition<any>>(\n action: Q,\n args: Parameters<ActionSignatureFromDef<Q>[\"applyAction\"]>[0],\n ) => Promise<ActionValidationResponse> = async (action, args) => {\n const result = await this.client(action).applyAction(args as any, {\n $validateOnly: true,\n $returnEdits: false,\n });\n return result as ActionValidationResponse;\n };\n\n public getValue<K extends KnownCacheKey>(\n cacheKey: K,\n ): Entry<K> | undefined {\n return this.layers.top.get(cacheKey);\n }\n\n batch<X>(\n { optimisticId, changes = createChangedObjects() }: {\n optimisticId?: OptimisticId;\n changes?: Changes;\n },\n batchFn: (batchContext: BatchContext) => X,\n ): {\n batchResult: BatchContext;\n retVal: X;\n changes: Changes;\n } {\n return this.layers.batch({ optimisticId, changes }, batchFn);\n }\n\n public invalidateObject<T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n pk: PrimaryKeyType<T>,\n ): Promise<unknown> {\n if (typeof apiName !== \"string\") {\n apiName = apiName.apiName;\n }\n\n return this.objects.getQuery({\n apiName,\n pk,\n }).revalidate(/* force */ true);\n }\n\n async #maybeRevalidateQueries(\n changes: Changes,\n optimisticId?: OptimisticId | undefined,\n ): Promise<void> {\n const logger = process.env.NODE_ENV !== \"production\"\n ? this.logger?.child({ methodName: \"maybeRevalidateQueries\" })\n : undefined;\n\n if (changes.isEmpty()) {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"No changes, aborting\");\n }\n return;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(DEBUG_ONLY__changesToString(changes), { optimisticId });\n }\n\n try {\n const promises: Array<Promise<unknown>> = [];\n for (const cacheKey of this.queries.keys()) {\n const promise = this.queries.peek(cacheKey)?.maybeUpdateAndRevalidate?.(\n changes,\n optimisticId,\n );\n if (promise) promises.push(promise);\n }\n await Promise.all(promises);\n } finally {\n if (process.env.NODE_ENV !== \"production\") {\n logger?.debug(\"in finally\", DEBUG_ONLY__changesToString(changes));\n }\n }\n }\n\n /**\n * Invalidates all cache entries for a specific object type.\n * This will revalidate:\n * 1. All objects of the specified type\n * 2. All lists of the specified type\n * 3. All links where the source object is of the specified type\n *\n * @param apiName - The API name of the object type to invalidate\n * @param changes - Optional changes object to track what has been modified\n * @returns Promise that resolves when all invalidations are complete\n */\n public invalidateObjectType<T extends ObjectTypeDefinition>(\n apiName: T[\"apiName\"] | T,\n changes: Changes | undefined,\n ): Promise<void> {\n if (typeof apiName !== \"string\") {\n apiName = apiName.apiName;\n }\n if (process.env.NODE_ENV !== \"production\") {\n this.logger?.child({ methodName: \"invalidateObjectType\" }).info(\n changes ? DEBUG_ONLY__changesToString(changes) : void 0,\n );\n }\n\n const promises: Array<Promise<void>> = [];\n\n for (const cacheKey of this.layers.truth.keys()) {\n if (changes && changes.modified.has(cacheKey)) {\n continue;\n }\n const query = this.queries.peek(cacheKey);\n if (!query) continue;\n\n promises.push(query.invalidateObjectType(apiName, changes));\n }\n\n // we use allSettled here because we don't care if it succeeds or fails, just that they all complete.\n return Promise.allSettled(promises).then(() => void 0);\n }\n\n public async invalidateAll(): Promise<void> {\n const promises: Array<Promise<unknown>> = [];\n for (const cacheKey of this.queries.keys()) {\n const query = this.queries.peek(cacheKey);\n if (query) {\n promises.push(query.revalidate(true));\n }\n }\n // we use allSettled here because we don't care if it succeeds or fails, just that they all complete.\n return Promise.allSettled(promises).then(() => void 0);\n }\n\n public async invalidateObjects(\n objects:\n | Osdk.Instance<ObjectTypeDefinition>\n | ReadonlyArray<Osdk.Instance<ObjectTypeDefinition>>,\n ): Promise<void> {\n const objectsArray = Array.isArray(objects) ? objects : [objects];\n const promises: Array<Promise<unknown>> = [];\n\n for (const obj of objectsArray) {\n promises.push(this.invalidateObject(obj.$objectType, obj.$primaryKey));\n }\n\n // we use allSettled here because we don't care if it succeeds or fails, just that they all complete.\n return Promise.allSettled(promises).then(() => void 0);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectSetCacheKey.js","names":[],"sources":["ObjectSetCacheKey.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 { CollectionStorageData } from \"../base-list/BaseCollectionQuery.js\";\nimport type { CacheKey } from \"../CacheKey.js\";\nimport type { Canonical } from \"../Canonical.js\";\nimport type { ObjectSetQuery } from \"./ObjectSetQuery.js\";\n\nexport interface ObjectSetStorageData extends CollectionStorageData {}\n\nexport interface ObjectSetOperations {\n where?: Canonical<any>;\n withProperties?: string[];\n union?: string[];\n intersect?: string[];\n subtract?: string[];\n pivotTo?: string;\n orderBy?: Canonical<Record<string, \"asc\" | \"desc\" | undefined>>;\n pageSize?: number;\n}\n\nexport interface ObjectSetCacheKey extends\n CacheKey<\n \"objectSet\",\n ObjectSetStorageData,\n ObjectSetQuery,\n [\n baseObjectSetWire: string,\n operations: Canonical<ObjectSetOperations>,\n ]\n >\n{\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { getWireObjectSet } from "../../../objectSet/createObjectSet.js";
|
|
18
|
+
import { AbstractHelper } from "../AbstractHelper.js";
|
|
19
|
+
import { ObjectSetQuery } from "./ObjectSetQuery.js";
|
|
20
|
+
export class ObjectSetHelper extends AbstractHelper {
|
|
21
|
+
constructor(store, cacheKeys, whereCanonicalizer, orderByCanonicalizer) {
|
|
22
|
+
super(store, cacheKeys);
|
|
23
|
+
this.whereCanonicalizer = whereCanonicalizer;
|
|
24
|
+
this.orderByCanonicalizer = orderByCanonicalizer;
|
|
25
|
+
}
|
|
26
|
+
observe(options, subFn) {
|
|
27
|
+
return super.observe(options, subFn);
|
|
28
|
+
}
|
|
29
|
+
getQuery(options) {
|
|
30
|
+
const {
|
|
31
|
+
baseObjectSet
|
|
32
|
+
} = options;
|
|
33
|
+
const baseObjectSetWire = JSON.stringify(getWireObjectSet(baseObjectSet));
|
|
34
|
+
const operations = this.buildCanonicalizedOperations(options);
|
|
35
|
+
const objectSetCacheKey = this.cacheKeys.get("objectSet", baseObjectSetWire, operations);
|
|
36
|
+
return this.store.queries.get(objectSetCacheKey, () => {
|
|
37
|
+
return new ObjectSetQuery(this.store, this.store.subjects.get(objectSetCacheKey), baseObjectSetWire, operations, objectSetCacheKey, options);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
buildCanonicalizedOperations(options) {
|
|
41
|
+
const operations = {};
|
|
42
|
+
if (options.where) {
|
|
43
|
+
operations.where = this.whereCanonicalizer.canonicalize(options.where);
|
|
44
|
+
}
|
|
45
|
+
if (options.withProperties) {
|
|
46
|
+
operations.withProperties = Object.keys(options.withProperties).sort();
|
|
47
|
+
}
|
|
48
|
+
if (options.union && options.union.length > 0) {
|
|
49
|
+
operations.union = options.union.map(os => JSON.stringify(getWireObjectSet(os)));
|
|
50
|
+
}
|
|
51
|
+
if (options.intersect && options.intersect.length > 0) {
|
|
52
|
+
operations.intersect = options.intersect.map(os => JSON.stringify(getWireObjectSet(os)));
|
|
53
|
+
}
|
|
54
|
+
if (options.subtract && options.subtract.length > 0) {
|
|
55
|
+
operations.subtract = options.subtract.map(os => JSON.stringify(getWireObjectSet(os)));
|
|
56
|
+
}
|
|
57
|
+
if (options.pivotTo) {
|
|
58
|
+
operations.pivotTo = options.pivotTo;
|
|
59
|
+
}
|
|
60
|
+
if (options.orderBy) {
|
|
61
|
+
operations.orderBy = this.orderByCanonicalizer.canonicalize(options.orderBy);
|
|
62
|
+
}
|
|
63
|
+
if (options.pageSize) {
|
|
64
|
+
operations.pageSize = options.pageSize;
|
|
65
|
+
}
|
|
66
|
+
return operations;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=ObjectSetHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectSetHelper.js","names":["getWireObjectSet","AbstractHelper","ObjectSetQuery","ObjectSetHelper","constructor","store","cacheKeys","whereCanonicalizer","orderByCanonicalizer","observe","options","subFn","getQuery","baseObjectSet","baseObjectSetWire","JSON","stringify","operations","buildCanonicalizedOperations","objectSetCacheKey","get","queries","subjects","where","canonicalize","withProperties","Object","keys","sort","union","length","map","os","intersect","subtract","pivotTo","orderBy","pageSize"],"sources":["ObjectSetHelper.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 { getWireObjectSet } from \"../../../objectSet/createObjectSet.js\";\nimport type { ObjectSetPayload } from \"../../ObjectSetPayload.js\";\nimport type { Observer } from \"../../ObservableClient/common.js\";\nimport { AbstractHelper } from \"../AbstractHelper.js\";\nimport type { CacheKeys } from \"../CacheKeys.js\";\nimport type { Canonical } from \"../Canonical.js\";\nimport type { KnownCacheKey } from \"../KnownCacheKey.js\";\nimport type { OrderByCanonicalizer } from \"../OrderByCanonicalizer.js\";\nimport type { QuerySubscription } from \"../QuerySubscription.js\";\nimport type { Store } from \"../Store.js\";\nimport type { WhereClauseCanonicalizer } from \"../WhereClauseCanonicalizer.js\";\nimport type {\n ObjectSetCacheKey,\n ObjectSetOperations,\n} from \"./ObjectSetCacheKey.js\";\nimport { ObjectSetQuery } from \"./ObjectSetQuery.js\";\nimport type { ObjectSetQueryOptions } from \"./ObjectSetQueryOptions.js\";\n\nexport class ObjectSetHelper extends AbstractHelper<\n ObjectSetQuery,\n ObjectSetQueryOptions\n> {\n whereCanonicalizer: WhereClauseCanonicalizer;\n orderByCanonicalizer: OrderByCanonicalizer;\n\n constructor(\n store: Store,\n cacheKeys: CacheKeys<KnownCacheKey>,\n whereCanonicalizer: WhereClauseCanonicalizer,\n orderByCanonicalizer: OrderByCanonicalizer,\n ) {\n super(store, cacheKeys);\n\n this.whereCanonicalizer = whereCanonicalizer;\n this.orderByCanonicalizer = orderByCanonicalizer;\n }\n\n observe(\n options: ObjectSetQueryOptions,\n subFn: Observer<ObjectSetPayload>,\n ): QuerySubscription<ObjectSetQuery> {\n return super.observe(options, subFn);\n }\n\n getQuery(options: ObjectSetQueryOptions): ObjectSetQuery {\n const { baseObjectSet } = options;\n const baseObjectSetWire = JSON.stringify(getWireObjectSet(baseObjectSet));\n const operations = this.buildCanonicalizedOperations(options);\n\n const objectSetCacheKey = this.cacheKeys.get<ObjectSetCacheKey>(\n \"objectSet\",\n baseObjectSetWire,\n operations,\n );\n\n return this.store.queries.get(objectSetCacheKey, () => {\n return new ObjectSetQuery(\n this.store,\n this.store.subjects.get(objectSetCacheKey),\n baseObjectSetWire,\n operations,\n objectSetCacheKey,\n options,\n );\n });\n }\n\n private buildCanonicalizedOperations(\n options: ObjectSetQueryOptions,\n ): Canonical<ObjectSetOperations> {\n const operations: ObjectSetOperations = {};\n\n if (options.where) {\n operations.where = this.whereCanonicalizer.canonicalize(options.where);\n }\n\n if (options.withProperties) {\n operations.withProperties = Object.keys(options.withProperties).sort();\n }\n\n if (options.union && options.union.length > 0) {\n operations.union = options.union.map(os =>\n JSON.stringify(getWireObjectSet(os))\n );\n }\n\n if (options.intersect && options.intersect.length > 0) {\n operations.intersect = options.intersect.map(os =>\n JSON.stringify(getWireObjectSet(os))\n );\n }\n\n if (options.subtract && options.subtract.length > 0) {\n operations.subtract = options.subtract.map(os =>\n JSON.stringify(getWireObjectSet(os))\n );\n }\n\n if (options.pivotTo) {\n operations.pivotTo = options.pivotTo as string;\n }\n\n if (options.orderBy) {\n operations.orderBy = this.orderByCanonicalizer.canonicalize(\n options.orderBy,\n );\n }\n\n if (options.pageSize) {\n operations.pageSize = options.pageSize;\n }\n\n return operations as Canonical<ObjectSetOperations>;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|