diff --git a/package-lock.json b/package-lock.json index 3cfaec8fd..d23c957d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19664,7 +19664,6 @@ "lodash": "^4.17.21", "markdown-it": "^13.0.0", "microformats-parser": "^1.4.0", - "mongodb": "^4.1.1", "multer": "^1.4.5-lts", "newbase60": "^1.3.1", "turndown": "^7.1.1", @@ -20644,7 +20643,6 @@ "lodash": "^4.17.21", "markdown-it": "^13.0.0", "microformats-parser": "^1.4.0", - "mongodb": "^4.1.1", "multer": "^1.4.5-lts", "newbase60": "^1.3.1", "turndown": "^7.1.1", diff --git a/packages/endpoint-micropub/index.js b/packages/endpoint-micropub/index.js index 1aed44739..114216139 100644 --- a/packages/endpoint-micropub/index.js +++ b/packages/endpoint-micropub/index.js @@ -1,7 +1,7 @@ import express from "express"; import multer from "multer"; import { actionController } from "./lib/controllers/action.js"; -import { postsController } from "./lib/controllers/posts.js"; +import { queryController } from "./lib/controllers/query.js"; const defaults = { mountPath: "/micropub", @@ -17,24 +17,14 @@ export const MicropubEndpoint = class { this._router = express.Router(); // eslint-disable-line new-cap } - navigationItems(application) { - if (application.hasDatabase) { - return { - href: this.options.mountPath, - text: "micropub.title", - }; - } - } - get routes() { const router = this._router; const multipartParser = multer({ storage: multer.memoryStorage(), }); - router.get("/", postsController.posts); + router.get("/", queryController); router.post("/", multipartParser.any(), actionController); - router.get("/:id", postsController.post); return router; } diff --git a/packages/endpoint-micropub/lib/controllers/posts.js b/packages/endpoint-micropub/lib/controllers/posts.js deleted file mode 100644 index 6a7bff2e0..000000000 --- a/packages/endpoint-micropub/lib/controllers/posts.js +++ /dev/null @@ -1,116 +0,0 @@ -import httpError from "http-errors"; -import mongodb from "mongodb"; -import { getConfig, queryConfig } from "../config.js"; -import { getMf2Properties, jf2ToMf2, url2Mf2 } from "../mf2.js"; - -export const postsController = { - /** - * List previously published posts - * - * @param {object} request HTTP request - * @param {object} response HTTP response - * @param {Function} next Next middleware callback - * @returns {object} HTTP response - */ - async posts(request, response, next) { - try { - const { application, publication } = request.app.locals; - - if (!application.hasDatabase) { - throw new httpError.NotImplemented( - response.__("errors.noDatabase.content") - ); - } - - let { page, limit, offset } = request.query; - page = Number.parseInt(page, 10) || 1; - limit = Number.parseInt(limit, 10) || 40; - offset = Number.parseInt(offset, 10) || (page - 1) * limit; - - const posts = await publication.posts - .find() - .sort({ _id: -1 }) - .skip(offset) - .limit(limit) - .toArray(); - - if (request.accepts("html")) { - response.render("posts", { - title: response.__("micropub.posts.title"), - posts, - page, - limit, - count: await publication.posts.countDocuments(), - parentUrl: request.baseUrl + request.path, - }); - } else { - let { filter, properties, q, url } = request.query; - const config = getConfig(application, publication); - const items = posts.map((post) => jf2ToMf2(post.properties)); - - if (!q) { - throw new httpError.BadRequest("Invalid query"); - } - - // `category` param is used to query `categories` configuration property - q = q === "category" ? "categories" : q; - - switch (q) { - case "config": - return response.json(config); - - case "source": - // Return mf2 for a given source URL - if (url) { - const mf2 = await url2Mf2(url); - return response.json(getMf2Properties(mf2, properties)); - } - - // Return mf2 for previously published posts - return response.json({ items }); - - default: - // Query configuration value (can be filtered, limited and offset) - if (config[q]) { - return response.json({ - [q]: queryConfig(config[q], { filter, limit, offset }), - }); - } - - throw new httpError.NotImplemented(`Unsupported parameter: ${q}`); - } - } - } catch (error) { - next(error); - } - }, - - /** - * View previously published post - * - * @param {object} request HTTP request - * @param {object} response HTTP response - * @param {Function} next Next middleware callback - * @returns {object} HTTP response - */ - async post(request, response, next) { - try { - const { publication } = request.app.locals; - const { id } = request.params; - const post = await publication.posts.findOne({ - _id: new mongodb.ObjectId(id), - }); - - if (!post) { - throw new httpError.NotFound("No post was found with this UUID"); - } - - response.render("post", { - parent: response.__("micropub.posts.title"), - post, - }); - } catch (error) { - next(error); - } - }, -}; diff --git a/packages/endpoint-micropub/lib/controllers/query.js b/packages/endpoint-micropub/lib/controllers/query.js new file mode 100644 index 000000000..35dcd3754 --- /dev/null +++ b/packages/endpoint-micropub/lib/controllers/query.js @@ -0,0 +1,74 @@ +import httpError from "http-errors"; +import { getConfig, queryConfig } from "../config.js"; +import { getMf2Properties, jf2ToMf2, url2Mf2 } from "../mf2.js"; + +/** + * Query previously published posts + * + * @param {object} request HTTP request + * @param {object} response HTTP response + * @param {Function} next Next middleware callback + * @returns {object} HTTP response + */ +export const queryController = async (request, response, next) => { + const { application, publication } = request.app.locals; + + try { + if (!application.hasDatabase) { + throw new httpError.NotImplemented( + response.__("errors.noDatabase.content") + ); + } + + const config = getConfig(application, publication); + + let { page, limit, offset } = request.query; + page = Number.parseInt(page, 10) || 1; + limit = Number.parseInt(limit, 10) || 40; + offset = Number.parseInt(offset, 10) || (page - 1) * limit; + + const posts = await publication.posts + .find() + .sort({ _id: -1 }) + .skip(offset) + .limit(limit) + .toArray(); + + let { filter, properties, q, url } = request.query; + if (!q) { + throw new httpError.BadRequest("Invalid query"); + } + + // `category` param is used to query `categories` configuration property + q = q === "category" ? "categories" : q; + + switch (q) { + case "config": + return response.json(config); + + case "source": + // Return mf2 for a given source URL + if (url) { + const mf2 = await url2Mf2(url); + return response.json(getMf2Properties(mf2, properties)); + } + + // Return mf2 for previously published posts + return response.json({ + items: posts.map((post) => jf2ToMf2(post.properties)), + }); + + default: + // Query configuration value (can be filtered, limited and offset) + if (config[q]) { + return response.json({ + [q]: queryConfig(config[q], { filter, limit, offset }), + }); + } + + throw new httpError.NotImplemented(`Unsupported parameter: ${q}`); + } + } catch (error) { + next(error); + } +}; diff --git a/packages/endpoint-micropub/locales/de.json b/packages/endpoint-micropub/locales/de.json deleted file mode 100644 index 110d92ef9..000000000 --- a/packages/endpoint-micropub/locales/de.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "posts": { - "none": "Keine Beiträge", - "title": "Veröffentlichte Beiträge" - }, - "properties": "Eigenschaften", - "title": "Beiträge" - } -} \ No newline at end of file diff --git a/packages/endpoint-micropub/locales/en.json b/packages/endpoint-micropub/locales/en.json deleted file mode 100644 index fc0f6c9b4..000000000 --- a/packages/endpoint-micropub/locales/en.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "title": "Posts", - "properties": "Properties", - "posts": { - "title": "Published posts", - "none": "No posts" - } - } -} diff --git a/packages/endpoint-micropub/locales/es.json b/packages/endpoint-micropub/locales/es.json deleted file mode 100644 index d42d895b1..000000000 --- a/packages/endpoint-micropub/locales/es.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "posts": { - "none": "No hay publicaciones", - "title": "Publicaciones publicadas" - }, - "properties": "Propiedades", - "title": "Publicaciones" - } -} \ No newline at end of file diff --git a/packages/endpoint-micropub/locales/fr.json b/packages/endpoint-micropub/locales/fr.json deleted file mode 100644 index cbbfeee47..000000000 --- a/packages/endpoint-micropub/locales/fr.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "posts": { - "none": "Pas d'articles", - "title": "Articles publiés" - }, - "properties": "Propriétés", - "title": "Articles" - } -} \ No newline at end of file diff --git a/packages/endpoint-micropub/locales/id.json b/packages/endpoint-micropub/locales/id.json deleted file mode 100644 index 0e1993b31..000000000 --- a/packages/endpoint-micropub/locales/id.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "posts": { - "none": "Tidak ada postingan", - "title": "Postingan yang diterbitkan" - }, - "properties": "Properti", - "title": "Postingan" - } -} \ No newline at end of file diff --git a/packages/endpoint-micropub/locales/nl.json b/packages/endpoint-micropub/locales/nl.json deleted file mode 100644 index 49c291d57..000000000 --- a/packages/endpoint-micropub/locales/nl.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "posts": { - "none": "Geen posts", - "title": "Gepubliceerde berichten" - }, - "properties": "Eigenschappen", - "title": "Berichten" - } -} \ No newline at end of file diff --git a/packages/endpoint-micropub/locales/pt.json b/packages/endpoint-micropub/locales/pt.json deleted file mode 100644 index 0f533f48c..000000000 --- a/packages/endpoint-micropub/locales/pt.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "micropub": { - "posts": { - "none": "Nenhuma postagem", - "title": "Postagens publicadas" - }, - "properties": "Propriedades", - "title": "Postagens" - } -} \ No newline at end of file diff --git a/packages/endpoint-micropub/package.json b/packages/endpoint-micropub/package.json index 91cd12dd5..16fe647a6 100644 --- a/packages/endpoint-micropub/package.json +++ b/packages/endpoint-micropub/package.json @@ -43,7 +43,6 @@ "lodash": "^4.17.21", "markdown-it": "^13.0.0", "microformats-parser": "^1.4.0", - "mongodb": "^4.1.1", "multer": "^1.4.5-lts", "newbase60": "^1.3.1", "turndown": "^7.1.1", diff --git a/packages/endpoint-micropub/tests/integration/200-posts-list.js b/packages/endpoint-micropub/tests/integration/200-posts-list.js deleted file mode 100644 index 359826688..000000000 --- a/packages/endpoint-micropub/tests/integration/200-posts-list.js +++ /dev/null @@ -1,17 +0,0 @@ -import test from "ava"; -import { JSDOM } from "jsdom"; -import { testServer } from "@indiekit-test/server"; -import { cookie } from "@indiekit-test/session"; - -test("Returns list of previously uploaded files", async (t) => { - const request = await testServer(); - const response = await request.get("/micropub").set("cookie", [cookie]); - const dom = new JSDOM(response.text); - - const result = dom.window.document; - - t.is( - result.querySelector("title").textContent, - "Published posts - Test configuration" - ); -}); diff --git a/packages/endpoint-micropub/tests/integration/200-posts-view.js b/packages/endpoint-micropub/tests/integration/200-posts-view.js deleted file mode 100644 index dc2726c7f..000000000 --- a/packages/endpoint-micropub/tests/integration/200-posts-view.js +++ /dev/null @@ -1,38 +0,0 @@ -import process from "node:process"; -import test from "ava"; -import nock from "nock"; -import { JSDOM } from "jsdom"; -import { testServer } from "@indiekit-test/server"; - -test("Views previously uploaded file", async (t) => { - nock("https://api.github.com") - .put((uri) => uri.includes("foobar.md")) - .reply(200); - - // Create post - const request = await testServer(); - await request - .post("/micropub") - .auth(process.env.TEST_TOKEN, { type: "bearer" }) - .set("accept", "application/json") - .send("h=entry") - .send("name=Foobar"); - - // Get post data by parsing list of posts and getting values from link - const postsResponse = await request.get("/micropub"); - const postsDom = new JSDOM(postsResponse.text); - const postLink = postsDom.window.document.querySelector(".file-list a"); - const postName = postLink.textContent; - const postId = postLink.href.split("/").pop(); - - // Visit post page - const postResponse = await request.get(`/micropub/${postId}`); - const postDom = new JSDOM(postResponse.text); - - const result = postDom.window.document; - - t.is( - result.querySelector("title").textContent, - `${postName} - Test configuration` - ); -}); diff --git a/packages/endpoint-micropub/tests/integration/404-posts-view.js b/packages/endpoint-micropub/tests/integration/404-posts-view.js deleted file mode 100644 index f3ddb50cf..000000000 --- a/packages/endpoint-micropub/tests/integration/404-posts-view.js +++ /dev/null @@ -1,14 +0,0 @@ -import process from "node:process"; -import test from "ava"; -import { testServer } from "@indiekit-test/server"; - -test("Returns 404 if can’t find previously published post", async (t) => { - const request = await testServer(); - - const result = await request - .get("/micropub/5ffcc8025c561a7bf53bd6e8") - .auth(process.env.TEST_TOKEN, { type: "bearer" }); - - t.is(result.statusCode, 404); - t.true(result.text.includes("No post was found with this UUID")); -}); diff --git a/packages/endpoint-micropub/tests/integration/501-posts-list-no-database.js b/packages/endpoint-micropub/tests/integration/501-posts-list-no-database.js deleted file mode 100644 index 332fe8174..000000000 --- a/packages/endpoint-micropub/tests/integration/501-posts-list-no-database.js +++ /dev/null @@ -1,23 +0,0 @@ -import process from "node:process"; -import test from "ava"; -import { JSDOM } from "jsdom"; -import { testServer } from "@indiekit-test/server"; - -test("Returns list of previously uploaded files", async (t) => { - const request = await testServer({ useDatabase: false }); - const response = await request - .get("/micropub") - .auth(process.env.TEST_TOKEN, { type: "bearer" }); - const dom = new JSDOM(response.text); - - const result = dom.window.document; - - t.is( - result.querySelector("title").textContent, - "Not Implemented - Test configuration" - ); - t.is( - result.querySelector(".article__body p").textContent, - "This feature requires a database." - ); -}); diff --git a/packages/endpoint-micropub/views/post.njk b/packages/endpoint-micropub/views/post.njk deleted file mode 100644 index c2eff35de..000000000 --- a/packages/endpoint-micropub/views/post.njk +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "document.njk" %} - -{% set title = post.properties.name or post.properties["post-type"] | capitalize %} -{% set content = post.properties.content.html %} - -{% block content %} - {% if post.properties.audio %} - {% for item in post.properties.audio %} -