ocean-brain 0.1.6 → 0.2.1

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.
@@ -6,10 +6,10 @@
6
6
  <link rel="icon" type="image/png" href="/icon.png" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
8
  <title>Ocean Brain</title>
9
- <script type="module" crossorigin src="/assets/index-TKn2sngc.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-DvNRv9YC.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="/assets/note-core-DTIu0anW.js">
11
- <link rel="modulepreload" crossorigin href="/assets/note-vendor-DhbUD4OO.js">
12
- <link rel="stylesheet" crossorigin href="/assets/index-BBmw_0Bo.css">
11
+ <link rel="modulepreload" crossorigin href="/assets/note-vendor-CUVHa9LU.js">
12
+ <link rel="stylesheet" crossorigin href="/assets/index-BJgBFWwL.css">
13
13
  </head>
14
14
 
15
15
  <body>
@@ -0,0 +1,46 @@
1
+ import { ServerBlockNoteEditor } from "@blocknote/server-util";
2
+ function preprocessCustomInlineContent(blocks) {
3
+ return blocks.map((block) => ({
4
+ ...block,
5
+ content: block.content?.map((inline) => {
6
+ if (inline.type === "reference") {
7
+ return {
8
+ type: "text",
9
+ text: `[[${inline.props?.title || inline.props?.id || ""}]]`,
10
+ styles: {}
11
+ };
12
+ }
13
+ if (inline.type === "tag") {
14
+ const tag = inline.props?.tag?.replace(/^@/, "") || "";
15
+ return {
16
+ type: "text",
17
+ text: `#${tag}`,
18
+ styles: {}
19
+ };
20
+ }
21
+ return inline;
22
+ }),
23
+ children: block.children?.length ? preprocessCustomInlineContent(block.children) : []
24
+ }));
25
+ }
26
+ let editorInstance = null;
27
+ function getEditor() {
28
+ if (!editorInstance) {
29
+ editorInstance = ServerBlockNoteEditor.create();
30
+ }
31
+ return editorInstance;
32
+ }
33
+ async function blocksToMarkdown(contentJson) {
34
+ try {
35
+ const blocks = JSON.parse(contentJson);
36
+ const processed = preprocessCustomInlineContent(blocks);
37
+ const editor = getEditor();
38
+ return await editor.blocksToMarkdownLossy(processed);
39
+ } catch {
40
+ return "";
41
+ }
42
+ }
43
+ export {
44
+ blocksToMarkdown
45
+ };
46
+ //# sourceMappingURL=blocknote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/modules/blocknote.ts"],"sourcesContent":["import { ServerBlockNoteEditor } from '@blocknote/server-util';\n\ninterface BlockNote {\n id?: string;\n type: string;\n props?: Record<string, unknown>;\n content?: BlockNote[];\n children?: BlockNote[];\n text?: string;\n styles?: Record<string, unknown>;\n}\n\nfunction preprocessCustomInlineContent(blocks: BlockNote[]): BlockNote[] {\n return blocks.map((block) => ({\n ...block,\n content: block.content?.map((inline) => {\n if (inline.type === 'reference') {\n return {\n type: 'text',\n text: `[[${inline.props?.title || inline.props?.id || ''}]]`,\n styles: {}\n };\n }\n if (inline.type === 'tag') {\n const tag = (inline.props?.tag as string)?.replace(/^@/, '') || '';\n return {\n type: 'text',\n text: `#${tag}`,\n styles: {}\n };\n }\n return inline;\n }),\n children: block.children?.length\n ? preprocessCustomInlineContent(block.children)\n : []\n }));\n}\n\nlet editorInstance: ServerBlockNoteEditor | null = null;\n\nfunction getEditor(): ServerBlockNoteEditor {\n if (!editorInstance) {\n editorInstance = ServerBlockNoteEditor.create();\n }\n return editorInstance;\n}\n\nexport async function blocksToMarkdown(contentJson: string): Promise<string> {\n try {\n const blocks = JSON.parse(contentJson);\n const processed = preprocessCustomInlineContent(blocks);\n const editor = getEditor();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await editor.blocksToMarkdownLossy(processed as any);\n } catch {\n return '';\n }\n}\n"],"mappings":"AAAA,SAAS,6BAA6B;AAYtC,SAAS,8BAA8B,QAAkC;AACrE,SAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC1B,GAAG;AAAA,IACH,SAAS,MAAM,SAAS,IAAI,CAAC,WAAW;AACpC,UAAI,OAAO,SAAS,aAAa;AAC7B,eAAO;AAAA,UACH,MAAM;AAAA,UACN,MAAM,KAAK,OAAO,OAAO,SAAS,OAAO,OAAO,MAAM,EAAE;AAAA,UACxD,QAAQ,CAAC;AAAA,QACb;AAAA,MACJ;AACA,UAAI,OAAO,SAAS,OAAO;AACvB,cAAM,MAAO,OAAO,OAAO,KAAgB,QAAQ,MAAM,EAAE,KAAK;AAChE,eAAO;AAAA,UACH,MAAM;AAAA,UACN,MAAM,IAAI,GAAG;AAAA,UACb,QAAQ,CAAC;AAAA,QACb;AAAA,MACJ;AACA,aAAO;AAAA,IACX,CAAC;AAAA,IACD,UAAU,MAAM,UAAU,SACpB,8BAA8B,MAAM,QAAQ,IAC5C,CAAC;AAAA,EACX,EAAE;AACN;AAEA,IAAI,iBAA+C;AAEnD,SAAS,YAAmC;AACxC,MAAI,CAAC,gBAAgB;AACjB,qBAAiB,sBAAsB,OAAO;AAAA,EAClD;AACA,SAAO;AACX;AAEA,eAAsB,iBAAiB,aAAsC;AACzE,MAAI;AACA,UAAM,SAAS,KAAK,MAAM,WAAW;AACrC,UAAM,YAAY,8BAA8B,MAAM;AACtD,UAAM,SAAS,UAAU;AAEzB,WAAO,MAAM,OAAO,sBAAsB,SAAgB;AAAA,EAC9D,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;","names":[]}
@@ -46,6 +46,7 @@ const noteType = gql`
46
46
  id: ID!
47
47
  title: String!
48
48
  content: String!
49
+ contentAsMarkdown: String!
49
50
  createdAt: String!
50
51
  updatedAt: String!
51
52
  pinned: Boolean!
@@ -388,7 +389,13 @@ const noteResolvers = {
388
389
  return await Promise.all(updatePromises);
389
390
  }
390
391
  },
391
- Note: { tags: async (note) => await models.tag.findMany({ where: { notes: { some: { id: note.id } } } }) }
392
+ Note: {
393
+ tags: async (note) => await models.tag.findMany({ where: { notes: { some: { id: note.id } } } }),
394
+ contentAsMarkdown: async (note) => {
395
+ const { blocksToMarkdown } = await import("../../modules/blocknote.js");
396
+ return blocksToMarkdown(note.content);
397
+ }
398
+ }
392
399
  };
393
400
  export {
394
401
  noteMutation,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/schema/note/index.ts"],"sourcesContent":["import type { IResolvers } from '@graphql-tools/utils';\n\nimport models from '~/models.js';\nimport { gql } from '~/modules/graphql.js';\n\nimport type { Note, Prisma } from '~/models.js';\nimport type { Pagination, SearchFilter, NoteInput } from '~/types/index.js';\n\nexport const noteType = gql`\n input PaginationInput {\n limit: Int!\n offset: Int!\n }\n\n input SearchFilterInput {\n query: String!\n sortBy: String\n sortOrder: String\n pinnedFirst: Boolean\n }\n\n input DateRangeInput {\n start: String!\n end: String!\n }\n\n enum NoteLayout {\n narrow\n wide\n full\n }\n\n input NoteInput {\n title: String\n content: String\n layout: NoteLayout\n }\n\n input NoteOrderInput {\n id: ID!\n order: Int!\n }\n\n type Tag {\n id: ID!\n name: String!\n createdAt: String!\n updatedAt: String!\n }\n\n type Note {\n id: ID!\n title: String!\n content: String!\n createdAt: String!\n updatedAt: String!\n pinned: Boolean!\n order: Int!\n layout: NoteLayout!\n tags: [Tag!]!\n }\n\n type Notes {\n totalCount: Int!\n notes: [Note!]!\n }\n`;\n\nexport const noteQuery = gql`\n type GraphNode {\n id: ID!\n title: String!\n connections: Int!\n }\n\n type GraphLink {\n source: ID!\n target: ID!\n }\n\n type NoteGraph {\n nodes: [GraphNode!]!\n links: [GraphLink!]!\n }\n\n type Query {\n allNotes(searchFilter: SearchFilterInput, pagination: PaginationInput): Notes!\n tagNotes(searchFilter: SearchFilterInput, pagination: PaginationInput): Notes!\n notesInDateRange(dateRange: DateRangeInput): [Note!]!\n pinnedNotes: [Note!]!\n imageNotes(src: String!): [Note!]!\n backReferences(id: ID!): [Note]!\n note(id: ID!): Note!\n noteGraph: NoteGraph!\n }\n`;\n\nexport const noteMutation = gql`\n type Mutation {\n createNote(note: NoteInput!): Note!\n updateNote(id: ID!, note: NoteInput!): Note!\n deleteNote(id: ID!): Boolean!\n pinNote(id: ID!, pinned: Boolean!): Note!\n reorderNotes(notes: [NoteOrderInput!]!): [Note!]!\n }\n`;\n\nexport const noteTypeDefs = `\n ${noteType}\n ${noteQuery}\n ${noteMutation}\n`;\n\ninterface BlockNote<T = unknown> {\n id: string;\n type: string;\n props: T;\n content?: BlockNote<T>[];\n children?: BlockNote<T>[];\n}\n\nconst extractBlocksByType = <T>(type: string, dataArray: BlockNote[]): BlockNote<T>[] => {\n let result: BlockNote[] = [];\n\n for (const data of dataArray) {\n if (data.type === type) {\n result.push(data);\n }\n\n if (data.children && data.children.length > 0) {\n result = result.concat(extractBlocksByType(type, data.children));\n }\n\n if (data.content && data.content.length > 0) {\n for (const contentItem of data.content) {\n if (contentItem.type === type) {\n result.push(contentItem);\n }\n }\n }\n }\n\n return result as unknown as BlockNote<T>[];\n};\n\nexport const noteResolvers: IResolvers = {\n Query: {\n allNotes: async (_, {\n searchFilter,\n pagination\n }: {\n searchFilter: SearchFilter;\n pagination: Pagination;\n }) => {\n const queryItems = searchFilter.query.split(' ');\n const included = queryItems\n .filter((item: string) => !item.startsWith('-'))\n .map((word: string) => `%${word}%`);\n const excluded = queryItems\n .filter((item: string) => item.startsWith('-'))\n .map((item: string) => item.slice(1))\n .map((word: string) => `%${word}%`);\n\n const where: Prisma.NoteWhereInput = {\n AND: [\n ...included.map((keyword: string) => ({\n OR: [\n { title: { contains: keyword } },\n { content: { contains: keyword } }\n ]\n })),\n ...excluded.map((keyword: string) => ({\n NOT: {\n OR: [\n { title: { contains: keyword } },\n { content: { contains: keyword } }\n ]\n }\n }))\n ]\n };\n\n const sortBy = searchFilter.sortBy || 'updatedAt';\n const sortOrder = searchFilter.sortOrder || 'desc';\n const pinnedFirst = searchFilter.pinnedFirst || false;\n\n const orderBy: Prisma.NoteOrderByWithRelationInput[] = [];\n\n if (pinnedFirst) {\n orderBy.push({ pinned: 'desc' });\n }\n\n if (sortBy === 'createdAt') {\n orderBy.push({ createdAt: sortOrder as 'asc' | 'desc' });\n } else {\n orderBy.push({ updatedAt: sortOrder as 'asc' | 'desc' });\n }\n\n const $notes = models.note.findMany({\n orderBy,\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset)\n });\n return {\n totalCount: models.note.count({ where }),\n notes: $notes\n };\n },\n notesInDateRange: async (_, { dateRange }: {\n dateRange: {\n start: string;\n end: string;\n };\n }) => {\n const where: Prisma.NoteWhereInput = {\n OR: [\n {\n updatedAt: {\n gte: new Date(dateRange.start),\n lte: new Date(dateRange.end)\n }\n },\n {\n createdAt: {\n gte: new Date(dateRange.start),\n lte: new Date(dateRange.end)\n }\n }\n ]\n };\n\n const $notes = await models.note.findMany({\n orderBy: { createdAt: 'asc' },\n where\n });\n\n return $notes;\n },\n tagNotes: async (_, {\n searchFilter,\n pagination\n }: {\n searchFilter: SearchFilter;\n pagination: Pagination;\n }) => {\n const where: Prisma.NoteWhereInput = { tags: { some: { id: Number(searchFilter.query) } } };\n\n const $notes = models.note.findMany({\n orderBy: { updatedAt: 'desc' },\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset)\n });\n return {\n totalCount: models.note.count({ where }),\n notes: $notes\n };\n },\n pinnedNotes: async () => models.note.findMany({\n orderBy: [\n { order: 'asc' },\n { updatedAt: 'desc' }\n ],\n where: { pinned: true }\n }),\n imageNotes: async (_, { src }) => models.note.findMany({\n orderBy: { updatedAt: 'desc' },\n where: { content: { contains: src } }\n }),\n backReferences: async (_, { id }: Note) => {\n return models.note.findMany({\n orderBy: [\n { pinned: 'desc' },\n { updatedAt: 'desc' }\n ],\n where: { content: { contains: `reference\",\"props\":{\"id\":\"${id}\"` } }\n });\n },\n note: async (_, { id }: Note) => {\n const $note = await models.note.findUnique({ where: { id: Number(id) } });\n if (!$note) {\n throw 'NOT FOUND';\n }\n if ($note.content) {\n const blocks = extractBlocksByType<{\n id: string;\n title: string;\n }>('reference', JSON.parse($note.content));\n if (blocks.length > 0) {\n const referenceIds = blocks.map(block => Number(block.props.id));\n const $references = await models.note.findMany({ where: { id: { in: referenceIds } } });\n const newContent = $references.reduce<string>((acc: string, $reference: Note) => {\n const reference = blocks.find(block => Number(block.props.id) === $reference.id);\n if (reference && reference.props.title !== $reference.title) {\n return acc.replace(\n `reference\",\"props\":{\"id\":\"${reference.props.id}\",\"title\":\"${reference.props.title}\"`,\n `reference\",\"props\":{\"id\":\"${$reference.id}\",\"title\":\"${$reference.title}\"`\n );\n }\n return acc;\n }, $note.content);\n if (newContent !== $note.content) {\n try {\n JSON.parse(newContent);\n return await models.note.update({\n where: { id: $note.id },\n data: { content: newContent }\n });\n } catch (e) {\n console.error(e);\n }\n }\n }\n }\n return $note;\n },\n noteGraph: async () => {\n const $notes = await models.note.findMany({\n select: {\n id: true,\n title: true,\n content: true\n }\n });\n\n const nodes: Array<{ id: string; title: string; connections: number }> = [];\n const links: Array<{ source: string; target: string }> = [];\n const connectionCount: Record<string, number> = {};\n const linkSet = new Set<string>();\n\n // Extract all references from each note\n for (const $note of $notes) {\n if ($note.content) {\n try {\n const blocks = extractBlocksByType<{ id: string }>('reference', JSON.parse($note.content));\n for (const block of blocks) {\n const targetId = block.props.id;\n // Avoid self-references and duplicate links\n if (targetId && String($note.id) !== targetId) {\n const linkKey = `${$note.id}-${targetId}`;\n const reverseLinkKey = `${targetId}-${$note.id}`;\n if (!linkSet.has(linkKey) && !linkSet.has(reverseLinkKey)) {\n linkSet.add(linkKey);\n links.push({\n source: String($note.id),\n target: targetId\n });\n // Count connections for both nodes\n connectionCount[String($note.id)] = (connectionCount[String($note.id)] || 0) + 1;\n connectionCount[targetId] = (connectionCount[targetId] || 0) + 1;\n }\n }\n }\n } catch {\n // Skip notes with invalid JSON content\n }\n }\n }\n\n // Build nodes array with connection counts\n for (const $note of $notes) {\n nodes.push({\n id: String($note.id),\n title: $note.title || 'Untitled',\n connections: connectionCount[String($note.id)] || 0\n });\n }\n\n return {\n nodes,\n links\n };\n }\n },\n Mutation: {\n createNote: async (_, { note }: { note: NoteInput }) => {\n const PLACEHOLDER_PREFIX = '{%';\n const PLACEHOLDER_SUFFIX = '%}';\n\n const replacePlaceholder = async (content: string) => {\n const placeholders = content.matchAll(new RegExp(`${PLACEHOLDER_PREFIX}([^}]+)${PLACEHOLDER_SUFFIX}`, 'g'));\n const $placeholders = await models.placeholder.findMany({\n select: {\n template: true,\n replacement: true\n },\n where: { template: { in: Array.from(new Set(Array.from(placeholders, p => p[1]))) } }\n });\n\n for (const $placeholder of $placeholders) {\n content = content.replace(new RegExp(`${PLACEHOLDER_PREFIX}${$placeholder.template}${PLACEHOLDER_SUFFIX}`, 'g'), $placeholder.replacement);\n }\n return content;\n };\n\n const replacedTitle = await replacePlaceholder(note.title);\n const replacedContent = await replacePlaceholder(note.content);\n\n const $note = await models.note.create({\n data: {\n title: replacedTitle,\n content: replacedContent,\n ...(note.layout && { layout: note.layout })\n }\n });\n if (note.content) {\n const blocks = extractBlocksByType<{ id: string }>(\n 'tag',\n JSON.parse(note.content)\n );\n\n return await models.note.update({\n where: { id: $note.id },\n data: { tags: { set: blocks.map(block => ({ id: Number(block.props.id) })) } }\n });\n }\n\n return $note;\n },\n updateNote: async (_, { id, note }: { id: number; note: NoteInput }) => {\n let blocks: BlockNote<{ id: string }>[] = [];\n\n if (note.content) {\n blocks = extractBlocksByType<{ id: string }>(\n 'tag',\n JSON.parse(note.content)\n );\n }\n\n const $note = await models.note.update({\n where: { id: Number(id) },\n data: {\n ...note,\n ...(note.content ? { tags: { set: blocks.map(block => ({ id: Number(block.props.id) })) } } : {})\n }\n });\n return $note;\n },\n deleteNote: async (_, { id }: Note) => {\n await models.tag.deleteMany({ where: { notes: { none: {} } } });\n await models.note.delete({ where: { id: Number(id) } });\n return true;\n },\n pinNote: (_, { id, pinned }: Note) => models.note.update({\n where: { id: Number(id) },\n data: { pinned: Boolean(pinned) }\n }),\n reorderNotes: async (_, { notes }: { notes: Array<{ id: string; order: number }> }) => {\n const updatePromises = notes.map(({ id, order }) =>\n models.note.update({\n where: { id: Number(id) },\n data: { order }\n })\n );\n return await Promise.all(updatePromises);\n }\n },\n Note: { tags: async (note: Note) => await models.tag.findMany({ where: { notes: { some: { id: note.id } } } }) }\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/schema/note/index.ts"],"sourcesContent":["import type { IResolvers } from '@graphql-tools/utils';\n\nimport models from '~/models.js';\nimport { gql } from '~/modules/graphql.js';\n\nimport type { Note, Prisma } from '~/models.js';\nimport type { Pagination, SearchFilter, NoteInput } from '~/types/index.js';\n\nexport const noteType = gql`\n input PaginationInput {\n limit: Int!\n offset: Int!\n }\n\n input SearchFilterInput {\n query: String!\n sortBy: String\n sortOrder: String\n pinnedFirst: Boolean\n }\n\n input DateRangeInput {\n start: String!\n end: String!\n }\n\n enum NoteLayout {\n narrow\n wide\n full\n }\n\n input NoteInput {\n title: String\n content: String\n layout: NoteLayout\n }\n\n input NoteOrderInput {\n id: ID!\n order: Int!\n }\n\n type Tag {\n id: ID!\n name: String!\n createdAt: String!\n updatedAt: String!\n }\n\n type Note {\n id: ID!\n title: String!\n content: String!\n contentAsMarkdown: String!\n createdAt: String!\n updatedAt: String!\n pinned: Boolean!\n order: Int!\n layout: NoteLayout!\n tags: [Tag!]!\n }\n\n type Notes {\n totalCount: Int!\n notes: [Note!]!\n }\n`;\n\nexport const noteQuery = gql`\n type GraphNode {\n id: ID!\n title: String!\n connections: Int!\n }\n\n type GraphLink {\n source: ID!\n target: ID!\n }\n\n type NoteGraph {\n nodes: [GraphNode!]!\n links: [GraphLink!]!\n }\n\n type Query {\n allNotes(searchFilter: SearchFilterInput, pagination: PaginationInput): Notes!\n tagNotes(searchFilter: SearchFilterInput, pagination: PaginationInput): Notes!\n notesInDateRange(dateRange: DateRangeInput): [Note!]!\n pinnedNotes: [Note!]!\n imageNotes(src: String!): [Note!]!\n backReferences(id: ID!): [Note]!\n note(id: ID!): Note!\n noteGraph: NoteGraph!\n }\n`;\n\nexport const noteMutation = gql`\n type Mutation {\n createNote(note: NoteInput!): Note!\n updateNote(id: ID!, note: NoteInput!): Note!\n deleteNote(id: ID!): Boolean!\n pinNote(id: ID!, pinned: Boolean!): Note!\n reorderNotes(notes: [NoteOrderInput!]!): [Note!]!\n }\n`;\n\nexport const noteTypeDefs = `\n ${noteType}\n ${noteQuery}\n ${noteMutation}\n`;\n\ninterface BlockNote<T = unknown> {\n id: string;\n type: string;\n props: T;\n content?: BlockNote<T>[];\n children?: BlockNote<T>[];\n}\n\nconst extractBlocksByType = <T>(type: string, dataArray: BlockNote[]): BlockNote<T>[] => {\n let result: BlockNote[] = [];\n\n for (const data of dataArray) {\n if (data.type === type) {\n result.push(data);\n }\n\n if (data.children && data.children.length > 0) {\n result = result.concat(extractBlocksByType(type, data.children));\n }\n\n if (data.content && data.content.length > 0) {\n for (const contentItem of data.content) {\n if (contentItem.type === type) {\n result.push(contentItem);\n }\n }\n }\n }\n\n return result as unknown as BlockNote<T>[];\n};\n\nexport const noteResolvers: IResolvers = {\n Query: {\n allNotes: async (_, {\n searchFilter,\n pagination\n }: {\n searchFilter: SearchFilter;\n pagination: Pagination;\n }) => {\n const queryItems = searchFilter.query.split(' ');\n const included = queryItems\n .filter((item: string) => !item.startsWith('-'))\n .map((word: string) => `%${word}%`);\n const excluded = queryItems\n .filter((item: string) => item.startsWith('-'))\n .map((item: string) => item.slice(1))\n .map((word: string) => `%${word}%`);\n\n const where: Prisma.NoteWhereInput = {\n AND: [\n ...included.map((keyword: string) => ({\n OR: [\n { title: { contains: keyword } },\n { content: { contains: keyword } }\n ]\n })),\n ...excluded.map((keyword: string) => ({\n NOT: {\n OR: [\n { title: { contains: keyword } },\n { content: { contains: keyword } }\n ]\n }\n }))\n ]\n };\n\n const sortBy = searchFilter.sortBy || 'updatedAt';\n const sortOrder = searchFilter.sortOrder || 'desc';\n const pinnedFirst = searchFilter.pinnedFirst || false;\n\n const orderBy: Prisma.NoteOrderByWithRelationInput[] = [];\n\n if (pinnedFirst) {\n orderBy.push({ pinned: 'desc' });\n }\n\n if (sortBy === 'createdAt') {\n orderBy.push({ createdAt: sortOrder as 'asc' | 'desc' });\n } else {\n orderBy.push({ updatedAt: sortOrder as 'asc' | 'desc' });\n }\n\n const $notes = models.note.findMany({\n orderBy,\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset)\n });\n return {\n totalCount: models.note.count({ where }),\n notes: $notes\n };\n },\n notesInDateRange: async (_, { dateRange }: {\n dateRange: {\n start: string;\n end: string;\n };\n }) => {\n const where: Prisma.NoteWhereInput = {\n OR: [\n {\n updatedAt: {\n gte: new Date(dateRange.start),\n lte: new Date(dateRange.end)\n }\n },\n {\n createdAt: {\n gte: new Date(dateRange.start),\n lte: new Date(dateRange.end)\n }\n }\n ]\n };\n\n const $notes = await models.note.findMany({\n orderBy: { createdAt: 'asc' },\n where\n });\n\n return $notes;\n },\n tagNotes: async (_, {\n searchFilter,\n pagination\n }: {\n searchFilter: SearchFilter;\n pagination: Pagination;\n }) => {\n const where: Prisma.NoteWhereInput = { tags: { some: { id: Number(searchFilter.query) } } };\n\n const $notes = models.note.findMany({\n orderBy: { updatedAt: 'desc' },\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset)\n });\n return {\n totalCount: models.note.count({ where }),\n notes: $notes\n };\n },\n pinnedNotes: async () => models.note.findMany({\n orderBy: [\n { order: 'asc' },\n { updatedAt: 'desc' }\n ],\n where: { pinned: true }\n }),\n imageNotes: async (_, { src }) => models.note.findMany({\n orderBy: { updatedAt: 'desc' },\n where: { content: { contains: src } }\n }),\n backReferences: async (_, { id }: Note) => {\n return models.note.findMany({\n orderBy: [\n { pinned: 'desc' },\n { updatedAt: 'desc' }\n ],\n where: { content: { contains: `reference\",\"props\":{\"id\":\"${id}\"` } }\n });\n },\n note: async (_, { id }: Note) => {\n const $note = await models.note.findUnique({ where: { id: Number(id) } });\n if (!$note) {\n throw 'NOT FOUND';\n }\n if ($note.content) {\n const blocks = extractBlocksByType<{\n id: string;\n title: string;\n }>('reference', JSON.parse($note.content));\n if (blocks.length > 0) {\n const referenceIds = blocks.map(block => Number(block.props.id));\n const $references = await models.note.findMany({ where: { id: { in: referenceIds } } });\n const newContent = $references.reduce<string>((acc: string, $reference: Note) => {\n const reference = blocks.find(block => Number(block.props.id) === $reference.id);\n if (reference && reference.props.title !== $reference.title) {\n return acc.replace(\n `reference\",\"props\":{\"id\":\"${reference.props.id}\",\"title\":\"${reference.props.title}\"`,\n `reference\",\"props\":{\"id\":\"${$reference.id}\",\"title\":\"${$reference.title}\"`\n );\n }\n return acc;\n }, $note.content);\n if (newContent !== $note.content) {\n try {\n JSON.parse(newContent);\n return await models.note.update({\n where: { id: $note.id },\n data: { content: newContent }\n });\n } catch (e) {\n console.error(e);\n }\n }\n }\n }\n return $note;\n },\n noteGraph: async () => {\n const $notes = await models.note.findMany({\n select: {\n id: true,\n title: true,\n content: true\n }\n });\n\n const nodes: Array<{ id: string; title: string; connections: number }> = [];\n const links: Array<{ source: string; target: string }> = [];\n const connectionCount: Record<string, number> = {};\n const linkSet = new Set<string>();\n\n // Extract all references from each note\n for (const $note of $notes) {\n if ($note.content) {\n try {\n const blocks = extractBlocksByType<{ id: string }>('reference', JSON.parse($note.content));\n for (const block of blocks) {\n const targetId = block.props.id;\n // Avoid self-references and duplicate links\n if (targetId && String($note.id) !== targetId) {\n const linkKey = `${$note.id}-${targetId}`;\n const reverseLinkKey = `${targetId}-${$note.id}`;\n if (!linkSet.has(linkKey) && !linkSet.has(reverseLinkKey)) {\n linkSet.add(linkKey);\n links.push({\n source: String($note.id),\n target: targetId\n });\n // Count connections for both nodes\n connectionCount[String($note.id)] = (connectionCount[String($note.id)] || 0) + 1;\n connectionCount[targetId] = (connectionCount[targetId] || 0) + 1;\n }\n }\n }\n } catch {\n // Skip notes with invalid JSON content\n }\n }\n }\n\n // Build nodes array with connection counts\n for (const $note of $notes) {\n nodes.push({\n id: String($note.id),\n title: $note.title || 'Untitled',\n connections: connectionCount[String($note.id)] || 0\n });\n }\n\n return {\n nodes,\n links\n };\n }\n },\n Mutation: {\n createNote: async (_, { note }: { note: NoteInput }) => {\n const PLACEHOLDER_PREFIX = '{%';\n const PLACEHOLDER_SUFFIX = '%}';\n\n const replacePlaceholder = async (content: string) => {\n const placeholders = content.matchAll(new RegExp(`${PLACEHOLDER_PREFIX}([^}]+)${PLACEHOLDER_SUFFIX}`, 'g'));\n const $placeholders = await models.placeholder.findMany({\n select: {\n template: true,\n replacement: true\n },\n where: { template: { in: Array.from(new Set(Array.from(placeholders, p => p[1]))) } }\n });\n\n for (const $placeholder of $placeholders) {\n content = content.replace(new RegExp(`${PLACEHOLDER_PREFIX}${$placeholder.template}${PLACEHOLDER_SUFFIX}`, 'g'), $placeholder.replacement);\n }\n return content;\n };\n\n const replacedTitle = await replacePlaceholder(note.title);\n const replacedContent = await replacePlaceholder(note.content);\n\n const $note = await models.note.create({\n data: {\n title: replacedTitle,\n content: replacedContent,\n ...(note.layout && { layout: note.layout })\n }\n });\n if (note.content) {\n const blocks = extractBlocksByType<{ id: string }>(\n 'tag',\n JSON.parse(note.content)\n );\n\n return await models.note.update({\n where: { id: $note.id },\n data: { tags: { set: blocks.map(block => ({ id: Number(block.props.id) })) } }\n });\n }\n\n return $note;\n },\n updateNote: async (_, { id, note }: { id: number; note: NoteInput }) => {\n let blocks: BlockNote<{ id: string }>[] = [];\n\n if (note.content) {\n blocks = extractBlocksByType<{ id: string }>(\n 'tag',\n JSON.parse(note.content)\n );\n }\n\n const $note = await models.note.update({\n where: { id: Number(id) },\n data: {\n ...note,\n ...(note.content ? { tags: { set: blocks.map(block => ({ id: Number(block.props.id) })) } } : {})\n }\n });\n return $note;\n },\n deleteNote: async (_, { id }: Note) => {\n await models.tag.deleteMany({ where: { notes: { none: {} } } });\n await models.note.delete({ where: { id: Number(id) } });\n return true;\n },\n pinNote: (_, { id, pinned }: Note) => models.note.update({\n where: { id: Number(id) },\n data: { pinned: Boolean(pinned) }\n }),\n reorderNotes: async (_, { notes }: { notes: Array<{ id: string; order: number }> }) => {\n const updatePromises = notes.map(({ id, order }) =>\n models.note.update({\n where: { id: Number(id) },\n data: { order }\n })\n );\n return await Promise.all(updatePromises);\n }\n },\n Note: {\n tags: async (note: Note) => await models.tag.findMany({ where: { notes: { some: { id: note.id } } } }),\n contentAsMarkdown: async (note: Note) => {\n const { blocksToMarkdown } = await import('~/modules/blocknote.js');\n return blocksToMarkdown(note.content);\n }\n }\n};\n"],"mappings":"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","names":[]}