emdash 0.0.1 → 0.0.3
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/astro/index.mjs +41 -38
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +18 -1
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/db/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{runner-B-u2F2b6.mjs → runner-C0hCbYnD.mjs} +15 -15
- package/dist/runner-C0hCbYnD.mjs.map +1 -0
- package/dist/storage/local.d.mts.map +1 -1
- package/dist/storage/local.mjs.map +1 -1
- package/dist/storage/s3.d.mts.map +1 -1
- package/dist/storage/s3.mjs.map +1 -1
- package/package.json +5 -5
- package/src/api/handlers/device-flow.ts +1 -4
- package/src/api/handlers/oauth-clients.ts +1 -5
- package/src/astro/integration/index.ts +1 -1
- package/src/astro/integration/vite-config.ts +8 -1
- package/src/astro/middleware.ts +35 -0
- package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -5
- package/src/astro/routes/api/auth/passkey/register/verify.ts +1 -3
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +1 -5
- package/src/astro/routes/api/import/wordpress/analyze.ts +1 -1
- package/src/astro/routes/api/import/wordpress/media.ts +1 -1
- package/src/astro/routes/api/revisions/[revisionId]/restore.ts +1 -5
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +1 -5
- package/src/cli/commands/publish.ts +1 -3
- package/src/cli/commands/seed.ts +1 -3
- package/src/database/migrations/001_initial.ts +39 -5
- package/src/database/migrations/032_rate_limits.ts +1 -4
- package/src/mcp/server.ts +2 -2
- package/src/storage/local.ts +1 -5
- package/src/storage/s3.ts +2 -10
- package/dist/runner-B-u2F2b6.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "emdash",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Astro-native CMS with WordPress migration support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -179,8 +179,8 @@
|
|
|
179
179
|
"upng-js": "^2.1.0",
|
|
180
180
|
"zod": "^4.3.5",
|
|
181
181
|
"@emdash-cms/gutenberg-to-portable-text": "0.0.1",
|
|
182
|
-
"@emdash-cms/
|
|
183
|
-
"@emdash-cms/
|
|
182
|
+
"@emdash-cms/admin": "0.0.2",
|
|
183
|
+
"@emdash-cms/auth": "0.0.1"
|
|
184
184
|
},
|
|
185
185
|
"optionalDependencies": {
|
|
186
186
|
"@libsql/kysely-libsql": "^0.4.0",
|
|
@@ -212,10 +212,10 @@
|
|
|
212
212
|
},
|
|
213
213
|
"repository": {
|
|
214
214
|
"type": "git",
|
|
215
|
-
"url": "git+https://github.com/
|
|
215
|
+
"url": "git+https://github.com/emdash-cms/emdash.git",
|
|
216
216
|
"directory": "packages/core"
|
|
217
217
|
},
|
|
218
|
-
"homepage": "https://github.com/
|
|
218
|
+
"homepage": "https://github.com/emdash-cms/emdash",
|
|
219
219
|
"keywords": [
|
|
220
220
|
"astro",
|
|
221
221
|
"cms",
|
|
@@ -664,10 +664,7 @@ export async function handleTokenRevoke(
|
|
|
664
664
|
|
|
665
665
|
if (row.token_type === "refresh") {
|
|
666
666
|
// Revoke refresh token and all its access tokens
|
|
667
|
-
await db
|
|
668
|
-
.deleteFrom("_emdash_oauth_tokens")
|
|
669
|
-
.where("refresh_token_hash", "=", hash)
|
|
670
|
-
.execute();
|
|
667
|
+
await db.deleteFrom("_emdash_oauth_tokens").where("refresh_token_hash", "=", hash).execute();
|
|
671
668
|
await db.deleteFrom("_emdash_oauth_tokens").where("token_hash", "=", hash).execute();
|
|
672
669
|
} else {
|
|
673
670
|
// Revoke just the access token
|
|
@@ -236,11 +236,7 @@ export async function handleOAuthClientUpdate(
|
|
|
236
236
|
updates.scopes = input.scopes ? JSON.stringify(input.scopes) : "";
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
await db
|
|
240
|
-
.updateTable("_emdash_oauth_clients")
|
|
241
|
-
.set(updates)
|
|
242
|
-
.where("id", "=", clientId)
|
|
243
|
-
.execute();
|
|
239
|
+
await db.updateTable("_emdash_oauth_clients").set(updates).where("id", "=", clientId).execute();
|
|
244
240
|
|
|
245
241
|
// Fetch the updated row
|
|
246
242
|
const updated = await db
|
|
@@ -269,6 +269,13 @@ export function createViteConfig(
|
|
|
269
269
|
// Vite discovers them one-by-one on first request, causing workerd
|
|
270
270
|
// to enter "worker cancelled" state on cold cache.
|
|
271
271
|
optimizeDeps: {
|
|
272
|
+
// Exclude EmDash virtual modules from esbuild's dependency
|
|
273
|
+
// scan. These are resolved by the Vite plugin at transform time,
|
|
274
|
+
// but esbuild encounters them when crawling emdash's dist files
|
|
275
|
+
// during pre-bundling and can't resolve them. Vite's exclude
|
|
276
|
+
// uses prefix matching (id.startsWith(m + "/")), so
|
|
277
|
+
// "virtual:emdash" matches all "virtual:emdash/*" imports.
|
|
278
|
+
exclude: ["virtual:emdash"],
|
|
272
279
|
include: [
|
|
273
280
|
// EmDash direct deps
|
|
274
281
|
"emdash > @portabletext/toolkit",
|
|
@@ -322,7 +329,7 @@ export function createViteConfig(
|
|
|
322
329
|
include: useSource
|
|
323
330
|
? ["@astrojs/react/client.js"]
|
|
324
331
|
: ["@emdash-cms/admin", "@astrojs/react/client.js"],
|
|
325
|
-
exclude: cloudflare ? [] : NODE_NATIVE_EXTERNALS,
|
|
332
|
+
exclude: cloudflare ? ["virtual:emdash"] : [...NODE_NATIVE_EXTERNALS, "virtual:emdash"],
|
|
326
333
|
},
|
|
327
334
|
};
|
|
328
335
|
}
|
package/src/astro/middleware.ts
CHANGED
|
@@ -54,6 +54,16 @@ let runtimeInitializing = false;
|
|
|
54
54
|
/** Whether i18n config has been initialized from the virtual module */
|
|
55
55
|
let i18nInitialized = false;
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Whether we've verified the database has been set up.
|
|
59
|
+
* On a fresh deployment the first request may hit a public page, bypassing
|
|
60
|
+
* runtime init. Without this check, template helpers like getSiteSettings()
|
|
61
|
+
* would query an empty database and crash. Once verified (or once the runtime
|
|
62
|
+
* has initialized via an admin/API request), this stays true for the worker's
|
|
63
|
+
* lifetime.
|
|
64
|
+
*/
|
|
65
|
+
let setupVerified = false;
|
|
66
|
+
|
|
57
67
|
/**
|
|
58
68
|
* Get EmDash configuration from virtual module
|
|
59
69
|
*/
|
|
@@ -190,6 +200,28 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
190
200
|
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
|
191
201
|
const sessionUser = await context.session?.get("user");
|
|
192
202
|
if (!sessionUser && !playgroundDb) {
|
|
203
|
+
// On a fresh deployment the database may be completely empty.
|
|
204
|
+
// Public pages call getSiteSettings() / getMenu() via getDb(), which
|
|
205
|
+
// bypasses runtime init and would crash with "no such table: options".
|
|
206
|
+
// Do a one-time lightweight probe using the same getDb() instance the
|
|
207
|
+
// page will use: if the migrations table doesn't exist, no migrations
|
|
208
|
+
// have ever run -- redirect to the setup wizard.
|
|
209
|
+
if (!setupVerified) {
|
|
210
|
+
try {
|
|
211
|
+
const { getDb } = await import("../loader.js");
|
|
212
|
+
const db = await getDb();
|
|
213
|
+
await db
|
|
214
|
+
.selectFrom("_emdash_migrations" as keyof Database)
|
|
215
|
+
.selectAll()
|
|
216
|
+
.limit(1)
|
|
217
|
+
.execute();
|
|
218
|
+
setupVerified = true;
|
|
219
|
+
} catch {
|
|
220
|
+
// Table doesn't exist -> fresh database, redirect to setup
|
|
221
|
+
return context.redirect("/_emdash/admin/setup");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
193
225
|
const response = await next();
|
|
194
226
|
setBaselineSecurityHeaders(response);
|
|
195
227
|
return response;
|
|
@@ -210,6 +242,9 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
210
242
|
// Get or create runtime
|
|
211
243
|
const runtime = await getRuntime(config);
|
|
212
244
|
|
|
245
|
+
// Runtime init runs migrations, so the DB is guaranteed set up
|
|
246
|
+
setupVerified = true;
|
|
247
|
+
|
|
213
248
|
// Get manifest (cached after first call)
|
|
214
249
|
const manifest = await runtime.getManifest();
|
|
215
250
|
|
|
@@ -95,11 +95,7 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
|
|
|
95
95
|
if (newStatus === "approved" && previousStatus !== "approved" && emdash.email) {
|
|
96
96
|
try {
|
|
97
97
|
const adminBaseUrl = await getSiteBaseUrl(emdash.db, request);
|
|
98
|
-
const content = await lookupContentAuthor(
|
|
99
|
-
emdash.db,
|
|
100
|
-
updated.collection,
|
|
101
|
-
updated.contentId,
|
|
102
|
-
);
|
|
98
|
+
const content = await lookupContentAuthor(emdash.db, updated.collection, updated.contentId);
|
|
103
99
|
if (content?.author) {
|
|
104
100
|
await sendCommentNotification({
|
|
105
101
|
email: emdash.email,
|
|
@@ -71,9 +71,7 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
|
|
71
71
|
// Get passkey name - prefer body.name, then check stored pending name
|
|
72
72
|
let passKeyName: string | undefined = body.name ?? undefined;
|
|
73
73
|
if (!passKeyName) {
|
|
74
|
-
const pending = await optionsRepo.get<{ name?: string }>(
|
|
75
|
-
`emdash:passkey_pending:${user.id}`,
|
|
76
|
-
);
|
|
74
|
+
const pending = await optionsRepo.get<{ name?: string }>(`emdash:passkey_pending:${user.id}`);
|
|
77
75
|
if (pending?.name) {
|
|
78
76
|
passKeyName = pending.name;
|
|
79
77
|
}
|
|
@@ -59,11 +59,7 @@ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
59
59
|
const denied = requireOwnerPerm(user, authorId, "content:publish_own", "content:publish_any");
|
|
60
60
|
if (denied) return denied;
|
|
61
61
|
|
|
62
|
-
const result = await emdash.handleContentSchedule(
|
|
63
|
-
collection,
|
|
64
|
-
resolvedId ?? id,
|
|
65
|
-
body.scheduledAt,
|
|
66
|
-
);
|
|
62
|
+
const result = await emdash.handleContentSchedule(collection, resolvedId ?? id, body.scheduledAt);
|
|
67
63
|
|
|
68
64
|
if (!result.success) return unwrapResult(result);
|
|
69
65
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { APIRoute } from "astro";
|
|
11
|
-
import mime from "mime/lite";
|
|
12
11
|
import { parseWxrString, SchemaRegistry, type WxrData } from "emdash";
|
|
12
|
+
import mime from "mime/lite";
|
|
13
13
|
|
|
14
14
|
import { requirePerm } from "#api/authorize.js";
|
|
15
15
|
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
import * as path from "node:path";
|
|
12
12
|
|
|
13
13
|
import type { APIRoute } from "astro";
|
|
14
|
-
import mime from "mime/lite";
|
|
15
14
|
import { MediaRepository, computeContentHash } from "emdash";
|
|
15
|
+
import mime from "mime/lite";
|
|
16
16
|
import { ulid } from "ulidx";
|
|
17
17
|
|
|
18
18
|
import { requirePerm } from "#api/authorize.js";
|
|
@@ -15,11 +15,7 @@ export const POST: APIRoute = async ({ params, locals }) => {
|
|
|
15
15
|
const { emdash, user } = locals;
|
|
16
16
|
const revisionId = params.revisionId!;
|
|
17
17
|
|
|
18
|
-
if (
|
|
19
|
-
!emdash?.handleRevisionRestore ||
|
|
20
|
-
!emdash?.handleRevisionGet ||
|
|
21
|
-
!emdash?.handleContentGet
|
|
22
|
-
) {
|
|
18
|
+
if (!emdash?.handleRevisionRestore || !emdash?.handleRevisionGet || !emdash?.handleContentGet) {
|
|
23
19
|
return apiError("NOT_CONFIGURED", "EmDash not configured", 500);
|
|
24
20
|
}
|
|
25
21
|
|
|
@@ -57,11 +57,7 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
|
|
|
57
57
|
// Update sort_order for each widget
|
|
58
58
|
await Promise.all(
|
|
59
59
|
body.widgetIds.map((id, index) =>
|
|
60
|
-
db
|
|
61
|
-
.updateTable("_emdash_widgets")
|
|
62
|
-
.set({ sort_order: index })
|
|
63
|
-
.where("id", "=", id)
|
|
64
|
-
.execute(),
|
|
60
|
+
db.updateTable("_emdash_widgets").set({ sort_order: index }).where("id", "=", id).execute(),
|
|
65
61
|
),
|
|
66
62
|
);
|
|
67
63
|
|
|
@@ -418,9 +418,7 @@ export const publishCommand = defineCommand({
|
|
|
418
418
|
process.exit(1);
|
|
419
419
|
}
|
|
420
420
|
} catch {
|
|
421
|
-
consola.error(
|
|
422
|
-
"No dist/ directory found. Run `emdash plugin bundle` first or use --build.",
|
|
423
|
-
);
|
|
421
|
+
consola.error("No dist/ directory found. Run `emdash plugin bundle` first or use --build.");
|
|
424
422
|
process.exit(1);
|
|
425
423
|
}
|
|
426
424
|
}
|
package/src/cli/commands/seed.ts
CHANGED
|
@@ -135,9 +135,7 @@ export const seedCommand = defineCommand({
|
|
|
135
135
|
const seedPath = await resolveSeedPath(cwd, args.path);
|
|
136
136
|
if (!seedPath) {
|
|
137
137
|
consola.error("No seed file found");
|
|
138
|
-
consola.info(
|
|
139
|
-
"Provide a path, create .emdash/seed.json, or set emdash.seed in package.json",
|
|
140
|
-
);
|
|
138
|
+
consola.info("Provide a path, create .emdash/seed.json, or set emdash.seed in package.json");
|
|
141
139
|
process.exit(1);
|
|
142
140
|
}
|
|
143
141
|
|
|
@@ -14,6 +14,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
14
14
|
// References entries in ec_* tables by collection + entry_id
|
|
15
15
|
await db.schema
|
|
16
16
|
.createTable("revisions")
|
|
17
|
+
.ifNotExists()
|
|
17
18
|
.addColumn("id", "text", (col) => col.primaryKey())
|
|
18
19
|
.addColumn("collection", "text", (col) => col.notNull()) // e.g., 'posts'
|
|
19
20
|
.addColumn("entry_id", "text", (col) => col.notNull()) // ID in the ec_* table
|
|
@@ -24,6 +25,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
24
25
|
|
|
25
26
|
await db.schema
|
|
26
27
|
.createIndex("idx_revisions_entry")
|
|
28
|
+
.ifNotExists()
|
|
27
29
|
.on("revisions")
|
|
28
30
|
.columns(["collection", "entry_id"])
|
|
29
31
|
.execute();
|
|
@@ -31,6 +33,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
31
33
|
// Taxonomies
|
|
32
34
|
await db.schema
|
|
33
35
|
.createTable("taxonomies")
|
|
36
|
+
.ifNotExists()
|
|
34
37
|
.addColumn("id", "text", (col) => col.primaryKey())
|
|
35
38
|
.addColumn("name", "text", (col) => col.notNull())
|
|
36
39
|
.addColumn("slug", "text", (col) => col.notNull())
|
|
@@ -43,11 +46,17 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
43
46
|
)
|
|
44
47
|
.execute();
|
|
45
48
|
|
|
46
|
-
await db.schema
|
|
49
|
+
await db.schema
|
|
50
|
+
.createIndex("idx_taxonomies_name")
|
|
51
|
+
.ifNotExists()
|
|
52
|
+
.on("taxonomies")
|
|
53
|
+
.column("name")
|
|
54
|
+
.execute();
|
|
47
55
|
|
|
48
56
|
// Content-Taxonomy junction - references entries in ec_* tables
|
|
49
57
|
await db.schema
|
|
50
58
|
.createTable("content_taxonomies")
|
|
59
|
+
.ifNotExists()
|
|
51
60
|
.addColumn("collection", "text", (col) => col.notNull()) // e.g., 'posts'
|
|
52
61
|
.addColumn("entry_id", "text", (col) => col.notNull()) // ID in the ec_* table
|
|
53
62
|
.addColumn("taxonomy_id", "text", (col) => col.notNull())
|
|
@@ -64,6 +73,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
64
73
|
// Media
|
|
65
74
|
await db.schema
|
|
66
75
|
.createTable("media")
|
|
76
|
+
.ifNotExists()
|
|
67
77
|
.addColumn("id", "text", (col) => col.primaryKey())
|
|
68
78
|
.addColumn("filename", "text", (col) => col.notNull())
|
|
69
79
|
.addColumn("mime_type", "text", (col) => col.notNull())
|
|
@@ -80,6 +90,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
80
90
|
|
|
81
91
|
await db.schema
|
|
82
92
|
.createIndex("idx_media_content_hash")
|
|
93
|
+
.ifNotExists()
|
|
83
94
|
.on("media")
|
|
84
95
|
.column("content_hash")
|
|
85
96
|
.execute();
|
|
@@ -87,6 +98,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
87
98
|
// Users
|
|
88
99
|
await db.schema
|
|
89
100
|
.createTable("users")
|
|
101
|
+
.ifNotExists()
|
|
90
102
|
.addColumn("id", "text", (col) => col.primaryKey())
|
|
91
103
|
.addColumn("email", "text", (col) => col.notNull().unique())
|
|
92
104
|
.addColumn("password_hash", "text", (col) => col.notNull())
|
|
@@ -97,11 +109,17 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
97
109
|
.addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
|
|
98
110
|
.execute();
|
|
99
111
|
|
|
100
|
-
await db.schema
|
|
112
|
+
await db.schema
|
|
113
|
+
.createIndex("idx_users_email")
|
|
114
|
+
.ifNotExists()
|
|
115
|
+
.on("users")
|
|
116
|
+
.column("email")
|
|
117
|
+
.execute();
|
|
101
118
|
|
|
102
119
|
// Options (key-value store)
|
|
103
120
|
await db.schema
|
|
104
121
|
.createTable("options")
|
|
122
|
+
.ifNotExists()
|
|
105
123
|
.addColumn("name", "text", (col) => col.primaryKey())
|
|
106
124
|
.addColumn("value", "text", (col) => col.notNull())
|
|
107
125
|
.execute();
|
|
@@ -109,6 +127,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
109
127
|
// Audit logs (security events)
|
|
110
128
|
await db.schema
|
|
111
129
|
.createTable("audit_logs")
|
|
130
|
+
.ifNotExists()
|
|
112
131
|
.addColumn("id", "text", (col) => col.primaryKey())
|
|
113
132
|
.addColumn("timestamp", "text", (col) => col.defaultTo(currentTimestamp(db)))
|
|
114
133
|
.addColumn("actor_id", "text")
|
|
@@ -120,9 +139,24 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
120
139
|
.addColumn("status", "text")
|
|
121
140
|
.execute();
|
|
122
141
|
|
|
123
|
-
await db.schema
|
|
124
|
-
|
|
125
|
-
|
|
142
|
+
await db.schema
|
|
143
|
+
.createIndex("idx_audit_actor")
|
|
144
|
+
.ifNotExists()
|
|
145
|
+
.on("audit_logs")
|
|
146
|
+
.column("actor_id")
|
|
147
|
+
.execute();
|
|
148
|
+
await db.schema
|
|
149
|
+
.createIndex("idx_audit_action")
|
|
150
|
+
.ifNotExists()
|
|
151
|
+
.on("audit_logs")
|
|
152
|
+
.column("action")
|
|
153
|
+
.execute();
|
|
154
|
+
await db.schema
|
|
155
|
+
.createIndex("idx_audit_timestamp")
|
|
156
|
+
.ifNotExists()
|
|
157
|
+
.on("audit_logs")
|
|
158
|
+
.column("timestamp")
|
|
159
|
+
.execute();
|
|
126
160
|
}
|
|
127
161
|
|
|
128
162
|
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
@@ -27,10 +27,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
|
|
|
27
27
|
.execute();
|
|
28
28
|
|
|
29
29
|
// ── Device code polling tracking ─────────────────────────────────
|
|
30
|
-
await db.schema
|
|
31
|
-
.alterTable("_emdash_device_codes")
|
|
32
|
-
.addColumn("last_polled_at", "text")
|
|
33
|
-
.execute();
|
|
30
|
+
await db.schema.alterTable("_emdash_device_codes").addColumn("last_polled_at", "text").execute();
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
export async function down(db: Kysely<unknown>): Promise<void> {
|
package/src/mcp/server.ts
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* The handlers instance is passed per-request via authInfo on the transport.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
|
-
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
14
12
|
import type { Permission, RoleLevel } from "@emdash-cms/auth";
|
|
15
13
|
import { canActOnOwn, Role } from "@emdash-cms/auth";
|
|
14
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
16
16
|
import { z } from "zod";
|
|
17
17
|
|
|
18
18
|
import type { EmDashHandlers } from "../astro/types.js";
|
package/src/storage/local.ts
CHANGED
|
@@ -103,11 +103,7 @@ export class LocalStorage implements Storage {
|
|
|
103
103
|
size: buffer.length,
|
|
104
104
|
};
|
|
105
105
|
} catch (error) {
|
|
106
|
-
throw new EmDashStorageError(
|
|
107
|
-
`Failed to upload file: ${options.key}`,
|
|
108
|
-
"UPLOAD_FAILED",
|
|
109
|
-
error,
|
|
110
|
-
);
|
|
106
|
+
throw new EmDashStorageError(`Failed to upload file: ${options.key}`, "UPLOAD_FAILED", error);
|
|
111
107
|
}
|
|
112
108
|
}
|
|
113
109
|
|
package/src/storage/s3.ts
CHANGED
|
@@ -97,11 +97,7 @@ export class S3Storage implements Storage {
|
|
|
97
97
|
size: body.length,
|
|
98
98
|
};
|
|
99
99
|
} catch (error) {
|
|
100
|
-
throw new EmDashStorageError(
|
|
101
|
-
`Failed to upload file: ${options.key}`,
|
|
102
|
-
"UPLOAD_FAILED",
|
|
103
|
-
error,
|
|
104
|
-
);
|
|
100
|
+
throw new EmDashStorageError(`Failed to upload file: ${options.key}`, "UPLOAD_FAILED", error);
|
|
105
101
|
}
|
|
106
102
|
}
|
|
107
103
|
|
|
@@ -166,11 +162,7 @@ export class S3Storage implements Storage {
|
|
|
166
162
|
if (hasErrorName(error) && error.name === "NotFound") {
|
|
167
163
|
return false;
|
|
168
164
|
}
|
|
169
|
-
throw new EmDashStorageError(
|
|
170
|
-
`Failed to check file existence: ${key}`,
|
|
171
|
-
"HEAD_FAILED",
|
|
172
|
-
error,
|
|
173
|
-
);
|
|
165
|
+
throw new EmDashStorageError(`Failed to check file existence: ${key}`, "HEAD_FAILED", error);
|
|
174
166
|
}
|
|
175
167
|
}
|
|
176
168
|
|