diff --git a/helpers/fixtures/index.js b/helpers/fixtures/index.js index a473b4b47..7f5b88347 100644 --- a/helpers/fixtures/index.js +++ b/helpers/fixtures/index.js @@ -3,8 +3,8 @@ import { fileURLToPath } from "node:url"; /** * @param {string} filename - Fixture’s file name - * @param {string} encoding - String encoding - * @returns {Promise|object} File contents + * @param {NodeJS.BufferEncoding} encoding - String encoding + * @returns {object} File contents */ export const getFixture = (filename, encoding = "utf8") => { const file = fileURLToPath(new URL(filename, import.meta.url)); diff --git a/helpers/store/index.js b/helpers/store/index.js index c9798bfde..d159bc380 100644 --- a/helpers/store/index.js +++ b/helpers/store/index.js @@ -26,11 +26,11 @@ export default class TestStore { } /** - * @private + * @access private * @param {string} path - Request path * @param {string} [method=GET] - Request method * @param {object} [body] - Request body - * @returns {Function} Store client interface + * @returns {Promise} Store client interface */ async #client(path, method = "GET", body) { const { baseUrl, user } = this.options; @@ -61,7 +61,7 @@ export default class TestStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File created */ async createFile(path, content, message) { await this.#client(path, "PUT", { content, message }); @@ -71,7 +71,7 @@ export default class TestStore { /** * Read file * @param {string} path - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File content */ async readFile(path) { const response = await this.#client(path); @@ -84,7 +84,7 @@ export default class TestStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File updated */ async updateFile(path, content, message) { await this.#client(path, "PATCH", { content, message }); @@ -95,7 +95,7 @@ export default class TestStore { * Delete file * @param {string} path - Path to file * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted */ async deleteFile(path, message) { await this.#client(path, "DELETE", { message }); diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 000000000..4c88dab2f --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "checkJs": true, + "module": "nodenext", + "resolveJsonModule": true, + "target": "es2021" + }, + "exclude": ["node_modules", "**/tests/**/*.js"], + "typeRoots": ["types", "./node_modules/@types"] +} diff --git a/package-lock.json b/package-lock.json index 2c153ffdd..8fc170fec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,10 @@ "@indiekit-test/session": "*", "@indiekit-test/store": "*", "@indiekit-test/token": "*", + "@types/cookie-session": "^2.0.44", + "@types/express": "^4.17.17", + "@types/express-fileupload": "^1.4.1", + "@types/lodash": "^4.14.195", "ava": "^5.0.0", "c8": "^7.8.0", "cookie-session": "^2.0.0", @@ -62,30 +66,39 @@ } }, "helpers/access-token": { + "name": "@indiekit-test/token", "license": "MIT" }, "helpers/config": { + "name": "@indiekit-test/config", "license": "MIT" }, "helpers/fixtures": { + "name": "@indiekit-test/fixtures", "license": "MIT" }, "helpers/frontend": { + "name": "@indiekit-test/frontend", "license": "MIT" }, "helpers/media-data": { + "name": "@indiekit-test/media-data", "license": "MIT" }, "helpers/mock-agent": { + "name": "@indiekit-test/mock-agent", "license": "MIT" }, "helpers/post-data": { + "name": "@indiekit-test/post-data", "license": "MIT" }, "helpers/publication": { + "name": "@indiekit-test/publication", "license": "MIT" }, "helpers/server": { + "name": "@indiekit-test/server", "license": "MIT", "dependencies": { "get-port": "^6.1.2" @@ -103,9 +116,11 @@ } }, "helpers/session": { + "name": "@indiekit-test/session", "license": "MIT" }, "helpers/store": { + "name": "@indiekit-test/store", "license": "MIT" }, "node_modules/@algolia/autocomplete-core": { @@ -4665,6 +4680,25 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/busboy": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.0.tgz", + "integrity": "sha512-ncOOhwmyFDW76c/Tuvv9MA9VGYUCn8blzyWmzYELcNGDb0WXWLSmFi7hJq25YdRBYJrmMBB5jZZwUjlJe9HCjQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -4676,6 +4710,25 @@ "@types/responselike": "^1.0.0" } }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-session": { + "version": "2.0.44", + "resolved": "https://registry.npmjs.org/@types/cookie-session/-/cookie-session-2.0.44.tgz", + "integrity": "sha512-3DheOZ41pql6raSIkqEPphJdhA2dX2bkS+s2Qacv8YMKkoCbAIEXbsDil7351ARzMqvfyDUGNeHGiRZveIzhqQ==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/keygrip": "*" + } + }, "node_modules/@types/eslint": { "version": "8.40.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.0.tgz", @@ -4702,6 +4755,40 @@ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-fileupload": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@types/express-fileupload/-/express-fileupload-1.4.1.tgz", + "integrity": "sha512-sbl865h1Sser6SF+efpw2F/+roGISj+PRIbMcGXbtzgJQCBAeeBmoSo7sPge/mBa22ymCHfFPtHFsag/wUxwfg==", + "dev": true, + "dependencies": { + "@types/busboy": "*", + "@types/express": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", @@ -4725,6 +4812,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", + "dev": true + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -4740,6 +4833,12 @@ "dev": true, "peer": true }, + "node_modules/@types/lodash": { + "version": "4.14.195", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", + "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "dev": true + }, "node_modules/@types/markdown-it": { "version": "12.2.3", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", @@ -4758,6 +4857,12 @@ "dev": true, "peer": true }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -4791,6 +4896,18 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -4804,6 +4921,26 @@ "@types/node": "*" } }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "dev": true, + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, "node_modules/@types/web-bluetooth": { "version": "0.0.17", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz", @@ -23267,6 +23404,7 @@ } }, "packages/endpoint-auth": { + "name": "@indiekit/endpoint-auth", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23283,6 +23421,7 @@ } }, "packages/endpoint-files": { + "name": "@indiekit/endpoint-files", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23296,6 +23435,7 @@ } }, "packages/endpoint-image": { + "name": "@indiekit/endpoint-image", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23308,6 +23448,7 @@ } }, "packages/endpoint-json-feed": { + "name": "@indiekit/endpoint-json-feed", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23319,6 +23460,7 @@ } }, "packages/endpoint-media": { + "name": "@indiekit/endpoint-media", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23335,6 +23477,7 @@ } }, "packages/endpoint-micropub": { + "name": "@indiekit/endpoint-micropub", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23355,6 +23498,7 @@ } }, "packages/endpoint-posts": { + "name": "@indiekit/endpoint-posts", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23371,6 +23515,7 @@ } }, "packages/endpoint-share": { + "name": "@indiekit/endpoint-share", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23384,6 +23529,7 @@ } }, "packages/endpoint-syndicate": { + "name": "@indiekit/endpoint-syndicate", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23397,6 +23543,7 @@ } }, "packages/error": { + "name": "@indiekit/error", "version": "1.0.0-beta.3", "license": "MIT", "engines": { @@ -23404,6 +23551,7 @@ } }, "packages/frontend": { + "name": "@indiekit/frontend", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23430,6 +23578,7 @@ } }, "packages/indiekit": { + "name": "@indiekit/indiekit", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23492,6 +23641,7 @@ } }, "packages/preset-hugo": { + "name": "@indiekit/preset-hugo", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23554,6 +23704,7 @@ } }, "packages/preset-jekyll": { + "name": "@indiekit/preset-jekyll", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23564,6 +23715,7 @@ } }, "packages/store-bitbucket": { + "name": "@indiekit/store-bitbucket", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23575,6 +23727,7 @@ } }, "packages/store-file-system": { + "name": "@indiekit/store-file-system", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23585,6 +23738,7 @@ } }, "packages/store-ftp": { + "name": "@indiekit/store-ftp", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23596,6 +23750,7 @@ } }, "packages/store-gitea": { + "name": "@indiekit/store-gitea", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23607,6 +23762,7 @@ } }, "packages/store-github": { + "name": "@indiekit/store-github", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23618,6 +23774,7 @@ } }, "packages/store-gitlab": { + "name": "@indiekit/store-gitlab", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23629,6 +23786,7 @@ } }, "packages/syndicator-internet-archive": { + "name": "@indiekit/syndicator-internet-archive", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23640,6 +23798,7 @@ } }, "packages/syndicator-mastodon": { + "name": "@indiekit/syndicator-mastodon", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { @@ -23654,6 +23813,7 @@ } }, "packages/syndicator-twitter": { + "name": "@indiekit/syndicator-twitter", "version": "1.0.0-beta.3", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index f1350ee56..40c1bd1ec 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,10 @@ "@indiekit-test/session": "*", "@indiekit-test/store": "*", "@indiekit-test/token": "*", + "@types/cookie-session": "^2.0.44", + "@types/express": "^4.17.17", + "@types/express-fileupload": "^1.4.1", + "@types/lodash": "^4.14.195", "ava": "^5.0.0", "c8": "^7.8.0", "cookie-session": "^2.0.0", @@ -159,4 +163,4 @@ ] } } -} \ No newline at end of file +} diff --git a/packages/create-indiekit/index.js b/packages/create-indiekit/index.js index c657a5510..010299aac 100644 --- a/packages/create-indiekit/index.js +++ b/packages/create-indiekit/index.js @@ -12,7 +12,7 @@ const { name, version, bugs } = require("./package.json"); const nodeVersion = 18; /** - * @returns {Function} init + * @returns {Promise} init */ export async function init() { const { log } = console; diff --git a/packages/create-indiekit/lib/utils.js b/packages/create-indiekit/lib/utils.js index b5b81f63a..4d71e77de 100644 --- a/packages/create-indiekit/lib/utils.js +++ b/packages/create-indiekit/lib/utils.js @@ -7,7 +7,7 @@ import prompts from "prompts"; * Add plug-in to Indiekit configuration * @param {string} pluginName - Name of selected plug-in * @param {object} config - Indiekit configuration - * @returns {object} Updated configuration + * @returns {Promise} Updated configuration */ export const addPluginConfig = async (pluginName, config) => { const plugin = await getPlugin(pluginName); @@ -64,7 +64,7 @@ export const isUrl = (string) => { /** * Get question prompts specified by plugin * @param {string} pluginName - Plug-in name - * @returns {object} Plug-in + * @returns {Promise} Plug-in */ export const getPlugin = async (pluginName) => { const { default: IndiekitPlugin } = await import(pluginName); diff --git a/packages/endpoint-auth/lib/client.js b/packages/endpoint-auth/lib/client.js index 4986487cf..96b7d82a2 100644 --- a/packages/endpoint-auth/lib/client.js +++ b/packages/endpoint-auth/lib/client.js @@ -4,7 +4,7 @@ import { mf2 } from "microformats-parser"; /** * Get client information * @param {string} client_id - Client URL - * @returns {object} Information about the client + * @returns {Promise} Information about the client */ export const getClientInformation = async (client_id) => { let client = { diff --git a/packages/endpoint-auth/lib/controllers/authorization.js b/packages/endpoint-auth/lib/controllers/authorization.js index 828818599..10acd14f9 100644 --- a/packages/endpoint-auth/lib/controllers/authorization.js +++ b/packages/endpoint-auth/lib/controllers/authorization.js @@ -10,10 +10,7 @@ export const authorizationController = { * * Validate parameters in request before redirecting to consent form * where the user is prompted to authenticate themselves. - * @param {object} request - HTTP request - * @param {Promise|object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} * @see {@link https://indieauth.spec.indieweb.org/#authorization-request} * @see {@link https://indieauth.spec.indieweb.org/#authorization-response} */ @@ -93,9 +90,7 @@ export const authorizationController = { /** * Authorization code request * Redeem verified authorization code for a profile URL. - * @param {object} request - HTTP request - * @param {Promise|object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} * @see {@link https://indieauth.spec.indieweb.org/#redeeming-the-authorization-code} * @see {@link https://indieauth.spec.indieweb.org/#profile-url-response} */ diff --git a/packages/endpoint-auth/lib/controllers/consent.js b/packages/endpoint-auth/lib/controllers/consent.js index 64e98c502..4bdcebf29 100644 --- a/packages/endpoint-auth/lib/controllers/consent.js +++ b/packages/endpoint-auth/lib/controllers/consent.js @@ -9,9 +9,7 @@ import { signToken } from "../token.js"; export const consentController = { /** * View consent form - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ get(request, response) { if (!request.query.request_uri) { @@ -44,9 +42,7 @@ export const consentController = { /** * Submit consent form - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} * @see {@link https://indieauth.spec.indieweb.org/#authorization-response} */ post(request, response) { diff --git a/packages/endpoint-auth/lib/controllers/documentation.js b/packages/endpoint-auth/lib/controllers/documentation.js index 2c779a21e..192a996c8 100644 --- a/packages/endpoint-auth/lib/controllers/documentation.js +++ b/packages/endpoint-auth/lib/controllers/documentation.js @@ -1,10 +1,6 @@ /** * Service documentation - * @param {object} error - Error - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").ErrorRequestHandler} */ export const documentationController = (error, request, response, next) => { if (request.accepts("html")) { diff --git a/packages/endpoint-auth/lib/controllers/password.js b/packages/endpoint-auth/lib/controllers/password.js index 1cc6fb19e..6deb0087c 100644 --- a/packages/endpoint-auth/lib/controllers/password.js +++ b/packages/endpoint-auth/lib/controllers/password.js @@ -4,9 +4,7 @@ import { createPasswordHash } from "../password.js"; export const passwordController = { /** * New password request - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ get(request, response) { const { name } = request.app.locals.application; @@ -21,9 +19,7 @@ export const passwordController = { /** * New password response - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async post(request, response) { const { password } = request.body; diff --git a/packages/endpoint-auth/lib/controllers/token.js b/packages/endpoint-auth/lib/controllers/token.js index 73e633992..d15660da8 100644 --- a/packages/endpoint-auth/lib/controllers/token.js +++ b/packages/endpoint-auth/lib/controllers/token.js @@ -4,10 +4,7 @@ import { signToken, verifyToken } from "../token.js"; export const tokenController = { /** * Verify bearer token - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ get(request, response, next) { try { @@ -44,9 +41,7 @@ export const tokenController = { * Authorization code request * * Redeem verified authorization code for an access token. - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} * @see {@link https://indieauth.spec.indieweb.org/#redeeming-the-authorization-code} * @see {@link https://indieauth.spec.indieweb.org/#access-token-response} */ diff --git a/packages/endpoint-auth/lib/middleware/code.js b/packages/endpoint-auth/lib/middleware/code.js index d1bb2ce1b..7ce54f04c 100644 --- a/packages/endpoint-auth/lib/middleware/code.js +++ b/packages/endpoint-auth/lib/middleware/code.js @@ -6,10 +6,7 @@ import { getCanonicalUrl, getRequestParameters } from "../utils.js"; /** * Validate authorization code before redeeming - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const codeValidator = (request, response, next) => { try { diff --git a/packages/endpoint-auth/lib/middleware/secret.js b/packages/endpoint-auth/lib/middleware/secret.js index bb9141347..295082154 100644 --- a/packages/endpoint-auth/lib/middleware/secret.js +++ b/packages/endpoint-auth/lib/middleware/secret.js @@ -3,10 +3,7 @@ import { IndiekitError } from "@indiekit/error"; /** * Check that server secret has been set - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const hasSecret = (request, response, next) => { if (!process.env.SECRET) { diff --git a/packages/endpoint-auth/lib/password.js b/packages/endpoint-auth/lib/password.js index 85b630bcd..ed232440a 100644 --- a/packages/endpoint-auth/lib/password.js +++ b/packages/endpoint-auth/lib/password.js @@ -4,7 +4,7 @@ import bcrypt from "bcrypt"; /** * Create password hash * @param {string} password - Password - * @returns {boolean} Password hash + * @returns {Promise} Password hash */ export async function createPasswordHash(password) { return bcrypt.hash(password, 10); @@ -13,7 +13,7 @@ export async function createPasswordHash(password) { /** * Verify password * @param {string} password - Password - * @returns {boolean} Password is valid + * @returns {Promise} Password valid */ export async function verifyPassword(password) { return bcrypt.compare(password, process.env.PASSWORD_SECRET); diff --git a/packages/endpoint-auth/lib/pkce.js b/packages/endpoint-auth/lib/pkce.js index 75081c7fa..386828552 100644 --- a/packages/endpoint-auth/lib/pkce.js +++ b/packages/endpoint-auth/lib/pkce.js @@ -4,7 +4,7 @@ import crypto from "node:crypto"; * Verify PKCE (Proof Key for Code Exchange) code * @param {string} verifier - Code verifier * @param {string} challenge - Code challenge - * @param {string} [challengeMethod=sha256] - Code challenge method + * @param {string} [challengeMethod="sha256"] - Code challenge method * @returns {boolean} - Code challenge result */ export const verifyCode = (verifier, challenge, challengeMethod = "sha256") => { diff --git a/packages/endpoint-auth/lib/pushed-authorization-request.js b/packages/endpoint-auth/lib/pushed-authorization-request.js index ea3ffd494..761965865 100644 --- a/packages/endpoint-auth/lib/pushed-authorization-request.js +++ b/packages/endpoint-auth/lib/pushed-authorization-request.js @@ -11,7 +11,7 @@ import { randomString } from "./utils.js"; /** * Create a PAR URI - * @param {object} request - HTTP request + * @param {import("express").Request} request - Request * @returns {string} OAuth request URI */ export const createRequestUri = (request) => { @@ -23,7 +23,7 @@ export const createRequestUri = (request) => { /** * Get data from PAR URI - * @param {object} request - HTTP request + * @param {import("express").Request} request - Request * @returns {object} Saved payload */ export const getRequestUriData = (request) => { diff --git a/packages/endpoint-auth/lib/scope.js b/packages/endpoint-auth/lib/scope.js index 26e40b4c5..639f16d45 100644 --- a/packages/endpoint-auth/lib/scope.js +++ b/packages/endpoint-auth/lib/scope.js @@ -3,7 +3,7 @@ export const scopes = ["create", "update", "draft", "media", "delete"]; /** * Get `items` object for checkboxes component * @param {string} scope - Selected scope(s) - * @param {object} response - HTTP response + * @param {import("express").Response} response - Response * @returns {object} Items for checkboxes component */ export function getScopeItems(scope, response) { diff --git a/packages/endpoint-auth/lib/token.js b/packages/endpoint-auth/lib/token.js index ac91dfbb8..38cd3d2be 100644 --- a/packages/endpoint-auth/lib/token.js +++ b/packages/endpoint-auth/lib/token.js @@ -4,7 +4,7 @@ import jwt from "jsonwebtoken"; /** * Sign token * @param {object} payload - JSON Web Token payload - * @param {string} [expiresIn=10m] - Token expiry + * @param {string} [expiresIn="10m"] - Token expiry * @returns {string} Signed JSON Web Token */ export const signToken = (payload, expiresIn = "10m") => diff --git a/packages/endpoint-auth/lib/utils.js b/packages/endpoint-auth/lib/utils.js index f189129d2..db12ac601 100644 --- a/packages/endpoint-auth/lib/utils.js +++ b/packages/endpoint-auth/lib/utils.js @@ -18,7 +18,7 @@ export const randomString = (length = 16) => /** * Get request parameters from either query string or JSON body - * @param {object} request - HTTP request + * @param {import("express").Request} request - Request * @returns {object} - Request parameters */ export const getRequestParameters = (request) => { diff --git a/packages/endpoint-files/lib/controllers/delete.js b/packages/endpoint-files/lib/controllers/delete.js index 420f47b52..dbb195a75 100644 --- a/packages/endpoint-files/lib/controllers/delete.js +++ b/packages/endpoint-files/lib/controllers/delete.js @@ -3,9 +3,7 @@ import { endpoint } from "../endpoint.js"; export const deleteController = { /** * Confirm file to delete - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async get(request, response) { const { back, fileName, scope } = response.locals; @@ -23,9 +21,7 @@ export const deleteController = { /** * Post delete action to media endpoint - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async post(request, response) { const { mediaEndpoint } = request.app.locals.application; diff --git a/packages/endpoint-files/lib/controllers/file.js b/packages/endpoint-files/lib/controllers/file.js index c728da71e..7c8d81923 100644 --- a/packages/endpoint-files/lib/controllers/file.js +++ b/packages/endpoint-files/lib/controllers/file.js @@ -2,10 +2,7 @@ import path from "node:path"; /** * View previously uploaded file - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const fileController = async (request, response, next) => { try { diff --git a/packages/endpoint-files/lib/controllers/files.js b/packages/endpoint-files/lib/controllers/files.js index 701c8bdde..77b58e6ca 100644 --- a/packages/endpoint-files/lib/controllers/files.js +++ b/packages/endpoint-files/lib/controllers/files.js @@ -4,10 +4,7 @@ import { getFileId, getFileName } from "../utils.js"; /** * List previously uploaded files - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const filesController = async (request, response, next) => { try { diff --git a/packages/endpoint-files/lib/controllers/form.js b/packages/endpoint-files/lib/controllers/form.js index 842e5dacb..f3fc495b9 100644 --- a/packages/endpoint-files/lib/controllers/form.js +++ b/packages/endpoint-files/lib/controllers/form.js @@ -6,9 +6,7 @@ import { endpoint } from "../endpoint.js"; export const formController = { /** * Get file to upload - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async get(request, response) { const { back, scope } = response.locals; @@ -24,9 +22,7 @@ export const formController = { /** * Post file to media endpoint - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async post(request, response) { const { mediaEndpoint } = request.app.locals.application; diff --git a/packages/endpoint-files/lib/endpoint.js b/packages/endpoint-files/lib/endpoint.js index 6a5c527ab..1baba5906 100644 --- a/packages/endpoint-files/lib/endpoint.js +++ b/packages/endpoint-files/lib/endpoint.js @@ -12,7 +12,7 @@ export const endpoint = { * Micropub media query * @param {string} url - URL * @param {string} accessToken - Access token - * @returns {object} Response data + * @returns {Promise} Response data */ async get(url, accessToken) { const endpointResponse = await fetch(url, { @@ -35,10 +35,10 @@ export const endpoint = { * Micropub action * @param {string} url - URL * @param {string} accessToken - Access token - * @param {FormData} [formData=false] - Form data - * @returns {object} Response data + * @param {FormData} [formData=null] - Form data + * @returns {Promise} Response data */ - async post(url, accessToken, formData) { + async post(url, accessToken, formData = null) { const endpointResponse = await fetch(url, { method: "POST", headers: { diff --git a/packages/endpoint-files/lib/utils.js b/packages/endpoint-files/lib/utils.js index 46eea8b11..9728c63f0 100644 --- a/packages/endpoint-files/lib/utils.js +++ b/packages/endpoint-files/lib/utils.js @@ -15,7 +15,7 @@ export const getFileId = (url) => { * @param {string} id - Post ID * @param {string} mediaEndpoint - Micropub media endpoint * @param {string} accessToken - Access token - * @returns {object} JF2 properties + * @returns {Promise} JF2 properties */ export const getFileData = async (id, mediaEndpoint, accessToken) => { const mediaUrl = new URL(mediaEndpoint); diff --git a/packages/endpoint-image/lib/middleware/cache.js b/packages/endpoint-image/lib/middleware/cache.js index cc1779f26..b143efd6f 100644 --- a/packages/endpoint-image/lib/middleware/cache.js +++ b/packages/endpoint-image/lib/middleware/cache.js @@ -1,8 +1,6 @@ /** * Send cache control headers in response - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback + * @type {import("express").RequestHandler} */ export function cacheControl(request, response, next) { response.set({ diff --git a/packages/endpoint-media/lib/controllers/action.js b/packages/endpoint-media/lib/controllers/action.js index 667ea5038..fc53408d0 100644 --- a/packages/endpoint-media/lib/controllers/action.js +++ b/packages/endpoint-media/lib/controllers/action.js @@ -5,10 +5,7 @@ import { checkScope } from "../scope.js"; /** * Perform requested file action - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const actionController = async (request, response, next) => { const { body, files, query } = request; diff --git a/packages/endpoint-media/lib/controllers/query.js b/packages/endpoint-media/lib/controllers/query.js index c6b12c24f..c31d35ff8 100644 --- a/packages/endpoint-media/lib/controllers/query.js +++ b/packages/endpoint-media/lib/controllers/query.js @@ -2,10 +2,7 @@ import { IndiekitError } from "@indiekit/error"; /** * Query uploaded files - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const queryController = async (request, response, next) => { const { application, publication } = request.app.locals; diff --git a/packages/endpoint-media/lib/file.js b/packages/endpoint-media/lib/file.js index 5b0bcde02..f92bb4510 100644 --- a/packages/endpoint-media/lib/file.js +++ b/packages/endpoint-media/lib/file.js @@ -6,7 +6,7 @@ import { randomString } from "./utils.js"; * Derive properties from file data * @param {object} publication - Publication configuration * @param {object} file - Original file object - * @returns {object} File properties + * @returns {Promise} File properties * @example fileData('brighton-pier.jpg') => { * basename: 'ds48s', * ext: '.jpg' @@ -36,7 +36,7 @@ export const getFileProperties = async (publication, file) => { /** * Derive media type (and return equivalent IndieWeb post type) * @param {object} file - File object - * @returns {string} Post type ('photo', 'video' or 'audio') + * @returns {Promise} Post type ('photo', 'video' or 'audio') * @example getMediaType('brighton-pier.jpg') => 'photo' */ export const getMediaType = async (file) => { diff --git a/packages/endpoint-media/lib/media-content.js b/packages/endpoint-media/lib/media-content.js index 2729529d5..24d77ed76 100644 --- a/packages/endpoint-media/lib/media-content.js +++ b/packages/endpoint-media/lib/media-content.js @@ -4,7 +4,7 @@ export const mediaContent = { * @param {object} publication - Publication configuration * @param {object} mediaData - Media data * @param {object} file - File to upload - * @returns {object} Data to use in response + * @returns {Promise} Data to use in response */ async upload(publication, mediaData, file) { const { store, storeMessageTemplate } = publication; @@ -32,7 +32,7 @@ export const mediaContent = { * Delete file from content store * @param {object} publication - Publication configuration * @param {object} mediaData - Post data - * @returns {object} Response data + * @returns {Promise} Response data */ async delete(publication, mediaData) { const { store, storeMessageTemplate } = publication; diff --git a/packages/endpoint-media/lib/media-data.js b/packages/endpoint-media/lib/media-data.js index 30d718b7c..47e93fadb 100644 --- a/packages/endpoint-media/lib/media-data.js +++ b/packages/endpoint-media/lib/media-data.js @@ -7,7 +7,7 @@ export const mediaData = { * Create media data * @param {object} publication - Publication configuration * @param {object} file - File - * @returns {object} Media data + * @returns {Promise} Media data */ async create(publication, file) { const { me, media, postTypes } = publication; @@ -56,7 +56,7 @@ export const mediaData = { * Read media data * @param {object} publication - Publication configuration * @param {string} url - URL of existing media - * @returns {object} Media data + * @returns {Promise} Media data */ async read(publication, url) { const { media } = publication; @@ -74,7 +74,7 @@ export const mediaData = { * Delete media data * @param {object} publication - Publication configuration * @param {string} url - URL of existing post - * @returns {boolean} Media data deleted + * @returns {Promise} Media data deleted */ async delete(publication, url) { const { media } = publication; diff --git a/packages/endpoint-media/lib/utils.js b/packages/endpoint-media/lib/utils.js index 1508464b4..a2699bd9e 100644 --- a/packages/endpoint-media/lib/utils.js +++ b/packages/endpoint-media/lib/utils.js @@ -15,7 +15,7 @@ export const randomString = () => Math.random().toString(36).slice(-5); * Render path from URI template and properties * @param {string} path - URI template path * @param {object} properties - Properties to use - * @param {string} publication - Publication configuration + * @param {object} publication - Publication configuration * @returns {string} Path */ export const renderPath = (path, properties, publication) => { @@ -54,6 +54,7 @@ export const renderPath = (path, properties, publication) => { publication.timeZone === "server" ? serverTimeZone : publication.timeZone, + // @ts-ignore (https://github.com/marnusw/date-fns-tz/issues/239) useAdditionalDayOfYearTokens: true, }); } @@ -82,16 +83,19 @@ export const renderPath = (path, properties, publication) => { * @param {object} object - Properties to use * @returns {string} String with substituted */ -export const supplant = (string, object) => - string.replace(/{([^{}]*)}/g, (a, b) => { - const r = object[b]; +export const supplant = (string, object) => { + const replacer = function (match, p1) { + const r = object[p1]; if (typeof r === "string" || typeof r === "number") { return r; } - return a; - }); + return match; + }; + + return string.replace(/{([^{}]*)}/g, replacer); +}; /** * Derive a permalink (by combining publication URL, that may include a path, diff --git a/packages/endpoint-micropub/lib/controllers/action.js b/packages/endpoint-micropub/lib/controllers/action.js index 707b8b203..66a0f4aed 100644 --- a/packages/endpoint-micropub/lib/controllers/action.js +++ b/packages/endpoint-micropub/lib/controllers/action.js @@ -7,10 +7,7 @@ import { uploadMedia } from "../media.js"; /** * Perform requested post action - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const actionController = async (request, response, next) => { const { body, files, query } = request; diff --git a/packages/endpoint-micropub/lib/controllers/query.js b/packages/endpoint-micropub/lib/controllers/query.js index 89e8200ba..3121f4d24 100644 --- a/packages/endpoint-micropub/lib/controllers/query.js +++ b/packages/endpoint-micropub/lib/controllers/query.js @@ -4,10 +4,7 @@ import { getMf2Properties, jf2ToMf2 } 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 + * @type {import("express").RequestHandler} */ export const queryController = async (request, response, next) => { const { application, publication } = request.app.locals; diff --git a/packages/endpoint-micropub/lib/jf2.js b/packages/endpoint-micropub/lib/jf2.js index 26d92cbb0..991cf94ea 100644 --- a/packages/endpoint-micropub/lib/jf2.js +++ b/packages/endpoint-micropub/lib/jf2.js @@ -12,8 +12,8 @@ import { /** * Create JF2 object from form-encoded request - * @param {string} body - Form-encoded request body - * @returns {string} Micropub action + * @param {object} body - Form-encoded request body + * @returns {object} Micropub action */ export const formEncodedToJf2 = (body) => { const jf2 = { @@ -45,7 +45,7 @@ export const formEncodedToJf2 = (body) => { * Convert mf2 to JF2 * @param {string} body - Form-encoded request body * @param {boolean} requestReferences - Request data for any referenced URLs - * @returns {string} Micropub action + * @returns {Promise} Micropub action */ export const mf2ToJf2 = async (body, requestReferences) => { const mf2 = { @@ -126,7 +126,7 @@ export const getAudioProperty = (properties, me) => { * JF2 allows for the provision of both plaintext and HTML representations. * Use existing values, or add HTML representation if only plaintext provided. * @param {object} properties - JF2 properties - * @returns {Array} `content` property + * @returns {object} `content` property * @see {@link https://www.w3.org/TR/jf2/#html-content} */ export const getContentProperty = (properties) => { @@ -225,7 +225,7 @@ export const getVideoProperty = (properties, me) => { * Get slug * @param {object} properties - JF2 properties * @param {string} separator - Slug separator - * @returns {Array} Array containing slug value + * @returns {string} Array containing slug value */ export const getSlugProperty = (properties, separator) => { const suggested = properties["mp-slug"]; diff --git a/packages/endpoint-micropub/lib/media.js b/packages/endpoint-micropub/lib/media.js index 140f54feb..d869e72bf 100644 --- a/packages/endpoint-micropub/lib/media.js +++ b/packages/endpoint-micropub/lib/media.js @@ -7,7 +7,7 @@ import { fetch, FormData } from "undici"; * @param {string} token - Bearer token * @param {object} properties - JF2 properties * @param {object} files - Files to upload - * @returns {Array} Uploaded file locations + * @returns {Promise} Uploaded file locations */ export const uploadMedia = async (mediaEndpoint, token, properties, files) => { for await (let [mediaProperty, media] of Object.entries(files)) { @@ -31,7 +31,9 @@ export const uploadMedia = async (mediaEndpoint, token, properties, files) => { }); if (!response.ok) { + /** @type {object} */ const body = await response.json(); + const message = body.error_description || response.statusText; throw new Error(message); } diff --git a/packages/endpoint-micropub/lib/mf2.js b/packages/endpoint-micropub/lib/mf2.js index cfd1ca7cb..eea17f4a8 100644 --- a/packages/endpoint-micropub/lib/mf2.js +++ b/packages/endpoint-micropub/lib/mf2.js @@ -2,7 +2,7 @@ * Return mf2 properties of a post * @param {object} mf2 - mf2 object * @param {Array|string} requestedProperties - mf2 properties to select - * @returns {Promise|object} mf2 with requested properties + * @returns {Promise} mf2 with requested properties */ export const getMf2Properties = (mf2, requestedProperties) => { if (!requestedProperties) { @@ -36,7 +36,7 @@ export const getMf2Properties = (mf2, requestedProperties) => { /** * Convert JF2 to mf2 - * @param {string} jf2 - JF2 + * @param {object} jf2 - JF2 * @returns {object} mf2 */ export const jf2ToMf2 = (jf2) => { diff --git a/packages/endpoint-micropub/lib/post-content.js b/packages/endpoint-micropub/lib/post-content.js index aa7b099df..ecfe1ce66 100644 --- a/packages/endpoint-micropub/lib/post-content.js +++ b/packages/endpoint-micropub/lib/post-content.js @@ -3,7 +3,7 @@ export const postContent = { * Create post * @param {object} publication - Publication configuration * @param {object} postData - Post data - * @returns {object} Response data + * @returns {Promise} Response data */ async create(publication, postData) { const { postTemplate, store, storeMessageTemplate } = publication; @@ -33,7 +33,7 @@ export const postContent = { * @param {object} publication - Publication configuration * @param {object} postData - Post data * @param {string} url - Files attached to request - * @returns {object} Response data + * @returns {Promise} Response data */ async update(publication, postData, url) { const { postTemplate, store, storeMessageTemplate } = publication; @@ -65,7 +65,7 @@ export const postContent = { * Delete post * @param {object} publication - Publication configuration * @param {object} postData - Post data - * @returns {object} Response data + * @returns {Promise} Response data */ async delete(publication, postData) { const { postTemplate, store, storeMessageTemplate } = publication; @@ -93,7 +93,7 @@ export const postContent = { * Undelete post * @param {object} publication - Publication configuration * @param {object} postData - Post data - * @returns {object} Response data + * @returns {Promise} Response data */ async undelete(publication, postData) { const { postTemplate, store, storeMessageTemplate } = publication; diff --git a/packages/endpoint-micropub/lib/post-data.js b/packages/endpoint-micropub/lib/post-data.js index 6375004d0..ef05b7e11 100644 --- a/packages/endpoint-micropub/lib/post-data.js +++ b/packages/endpoint-micropub/lib/post-data.js @@ -11,7 +11,7 @@ export const postData = { * @param {object} publication - Publication configuration * @param {object} properties - JF2 properties * @param {boolean} [draftMode=false] - Draft mode - * @returns {object} Post data + * @returns {Promise} Post data */ async create(publication, properties, draftMode = false) { const { me, posts, postTypes, syndicationTargets } = publication; @@ -64,7 +64,7 @@ export const postData = { * Read post data * @param {object} publication - Publication configuration * @param {string} url - URL of existing post - * @returns {object} Post data + * @returns {Promise} Post data */ async read(publication, url) { const { posts } = publication; @@ -85,7 +85,7 @@ export const postData = { * @param {object} publication - Publication configuration * @param {string} url - URL of existing post * @param {object} operation - Requested operation(s) - * @returns {object} Post data + * @returns {Promise} Post data */ async update(publication, url, operation) { const { me, posts, postTypes } = publication; @@ -148,7 +148,7 @@ export const postData = { * Delete (most) properties, keeping a record of deleted for later retrieval * @param {object} publication - Publication configuration * @param {string} url - URL of existing post - * @returns {object} Post data + * @returns {Promise} Post data */ async delete(publication, url) { const { posts, postTypes } = publication; @@ -194,7 +194,7 @@ export const postData = { * @param {object} publication - Publication configuration * @param {string} url - URL of existing post * @param {boolean} [draftMode=false] - Draft mode - * @returns {object} Post data + * @returns {Promise} Post data */ async undelete(publication, url, draftMode) { const { posts, postTypes } = publication; diff --git a/packages/endpoint-micropub/lib/post-type-count.js b/packages/endpoint-micropub/lib/post-type-count.js index e697a9544..ba07c3e33 100644 --- a/packages/endpoint-micropub/lib/post-type-count.js +++ b/packages/endpoint-micropub/lib/post-type-count.js @@ -3,7 +3,7 @@ export const postTypeCount = { * Count the number of posts of a given type * @param {object} publication - Publication configuration * @param {object} properties - JF2 properties - * @returns {object} Post count + * @returns {Promise} Post count */ async get(publication, properties) { if (!publication.posts || !publication.posts.count()) { diff --git a/packages/endpoint-micropub/lib/update.js b/packages/endpoint-micropub/lib/update.js index e566cc18e..adeb0456e 100644 --- a/packages/endpoint-micropub/lib/update.js +++ b/packages/endpoint-micropub/lib/update.js @@ -42,7 +42,7 @@ export const addProperties = (object, additions) => { * Replace entries of a property. If property doesn’t exist, create it. * @param {object} object - Object to update * @param {object} replacements - Properties to replace (mf2) - * @returns {object} Updated object (JF2) + * @returns {Promise} Updated object (JF2) */ export const replaceEntries = async (object, replacements) => { for await (const [key, value] of Object.entries(replacements)) { diff --git a/packages/endpoint-micropub/lib/utils.js b/packages/endpoint-micropub/lib/utils.js index 22eae710a..06cdc2405 100644 --- a/packages/endpoint-micropub/lib/utils.js +++ b/packages/endpoint-micropub/lib/utils.js @@ -33,7 +33,7 @@ export const excerptString = (string, n) => { /** * Slugify a string * @param {string} string - String to excerpt - * @param {number} separator - Character used to separate words + * @param {string} [separator="-"] - Character used to separate words * @returns {string} Slugified string * @example slugifyString('Foo bar baz', '_') => 'foo_bar_baz' */ @@ -86,8 +86,8 @@ export const randomString = () => Math.random().toString(36).slice(-5); /** * Render relative path if URL is on publication - * @param {URL} url - External URL - * @param {URL} me - Publication URL + * @param {string} url - External URL + * @param {string} me - Publication URL * @returns {string} Path */ export const relativeMediaPath = (url, me) => @@ -98,7 +98,7 @@ export const relativeMediaPath = (url, me) => * @param {string} path - URI template path * @param {object} properties - Properties to use * @param {object} publication - Publication configuration - * @returns {string} Path + * @returns {Promise} Path */ export const renderPath = async (path, properties, publication) => { const dateObject = new Date(properties.published); @@ -137,6 +137,7 @@ export const renderPath = async (path, properties, publication) => { publication.timeZone === "server" ? serverTimeZone : publication.timeZone, + // @ts-ignore (https://github.com/marnusw/date-fns-tz/issues/239) useAdditionalDayOfYearTokens: true, }); } @@ -169,16 +170,19 @@ export const renderPath = async (path, properties, publication) => { * @param {object} object - Properties to use * @returns {string} String with substituted */ -export const supplant = (string, object) => - string.replace(/{([^{}]*)}/g, (a, b) => { - const r = object[b]; +export const supplant = (string, object) => { + const replacer = function (match, p1) { + const r = object[p1]; if (typeof r === "string" || typeof r === "number") { return r; } - return a; - }); + return match; + }; + + return string.replace(/{([^{}]*)}/g, replacer); +}; /** * Convert string to array if not already an array diff --git a/packages/endpoint-posts/lib/controllers/delete.js b/packages/endpoint-posts/lib/controllers/delete.js index 3b807be72..5e53fe58d 100644 --- a/packages/endpoint-posts/lib/controllers/delete.js +++ b/packages/endpoint-posts/lib/controllers/delete.js @@ -4,9 +4,7 @@ import { endpoint } from "../endpoint.js"; export const deleteController = { /** * Confirm post to delete/undelete - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async get(request, response) { const { action, back, postName, scope } = response.locals; @@ -23,9 +21,7 @@ export const deleteController = { /** * Post delete/undelete action to Micropub endpoint - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async post(request, response) { const { micropubEndpoint } = request.app.locals.application; diff --git a/packages/endpoint-posts/lib/controllers/form.js b/packages/endpoint-posts/lib/controllers/form.js index 40f1d866c..9cdc83a16 100644 --- a/packages/endpoint-posts/lib/controllers/form.js +++ b/packages/endpoint-posts/lib/controllers/form.js @@ -7,9 +7,7 @@ import { getLocationProperty } from "../utils.js"; export const formController = { /** * Get post to create/update - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async get(request, response) { const { action, back, postTypeName, scope } = response.locals; @@ -25,9 +23,7 @@ export const formController = { /** * Post to Micropub endpoint - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async post(request, response) { const { micropubEndpoint } = request.app.locals.application; diff --git a/packages/endpoint-posts/lib/controllers/post.js b/packages/endpoint-posts/lib/controllers/post.js index cffe14000..56b414621 100644 --- a/packages/endpoint-posts/lib/controllers/post.js +++ b/packages/endpoint-posts/lib/controllers/post.js @@ -3,9 +3,7 @@ import { checkScope } from "@indiekit/endpoint-micropub/lib/scope.js"; /** * View previously published post - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const postController = async (request, response) => { const { back, draftMode, post, postName, postStatus, scope } = diff --git a/packages/endpoint-posts/lib/controllers/posts.js b/packages/endpoint-posts/lib/controllers/posts.js index 03ac7c05c..e9af17516 100644 --- a/packages/endpoint-posts/lib/controllers/posts.js +++ b/packages/endpoint-posts/lib/controllers/posts.js @@ -7,10 +7,7 @@ import { getPostId, getPostName } from "../utils.js"; /** * List previously published posts - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export const postsController = async (request, response, next) => { try { diff --git a/packages/endpoint-posts/lib/endpoint.js b/packages/endpoint-posts/lib/endpoint.js index ab389f19b..6f702e30a 100644 --- a/packages/endpoint-posts/lib/endpoint.js +++ b/packages/endpoint-posts/lib/endpoint.js @@ -5,7 +5,7 @@ export const endpoint = { * Micropub query * @param {string} url - URL * @param {string} accessToken - Access token - * @returns {object} Response data + * @returns {Promise} Response data */ async get(url, accessToken) { const endpointResponse = await fetch(url, { @@ -29,7 +29,7 @@ export const endpoint = { * @param {string} url - URL * @param {string} accessToken - Access token * @param {object} [jsonBody=false] - JSON body - * @returns {object} Response data + * @returns {Promise} Response data */ async post(url, accessToken, jsonBody = false) { const endpointResponse = await fetch(url, { diff --git a/packages/endpoint-posts/lib/utils.js b/packages/endpoint-posts/lib/utils.js index cebe8d2bf..b321d6e2f 100644 --- a/packages/endpoint-posts/lib/utils.js +++ b/packages/endpoint-posts/lib/utils.js @@ -38,7 +38,7 @@ export const getPostId = (url) => { * @param {string} id - Post ID * @param {string} micropubEndpoint - Micropub endpoint * @param {string} accessToken - Access token - * @returns {object} JF2 properties + * @returns {Promise} JF2 properties */ export const getPostData = async (id, micropubEndpoint, accessToken) => { const micropubUrl = new URL(micropubEndpoint); diff --git a/packages/endpoint-share/lib/controllers/share.js b/packages/endpoint-share/lib/controllers/share.js index 2851a3534..8b4fc85d5 100644 --- a/packages/endpoint-share/lib/controllers/share.js +++ b/packages/endpoint-share/lib/controllers/share.js @@ -5,8 +5,7 @@ import { validationResult } from "express-validator"; export const shareController = { /** * View share page - * @param {object} request - HTTP request - * @param {object} response - HTTP response + * @type {import("express").RequestHandler} */ get(request, response) { const { content, name, url, success } = request.query; @@ -23,9 +22,7 @@ export const shareController = { /** * Post share content - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ async post(request, response) { const { application } = request.app.locals; @@ -58,7 +55,9 @@ export const shareController = { throw await IndiekitError.fromFetch(micropubResponse); } + /** @type {object} */ const body = await micropubResponse.json(); + const message = encodeURIComponent(body.success_description); response.redirect(`?success=${message}`); diff --git a/packages/endpoint-syndicate/lib/controllers/syndicate.js b/packages/endpoint-syndicate/lib/controllers/syndicate.js index 1aee5b9a5..10d35f6df 100644 --- a/packages/endpoint-syndicate/lib/controllers/syndicate.js +++ b/packages/endpoint-syndicate/lib/controllers/syndicate.js @@ -75,6 +75,7 @@ export const syndicateController = { throw await IndiekitError.fromFetch(micropubResponse); } + /** @type {object} */ const body = await micropubResponse.json(); // Include failed syndication targets in ‘success’ response diff --git a/packages/endpoint-syndicate/lib/utils.js b/packages/endpoint-syndicate/lib/utils.js index 0d8672a4d..c8b4f2f57 100644 --- a/packages/endpoint-syndicate/lib/utils.js +++ b/packages/endpoint-syndicate/lib/utils.js @@ -2,7 +2,7 @@ * Get post data * @param {object} publication - Publication configuration * @param {string} url - URL of existing post (optional) - * @returns {object} Post data for given URL else recently published post + * @returns {Promise} Post data for given URL else recently published post */ export const getPostData = async (publication, url) => { const { posts } = publication; diff --git a/packages/frontend/lib/filters/url.js b/packages/frontend/lib/filters/url.js index 92bd334d4..55750649d 100644 --- a/packages/frontend/lib/filters/url.js +++ b/packages/frontend/lib/filters/url.js @@ -4,7 +4,7 @@ import path from "node:path"; * Get absolute URL or path * @param {string} string - URL or path * @param {string} baseUrl - Base URL - * @returns {URL} Absolute URL + * @returns {string} Absolute URL */ export const absoluteUrl = (string, baseUrl) => { string = String(string); @@ -19,7 +19,7 @@ export const absoluteUrl = (string, baseUrl) => { /** * Get friendly URL * @param {string} string - URL or path - * @returns {URL} Friendly URL + * @returns {string} Friendly URL */ export const friendlyUrl = (string) => { string = String(string); diff --git a/packages/frontend/lib/globals/classes.js b/packages/frontend/lib/globals/classes.js index fcd4ba729..4ebb4410b 100644 --- a/packages/frontend/lib/globals/classes.js +++ b/packages/frontend/lib/globals/classes.js @@ -1,7 +1,7 @@ /** * Generate space-separated list of class names * @param {string} baseClass - Base class name - * @param {string} [options={}] - Component options + * @param {object} [options={}] - Component options * @returns {string} Space-separated list of class names */ export const classes = (baseClass, options = {}) => { diff --git a/packages/frontend/lib/globals/pages.js b/packages/frontend/lib/globals/pages.js index 203fd258e..a23ecec9a 100644 --- a/packages/frontend/lib/globals/pages.js +++ b/packages/frontend/lib/globals/pages.js @@ -1,8 +1,8 @@ /** * Generate pagination data * @param {number} currentPage - Current page - * @param {limit} limit - Limit of items per page - * @param {count} count - Count of all items + * @param {number} limit - Limit of items per page + * @param {number} count - Count of all items * @returns {object} Options for pagination component */ export const pages = (currentPage, limit, count) => { diff --git a/packages/frontend/lib/nunjucks.js b/packages/frontend/lib/nunjucks.js index 5a95f00aa..f8235edaa 100644 --- a/packages/frontend/lib/nunjucks.js +++ b/packages/frontend/lib/nunjucks.js @@ -4,7 +4,8 @@ import * as filters from "./filters/index.js"; import * as globals from "./globals/index.js"; /** - * @param {Function} app - Express + * @typedef {import("express").Application} Application + * @param {Application} app - Express * @returns {object} Nunjucks environment */ export const templates = (app) => { diff --git a/packages/indiekit/config/express.js b/packages/indiekit/config/express.js index 504071d22..abe8bd8ee 100644 --- a/packages/indiekit/config/express.js +++ b/packages/indiekit/config/express.js @@ -9,6 +9,11 @@ import { logging } from "../lib/middleware/logging.js"; import { routes } from "../lib/routes.js"; import { views } from "../lib/views.js"; +/** + * @typedef {import("express").Application} Application + * @param {object} indiekitConfig - Indiekit configuration + * @returns {Application} Express application + */ export const expressConfig = (indiekitConfig) => { const app = express(); diff --git a/packages/indiekit/lib/cache.js b/packages/indiekit/lib/cache.js index 1efaf8639..746b9e83e 100644 --- a/packages/indiekit/lib/cache.js +++ b/packages/indiekit/lib/cache.js @@ -2,9 +2,10 @@ import { fetch } from "undici"; /** * Get cached response value - * @param {Function} cache - Application cache (returns `false` if no database) + * @typedef {import("keyv")} Keyv + * @param {Keyv} cache - Application cache (returns `false` if no database) * @param {string} url - URL to fetch and cache (used as key) - * @returns {object} Cached response value + * @returns {Promise} Cached response value */ export const getCachedResponse = async (cache, url) => { let cachedResponse = cache && (await cache.get(url)); diff --git a/packages/indiekit/lib/categories.js b/packages/indiekit/lib/categories.js index 9d09cbe51..fa56e083b 100644 --- a/packages/indiekit/lib/categories.js +++ b/packages/indiekit/lib/categories.js @@ -6,7 +6,7 @@ import { isUrl } from "./utils.js"; * from remote JSON file specified in `url` value. * @param {object} cache - Application cache * @param {object} publication - Publication configuration - * @returns {Promise|Array} Array of categories + * @returns {Promise} Array of categories */ export const getCategories = async (cache, publication) => { const { categories } = publication; diff --git a/packages/indiekit/lib/endpoints.js b/packages/indiekit/lib/endpoints.js index 6616754a4..e04d52353 100644 --- a/packages/indiekit/lib/endpoints.js +++ b/packages/indiekit/lib/endpoints.js @@ -3,7 +3,7 @@ import { isUrl, getUrl } from "./utils.js"; /** * Get endpoint URLs from application configuration or default plug-ins * @param {object} application - Application configuration - * @param {object} request - HTTP request + * @param {import("express").Request} request - Request * @returns {object} Endpoint URLs */ export const getEndpoints = (application, request) => { diff --git a/packages/indiekit/lib/indieauth.js b/packages/indiekit/lib/indieauth.js index 611289e63..0e358628b 100644 --- a/packages/indiekit/lib/indieauth.js +++ b/packages/indiekit/lib/indieauth.js @@ -22,7 +22,7 @@ export const IndieAuth = class { * Get authentication URL * @param {string} authorizationEndpoint - Authorization endpoint * @param {string} state - State - * @returns {Promise|string} Authentication URL + * @returns {Promise} Authentication URL */ async getAuthUrl(authorizationEndpoint, state) { // PKCE code challenge @@ -49,7 +49,7 @@ export const IndieAuth = class { * Exchange authorization code for access token * @param {string} tokenEndpoint - Token endpoint * @param {string} code - Code received from authentication endpoint - * @returns {Promise|object} Access token + * @returns {Promise} Access token */ async authorizationCodeGrant(tokenEndpoint, code) { const tokenUrl = new URL(tokenEndpoint); @@ -180,7 +180,7 @@ export const IndieAuth = class { /** * Authenticate user (i.e. check they are who they say they are) by * checking bearer token matches access token saved in current session. - * @returns {Function} Next middleware + * @returns {import("express").RequestHandler} Next middleware */ authenticate() { const { devMode, me } = this; diff --git a/packages/indiekit/lib/installed-plugins.js b/packages/indiekit/lib/installed-plugins.js index 1dbafff92..6eaf952a2 100644 --- a/packages/indiekit/lib/installed-plugins.js +++ b/packages/indiekit/lib/installed-plugins.js @@ -1,7 +1,7 @@ /** * Add plug-ins to application configuration * @param {object} Indiekit - Indiekit instance - * @returns {Promise|Array} Installed plug-ins + * @returns {Promise} Installed plug-ins */ export const getInstalledPlugins = async (Indiekit) => { const installedPlugins = []; diff --git a/packages/indiekit/lib/middleware/error.js b/packages/indiekit/lib/middleware/error.js index e58f8c9d0..8b3af8e29 100644 --- a/packages/indiekit/lib/middleware/error.js +++ b/packages/indiekit/lib/middleware/error.js @@ -4,12 +4,20 @@ import makeDebug from "debug"; const debug = makeDebug("indiekit:error"); +/** + * Return not found error + * @type {import("express").RequestHandler} + */ export const notFound = (request, response, next) => { const error = IndiekitError.notFound(response.__("NotFoundError.page")); next(error); }; +/** + * Return error + * @type {import("express").ErrorRequestHandler} + */ // eslint-disable-next-line no-unused-vars export const internalServer = (error, request, response, next) => { response.status(error.status || 500); diff --git a/packages/indiekit/lib/middleware/force-https.js b/packages/indiekit/lib/middleware/force-https.js index 860fe984d..f06156da6 100644 --- a/packages/indiekit/lib/middleware/force-https.js +++ b/packages/indiekit/lib/middleware/force-https.js @@ -1,9 +1,6 @@ /** * Redirect HTTP requests to HTTPS (typically on Heroku) - * @param {object} request - HTTP request - * @param {object} response - HTTP response - * @param {Function} next - Next middleware callback - * @returns {object} HTTP response + * @type {import("express").RequestHandler} */ export function forceHttps(request, response, next) { const protocol = request.headers["x-forwarded-proto"]; diff --git a/packages/indiekit/lib/middleware/internationalisation.js b/packages/indiekit/lib/middleware/internationalisation.js index 0b76084d7..8d537b34d 100644 --- a/packages/indiekit/lib/middleware/internationalisation.js +++ b/packages/indiekit/lib/middleware/internationalisation.js @@ -3,7 +3,7 @@ import i18n from "i18n"; /** * Set locale * @param {object} indiekitConfig - Indiekit configuration - * @returns {Function} Next middleware + * @returns {import("express").RequestHandler} Next middleware */ export const internationalisation = (indiekitConfig) => function (request, response, next) { diff --git a/packages/indiekit/lib/middleware/locals.js b/packages/indiekit/lib/middleware/locals.js index c1b5dad21..1509c56f9 100644 --- a/packages/indiekit/lib/middleware/locals.js +++ b/packages/indiekit/lib/middleware/locals.js @@ -5,7 +5,7 @@ import { getUrl } from "../utils.js"; /** * Expose configuration to frontend templates and plug-ins * @param {object} indiekitConfig - Indiekit configuration - * @returns {Function} Next middleware + * @returns {import("express").RequestHandler} Next middleware */ export const locals = (indiekitConfig) => function (request, response, next) { diff --git a/packages/indiekit/lib/mongodb.js b/packages/indiekit/lib/mongodb.js index d47dd44d7..c6ef9e3b6 100644 --- a/packages/indiekit/lib/mongodb.js +++ b/packages/indiekit/lib/mongodb.js @@ -3,7 +3,7 @@ import mongodb from "mongodb"; /** * Connect to MongoDB database * @param {*} mongodbUrl - MongoDB URL - * @returns {Promise|object} MongoDB database instance + * @returns {Promise} MongoDB database instance */ export const getMongodbConfig = async (mongodbUrl) => { if (mongodbUrl) { diff --git a/packages/indiekit/lib/state.js b/packages/indiekit/lib/state.js index d5934eb18..697d81a2d 100644 --- a/packages/indiekit/lib/state.js +++ b/packages/indiekit/lib/state.js @@ -20,7 +20,7 @@ export const generateState = (clientId, iv) => { /** * Validate state generated using `generateState` method - * @param {string} state - State + * @param {object} state - State * @param {string} clientId - Client ID * @param {object} iv - Initialization vector * @returns {object|boolean} Validated state object, returns false on failure diff --git a/packages/indiekit/lib/token.js b/packages/indiekit/lib/token.js index d809bd9ec..6a94d5cb3 100644 --- a/packages/indiekit/lib/token.js +++ b/packages/indiekit/lib/token.js @@ -31,7 +31,7 @@ export const findBearerToken = (request) => { * Request token values * @param {string} tokenEndpoint - Token endpoint * @param {object} bearerToken - OAuth bearer token - * @returns {Promise|object} Token values to verify + * @returns {Promise} Token values to verify */ export const requestTokenValues = async (tokenEndpoint, bearerToken) => { const tokenResponse = await fetch(tokenEndpoint, { diff --git a/packages/indiekit/lib/utils.js b/packages/indiekit/lib/utils.js index 9fe73294f..e1cfd55d2 100644 --- a/packages/indiekit/lib/utils.js +++ b/packages/indiekit/lib/utils.js @@ -51,7 +51,7 @@ export const getCanonicalUrl = (url) => new URL(url).href; /** * Get fully resolved server URL - * @param {object} request - HTTP request + * @param {import("express").Request} request - Request * @returns {string} Fully resolved URL */ export const getUrl = (request) => { diff --git a/packages/preset-hugo/index.js b/packages/preset-hugo/index.js index 805885835..d1b0f9253 100644 --- a/packages/preset-hugo/index.js +++ b/packages/preset-hugo/index.js @@ -47,7 +47,7 @@ export default class HugoPreset { /** * Get front matter - * @private + * @access private * @param {object} properties - Post data variables * @returns {string} Front matter in chosen format */ diff --git a/packages/store-bitbucket/index.js b/packages/store-bitbucket/index.js index 58177b7e5..c0ea4e09b 100644 --- a/packages/store-bitbucket/index.js +++ b/packages/store-bitbucket/index.js @@ -8,10 +8,16 @@ const defaults = { }; /** - * @typedef Response - * @property {object} response - HTTP response + * @typedef {import("bitbucket").APIClient} APIClient */ export default class BitbucketStore { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.user] - Username + * @param {string} [options.repo] - Repository + * @param {string} [options.branch] - Branch + * @param {string} [options.password] - Password + */ constructor(options = {}) { this.id = "bitbucket"; this.meta = import.meta; @@ -50,8 +56,8 @@ export default class BitbucketStore { } /** - * @private - * @returns {Function} Bitbucket client interface + * @access private + * @returns {APIClient} Bitbucket client interface */ get #client() { const { Bitbucket } = bitbucket; @@ -69,7 +75,7 @@ export default class BitbucketStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File created * @see {@link https://bitbucketjs.netlify.app/#api-repositories-repositories_createSrcFileCommit} */ async createFile(path, content, message) { @@ -95,7 +101,7 @@ export default class BitbucketStore { /** * Read file in a repository * @param {string} path - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File content * @see {@link https://bitbucketjs.netlify.app/#api-repositories-repositories_readSrc} */ async readFile(path) { @@ -124,7 +130,7 @@ export default class BitbucketStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File updated * @see {@link https://bitbucketjs.netlify.app/#api-repositories-repositories_createSrcFileCommit} */ async updateFile(path, content, message) { @@ -151,7 +157,7 @@ export default class BitbucketStore { * Delete file in a repository * @param {string} path - Path to file * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted * @see {@link https://bitbucketjs.netlify.app/#api-repositories-repositories_createSrcFileCommit} */ async deleteFile(path, message) { diff --git a/packages/store-file-system/index.js b/packages/store-file-system/index.js index a9be6c0c6..7da8d5336 100644 --- a/packages/store-file-system/index.js +++ b/packages/store-file-system/index.js @@ -41,7 +41,7 @@ export default class FileSystemStore { /** * Get absolute file path - * @private + * @access private * @param {string} filePath - Path to file * @returns {string} Absolute file path */ @@ -53,7 +53,7 @@ export default class FileSystemStore { * Create file in a directory * @param {string} filePath - Path to file * @param {string} content - File content - * @returns {Promise} A promise to the response + * @returns {Promise} File created */ async createFile(filePath, content) { try { @@ -80,7 +80,7 @@ export default class FileSystemStore { * Update file in a directory * @param {string} filePath - Path to file * @param {string} content - File content - * @returns {Promise} A promise to the response + * @returns {Promise} File updated */ async updateFile(filePath, content) { try { @@ -101,7 +101,7 @@ export default class FileSystemStore { /** * Delete file in a directory * @param {string} filePath - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted */ async deleteFile(filePath) { try { diff --git a/packages/store-ftp/index.js b/packages/store-ftp/index.js index 02b394063..2712e8855 100644 --- a/packages/store-ftp/index.js +++ b/packages/store-ftp/index.js @@ -13,10 +13,16 @@ const defaults = { }; /** - * @typedef Response - * @property {object} response - FTP response + * @typedef {import("basic-ftp").Client} Client - FTP client */ export default class FtpStore { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.host] - FTP hostname + * @param {string} [options.user] - FTP username + * @param {string} [options.password] - FTP password + * @param {string} [options.directory] - Directory + */ constructor(options = {}) { this.id = "ftp"; this.meta = import.meta; @@ -56,8 +62,8 @@ export default class FtpStore { /** * Get FTP client interface - * @private - * @returns {Function} FTP client interface + * @access private + * @returns {Promise} FTP client interface */ async #client() { const { host, user, password, port, verbose } = this.options; @@ -69,9 +75,9 @@ export default class FtpStore { /** * Create readable stream - * @private + * @access private * @param {string} content - File content - * @returns {string} Readable stream + * @returns {Readable} Readable stream */ #createReadableStream(content) { const readableStream = new Readable(); @@ -83,7 +89,7 @@ export default class FtpStore { /** * Get absolute file path - * @private + * @access private * @param {string} filePath - Path to file * @returns {string} Absolute file path */ @@ -95,7 +101,7 @@ export default class FtpStore { * Create file * @param {string} filePath - Path to file * @param {string} content - File content - * @returns {Promise} A promise to the response + * @returns {Promise} File created */ async createFile(filePath, content) { try { @@ -123,7 +129,7 @@ export default class FtpStore { * Update file * @param {string} filePath - Path to file * @param {string} content - File content - * @returns {Promise} A promise to the response + * @returns {Promise} File updated */ async updateFile(filePath, content) { try { @@ -147,7 +153,7 @@ export default class FtpStore { /** * Delete file * @param {string} filePath - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted */ async deleteFile(filePath) { try { diff --git a/packages/store-gitea/index.js b/packages/store-gitea/index.js index 259856e88..e98304c91 100644 --- a/packages/store-gitea/index.js +++ b/packages/store-gitea/index.js @@ -9,11 +9,15 @@ const defaults = { token: process.env.GITEA_TOKEN, }; -/** - * @typedef Response - * @property {object} response - HTTP response - */ export default class GiteaStore { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.instance] - Instance URL + * @param {string} [options.user] - Username + * @param {string} [options.repo] - Repository + * @param {string} [options.branch] - Branch + * @param {string} [options.token] - Access token + */ constructor(options = {}) { this.id = "gitea"; this.meta = import.meta; @@ -59,11 +63,11 @@ export default class GiteaStore { } /** - * @private + * @access private * @param {string} path - Request path * @param {string} [method=GET] - Request method * @param {object} [body] - Request body - * @returns {Function} Gitea client interface + * @returns {Promise} Gitea client interface */ async #client(path, method = "GET", body) { const { instance, user, repo } = this.options; @@ -92,7 +96,7 @@ export default class GiteaStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} HTTP response + * @returns {Promise} File created * @see {@link https://gitea.com/api/swagger#/repository/repoCreateFile} */ async createFile(path, content, message) { @@ -117,7 +121,7 @@ export default class GiteaStore { /** * Read file in a repository * @param {string} path - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File contents * @see {@link https://gitea.com/api/swagger#/repository/repoGetContents} */ async readFile(path) { @@ -141,7 +145,7 @@ export default class GiteaStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File updated * @see {@link https://gitea.com/api/swagger#/repository/repoUpdateFile} */ async updateFile(path, content, message) { @@ -170,7 +174,7 @@ export default class GiteaStore { * Delete file in a repository * @param {string} path - Path to file * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted * @see {@link https://gitea.com/api/swagger#/repository/repoDeleteFile} */ async deleteFile(path, message) { diff --git a/packages/store-github/index.js b/packages/store-github/index.js index b1b49dfe4..8c616f641 100644 --- a/packages/store-github/index.js +++ b/packages/store-github/index.js @@ -9,11 +9,14 @@ const defaults = { token: process.env.GITHUB_TOKEN, }; -/** - * @typedef Response - * @property {object} response - HTTP response - */ export default class GithubStore { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.user] - Username + * @param {string} [options.repo] - Repository + * @param {string} [options.branch] - Branch + * @param {string} [options.token] - Personal access token + */ constructor(options = {}) { this.id = "github"; this.meta = import.meta; @@ -52,11 +55,11 @@ export default class GithubStore { } /** - * @private + * @access private * @param {string} path - Request path * @param {string} [method=GET] - Request method * @param {object} [body] - Request body - * @returns {Function} GitHub client interface + * @returns {Promise} GitHub client interface */ async #client(path, method = "GET", body) { const { baseUrl, user, repo, token } = this.options; @@ -91,7 +94,7 @@ export default class GithubStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File created * @see {@link https://docs.github.com/en/rest/repos/contents#create-or-update-file-contents} */ async createFile(path, content, message) { @@ -109,7 +112,7 @@ export default class GithubStore { /** * Read file in a repository * @param {string} path - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File content * @see {@link https://docs.github.com/en/rest/repos/contents#get-repository-content} */ async readFile(path) { @@ -124,7 +127,7 @@ export default class GithubStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File updated * @see {@link https://docs.github.com/en/rest/repos/contents#create-or-update-file-contents} */ async updateFile(path, content, message) { @@ -146,7 +149,7 @@ export default class GithubStore { * Delete file in a repository * @param {string} path - Path to file * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted * @see {@link https://docs.github.com/en/rest/repos/contents#delete-a-file} */ async deleteFile(path, message) { diff --git a/packages/store-gitlab/index.js b/packages/store-gitlab/index.js index 0015a5cfb..1ed8d8843 100644 --- a/packages/store-gitlab/index.js +++ b/packages/store-gitlab/index.js @@ -10,10 +10,18 @@ const defaults = { }; /** - * @typedef Response - * @property {object} response - HTTP response + * @typedef {import("@gitbeaker/core").Gitlab} Gitlab */ export default class GitlabStore { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.instance] - Instance URL + * @param {string} [options.projectId] - Project ID + * @param {string} [options.user] - Username + * @param {string} [options.repo] - Repository + * @param {string} [options.branch] - Branch + * @param {string} [options.token] - Access token + */ constructor(options = {}) { this.id = "gitlab"; this.meta = import.meta; @@ -60,8 +68,8 @@ export default class GitlabStore { } /** - * @private - * @returns {Function} GitLab client interface + * @access private + * @returns {Gitlab} GitLab client interface */ get #client() { const { Gitlab } = gitbeaker; @@ -76,7 +84,7 @@ export default class GitlabStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} HTTP response + * @returns {Promise} File created * @see {@link https://docs.gitlab.com/ee/api/repository_files.html#create-new-file-in-repository} */ async createFile(path, content, message) { @@ -106,7 +114,7 @@ export default class GitlabStore { /** * Read file in a repository * @param {string} path - Path to file - * @returns {Promise} A promise to the response + * @returns {Promise} File content * @see {@link https://docs.gitlab.com/ee/api/repository_files.html#get-file-from-repository} */ async readFile(path) { @@ -133,7 +141,7 @@ export default class GitlabStore { * @param {string} path - Path to file * @param {string} content - File content * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File updated * @see {@link https://docs.gitlab.com/ee/api/repository_files.html#update-existing-file-in-repository} */ async updateFile(path, content, message) { @@ -164,7 +172,7 @@ export default class GitlabStore { * Delete file in a repository * @param {string} path - Path to file * @param {string} message - Commit message - * @returns {Promise} A promise to the response + * @returns {Promise} File deleted * @see {@link https://docs.gitlab.com/ee/api/repository_files.html#delete-existing-file-in-repository} */ async deleteFile(path, message) { diff --git a/packages/syndicator-internet-archive/index.js b/packages/syndicator-internet-archive/index.js index 18341beba..5ff5c5e9e 100644 --- a/packages/syndicator-internet-archive/index.js +++ b/packages/syndicator-internet-archive/index.js @@ -11,6 +11,13 @@ const defaults = { }; export default class InternetArchiveSyndicator { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.accessKey] - S3 access key + * @param {string} [options.secretKey] - S3 secret key + * @param {boolean} [options.checked] - Check syndicator in UI + * @param {boolean} [options.forced] - Force syndicator + */ constructor(options = {}) { this.id = "internet-archive"; this.meta = import.meta; diff --git a/packages/syndicator-internet-archive/lib/internet-archive.js b/packages/syndicator-internet-archive/lib/internet-archive.js index 88e922b6d..6dcb0ccc8 100644 --- a/packages/syndicator-internet-archive/lib/internet-archive.js +++ b/packages/syndicator-internet-archive/lib/internet-archive.js @@ -2,8 +2,6 @@ import { fetch } from "undici"; /** * Save Page Now 2 (SPN2) API - * @typedef Response - * @property {object} response - SPN2 response * @param {object} options - Options * @returns {object} SPN2 response * @see {@link https://docs.google.com/document/d/1Nsv52MvSjbLb2PCpHlat0gkzw0EvtSgpKHu4mk0MnrA/} @@ -21,6 +19,7 @@ export const internetArchive = (options) => ({ ...(data && { body: new URLSearchParams(data).toString() }), }); + /** @type {object} */ const body = await response.json(); if (!response.ok) { @@ -68,7 +67,7 @@ export const internetArchive = (options) => ({ /** * Save to Internet Archive * @param {object} properties - JF2 properties object - * @returns {string} URL of archived web page + * @returns {Promise} URL of archived web page */ async save(properties) { // Get a job ID from capture request diff --git a/packages/syndicator-mastodon/index.js b/packages/syndicator-mastodon/index.js index 4cdbb5baa..fec90f429 100644 --- a/packages/syndicator-mastodon/index.js +++ b/packages/syndicator-mastodon/index.js @@ -10,6 +10,15 @@ const defaults = { }; export default class MastodonSyndicator { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.accessToken] - Access token + * @param {string} [options.characterLimit] - Server character limit + * @param {string} [options.url] - Server URL + * @param {string} [options.user] - Username + * @param {boolean} [options.checked] - Check syndicator in UI + * @param {boolean} [options.forced] - Force syndicator + */ constructor(options = {}) { this.id = "mastodon"; this.meta = import.meta; diff --git a/packages/syndicator-mastodon/lib/mastodon.js b/packages/syndicator-mastodon/lib/mastodon.js index 1c8ee27e6..5fa4439d6 100644 --- a/packages/syndicator-mastodon/lib/mastodon.js +++ b/packages/syndicator-mastodon/lib/mastodon.js @@ -17,7 +17,7 @@ export const mastodon = ({ accessToken, characterLimit, serverUrl }) => ({ /** * Post a favourite * @param {string} tootUrl - URL of toot to favourite - * @returns {string} Mastodon status URL + * @returns {Promise} Mastodon status URL */ async postFavourite(tootUrl) { const statusId = getStatusIdFromUrl(tootUrl); @@ -28,7 +28,7 @@ export const mastodon = ({ accessToken, characterLimit, serverUrl }) => ({ /** * Post a reblog * @param {string} tootUrl - URL of toot to reblog - * @returns {string} Mastodon status URL + * @returns {Promise} Mastodon status URL */ async postReblog(tootUrl) { const statusId = getStatusIdFromUrl(tootUrl); @@ -39,7 +39,7 @@ export const mastodon = ({ accessToken, characterLimit, serverUrl }) => ({ /** * Post a status * @param {object} parameters - Status parameters - * @returns {string} Mastodon status URL + * @returns {Promise} Mastodon status URL */ async postStatus(parameters) { const { data } = await this.client().postStatus(parameters.status, { @@ -51,9 +51,9 @@ export const mastodon = ({ accessToken, characterLimit, serverUrl }) => ({ /** * Upload media and return Mastodon media id - * @param {string} media - JF2 media object + * @param {object} media - JF2 media object * @param {string} me - Publication URL - * @returns {string} Mastodon media id + * @returns {Promise} Mastodon media id */ async uploadMedia(media, me) { const { alt, url } = media; @@ -81,7 +81,7 @@ export const mastodon = ({ accessToken, characterLimit, serverUrl }) => ({ * Post to Mastodon * @param {object} properties - JF2 properties object * @param {object} publication - Publication configuration - * @returns {string} URL of syndicated toot + * @returns {Promise} URL of syndicated toot */ async post(properties, publication) { let mediaIds = []; diff --git a/packages/syndicator-mastodon/lib/utils.js b/packages/syndicator-mastodon/lib/utils.js index 23d61f7ad..8f0512346 100644 --- a/packages/syndicator-mastodon/lib/utils.js +++ b/packages/syndicator-mastodon/lib/utils.js @@ -8,9 +8,9 @@ import { htmlToText } from "html-to-text"; * Get status parameters from given JF2 properties * @param {object} properties - A JF2 properties object * @param {object} [options={}] - Options - * @param {number} options.characterLimit - Character limit - * @param {Array} options.mediaIds - Mastodon media IDs - * @param {string} options.serverUrl - Server URL, i.e. https://mastodon.social + * @param {number} [options.characterLimit] - Character limit + * @param {Array} [options.mediaIds] - Mastodon media IDs + * @param {string} [options.serverUrl] - Server URL, i.e. https://mastodon.social * @returns {object} Status parameters */ export const createStatus = (properties, options = {}) => { @@ -73,7 +73,7 @@ export const createStatus = (properties, options = {}) => { * Get absolute URL * @param {string} string - URL or path * @param {string} me - Publication URL - * @returns {URL} Absolute URL + * @returns {string} Absolute URL */ export const getAbsoluteUrl = (string, me) => { try { diff --git a/packages/syndicator-twitter/index.js b/packages/syndicator-twitter/index.js index 13ce53f29..8d65ed114 100644 --- a/packages/syndicator-twitter/index.js +++ b/packages/syndicator-twitter/index.js @@ -11,6 +11,16 @@ const defaults = { }; export default class TwitterSyndicator { + /** + * @param {object} [options={}] - Plugin options + * @param {string} [options.accessToken] - Access token + * @param {string} [options.accessTokenSecret] - Access token secret + * @param {string} [options.apiKey] - API key + * @param {string} [options.apiKeySecret] - API key secret + * @param {string} [options.user] - Username + * @param {boolean} [options.checked] - Check syndicator in UI + * @param {boolean} [options.forced] - Force syndicator + */ constructor(options = {}) { this.id = "twitter"; this.meta = import.meta; diff --git a/packages/syndicator-twitter/lib/twitter.js b/packages/syndicator-twitter/lib/twitter.js index bb8a7dd5a..05111e8c2 100644 --- a/packages/syndicator-twitter/lib/twitter.js +++ b/packages/syndicator-twitter/lib/twitter.js @@ -22,7 +22,7 @@ export const twitter = (options) => ({ /** * Post a like * @param {string} tweetUrl - URL of tweet to like - * @returns {string} Twitter status URL + * @returns {Promise} Twitter status URL */ async postLike(tweetUrl) { try { @@ -41,7 +41,7 @@ export const twitter = (options) => ({ /** * Post a retweet * @param {string} tweetUrl - URL of tweet to retweet - * @returns {string} Twitter status URL + * @returns {Promise} Twitter status URL */ async postRetweet(tweetUrl) { try { @@ -60,7 +60,7 @@ export const twitter = (options) => ({ /** * Post a status * @param {object} parameters - Status parameters - * @returns {string} Twitter status URL + * @returns {Promise} Twitter status URL */ async postStatus(parameters) { try { @@ -78,9 +78,9 @@ export const twitter = (options) => ({ /** * Upload media and return Twitter media id - * @param {string} media - JF2 media object + * @param {object} media - JF2 media object * @param {string} me - Publication URL - * @returns {string} Twitter media id + * @returns {Promise} Twitter media id */ async uploadMedia(media, me) { const { alt, url } = media; @@ -122,7 +122,7 @@ export const twitter = (options) => ({ * Post to Twitter * @param {object} properties - JF2 properties object * @param {object} publication - Publication configuration - * @returns {string} URL of syndicated tweet + * @returns {Promise} URL of syndicated tweet */ async post(properties, publication) { let mediaIds = []; diff --git a/packages/syndicator-twitter/lib/utils.js b/packages/syndicator-twitter/lib/utils.js index 0806dd5b9..3e2c19470 100644 --- a/packages/syndicator-twitter/lib/utils.js +++ b/packages/syndicator-twitter/lib/utils.js @@ -7,10 +7,10 @@ import { htmlToText } from "html-to-text"; /** * Get status parameters from given JF2 properties * @param {object} properties - A JF2 properties object - * @param {Array} mediaIds - Twitter media IDs + * @param {Array|null} [mediaIds=null] - Twitter media IDs * @returns {object} Status parameters */ -export const createStatus = (properties, mediaIds = false) => { +export const createStatus = (properties, mediaIds = null) => { const parameters = {}; let status; @@ -74,7 +74,7 @@ export const createStatus = (properties, mediaIds = false) => { * Get absolute URL * @param {string} string - URL or path * @param {string} me - Publication URL - * @returns {URL} Absolute URL + * @returns {string} Absolute URL */ export const getAbsoluteUrl = (string, me) => { try { diff --git a/types/express/index.d.ts b/types/express/index.d.ts new file mode 100644 index 000000000..f1b9067ec --- /dev/null +++ b/types/express/index.d.ts @@ -0,0 +1,19 @@ +import { Express } from "express-serve-static-core"; + +declare global { + namespace Express { + interface Request { + verifiedToken: { + client_id: string; + code_challenge: string; + code_challenge_method: string; + jti: string; + me: string; + redirect_uri: string; + scope: string; + iat: number; + exp: number; + }; + } + } +}