@osdk/client 2.8.0-beta.14 → 2.8.0-beta.15

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @osdk/client
2
2
 
3
+ ## 2.8.0-beta.15
4
+
5
+ ### Minor Changes
6
+
7
+ - dfc8019: Preserve derived property values when subscription updates write to RDP cache keys
8
+
9
+ ### Patch Changes
10
+
11
+ - @osdk/api@2.8.0-beta.15
12
+ - @osdk/client.unstable@2.8.0-beta.15
13
+ - @osdk/generator-converters@2.8.0-beta.15
14
+
3
15
  ## 2.8.0-beta.14
4
16
 
5
17
  ### Minor Changes
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import deepEqual from "fast-deep-equal";
18
+ import { UnderlyingOsdkObject } from "../../../object/convertWireToOsdkObjects/InternalSymbols.js";
18
19
  import { getDefType } from "../../../util/interfaceUtils.js";
19
20
  import { AbstractHelper } from "../AbstractHelper.js";
20
21
  import { tombstone } from "../tombstone.js";
@@ -60,7 +61,27 @@ export class ObjectsHelper extends AbstractHelper {
60
61
  if (!dataChanged && !statusChanged) {
61
62
  return;
62
63
  }
63
- const valueToWrite = !dataChanged && existing ? existing.value : value;
64
+ let valueToWrite = !dataChanged && existing ? existing.value : value;
65
+
66
+ // When an object (e.g. from a subscription update) is written to a cache
67
+ // key that has RDP configuration, the incoming value may lack derived
68
+ // property values. Merge with the existing cached value so that RDP fields
69
+ // not present in the incoming object are preserved.
70
+ if (valueToWrite !== tombstone && existing?.value && this.isObjectHolder(existing.value)) {
71
+ const expectedRdpFields = this.store.objectCacheKeyRegistry.getRdpFieldSet(sourceCacheKey);
72
+ if (expectedRdpFields.size > 0) {
73
+ const underlying = valueToWrite[UnderlyingOsdkObject];
74
+ const actualRdpFields = new Set();
75
+ for (const field of expectedRdpFields) {
76
+ if (underlying && field in underlying) {
77
+ actualRdpFields.add(field);
78
+ }
79
+ }
80
+ if (actualRdpFields.size !== expectedRdpFields.size) {
81
+ valueToWrite = mergeObjectFields(valueToWrite, actualRdpFields, expectedRdpFields, existing.value);
82
+ }
83
+ }
84
+ }
64
85
  batch.write(sourceCacheKey, valueToWrite, status);
65
86
  if (value !== tombstone) {
66
87
  batch.changes.registerObject(sourceCacheKey, value, !existing);
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectsHelper.js","names":["deepEqual","getDefType","AbstractHelper","tombstone","mergeObjectFields","ObjectQuery","ObjectsHelper","observe","options","subFn","getQuery","rdpConfig","apiName","pk","defType","objectCacheKey","cacheKeys","get","undefined","store","queries","subjects","dedupeInterval","storeOsdkInstances","values","batch","map","v","$objectType","$apiName","$primaryKey","writeToStore","cacheKey","propagateWrite","sourceCacheKey","value","status","existing","read","dataChanged","statusChanged","valueToWrite","write","changes","registerObject","metadata","objectCacheKeyRegistry","getMetadata","relatedKeys","getVariants","primaryKey","Set","targetKey","isKeyActive","targetCurrentValue","merged","mergeForTarget","isObjectHolder","key","subject","peek","observed","pendingCleanup","sourceValue","targetCacheKey","sourceRdpFields","getRdpFieldSet","targetRdpFields"],"sources":["ObjectsHelper.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 { ObjectOrInterfaceDefinition, Osdk } from \"@osdk/api\";\nimport deepEqual from \"fast-deep-equal\";\nimport type { ObjectHolder } from \"../../../object/convertWireToOsdkObjects/ObjectHolder.js\";\nimport { getDefType } from \"../../../util/interfaceUtils.js\";\nimport type { ObjectPayload } from \"../../ObjectPayload.js\";\nimport type { ObserveObjectOptions } from \"../../ObservableClient.js\";\nimport type { Observer, Status } from \"../../ObservableClient/common.js\";\nimport { AbstractHelper } from \"../AbstractHelper.js\";\nimport type { BatchContext } from \"../BatchContext.js\";\nimport type { Canonical } from \"../Canonical.js\";\nimport type { QuerySubscription } from \"../QuerySubscription.js\";\nimport type { Rdp } from \"../RdpCanonicalizer.js\";\nimport { tombstone } from \"../tombstone.js\";\nimport { mergeObjectFields } from \"../utils/rdpFieldOperations.js\";\nimport { type ObjectCacheKey } from \"./ObjectCacheKey.js\";\nimport { ObjectQuery } from \"./ObjectQuery.js\";\n\nexport class ObjectsHelper extends AbstractHelper<\n ObjectQuery,\n ObserveObjectOptions<any>\n> {\n observe<T extends ObjectOrInterfaceDefinition>(\n options: ObserveObjectOptions<T>,\n subFn: Observer<ObjectPayload>,\n ): QuerySubscription<ObjectQuery> {\n return super.observe(options, subFn);\n }\n\n getQuery<T extends ObjectOrInterfaceDefinition>(\n options: ObserveObjectOptions<T>,\n rdpConfig?: Canonical<Rdp> | null,\n ): ObjectQuery {\n const apiName = typeof options.apiName === \"string\"\n ? options.apiName\n : options.apiName.apiName;\n const { pk } = options;\n\n const defType = getDefType(options.apiName);\n\n const objectCacheKey = this.cacheKeys.get<ObjectCacheKey>(\n \"object\",\n apiName,\n pk,\n rdpConfig ?? undefined,\n );\n\n return this.store.queries.get(objectCacheKey, () =>\n new ObjectQuery(\n this.store,\n this.store.subjects.get(objectCacheKey),\n apiName,\n pk,\n objectCacheKey,\n { dedupeInterval: 0 },\n defType,\n ));\n }\n\n /**\n * Internal helper method for writing objects to the store and returning their\n * object keys. For list queries with RDPs, the rdpConfig is included in the\n * cache key to ensure proper data isolation.\n * @internal\n */\n public storeOsdkInstances(\n values: Array<ObjectHolder> | Array<Osdk.Instance<any, any, any>>,\n batch: BatchContext,\n rdpConfig?: Canonical<Rdp> | null,\n ): ObjectCacheKey[] {\n return values.map(v =>\n this.getQuery({\n apiName: v.$objectType ?? v.$apiName,\n pk: v.$primaryKey as string | number,\n }, rdpConfig).writeToStore(\n v as ObjectHolder,\n \"loaded\",\n batch,\n ).cacheKey\n );\n }\n\n /**\n * Write an object to cache and propagate to all related cache keys\n * @internal\n */\n public propagateWrite(\n sourceCacheKey: ObjectCacheKey,\n value: ObjectHolder | typeof tombstone,\n status: Status,\n batch: BatchContext,\n ): void {\n const existing = batch.read(sourceCacheKey);\n const dataChanged = !existing\n || existing.value === undefined\n || value === tombstone\n || !deepEqual(existing.value, value);\n const statusChanged = !existing || existing.status !== status;\n\n if (!dataChanged && !statusChanged) {\n return;\n }\n\n const valueToWrite = !dataChanged && existing ? existing.value : value;\n batch.write(sourceCacheKey, valueToWrite, status);\n\n if (value !== tombstone) {\n batch.changes.registerObject(sourceCacheKey, value, !existing);\n }\n\n const metadata = this.store.objectCacheKeyRegistry.getMetadata(\n sourceCacheKey,\n );\n\n const relatedKeys = metadata\n ? this.store.objectCacheKeyRegistry.getVariants(\n metadata.apiName,\n metadata.primaryKey,\n )\n : new Set([sourceCacheKey]);\n\n for (const targetKey of relatedKeys) {\n if (targetKey === sourceCacheKey || !this.isKeyActive(targetKey)) {\n continue;\n }\n\n if (value === tombstone) {\n batch.write(targetKey, tombstone, status);\n continue;\n }\n\n const targetCurrentValue = batch.read(targetKey)?.value;\n const merged = this.mergeForTarget(\n value,\n targetCurrentValue && this.isObjectHolder(targetCurrentValue)\n ? targetCurrentValue\n : undefined,\n sourceCacheKey,\n targetKey,\n );\n\n batch.write(targetKey, merged, status);\n }\n }\n\n /**\n * Check if a cache key is actively observed or pending cleanup.\n * During React unmount-remount cycles, a key may be momentarily\n * unobserved while its cleanup is deferred to a microtask.\n * We still propagate to such keys to prevent stale data when\n * the subscription is re-established.\n */\n private isKeyActive(key: ObjectCacheKey): boolean {\n const subject = this.store.subjects.peek(key);\n if (subject?.observed === true) {\n return true;\n }\n return (this.store.pendingCleanup.get(key) ?? 0) > 0;\n }\n\n /**\n * Type guard to check if a value is an ObjectHolder\n */\n private isObjectHolder(\n value: ObjectHolder | undefined,\n ): value is ObjectHolder {\n return value != null\n && typeof value === \"object\"\n && \"$apiName\" in value\n && \"$primaryKey\" in value;\n }\n\n /**\n * Merge object data for a specific target cache key, preserving RDP fields\n */\n private mergeForTarget(\n sourceValue: ObjectHolder,\n targetCurrentValue: ObjectHolder | undefined,\n sourceCacheKey: ObjectCacheKey,\n targetCacheKey: ObjectCacheKey,\n ): ObjectHolder {\n const sourceRdpFields = this.store.objectCacheKeyRegistry.getRdpFieldSet(\n sourceCacheKey,\n );\n const targetRdpFields = this.store.objectCacheKeyRegistry.getRdpFieldSet(\n targetCacheKey,\n );\n\n return mergeObjectFields(\n sourceValue,\n sourceRdpFields,\n targetRdpFields,\n targetCurrentValue,\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"ObjectsHelper.js","names":["deepEqual","UnderlyingOsdkObject","getDefType","AbstractHelper","tombstone","mergeObjectFields","ObjectQuery","ObjectsHelper","observe","options","subFn","getQuery","rdpConfig","apiName","pk","defType","objectCacheKey","cacheKeys","get","undefined","store","queries","subjects","dedupeInterval","storeOsdkInstances","values","batch","map","v","$objectType","$apiName","$primaryKey","writeToStore","cacheKey","propagateWrite","sourceCacheKey","value","status","existing","read","dataChanged","statusChanged","valueToWrite","isObjectHolder","expectedRdpFields","objectCacheKeyRegistry","getRdpFieldSet","size","underlying","actualRdpFields","Set","field","add","write","changes","registerObject","metadata","getMetadata","relatedKeys","getVariants","primaryKey","targetKey","isKeyActive","targetCurrentValue","merged","mergeForTarget","key","subject","peek","observed","pendingCleanup","sourceValue","targetCacheKey","sourceRdpFields","targetRdpFields"],"sources":["ObjectsHelper.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 { ObjectOrInterfaceDefinition, Osdk } from \"@osdk/api\";\nimport deepEqual from \"fast-deep-equal\";\nimport { UnderlyingOsdkObject } from \"../../../object/convertWireToOsdkObjects/InternalSymbols.js\";\nimport type { ObjectHolder } from \"../../../object/convertWireToOsdkObjects/ObjectHolder.js\";\nimport { getDefType } from \"../../../util/interfaceUtils.js\";\nimport type { ObjectPayload } from \"../../ObjectPayload.js\";\nimport type { ObserveObjectOptions } from \"../../ObservableClient.js\";\nimport type { Observer, Status } from \"../../ObservableClient/common.js\";\nimport { AbstractHelper } from \"../AbstractHelper.js\";\nimport type { BatchContext } from \"../BatchContext.js\";\nimport type { Canonical } from \"../Canonical.js\";\nimport type { QuerySubscription } from \"../QuerySubscription.js\";\nimport type { Rdp } from \"../RdpCanonicalizer.js\";\nimport { tombstone } from \"../tombstone.js\";\nimport { mergeObjectFields } from \"../utils/rdpFieldOperations.js\";\nimport { type ObjectCacheKey } from \"./ObjectCacheKey.js\";\nimport { ObjectQuery } from \"./ObjectQuery.js\";\n\nexport class ObjectsHelper extends AbstractHelper<\n ObjectQuery,\n ObserveObjectOptions<any>\n> {\n observe<T extends ObjectOrInterfaceDefinition>(\n options: ObserveObjectOptions<T>,\n subFn: Observer<ObjectPayload>,\n ): QuerySubscription<ObjectQuery> {\n return super.observe(options, subFn);\n }\n\n getQuery<T extends ObjectOrInterfaceDefinition>(\n options: ObserveObjectOptions<T>,\n rdpConfig?: Canonical<Rdp> | null,\n ): ObjectQuery {\n const apiName = typeof options.apiName === \"string\"\n ? options.apiName\n : options.apiName.apiName;\n const { pk } = options;\n\n const defType = getDefType(options.apiName);\n\n const objectCacheKey = this.cacheKeys.get<ObjectCacheKey>(\n \"object\",\n apiName,\n pk,\n rdpConfig ?? undefined,\n );\n\n return this.store.queries.get(objectCacheKey, () =>\n new ObjectQuery(\n this.store,\n this.store.subjects.get(objectCacheKey),\n apiName,\n pk,\n objectCacheKey,\n { dedupeInterval: 0 },\n defType,\n ));\n }\n\n /**\n * Internal helper method for writing objects to the store and returning their\n * object keys. For list queries with RDPs, the rdpConfig is included in the\n * cache key to ensure proper data isolation.\n * @internal\n */\n public storeOsdkInstances(\n values: Array<ObjectHolder> | Array<Osdk.Instance<any, any, any>>,\n batch: BatchContext,\n rdpConfig?: Canonical<Rdp> | null,\n ): ObjectCacheKey[] {\n return values.map(v =>\n this.getQuery({\n apiName: v.$objectType ?? v.$apiName,\n pk: v.$primaryKey as string | number,\n }, rdpConfig).writeToStore(\n v as ObjectHolder,\n \"loaded\",\n batch,\n ).cacheKey\n );\n }\n\n /**\n * Write an object to cache and propagate to all related cache keys\n * @internal\n */\n public propagateWrite(\n sourceCacheKey: ObjectCacheKey,\n value: ObjectHolder | typeof tombstone,\n status: Status,\n batch: BatchContext,\n ): void {\n const existing = batch.read(sourceCacheKey);\n const dataChanged = !existing\n || existing.value === undefined\n || value === tombstone\n || !deepEqual(existing.value, value);\n const statusChanged = !existing || existing.status !== status;\n\n if (!dataChanged && !statusChanged) {\n return;\n }\n\n let valueToWrite = !dataChanged && existing ? existing.value : value;\n\n // When an object (e.g. from a subscription update) is written to a cache\n // key that has RDP configuration, the incoming value may lack derived\n // property values. Merge with the existing cached value so that RDP fields\n // not present in the incoming object are preserved.\n if (\n valueToWrite !== tombstone\n && existing?.value\n && this.isObjectHolder(existing.value)\n ) {\n const expectedRdpFields = this.store.objectCacheKeyRegistry\n .getRdpFieldSet(sourceCacheKey);\n if (expectedRdpFields.size > 0) {\n const underlying = valueToWrite[UnderlyingOsdkObject];\n const actualRdpFields = new Set<string>();\n for (const field of expectedRdpFields) {\n if (underlying && field in underlying) {\n actualRdpFields.add(field);\n }\n }\n\n if (actualRdpFields.size !== expectedRdpFields.size) {\n valueToWrite = mergeObjectFields(\n valueToWrite,\n actualRdpFields,\n expectedRdpFields,\n existing.value,\n );\n }\n }\n }\n\n batch.write(sourceCacheKey, valueToWrite, status);\n\n if (value !== tombstone) {\n batch.changes.registerObject(sourceCacheKey, value, !existing);\n }\n\n const metadata = this.store.objectCacheKeyRegistry.getMetadata(\n sourceCacheKey,\n );\n\n const relatedKeys = metadata\n ? this.store.objectCacheKeyRegistry.getVariants(\n metadata.apiName,\n metadata.primaryKey,\n )\n : new Set([sourceCacheKey]);\n\n for (const targetKey of relatedKeys) {\n if (targetKey === sourceCacheKey || !this.isKeyActive(targetKey)) {\n continue;\n }\n\n if (value === tombstone) {\n batch.write(targetKey, tombstone, status);\n continue;\n }\n\n const targetCurrentValue = batch.read(targetKey)?.value;\n const merged = this.mergeForTarget(\n value,\n targetCurrentValue && this.isObjectHolder(targetCurrentValue)\n ? targetCurrentValue\n : undefined,\n sourceCacheKey,\n targetKey,\n );\n\n batch.write(targetKey, merged, status);\n }\n }\n\n /**\n * Check if a cache key is actively observed or pending cleanup.\n * During React unmount-remount cycles, a key may be momentarily\n * unobserved while its cleanup is deferred to a microtask.\n * We still propagate to such keys to prevent stale data when\n * the subscription is re-established.\n */\n private isKeyActive(key: ObjectCacheKey): boolean {\n const subject = this.store.subjects.peek(key);\n if (subject?.observed === true) {\n return true;\n }\n return (this.store.pendingCleanup.get(key) ?? 0) > 0;\n }\n\n /**\n * Type guard to check if a value is an ObjectHolder\n */\n private isObjectHolder(\n value: ObjectHolder | undefined,\n ): value is ObjectHolder {\n return value != null\n && typeof value === \"object\"\n && \"$apiName\" in value\n && \"$primaryKey\" in value;\n }\n\n /**\n * Merge object data for a specific target cache key, preserving RDP fields\n */\n private mergeForTarget(\n sourceValue: ObjectHolder,\n targetCurrentValue: ObjectHolder | undefined,\n sourceCacheKey: ObjectCacheKey,\n targetCacheKey: ObjectCacheKey,\n ): ObjectHolder {\n const sourceRdpFields = this.store.objectCacheKeyRegistry.getRdpFieldSet(\n sourceCacheKey,\n );\n const targetRdpFields = this.store.objectCacheKeyRegistry.getRdpFieldSet(\n targetCacheKey,\n );\n\n return mergeObjectFields(\n sourceValue,\n sourceRdpFields,\n targetRdpFields,\n targetCurrentValue,\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -27,6 +27,138 @@ function createFakeRdpConfig(...fields) {
27
27
  }
28
28
  return rdp;
29
29
  }
30
+ describe("ObjectsHelper.propagateWrite RDP merge", () => {
31
+ let client;
32
+ let store;
33
+ let emp;
34
+ beforeAll(async () => {
35
+ const testSetup = startNodeApiServer(new FauxFoundry("https://stack.palantir.com/"), createClient);
36
+ client = testSetup.client;
37
+ const fauxOntology = testSetup.fauxFoundry.getDefaultOntology();
38
+ ontologies.addEmployeeOntology(fauxOntology);
39
+ testSetup.fauxFoundry.getDefaultDataStore().registerObject(Employee, {
40
+ employeeId: 1,
41
+ fullName: "Alice"
42
+ });
43
+ emp = await client(Employee).fetchOne(1, {
44
+ $includeRid: true
45
+ });
46
+ return () => {
47
+ testSetup.apiServer.close();
48
+ };
49
+ });
50
+ beforeEach(() => {
51
+ store = new Store(client);
52
+ return () => {
53
+ store = undefined;
54
+ };
55
+ });
56
+ it("skips merge when incoming object already has all expected RDP fields", () => {
57
+ // Use "fullName" as RDP field — it exists on the Employee object,
58
+ // so actualRdpFields.size === expectedRdpFields.size and merge is skipped.
59
+ const rdpConfig = createFakeRdpConfig("fullName");
60
+
61
+ // Create key B (with RDP for "fullName") and seed it
62
+ const queryB = store.objects.getQuery({
63
+ apiName: Employee,
64
+ pk: 1
65
+ }, rdpConfig);
66
+ store.batch({}, batch => {
67
+ queryB.writeToStore(emp, "loaded", batch);
68
+ });
69
+
70
+ // Write an updated object directly to key B — since the Employee
71
+ // object already has "fullName", all expected RDP fields are present
72
+ // and the merge short-circuit should fire.
73
+ const updated = emp.$clone({
74
+ fullName: "Bob"
75
+ });
76
+ store.batch({}, batch => {
77
+ queryB.writeToStore(updated, "loaded", batch);
78
+ });
79
+
80
+ // Key B should have the updated value (merge was skipped)
81
+ const valueB = store.getValue(queryB.cacheKey);
82
+ expect(valueB?.value).toEqual(expect.objectContaining({
83
+ $primaryKey: 1,
84
+ fullName: "Bob"
85
+ }));
86
+ });
87
+ it("does not merge on first write to an RDP key (no existing value)", () => {
88
+ const rdpConfig = createFakeRdpConfig("derivedAddress");
89
+
90
+ // Create key B (with RDP for "derivedAddress") — no prior write
91
+ const queryB = store.objects.getQuery({
92
+ apiName: Employee,
93
+ pk: 1
94
+ }, rdpConfig);
95
+
96
+ // First write — there is no existing value so the merge guard
97
+ // (existing?.value) is false and the value is written as-is.
98
+ store.batch({}, batch => {
99
+ queryB.writeToStore(emp, "loaded", batch);
100
+ });
101
+ const valueB = store.getValue(queryB.cacheKey);
102
+ expect(valueB?.value).toEqual(expect.objectContaining({
103
+ $primaryKey: 1,
104
+ fullName: "Alice"
105
+ }));
106
+ });
107
+ it("does not merge for a non-RDP cache key", () => {
108
+ // Create a plain (no RDP) key and write twice — the merge block
109
+ // should be skipped because expectedRdpFields is empty.
110
+ const query = store.objects.getQuery({
111
+ apiName: Employee,
112
+ pk: 1
113
+ }, undefined);
114
+ store.batch({}, batch => {
115
+ query.writeToStore(emp, "loaded", batch);
116
+ });
117
+ const updated = emp.$clone({
118
+ fullName: "Dave"
119
+ });
120
+ store.batch({}, batch => {
121
+ query.writeToStore(updated, "loaded", batch);
122
+ });
123
+ const value = store.getValue(query.cacheKey);
124
+ expect(value?.value).toEqual(expect.objectContaining({
125
+ $primaryKey: 1,
126
+ fullName: "Dave"
127
+ }));
128
+ });
129
+ it("merges when incoming object is missing expected RDP fields", () => {
130
+ // Use "derivedAddress" as RDP field — it does NOT exist on the Employee
131
+ // object, so actualRdpFields.size < expectedRdpFields.size and merge runs
132
+ // to preserve the cached RDP value.
133
+ const rdpConfig = createFakeRdpConfig("derivedAddress");
134
+
135
+ // Create key B (with RDP for "derivedAddress") and seed it
136
+ const queryB = store.objects.getQuery({
137
+ apiName: Employee,
138
+ pk: 1
139
+ }, rdpConfig);
140
+ store.batch({}, batch => {
141
+ queryB.writeToStore(emp, "loaded", batch);
142
+ });
143
+
144
+ // Write an updated object directly to key B — since "derivedAddress"
145
+ // is NOT on the Employee object, actualRdpFields < expectedRdpFields
146
+ // and merge runs to preserve cached RDP values.
147
+ const updated = emp.$clone({
148
+ fullName: "Charlie"
149
+ });
150
+ store.batch({}, batch => {
151
+ queryB.writeToStore(updated, "loaded", batch);
152
+ });
153
+
154
+ // Key B should have the updated base fields via merge
155
+ const valueB = store.getValue(queryB.cacheKey);
156
+ expect(valueB?.value).toEqual(expect.objectContaining({
157
+ $primaryKey: 1,
158
+ fullName: "Charlie"
159
+ }));
160
+ });
161
+ });
30
162
  describe("ObjectsHelper.isKeyActive", () => {
31
163
  let client;
32
164
  let store;
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectsHelper.test.js","names":["Employee","FauxFoundry","ontologies","startNodeApiServer","beforeAll","beforeEach","describe","expect","it","createClient","Store","mockSingleSubCallback","updateObject","waitForCall","createFakeRdpConfig","fields","rdp","field","client","store","emp","testSetup","fauxOntology","fauxFoundry","getDefaultOntology","addEmployeeOntology","getDefaultDataStore","registerObject","employeeId","fullName","fetchOne","$includeRid","apiServer","close","undefined","rdpConfig","queryB","objects","getQuery","apiName","pk","batch","writeToStore","subjectB","subjects","get","cacheKey","subB","subscribe","unsubscribe","pendingCleanup","set","updated","$clone","valueB","getValue","toBeDefined","value","toEqual","objectContaining","$primaryKey","delete","sub1","subFn","cacheKeys","retain","sub2","next","toHaveBeenCalledWith"],"sources":["ObjectsHelper.test.ts"],"sourcesContent":["/*\n * Copyright 2026 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 { Osdk } from \"@osdk/api\";\nimport { Employee } from \"@osdk/client.test.ontology\";\nimport { FauxFoundry, ontologies, startNodeApiServer } from \"@osdk/shared.test\";\nimport { beforeAll, beforeEach, describe, expect, it } from \"vitest\";\nimport type { Client } from \"../../../Client.js\";\nimport { createClient } from \"../../../createClient.js\";\nimport type { Canonical } from \"../Canonical.js\";\nimport type { Rdp } from \"../RdpCanonicalizer.js\";\nimport { Store } from \"../Store.js\";\nimport {\n mockSingleSubCallback,\n updateObject,\n waitForCall,\n} from \"../testUtils.js\";\n\nfunction createFakeRdpConfig(...fields: string[]): Canonical<Rdp> {\n const rdp: Rdp = {};\n for (const field of fields) {\n rdp[field] = () => ({}) as any;\n }\n return rdp as Canonical<Rdp>;\n}\n\ndescribe(\"ObjectsHelper.isKeyActive\", () => {\n let client: Client;\n let store: Store;\n let emp: Osdk.Instance<Employee>;\n\n beforeAll(async () => {\n const testSetup = startNodeApiServer(\n new FauxFoundry(\"https://stack.palantir.com/\"),\n createClient,\n );\n client = testSetup.client;\n\n const fauxOntology = testSetup.fauxFoundry.getDefaultOntology();\n ontologies.addEmployeeOntology(fauxOntology);\n\n testSetup.fauxFoundry.getDefaultDataStore().registerObject(Employee, {\n employeeId: 1,\n fullName: \"Alice\",\n });\n\n emp = await client(Employee).fetchOne(1, { $includeRid: true });\n\n return () => {\n testSetup.apiServer.close();\n };\n });\n\n beforeEach(() => {\n store = new Store(client);\n return () => {\n store = undefined!;\n };\n });\n\n it(\"propagateWrite propagates to a variant key with pending cleanup\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Seed key A (no RDP)\n updateObject(store, emp);\n\n // Create key B (with RDP) and seed it\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(\n emp as any,\n \"loaded\",\n batch,\n );\n });\n\n // Subscribe then unsubscribe to make key B unobserved\n const subjectB = store.subjects.get(queryB.cacheKey);\n const subB = subjectB.subscribe(() => {});\n subB.unsubscribe();\n\n // Simulate pending cleanup (React unmount-remount cycle)\n store.pendingCleanup.set(queryB.cacheKey, 1);\n\n // Write through key A — should propagate to B due to pending cleanup\n const updated = emp.$clone({ fullName: \"Bob\" });\n updateObject(store, updated);\n\n // Key B should have the propagated write\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB).toBeDefined();\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n $primaryKey: 1,\n fullName: \"Bob\",\n }),\n );\n });\n\n it(\"propagateWrite skips variant key that is neither observed nor pending cleanup\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Seed key A (no RDP)\n updateObject(store, emp);\n\n // Create key B (with RDP) and seed it\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(\n emp as any,\n \"loaded\",\n batch,\n );\n });\n\n // Subscribe then unsubscribe, no pending cleanup (cleanup already ran)\n const subjectB = store.subjects.get(queryB.cacheKey);\n const subB = subjectB.subscribe(() => {});\n subB.unsubscribe();\n\n // Write through key A\n const updated = emp.$clone({ fullName: \"Charlie\" });\n updateObject(store, updated);\n\n // Key B should NOT propagate (no subscribers, no pending cleanup)\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n fullName: \"Alice\", // still the original seeded value\n }),\n );\n });\n\n it(\"pending cleanup protects propagation then stops after cleanup runs\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedPhone\");\n\n // Seed both keys\n updateObject(store, emp);\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n // Subscribe, unsubscribe, mark pending cleanup\n const subjectB = store.subjects.get(queryB.cacheKey);\n const subB = subjectB.subscribe(() => {});\n subB.unsubscribe();\n store.pendingCleanup.set(queryB.cacheKey, 1);\n\n // Should propagate while pending cleanup is active\n updateObject(store, emp.$clone({ fullName: \"Bob\" }));\n expect(store.getValue(queryB.cacheKey)?.value).toEqual(\n expect.objectContaining({ fullName: \"Bob\" }),\n );\n\n // Simulate cleanup microtask completing\n store.pendingCleanup.delete(queryB.cacheKey);\n\n // Should NOT propagate after cleanup ran\n updateObject(store, emp.$clone({ fullName: \"Charlie\" }));\n expect(store.getValue(queryB.cacheKey)?.value).toEqual(\n expect.objectContaining({ fullName: \"Bob\" }),\n );\n });\n\n it(\"re-subscribing before microtask flush receives latest data\", async () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Seed both keys\n updateObject(store, emp);\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n // Subscribe, unsubscribe (unmount), mark pending cleanup\n const subjectB = store.subjects.get(queryB.cacheKey);\n const sub1 = subjectB.subscribe(() => {});\n sub1.unsubscribe();\n store.pendingCleanup.set(queryB.cacheKey, 1);\n\n // Write new data while pending cleanup is active\n updateObject(store, emp.$clone({ fullName: \"Updated\" }));\n\n // Re-subscribe (remount) — should see updated data\n const subFn = mockSingleSubCallback();\n store.cacheKeys.retain(queryB.cacheKey);\n const sub2 = subjectB.subscribe(\n (value) => subFn.next(value as any),\n );\n\n await waitForCall(subFn);\n expect(subFn.next).toHaveBeenCalledWith(\n expect.objectContaining({\n value: expect.objectContaining({\n fullName: \"Updated\",\n }),\n }),\n );\n\n sub2.unsubscribe();\n });\n});\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,QAAQ,QAAQ,4BAA4B;AACrD,SAASC,WAAW,EAAEC,UAAU,EAAEC,kBAAkB,QAAQ,mBAAmB;AAC/E,SAASC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,QAAQ;AAEpE,SAASC,YAAY,QAAQ,0BAA0B;AAGvD,SAASC,KAAK,QAAQ,aAAa;AACnC,SACEC,qBAAqB,EACrBC,YAAY,EACZC,WAAW,QACN,iBAAiB;AAExB,SAASC,mBAAmBA,CAAC,GAAGC,MAAgB,EAAkB;EAChE,MAAMC,GAAQ,GAAG,CAAC,CAAC;EACnB,KAAK,MAAMC,KAAK,IAAIF,MAAM,EAAE;IAC1BC,GAAG,CAACC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAQ;EAChC;EACA,OAAOD,GAAG;AACZ;AAEAV,QAAQ,CAAC,2BAA2B,EAAE,MAAM;EAC1C,IAAIY,MAAc;EAClB,IAAIC,KAAY;EAChB,IAAIC,GAA4B;EAEhChB,SAAS,CAAC,YAAY;IACpB,MAAMiB,SAAS,GAAGlB,kBAAkB,CAClC,IAAIF,WAAW,CAAC,6BAA6B,CAAC,EAC9CQ,YACF,CAAC;IACDS,MAAM,GAAGG,SAAS,CAACH,MAAM;IAEzB,MAAMI,YAAY,GAAGD,SAAS,CAACE,WAAW,CAACC,kBAAkB,CAAC,CAAC;IAC/DtB,UAAU,CAACuB,mBAAmB,CAACH,YAAY,CAAC;IAE5CD,SAAS,CAACE,WAAW,CAACG,mBAAmB,CAAC,CAAC,CAACC,cAAc,CAAC3B,QAAQ,EAAE;MACnE4B,UAAU,EAAE,CAAC;MACbC,QAAQ,EAAE;IACZ,CAAC,CAAC;IAEFT,GAAG,GAAG,MAAMF,MAAM,CAAClB,QAAQ,CAAC,CAAC8B,QAAQ,CAAC,CAAC,EAAE;MAAEC,WAAW,EAAE;IAAK,CAAC,CAAC;IAE/D,OAAO,MAAM;MACXV,SAAS,CAACW,SAAS,CAACC,KAAK,CAAC,CAAC;IAC7B,CAAC;EACH,CAAC,CAAC;EAEF5B,UAAU,CAAC,MAAM;IACfc,KAAK,GAAG,IAAIT,KAAK,CAACQ,MAAM,CAAC;IACzB,OAAO,MAAM;MACXC,KAAK,GAAGe,SAAU;IACpB,CAAC;EACH,CAAC,CAAC;EAEF1B,EAAE,CAAC,iEAAiE,EAAE,MAAM;IAC1E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;;IAExB;IACA,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CACjBtB,GAAG,EACH,QAAQ,EACRqB,KACF,CAAC;IACH,CAAC,CAAC;;IAEF;IACA,MAAME,QAAQ,GAAGxB,KAAK,CAACyB,QAAQ,CAACC,GAAG,CAACT,MAAM,CAACU,QAAQ,CAAC;IACpD,MAAMC,IAAI,GAAGJ,QAAQ,CAACK,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCD,IAAI,CAACE,WAAW,CAAC,CAAC;;IAElB;IACA9B,KAAK,CAAC+B,cAAc,CAACC,GAAG,CAACf,MAAM,CAACU,QAAQ,EAAE,CAAC,CAAC;;IAE5C;IACA,MAAMM,OAAO,GAAGhC,GAAG,CAACiC,MAAM,CAAC;MAAExB,QAAQ,EAAE;IAAM,CAAC,CAAC;IAC/CjB,YAAY,CAACO,KAAK,EAAEiC,OAAO,CAAC;;IAE5B;IACA,MAAME,MAAM,GAAGnC,KAAK,CAACoC,QAAQ,CAACnB,MAAM,CAACU,QAAQ,CAAC;IAC9CvC,MAAM,CAAC+C,MAAM,CAAC,CAACE,WAAW,CAAC,CAAC;IAC5BjD,MAAM,CAAC+C,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3BnD,MAAM,CAACoD,gBAAgB,CAAC;MACtBC,WAAW,EAAE,CAAC;MACd/B,QAAQ,EAAE;IACZ,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,+EAA+E,EAAE,MAAM;IACxF,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;;IAExB;IACA,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CACjBtB,GAAG,EACH,QAAQ,EACRqB,KACF,CAAC;IACH,CAAC,CAAC;;IAEF;IACA,MAAME,QAAQ,GAAGxB,KAAK,CAACyB,QAAQ,CAACC,GAAG,CAACT,MAAM,CAACU,QAAQ,CAAC;IACpD,MAAMC,IAAI,GAAGJ,QAAQ,CAACK,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCD,IAAI,CAACE,WAAW,CAAC,CAAC;;IAElB;IACA,MAAMG,OAAO,GAAGhC,GAAG,CAACiC,MAAM,CAAC;MAAExB,QAAQ,EAAE;IAAU,CAAC,CAAC;IACnDjB,YAAY,CAACO,KAAK,EAAEiC,OAAO,CAAC;;IAE5B;IACA,MAAME,MAAM,GAAGnC,KAAK,CAACoC,QAAQ,CAACnB,MAAM,CAACU,QAAQ,CAAC;IAC9CvC,MAAM,CAAC+C,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3BnD,MAAM,CAACoD,gBAAgB,CAAC;MACtB9B,QAAQ,EAAE,OAAO,CAAE;IACrB,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,oEAAoE,EAAE,MAAM;IAC7E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,cAAc,CAAC;;IAErD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;IACxB,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;;IAEF;IACA,MAAME,QAAQ,GAAGxB,KAAK,CAACyB,QAAQ,CAACC,GAAG,CAACT,MAAM,CAACU,QAAQ,CAAC;IACpD,MAAMC,IAAI,GAAGJ,QAAQ,CAACK,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCD,IAAI,CAACE,WAAW,CAAC,CAAC;IAClB9B,KAAK,CAAC+B,cAAc,CAACC,GAAG,CAACf,MAAM,CAACU,QAAQ,EAAE,CAAC,CAAC;;IAE5C;IACAlC,YAAY,CAACO,KAAK,EAAEC,GAAG,CAACiC,MAAM,CAAC;MAAExB,QAAQ,EAAE;IAAM,CAAC,CAAC,CAAC;IACpDtB,MAAM,CAACY,KAAK,CAACoC,QAAQ,CAACnB,MAAM,CAACU,QAAQ,CAAC,EAAEW,KAAK,CAAC,CAACC,OAAO,CACpDnD,MAAM,CAACoD,gBAAgB,CAAC;MAAE9B,QAAQ,EAAE;IAAM,CAAC,CAC7C,CAAC;;IAED;IACAV,KAAK,CAAC+B,cAAc,CAACW,MAAM,CAACzB,MAAM,CAACU,QAAQ,CAAC;;IAE5C;IACAlC,YAAY,CAACO,KAAK,EAAEC,GAAG,CAACiC,MAAM,CAAC;MAAExB,QAAQ,EAAE;IAAU,CAAC,CAAC,CAAC;IACxDtB,MAAM,CAACY,KAAK,CAACoC,QAAQ,CAACnB,MAAM,CAACU,QAAQ,CAAC,EAAEW,KAAK,CAAC,CAACC,OAAO,CACpDnD,MAAM,CAACoD,gBAAgB,CAAC;MAAE9B,QAAQ,EAAE;IAAM,CAAC,CAC7C,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,4DAA4D,EAAE,YAAY;IAC3E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;IACxB,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;;IAEF;IACA,MAAME,QAAQ,GAAGxB,KAAK,CAACyB,QAAQ,CAACC,GAAG,CAACT,MAAM,CAACU,QAAQ,CAAC;IACpD,MAAMgB,IAAI,GAAGnB,QAAQ,CAACK,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCc,IAAI,CAACb,WAAW,CAAC,CAAC;IAClB9B,KAAK,CAAC+B,cAAc,CAACC,GAAG,CAACf,MAAM,CAACU,QAAQ,EAAE,CAAC,CAAC;;IAE5C;IACAlC,YAAY,CAACO,KAAK,EAAEC,GAAG,CAACiC,MAAM,CAAC;MAAExB,QAAQ,EAAE;IAAU,CAAC,CAAC,CAAC;;IAExD;IACA,MAAMkC,KAAK,GAAGpD,qBAAqB,CAAC,CAAC;IACrCQ,KAAK,CAAC6C,SAAS,CAACC,MAAM,CAAC7B,MAAM,CAACU,QAAQ,CAAC;IACvC,MAAMoB,IAAI,GAAGvB,QAAQ,CAACK,SAAS,CAC5BS,KAAK,IAAKM,KAAK,CAACI,IAAI,CAACV,KAAY,CACpC,CAAC;IAED,MAAM5C,WAAW,CAACkD,KAAK,CAAC;IACxBxD,MAAM,CAACwD,KAAK,CAACI,IAAI,CAAC,CAACC,oBAAoB,CACrC7D,MAAM,CAACoD,gBAAgB,CAAC;MACtBF,KAAK,EAAElD,MAAM,CAACoD,gBAAgB,CAAC;QAC7B9B,QAAQ,EAAE;MACZ,CAAC;IACH,CAAC,CACH,CAAC;IAEDqC,IAAI,CAACjB,WAAW,CAAC,CAAC;EACpB,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"ObjectsHelper.test.js","names":["Employee","FauxFoundry","ontologies","startNodeApiServer","beforeAll","beforeEach","describe","expect","it","createClient","Store","mockSingleSubCallback","updateObject","waitForCall","createFakeRdpConfig","fields","rdp","field","client","store","emp","testSetup","fauxOntology","fauxFoundry","getDefaultOntology","addEmployeeOntology","getDefaultDataStore","registerObject","employeeId","fullName","fetchOne","$includeRid","apiServer","close","undefined","rdpConfig","queryB","objects","getQuery","apiName","pk","batch","writeToStore","updated","$clone","valueB","getValue","cacheKey","value","toEqual","objectContaining","$primaryKey","query","subjectB","subjects","get","subB","subscribe","unsubscribe","pendingCleanup","set","toBeDefined","delete","sub1","subFn","cacheKeys","retain","sub2","next","toHaveBeenCalledWith"],"sources":["ObjectsHelper.test.ts"],"sourcesContent":["/*\n * Copyright 2026 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 { Osdk } from \"@osdk/api\";\nimport { Employee } from \"@osdk/client.test.ontology\";\nimport { FauxFoundry, ontologies, startNodeApiServer } from \"@osdk/shared.test\";\nimport { beforeAll, beforeEach, describe, expect, it } from \"vitest\";\nimport type { Client } from \"../../../Client.js\";\nimport { createClient } from \"../../../createClient.js\";\nimport type { Canonical } from \"../Canonical.js\";\nimport type { Rdp } from \"../RdpCanonicalizer.js\";\nimport { Store } from \"../Store.js\";\nimport {\n mockSingleSubCallback,\n updateObject,\n waitForCall,\n} from \"../testUtils.js\";\n\nfunction createFakeRdpConfig(...fields: string[]): Canonical<Rdp> {\n const rdp: Rdp = {};\n for (const field of fields) {\n rdp[field] = () => ({}) as any;\n }\n return rdp as Canonical<Rdp>;\n}\n\ndescribe(\"ObjectsHelper.propagateWrite RDP merge\", () => {\n let client: Client;\n let store: Store;\n let emp: Osdk.Instance<Employee>;\n\n beforeAll(async () => {\n const testSetup = startNodeApiServer(\n new FauxFoundry(\"https://stack.palantir.com/\"),\n createClient,\n );\n client = testSetup.client;\n\n const fauxOntology = testSetup.fauxFoundry.getDefaultOntology();\n ontologies.addEmployeeOntology(fauxOntology);\n\n testSetup.fauxFoundry.getDefaultDataStore().registerObject(Employee, {\n employeeId: 1,\n fullName: \"Alice\",\n });\n\n emp = await client(Employee).fetchOne(1, { $includeRid: true });\n\n return () => {\n testSetup.apiServer.close();\n };\n });\n\n beforeEach(() => {\n store = new Store(client);\n return () => {\n store = undefined!;\n };\n });\n\n it(\"skips merge when incoming object already has all expected RDP fields\", () => {\n // Use \"fullName\" as RDP field — it exists on the Employee object,\n // so actualRdpFields.size === expectedRdpFields.size and merge is skipped.\n const rdpConfig = createFakeRdpConfig(\"fullName\");\n\n // Create key B (with RDP for \"fullName\") and seed it\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n // Write an updated object directly to key B — since the Employee\n // object already has \"fullName\", all expected RDP fields are present\n // and the merge short-circuit should fire.\n const updated = emp.$clone({ fullName: \"Bob\" });\n store.batch({}, (batch) => {\n queryB.writeToStore(updated as any, \"loaded\", batch);\n });\n\n // Key B should have the updated value (merge was skipped)\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n $primaryKey: 1,\n fullName: \"Bob\",\n }),\n );\n });\n\n it(\"does not merge on first write to an RDP key (no existing value)\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Create key B (with RDP for \"derivedAddress\") — no prior write\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n\n // First write — there is no existing value so the merge guard\n // (existing?.value) is false and the value is written as-is.\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n $primaryKey: 1,\n fullName: \"Alice\",\n }),\n );\n });\n\n it(\"does not merge for a non-RDP cache key\", () => {\n // Create a plain (no RDP) key and write twice — the merge block\n // should be skipped because expectedRdpFields is empty.\n const query = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, undefined);\n\n store.batch({}, (batch) => {\n query.writeToStore(emp as any, \"loaded\", batch);\n });\n\n const updated = emp.$clone({ fullName: \"Dave\" });\n store.batch({}, (batch) => {\n query.writeToStore(updated as any, \"loaded\", batch);\n });\n\n const value = store.getValue(query.cacheKey);\n expect(value?.value).toEqual(\n expect.objectContaining({\n $primaryKey: 1,\n fullName: \"Dave\",\n }),\n );\n });\n\n it(\"merges when incoming object is missing expected RDP fields\", () => {\n // Use \"derivedAddress\" as RDP field — it does NOT exist on the Employee\n // object, so actualRdpFields.size < expectedRdpFields.size and merge runs\n // to preserve the cached RDP value.\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Create key B (with RDP for \"derivedAddress\") and seed it\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n // Write an updated object directly to key B — since \"derivedAddress\"\n // is NOT on the Employee object, actualRdpFields < expectedRdpFields\n // and merge runs to preserve cached RDP values.\n const updated = emp.$clone({ fullName: \"Charlie\" });\n store.batch({}, (batch) => {\n queryB.writeToStore(updated as any, \"loaded\", batch);\n });\n\n // Key B should have the updated base fields via merge\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n $primaryKey: 1,\n fullName: \"Charlie\",\n }),\n );\n });\n});\n\ndescribe(\"ObjectsHelper.isKeyActive\", () => {\n let client: Client;\n let store: Store;\n let emp: Osdk.Instance<Employee>;\n\n beforeAll(async () => {\n const testSetup = startNodeApiServer(\n new FauxFoundry(\"https://stack.palantir.com/\"),\n createClient,\n );\n client = testSetup.client;\n\n const fauxOntology = testSetup.fauxFoundry.getDefaultOntology();\n ontologies.addEmployeeOntology(fauxOntology);\n\n testSetup.fauxFoundry.getDefaultDataStore().registerObject(Employee, {\n employeeId: 1,\n fullName: \"Alice\",\n });\n\n emp = await client(Employee).fetchOne(1, { $includeRid: true });\n\n return () => {\n testSetup.apiServer.close();\n };\n });\n\n beforeEach(() => {\n store = new Store(client);\n return () => {\n store = undefined!;\n };\n });\n\n it(\"propagateWrite propagates to a variant key with pending cleanup\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Seed key A (no RDP)\n updateObject(store, emp);\n\n // Create key B (with RDP) and seed it\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(\n emp as any,\n \"loaded\",\n batch,\n );\n });\n\n // Subscribe then unsubscribe to make key B unobserved\n const subjectB = store.subjects.get(queryB.cacheKey);\n const subB = subjectB.subscribe(() => {});\n subB.unsubscribe();\n\n // Simulate pending cleanup (React unmount-remount cycle)\n store.pendingCleanup.set(queryB.cacheKey, 1);\n\n // Write through key A — should propagate to B due to pending cleanup\n const updated = emp.$clone({ fullName: \"Bob\" });\n updateObject(store, updated);\n\n // Key B should have the propagated write\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB).toBeDefined();\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n $primaryKey: 1,\n fullName: \"Bob\",\n }),\n );\n });\n\n it(\"propagateWrite skips variant key that is neither observed nor pending cleanup\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Seed key A (no RDP)\n updateObject(store, emp);\n\n // Create key B (with RDP) and seed it\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(\n emp as any,\n \"loaded\",\n batch,\n );\n });\n\n // Subscribe then unsubscribe, no pending cleanup (cleanup already ran)\n const subjectB = store.subjects.get(queryB.cacheKey);\n const subB = subjectB.subscribe(() => {});\n subB.unsubscribe();\n\n // Write through key A\n const updated = emp.$clone({ fullName: \"Charlie\" });\n updateObject(store, updated);\n\n // Key B should NOT propagate (no subscribers, no pending cleanup)\n const valueB = store.getValue(queryB.cacheKey);\n expect(valueB?.value).toEqual(\n expect.objectContaining({\n fullName: \"Alice\", // still the original seeded value\n }),\n );\n });\n\n it(\"pending cleanup protects propagation then stops after cleanup runs\", () => {\n const rdpConfig = createFakeRdpConfig(\"derivedPhone\");\n\n // Seed both keys\n updateObject(store, emp);\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n // Subscribe, unsubscribe, mark pending cleanup\n const subjectB = store.subjects.get(queryB.cacheKey);\n const subB = subjectB.subscribe(() => {});\n subB.unsubscribe();\n store.pendingCleanup.set(queryB.cacheKey, 1);\n\n // Should propagate while pending cleanup is active\n updateObject(store, emp.$clone({ fullName: \"Bob\" }));\n expect(store.getValue(queryB.cacheKey)?.value).toEqual(\n expect.objectContaining({ fullName: \"Bob\" }),\n );\n\n // Simulate cleanup microtask completing\n store.pendingCleanup.delete(queryB.cacheKey);\n\n // Should NOT propagate after cleanup ran\n updateObject(store, emp.$clone({ fullName: \"Charlie\" }));\n expect(store.getValue(queryB.cacheKey)?.value).toEqual(\n expect.objectContaining({ fullName: \"Bob\" }),\n );\n });\n\n it(\"re-subscribing before microtask flush receives latest data\", async () => {\n const rdpConfig = createFakeRdpConfig(\"derivedAddress\");\n\n // Seed both keys\n updateObject(store, emp);\n const queryB = store.objects.getQuery({\n apiName: Employee,\n pk: 1,\n }, rdpConfig);\n store.batch({}, (batch) => {\n queryB.writeToStore(emp as any, \"loaded\", batch);\n });\n\n // Subscribe, unsubscribe (unmount), mark pending cleanup\n const subjectB = store.subjects.get(queryB.cacheKey);\n const sub1 = subjectB.subscribe(() => {});\n sub1.unsubscribe();\n store.pendingCleanup.set(queryB.cacheKey, 1);\n\n // Write new data while pending cleanup is active\n updateObject(store, emp.$clone({ fullName: \"Updated\" }));\n\n // Re-subscribe (remount) — should see updated data\n const subFn = mockSingleSubCallback();\n store.cacheKeys.retain(queryB.cacheKey);\n const sub2 = subjectB.subscribe(\n (value) => subFn.next(value as any),\n );\n\n await waitForCall(subFn);\n expect(subFn.next).toHaveBeenCalledWith(\n expect.objectContaining({\n value: expect.objectContaining({\n fullName: \"Updated\",\n }),\n }),\n );\n\n sub2.unsubscribe();\n });\n});\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,QAAQ,QAAQ,4BAA4B;AACrD,SAASC,WAAW,EAAEC,UAAU,EAAEC,kBAAkB,QAAQ,mBAAmB;AAC/E,SAASC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,QAAQ;AAEpE,SAASC,YAAY,QAAQ,0BAA0B;AAGvD,SAASC,KAAK,QAAQ,aAAa;AACnC,SACEC,qBAAqB,EACrBC,YAAY,EACZC,WAAW,QACN,iBAAiB;AAExB,SAASC,mBAAmBA,CAAC,GAAGC,MAAgB,EAAkB;EAChE,MAAMC,GAAQ,GAAG,CAAC,CAAC;EACnB,KAAK,MAAMC,KAAK,IAAIF,MAAM,EAAE;IAC1BC,GAAG,CAACC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAQ;EAChC;EACA,OAAOD,GAAG;AACZ;AAEAV,QAAQ,CAAC,wCAAwC,EAAE,MAAM;EACvD,IAAIY,MAAc;EAClB,IAAIC,KAAY;EAChB,IAAIC,GAA4B;EAEhChB,SAAS,CAAC,YAAY;IACpB,MAAMiB,SAAS,GAAGlB,kBAAkB,CAClC,IAAIF,WAAW,CAAC,6BAA6B,CAAC,EAC9CQ,YACF,CAAC;IACDS,MAAM,GAAGG,SAAS,CAACH,MAAM;IAEzB,MAAMI,YAAY,GAAGD,SAAS,CAACE,WAAW,CAACC,kBAAkB,CAAC,CAAC;IAC/DtB,UAAU,CAACuB,mBAAmB,CAACH,YAAY,CAAC;IAE5CD,SAAS,CAACE,WAAW,CAACG,mBAAmB,CAAC,CAAC,CAACC,cAAc,CAAC3B,QAAQ,EAAE;MACnE4B,UAAU,EAAE,CAAC;MACbC,QAAQ,EAAE;IACZ,CAAC,CAAC;IAEFT,GAAG,GAAG,MAAMF,MAAM,CAAClB,QAAQ,CAAC,CAAC8B,QAAQ,CAAC,CAAC,EAAE;MAAEC,WAAW,EAAE;IAAK,CAAC,CAAC;IAE/D,OAAO,MAAM;MACXV,SAAS,CAACW,SAAS,CAACC,KAAK,CAAC,CAAC;IAC7B,CAAC;EACH,CAAC,CAAC;EAEF5B,UAAU,CAAC,MAAM;IACfc,KAAK,GAAG,IAAIT,KAAK,CAACQ,MAAM,CAAC;IACzB,OAAO,MAAM;MACXC,KAAK,GAAGe,SAAU;IACpB,CAAC;EACH,CAAC,CAAC;EAEF1B,EAAE,CAAC,sEAAsE,EAAE,MAAM;IAC/E;IACA;IACA,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,UAAU,CAAC;;IAEjD;IACA,MAAMsB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;;IAEF;IACA;IACA;IACA,MAAME,OAAO,GAAGvB,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAM,CAAC,CAAC;IAC/CV,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACC,OAAO,EAAS,QAAQ,EAAEF,KAAK,CAAC;IACtD,CAAC,CAAC;;IAEF;IACA,MAAMI,MAAM,GAAG1B,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC;IAC9CxC,MAAM,CAACsC,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3B1C,MAAM,CAAC2C,gBAAgB,CAAC;MACtBC,WAAW,EAAE,CAAC;MACdtB,QAAQ,EAAE;IACZ,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,iEAAiE,EAAE,MAAM;IAC1E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACA,MAAMsB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;;IAEb;IACA;IACAhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;IAEF,MAAMI,MAAM,GAAG1B,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC;IAC9CxC,MAAM,CAACsC,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3B1C,MAAM,CAAC2C,gBAAgB,CAAC;MACtBC,WAAW,EAAE,CAAC;MACdtB,QAAQ,EAAE;IACZ,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,wCAAwC,EAAE,MAAM;IACjD;IACA;IACA,MAAM4C,KAAK,GAAGjC,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACnCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEN,SAAS,CAAC;IAEbf,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBW,KAAK,CAACV,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IACjD,CAAC,CAAC;IAEF,MAAME,OAAO,GAAGvB,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAO,CAAC,CAAC;IAChDV,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBW,KAAK,CAACV,YAAY,CAACC,OAAO,EAAS,QAAQ,EAAEF,KAAK,CAAC;IACrD,CAAC,CAAC;IAEF,MAAMO,KAAK,GAAG7B,KAAK,CAAC2B,QAAQ,CAACM,KAAK,CAACL,QAAQ,CAAC;IAC5CxC,MAAM,CAACyC,KAAK,EAAEA,KAAK,CAAC,CAACC,OAAO,CAC1B1C,MAAM,CAAC2C,gBAAgB,CAAC;MACtBC,WAAW,EAAE,CAAC;MACdtB,QAAQ,EAAE;IACZ,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,4DAA4D,EAAE,MAAM;IACrE;IACA;IACA;IACA,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACA,MAAMsB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;;IAEF;IACA;IACA;IACA,MAAME,OAAO,GAAGvB,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAU,CAAC,CAAC;IACnDV,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACC,OAAO,EAAS,QAAQ,EAAEF,KAAK,CAAC;IACtD,CAAC,CAAC;;IAEF;IACA,MAAMI,MAAM,GAAG1B,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC;IAC9CxC,MAAM,CAACsC,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3B1C,MAAM,CAAC2C,gBAAgB,CAAC;MACtBC,WAAW,EAAE,CAAC;MACdtB,QAAQ,EAAE;IACZ,CAAC,CACH,CAAC;EACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFvB,QAAQ,CAAC,2BAA2B,EAAE,MAAM;EAC1C,IAAIY,MAAc;EAClB,IAAIC,KAAY;EAChB,IAAIC,GAA4B;EAEhChB,SAAS,CAAC,YAAY;IACpB,MAAMiB,SAAS,GAAGlB,kBAAkB,CAClC,IAAIF,WAAW,CAAC,6BAA6B,CAAC,EAC9CQ,YACF,CAAC;IACDS,MAAM,GAAGG,SAAS,CAACH,MAAM;IAEzB,MAAMI,YAAY,GAAGD,SAAS,CAACE,WAAW,CAACC,kBAAkB,CAAC,CAAC;IAC/DtB,UAAU,CAACuB,mBAAmB,CAACH,YAAY,CAAC;IAE5CD,SAAS,CAACE,WAAW,CAACG,mBAAmB,CAAC,CAAC,CAACC,cAAc,CAAC3B,QAAQ,EAAE;MACnE4B,UAAU,EAAE,CAAC;MACbC,QAAQ,EAAE;IACZ,CAAC,CAAC;IAEFT,GAAG,GAAG,MAAMF,MAAM,CAAClB,QAAQ,CAAC,CAAC8B,QAAQ,CAAC,CAAC,EAAE;MAAEC,WAAW,EAAE;IAAK,CAAC,CAAC;IAE/D,OAAO,MAAM;MACXV,SAAS,CAACW,SAAS,CAACC,KAAK,CAAC,CAAC;IAC7B,CAAC;EACH,CAAC,CAAC;EAEF5B,UAAU,CAAC,MAAM;IACfc,KAAK,GAAG,IAAIT,KAAK,CAACQ,MAAM,CAAC;IACzB,OAAO,MAAM;MACXC,KAAK,GAAGe,SAAU;IACpB,CAAC;EACH,CAAC,CAAC;EAEF1B,EAAE,CAAC,iEAAiE,EAAE,MAAM;IAC1E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;;IAExB;IACA,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CACjBtB,GAAG,EACH,QAAQ,EACRqB,KACF,CAAC;IACH,CAAC,CAAC;;IAEF;IACA,MAAMY,QAAQ,GAAGlC,KAAK,CAACmC,QAAQ,CAACC,GAAG,CAACnB,MAAM,CAACW,QAAQ,CAAC;IACpD,MAAMS,IAAI,GAAGH,QAAQ,CAACI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCD,IAAI,CAACE,WAAW,CAAC,CAAC;;IAElB;IACAvC,KAAK,CAACwC,cAAc,CAACC,GAAG,CAACxB,MAAM,CAACW,QAAQ,EAAE,CAAC,CAAC;;IAE5C;IACA,MAAMJ,OAAO,GAAGvB,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAM,CAAC,CAAC;IAC/CjB,YAAY,CAACO,KAAK,EAAEwB,OAAO,CAAC;;IAE5B;IACA,MAAME,MAAM,GAAG1B,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC;IAC9CxC,MAAM,CAACsC,MAAM,CAAC,CAACgB,WAAW,CAAC,CAAC;IAC5BtD,MAAM,CAACsC,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3B1C,MAAM,CAAC2C,gBAAgB,CAAC;MACtBC,WAAW,EAAE,CAAC;MACdtB,QAAQ,EAAE;IACZ,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,+EAA+E,EAAE,MAAM;IACxF,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;;IAExB;IACA,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CACjBtB,GAAG,EACH,QAAQ,EACRqB,KACF,CAAC;IACH,CAAC,CAAC;;IAEF;IACA,MAAMY,QAAQ,GAAGlC,KAAK,CAACmC,QAAQ,CAACC,GAAG,CAACnB,MAAM,CAACW,QAAQ,CAAC;IACpD,MAAMS,IAAI,GAAGH,QAAQ,CAACI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCD,IAAI,CAACE,WAAW,CAAC,CAAC;;IAElB;IACA,MAAMf,OAAO,GAAGvB,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAU,CAAC,CAAC;IACnDjB,YAAY,CAACO,KAAK,EAAEwB,OAAO,CAAC;;IAE5B;IACA,MAAME,MAAM,GAAG1B,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC;IAC9CxC,MAAM,CAACsC,MAAM,EAAEG,KAAK,CAAC,CAACC,OAAO,CAC3B1C,MAAM,CAAC2C,gBAAgB,CAAC;MACtBrB,QAAQ,EAAE,OAAO,CAAE;IACrB,CAAC,CACH,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,oEAAoE,EAAE,MAAM;IAC7E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,cAAc,CAAC;;IAErD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;IACxB,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;;IAEF;IACA,MAAMY,QAAQ,GAAGlC,KAAK,CAACmC,QAAQ,CAACC,GAAG,CAACnB,MAAM,CAACW,QAAQ,CAAC;IACpD,MAAMS,IAAI,GAAGH,QAAQ,CAACI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCD,IAAI,CAACE,WAAW,CAAC,CAAC;IAClBvC,KAAK,CAACwC,cAAc,CAACC,GAAG,CAACxB,MAAM,CAACW,QAAQ,EAAE,CAAC,CAAC;;IAE5C;IACAnC,YAAY,CAACO,KAAK,EAAEC,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAM,CAAC,CAAC,CAAC;IACpDtB,MAAM,CAACY,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC,EAAEC,KAAK,CAAC,CAACC,OAAO,CACpD1C,MAAM,CAAC2C,gBAAgB,CAAC;MAAErB,QAAQ,EAAE;IAAM,CAAC,CAC7C,CAAC;;IAED;IACAV,KAAK,CAACwC,cAAc,CAACG,MAAM,CAAC1B,MAAM,CAACW,QAAQ,CAAC;;IAE5C;IACAnC,YAAY,CAACO,KAAK,EAAEC,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAU,CAAC,CAAC,CAAC;IACxDtB,MAAM,CAACY,KAAK,CAAC2B,QAAQ,CAACV,MAAM,CAACW,QAAQ,CAAC,EAAEC,KAAK,CAAC,CAACC,OAAO,CACpD1C,MAAM,CAAC2C,gBAAgB,CAAC;MAAErB,QAAQ,EAAE;IAAM,CAAC,CAC7C,CAAC;EACH,CAAC,CAAC;EAEFrB,EAAE,CAAC,4DAA4D,EAAE,YAAY;IAC3E,MAAM2B,SAAS,GAAGrB,mBAAmB,CAAC,gBAAgB,CAAC;;IAEvD;IACAF,YAAY,CAACO,KAAK,EAAEC,GAAG,CAAC;IACxB,MAAMgB,MAAM,GAAGjB,KAAK,CAACkB,OAAO,CAACC,QAAQ,CAAC;MACpCC,OAAO,EAAEvC,QAAQ;MACjBwC,EAAE,EAAE;IACN,CAAC,EAAEL,SAAS,CAAC;IACbhB,KAAK,CAACsB,KAAK,CAAC,CAAC,CAAC,EAAGA,KAAK,IAAK;MACzBL,MAAM,CAACM,YAAY,CAACtB,GAAG,EAAS,QAAQ,EAAEqB,KAAK,CAAC;IAClD,CAAC,CAAC;;IAEF;IACA,MAAMY,QAAQ,GAAGlC,KAAK,CAACmC,QAAQ,CAACC,GAAG,CAACnB,MAAM,CAACW,QAAQ,CAAC;IACpD,MAAMgB,IAAI,GAAGV,QAAQ,CAACI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzCM,IAAI,CAACL,WAAW,CAAC,CAAC;IAClBvC,KAAK,CAACwC,cAAc,CAACC,GAAG,CAACxB,MAAM,CAACW,QAAQ,EAAE,CAAC,CAAC;;IAE5C;IACAnC,YAAY,CAACO,KAAK,EAAEC,GAAG,CAACwB,MAAM,CAAC;MAAEf,QAAQ,EAAE;IAAU,CAAC,CAAC,CAAC;;IAExD;IACA,MAAMmC,KAAK,GAAGrD,qBAAqB,CAAC,CAAC;IACrCQ,KAAK,CAAC8C,SAAS,CAACC,MAAM,CAAC9B,MAAM,CAACW,QAAQ,CAAC;IACvC,MAAMoB,IAAI,GAAGd,QAAQ,CAACI,SAAS,CAC5BT,KAAK,IAAKgB,KAAK,CAACI,IAAI,CAACpB,KAAY,CACpC,CAAC;IAED,MAAMnC,WAAW,CAACmD,KAAK,CAAC;IACxBzD,MAAM,CAACyD,KAAK,CAACI,IAAI,CAAC,CAACC,oBAAoB,CACrC9D,MAAM,CAAC2C,gBAAgB,CAAC;MACtBF,KAAK,EAAEzC,MAAM,CAAC2C,gBAAgB,CAAC;QAC7BrB,QAAQ,EAAE;MACZ,CAAC;IACH,CAAC,CACH,CAAC;IAEDsC,IAAI,CAACT,WAAW,CAAC,CAAC;EACpB,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -14,6 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- export const USER_AGENT = `osdk-client/${"2.8.0-beta.14"}`;
18
- export const OBSERVABLE_USER_AGENT = `osdk-observable-client/${"2.8.0-beta.14"}`;
17
+ export const USER_AGENT = `osdk-client/${"2.8.0-beta.15"}`;
18
+ export const OBSERVABLE_USER_AGENT = `osdk-observable-client/${"2.8.0-beta.15"}`;
19
19
  //# sourceMappingURL=UserAgent.js.map
@@ -2044,8 +2044,8 @@ var createStandardOntologyProviderFactory = (client) => {
2044
2044
 
2045
2045
  // src/util/UserAgent.ts
2046
2046
  chunkQPPKY7HT_cjs.init_cjs_shims();
2047
- var USER_AGENT = `osdk-client/${"2.8.0-beta.14"}`;
2048
- var OBSERVABLE_USER_AGENT = `osdk-observable-client/${"2.8.0-beta.14"}`;
2047
+ var USER_AGENT = `osdk-client/${"2.8.0-beta.15"}`;
2048
+ var OBSERVABLE_USER_AGENT = `osdk-observable-client/${"2.8.0-beta.15"}`;
2049
2049
 
2050
2050
  // src/createMinimalClient.ts
2051
2051
  function createMinimalClient(metadata2, baseUrl, tokenProvider, options = {}, fetchFn = global.fetch, objectSetFactory = chunkQ2XRNNC7_cjs.createObjectSet, createOntologyProviderFactory = createStandardOntologyProviderFactory) {
@@ -2649,5 +2649,5 @@ exports.createOsdkObject = createOsdkObject;
2649
2649
  exports.extractPrimaryKeyFromObjectSpecifier = extractPrimaryKeyFromObjectSpecifier;
2650
2650
  exports.getDefType = getDefType;
2651
2651
  exports.isObjectSpecifiersObject = isObjectSpecifiersObject;
2652
- //# sourceMappingURL=chunk-4HVAJSMV.cjs.map
2653
- //# sourceMappingURL=chunk-4HVAJSMV.cjs.map
2652
+ //# sourceMappingURL=chunk-RTSJQAWK.cjs.map
2653
+ //# sourceMappingURL=chunk-RTSJQAWK.cjs.map