diff --git a/ghost/link-redirects/.eslintrc.js b/ghost/link-redirects/.eslintrc.js new file mode 100644 index 0000000000..c9c1bcb522 --- /dev/null +++ b/ghost/link-redirects/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: ['ghost'], + extends: [ + 'plugin:ghost/node' + ] +}; diff --git a/ghost/link-redirects/README.md b/ghost/link-redirects/README.md new file mode 100644 index 0000000000..a4ccb2c18f --- /dev/null +++ b/ghost/link-redirects/README.md @@ -0,0 +1,21 @@ +# Link Redirects + + +## Usage + + +## Develop + +This is a monorepo package. + +Follow the instructions for the top-level repo. +1. `git clone` this repo & `cd` into it as usual +2. Run `yarn` to install top-level dependencies. + + + +## Test + +- `yarn lint` run just eslint +- `yarn test` run lint and tests + diff --git a/ghost/link-redirects/index.js b/ghost/link-redirects/index.js new file mode 100644 index 0000000000..bb9dae614a --- /dev/null +++ b/ghost/link-redirects/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/link-redirects'); diff --git a/ghost/link-redirects/lib/LinkRedirect.js b/ghost/link-redirects/lib/LinkRedirect.js new file mode 100644 index 0000000000..a44f8e4c38 --- /dev/null +++ b/ghost/link-redirects/lib/LinkRedirect.js @@ -0,0 +1,23 @@ +const ObjectID = require('bson-objectid').default; + +module.exports = class LinkRedirect { + /** @type {ObjectID} */ + link_id; + /** @type {URL} */ + from; + /** @type {URL} */ + to; + + constructor(data) { + if (!data.id) { + this.link_id = new ObjectID(); + } + + if (typeof data.id === 'string') { + this.link_id = ObjectID.createFromHexString(data.id); + } + + this.from = data.from; + this.to = data.to; + } +}; diff --git a/ghost/link-redirects/lib/LinkRedirectsService.js b/ghost/link-redirects/lib/LinkRedirectsService.js new file mode 100644 index 0000000000..656b080c40 --- /dev/null +++ b/ghost/link-redirects/lib/LinkRedirectsService.js @@ -0,0 +1,34 @@ +const LinkRedirect = require('./LinkRedirect'); + +class LinkRedirectsService { + /** + * @param {URL} to + * + * @returns {Promise} + */ + async addRedirect(to) { + const from = new URL(to); + + from.searchParams.set('redirected', 'true'); // Dummy for skateboard + + const link = new LinkRedirect({ + to, + from + }); + + return link; + } + + /** + * @param {import('express').Request} req + * @param {import('express').Response} res + * @param {import('express').NextFunction} next + * + * @returns {Promise} + */ + async handleRequest(req, res, next) { + return next(); + } +} + +module.exports = LinkRedirectsService; diff --git a/ghost/link-redirects/lib/RedirectEvent.js b/ghost/link-redirects/lib/RedirectEvent.js new file mode 100644 index 0000000000..2f8635d9ee --- /dev/null +++ b/ghost/link-redirects/lib/RedirectEvent.js @@ -0,0 +1,24 @@ +/** + * @typedef {object} RedirectEventData + * @prop {URL} url + * @prop {import('./LinkRedirect')} link + */ + +module.exports = class RedirectEvent { + /** + * @param {RedirectEventData} data + * @param {Date} timestamp + */ + constructor(data, timestamp) { + this.data = data; + this.timestamp = timestamp; + } + + /** + * @param {RedirectEventData} data + * @param {Date} [timestamp] + */ + static create(data, timestamp) { + return new RedirectEvent(data, timestamp ?? new Date); + } +}; diff --git a/ghost/link-redirects/lib/link-redirects.js b/ghost/link-redirects/lib/link-redirects.js new file mode 100644 index 0000000000..950add53db --- /dev/null +++ b/ghost/link-redirects/lib/link-redirects.js @@ -0,0 +1,5 @@ +module.exports = { + LinkRedirect: require('./LinkRedirect'), + RedirectEvent: require('./RedirectEvent'), + LinkRedirectsService: require('./LinkRedirectsService') +}; diff --git a/ghost/link-redirects/package.json b/ghost/link-redirects/package.json new file mode 100644 index 0000000000..d045ad00c8 --- /dev/null +++ b/ghost/link-redirects/package.json @@ -0,0 +1,30 @@ +{ + "name": "@tryghost/link-redirects", + "version": "0.0.0", + "repository": "https://github.com/TryGhost/Ghost/tree/main/packages/link-redirects", + "author": "Ghost Foundation", + "private": true, + "main": "index.js", + "scripts": { + "dev": "echo \"Implement me!\"", + "test:unit": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", + "test": "yarn test:unit", + "lint:code": "eslint *.js lib/ --ext .js --cache", + "lint": "yarn lint:code && yarn lint:test", + "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache" + }, + "files": [ + "index.js", + "lib" + ], + "devDependencies": { + "@types/express": "^4.17.14", + "c8": "7.12.0", + "mocha": "10.0.0", + "should": "13.2.3", + "sinon": "14.0.0" + }, + "dependencies": { + "bson-objectid": "^2.0.3" + } +} diff --git a/ghost/link-redirects/test/.eslintrc.js b/ghost/link-redirects/test/.eslintrc.js new file mode 100644 index 0000000000..829b601eb0 --- /dev/null +++ b/ghost/link-redirects/test/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: ['ghost'], + extends: [ + 'plugin:ghost/test' + ] +}; diff --git a/ghost/link-redirects/test/LinkRedirectsService.test.js b/ghost/link-redirects/test/LinkRedirectsService.test.js new file mode 100644 index 0000000000..0391d32510 --- /dev/null +++ b/ghost/link-redirects/test/LinkRedirectsService.test.js @@ -0,0 +1,5 @@ +describe('LinkRedirectsService', function () { + it('exists', function () { + require('../lib/LinkRedirectsService'); + }); +}); diff --git a/yarn.lock b/yarn.lock index 8985b16aef..5dcbaf4a39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3912,6 +3912,16 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/express@^4.17.14": + version "4.17.14" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" + integrity sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/fs-extra@^5.0.5": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" @@ -6882,7 +6892,7 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -bson-objectid@2.0.3: +bson-objectid@2.0.3, bson-objectid@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/bson-objectid/-/bson-objectid-2.0.3.tgz#d840185172846b2f10c42ce2bcdb4a50956a9db5" integrity sha512-WYwVtY9yqk179EPMNuF3vcxufdrGLEo2XwqdRVbfLVe9X6jLt7WKZQgP+ObOcprakBGbHxzl76tgTaieqsH29g==