emdash 0.40.0 → 0.40.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/api/route-utils.mjs +6 -6
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/{api-cFFZpyS0.mjs → api-CuyNEHZG.mjs} +3 -3
- package/dist/{api-cFFZpyS0.mjs.map → api-CuyNEHZG.mjs.map} +1 -1
- package/dist/{apply-CoT603H3.mjs → apply-npY1TAhG.mjs} +237 -34
- package/dist/apply-npY1TAhG.mjs.map +1 -0
- package/dist/astro/index.d.mts +3 -3
- package/dist/astro/index.mjs +9 -9
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +3 -3
- package/dist/astro/middleware/redirect.mjs +1 -1
- package/dist/astro/middleware.d.mts +3 -3
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +19 -18
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +2 -2
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +2 -2
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +11 -11
- package/dist/astro/routes/api/admin/plugins/index.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +11 -11
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +12 -12
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/updates.mjs +8 -8
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +8 -8
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +8 -8
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/capabilities.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/exports/index.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/imports/index.mjs +3 -3
- package/dist/astro/routes/api/dashboard.mjs +2 -2
- package/dist/astro/routes/api/health.mjs +1 -1
- package/dist/astro/routes/api/import/probe.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +3 -3
- package/dist/astro/routes/api/import/wordpress/media.d.mts +3 -3
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +3 -3
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +3 -3
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +3 -3
- package/dist/astro/routes/api/manifest.mjs +1 -1
- package/dist/astro/routes/api/mcp.mjs +13 -33
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +1 -1
- package/dist/astro/routes/api/media/_id_/upload.mjs +1 -1
- package/dist/astro/routes/api/media/_id_/usage.mjs +2 -2
- package/dist/astro/routes/api/media/_id_.mjs +2 -2
- package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +1 -1
- package/dist/astro/routes/api/media/upload-url.mjs +1 -1
- package/dist/astro/routes/api/media.mjs +2 -2
- package/dist/astro/routes/api/redirects/404s/index.mjs +2 -2
- package/dist/astro/routes/api/redirects/404s/summary.mjs +2 -2
- package/dist/astro/routes/api/redirects/_id_.mjs +2 -2
- package/dist/astro/routes/api/redirects/index.mjs +2 -2
- package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +8 -8
- package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +8 -8
- package/dist/astro/routes/api/schema/block-types/index.mjs +8 -8
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +8 -8
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +8 -8
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +8 -8
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +8 -8
- package/dist/astro/routes/api/schema/collections/index.mjs +8 -8
- package/dist/astro/routes/api/schema/collections/reorder.mjs +8 -8
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +8 -8
- package/dist/astro/routes/api/schema/orphans/index.mjs +8 -8
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +2 -2
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +2 -2
- package/dist/astro/routes/api/settings/backups/export.mjs +2 -2
- package/dist/astro/routes/api/settings/backups/index.mjs +2 -2
- package/dist/astro/routes/api/settings.mjs +3 -3
- package/dist/astro/routes/api/setup/dev-bypass.mjs +4 -4
- package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
- package/dist/astro/routes/api/setup/index.mjs +35 -10
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/snapshot.mjs +2 -2
- package/dist/astro/routes/api/snapshot.mjs.map +1 -1
- package/dist/astro/routes/robots.txt.mjs +2 -2
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +2 -2
- package/dist/astro/routes/sitemap.xml.mjs +2 -2
- package/dist/astro/types.d.mts +7 -3
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/{backup-CBu0LrXf.mjs → backup-BQRj3afm.mjs} +3 -3
- package/dist/{backup-CBu0LrXf.mjs.map → backup-BQRj3afm.mjs.map} +1 -1
- package/dist/cli/index.mjs +6 -6
- package/dist/client/index.d.mts +14 -14
- package/dist/{config-5ii2haYu.d.mts → config-BjEm_3xL.d.mts} +25 -16
- package/dist/config-BjEm_3xL.d.mts.map +1 -0
- package/dist/{context-BeGccdUX.mjs → context-BV_7t-Ua.mjs} +6 -6
- package/dist/{context-BeGccdUX.mjs.map → context-BV_7t-Ua.mjs.map} +1 -1
- package/dist/{dashboard-DjrB-xxZ.mjs → dashboard-BP-iJqpd.mjs} +2 -2
- package/dist/{dashboard-DjrB-xxZ.mjs.map → dashboard-BP-iJqpd.mjs.map} +1 -1
- package/dist/db/libsql-migrations.mjs +2 -2
- package/dist/db/postgres-migrations.mjs +2 -2
- package/dist/db/sqlite-migrations.mjs +2 -2
- package/dist/{direct-executor-BmuFJJZV.mjs → direct-executor-D2lNadwo.mjs} +2 -2
- package/dist/{direct-executor-BmuFJJZV.mjs.map → direct-executor-D2lNadwo.mjs.map} +1 -1
- package/dist/{emdash-runtime-DAjghyEG.mjs → emdash-runtime-CtfnZmPi.mjs} +56 -56
- package/dist/emdash-runtime-CtfnZmPi.mjs.map +1 -0
- package/dist/{entry-lock-DVhCt49A.d.mts → entry-lock-Cf5OoIgN.d.mts} +18 -18
- package/dist/{entry-lock-DVhCt49A.d.mts.map → entry-lock-Cf5OoIgN.d.mts.map} +1 -1
- package/dist/{hreflang-DMFBL2eb.mjs → hreflang-CbVI4paR.mjs} +2 -2
- package/dist/{hreflang-DMFBL2eb.mjs.map → hreflang-CbVI4paR.mjs.map} +1 -1
- package/dist/{identity-IyNWwXr6.mjs → identity-Be5kzutJ.mjs} +2 -2
- package/dist/{identity-IyNWwXr6.mjs.map → identity-Be5kzutJ.mjs.map} +1 -1
- package/dist/{import-C3JZplWq.mjs → import-YzfKCaco.mjs} +2 -2
- package/dist/{import-C3JZplWq.mjs.map → import-YzfKCaco.mjs.map} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +16 -16
- package/dist/{manifest-builder-B8zR-73J.mjs → manifest-builder-BmSAOOEF.mjs} +2 -2
- package/dist/{manifest-builder-B8zR-73J.mjs.map → manifest-builder-BmSAOOEF.mjs.map} +1 -1
- package/dist/media/local-runtime.d.mts +3 -3
- package/dist/media/local-runtime.mjs +3 -3
- package/dist/{media-Qp5S3eH3.mjs → media-CPXTbb1R.mjs} +20 -2
- package/dist/media-CPXTbb1R.mjs.map +1 -0
- package/dist/{media-h7tOiDLj.mjs → media-JXRWDhw3.mjs} +77 -4
- package/dist/media-JXRWDhw3.mjs.map +1 -0
- package/dist/{media-usage-My-Vi-ex.mjs → media-usage-De-zeR9E.mjs} +2 -2
- package/dist/{media-usage-My-Vi-ex.mjs.map → media-usage-De-zeR9E.mjs.map} +1 -1
- package/dist/{menus-TsSGmSR4.mjs → menus-Cm68rsAq.mjs} +4 -4
- package/dist/{menus-TsSGmSR4.mjs.map → menus-Cm68rsAq.mjs.map} +1 -1
- package/dist/migrations/index.mjs +2 -2
- package/dist/page/index.mjs +2 -2
- package/dist/plugin-test-runtime.d.mts +3 -3
- package/dist/plugin-test-runtime.mjs +18 -18
- package/dist/plugin-utils.d.mts +3 -3
- package/dist/plugins/adapt-sandbox-entry.d.mts +3 -3
- package/dist/plugins/host.d.mts +1 -1
- package/dist/plugins/host.mjs +6 -6
- package/dist/{redirect-iJf5fltD.mjs → redirect-B29UjdUn.mjs} +10 -14
- package/dist/redirect-B29UjdUn.mjs.map +1 -0
- package/dist/{redirects-CYu1u1aK.mjs → redirects-Ca2MPfEG.mjs} +2 -2
- package/dist/{redirects-CYu1u1aK.mjs.map → redirects-Ca2MPfEG.mjs.map} +1 -1
- package/dist/{routes-CUsM40Cc.mjs → routes-vrR95WR6.mjs} +2 -2
- package/dist/{routes-CUsM40Cc.mjs.map → routes-vrR95WR6.mjs.map} +1 -1
- package/dist/runtime.d.mts +3 -3
- package/dist/seed/index.mjs +4 -4
- package/dist/seo/index.mjs +3 -3
- package/dist/{settings-CgjRWGW9.mjs → settings-B4vDl1fK.mjs} +2 -2
- package/dist/{settings-CgjRWGW9.mjs.map → settings-B4vDl1fK.mjs.map} +1 -1
- package/dist/{settings-2xNYr90o.mjs → settings-Dyj6v8C4.mjs} +2 -2
- package/dist/{settings-2xNYr90o.mjs.map → settings-Dyj6v8C4.mjs.map} +1 -1
- package/dist/{snapshot-CugwUqKQ.mjs → snapshot-PawoX-WG.mjs} +180 -3
- package/dist/snapshot-PawoX-WG.mjs.map +1 -0
- package/dist/{storage-query-Bdv7A62k.d.mts → storage-query-FXJH5pI8.d.mts} +6 -1
- package/dist/storage-query-FXJH5pI8.d.mts.map +1 -0
- package/dist/{transfer-BhUCrgDc.mjs → transfer-DgeCvHnj.mjs} +4 -4
- package/dist/{transfer-BhUCrgDc.mjs.map → transfer-DgeCvHnj.mjs.map} +1 -1
- package/dist/validate-CM79QXYE.d.mts.map +1 -1
- package/dist/version-DXsxRrob.mjs +7 -0
- package/dist/{version-DUQDHgrf.mjs.map → version-DXsxRrob.mjs.map} +1 -1
- package/package.json +5 -5
- package/src/api/handlers/index.ts +1 -0
- package/src/api/handlers/media-upload.ts +17 -71
- package/src/api/handlers/media.ts +97 -3
- package/src/api/handlers/snapshot.ts +257 -3
- package/src/astro/integration/vite-config.ts +10 -4
- package/src/astro/middleware.ts +1 -0
- package/src/astro/routes/api/setup/index.ts +66 -23
- package/src/astro/routes/api/snapshot.ts +2 -1
- package/src/astro/types.ts +5 -0
- package/src/cleanup.ts +10 -0
- package/src/components/Columns.astro +3 -1
- package/src/components/Cover.astro +3 -1
- package/src/database/repositories/media.ts +40 -1
- package/src/database/repositories/redirect.ts +17 -34
- package/src/emdash-runtime.ts +28 -0
- package/src/index.ts +1 -0
- package/src/mcp/server.ts +13 -48
- package/src/seed/apply.ts +322 -41
- package/dist/apply-CoT603H3.mjs.map +0 -1
- package/dist/config-5ii2haYu.d.mts.map +0 -1
- package/dist/emdash-runtime-DAjghyEG.mjs.map +0 -1
- package/dist/media-Qp5S3eH3.mjs.map +0 -1
- package/dist/media-h7tOiDLj.mjs.map +0 -1
- package/dist/redirect-iJf5fltD.mjs.map +0 -1
- package/dist/snapshot-CugwUqKQ.mjs.map +0 -1
- package/dist/storage-query-Bdv7A62k.d.mts.map +0 -1
- package/dist/version-DUQDHgrf.mjs +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as InvalidCursorError } from "./types-BkUg2yHx.mjs";
|
|
2
2
|
import { t as isValidFocalPointUpdate } from "./focal-point-Gr34o-4o.mjs";
|
|
3
|
-
import { t as MediaRepository } from "./media-
|
|
3
|
+
import { t as MediaRepository } from "./media-CPXTbb1R.mjs";
|
|
4
4
|
import { t as removeUploadAttempt } from "./upload-attempts-B68ZGNu9.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/api/handlers/media.ts
|
|
@@ -109,6 +109,76 @@ async function handleMediaCreate(db, input) {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
+
* Confirm an upload minted by the signed upload URL endpoint.
|
|
113
|
+
*
|
|
114
|
+
* The storage key must belong to a pending media row created for the same
|
|
115
|
+
* user; arbitrary keys never reach storage this way.
|
|
116
|
+
*/
|
|
117
|
+
async function handleMediaRegisterUpload(db, storage, input) {
|
|
118
|
+
const invalidKey = {
|
|
119
|
+
success: false,
|
|
120
|
+
error: {
|
|
121
|
+
code: "INVALID_STORAGE_KEY",
|
|
122
|
+
message: "storageKey does not match a pending upload created for this user; request a signed upload URL first"
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
try {
|
|
126
|
+
const repo = new MediaRepository(db);
|
|
127
|
+
const pending = await repo.findPendingByStorageKey(input.storageKey);
|
|
128
|
+
if (!pending) return invalidKey;
|
|
129
|
+
if ((pending.authorId ?? null) !== (input.authorId ?? null)) return invalidKey;
|
|
130
|
+
if (pending.size === null) return {
|
|
131
|
+
success: false,
|
|
132
|
+
error: {
|
|
133
|
+
code: "INVALID_STATE",
|
|
134
|
+
message: "Pending upload has no expected size"
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
if (!await storage.exists(input.storageKey)) return {
|
|
138
|
+
success: false,
|
|
139
|
+
error: {
|
|
140
|
+
code: "FILE_NOT_FOUND",
|
|
141
|
+
message: "File was not uploaded to storage"
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const storedFile = await storage.download(input.storageKey);
|
|
145
|
+
try {
|
|
146
|
+
if (storedFile.size !== pending.size) return {
|
|
147
|
+
success: false,
|
|
148
|
+
error: {
|
|
149
|
+
code: "UPLOAD_SIZE_MISMATCH",
|
|
150
|
+
message: "Stored file size does not match the pending upload"
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
} finally {
|
|
154
|
+
try {
|
|
155
|
+
await storedFile.body.cancel();
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error("[media] upload confirmation cancellation failed:", error);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const item = await repo.confirmUpload(pending.id, void 0, input.storageKey);
|
|
161
|
+
if (!item) return invalidKey;
|
|
162
|
+
try {
|
|
163
|
+
await repo.deleteUploadAttempt(input.storageKey);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error("[media] upload attempt cleanup failed:", error);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
success: true,
|
|
169
|
+
data: { item }
|
|
170
|
+
};
|
|
171
|
+
} catch {
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
error: {
|
|
175
|
+
code: "MEDIA_REGISTER_ERROR",
|
|
176
|
+
message: "Failed to register the upload"
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
112
182
|
* Update media metadata
|
|
113
183
|
*/
|
|
114
184
|
async function handleMediaUpdate(db, id, input) {
|
|
@@ -197,12 +267,15 @@ async function handleMediaDelete(db, id, storage) {
|
|
|
197
267
|
if (storage) await repo.trackStorageKeyForCleanup(media.id, media.storageKey);
|
|
198
268
|
const storageKey = await repo.deleteWithStorageKey(id);
|
|
199
269
|
if (!storageKey) return notFound;
|
|
270
|
+
let storageDeleted = false;
|
|
271
|
+
if (storage) if (await repo.isStorageKeyReferenced(storageKey)) await repo.deleteUploadAttempt(storageKey);
|
|
272
|
+
else storageDeleted = await removeUploadAttempt(storage, repo, storageKey, { allowUntracked: true });
|
|
200
273
|
return {
|
|
201
274
|
success: true,
|
|
202
275
|
data: {
|
|
203
276
|
deleted: true,
|
|
204
277
|
storageKey,
|
|
205
|
-
storageDeleted
|
|
278
|
+
storageDeleted
|
|
206
279
|
}
|
|
207
280
|
};
|
|
208
281
|
} catch {
|
|
@@ -217,5 +290,5 @@ async function handleMediaDelete(db, id, storage) {
|
|
|
217
290
|
}
|
|
218
291
|
|
|
219
292
|
//#endregion
|
|
220
|
-
export {
|
|
221
|
-
//# sourceMappingURL=media-
|
|
293
|
+
export { handleMediaRegisterUpload as a, handleMediaList as i, handleMediaDelete as n, handleMediaReplaceMetadata as o, handleMediaGet as r, handleMediaUpdate as s, handleMediaCreate as t };
|
|
294
|
+
//# sourceMappingURL=media-JXRWDhw3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-JXRWDhw3.mjs","names":[],"sources":["../src/api/handlers/media.ts"],"sourcesContent":["/**\n * Media CRUD handlers\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { MediaRepository, type MediaItem } from \"../../database/repositories/media.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { isValidFocalPointUpdate, type FocalPointUpdate } from \"../../media/focal-point.js\";\nimport { removeUploadAttempt } from \"../../media/upload-attempts.js\";\nimport type { Storage } from \"../../storage/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\nconst FOREIGN_KEY_VIOLATION_RE = /foreign key constraint failed/i;\n\nexport interface MediaListResponse {\n\titems: MediaItem[];\n\tnextCursor?: string;\n\ttotalCount?: number;\n}\n\nexport interface MediaResponse {\n\titem: MediaItem;\n}\n\n/**\n * List media items\n */\nexport async function handleMediaList(\n\tdb: Kysely<Database>,\n\tparams: {\n\t\tcursor?: string;\n\t\tpage?: number;\n\t\tlimit?: number;\n\t\tmimeType?: string | readonly string[];\n\t\tq?: string;\n\t\tfolderId?: string | null;\n\t},\n): Promise<ApiResult<MediaListResponse>> {\n\ttry {\n\t\tif (params.page !== undefined) {\n\t\t\tconst limit = Math.min(params.limit || 50, 100);\n\t\t\tconst offset = (params.page - 1) * limit;\n\t\t\tif (\n\t\t\t\tparams.cursor !== undefined ||\n\t\t\t\t!Number.isSafeInteger(params.page) ||\n\t\t\t\tparams.page < 1 ||\n\t\t\t\t!Number.isSafeInteger(offset)\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: { code: \"VALIDATION_ERROR\", message: \"Invalid media page\" },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst repo = new MediaRepository(db);\n\t\t\tconst result = await repo.findPage({\n\t\t\t\tpage: params.page,\n\t\t\t\tlimit,\n\t\t\t\tmimeType: params.mimeType,\n\t\t\t\tq: params.q,\n\t\t\t\tfolderId: params.folderId,\n\t\t\t});\n\t\t\treturn { success: true, data: result };\n\t\t}\n\n\t\tconst repo = new MediaRepository(db);\n\t\tconst result = await repo.findMany({\n\t\t\tcursor: params.cursor,\n\t\t\tlimit: Math.min(params.limit || 50, 100),\n\t\t\tmimeType: params.mimeType,\n\t\t\tq: params.q,\n\t\t\tfolderId: params.folderId,\n\t\t});\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\titems: result.items,\n\t\t\t\tnextCursor: result.nextCursor,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CURSOR\", message: error.message },\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_LIST_ERROR\",\n\t\t\t\tmessage: \"Failed to list media\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Get single media item\n */\nexport async function handleMediaGet(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<MediaResponse>> {\n\ttry {\n\t\tconst repo = new MediaRepository(db);\n\t\tconst item = await repo.findById(id);\n\n\t\tif (!item) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\tmessage: `Media item not found: ${id}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { item },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_GET_ERROR\",\n\t\t\t\tmessage: \"Failed to get media\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Create media item (after file upload)\n */\nexport async function handleMediaCreate(\n\tdb: Kysely<Database>,\n\tinput: {\n\t\tfilename: string;\n\t\tmimeType: string;\n\t\tsize?: number;\n\t\twidth?: number;\n\t\theight?: number;\n\t\talt?: string;\n\t\tstorageKey: string;\n\t\tcontentHash?: string;\n\t\tblurhash?: string;\n\t\tdominantColor?: string;\n\t\tauthorId?: string;\n\t\tfolderId?: string | null;\n\t},\n): Promise<ApiResult<MediaResponse>> {\n\ttry {\n\t\tconst repo = new MediaRepository(db);\n\t\tconst item = await repo.create(input);\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { item },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_CREATE_ERROR\",\n\t\t\t\tmessage: \"Failed to create media\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Confirm an upload minted by the signed upload URL endpoint.\n *\n * The storage key must belong to a pending media row created for the same\n * user; arbitrary keys never reach storage this way.\n */\nexport async function handleMediaRegisterUpload(\n\tdb: Kysely<Database>,\n\tstorage: Storage,\n\tinput: {\n\t\tstorageKey: string;\n\t\tauthorId?: string;\n\t},\n): Promise<ApiResult<MediaResponse>> {\n\tconst invalidKey: ApiResult<never> = {\n\t\tsuccess: false,\n\t\terror: {\n\t\t\tcode: \"INVALID_STORAGE_KEY\",\n\t\t\tmessage:\n\t\t\t\t\"storageKey does not match a pending upload created for this user; request a signed upload URL first\",\n\t\t},\n\t};\n\ttry {\n\t\tconst repo = new MediaRepository(db);\n\t\tconst pending = await repo.findPendingByStorageKey(input.storageKey);\n\t\tif (!pending) return invalidKey;\n\t\tif ((pending.authorId ?? null) !== (input.authorId ?? null)) return invalidKey;\n\t\tif (pending.size === null) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_STATE\",\n\t\t\t\t\tmessage: \"Pending upload has no expected size\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (!(await storage.exists(input.storageKey))) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"FILE_NOT_FOUND\", message: \"File was not uploaded to storage\" },\n\t\t\t};\n\t\t}\n\n\t\tconst storedFile = await storage.download(input.storageKey);\n\t\ttry {\n\t\t\tif (storedFile.size !== pending.size) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"UPLOAD_SIZE_MISMATCH\",\n\t\t\t\t\t\tmessage: \"Stored file size does not match the pending upload\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tawait storedFile.body.cancel();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[media] upload confirmation cancellation failed:\", error);\n\t\t\t}\n\t\t}\n\n\t\tconst item = await repo.confirmUpload(pending.id, undefined, input.storageKey);\n\t\tif (!item) return invalidKey;\n\t\ttry {\n\t\t\tawait repo.deleteUploadAttempt(input.storageKey);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[media] upload attempt cleanup failed:\", error);\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { item },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_REGISTER_ERROR\",\n\t\t\t\tmessage: \"Failed to register the upload\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Update media metadata\n */\nexport async function handleMediaUpdate(\n\tdb: Kysely<Database>,\n\tid: string,\n\tinput: {\n\t\talt?: string;\n\t\tcaption?: string;\n\t\twidth?: number;\n\t\theight?: number;\n\t\tfolderId?: string | null;\n\t} & FocalPointUpdate,\n): Promise<ApiResult<MediaResponse>> {\n\tif (!isValidFocalPointUpdate(input)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\tmessage: \"focalX and focalY must both be valid numbers or both be null\",\n\t\t\t},\n\t\t};\n\t}\n\ttry {\n\t\tconst repo = new MediaRepository(db);\n\t\tconst item = await repo.update(id, input);\n\n\t\tif (!item) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\tmessage: `Media item not found: ${id}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { item },\n\t\t};\n\t} catch (error) {\n\t\tif (isForeignKeyViolation(error)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Media folder not found\" },\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_UPDATE_ERROR\",\n\t\t\t\tmessage: \"Failed to update media\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaReplaceMetadata(\n\tdb: Kysely<Database>,\n\tid: string,\n\texpectedStorageKey: string,\n\tinput: { size: number; width: number; height: number; contentHash: string },\n): Promise<ApiResult<MediaResponse>> {\n\ttry {\n\t\tconst item = await new MediaRepository(db).replaceReadyFile(id, expectedStorageKey, input);\n\t\tif (!item) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"MEDIA_REPLACE_METADATA_ERROR\",\n\t\t\t\t\tmessage: \"Failed to update replaced media metadata\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: { item } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_REPLACE_METADATA_ERROR\",\n\t\t\t\tmessage: \"Failed to update replaced media metadata\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nfunction isForeignKeyViolation(error: unknown): boolean {\n\tif (error && typeof error === \"object\") {\n\t\tif (\"code\" in error && error.code === \"23503\") return true;\n\t}\n\tconst message = error instanceof Error ? error.message : \"\";\n\tif (FOREIGN_KEY_VIOLATION_RE.test(message)) return true;\n\treturn Boolean(\n\t\terror && typeof error === \"object\" && \"cause\" in error && isForeignKeyViolation(error.cause),\n\t);\n}\n\n/** Delete a media item, then delete or queue cleanup of its stored object. */\nexport async function handleMediaDelete(\n\tdb: Kysely<Database>,\n\tid: string,\n\tstorage?: Storage | null,\n): Promise<ApiResult<{ deleted: true; storageKey: string; storageDeleted: boolean }>> {\n\ttry {\n\t\tconst repo = new MediaRepository(db);\n\t\tconst notFound: ApiResult<never> = {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"NOT_FOUND\", message: `Media item not found: ${id}` },\n\t\t};\n\n\t\tconst media = await repo.findById(id);\n\t\tif (!media) return notFound;\n\n\t\tif (storage) await repo.trackStorageKeyForCleanup(media.id, media.storageKey);\n\t\tconst storageKey = await repo.deleteWithStorageKey(id);\n\t\tif (!storageKey) return notFound;\n\n\t\tlet storageDeleted = false;\n\t\tif (storage) {\n\t\t\tif (await repo.isStorageKeyReferenced(storageKey)) {\n\t\t\t\t// A legacy or concurrently-created row still owns this object. Remove\n\t\t\t\t// the cleanup marker created above so scheduled cleanup cannot delete it.\n\t\t\t\tawait repo.deleteUploadAttempt(storageKey);\n\t\t\t} else {\n\t\t\t\tstorageDeleted = await removeUploadAttempt(storage, repo, storageKey, {\n\t\t\t\t\tallowUntracked: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { deleted: true, storageKey, storageDeleted },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"MEDIA_DELETE_ERROR\",\n\t\t\t\tmessage: \"Failed to delete media\",\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { u as isPostgres } from "./dialect-helpers-7_IqPdh9.mjs";
|
|
|
4
4
|
import { getRequestContext } from "./request-context.mjs";
|
|
5
5
|
import { i as InvalidCursorError } from "./types-BkUg2yHx.mjs";
|
|
6
6
|
import { t as withTransaction } from "./transaction-BcJO4Tmc.mjs";
|
|
7
|
-
import { t as MediaRepository } from "./media-
|
|
7
|
+
import { t as MediaRepository } from "./media-CPXTbb1R.mjs";
|
|
8
8
|
import { a as continueMediaUsageActivation, n as MediaUsageActivationVersionMismatchError, s as getMediaUsageActivationStatus, t as MEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION } from "./activation-LOkDM5WT.mjs";
|
|
9
9
|
import { B as CONTENT_MEDIA_USAGE_ADAPTER_ID, D as contentRefreshKey, G as jsonTextValues, K as CONTENT_SOURCE_SCHEMA_VERSION, R as buildContentMediaUsageFieldFingerprint, V as CONTENT_MEDIA_USAGE_COLLECTION_SCOPE, W as MediaUsageRepository, j as refreshContentMediaUsageForWorkBatch, z as loadContentMediaUsageFields } from "./block-type-registry-DUI_3KxT.mjs";
|
|
10
10
|
import { t as MediaUsageWorkRepository } from "./media-usage-work-C2OZLCAd.mjs";
|
|
@@ -1626,4 +1626,4 @@ function normalizeMediaUsageReferenceType(referenceType) {
|
|
|
1626
1626
|
|
|
1627
1627
|
//#endregion
|
|
1628
1628
|
export { handleMediaUsageSummaries as a, handleMediaUsageRepair as i, handleMediaUsageProgress as n, media_usage_exports as o, handleMediaUsageProgressAdvance as r, processMediaUsageWorkAfterWrite as s, handleMediaUsageDetails as t };
|
|
1629
|
-
//# sourceMappingURL=media-usage-
|
|
1629
|
+
//# sourceMappingURL=media-usage-De-zeR9E.mjs.map
|