ocean-brain 0.7.5 → 0.8.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.
- package/dist/index.js +3 -3
- package/dist/mcp.js +180 -736
- package/package.json +6 -2
- package/server/client/dist/assets/ArrowRight.es-CbA8ey6a.js +1 -0
- package/server/client/dist/assets/{Calendar-Bc2zJueR.js → Calendar-CgWgr1BV.js} +2 -2
- package/server/client/dist/assets/Callout-DKruIT0f.js +1 -0
- package/server/client/dist/assets/Copy.es-DFbgpaNJ.js +1 -0
- package/server/client/dist/assets/Graph-kCltGRlY.js +1 -0
- package/server/client/dist/assets/{Image-DxWhlIDG.js → Image-7W0DZwMo.js} +1 -1
- package/server/client/dist/assets/Image.es-5pXLx9TU.js +1 -0
- package/server/client/dist/assets/Note-BW6Np_5g.js +20 -0
- package/server/client/dist/assets/Plus.es-B0sg64VJ.js +1 -0
- package/server/client/dist/assets/Reminders-C10fHQcl.js +1 -0
- package/server/client/dist/assets/Search-tf2nV4v0.js +1 -0
- package/server/client/dist/assets/{SurfaceCard-CkAVMLPs.js → SurfaceCard-pydtvHfu.js} +1 -1
- package/server/client/dist/assets/Tag-uCoYbISy.js +1 -0
- package/server/client/dist/assets/TagNotes-CqOcQiRw.js +1 -0
- package/server/client/dist/assets/Trash.es-w32Goxfa.js +1 -0
- package/server/client/dist/assets/ViewNotes-slPXXoOY.js +1 -0
- package/server/client/dist/assets/ViewSectionDialog-brTrsF6G.js +102 -0
- package/server/client/dist/assets/Views-B_wsb-XJ.js +1 -0
- package/server/client/dist/assets/{graph-vendor-CUxe67Lr.js → graph-vendor-BAF95C0g.js} +2 -2
- package/server/client/dist/assets/image.api-CYsjXiMr.js +17 -0
- package/server/client/dist/assets/index-BR05aSXr.js +342 -0
- package/server/client/dist/assets/{index-D3BfroIT.js → index-D83QbOcw.js} +1 -1
- package/server/client/dist/assets/{index-C5BGzDgt.css → index-DPI6YoDt.css} +1 -1
- package/server/client/dist/assets/manage-image-BYIhWu56.js +1 -0
- package/server/client/dist/assets/{manage-image-detail-C8Q7K7I3.js → manage-image-detail-6KgmQvbN.js} +1 -1
- package/server/client/dist/assets/mcp-Dd98N9Hq.js +4 -0
- package/server/client/dist/assets/mcp-admin-adapter-DOgBsYpl.js +1 -0
- package/server/client/dist/assets/note-core-CMGUaW1v.js +176 -0
- package/server/client/dist/assets/note-vendor-Hoz9Q4-4.js +54 -0
- package/server/client/dist/assets/{placeholder-Cr_nI8UI.js → placeholder-siHGg9aK.js} +4 -4
- package/server/client/dist/assets/{properties-CvYWJWUM.js → properties-CyVRKgcT.js} +1 -1
- package/server/client/dist/assets/tag.api-CwmC8crB.js +21 -0
- package/server/client/dist/assets/trash-wojQBK9Z.js +1 -0
- package/server/client/dist/assets/{useReminderMutate-CDmIEwsw.js → useReminderMutate-DuVKxpBh.js} +1 -1
- package/server/client/dist/index.html +5 -5
- package/server/dist/app.js +0 -1
- package/server/dist/features/auth/http/api.js +0 -1
- package/server/dist/features/auth/http/login-page.js +272 -5
- package/server/dist/features/auth/http/pages.js +20 -3
- package/server/dist/features/auth/service.js +3 -2
- package/server/dist/features/cache/graphql/cache.field.resolver.js +0 -1
- package/server/dist/features/cache/graphql/cache.mutation.resolver.js +0 -1
- package/server/dist/features/cache/graphql/cache.query.resolver.js +0 -1
- package/server/dist/features/cache/graphql/cache.resolver.js +0 -1
- package/server/dist/features/cache/graphql/cache.type-defs.js +0 -1
- package/server/dist/features/cache/graphql/index.js +0 -1
- package/server/dist/features/image/graphql/image.field.resolver.js +0 -1
- package/server/dist/features/image/graphql/image.mutation.resolver.js +0 -1
- package/server/dist/features/image/graphql/image.query.resolver.js +0 -1
- package/server/dist/features/image/graphql/image.resolver.js +0 -1
- package/server/dist/features/image/graphql/image.type-defs.js +0 -1
- package/server/dist/features/image/graphql/index.js +0 -1
- package/server/dist/features/image/http/upload.js +34 -24
- package/server/dist/features/image/services/delete.js +0 -1
- package/server/dist/features/image/services/upload.js +0 -1
- package/server/dist/features/image/services/validation.js +110 -0
- package/server/dist/features/mcp-admin/http/handlers.js +11 -4
- package/server/dist/features/mcp-admin/service.js +0 -1
- package/server/dist/features/note/graphql/index.js +0 -1
- package/server/dist/features/note/graphql/note.field.resolver.js +0 -1
- package/server/dist/features/note/graphql/note.mutation.resolver.js +0 -1
- package/server/dist/features/note/graphql/note.query.resolver.js +0 -1
- package/server/dist/features/note/graphql/note.resolver.js +0 -1
- package/server/dist/features/note/graphql/note.type-defs.js +0 -1
- package/server/dist/features/note/http/mcp.js +8 -44
- package/server/dist/features/note/services/authoring.js +0 -1
- package/server/dist/features/note/services/cleanup.js +2 -3
- package/server/dist/features/note/services/content-blocks.js +0 -1
- package/server/dist/features/note/services/markdown-intent-write.js +11 -44
- package/server/dist/features/note/services/markdown-patch.js +4 -124
- package/server/dist/features/note/services/properties.js +0 -1
- package/server/dist/features/note/services/search-backfill.js +0 -1
- package/server/dist/features/note/services/search.js +0 -1
- package/server/dist/features/note/services/snapshot.js +0 -1
- package/server/dist/features/note/services/tag-filter.js +0 -1
- package/server/dist/features/note/services/trash.js +0 -1
- package/server/dist/features/note/services/write-conflict.js +0 -1
- package/server/dist/features/note/services/write.js +13 -14
- package/server/dist/features/placeholder/graphql/index.js +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.field.resolver.js +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.mutation.resolver.js +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.query.resolver.js +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.resolver.js +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.type-defs.js +0 -1
- package/server/dist/features/reminder/graphql/index.js +0 -1
- package/server/dist/features/reminder/graphql/reminder.field.resolver.js +0 -1
- package/server/dist/features/reminder/graphql/reminder.mutation.resolver.js +0 -1
- package/server/dist/features/reminder/graphql/reminder.query.resolver.js +0 -1
- package/server/dist/features/reminder/graphql/reminder.resolver.js +0 -1
- package/server/dist/features/reminder/graphql/reminder.type-defs.js +0 -1
- package/server/dist/features/tag/graphql/index.js +0 -1
- package/server/dist/features/tag/graphql/tag.field.resolver.js +0 -1
- package/server/dist/features/tag/graphql/tag.mutation.resolver.js +0 -1
- package/server/dist/features/tag/graphql/tag.query.resolver.js +16 -2
- package/server/dist/features/tag/graphql/tag.resolver.js +0 -1
- package/server/dist/features/tag/graphql/tag.type-defs.js +2 -1
- package/server/dist/features/tag/http/mcp.js +0 -1
- package/server/dist/features/tag/services/organization.js +0 -1
- package/server/dist/features/view/graphql/index.js +0 -1
- package/server/dist/features/view/graphql/view.mutation.resolver.js +0 -1
- package/server/dist/features/view/graphql/view.query.resolver.js +0 -1
- package/server/dist/features/view/graphql/view.resolver.js +0 -1
- package/server/dist/features/view/graphql/view.type-defs.js +0 -1
- package/server/dist/features/view/services/workspace.js +0 -1
- package/server/dist/main.js +0 -1
- package/server/dist/models.js +0 -1
- package/server/dist/modules/app-version.js +104 -0
- package/server/dist/modules/auth-guard.js +0 -1
- package/server/dist/modules/auth-mode.js +0 -1
- package/server/dist/modules/auth-redirect.js +0 -1
- package/server/dist/modules/blocknote-markdown-editor.js +53 -0
- package/server/dist/modules/blocknote-tree.js +0 -1
- package/server/dist/modules/blocknote.js +10 -4
- package/server/dist/modules/data-maintenance.js +0 -1
- package/server/dist/modules/error-handler.js +0 -1
- package/server/dist/modules/graphql.js +0 -1
- package/server/dist/modules/logger.js +0 -1
- package/server/dist/modules/mcp-auth.js +62 -2
- package/server/dist/modules/mcp-token.js +0 -1
- package/server/dist/modules/prisma-runtime.js +0 -1
- package/server/dist/modules/rate-limit.js +0 -1
- package/server/dist/modules/recovery-retention.js +0 -1
- package/server/dist/modules/server-events-handler.js +0 -1
- package/server/dist/modules/server-events.js +0 -1
- package/server/dist/modules/session-store.js +0 -1
- package/server/dist/modules/use-async.js +0 -1
- package/server/dist/paths.js +1 -1
- package/server/dist/routes/api.js +2 -9
- package/server/dist/routes/auth-pages.js +0 -1
- package/server/dist/routes/client.js +51 -2
- package/server/dist/routes/graphql.js +0 -1
- package/server/dist/routes/index.js +0 -1
- package/server/dist/routes/mcp.js +0 -1
- package/server/dist/schema/index.js +0 -1
- package/server/dist/start.js +0 -1
- package/server/dist/types/index.js +0 -1
- package/server/dist/types/input.js +0 -1
- package/server/client/dist/assets/Callout-B4kA_Cvr.js +0 -1
- package/server/client/dist/assets/Graph-uq5jfJgt.js +0 -1
- package/server/client/dist/assets/Image.es-BpAOJjJT.js +0 -1
- package/server/client/dist/assets/Note-Bo8ZYRP-.js +0 -22
- package/server/client/dist/assets/Plus.es-Dc_js8AC.js +0 -1
- package/server/client/dist/assets/Reminders-lj7Equld.js +0 -1
- package/server/client/dist/assets/Search-1wcRO5--.js +0 -1
- package/server/client/dist/assets/Tag-CeygwFfv.js +0 -1
- package/server/client/dist/assets/TagNotes-B8DqItxw.js +0 -1
- package/server/client/dist/assets/Trash.es-OuQVb_SX.js +0 -1
- package/server/client/dist/assets/ViewNotes-BH7PbdOD.js +0 -1
- package/server/client/dist/assets/ViewSectionTableRenderer-BJwhd5be.js +0 -102
- package/server/client/dist/assets/Views-eYFtsdFj.js +0 -1
- package/server/client/dist/assets/image.api-C0eYGCeH.js +0 -17
- package/server/client/dist/assets/index-jIfkRdY_.js +0 -361
- package/server/client/dist/assets/manage-image-C0YwkLIP.js +0 -1
- package/server/client/dist/assets/mcp-DHHhTLC8.js +0 -1
- package/server/client/dist/assets/note-core-Z6kqulGB.js +0 -180
- package/server/client/dist/assets/note-vendor-i1M2FSI2.js +0 -54
- package/server/client/dist/assets/trash-DA27aW7L.js +0 -1
- package/server/client/dist/fonts/Pretendard-Bold.woff +0 -0
- package/server/client/dist/fonts/Pretendard-Regular.woff +0 -0
- package/server/dist/app.js.map +0 -1
- package/server/dist/features/auth/http/api.js.map +0 -1
- package/server/dist/features/auth/http/login-page.js.map +0 -1
- package/server/dist/features/auth/http/pages.js.map +0 -1
- package/server/dist/features/auth/service.js.map +0 -1
- package/server/dist/features/cache/graphql/cache.field.resolver.js.map +0 -1
- package/server/dist/features/cache/graphql/cache.mutation.resolver.js.map +0 -1
- package/server/dist/features/cache/graphql/cache.query.resolver.js.map +0 -1
- package/server/dist/features/cache/graphql/cache.resolver.js.map +0 -1
- package/server/dist/features/cache/graphql/cache.type-defs.js.map +0 -1
- package/server/dist/features/cache/graphql/index.js.map +0 -1
- package/server/dist/features/image/graphql/image.field.resolver.js.map +0 -1
- package/server/dist/features/image/graphql/image.mutation.resolver.js.map +0 -1
- package/server/dist/features/image/graphql/image.query.resolver.js.map +0 -1
- package/server/dist/features/image/graphql/image.resolver.js.map +0 -1
- package/server/dist/features/image/graphql/image.type-defs.js.map +0 -1
- package/server/dist/features/image/graphql/index.js.map +0 -1
- package/server/dist/features/image/http/upload.js.map +0 -1
- package/server/dist/features/image/services/delete.js.map +0 -1
- package/server/dist/features/image/services/remote-fetch.js +0 -176
- package/server/dist/features/image/services/remote-fetch.js.map +0 -1
- package/server/dist/features/image/services/upload.js.map +0 -1
- package/server/dist/features/mcp-admin/http/handlers.js.map +0 -1
- package/server/dist/features/mcp-admin/service.js.map +0 -1
- package/server/dist/features/note/graphql/index.js.map +0 -1
- package/server/dist/features/note/graphql/note.field.resolver.js.map +0 -1
- package/server/dist/features/note/graphql/note.mutation.resolver.js.map +0 -1
- package/server/dist/features/note/graphql/note.query.resolver.js.map +0 -1
- package/server/dist/features/note/graphql/note.resolver.js.map +0 -1
- package/server/dist/features/note/graphql/note.type-defs.js.map +0 -1
- package/server/dist/features/note/http/mcp.js.map +0 -1
- package/server/dist/features/note/services/authoring.js.map +0 -1
- package/server/dist/features/note/services/cleanup.js.map +0 -1
- package/server/dist/features/note/services/content-blocks.js.map +0 -1
- package/server/dist/features/note/services/markdown-intent-write.js.map +0 -1
- package/server/dist/features/note/services/markdown-patch.js.map +0 -1
- package/server/dist/features/note/services/properties.js.map +0 -1
- package/server/dist/features/note/services/search-backfill.js.map +0 -1
- package/server/dist/features/note/services/search.js.map +0 -1
- package/server/dist/features/note/services/snapshot.js.map +0 -1
- package/server/dist/features/note/services/tag-filter.js.map +0 -1
- package/server/dist/features/note/services/trash.js.map +0 -1
- package/server/dist/features/note/services/write-conflict.js.map +0 -1
- package/server/dist/features/note/services/write.js.map +0 -1
- package/server/dist/features/placeholder/graphql/index.js.map +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.field.resolver.js.map +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.mutation.resolver.js.map +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.query.resolver.js.map +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.resolver.js.map +0 -1
- package/server/dist/features/placeholder/graphql/placeholder.type-defs.js.map +0 -1
- package/server/dist/features/reminder/graphql/index.js.map +0 -1
- package/server/dist/features/reminder/graphql/reminder.field.resolver.js.map +0 -1
- package/server/dist/features/reminder/graphql/reminder.mutation.resolver.js.map +0 -1
- package/server/dist/features/reminder/graphql/reminder.query.resolver.js.map +0 -1
- package/server/dist/features/reminder/graphql/reminder.resolver.js.map +0 -1
- package/server/dist/features/reminder/graphql/reminder.type-defs.js.map +0 -1
- package/server/dist/features/tag/graphql/index.js.map +0 -1
- package/server/dist/features/tag/graphql/tag.field.resolver.js.map +0 -1
- package/server/dist/features/tag/graphql/tag.mutation.resolver.js.map +0 -1
- package/server/dist/features/tag/graphql/tag.query.resolver.js.map +0 -1
- package/server/dist/features/tag/graphql/tag.resolver.js.map +0 -1
- package/server/dist/features/tag/graphql/tag.type-defs.js.map +0 -1
- package/server/dist/features/tag/http/mcp.js.map +0 -1
- package/server/dist/features/tag/services/organization.js.map +0 -1
- package/server/dist/features/view/graphql/index.js.map +0 -1
- package/server/dist/features/view/graphql/view.mutation.resolver.js.map +0 -1
- package/server/dist/features/view/graphql/view.query.resolver.js.map +0 -1
- package/server/dist/features/view/graphql/view.resolver.js.map +0 -1
- package/server/dist/features/view/graphql/view.type-defs.js.map +0 -1
- package/server/dist/features/view/services/workspace.js.map +0 -1
- package/server/dist/main.js.map +0 -1
- package/server/dist/models.js.map +0 -1
- package/server/dist/modules/auth-guard.js.map +0 -1
- package/server/dist/modules/auth-mode.js.map +0 -1
- package/server/dist/modules/auth-redirect.js.map +0 -1
- package/server/dist/modules/blocknote-tree.js.map +0 -1
- package/server/dist/modules/blocknote.js.map +0 -1
- package/server/dist/modules/data-maintenance.js.map +0 -1
- package/server/dist/modules/error-handler.js.map +0 -1
- package/server/dist/modules/graphql.js.map +0 -1
- package/server/dist/modules/logger.js.map +0 -1
- package/server/dist/modules/mcp-auth.js.map +0 -1
- package/server/dist/modules/mcp-token.js.map +0 -1
- package/server/dist/modules/prisma-runtime.js.map +0 -1
- package/server/dist/modules/rate-limit.js.map +0 -1
- package/server/dist/modules/recovery-retention.js.map +0 -1
- package/server/dist/modules/server-events-handler.js.map +0 -1
- package/server/dist/modules/server-events.js.map +0 -1
- package/server/dist/modules/session-store.js.map +0 -1
- package/server/dist/modules/use-async.js.map +0 -1
- package/server/dist/paths.js.map +0 -1
- package/server/dist/routes/api.js.map +0 -1
- package/server/dist/routes/auth-pages.js.map +0 -1
- package/server/dist/routes/client.js.map +0 -1
- package/server/dist/routes/graphql.js.map +0 -1
- package/server/dist/routes/index.js.map +0 -1
- package/server/dist/routes/mcp.js.map +0 -1
- package/server/dist/schema/index.js.map +0 -1
- package/server/dist/start.js.map +0 -1
- package/server/dist/types/index.js.map +0 -1
- package/server/dist/types/input.js.map +0 -1
|
@@ -5,6 +5,7 @@ import { sanitizeRedirectPath } from "../../modules/auth-redirect.js";
|
|
|
5
5
|
import { createAppError } from "../../modules/error-handler.js";
|
|
6
6
|
const AUTH_SESSION_GENERATION_HEADER = "X-Ocean-Brain-Session-Generation";
|
|
7
7
|
const AUTH_SESSION_GENERATION = crypto.randomUUID();
|
|
8
|
+
const getSessionGeneration = () => AUTH_SESSION_GENERATION;
|
|
8
9
|
const createPasswordHash = async (password) => {
|
|
9
10
|
const salt = crypto.randomBytes(16).toString("hex");
|
|
10
11
|
const hash = crypto.pbkdf2Sync(password, salt, 1e3, 64, "sha512").toString("hex");
|
|
@@ -18,7 +19,7 @@ const comparePassword = async (password, storedHash) => {
|
|
|
18
19
|
const compareSharedSecret = compareCommonSharedSecret;
|
|
19
20
|
const buildSessionResponse = (authConfig, req) => buildAuthSessionResponse(authConfig, Boolean(req.session?.authenticated));
|
|
20
21
|
const setSessionStatusHeaders = (res) => {
|
|
21
|
-
res.set(AUTH_SESSION_GENERATION_HEADER,
|
|
22
|
+
res.set(AUTH_SESSION_GENERATION_HEADER, getSessionGeneration());
|
|
22
23
|
res.set("Cache-Control", "no-store");
|
|
23
24
|
};
|
|
24
25
|
const refreshCsrfToken = (req) => {
|
|
@@ -64,9 +65,9 @@ export {
|
|
|
64
65
|
compareSharedSecret,
|
|
65
66
|
createPasswordHash,
|
|
66
67
|
destroySession,
|
|
68
|
+
getSessionGeneration,
|
|
67
69
|
refreshCsrfToken,
|
|
68
70
|
regenerateSession,
|
|
69
71
|
sanitizeRedirectPath,
|
|
70
72
|
setSessionStatusHeaders
|
|
71
73
|
};
|
|
72
|
-
//# sourceMappingURL=service.js.map
|
|
@@ -1,48 +1,58 @@
|
|
|
1
1
|
import { createAppError } from "../../../modules/error-handler.js";
|
|
2
|
-
import { fetchRemoteImage, RemoteImageFetchError } from "../services/remote-fetch.js";
|
|
3
2
|
import { persistUploadedImage } from "../services/upload.js";
|
|
3
|
+
import { ImageValidationError, normalizeImageContentType, validateImagePayload } from "../services/validation.js";
|
|
4
|
+
const IMAGE_DATA_URL_PATTERN = /^data:(image\/[a-z0-9.+-]+);base64,([A-Za-z0-9+/]+={0,2})$/i;
|
|
4
5
|
const createUploadResponse = (image) => {
|
|
5
6
|
return {
|
|
6
7
|
id: image.id,
|
|
7
8
|
url: image.url
|
|
8
9
|
};
|
|
9
10
|
};
|
|
11
|
+
const parseImageDataUrl = (image) => {
|
|
12
|
+
const match = IMAGE_DATA_URL_PATTERN.exec(image);
|
|
13
|
+
if (!match || !match[2] || match[2].length % 4 !== 0) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
base64: match[2],
|
|
18
|
+
contentType: normalizeImageContentType(match[1])
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const createUploadValidationError = (error) => {
|
|
22
|
+
if (error.code === "IMAGE_UNSUPPORTED_CONTENT_TYPE") {
|
|
23
|
+
return createAppError(415, "IMAGE_UPLOAD_UNSUPPORTED_TYPE", "Uploaded image content type is not supported.");
|
|
24
|
+
}
|
|
25
|
+
return createAppError(400, "INVALID_IMAGE_UPLOAD", "Uploaded image content is invalid.");
|
|
26
|
+
};
|
|
10
27
|
const createUploadImageHandler = (persistImage = persistUploadedImage) => {
|
|
11
28
|
return async (req, res) => {
|
|
12
29
|
const { image } = req.body ?? {};
|
|
13
|
-
if (typeof image !== "string"
|
|
30
|
+
if (typeof image !== "string") {
|
|
14
31
|
throw createAppError(400, "INVALID_IMAGE_UPLOAD", "No image uploaded");
|
|
15
32
|
}
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
extension
|
|
22
|
-
});
|
|
23
|
-
res.status(200).json(createUploadResponse(uploadedImage)).end();
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
const createUploadImageFromSrcHandler = (fetchImage = fetchRemoteImage, persistImage = persistUploadedImage) => {
|
|
27
|
-
return async (req, res) => {
|
|
28
|
-
const src = String(req.body?.src ?? "");
|
|
33
|
+
const parsedImage = parseImageDataUrl(image);
|
|
34
|
+
if (!parsedImage) {
|
|
35
|
+
throw createAppError(400, "INVALID_IMAGE_UPLOAD", "No image uploaded");
|
|
36
|
+
}
|
|
37
|
+
let validatedImage;
|
|
29
38
|
try {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
extension: remoteImage.extension
|
|
39
|
+
validatedImage = validateImagePayload({
|
|
40
|
+
buffer: Buffer.from(parsedImage.base64, "base64"),
|
|
41
|
+
contentType: parsedImage.contentType
|
|
34
42
|
});
|
|
35
|
-
res.status(200).json(createUploadResponse(uploadedImage)).end();
|
|
36
43
|
} catch (error) {
|
|
37
|
-
if (error instanceof
|
|
38
|
-
throw
|
|
44
|
+
if (error instanceof ImageValidationError) {
|
|
45
|
+
throw createUploadValidationError(error);
|
|
39
46
|
}
|
|
40
47
|
throw error;
|
|
41
48
|
}
|
|
49
|
+
const uploadedImage = await persistImage({
|
|
50
|
+
buffer: validatedImage.buffer,
|
|
51
|
+
extension: validatedImage.extension
|
|
52
|
+
});
|
|
53
|
+
res.status(200).json(createUploadResponse(uploadedImage)).end();
|
|
42
54
|
};
|
|
43
55
|
};
|
|
44
56
|
export {
|
|
45
|
-
createUploadImageFromSrcHandler,
|
|
46
57
|
createUploadImageHandler
|
|
47
58
|
};
|
|
48
|
-
//# sourceMappingURL=upload.js.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
class ImageValidationError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
constructor(code, status, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "ImageValidationError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.status = status;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const SUPPORTED_IMAGE_TYPES = /* @__PURE__ */ new Map([
|
|
12
|
+
["image/png", "png"],
|
|
13
|
+
["image/jpeg", "jpg"],
|
|
14
|
+
["image/gif", "gif"],
|
|
15
|
+
["image/webp", "webp"],
|
|
16
|
+
["image/bmp", "bmp"],
|
|
17
|
+
["image/avif", "avif"]
|
|
18
|
+
]);
|
|
19
|
+
const startsWithBytes = (buffer, bytes) => {
|
|
20
|
+
return bytes.every((byte, index) => buffer[index] === byte);
|
|
21
|
+
};
|
|
22
|
+
const readAscii = (buffer, start, end) => {
|
|
23
|
+
return buffer.subarray(start, end).toString("ascii");
|
|
24
|
+
};
|
|
25
|
+
const hasPngSignature = (buffer) => {
|
|
26
|
+
return buffer.length >= 8 && startsWithBytes(buffer, [137, 80, 78, 71, 13, 10, 26, 10]);
|
|
27
|
+
};
|
|
28
|
+
const hasJpegSignature = (buffer) => {
|
|
29
|
+
return buffer.length >= 3 && startsWithBytes(buffer, [255, 216, 255]);
|
|
30
|
+
};
|
|
31
|
+
const hasGifSignature = (buffer) => {
|
|
32
|
+
return buffer.length >= 6 && ["GIF87a", "GIF89a"].includes(readAscii(buffer, 0, 6));
|
|
33
|
+
};
|
|
34
|
+
const hasWebpSignature = (buffer) => {
|
|
35
|
+
return buffer.length >= 12 && readAscii(buffer, 0, 4) === "RIFF" && readAscii(buffer, 8, 12) === "WEBP";
|
|
36
|
+
};
|
|
37
|
+
const hasBmpSignature = (buffer) => {
|
|
38
|
+
return buffer.length >= 2 && readAscii(buffer, 0, 2) === "BM";
|
|
39
|
+
};
|
|
40
|
+
const hasAvifSignature = (buffer) => {
|
|
41
|
+
if (buffer.length < 16 || readAscii(buffer, 4, 8) !== "ftyp") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const ftypBoxSize = buffer.readUInt32BE(0);
|
|
45
|
+
if (ftypBoxSize !== 0 && (ftypBoxSize < 16 || ftypBoxSize > buffer.length)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const isAvifBrand = (brand) => brand === "avif" || brand === "avis";
|
|
49
|
+
const majorBrand = readAscii(buffer, 8, 12);
|
|
50
|
+
if (isAvifBrand(majorBrand)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
const boxEnd = ftypBoxSize === 0 ? buffer.length : ftypBoxSize;
|
|
54
|
+
for (let offset = 16; offset + 4 <= boxEnd; offset += 4) {
|
|
55
|
+
const brand = readAscii(buffer, offset, offset + 4);
|
|
56
|
+
if (isAvifBrand(brand)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
};
|
|
62
|
+
const hasExpectedImageSignature = (contentType, buffer) => {
|
|
63
|
+
switch (contentType) {
|
|
64
|
+
case "image/png":
|
|
65
|
+
return hasPngSignature(buffer);
|
|
66
|
+
case "image/jpeg":
|
|
67
|
+
return hasJpegSignature(buffer);
|
|
68
|
+
case "image/gif":
|
|
69
|
+
return hasGifSignature(buffer);
|
|
70
|
+
case "image/webp":
|
|
71
|
+
return hasWebpSignature(buffer);
|
|
72
|
+
case "image/bmp":
|
|
73
|
+
return hasBmpSignature(buffer);
|
|
74
|
+
case "image/avif":
|
|
75
|
+
return hasAvifSignature(buffer);
|
|
76
|
+
default:
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const normalizeImageContentType = (contentType) => {
|
|
81
|
+
return contentType?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
82
|
+
};
|
|
83
|
+
const getSupportedImageExtension = (contentType) => {
|
|
84
|
+
return SUPPORTED_IMAGE_TYPES.get(normalizeImageContentType(contentType));
|
|
85
|
+
};
|
|
86
|
+
const validateImagePayload = ({
|
|
87
|
+
buffer,
|
|
88
|
+
contentType: rawContentType
|
|
89
|
+
}) => {
|
|
90
|
+
const contentType = normalizeImageContentType(rawContentType);
|
|
91
|
+
const extension = SUPPORTED_IMAGE_TYPES.get(contentType);
|
|
92
|
+
if (!extension) {
|
|
93
|
+
throw new ImageValidationError("IMAGE_UNSUPPORTED_CONTENT_TYPE", 415, "Image content type is not supported.");
|
|
94
|
+
}
|
|
95
|
+
const hasExpectedSignature = hasExpectedImageSignature(contentType, buffer);
|
|
96
|
+
if (!hasExpectedSignature) {
|
|
97
|
+
throw new ImageValidationError("IMAGE_INVALID_CONTENT", 415, "Image content does not match the declared type.");
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
buffer,
|
|
101
|
+
contentType,
|
|
102
|
+
extension
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
export {
|
|
106
|
+
ImageValidationError,
|
|
107
|
+
getSupportedImageExtension,
|
|
108
|
+
normalizeImageContentType,
|
|
109
|
+
validateImagePayload
|
|
110
|
+
};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
import { getOceanBrainVersionInfo } from "../../../modules/app-version.js";
|
|
1
2
|
import { createAppError } from "../../../modules/error-handler.js";
|
|
2
3
|
import { createMcpAdminService } from "../service.js";
|
|
4
|
+
const createMcpAdminStatusResponse = async (service) => {
|
|
5
|
+
const status = await service.getStatus();
|
|
6
|
+
return {
|
|
7
|
+
...status,
|
|
8
|
+
server: getOceanBrainVersionInfo()
|
|
9
|
+
};
|
|
10
|
+
};
|
|
3
11
|
const createMcpAdminStatusHandler = (service = createMcpAdminService()) => {
|
|
4
12
|
return async (_req, res) => {
|
|
5
|
-
const status = await service
|
|
13
|
+
const status = await createMcpAdminStatusResponse(service);
|
|
6
14
|
res.status(200).json(status).end();
|
|
7
15
|
};
|
|
8
16
|
};
|
|
@@ -13,7 +21,7 @@ const createMcpAdminSetEnabledHandler = (service = createMcpAdminService()) => {
|
|
|
13
21
|
throw createAppError(400, "INVALID_MCP_ENABLED", "enabled must be a boolean.");
|
|
14
22
|
}
|
|
15
23
|
await service.setEnabled(enabled);
|
|
16
|
-
const status = await service
|
|
24
|
+
const status = await createMcpAdminStatusResponse(service);
|
|
17
25
|
res.status(200).json(status).end();
|
|
18
26
|
};
|
|
19
27
|
};
|
|
@@ -29,7 +37,7 @@ const createMcpAdminRotateTokenHandler = (service = createMcpAdminService()) =>
|
|
|
29
37
|
const createMcpAdminRevokeTokenHandler = (service = createMcpAdminService()) => {
|
|
30
38
|
return async (_req, res) => {
|
|
31
39
|
await service.revokeActiveToken();
|
|
32
|
-
const status = await service
|
|
40
|
+
const status = await createMcpAdminStatusResponse(service);
|
|
33
41
|
res.status(200).json(status).end();
|
|
34
42
|
};
|
|
35
43
|
};
|
|
@@ -39,4 +47,3 @@ export {
|
|
|
39
47
|
createMcpAdminSetEnabledHandler,
|
|
40
48
|
createMcpAdminStatusHandler
|
|
41
49
|
};
|
|
42
|
-
//# sourceMappingURL=handlers.js.map
|
|
@@ -38,15 +38,6 @@ const resolveOptionalString = (value, code, message) => {
|
|
|
38
38
|
}
|
|
39
39
|
throw createAppError(400, code, message);
|
|
40
40
|
};
|
|
41
|
-
const resolveOptionalBoolean = (value, code, message) => {
|
|
42
|
-
if (value === void 0) {
|
|
43
|
-
return void 0;
|
|
44
|
-
}
|
|
45
|
-
if (typeof value === "boolean") {
|
|
46
|
-
return value;
|
|
47
|
-
}
|
|
48
|
-
throw createAppError(400, code, message);
|
|
49
|
-
};
|
|
50
41
|
const resolveMetadataPropertyPatch = (value) => {
|
|
51
42
|
if (value === void 0) {
|
|
52
43
|
return void 0;
|
|
@@ -117,24 +108,6 @@ const resolveMarkdownWritePolicy = (value) => {
|
|
|
117
108
|
}
|
|
118
109
|
policy.allowNoop = value.allowNoop;
|
|
119
110
|
}
|
|
120
|
-
if (value.maxChangedChars !== void 0) {
|
|
121
|
-
if (!isNonNegativeInteger(value.maxChangedChars)) {
|
|
122
|
-
throw createAppError(400, "INVALID_MARKDOWN_POLICY", "maxChangedChars must be a non-negative integer.");
|
|
123
|
-
}
|
|
124
|
-
policy.maxChangedChars = value.maxChangedChars;
|
|
125
|
-
}
|
|
126
|
-
if (value.maxChangedLines !== void 0) {
|
|
127
|
-
if (!isNonNegativeInteger(value.maxChangedLines)) {
|
|
128
|
-
throw createAppError(400, "INVALID_MARKDOWN_POLICY", "maxChangedLines must be a non-negative integer.");
|
|
129
|
-
}
|
|
130
|
-
policy.maxChangedLines = value.maxChangedLines;
|
|
131
|
-
}
|
|
132
|
-
if (value.diffPreviewMaxChars !== void 0) {
|
|
133
|
-
if (!isNonNegativeInteger(value.diffPreviewMaxChars)) {
|
|
134
|
-
throw createAppError(400, "INVALID_MARKDOWN_POLICY", "diffPreviewMaxChars must be a non-negative integer.");
|
|
135
|
-
}
|
|
136
|
-
policy.diffPreviewMaxChars = value.diffPreviewMaxChars;
|
|
137
|
-
}
|
|
138
111
|
if (value.preserveTags !== void 0) {
|
|
139
112
|
if (!PRESERVATION_POLICIES.has(value.preserveTags)) {
|
|
140
113
|
throw createAppError(400, "INVALID_MARKDOWN_POLICY", "preserveTags must be boolean or warn.");
|
|
@@ -368,7 +341,7 @@ const createMcpNoteWriteBaselineHandler = (findNoteBaseline = async (id) => mode
|
|
|
368
341
|
};
|
|
369
342
|
const createMcpPatchNoteMarkdownHandler = (patchMarkdown = patchNoteMarkdown, emitEvent = emitServerEvent) => {
|
|
370
343
|
return async (req, res) => {
|
|
371
|
-
const { id, expectedUpdatedAt, baseMarkdownSha256, intent, selector, operation, policy
|
|
344
|
+
const { id, expectedUpdatedAt, baseMarkdownSha256, intent, selector, operation, policy } = req.body ?? {};
|
|
372
345
|
const noteId = resolvePositiveNoteId(id);
|
|
373
346
|
const resolvedExpectedUpdatedAt = resolveOptionalString(
|
|
374
347
|
expectedUpdatedAt,
|
|
@@ -380,7 +353,6 @@ const createMcpPatchNoteMarkdownHandler = (patchMarkdown = patchNoteMarkdown, em
|
|
|
380
353
|
"INVALID_MARKDOWN_HASH",
|
|
381
354
|
"baseMarkdownSha256 must be a string."
|
|
382
355
|
);
|
|
383
|
-
const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
|
|
384
356
|
if (typeof intent !== "string") {
|
|
385
357
|
throw createAppError(400, "INVALID_PATCH_INTENT", "Patch intent must be a string.");
|
|
386
358
|
}
|
|
@@ -391,8 +363,7 @@ const createMcpPatchNoteMarkdownHandler = (patchMarkdown = patchNoteMarkdown, em
|
|
|
391
363
|
intent,
|
|
392
364
|
selector: resolvePatchSelector(selector),
|
|
393
365
|
operation: resolvePatchOperation(operation),
|
|
394
|
-
policy: resolveMarkdownWritePolicy(policy)
|
|
395
|
-
dryRun: resolvedDryRun
|
|
366
|
+
policy: resolveMarkdownWritePolicy(policy)
|
|
396
367
|
});
|
|
397
368
|
if (result.status === "applied") {
|
|
398
369
|
emitEvent({
|
|
@@ -407,7 +378,7 @@ const createMcpPatchNoteMarkdownHandler = (patchMarkdown = patchNoteMarkdown, em
|
|
|
407
378
|
};
|
|
408
379
|
const createMcpAppendNoteMarkdownHandler = (appendMarkdown = appendNoteMarkdown, emitEvent = emitServerEvent) => {
|
|
409
380
|
return async (req, res) => {
|
|
410
|
-
const { id, expectedUpdatedAt, baseMarkdownSha256, intent, insertion, placement, separator, policy
|
|
381
|
+
const { id, expectedUpdatedAt, baseMarkdownSha256, intent, insertion, placement, separator, policy } = req.body ?? {};
|
|
411
382
|
const noteId = resolvePositiveNoteId(id);
|
|
412
383
|
const resolvedExpectedUpdatedAt = resolveOptionalString(
|
|
413
384
|
expectedUpdatedAt,
|
|
@@ -419,7 +390,6 @@ const createMcpAppendNoteMarkdownHandler = (appendMarkdown = appendNoteMarkdown,
|
|
|
419
390
|
"INVALID_MARKDOWN_HASH",
|
|
420
391
|
"baseMarkdownSha256 must be a string."
|
|
421
392
|
);
|
|
422
|
-
const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
|
|
423
393
|
if (typeof intent !== "string") {
|
|
424
394
|
throw createAppError(400, "INVALID_APPEND_INTENT", "Append intent must be a string.");
|
|
425
395
|
}
|
|
@@ -434,8 +404,7 @@ const createMcpAppendNoteMarkdownHandler = (appendMarkdown = appendNoteMarkdown,
|
|
|
434
404
|
insertion,
|
|
435
405
|
placement: resolveAppendPlacement(placement),
|
|
436
406
|
separator: resolveSeparator(separator),
|
|
437
|
-
policy: resolveMarkdownWritePolicy(policy)
|
|
438
|
-
dryRun: resolvedDryRun
|
|
407
|
+
policy: resolveMarkdownWritePolicy(policy)
|
|
439
408
|
});
|
|
440
409
|
if (result.status === "applied") {
|
|
441
410
|
emitEvent({
|
|
@@ -450,7 +419,7 @@ const createMcpAppendNoteMarkdownHandler = (appendMarkdown = appendNoteMarkdown,
|
|
|
450
419
|
};
|
|
451
420
|
const createMcpReplaceNoteMarkdownHandler = (replaceMarkdown = replaceNoteMarkdown, emitEvent = emitServerEvent) => {
|
|
452
421
|
return async (req, res) => {
|
|
453
|
-
const { id, expectedUpdatedAt, baseMarkdownSha256, intent, replacement, policy
|
|
422
|
+
const { id, expectedUpdatedAt, baseMarkdownSha256, intent, replacement, policy } = req.body ?? {};
|
|
454
423
|
const noteId = resolvePositiveNoteId(id);
|
|
455
424
|
const resolvedExpectedUpdatedAt = resolveOptionalString(
|
|
456
425
|
expectedUpdatedAt,
|
|
@@ -462,7 +431,6 @@ const createMcpReplaceNoteMarkdownHandler = (replaceMarkdown = replaceNoteMarkdo
|
|
|
462
431
|
"INVALID_MARKDOWN_HASH",
|
|
463
432
|
"baseMarkdownSha256 must be a string."
|
|
464
433
|
);
|
|
465
|
-
const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
|
|
466
434
|
if (typeof intent !== "string") {
|
|
467
435
|
throw createAppError(400, "INVALID_REPLACE_INTENT", "Replace intent must be a string.");
|
|
468
436
|
}
|
|
@@ -475,8 +443,7 @@ const createMcpReplaceNoteMarkdownHandler = (replaceMarkdown = replaceNoteMarkdo
|
|
|
475
443
|
baseMarkdownSha256: resolvedBaseMarkdownSha256,
|
|
476
444
|
intent,
|
|
477
445
|
replacement,
|
|
478
|
-
policy: resolveMarkdownWritePolicy(policy)
|
|
479
|
-
dryRun: resolvedDryRun
|
|
446
|
+
policy: resolveMarkdownWritePolicy(policy)
|
|
480
447
|
});
|
|
481
448
|
if (result.status === "applied") {
|
|
482
449
|
emitEvent({
|
|
@@ -491,11 +458,10 @@ const createMcpReplaceNoteMarkdownHandler = (replaceMarkdown = replaceNoteMarkdo
|
|
|
491
458
|
};
|
|
492
459
|
const createMcpUpdateNoteMetadataHandler = (updateMetadata = updateNoteMetadata, emitEvent = emitServerEvent) => {
|
|
493
460
|
return async (req, res) => {
|
|
494
|
-
const { id, expectedUpdatedAt, title, layout, properties
|
|
461
|
+
const { id, expectedUpdatedAt, title, layout, properties } = req.body ?? {};
|
|
495
462
|
const noteId = resolvePositiveNoteId(id);
|
|
496
463
|
const resolvedLayout = resolveNoteLayout(layout);
|
|
497
464
|
const resolvedProperties = resolveMetadataPropertyPatch(properties);
|
|
498
|
-
const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
|
|
499
465
|
if (typeof expectedUpdatedAt !== "string") {
|
|
500
466
|
throw createAppError(400, "INVALID_NOTE_VERSION", "expectedUpdatedAt must be a string.");
|
|
501
467
|
}
|
|
@@ -513,8 +479,7 @@ const createMcpUpdateNoteMetadataHandler = (updateMetadata = updateNoteMetadata,
|
|
|
513
479
|
expectedUpdatedAt,
|
|
514
480
|
...title !== void 0 ? { title } : {},
|
|
515
481
|
...resolvedLayout ? { layout: resolvedLayout } : {},
|
|
516
|
-
...resolvedProperties !== void 0 ? { properties: resolvedProperties } : {}
|
|
517
|
-
dryRun: resolvedDryRun
|
|
482
|
+
...resolvedProperties !== void 0 ? { properties: resolvedProperties } : {}
|
|
518
483
|
});
|
|
519
484
|
if (result.status === "applied") {
|
|
520
485
|
emitEvent({
|
|
@@ -558,4 +523,3 @@ export {
|
|
|
558
523
|
createMcpUpdateNoteHandler,
|
|
559
524
|
createMcpUpdateNoteMetadataHandler
|
|
560
525
|
};
|
|
561
|
-
//# sourceMappingURL=mcp.js.map
|
|
@@ -76,8 +76,8 @@ const createNoteCleanupService = (deps) => {
|
|
|
76
76
|
})),
|
|
77
77
|
orphanedTagNames: orphanedTags.map((tag) => tag.name),
|
|
78
78
|
orphanedTagIds: orphanedTags.map((tag) => tag.id),
|
|
79
|
-
requiresForce: candidate.requiresForce
|
|
80
|
-
forceReasons:
|
|
79
|
+
requiresForce: candidate.requiresForce,
|
|
80
|
+
forceReasons: candidate.forceReasons
|
|
81
81
|
};
|
|
82
82
|
};
|
|
83
83
|
const getDeletePreview = async (id) => {
|
|
@@ -196,4 +196,3 @@ export {
|
|
|
196
196
|
listNoteCleanupCandidates,
|
|
197
197
|
normalizeCleanupKeywords
|
|
198
198
|
};
|
|
199
|
-
//# sourceMappingURL=cleanup.js.map
|