diff --git a/packages/database/src/lib/crossAppConverters.ts b/packages/database/src/lib/crossAppConverters.ts index d5c9dfc9f..92cb99acf 100644 --- a/packages/database/src/lib/crossAppConverters.ts +++ b/packages/database/src/lib/crossAppConverters.ts @@ -1,13 +1,16 @@ import { LocalRef, Ref, + LocalOrRemoteRef, CrossAppEmbedding, InlineCrossAppContent, CrossAppBase, CrossAppNode, + CrossAppRelation, } from "../crossAppContracts"; import { LocalContentDataInput, LocalConceptDataInput } from "../inputTypes"; import { Enums, CompositeTypes } from "../dbTypes"; +import { spaceUriAndLocalIdToRid, ridToSpaceUriAndLocalId } from "./rid"; type InlineEmbeddingInput = CompositeTypes<"inline_embedding_input">; type InlineAbstractBase = Partial; @@ -39,6 +42,62 @@ const decodeRef = ( return decodeLocalRef(ref, localVarName); }; +const decodeLocalOrRemoteRef = < + LocalVarName extends string, + DbVarName extends string, +>({ + ref, + dbVarName, + localVarName, + currentSpaceUri, +}: { + ref: LocalOrRemoteRef | InlineAbstractBase | undefined; + dbVarName: DbVarName; + localVarName: LocalVarName; + currentSpaceUri: string; +}): + | Record + | Record + | Record => { + if (ref === undefined) return {}; + if ("dbId" in ref) + return { [dbVarName]: ref.dbId } as Record; + if ("rid" in ref && ref.rid !== undefined) { + const { sourceLocalId, spaceUri } = ridToSpaceUriAndLocalId(ref.rid); + if (spaceUri === currentSpaceUri) + return { + [localVarName]: sourceLocalId, + } as Record; + return { + [localVarName]: ref.rid, + } as Record; + } + if ("space" in ref && ref.space !== undefined) { + if ("dbId" in ref.space) { + // not sure how to handle this + return { + [localVarName]: ref.localId, + } as Record; + } + if ("url" in ref.space) { + if (ref.space.url === currentSpaceUri) { + return { + [localVarName]: ref.localId, + } as Record; + } else + return { + [localVarName]: spaceUriAndLocalIdToRid(ref.space.url, ref.localId), + } as Record; + } + } + if ("localId" in ref) { + return { + [localVarName]: ref.localId, + } as Record; + } + return {}; +}; + const crossAppEmbeddingToDbEmbedding = ( embedding: CrossAppEmbedding | undefined, ): InlineEmbeddingInput | undefined => @@ -109,3 +168,42 @@ export const crossAppNodeToDbConcept = ( last_modified: node.modifiedAt?.toISOString(), }); }; + +export const crossAppRelationToDbConcept = ( + node: CrossAppRelation, + currentSpaceUri: string, +): LocalConceptDataInput => { + const relData = { + ...decodeLocalOrRemoteRef({ + ref: node.source, + dbVarName: "source", + localVarName: "source_local_id", + currentSpaceUri, + }), + ...decodeLocalOrRemoteRef({ + ref: node.destination, + dbVarName: "destination", + localVarName: "destination_local_id", + currentSpaceUri, + }), + }; + const refLocalIds = Object.fromEntries( + Object.entries(relData) + .filter(([k]) => k.endsWith("_local_id")) + .map(([k, v]) => [k.substring(0, k.length - 9), v]), + ) as Record; + const refIds = Object.fromEntries( + Object.entries(relData).filter( + ([k]) => k.endsWith("_id") && !k.endsWith("_local_id"), + ), + ) as Record; + + return filterUndefined({ + ...decodeLocalRef(node, "source_local_id"), + ...decodeRef(node.author, "author_id", "author_local_id"), + local_reference_content: refLocalIds, + reference_content: refIds, + created: node.createdAt?.toISOString(), + last_modified: node.modifiedAt?.toISOString(), + }); +};