Skip to content

Commit b96d227

Browse files
authored
ENG-2004 Add converter for CrossAppNode to LocalContentDataInput (#1205)
* eng-2004-converter-cross-app-node-to-localContent
1 parent f1d738e commit b96d227

2 files changed

Lines changed: 96 additions & 5 deletions

File tree

packages/database/src/crossAppContracts.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ContentType } from "@repo/content-model";
22
import { Enums } from "./dbTypes";
33

4-
type LocalRef = {
4+
export type LocalRef = {
55
// This localId is expected to be unique within the current space
66
localId: string;
77
};
@@ -12,24 +12,24 @@ type DbRef = {
1212
};
1313

1414
// Generalized reference
15-
type Ref = LocalRef | DbRef;
15+
export type Ref = LocalRef | DbRef;
1616

1717
// Common attributes for most types
18-
type CrossAppBase = LocalRef & {
18+
export type CrossAppBase = LocalRef & {
1919
createdAt: Date;
2020
modifiedAt?: Date;
2121
author: Ref;
2222
};
2323

2424
// An inline vector semantic embedding
25-
type CrossAppEmbedding = {
25+
export type CrossAppEmbedding = {
2626
value: number[];
2727
embedding?: Enums<"EmbeddingName">;
2828
};
2929

3030
// A Content object. It can be put inline inside a concept.
3131
// Missing CrossAppBase attributes are inferred from enclosing object.
32-
type InlineCrossAppContent = Partial<CrossAppBase> & {
32+
export type InlineCrossAppContent = Partial<CrossAppBase> & {
3333
value: string;
3434
embedding?: CrossAppEmbedding;
3535
scale?: Enums<"Scale">;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import {
2+
LocalRef,
3+
Ref,
4+
CrossAppEmbedding,
5+
InlineCrossAppContent,
6+
CrossAppBase,
7+
CrossAppNode,
8+
} from "../crossAppContracts";
9+
import { LocalContentDataInput } from "../inputTypes";
10+
import { Enums, CompositeTypes } from "../dbTypes";
11+
12+
type InlineEmbeddingInput = CompositeTypes<"inline_embedding_input">;
13+
type InlineAbstractBase = Partial<CrossAppBase>;
14+
15+
const decodeLocalRef = <LocalVarName extends string>(
16+
ref: LocalRef | InlineAbstractBase | undefined,
17+
localVarName: LocalVarName,
18+
): Record<LocalVarName, string> | Record<string, never> => {
19+
if (ref === undefined) return {};
20+
if ("localId" in ref) {
21+
return {
22+
[localVarName]: ref.localId,
23+
} as Record<LocalVarName, string>;
24+
}
25+
return {};
26+
};
27+
28+
const decodeRef = <DbVarName extends string, LocalVarName extends string>(
29+
ref: Ref | undefined,
30+
dbVarName: DbVarName,
31+
localVarName: LocalVarName,
32+
):
33+
| Record<DbVarName, number>
34+
| Record<LocalVarName, string>
35+
| Record<string, never> => {
36+
if (ref === undefined) return {};
37+
if ("dbId" in ref)
38+
return { [dbVarName]: ref.dbId } as Record<DbVarName, number>;
39+
return decodeLocalRef(ref, localVarName);
40+
};
41+
42+
const crossAppEmbeddingToDbEmbedding = (
43+
embedding: CrossAppEmbedding | undefined,
44+
): InlineEmbeddingInput | undefined =>
45+
embedding === undefined
46+
? undefined
47+
: {
48+
vector: embedding.value,
49+
model: embedding.embedding || "openai_text_embedding_3_small_1536",
50+
};
51+
52+
const filterUndefined = <T extends Record<string, unknown>>(data: T): T => {
53+
return Object.fromEntries(
54+
Object.entries(data).filter(([, v]) => v !== undefined),
55+
) as T;
56+
};
57+
58+
const inlineCrossAppContentToDbContent = (
59+
content: InlineCrossAppContent | undefined,
60+
variant: Enums<"ContentVariant">,
61+
): LocalContentDataInput | undefined => {
62+
if (content === undefined) return undefined;
63+
return filterUndefined<LocalContentDataInput>({
64+
...decodeLocalRef(content, "source_local_id"),
65+
text: content.value,
66+
scale: content.scale || "document",
67+
content_type: content.contentType || "text/plain",
68+
variant,
69+
created: content.createdAt?.toISOString(),
70+
last_modified: content.modifiedAt?.toISOString(),
71+
...decodeRef(content.author, "author_id", "author_local_id"),
72+
embedding_inline: crossAppEmbeddingToDbEmbedding(content.embedding),
73+
});
74+
};
75+
76+
export const crossAppNodeToDbContent = (
77+
node: CrossAppNode | undefined,
78+
variant: "full" | "direct",
79+
): LocalContentDataInput | undefined => {
80+
if (node === undefined) return undefined;
81+
const content = node.content[variant];
82+
return inlineCrossAppContentToDbContent(
83+
{
84+
...content,
85+
createdAt: content.createdAt || node.createdAt,
86+
modifiedAt: content.modifiedAt || node.modifiedAt,
87+
author: content.author || node.author,
88+
},
89+
variant,
90+
);
91+
};

0 commit comments

Comments
 (0)