Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,6 @@ export const roamClaimFullMarkdownExample: {
full: {
contentType: contentTypes.markdown,
value: buildFullMarkdown({ title, blocks }),
author: { localId: "someone" },
authorId: "someone",
},
};
4 changes: 2 additions & 2 deletions apps/roam/src/utils/convertRoamNodeToFullContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ export const convertRoamNodeToFullContent = ({
const blocks = getFullTreeByParentUid(node.source_local_id).children;
const viewType = getPageViewType(title) || "bullet";
const crossAppNode: CrossAppNode = {
author: { localId: node.author_local_id },
authorId: node.author_local_id,
localId: node.source_local_id,
createdAt: new Date(node.created || Date.now()),
modifiedAt: new Date(node.last_modified || Date.now()),
nodeType: { localId: node.node_type_id },
nodeType: node.node_type_id,
content: {
direct: {
localId: node.source_local_id,
Expand Down
27 changes: 9 additions & 18 deletions packages/database/src/crossAppContracts.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
import type { ContentType } from "@repo/content-model";
import { Enums, type Json } from "./dbTypes";

export type LocalRef = {
// This localId is expected to be unique within the current space
localId: string;
};

type DbRef = {
// Some operations will refer to objects through their database Id
dbId: number;
};

// Generalized reference
export type Ref = LocalRef | DbRef;
// An identifier for objects in the platform. Expected to be unique within the platform.
export type LocalId = string;

// Common attributes for most types
export type CrossAppBase = LocalRef & {
export type CrossAppBase = {
localId: LocalId;
createdAt: Date;
modifiedAt?: Date;
author: Ref;
authorId: LocalId;
};

export type CrossAppSchemaBase = CrossAppBase & {
Expand Down Expand Up @@ -48,13 +39,13 @@ export type CrossAppRelationTripleSchema = CrossAppSchemaBase &
relation?: never;
}
| {
relation: Ref;
relation: LocalId;
label?: never;
complement?: never;
}
) & {
sourceType: Ref;
destinationType: Ref;
sourceType: LocalId;
destinationType: LocalId;
};

// An inline vector semantic embedding
Expand All @@ -79,7 +70,7 @@ type InlineCrossAppTypedContent = InlineCrossAppContent & {

// A node instance
export type CrossAppNode = CrossAppBase & {
nodeType: Ref;
nodeType: LocalId;
content: {
direct: InlineCrossAppContent;
full?: InlineCrossAppTypedContent;
Expand Down
20 changes: 8 additions & 12 deletions packages/database/src/crossAppNodeContract.example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,21 @@ Multiple studies show that sleep after learning strengthens memory traces.

export const roamOriginNodeExample: CrossAppNode = {
localId: ROAM_SOURCE_NODE_ID,
nodeType: {
localId: "rCLM0schema",
},
nodeType: "rCLM0schema",
content: {
direct: {
value: "Sleep improves memory consolidation",
author: { localId: "someone" },
authorId: "someone",
},
full: {
contentType: contentTypes.markdown,
value: roamFullMarkdown,
author: { localId: "someone" },
authorId: "someone",
},
},
createdAt: new Date("2026-06-12T14:00:00.000Z"),
modifiedAt: new Date("2026-06-12T15:00:00.000Z"),
author: { localId: "maparent" },
authorId: "maparent",
};

// const OBSIDIAN_SOURCE_SPACE_ID = "obsidian:9a8b7c6d5e4f3210";
Expand All @@ -48,21 +46,19 @@ Participants with more REM sleep showed better next-day recall.

export const obsidianOriginNodeExample: CrossAppNode = {
localId: OBSIDIAN_SOURCE_NODE_ID,
nodeType: {
localId: OBSIDIAN_SOURCE_NODE_TYPE_ID,
},
nodeType: OBSIDIAN_SOURCE_NODE_TYPE_ID,
content: {
direct: {
value: "EVD - REM sleep and recall",
author: { localId: "someone" },
authorId: "someone",
},
full: {
contentType: contentTypes.markdown,
value: obsidianFullMarkdown,
author: { localId: "someone" },
authorId: "someone",
},
},
createdAt: new Date("2026-06-14T10:30:00.000Z"),
modifiedAt: new Date("2026-06-14T15:00:00.000Z"),
author: { localId: "maparent" },
authorId: "maparent",
};
43 changes: 6 additions & 37 deletions packages/database/src/lib/crossAppConverters.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,12 @@
import {
LocalRef,
Ref,
CrossAppEmbedding,
InlineCrossAppContent,
CrossAppBase,
CrossAppNode,
} from "../crossAppContracts";
import { LocalContentDataInput, LocalConceptDataInput } from "../inputTypes";
import { Enums, CompositeTypes } from "../dbTypes";

type InlineEmbeddingInput = CompositeTypes<"inline_embedding_input">;
type InlineAbstractBase = Partial<CrossAppBase>;

const decodeLocalRef = <LocalVarName extends string>(
ref: LocalRef | InlineAbstractBase | undefined,
localVarName: LocalVarName,
): Record<LocalVarName, string> | Record<string, never> => {
if (ref === undefined) return {};
if ("localId" in ref) {
return {
[localVarName]: ref.localId,
} as Record<LocalVarName, string>;
}
return {};
};

const decodeRef = <DbVarName extends string, LocalVarName extends string>(
ref: Ref | undefined,
dbVarName: DbVarName,
localVarName: LocalVarName,
):
| Record<DbVarName, number>
| Record<LocalVarName, string>
| Record<string, never> => {
if (ref === undefined) return {};
if ("dbId" in ref)
return { [dbVarName]: ref.dbId } as Record<DbVarName, number>;
return decodeLocalRef(ref, localVarName);
};

const crossAppEmbeddingToDbEmbedding = (
embedding: CrossAppEmbedding | undefined,
Expand All @@ -64,14 +33,14 @@ const inlineCrossAppContentToDbContent = (
): LocalContentDataInput | undefined => {
if (content === undefined) return undefined;
return filterUndefined<LocalContentDataInput>({
...decodeLocalRef(content, "source_local_id"),
source_local_id: content.localId,
text: content.value,
scale: content.scale || "document",
content_type: content.contentType || "text/plain",
variant,
created: content.createdAt?.toISOString(),
last_modified: content.modifiedAt?.toISOString(),
...decodeRef(content.author, "author_id", "author_local_id"),
author_local_id: content.authorId,
embedding_inline: crossAppEmbeddingToDbEmbedding(content.embedding),
});
};
Expand All @@ -88,7 +57,7 @@ export const crossAppNodeToDbContent = (
...content,
createdAt: content.createdAt || node.createdAt,
modifiedAt: content.modifiedAt || node.modifiedAt,
author: content.author || node.author,
authorId: content.authorId || node.authorId,
},
variant,
);
Expand All @@ -98,10 +67,10 @@ export const crossAppNodeToDbConcept = (
node: CrossAppNode,
): LocalConceptDataInput => {
return filterUndefined<LocalConceptDataInput>({
...decodeLocalRef(node, "source_local_id"),
source_local_id: node.localId,
name: node.content.direct.value,
...decodeRef(node.author, "author_id", "author_local_id"),
...decodeRef(node.nodeType, "schema_id", "schema_represented_by_local_id"),
author_local_id: node.authorId,
schema_represented_by_local_id: node.nodeType,
contents_inline: filterUndefinedArray([
crossAppNodeToDbContent(node, "direct"),
crossAppNodeToDbContent(node, "full"),
Expand Down