From 0905fc3c758091497ace61272857238a8d75957c Mon Sep 17 00:00:00 2001 From: Nihal Bhatnagar Date: Mon, 25 Nov 2024 15:08:35 -0600 Subject: [PATCH 1/4] Interfaces for subscribe --- .../objectSet/ObjectSetListenerWebsocket.ts | 49 ++++++++++----- packages/e2e.generated.catchall/ontology.json | 23 ++++++- .../src/generatedNoCheck/index.ts | 2 +- .../generatedNoCheck/ontology/interfaces.ts | 1 + .../ontology/interfaces/OsdkTestInterface.ts | 63 +++++++++++++++++++ .../ontology/objects/OsdkTestObject.ts | 8 ++- 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces/OsdkTestInterface.ts diff --git a/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts b/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts index 450b19147..094cb4884 100644 --- a/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts +++ b/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts @@ -35,7 +35,10 @@ import WebSocket from "isomorphic-ws"; import invariant from "tiny-invariant"; import type { Logger } from "../Logger.js"; import type { ClientCacheKey, MinimalClient } from "../MinimalClientContext.js"; -import { convertWireToOsdkObjects } from "../object/convertWireToOsdkObjects.js"; +import { + convertWireToOsdkObjects, + convertWireToOsdkObjects2, +} from "../object/convertWireToOsdkObjects.js"; const MINIMUM_RECONNECT_DELAY_MS = 5 * 1000; @@ -65,7 +68,8 @@ interface Subscription< > { listener: Required>; objectSet: ObjectSet; - primaryKeyPropertyName: string; + interfaceApiName?: string; + primaryKeyPropertyName?: string; requestedProperties: Array

; requestedReferenceProperties: Array

; subscriptionId: string; @@ -173,9 +177,13 @@ export class ObjectSetListenerWebsocket { globalThis.crypto ??= (await import("node:crypto")).webcrypto as any; } - const objDef = await this.#client.ontologyProvider.getObjectDefinition( - objectType.apiName, - ); + const objDef = objectType.type === "object" + ? await this.#client.ontologyProvider.getObjectDefinition( + objectType.apiName, + ) + : await this.#client.ontologyProvider.getInterfaceDefinition( + objectType.apiName, + ); if (properties.length === 0) { properties = Object.keys(objDef.properties) as Array

; @@ -191,13 +199,18 @@ export class ObjectSetListenerWebsocket { const sub: Subscription = { listener: fillOutListener(listener), objectSet, - primaryKeyPropertyName: objDef.primaryKeyApiName, + primaryKeyPropertyName: objDef.type === "interface" + ? undefined + : objDef.primaryKeyApiName, requestedProperties: objectProperties, requestedReferenceProperties: referenceProperties, status: "preparing", // Since we don't have a real subscription id yet but we need to keep // track of this reference, we can just use a random uuid. subscriptionId: `TMP-${crypto.randomUUID()}`, + interfaceApiName: objDef.type === "interface" + ? objDef.apiName + : undefined, }; this.#subscriptions.set(sub.subscriptionId, sub); @@ -273,12 +286,19 @@ export class ObjectSetListenerWebsocket { const subscribe: ObjectSetStreamSubscribeRequests = { id, requests: readySubs.map(( - { objectSet, requestedProperties, requestedReferenceProperties }, + { + objectSet, + requestedProperties, + requestedReferenceProperties, + interfaceApiName, + }, ) => { return { objectSet: objectSet, - propertySet: requestedProperties, - referenceSet: requestedReferenceProperties, + propertySet: interfaceApiName == null ? requestedProperties : [], + referenceSet: interfaceApiName == null + ? requestedReferenceProperties + : [], }; }), }; @@ -432,15 +452,17 @@ export class ObjectSetListenerWebsocket { ); const osdkObjectsWithReferenceUpdates = await Promise.all( referenceUpdates.map(async (o) => { - const osdkObjectArray = await convertWireToOsdkObjects( + const osdkObjectArray = await this.#client.objectFactory( this.#client, [{ __apiName: o.objectType, - __primaryKey: o.primaryKey[sub.primaryKeyPropertyName], + __primaryKey: sub.primaryKeyPropertyName != null + ? o.primaryKey[sub.primaryKeyPropertyName] + : undefined, ...o.primaryKey, [o.property]: o.value, }], - undefined, + sub.interfaceApiName, ) as Array>; const singleOsdkObject = osdkObjectArray[0] ?? undefined; return singleOsdkObject != null @@ -465,11 +487,10 @@ export class ObjectSetListenerWebsocket { for (const key of keysToDelete) { delete o.object[key]; } - const osdkObjectArray = await this.#client.objectFactory( this.#client, [o.object], - undefined, + sub.interfaceApiName, ) as Array>; const singleOsdkObject = osdkObjectArray[0] ?? undefined; return singleOsdkObject != null diff --git a/packages/e2e.generated.catchall/ontology.json b/packages/e2e.generated.catchall/ontology.json index d5dd8d28d..ea1ea2a41 100644 --- a/packages/e2e.generated.catchall/ontology.json +++ b/packages/e2e.generated.catchall/ontology.json @@ -245,13 +245,18 @@ "visibility": "NORMAL" }, "linkTypes": [], - "implementsInterfaces": ["FooInterface"], + "implementsInterfaces": ["FooInterface", "OsdkTestInterface"], "implementsInterfaces2": { "FooInterface": { "properties": { "name": "osdkObjectName", "description": "description" } + }, + "OsdkTestInterface": { + "properties": { + "objectDescription": "description" + } } }, "sharedPropertyTypeMapping": {} @@ -1294,6 +1299,22 @@ }, "rid": "ri.ontology.main.interface-type.1b1b1b1b-1b1b-1b1b-1b1b-1b1b1b1b1b1b", "status": "ACTIVE" + }, + "OsdkTestInterface": { + "apiName": "OsdkTestInterface", + "displayName": "OsdkTestInterface", + "description": "OsdkTestInterface", + "properties": { + "objectDescription": { + "rid": "ri.ontology.main.shared-property.751ed7ee-5d2c-41a1-bf60-9cbef5623f23", + "apiName": "objectDescription", + "dataType": { + "type": "string" + } + } + }, + "rid": "ri.ontology.main.interface.06c534fd-4f68-44d9-b268-72729a47eaab", + "status": "ACTIVE" } }, diff --git a/packages/e2e.generated.catchall/src/generatedNoCheck/index.ts b/packages/e2e.generated.catchall/src/generatedNoCheck/index.ts index 72d780caf..b22d4be86 100644 --- a/packages/e2e.generated.catchall/src/generatedNoCheck/index.ts +++ b/packages/e2e.generated.catchall/src/generatedNoCheck/index.ts @@ -7,7 +7,7 @@ export { editOsdkTestObject, } from './ontology/actions.js'; export * as $Actions from './ontology/actions.js'; -export { FooInterface, InterfaceNoProps } from './ontology/interfaces.js'; +export { FooInterface, InterfaceNoProps, OsdkTestInterface } from './ontology/interfaces.js'; export * as $Interfaces from './ontology/interfaces.js'; export { BoundariesUsState, diff --git a/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces.ts b/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces.ts index a571e4dfc..602f0e63b 100644 --- a/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces.ts +++ b/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces.ts @@ -1,2 +1,3 @@ export { FooInterface } from './interfaces/FooInterface.js'; export { InterfaceNoProps } from './interfaces/InterfaceNoProps.js'; +export { OsdkTestInterface } from './interfaces/OsdkTestInterface.js'; diff --git a/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces/OsdkTestInterface.ts b/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces/OsdkTestInterface.ts new file mode 100644 index 000000000..2ac8ecb24 --- /dev/null +++ b/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/interfaces/OsdkTestInterface.ts @@ -0,0 +1,63 @@ +import type { PropertyDef as $PropertyDef } from '@osdk/client'; +import { $osdkMetadata } from '../../OntologyMetadata.js'; + +import type { + InterfaceDefinition as $InterfaceDefinition, + ObjectSet as $ObjectSet, + Osdk as $Osdk, + PropertyValueWireToClient as $PropType, +} from '@osdk/client'; + +export type OsdkObjectLinks$OsdkTestInterface = {}; + +export namespace OsdkTestInterface { + export type PropertyKeys = 'objectDescription'; + + export interface Props { + readonly objectDescription: $PropType['string'] | undefined; + } + export type StrictProps = Props; + + export interface ObjectSet extends $ObjectSet {} + + export type OsdkInstance< + OPTIONS extends never | '$rid' = never, + K extends keyof OsdkTestInterface.Props = keyof OsdkTestInterface.Props, + > = $Osdk.Instance; + + /** @deprecated use OsdkInstance */ + export type OsdkObject< + OPTIONS extends never | '$rid' = never, + K extends keyof OsdkTestInterface.Props = keyof OsdkTestInterface.Props, + > = OsdkInstance; +} + +export interface OsdkTestInterface extends $InterfaceDefinition { + osdkMetadata: typeof $osdkMetadata; + type: 'interface'; + apiName: 'OsdkTestInterface'; + __DefinitionMetadata?: { + objectSet: OsdkTestInterface.ObjectSet; + props: OsdkTestInterface.Props; + linksType: OsdkObjectLinks$OsdkTestInterface; + strictProps: OsdkTestInterface.StrictProps; + apiName: 'OsdkTestInterface'; + description: 'OsdkTestInterface'; + displayName: 'OsdkTestInterface'; + links: {}; + properties: { + /** + * (no ontology metadata) + */ + objectDescription: $PropertyDef<'string', 'nullable', 'single'>; + }; + rid: 'ri.ontology.main.interface.06c534fd-4f68-44d9-b268-72729a47eaab'; + type: 'interface'; + }; +} + +export const OsdkTestInterface: OsdkTestInterface = { + type: 'interface', + apiName: 'OsdkTestInterface', + osdkMetadata: $osdkMetadata, +}; diff --git a/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/objects/OsdkTestObject.ts b/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/objects/OsdkTestObject.ts index cc90374e6..9ab2bc967 100644 --- a/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/objects/OsdkTestObject.ts +++ b/packages/e2e.generated.catchall/src/generatedNoCheck/ontology/objects/OsdkTestObject.ts @@ -58,18 +58,24 @@ export interface OsdkTestObject extends $ObjectTypeDefinition { color: '#4C90F0'; name: 'cube'; }; - implements: ['FooInterface']; + implements: ['FooInterface', 'OsdkTestInterface']; interfaceMap: { FooInterface: { name: 'osdkObjectName'; description: 'description'; }; + OsdkTestInterface: { + objectDescription: 'description'; + }; }; inverseInterfaceMap: { FooInterface: { osdkObjectName: 'name'; description: 'description'; }; + OsdkTestInterface: { + description: 'objectDescription'; + }; }; links: {}; pluralDisplayName: 'Osdk Test Objects'; From 390269199085420a2ce4e7de41e976b72db5c162 Mon Sep 17 00:00:00 2001 From: Nihal Bhatnagar Date: Mon, 25 Nov 2024 23:13:22 -0600 Subject: [PATCH 2/4] Update for reference updates --- .../objectSet/ObjectSetListenerWebsocket.ts | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts b/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts index 094cb4884..14b81f3bf 100644 --- a/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts +++ b/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts @@ -185,16 +185,25 @@ export class ObjectSetListenerWebsocket { objectType.apiName, ); - if (properties.length === 0) { - properties = Object.keys(objDef.properties) as Array

; - } + let objectProperties: Array

= []; + let referenceProperties: Array

= []; - const objectProperties = properties.filter((p) => - objDef.properties[p].type !== "geotimeSeriesReference" - ); - const referenceProperties = properties.filter((p) => - objDef.properties[p].type === "geotimeSeriesReference" - ); + if (objectType.type === "object") { + if (properties.length === 0) { + properties = Object.keys(objDef.properties) as Array

; + } + + objectProperties = properties.filter((p) => + objDef.properties[p].type !== "geotimeSeriesReference" + ); + + referenceProperties = properties.filter((p) => + objDef.properties[p].type === "geotimeSeriesReference" + ); + } else { + objectProperties = []; + referenceProperties = properties; + } const sub: Subscription = { listener: fillOutListener(listener), @@ -208,9 +217,9 @@ export class ObjectSetListenerWebsocket { // Since we don't have a real subscription id yet but we need to keep // track of this reference, we can just use a random uuid. subscriptionId: `TMP-${crypto.randomUUID()}`, - interfaceApiName: objDef.type === "interface" - ? objDef.apiName - : undefined, + interfaceApiName: objDef.type === "object" + ? undefined + : objDef.apiName, }; this.#subscriptions.set(sub.subscriptionId, sub); @@ -295,10 +304,8 @@ export class ObjectSetListenerWebsocket { ) => { return { objectSet: objectSet, - propertySet: interfaceApiName == null ? requestedProperties : [], - referenceSet: interfaceApiName == null - ? requestedReferenceProperties - : [], + propertySet: requestedProperties, + referenceSet: requestedReferenceProperties, }; }), }; From b27387bcf46e5b10275ba3028a17345a6ba87d14 Mon Sep 17 00:00:00 2001 From: Nihal Bhatnagar Date: Mon, 25 Nov 2024 23:29:56 -0600 Subject: [PATCH 3/4] Update --- .../src/runSubscriptionsTest.ts | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/e2e.sandbox.catchall/src/runSubscriptionsTest.ts b/packages/e2e.sandbox.catchall/src/runSubscriptionsTest.ts index 78b8c7903..b745db93f 100644 --- a/packages/e2e.sandbox.catchall/src/runSubscriptionsTest.ts +++ b/packages/e2e.sandbox.catchall/src/runSubscriptionsTest.ts @@ -19,7 +19,12 @@ import { __EXPERIMENTAL__NOT_SUPPORTED_YET__preexistingObjectSet, __EXPERIMENTAL__NOT_SUPPORTED_YET_subscribe, } from "@osdk/api/unstable"; -import { $Actions, MtaBus, OsdkTestObject } from "@osdk/e2e.generated.catchall"; +import { + $Actions, + MtaBus, + OsdkTestInterface, + OsdkTestObject, +} from "@osdk/e2e.generated.catchall"; import { client, dsClient } from "./client.js"; export async function runSubscriptionsTest() { @@ -67,6 +72,28 @@ export async function runSubscriptionsTest() { { properties: ["stringProperty"] }, ); + const interfaceSubscription = client(OsdkTestInterface).subscribe({ + onChange(object) { + console.log( + "Interface with primaryKey ", + object.object.$primaryKey, + " changed objectDescription to ", + object.object.objectDescription, + ); + }, + async onSuccessfulSubscription() { + console.log("Successfully subscribed to OsdkTestInterface"); + await client($Actions.createOsdkTestObject).applyAction({ + description: "test", + osdk_object_name: "OsdkTestObject", + string_property: "test", + }); + }, + onError(err) { + console.error("Error in interface subscription: ", err); + }, + }); + const mtaBusSubscription = dsClient( __EXPERIMENTAL__NOT_SUPPORTED_YET_subscribe, ).subscribe( From 45a27fa833fe78f8fdeec9a571f024f4124d54d4 Mon Sep 17 00:00:00 2001 From: Nihal Bhatnagar Date: Mon, 25 Nov 2024 23:51:14 -0600 Subject: [PATCH 4/4] changeset --- .changeset/forty-ligers-scream.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/forty-ligers-scream.md diff --git a/.changeset/forty-ligers-scream.md b/.changeset/forty-ligers-scream.md new file mode 100644 index 000000000..05adfa845 --- /dev/null +++ b/.changeset/forty-ligers-scream.md @@ -0,0 +1,5 @@ +--- +"@osdk/client": patch +--- + +Allows interfaces to be used with subscribe