@rmdes/indiekit-endpoint-activitypub 3.11.1 → 3.11.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.
@@ -67,7 +67,8 @@ export function createMastodonRouter({ collections, pluginOptions = {} }) {
67
67
 
68
68
  // ─── Body parsers ───────────────────────────────────────────────────────
69
69
  // Mastodon clients send JSON, form-urlencoded, and occasionally text/plain.
70
- // These must be applied before route handlers.
70
+ // Note: multipart/form-data is handled globally by express-fileupload
71
+ // (configured in Indiekit's express.js), so no multer needed here.
71
72
  router.use("/api", express.json());
72
73
  router.use("/api", express.urlencoded({ extended: true }));
73
74
  router.use("/oauth", express.json());
@@ -5,18 +5,16 @@
5
5
  * POST /api/v1/media — legacy upload (same as v2)
6
6
  * GET /api/v1/media/:id — get media attachment metadata
7
7
  * PUT /api/v1/media/:id — update media metadata (description/focus)
8
+ *
9
+ * File uploads are handled by express-fileupload (configured globally by
10
+ * Indiekit's express.js). Files arrive on req.files, NOT req.file (multer).
8
11
  */
9
12
  import express from "express";
10
- import multer from "multer";
11
13
  import { ObjectId } from "mongodb";
12
14
  import { tokenRequired } from "../middleware/token-required.js";
13
15
  import { scopeRequired } from "../middleware/scope-required.js";
14
16
 
15
17
  const router = express.Router(); // eslint-disable-line new-cap
16
- const upload = multer({
17
- storage: multer.memoryStorage(),
18
- limits: { fileSize: 40 * 1024 * 1024 },
19
- });
20
18
 
21
19
  /**
22
20
  * Determine Mastodon media type from MIME type.
@@ -54,6 +52,7 @@ function serializeMediaAttachment(doc) {
54
52
 
55
53
  /**
56
54
  * Upload file to the Micropub media endpoint.
55
+ * Accepts an express-fileupload file object (has .data Buffer, .mimetype, .name).
57
56
  * Returns the URL from the Location header.
58
57
  */
59
58
  async function uploadToMediaEndpoint(file, application, token) {
@@ -67,8 +66,8 @@ async function uploadToMediaEndpoint(file, application, token) {
67
66
  : new URL(mediaEndpoint, application.url).href;
68
67
 
69
68
  const formData = new FormData();
70
- const blob = new Blob([file.buffer], { type: file.mimetype });
71
- formData.append("file", blob, file.originalname);
69
+ const blob = new Blob([file.data], { type: file.mimetype });
70
+ formData.append("file", blob, file.name);
72
71
 
73
72
  const response = await fetch(mediaUrl, {
74
73
  method: "POST",
@@ -95,7 +94,6 @@ router.post(
95
94
  "/api/v2/media",
96
95
  tokenRequired,
97
96
  scopeRequired("write", "write:media"),
98
- upload.single("file"),
99
97
  async (req, res, next) => {
100
98
  try {
101
99
  const { application } = req.app.locals;
@@ -103,7 +101,8 @@ router.post(
103
101
  const token =
104
102
  req.session?.access_token || req.mastodonToken?.accessToken;
105
103
 
106
- if (!req.file) {
104
+ const file = req.files?.file;
105
+ if (!file) {
107
106
  return res.status(422).json({ error: "No file provided" });
108
107
  }
109
108
 
@@ -113,17 +112,13 @@ router.post(
113
112
  .json({ error: "Authentication required for media upload" });
114
113
  }
115
114
 
116
- const fileUrl = await uploadToMediaEndpoint(
117
- req.file,
118
- application,
119
- token,
120
- );
115
+ const fileUrl = await uploadToMediaEndpoint(file, application, token);
121
116
 
122
117
  const doc = {
123
118
  url: fileUrl,
124
119
  description: req.body.description || "",
125
120
  focus: req.body.focus || null,
126
- mimeType: req.file.mimetype,
121
+ mimeType: file.mimetype,
127
122
  createdAt: new Date(),
128
123
  };
129
124
 
@@ -143,7 +138,6 @@ router.post(
143
138
  "/api/v1/media",
144
139
  tokenRequired,
145
140
  scopeRequired("write", "write:media"),
146
- upload.single("file"),
147
141
  async (req, res, next) => {
148
142
  try {
149
143
  const { application } = req.app.locals;
@@ -151,7 +145,8 @@ router.post(
151
145
  const token =
152
146
  req.session?.access_token || req.mastodonToken?.accessToken;
153
147
 
154
- if (!req.file) {
148
+ const file = req.files?.file;
149
+ if (!file) {
155
150
  return res.status(422).json({ error: "No file provided" });
156
151
  }
157
152
 
@@ -161,17 +156,13 @@ router.post(
161
156
  .json({ error: "Authentication required for media upload" });
162
157
  }
163
158
 
164
- const fileUrl = await uploadToMediaEndpoint(
165
- req.file,
166
- application,
167
- token,
168
- );
159
+ const fileUrl = await uploadToMediaEndpoint(file, application, token);
169
160
 
170
161
  const doc = {
171
162
  url: fileUrl,
172
163
  description: req.body.description || "",
173
164
  focus: req.body.focus || null,
174
- mimeType: req.file.mimetype,
165
+ mimeType: file.mimetype,
175
166
  createdAt: new Date(),
176
167
  };
177
168
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rmdes/indiekit-endpoint-activitypub",
3
- "version": "3.11.1",
3
+ "version": "3.11.3",
4
4
  "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
5
5
  "keywords": [
6
6
  "indiekit",
@@ -45,7 +45,6 @@
45
45
  "express": "^5.0.0",
46
46
  "express-rate-limit": "^7.5.1",
47
47
  "ioredis": "^5.9.3",
48
- "multer": "^2.1.1",
49
48
  "sanitize-html": "^2.13.1",
50
49
  "unfurl.js": "^6.4.0"
51
50
  },