ocean-brain 0.12.0 → 0.12.2
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.
- package/README.md +1 -1
- package/package.json +4 -2
- package/server/client/dist/assets/{ArrowRight.es-DZTjsBaI.js → ArrowRight.es-CD1IMhU2.js} +1 -1
- package/server/client/dist/assets/{AuxiliaryPanelHeader-Bp3iRjm6.js → AuxiliaryPanelHeader-zoJGsYWR.js} +1 -1
- package/server/client/dist/assets/Calendar-6otw_EJn.js +25 -0
- package/server/client/dist/assets/{Callout-Cye6_6BM.js → Callout-C1QiCWCa.js} +1 -1
- package/server/client/dist/assets/{CheckCircle.es-BTloiuti.js → CheckCircle.es-C7fkzE3t.js} +1 -1
- package/server/client/dist/assets/{Copy.es-CkLUgwY-.js → Copy.es-D6rl6b78.js} +1 -1
- package/server/client/dist/assets/{File.es-c83QExqr.js → File.es-CcjtzE38.js} +1 -1
- package/server/client/dist/assets/{FlowArrow.es-DWiIXWQG.js → FlowArrow.es-CAIThqWk.js} +1 -1
- package/server/client/dist/assets/{Graph-jbPLcne9.js → Graph-BHsmPDPh.js} +1 -1
- package/server/client/dist/assets/{Image.es-vY-nTyOe.js → Image.es-BDpo5R66.js} +1 -1
- package/server/client/dist/assets/Note-Dq2Szaxd.js +19 -0
- package/server/client/dist/assets/{NotePropertiesPanel-uO-JKy19.js → NotePropertiesPanel-Cu3RgDic.js} +2 -2
- package/server/client/dist/assets/{Plus.es-CaRgmXc_.js → Plus.es-P9Fjwtud.js} +1 -1
- package/server/client/dist/assets/{Reminders-BAgZEUwV.js → Reminders-DKm0GFI2.js} +1 -1
- package/server/client/dist/assets/{Search-BxozUWkC.js → Search-DVROxY_B.js} +1 -1
- package/server/client/dist/assets/{SurfaceCard-BAlcul6z.js → SurfaceCard-D_OU_Oy6.js} +1 -1
- package/server/client/dist/assets/{Tag-BhCf_mil.js → Tag-wMHTRwlF.js} +1 -1
- package/server/client/dist/assets/{TagNotes-BIzhXqwp.js → TagNotes-BRza6i14.js} +1 -1
- package/server/client/dist/assets/{Trash.es-prxIxo9c.js → Trash.es-BeR1sZMe.js} +1 -1
- package/server/client/dist/assets/{ViewChip-Cq_YzRvB.js → ViewChip-D-Ax5PdL.js} +1 -1
- package/server/client/dist/assets/{Views-C26uWznP.js → Views-CL7rC05G.js} +1 -1
- package/server/client/dist/assets/{abnfDiagram-VRR7QNED-2cuaaDg0.js → abnfDiagram-N423BO3Z-D44O4T7q.js} +1 -1
- package/server/client/dist/assets/{app-DbQdHfMb.js → app-CyQtGTtn.js} +3 -3
- package/server/client/dist/assets/app-DGFNtdpS.css +1 -0
- package/server/client/dist/assets/{arc-Cr-oYJoQ.js → arc-Cil9fXuW.js} +1 -1
- package/server/client/dist/assets/architectureDiagram-T3A2C74G-Cjq6ayF2.js +36 -0
- package/server/client/dist/assets/{blockDiagram-677ZJIJ3-evR8rlpQ.js → blockDiagram-VBNYF7ZC-B2Xm5N0i.js} +1 -1
- package/server/client/dist/assets/{c4Diagram-LMCZKHZV-zCjuWUmC.js → c4Diagram-5PPSVZJV-Dp0y-lCR.js} +1 -1
- package/server/client/dist/assets/channel-DZFalh-h.js +1 -0
- package/server/client/dist/assets/{chunk-32BRIVSS-102-EyWU.js → chunk-2GRJ4B5K-CWaaNkFx.js} +1 -1
- package/server/client/dist/assets/{chunk-2Q5K7J3B-P0v1gRui.js → chunk-2Q5K7J3B-Ces-xz2S.js} +1 -1
- package/server/client/dist/assets/{chunk-EX3LRPZG-k5hlNinR.js → chunk-5RXB4S5H-B-4Chlfc.js} +1 -1
- package/server/client/dist/assets/{chunk-5VM5RSS4-uqI_1K1p.js → chunk-5VM5RSS4-C8_HVwuz.js} +1 -1
- package/server/client/dist/assets/{chunk-MOJQB5TN-B-LmIwhJ.js → chunk-6Q2QTUOP-xZ8ofRqk.js} +1 -1
- package/server/client/dist/assets/{chunk-V7JOEXUC-CmSzAkUx.js → chunk-GF5L2VYU-Bpa43a7s.js} +1 -1
- package/server/client/dist/assets/{chunk-JWPE2WC7-PLvgEy_B.js → chunk-JWPE2WC7-DsyTXbuq.js} +1 -1
- package/server/client/dist/assets/{chunk-VR4S4FIN-IiOfWaBG.js → chunk-KBJHAD2P-BDhjm9-8.js} +1 -1
- package/server/client/dist/assets/{chunk-RYQCIY6F-CaNSMki0.js → chunk-RYQCIY6F-Cn-jdp6I.js} +1 -1
- package/server/client/dist/assets/{chunk-XXDRQBXY-DRXrI6SM.js → chunk-XXDRQBXY-BKsc_0wh.js} +1 -1
- package/server/client/dist/assets/classDiagram-JCYQIIEL-CkEhFvVV.js +1 -0
- package/server/client/dist/assets/classDiagram-v2-OCEON4UE-CkEhFvVV.js +1 -0
- package/server/client/dist/assets/{cose-bilkent-JH36ORCC-COcEaZRS.js → cose-bilkent-JH36ORCC-jmn3Q4zj.js} +1 -1
- package/server/client/dist/assets/{cynefinDiagram-TSTJHNR4-CSHqcg9K.js → cynefinDiagram-MW4NZA55-BpLstuBJ.js} +1 -1
- package/server/client/dist/assets/{dagre-VKFMJZFB-XAWCPOS0.js → dagre-VZM6K2ZE-B5ft5Yzm.js} +1 -1
- package/server/client/dist/assets/{diagram-OA4YK3LP-CXTlHB5A.js → diagram-7IWD3JNH-B_W9IsWZ.js} +1 -1
- package/server/client/dist/assets/{diagram-FQU43EPY-scBCDUnE.js → diagram-B4RE2ZJO-32chS3GX.js} +1 -1
- package/server/client/dist/assets/{diagram-NH7WQ7WH-DcWalY4j.js → diagram-LBJQPF4R-Bqupdb3-.js} +1 -1
- package/server/client/dist/assets/{diagram-G47NLZAW-nPKP5kd8.js → diagram-Q27KOJAE-BD8jKBsv.js} +1 -1
- package/server/client/dist/assets/diagram-UB23O5K3-C40jAU8D.js +41 -0
- package/server/client/dist/assets/{ebnfDiagram-CCIWWBDH-nHt3vRNt.js → ebnfDiagram-BXEA7PRR-BQfW9mFA.js} +1 -1
- package/server/client/dist/assets/{erDiagram-Q63AITRT-K6stUUV2.js → erDiagram-JOGREHBK-ILZnLzz2.js} +1 -1
- package/server/client/dist/assets/{flowDiagram-23GEKE2U-DDWtKrEp.js → flowDiagram-UKHOOZJN-CDmwr2dI.js} +4 -4
- package/server/client/dist/assets/{ganttDiagram-NO4QXBWP-Daqh7b4I.js → ganttDiagram-PKOTCBZU-DBcrUc49.js} +1 -1
- package/server/client/dist/assets/{gitGraphDiagram-IHSO6WYX-D73CLkcG.js → gitGraphDiagram-DS77QQ5N-_xO6__FK.js} +1 -1
- package/server/client/dist/assets/{image.api-Bbwmcw0T.js → image.api-CtfyPwkV.js} +1 -1
- package/server/client/dist/assets/{index-8bsOoxxg.js → index-BEfKfbvr.js} +1 -1
- package/server/client/dist/assets/{infoDiagram-FWYZ7A6U-Bc1YI5Iu.js → infoDiagram-6WML65LV-CuIIcu-L.js} +1 -1
- package/server/client/dist/assets/{ishikawaDiagram-FXEZZL3T-BJDXbmaY.js → ishikawaDiagram-WSZJBQD7-BVtRGTOj.js} +1 -1
- package/server/client/dist/assets/{journeyDiagram-5HDEW3XC-DlyJx4xT.js → journeyDiagram-NVQOT4AX-D5-Nzb2N.js} +1 -1
- package/server/client/dist/assets/{kanban-definition-HUTT4EX6-AmTeXesc.js → kanban-definition-27J2QSJJ-DmOhgC8H.js} +1 -1
- package/server/client/dist/assets/{manage-image-detail-CPpeRZD4.js → manage-image-detail-BNYOCSmu.js} +1 -1
- package/server/client/dist/assets/{manage-image-DCBgglLx.js → manage-image-m-7v_Z1W.js} +1 -1
- package/server/client/dist/assets/{mcp-Y2p95Lm9.js → mcp-B-aGeAQD.js} +1 -1
- package/server/client/dist/assets/{mcp-admin-adapter-z9OaMVrl.js → mcp-admin-adapter-Cw6w5mfg.js} +1 -1
- package/server/client/dist/assets/mermaid.core-C2tL9tq7.js +308 -0
- package/server/client/dist/assets/{mindmap-definition-LN4V7U3C-C_6tKVmY.js → mindmap-definition-FAOFIHXS-DuvsPqrh.js} +1 -1
- package/server/client/dist/assets/{note-ui-Cv6quEYh.js → note-ui-CYsZc3DI.js} +1 -1
- package/server/client/dist/assets/{pegDiagram-2B236MQR-CGKCNdrV.js → pegDiagram-VL7TDLO6-D64crEZV.js} +1 -1
- package/server/client/dist/assets/{pieDiagram-ENE6RG2P-C3cMh7d5.js → pieDiagram-7S7Q4E2Y--kl7vopC.js} +1 -1
- package/server/client/dist/assets/{placeholder-CHRQt_T8.js → placeholder-C5fNzKrL.js} +1 -1
- package/server/client/dist/assets/{properties-CwxDtivz.js → properties-B93_V2uD.js} +1 -1
- package/server/client/dist/assets/{quadrantDiagram-ABIIQ3AL-CVVzGxBd.js → quadrantDiagram-CIZ2JOQS-DuvJ4M2y.js} +1 -1
- package/server/client/dist/assets/{railroadDiagram-RFXS5EU6-wa-4aJR9.js → railroadDiagram-AXF67PYL-BMKmCOY7.js} +1 -1
- package/server/client/dist/assets/{requirementDiagram-TGXJPOKE-DyuC9W7q.js → requirementDiagram-LRYGKXZP-DY1eJcy0.js} +1 -1
- package/server/client/dist/assets/route-preload.js +2 -2
- package/server/client/dist/assets/{sankeyDiagram-HTMAVEWB-B70y-MQg.js → sankeyDiagram-W5VNT64P-C3Ka4GKM.js} +1 -1
- package/server/client/dist/assets/{search-DCLnUWYd.js → search-BmXuuK26.js} +1 -1
- package/server/client/dist/assets/{search-admin-adapter-BLMYNm9w.js → search-admin-adapter-Dj0KKKrJ.js} +1 -1
- package/server/client/dist/assets/{sequenceDiagram-DBY2YBRQ-mGkh3IEy.js → sequenceDiagram-SI44F4Z6-Bhpwtk2s.js} +1 -1
- package/server/client/dist/assets/{sizeCapture-X5ZJPWSS-BhnCNP5z.js → sizeCapture-X5ZJPWSS-BFta71TW.js} +1 -1
- package/server/client/dist/assets/{stateDiagram-2N3HPSRC-BqSKSfKi.js → stateDiagram-OKZ733FA-D6GCn1io.js} +1 -1
- package/server/client/dist/assets/{stateDiagram-v2-6OUMAXLB-Wl7lGTf3.js → stateDiagram-v2-UEYNNEHI-g4yinGDn.js} +1 -1
- package/server/client/dist/assets/{swimlanes-5IMT3BWC-CZ7ckdmY.js → swimlanes-SLNWSIFB-DLFvOjUl.js} +2 -2
- package/server/client/dist/assets/swimlanesDiagram-ULZ7WXOC-Ci4mcvmo.js +8 -0
- package/server/client/dist/assets/{tag.api-bU52U0tT.js → tag.api-BJ6eaHui.js} +1 -1
- package/server/client/dist/assets/{time-DZKkPFUi.js → time-DI902Sxa.js} +1 -1
- package/server/client/dist/assets/{timeline-definition-FHXFAJF6-C-t9-x4M.js → timeline-definition-Z64GVDOM-DTSIekSM.js} +1 -1
- package/server/client/dist/assets/{trash-BNeUFJnC.js → trash-GulvRh9f.js} +1 -1
- package/server/client/dist/assets/{useNoteMutate-VJYw0Vt_.js → useNoteMutate-xEIypxi5.js} +1 -1
- package/server/client/dist/assets/{useReminderMutate-DaO0QssD.js → useReminderMutate-kTBRSjYc.js} +1 -1
- package/server/client/dist/assets/{vennDiagram-L72KCM5P-CP014Nl5.js → vennDiagram-T6HMQDX7-CMNqSI2X.js} +1 -1
- package/server/client/dist/assets/{wardleyDiagram-EHGQE667-B7Ghd-94.js → wardleyDiagram-T6FBY63Y-DV-JOYqB.js} +1 -1
- package/server/client/dist/assets/{xychartDiagram-FW5EYKEG-C4YGS0YJ.js → xychartDiagram-ELKLHX3M-BUIniF4m.js} +4 -4
- package/server/client/dist/index.html +4 -4
- package/server/dist/app.js +5 -5
- package/server/dist/features/note/graphql/note.query.resolver.js +18 -16
- package/server/dist/features/placeholder/graphql/placeholder.mutation.resolver.js +2 -3
- package/server/dist/features/placeholder/graphql/placeholder.query.resolver.js +4 -3
- package/server/dist/features/search/sqlite-vector-index.js +71 -138
- package/server/dist/features/view/graphql/view.query.resolver.js +15 -7
- package/server/dist/main.js +1 -35
- package/server/dist/modules/blocknote.js +33 -17
- package/server/dist/routes/api.js +6 -1
- package/server/dist/routes/client.js +15 -4
- package/server/dist/server.js +40 -0
- package/server/client/dist/assets/Calendar-BLiViCGr.js +0 -25
- package/server/client/dist/assets/Note-BTQLB80Y.js +0 -25
- package/server/client/dist/assets/app-CEkicO08.css +0 -1
- package/server/client/dist/assets/architectureDiagram-ZJ3FMSHR-HF8-bEM0.js +0 -36
- package/server/client/dist/assets/channel-Cq5ZBtfo.js +0 -1
- package/server/client/dist/assets/classDiagram-OUVF2IWQ-BqUaa8a6.js +0 -1
- package/server/client/dist/assets/classDiagram-v2-EOCWNBFH-BqUaa8a6.js +0 -1
- package/server/client/dist/assets/diagram-WEI45ONY-D1uvaJub.js +0 -41
- package/server/client/dist/assets/mermaid.core-B528P54n.js +0 -308
- package/server/client/dist/assets/swimlanesDiagram-G3AALYLV-BZL3DQ-c.js +0 -8
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { mkdir } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { DatabaseSync } from "node:sqlite";
|
|
4
|
+
import { setImmediate as yieldToEventLoop } from "node:timers/promises";
|
|
3
5
|
import { getLoadablePath } from "sqlite-vec";
|
|
4
|
-
import sqlite3 from "sqlite3";
|
|
5
6
|
const SEMANTIC_INDEX_SCHEMA_VERSION = 2;
|
|
6
7
|
const SEARCH_DATABASE_SCHEMA_VERSION = 1;
|
|
7
8
|
const SEARCH_DATABASE_SCHEMA_SQL = `
|
|
@@ -50,69 +51,27 @@ const openDatabase = async (filePath) => {
|
|
|
50
51
|
if (filePath !== ":memory:") {
|
|
51
52
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
52
53
|
}
|
|
53
|
-
const database =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
await new Promise((resolve, reject) => {
|
|
63
|
-
database.loadExtension(getLoadablePath(), (error) => {
|
|
64
|
-
if (error) {
|
|
65
|
-
reject(error);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
resolve();
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
return database;
|
|
54
|
+
const database = new DatabaseSync(filePath, { allowExtension: true });
|
|
55
|
+
try {
|
|
56
|
+
database.loadExtension(getLoadablePath());
|
|
57
|
+
database.enableLoadExtension(false);
|
|
58
|
+
return database;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
database.close();
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
72
63
|
};
|
|
73
64
|
const run = (database, sql, parameters = []) => {
|
|
74
|
-
return
|
|
75
|
-
database.run(sql, parameters, function onRun(error) {
|
|
76
|
-
if (error) {
|
|
77
|
-
reject(error);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
resolve(this);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
65
|
+
return database.prepare(sql).run(...parameters);
|
|
83
66
|
};
|
|
84
67
|
const get = (database, sql, parameters = []) => {
|
|
85
|
-
return
|
|
86
|
-
database.get(sql, parameters, (error, row) => {
|
|
87
|
-
if (error) {
|
|
88
|
-
reject(error);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
resolve(row);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
68
|
+
return database.prepare(sql).get(...parameters);
|
|
94
69
|
};
|
|
95
70
|
const all = (database, sql, parameters = []) => {
|
|
96
|
-
return
|
|
97
|
-
database.all(sql, parameters, (error, rows) => {
|
|
98
|
-
if (error) {
|
|
99
|
-
reject(error);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
resolve(rows);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
71
|
+
return database.prepare(sql).all(...parameters);
|
|
105
72
|
};
|
|
106
73
|
const exec = (database, sql) => {
|
|
107
|
-
|
|
108
|
-
database.exec(sql, (error) => {
|
|
109
|
-
if (error) {
|
|
110
|
-
reject(error);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
resolve();
|
|
114
|
-
});
|
|
115
|
-
});
|
|
74
|
+
database.exec(sql);
|
|
116
75
|
};
|
|
117
76
|
const initializeSearchDatabase = async (database) => {
|
|
118
77
|
await exec(
|
|
@@ -134,19 +93,35 @@ const initializeSearchDatabase = async (database) => {
|
|
|
134
93
|
await exec(database, `PRAGMA user_version = ${SEARCH_DATABASE_SCHEMA_VERSION};`);
|
|
135
94
|
};
|
|
136
95
|
const close = (database) => {
|
|
137
|
-
|
|
138
|
-
database.close((error) => {
|
|
139
|
-
if (error) {
|
|
140
|
-
reject(error);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
resolve();
|
|
144
|
-
});
|
|
145
|
-
});
|
|
96
|
+
database.close();
|
|
146
97
|
};
|
|
147
98
|
const serializeEmbedding = (embedding) => {
|
|
148
99
|
return Buffer.from(Float32Array.from(embedding).buffer);
|
|
149
100
|
};
|
|
101
|
+
const INSERT_YIELD_INTERVAL = 250;
|
|
102
|
+
const insertChunks = async (database, chunks) => {
|
|
103
|
+
const statement = database.prepare(`
|
|
104
|
+
INSERT INTO search_chunks (
|
|
105
|
+
note_id,
|
|
106
|
+
chunk_index,
|
|
107
|
+
source_hash,
|
|
108
|
+
text,
|
|
109
|
+
embedding
|
|
110
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
111
|
+
`);
|
|
112
|
+
for (const [index, chunk] of chunks.entries()) {
|
|
113
|
+
statement.run(
|
|
114
|
+
chunk.noteId,
|
|
115
|
+
chunk.chunkIndex,
|
|
116
|
+
chunk.sourceHash,
|
|
117
|
+
chunk.text,
|
|
118
|
+
serializeEmbedding(chunk.embedding)
|
|
119
|
+
);
|
|
120
|
+
if ((index + 1) % INSERT_YIELD_INTERVAL === 0 && index + 1 < chunks.length) {
|
|
121
|
+
await yieldToEventLoop();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
150
125
|
const isSemanticIndexProfile = (value) => {
|
|
151
126
|
if (!value || typeof value !== "object") {
|
|
152
127
|
return false;
|
|
@@ -217,27 +192,7 @@ class SqliteSemanticVectorIndex {
|
|
|
217
192
|
try {
|
|
218
193
|
await run(database, "DELETE FROM search_chunks");
|
|
219
194
|
await run(database, "DELETE FROM search_index_state");
|
|
220
|
-
|
|
221
|
-
await run(
|
|
222
|
-
database,
|
|
223
|
-
`
|
|
224
|
-
INSERT INTO search_chunks (
|
|
225
|
-
note_id,
|
|
226
|
-
chunk_index,
|
|
227
|
-
source_hash,
|
|
228
|
-
text,
|
|
229
|
-
embedding
|
|
230
|
-
) VALUES (?, ?, ?, ?, ?)
|
|
231
|
-
`,
|
|
232
|
-
[
|
|
233
|
-
chunk.noteId,
|
|
234
|
-
chunk.chunkIndex,
|
|
235
|
-
chunk.sourceHash,
|
|
236
|
-
chunk.text,
|
|
237
|
-
serializeEmbedding(chunk.embedding)
|
|
238
|
-
]
|
|
239
|
-
);
|
|
240
|
-
}
|
|
195
|
+
await insertChunks(database, chunks);
|
|
241
196
|
await run(
|
|
242
197
|
database,
|
|
243
198
|
`
|
|
@@ -472,37 +427,35 @@ class SqliteSemanticVectorIndex {
|
|
|
472
427
|
async getNoteSyncQueueStatus() {
|
|
473
428
|
return this.runExclusive(async () => {
|
|
474
429
|
const database = await this.getDatabase();
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
)
|
|
505
|
-
]);
|
|
430
|
+
const queue = get(
|
|
431
|
+
database,
|
|
432
|
+
`
|
|
433
|
+
SELECT
|
|
434
|
+
COUNT(*) AS pendingNoteCount,
|
|
435
|
+
MIN(first_queued_at) AS oldestQueuedAt
|
|
436
|
+
FROM search_note_sync_queue
|
|
437
|
+
`
|
|
438
|
+
);
|
|
439
|
+
const state = get(
|
|
440
|
+
database,
|
|
441
|
+
`
|
|
442
|
+
SELECT
|
|
443
|
+
last_synced_at AS lastSyncedAt,
|
|
444
|
+
last_reconciled_at AS lastReconciledAt
|
|
445
|
+
FROM search_note_sync_state
|
|
446
|
+
WHERE id = 1
|
|
447
|
+
`
|
|
448
|
+
);
|
|
449
|
+
const latestError = get(
|
|
450
|
+
database,
|
|
451
|
+
`
|
|
452
|
+
SELECT last_error AS error
|
|
453
|
+
FROM search_note_sync_queue
|
|
454
|
+
WHERE last_error IS NOT NULL
|
|
455
|
+
ORDER BY next_attempt_at DESC, note_id ASC
|
|
456
|
+
LIMIT 1
|
|
457
|
+
`
|
|
458
|
+
);
|
|
506
459
|
return {
|
|
507
460
|
pendingNoteCount: queue?.pendingNoteCount ?? 0,
|
|
508
461
|
oldestQueuedAt: queue?.oldestQueuedAt === null || queue?.oldestQueuedAt === void 0 ? null : new Date(queue.oldestQueuedAt).toISOString(),
|
|
@@ -526,27 +479,7 @@ class SqliteSemanticVectorIndex {
|
|
|
526
479
|
await exec(database, "BEGIN IMMEDIATE;");
|
|
527
480
|
try {
|
|
528
481
|
await run(database, "DELETE FROM search_chunks WHERE note_id = ?", [noteId]);
|
|
529
|
-
|
|
530
|
-
await run(
|
|
531
|
-
database,
|
|
532
|
-
`
|
|
533
|
-
INSERT INTO search_chunks (
|
|
534
|
-
note_id,
|
|
535
|
-
chunk_index,
|
|
536
|
-
source_hash,
|
|
537
|
-
text,
|
|
538
|
-
embedding
|
|
539
|
-
) VALUES (?, ?, ?, ?, ?)
|
|
540
|
-
`,
|
|
541
|
-
[
|
|
542
|
-
chunk.noteId,
|
|
543
|
-
chunk.chunkIndex,
|
|
544
|
-
chunk.sourceHash,
|
|
545
|
-
chunk.text,
|
|
546
|
-
serializeEmbedding(chunk.embedding)
|
|
547
|
-
]
|
|
548
|
-
);
|
|
549
|
-
}
|
|
482
|
+
await insertChunks(database, chunks);
|
|
550
483
|
await this.refreshIndexCounts(database);
|
|
551
484
|
await exec(database, "COMMIT;");
|
|
552
485
|
} catch (error) {
|
|
@@ -7,12 +7,18 @@ import {
|
|
|
7
7
|
getViewSectionNotes,
|
|
8
8
|
getViewWorkspace
|
|
9
9
|
} from "../../../features/view/services/workspace.js";
|
|
10
|
-
const
|
|
10
|
+
const createViewQueryResolvers = (deps = {
|
|
11
|
+
getNotesByProperties,
|
|
12
|
+
getViewSectionBoardColumn,
|
|
13
|
+
getViewSectionById,
|
|
14
|
+
getViewSectionNotes,
|
|
15
|
+
getViewWorkspace
|
|
16
|
+
}) => ({
|
|
11
17
|
viewWorkspace: async () => {
|
|
12
|
-
return getViewWorkspace();
|
|
18
|
+
return deps.getViewWorkspace();
|
|
13
19
|
},
|
|
14
20
|
viewSection: async (_, { id }) => {
|
|
15
|
-
return getViewSectionById(id);
|
|
21
|
+
return deps.getViewSectionById(id);
|
|
16
22
|
},
|
|
17
23
|
viewSectionNotes: async (_, {
|
|
18
24
|
id,
|
|
@@ -23,7 +29,7 @@ const viewQueryResolvers = {
|
|
|
23
29
|
sortBy,
|
|
24
30
|
sortOrder
|
|
25
31
|
}) => {
|
|
26
|
-
const sectionNotes = await getViewSectionNotes(
|
|
32
|
+
const sectionNotes = await deps.getViewSectionNotes(
|
|
27
33
|
id,
|
|
28
34
|
{
|
|
29
35
|
limit: Number(pagination.limit),
|
|
@@ -45,7 +51,7 @@ const viewQueryResolvers = {
|
|
|
45
51
|
}
|
|
46
52
|
}) => {
|
|
47
53
|
try {
|
|
48
|
-
const columnNotes = await getViewSectionBoardColumn(id, optionValue, {
|
|
54
|
+
const columnNotes = await deps.getViewSectionBoardColumn(id, optionValue, {
|
|
49
55
|
limit: Number(pagination.limit),
|
|
50
56
|
offset: Number(pagination.offset)
|
|
51
57
|
});
|
|
@@ -72,7 +78,7 @@ const viewQueryResolvers = {
|
|
|
72
78
|
}
|
|
73
79
|
}) => {
|
|
74
80
|
try {
|
|
75
|
-
return await getNotesByProperties(input, {
|
|
81
|
+
return await deps.getNotesByProperties(input, {
|
|
76
82
|
limit: Number(pagination.limit),
|
|
77
83
|
offset: Number(pagination.offset)
|
|
78
84
|
});
|
|
@@ -87,7 +93,9 @@ const viewQueryResolvers = {
|
|
|
87
93
|
throw error;
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
|
-
};
|
|
96
|
+
});
|
|
97
|
+
const viewQueryResolvers = createViewQueryResolvers();
|
|
91
98
|
export {
|
|
99
|
+
createViewQueryResolvers,
|
|
92
100
|
viewQueryResolvers
|
|
93
101
|
};
|
package/server/dist/main.js
CHANGED
|
@@ -1,38 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ensureNoteReferenceIndex } from "./features/note/services/note-reference-index.js";
|
|
3
|
-
import { getDefaultSemanticSearchManager } from "./features/search/search-manager.js";
|
|
4
|
-
import { logAuthConfig, resolveAuthConfig } from "./modules/auth-mode.js";
|
|
5
|
-
import { startDataMaintenanceScheduler } from "./modules/data-maintenance.js";
|
|
6
|
-
const PORT = Number(process.env.PORT || 6683);
|
|
7
|
-
const HOST = process.env.HOST || "0.0.0.0";
|
|
8
|
-
const startServer = async () => {
|
|
9
|
-
const authConfig = resolveAuthConfig(process.env);
|
|
10
|
-
logAuthConfig(authConfig);
|
|
11
|
-
const app = createApp(authConfig);
|
|
12
|
-
getDefaultSemanticSearchManager();
|
|
13
|
-
const rebuiltReferenceCount = await ensureNoteReferenceIndex();
|
|
14
|
-
if (rebuiltReferenceCount > 0) {
|
|
15
|
-
process.stdout.write(`[maintenance] Rebuilt ${rebuiltReferenceCount} note reference rows
|
|
16
|
-
`);
|
|
17
|
-
}
|
|
18
|
-
app.listen(PORT, HOST, () => {
|
|
19
|
-
process.stdout.write(`http server listen on ${HOST}:${PORT} (auth: ${authConfig.mode})
|
|
20
|
-
`);
|
|
21
|
-
startDataMaintenanceScheduler({
|
|
22
|
-
onResults: (results) => {
|
|
23
|
-
for (const result of results) {
|
|
24
|
-
process.stdout.write(`[maintenance] Reconciled ${result.processedCount} rows for ${result.key}
|
|
25
|
-
`);
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
onError: (error) => {
|
|
29
|
-
const message = error instanceof Error ? error.message : "Unknown data maintenance error";
|
|
30
|
-
process.stderr.write(`[maintenance] Background run failed: ${message}
|
|
31
|
-
`);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
};
|
|
1
|
+
import { startServer } from "./server.js";
|
|
36
2
|
startServer().catch((error) => {
|
|
37
3
|
const message = error instanceof Error ? error.message : "Unknown auth configuration error";
|
|
38
4
|
process.stderr.write(`[auth] Startup failed: ${message}
|
|
@@ -62,12 +62,6 @@ function visitBlocks(blocks, visit) {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
function createTagPlaceholder(index) {
|
|
66
|
-
return `${TAG_PLACEHOLDER_PREFIX}${index}${TAG_PLACEHOLDER_SUFFIX}`;
|
|
67
|
-
}
|
|
68
|
-
function createReferencePlaceholder(index) {
|
|
69
|
-
return `${REFERENCE_PLACEHOLDER_PREFIX}${index}${REFERENCE_PLACEHOLDER_SUFFIX}`;
|
|
70
|
-
}
|
|
71
65
|
function isValidNoteIdString(id) {
|
|
72
66
|
if (!/^[1-9]\d*$/.test(id)) {
|
|
73
67
|
return false;
|
|
@@ -143,7 +137,7 @@ function mapBlocks(blocks, mapContent) {
|
|
|
143
137
|
children: block.children?.length ? mapBlocks(block.children, mapContent) : []
|
|
144
138
|
}));
|
|
145
139
|
}
|
|
146
|
-
function preprocessCustomInlineContent(blocks, placeholderToTag,
|
|
140
|
+
function preprocessCustomInlineContent(blocks, placeholderToTag, createTagPlaceholder) {
|
|
147
141
|
return mapBlocks(
|
|
148
142
|
blocks,
|
|
149
143
|
(content) => mapBlockContent(content, (inline) => {
|
|
@@ -158,7 +152,7 @@ function preprocessCustomInlineContent(blocks, placeholderToTag, nextPlaceholder
|
|
|
158
152
|
}
|
|
159
153
|
if (inline.type === "tag") {
|
|
160
154
|
const tag = inline.props?.tag || "";
|
|
161
|
-
const placeholder = createTagPlaceholder(
|
|
155
|
+
const placeholder = createTagPlaceholder();
|
|
162
156
|
placeholderToTag.set(placeholder, tag);
|
|
163
157
|
return {
|
|
164
158
|
type: "text",
|
|
@@ -179,9 +173,13 @@ function restoreTagPlaceholdersInMarkdown(markdown, placeholderToTag) {
|
|
|
179
173
|
}
|
|
180
174
|
function preprocessMarkdownExplicitTags(markdown) {
|
|
181
175
|
const placeholderToTag = /* @__PURE__ */ new Map();
|
|
182
|
-
|
|
176
|
+
const createPlaceholder = createProtectedTextPlaceholderFactory(
|
|
177
|
+
markdown,
|
|
178
|
+
TAG_PLACEHOLDER_PREFIX,
|
|
179
|
+
TAG_PLACEHOLDER_SUFFIX
|
|
180
|
+
);
|
|
183
181
|
const preprocessedMarkdown = markdown.replace(/\[(@[^\s[\]]+)\]/g, (_match, tagToken) => {
|
|
184
|
-
const placeholder =
|
|
182
|
+
const placeholder = createPlaceholder();
|
|
185
183
|
placeholderToTag.set(placeholder, tagToken);
|
|
186
184
|
return placeholder;
|
|
187
185
|
});
|
|
@@ -192,6 +190,11 @@ function preprocessMarkdownExplicitTags(markdown) {
|
|
|
192
190
|
}
|
|
193
191
|
function preprocessMarkdownExplicitReferences(markdown) {
|
|
194
192
|
const placeholderToReference = /* @__PURE__ */ new Map();
|
|
193
|
+
const createPlaceholder = createProtectedTextPlaceholderFactory(
|
|
194
|
+
markdown,
|
|
195
|
+
REFERENCE_PLACEHOLDER_PREFIX,
|
|
196
|
+
REFERENCE_PLACEHOLDER_SUFFIX
|
|
197
|
+
);
|
|
195
198
|
let activeFence = null;
|
|
196
199
|
const preprocessedLines = markdown.split(/(?<=\n)/).map((line) => {
|
|
197
200
|
const { body: lineBody, lineEnding } = splitMarkdownLineEnding(line);
|
|
@@ -212,31 +215,39 @@ function preprocessMarkdownExplicitReferences(markdown) {
|
|
|
212
215
|
if (/^(?: {4,}|\t)/.test(lineBody)) {
|
|
213
216
|
return line;
|
|
214
217
|
}
|
|
215
|
-
return `${replaceMarkdownLineExplicitReferences(
|
|
218
|
+
return `${replaceMarkdownLineExplicitReferences(
|
|
219
|
+
lineBody,
|
|
220
|
+
placeholderToReference,
|
|
221
|
+
createPlaceholder
|
|
222
|
+
)}${lineEnding}`;
|
|
216
223
|
});
|
|
217
224
|
return {
|
|
218
225
|
markdown: preprocessedLines.join(""),
|
|
219
226
|
placeholderToReference
|
|
220
227
|
};
|
|
221
228
|
}
|
|
222
|
-
function replaceMarkdownLineExplicitReferences(line, placeholderToReference) {
|
|
229
|
+
function replaceMarkdownLineExplicitReferences(line, placeholderToReference, createPlaceholder) {
|
|
223
230
|
let result = "";
|
|
224
231
|
let cursor = 0;
|
|
225
232
|
while (cursor < line.length) {
|
|
226
233
|
const codeSpan = findNextInlineCodeSpan(line, cursor);
|
|
227
234
|
if (!codeSpan) {
|
|
228
|
-
result += replaceExplicitReferenceTokens(line.slice(cursor), placeholderToReference);
|
|
235
|
+
result += replaceExplicitReferenceTokens(line.slice(cursor), placeholderToReference, createPlaceholder);
|
|
229
236
|
break;
|
|
230
237
|
}
|
|
231
|
-
result += replaceExplicitReferenceTokens(
|
|
238
|
+
result += replaceExplicitReferenceTokens(
|
|
239
|
+
line.slice(cursor, codeSpan.start),
|
|
240
|
+
placeholderToReference,
|
|
241
|
+
createPlaceholder
|
|
242
|
+
);
|
|
232
243
|
result += line.slice(codeSpan.start, codeSpan.end);
|
|
233
244
|
cursor = codeSpan.end;
|
|
234
245
|
}
|
|
235
246
|
return result;
|
|
236
247
|
}
|
|
237
|
-
function replaceExplicitReferenceTokens(text, placeholderToReference) {
|
|
248
|
+
function replaceExplicitReferenceTokens(text, placeholderToReference, createPlaceholder) {
|
|
238
249
|
return text.replace(/\[\[([^\n]+?)\]\]\(note:([^)\s]+)\)/g, (token, title, id) => {
|
|
239
|
-
const placeholder =
|
|
250
|
+
const placeholder = createPlaceholder();
|
|
240
251
|
placeholderToReference.set(placeholder, { id, title, token });
|
|
241
252
|
return placeholder;
|
|
242
253
|
});
|
|
@@ -1030,7 +1041,12 @@ async function blocksToMarkdown(contentJson) {
|
|
|
1030
1041
|
const blocks = parseBlockNoteContent(contentJson);
|
|
1031
1042
|
const supportedBlocks = stripUnsupportedMarkdownBlocks(blocks);
|
|
1032
1043
|
const placeholderToTag = /* @__PURE__ */ new Map();
|
|
1033
|
-
const
|
|
1044
|
+
const createTagPlaceholder = createProtectedTextPlaceholderFactory(
|
|
1045
|
+
contentJson,
|
|
1046
|
+
TAG_PLACEHOLDER_PREFIX,
|
|
1047
|
+
TAG_PLACEHOLDER_SUFFIX
|
|
1048
|
+
);
|
|
1049
|
+
const processed = preprocessCustomInlineContent(supportedBlocks, placeholderToTag, createTagPlaceholder);
|
|
1034
1050
|
const editor = getEditor();
|
|
1035
1051
|
const markdown = await editor.blocksToMarkdownLossy(
|
|
1036
1052
|
processed
|
|
@@ -83,7 +83,12 @@ const createApiRouter = (authConfig, mcpAdminService) => {
|
|
|
83
83
|
requireSession,
|
|
84
84
|
csrfProtection,
|
|
85
85
|
useAsync(createSearchAdminReindexHandler())
|
|
86
|
-
).post("/image", sessionAccessRateLimit, requireSession, csrfProtection, useAsync(createUploadImageHandler())).get("/events", sessionAccessRateLimit, requireSession, csrfProtection, createServerEventsHandler())
|
|
86
|
+
).post("/image", sessionAccessRateLimit, requireSession, csrfProtection, useAsync(createUploadImageHandler())).get("/events", sessionAccessRateLimit, requireSession, csrfProtection, createServerEventsHandler()).use((_req, res) => {
|
|
87
|
+
res.status(404).json({
|
|
88
|
+
code: "API_ROUTE_NOT_FOUND",
|
|
89
|
+
message: "The requested API route was not found."
|
|
90
|
+
}).end();
|
|
91
|
+
});
|
|
87
92
|
};
|
|
88
93
|
export {
|
|
89
94
|
createApiRouter
|
|
@@ -4,6 +4,9 @@ import path from "path";
|
|
|
4
4
|
import { createCsrfProtection, isAuthenticatedRequest } from "../modules/auth-guard.js";
|
|
5
5
|
import { paths } from "../paths.js";
|
|
6
6
|
const IMAGE_ASSET_RATE_LIMIT_MESSAGE = "Too many image asset requests. Please try again later.";
|
|
7
|
+
const isClientDocumentRequest = (req) => {
|
|
8
|
+
return req.method === "GET" && Boolean(req.headers.accept?.includes("text/html")) && path.extname(req.path) === "";
|
|
9
|
+
};
|
|
7
10
|
const shouldBlockClientRoute = (authConfig, requestPath, authenticated) => {
|
|
8
11
|
if (authConfig.mode !== "password" || authenticated) {
|
|
9
12
|
return false;
|
|
@@ -52,7 +55,17 @@ const createClientRouteCsrfTokenMiddleware = (authConfig) => {
|
|
|
52
55
|
csrfProtection(req, res, next);
|
|
53
56
|
};
|
|
54
57
|
};
|
|
55
|
-
const
|
|
58
|
+
const createProductionClientContentRouter = () => Router().use(express.static(paths.clientDist, { extensions: ["html"] })).get(/.*/, (req, res, next) => {
|
|
59
|
+
if (!isClientDocumentRequest(req)) {
|
|
60
|
+
next();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
res.sendFile("index.html", { root: paths.clientDist });
|
|
64
|
+
}).use((_req, res) => {
|
|
65
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
66
|
+
res.status(404).end();
|
|
67
|
+
});
|
|
68
|
+
const createClientRouter = (authConfig, clientContentMiddleware = createProductionClientContentRouter()) => Router().use(
|
|
56
69
|
"/assets/images",
|
|
57
70
|
createImageAssetAuthRateLimit(authConfig),
|
|
58
71
|
createProtectedImageAssetsMiddleware(authConfig),
|
|
@@ -78,9 +91,7 @@ const createClientRouter = (authConfig) => Router().use(
|
|
|
78
91
|
return;
|
|
79
92
|
}
|
|
80
93
|
next();
|
|
81
|
-
}).use(createClientRouteCsrfTokenMiddleware(authConfig)).use(
|
|
82
|
-
res.sendFile("index.html", { root: paths.clientDist });
|
|
83
|
-
});
|
|
94
|
+
}).use(createClientRouteCsrfTokenMiddleware(authConfig)).use(clientContentMiddleware);
|
|
84
95
|
export {
|
|
85
96
|
createClientRouter
|
|
86
97
|
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createServer as createNodeHttpServer } from "node:http";
|
|
2
|
+
import { createApp } from "./app.js";
|
|
3
|
+
import { ensureNoteReferenceIndex } from "./features/note/services/note-reference-index.js";
|
|
4
|
+
import { getDefaultSemanticSearchManager } from "./features/search/search-manager.js";
|
|
5
|
+
import { logAuthConfig, resolveAuthConfig } from "./modules/auth-mode.js";
|
|
6
|
+
import { startDataMaintenanceScheduler } from "./modules/data-maintenance.js";
|
|
7
|
+
const startServer = async (options = {}) => {
|
|
8
|
+
const port = Number(process.env.PORT || 6683);
|
|
9
|
+
const host = process.env.HOST || "0.0.0.0";
|
|
10
|
+
const authConfig = resolveAuthConfig(process.env);
|
|
11
|
+
logAuthConfig(authConfig);
|
|
12
|
+
const httpServer = options.serverFactory ? await options.serverFactory(authConfig) : createNodeHttpServer(createApp(authConfig));
|
|
13
|
+
getDefaultSemanticSearchManager();
|
|
14
|
+
const rebuiltReferenceCount = await ensureNoteReferenceIndex();
|
|
15
|
+
if (rebuiltReferenceCount > 0) {
|
|
16
|
+
process.stdout.write(`[maintenance] Rebuilt ${rebuiltReferenceCount} note reference rows
|
|
17
|
+
`);
|
|
18
|
+
}
|
|
19
|
+
httpServer.listen(port, host, () => {
|
|
20
|
+
process.stdout.write(`http server listen on ${host}:${port} (auth: ${authConfig.mode})
|
|
21
|
+
`);
|
|
22
|
+
startDataMaintenanceScheduler({
|
|
23
|
+
onResults: (results) => {
|
|
24
|
+
for (const result of results) {
|
|
25
|
+
process.stdout.write(`[maintenance] Reconciled ${result.processedCount} rows for ${result.key}
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
onError: (error) => {
|
|
30
|
+
const message = error instanceof Error ? error.message : "Unknown data maintenance error";
|
|
31
|
+
process.stderr.write(`[maintenance] Background run failed: ${message}
|
|
32
|
+
`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
return httpServer;
|
|
37
|
+
};
|
|
38
|
+
export {
|
|
39
|
+
startServer
|
|
40
|
+
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import{r as s,j as e}from"./floating-ui.react-dom-BWTnA00G.js";import{C as ae,T as b,F as re,c as _,m as f,M as H,y as ne,z as Y,B as Z,R as se,a2 as oe,q as P,g as Q,P as le,l as ie,h as ce}from"./time-DZKkPFUi.js";import{N as de,C as me}from"./url-BvjSC8PU.js";import{s as he,a as U}from"./useNoteMutate-VJYw0Vt_.js";import{e as ue}from"./app-DbQdHfMb.js";import{C as ge}from"./Callout-Cye6_6BM.js";import"./preload-helper-BXl3LOEh.js";import"./sortable.esm-DgSW3bAA.js";const pe=new Map([["bold",s.createElement(s.Fragment,null,s.createElement("path",{d:"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Zm112-80a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,132Zm0,40a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,172Z"}))],["duotone",s.createElement(s.Fragment,null,s.createElement("path",{d:"M208,88H152V32Z",opacity:"0.2"}),s.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Zm-32-80a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,136Zm0,32a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,168Z"}))],["fill",s.createElement(s.Fragment,null,s.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,176H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm0-32H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm-8-56V44l44,44Z"}))],["light",s.createElement(s.Fragment,null,s.createElement("path",{d:"M212.24,83.76l-56-56A6,6,0,0,0,152,26H56A14,14,0,0,0,42,40V216a14,14,0,0,0,14,14H200a14,14,0,0,0,14-14V88A6,6,0,0,0,212.24,83.76ZM158,46.48,193.52,82H158ZM200,218H56a2,2,0,0,1-2-2V40a2,2,0,0,1,2-2h90V88a6,6,0,0,0,6,6h50V216A2,2,0,0,1,200,218Zm-34-82a6,6,0,0,1-6,6H96a6,6,0,0,1,0-12h64A6,6,0,0,1,166,136Zm0,32a6,6,0,0,1-6,6H96a6,6,0,0,1,0-12h64A6,6,0,0,1,166,168Z"}))],["regular",s.createElement(s.Fragment,null,s.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Zm-32-80a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,136Zm0,32a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,168Z"}))],["thin",s.createElement(s.Fragment,null,s.createElement("path",{d:"M210.83,85.17l-56-56A4,4,0,0,0,152,28H56A12,12,0,0,0,44,40V216a12,12,0,0,0,12,12H200a12,12,0,0,0,12-12V88A4,4,0,0,0,210.83,85.17ZM156,41.65,198.34,84H156ZM200,220H56a4,4,0,0,1-4-4V40a4,4,0,0,1,4-4h92V88a4,4,0,0,0,4,4h52V216A4,4,0,0,1,200,220Zm-36-84a4,4,0,0,1-4,4H96a4,4,0,0,1,0-8h64A4,4,0,0,1,164,136Zm0,32a4,4,0,0,1-4,4H96a4,4,0,0,1,0-8h64A4,4,0,0,1,164,168Z"}))]]),B=s.forwardRef((a,t)=>s.createElement(ae,{ref:t,...a,weights:pe}));B.displayName="FileTextIcon";const xe=B,ye=({day:a,cellClassName:t,dayNumberClassName:r,isCurrentMonth:i,items:l,overflowCount:c,onOpenOverflow:h})=>e.jsxs("div",{className:`min-h-[196px] rounded-[16px] border p-2.5 ${t}`.trim(),children:[e.jsx("div",{className:"mb-2.5 flex justify-end",children:e.jsx(b,{as:"span",variant:"label",className:`flex h-7 w-7 items-center justify-center rounded-[10px] ${r}`.trim(),children:a})}),i&&l.length>0?e.jsxs("div",{className:"flex flex-col gap-1.5",children:[l,c>0?e.jsxs("button",{type:"button",onClick:h,className:"focus-ring-soft w-full rounded-[10px] border border-dashed border-border-subtle/70 bg-subtle/70 py-1 text-center text-micro font-semibold text-fg-tertiary outline-none transition-colors hover:border-border-secondary/70 hover:bg-hover-subtle hover:text-fg-secondary",children:["+",c," more"]}):null]}):null]}),K=({params:a,toneClassName:t="",header:r,title:i,meta:l,titleClassName:c=""})=>e.jsx(re,{to:de,params:a,className:"focus-ring-soft group block rounded-[8px] outline-none",children:e.jsxs("div",{className:_("flex items-start gap-1.5 rounded-[8px] px-1.5 py-1 transition-colors group-hover:bg-hover-subtle",t),children:[r?e.jsx("span",{className:"mt-[2px] flex h-4 w-4 shrink-0 items-center justify-center text-fg-tertiary",children:r}):e.jsx("span",{"aria-hidden":"true",className:"mt-[6px] h-1.5 w-1.5 shrink-0 rounded-full bg-fg-placeholder"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx(b,{as:"div",variant:"label",weight:"medium",tone:"secondary",className:_("line-clamp-1",c),children:i}),l?e.jsx(b,{as:"div",variant:"micro",weight:"medium",tone:"tertiary",className:"mt-0.5",children:l}):null]})]})}),fe=({note:a,type:t})=>e.jsx(K,{params:{id:a.id},header:e.jsx(xe,{size:12}),title:a.title,meta:f(Number(t==="create"?a.createdAt:a.updatedAt)).format("HH:mm")}),be=({reminder:a})=>e.jsx(K,{params:{id:String(a.note?.id??a.noteId)},header:e.jsx(he,{size:12}),title:a.content||a.note?.title||"No title",titleClassName:a.completed?"line-through":"",meta:f(Number(a.reminderDate)).format("HH:mm")}),k=3,q=(a,t)=>a.map(r=>r.type==="note"?e.jsx(fe,{note:r.item,type:t},`note-${r.item.id}`):e.jsx(be,{reminder:r.item},`reminder-${r.item.id}`)),je=({year:a,month:t,day:r,isCurrentMonth:i,isSunday:l,isToday:c,isPast:h,notes:u,reminders:g,type:M})=>{const[v,N]=s.useState(!1),x=s.useMemo(()=>{const n=u.map(m=>({type:"note",item:m})),d=g.map(m=>({type:"reminder",item:m}));return h?[...n,...d]:[...d,...n]},[h,u,g]),D=x.length>k,R=s.useMemo(()=>q(x.slice(0,k),M),[x,M]),w=s.useMemo(()=>q(x,M),[x,M]),E=s.useCallback(()=>N(!0),[]),A=s.useCallback(()=>N(!1),[]),S=()=>i?c?"border-border-secondary/70 bg-[color:color-mix(in_srgb,var(--surface)_88%,var(--accent-soft-primary)_12%)]":"bg-surface border-border-subtle":"bg-muted/18 border-border-subtle/70",$=()=>c?"bg-cta text-fg-on-filled font-semibold":i?l?"text-fg-weekend font-bold":"text-fg-secondary font-bold":"text-fg-disabled opacity-55";return e.jsxs(e.Fragment,{children:[e.jsx(ye,{day:r,cellClassName:S(),dayNumberClassName:$(),isCurrentMonth:i,items:R,overflowCount:D?x.length-k:0,onOpenOverflow:E}),D&&e.jsxs(H,{isOpen:v,onClose:A,variant:"inspect",children:[e.jsx(H.Header,{title:`${a}/${String(t).padStart(2,"0")}/${String(r).padStart(2,"0")}`,onClose:A}),e.jsxs(H.Body,{children:[e.jsxs(H.Description,{className:"sr-only",children:["View all notes and reminders scheduled for day ",r,"."]}),e.jsx("div",{className:"flex max-h-[60vh] flex-col gap-2 overflow-y-auto",children:w})]})]})]})},Me=s.memo(je),Ne=["January","February","March","April","May","June","July","August","September","October","November","December"],ve=({month:a,year:t,type:r,onPrevMonth:i,onNextMonth:l,onToday:c,onTypeChange:h})=>e.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex flex-wrap items-end gap-x-2.5 gap-y-1",children:[e.jsx(b,{as:"h1",variant:"display",weight:"bold",tracking:"tighter",className:"text-2xl leading-none sm:text-[2.15rem]",children:Ne[a-1]}),e.jsx(b,{as:"span",variant:"subheading",weight:"medium",tone:"secondary",tracking:"tight",className:"pb-0.5",children:t})]}),e.jsx(b,{as:"p",variant:"meta",weight:"medium",tone:"secondary",children:"Track note activity and reminders across the month"})]}),e.jsx("div",{className:"flex lg:justify-end",children:e.jsxs("div",{className:"surface-base inline-flex flex-wrap items-center gap-3 rounded-[16px] px-3.5 py-2.5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ue,{className:"h-4 w-4 shrink-0 text-fg-tertiary"}),e.jsx(b,{id:"calendar-note-date-label",as:"span",variant:"label",weight:"medium",tone:"tertiary",children:"Note date"}),e.jsxs(ne,{value:r,"aria-labelledby":"calendar-note-date-label",onValueChange:g=>h(g),variant:"ghost",size:"sm",children:[e.jsx(Y,{value:"create",children:"Created"}),e.jsx(Y,{value:"update",children:"Updated"})]})]}),e.jsx("div",{className:"h-5 w-px bg-divider"}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(Z,{variant:"ghost",size:"sm",onClick:c,children:"Today"}),e.jsx(Z,{variant:"ghost",size:"icon-sm","aria-label":"Previous month",onClick:i,children:e.jsx(se,{width:18,height:18})}),e.jsx(Z,{variant:"ghost",size:"icon-sm","aria-label":"Next month",onClick:l,children:e.jsx(oe,{width:18,height:18})})]})]})})]}),De=`
|
|
2
|
-
query NotesInDateRange($dateRange: DateRangeInput) {
|
|
3
|
-
notesInDateRange(dateRange: $dateRange) {
|
|
4
|
-
id
|
|
5
|
-
title
|
|
6
|
-
createdAt
|
|
7
|
-
updatedAt
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
`,Ae=`
|
|
11
|
-
query RemindersInDateRange($dateRange: DateRangeInput) {
|
|
12
|
-
remindersInDateRange(dateRange: $dateRange) {
|
|
13
|
-
id
|
|
14
|
-
noteId
|
|
15
|
-
reminderDate
|
|
16
|
-
completed
|
|
17
|
-
priority
|
|
18
|
-
content
|
|
19
|
-
note {
|
|
20
|
-
id
|
|
21
|
-
title
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
`,Ce=async a=>{const t=await Q(De,{dateRange:a});if(t.type==="error")throw t;return t.notesInDateRange},He=async a=>{const t=await Q(Ae,{dateRange:a});if(t.type==="error")throw t;return t.remindersInDateRange},Re=({year:a,month:t})=>{const r=`${a}-${String(t).padStart(2,"0")}-01`,i=t===12?1:t+1,c=`${t===12?a+1:a}-${String(i).padStart(2,"0")}-01`,h={start:r,end:c},u=U({queryKey:P.calendar.notesInDateRange(a,t),queryFn:()=>Ce(h)}),g=U({queryKey:P.reminders.inDateRange(a,t),queryFn:()=>He(h)});return{notes:u.data??[],reminders:g.data??[],isLoading:u.isLoading||g.isLoading,isError:u.isError||g.isError}},we=["SUN","MON","TUE","WED","THU","FRI","SAT"],Ee=[],Se=[],z=ce(me);function Le(){const a=z.useNavigate(),{year:t,month:r,type:i}=z.useSearch(),l=s.useRef(null),c=s.useRef(!1),h=s.useRef(0),u=s.useRef(0),g=s.useCallback(n=>{c.current=!0,h.current=n.pageX-(l.current?.offsetLeft??0),u.current=l.current?.scrollLeft??0,l.current&&(l.current.style.cursor="grabbing",l.current.style.userSelect="none")},[]),M=s.useCallback(n=>{if(!c.current||!l.current)return;n.preventDefault();const m=(n.pageX-l.current.offsetLeft-h.current)*1.2;l.current.scrollLeft=u.current-m},[]),v=s.useCallback(()=>{c.current=!1,l.current&&(l.current.style.cursor="grab",l.current.style.userSelect="")},[]),{notes:N,reminders:x,isLoading:D,isError:R}=Re({year:t,month:r}),w=s.useMemo(()=>{const n=f(),d=`${n.year()}-${n.month()+1}-${n.date()}`,m=new Map;for(const o of N){const y=i==="create"?f(Number(o.createdAt)):f(Number(o.updatedAt)),p=`${y.year()}-${y.month()+1}-${y.date()}`,j=m.get(p)||[];j.push(o),m.set(p,j)}const V=new Map;for(const o of x){const y=f(Number(o.reminderDate)),p=`${y.year()}-${y.month()+1}-${y.date()}`,j=V.get(p)||[];j.push(o),V.set(p,j)}const W=new Date(t,r-1,1),X=new Date(t,r,0),I=W.getDay(),T=X.getDate(),C=[],O=r===1?12:r-1,F=r===1?t-1:t,J=new Date(F,O,0).getDate();for(let o=I-1;o>=0;o--)C.push({day:J-o,isCurrentMonth:!1,year:F,month:O});for(let o=1;o<=T;o++)C.push({day:o,isCurrentMonth:!0,year:t,month:r});const L=(I+T)%7,G=L===0?0:7-L,ee=r===12?1:r+1,te=r===12?t+1:t;for(let o=1;o<=G;o++)C.push({day:o,isCurrentMonth:!1,year:te,month:ee});return C.map((o,y)=>{const p=`${o.year}-${o.month}-${o.day}`,j=f(`${o.year}-${String(o.month).padStart(2,"0")}-${String(o.day).padStart(2,"0")}`);return{key:p,year:o.year,month:o.month,day:o.day,isCurrentMonth:o.isCurrentMonth,isSunday:y%7===0,isToday:p===d,isPast:j.isBefore(n,"day"),notes:m.get(p)||Ee,reminders:V.get(p)||Se}})},[t,r,N,x,i]),E=()=>{const n=r===1?12:r-1,d=r===1?t-1:t;a({search:m=>({...m,month:n,year:d})})},A=()=>{const n=r===12?1:r+1,d=r===12?t+1:t;a({search:m=>({...m,month:n,year:d})})},S=()=>{a({search:n=>({...n,month:f().month()+1,year:f().year()})})},$=n=>{n&&a({search:d=>({...d,type:n})})};return e.jsx(le,{title:"Calendar",variant:"none",children:R?e.jsx(ge,{children:"Failed to load calendar data. Please try again later."}):e.jsxs("div",{className:"surface-base",children:[e.jsx("div",{className:"border-b border-border-subtle/80 px-4 py-4 sm:px-5",children:e.jsx(ve,{month:r,year:t,type:i,onPrevMonth:E,onNextMonth:A,onToday:S,onTypeChange:$})}),e.jsx("div",{ref:l,className:"cursor-grab overflow-x-auto px-4 pb-4 pt-3 sm:px-5",onMouseDown:g,onMouseMove:M,onMouseUp:v,onMouseLeave:v,children:e.jsxs("div",{className:"min-w-[1260px]",children:[e.jsx("div",{className:"mb-2.5 grid grid-cols-7 gap-1.5",children:we.map((n,d)=>e.jsx(b,{as:"div",variant:"label",weight:"semibold",tracking:"wider",transform:"uppercase",className:`py-2 text-center ${d===0?"text-fg-weekend":"text-fg-tertiary"}`,children:n},n))}),D?e.jsx("div",{className:"grid grid-cols-7 gap-1.5",children:Array.from({length:35}).map((n,d)=>e.jsx(ie,{height:180},d))}):e.jsx("div",{className:"grid grid-cols-7 gap-1.5",children:w.map(n=>e.jsx(Me,{year:n.year,month:n.month,day:n.day,isCurrentMonth:n.isCurrentMonth,isSunday:n.isSunday,isToday:n.isToday,isPast:n.isPast,notes:n.notes,reminders:n.reminders,type:i},n.key))})]})})]})})}export{Le as default};
|