Rolled out API framework JSDoc typing to more places

- this updates a bunch of places where we're just using Object to cheat
  the system
- doing this means editor autocomplete and basic type checking is better
  because we now have proper types in place
- functionality should not change, these are just comments
This commit is contained in:
Daniel Lockyer 2024-05-08 09:17:41 +02:00 committed by Daniel Lockyer
parent 1fea2fc616
commit 82c612bad9
14 changed files with 58 additions and 40 deletions

View File

@ -99,8 +99,8 @@ module.exports = {
*
* @param {Object} result - API response
* @param {Object} apiConfigHeaders
* @param {Object} frame
* @return {Promise}
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise<object>}
*/
async get(result, apiConfigHeaders = {}, frame) {
let headers = {};

View File

@ -10,7 +10,7 @@ const headers = require('./headers');
* This wrapper is used in the routes definition (see web/).
* The wrapper receives the express request, prepares the frame and forwards the request to the pipeline.
*
* @param {Function} apiImpl - Pipeline wrapper, which executes the target ctrl function.
* @param {import('@tryghost/api-framework').Controller} apiImpl - Pipeline wrapper, which executes the target ctrl function.
* @return {import('express').RequestHandler}
*/
const http = (apiImpl) => {
@ -18,6 +18,7 @@ const http = (apiImpl) => {
* @param {import('express').Request} req - Express request object.
* @param {import('express').Response} res - Express response object.
* @param {import('express').NextFunction} next - Express next function.
* @returns {Promise<import('express').RequestHandler>}
*/
return async function Http(req, res, next) {
debug(`External API request to ${req.url}`);

View File

@ -20,8 +20,8 @@ const STAGES = {
*
* @param {Object} apiUtils - Local utils of target API version.
* @param {Object} apiConfig - Docname & Method of ctrl.
* @param {Object} apiImpl - Controller configuration.
* @param {Object} frame
* @param {import('@tryghost/api-framework').ControllerMethod} apiImpl - Controller configuration.
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
input(apiUtils, apiConfig, apiImpl, frame) {
@ -57,8 +57,8 @@ const STAGES = {
*
* @param {Object} apiUtils - Local utils of target API version.
* @param {Object} apiConfig - Docname & Method of ctrl.
* @param {Object} apiImpl - Controller configuration.
* @param {Object} frame
* @param {import('@tryghost/api-framework').ControllerMethod} apiImpl - Controller configuration.
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
input(apiUtils, apiConfig, apiImpl, frame) {
@ -80,8 +80,8 @@ const STAGES = {
*
* @param {Object} apiUtils - Local utils of target API version.
* @param {Object} apiConfig - Docname & Method of ctrl.
* @param {Object} apiImpl - Controller configuration.
* @param {Object} frame
* @param {import('@tryghost/api-framework').ControllerMethod} apiImpl - Controller configuration.
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
output(response, apiUtils, apiConfig, apiImpl, frame) {
@ -99,8 +99,8 @@ const STAGES = {
*
* @param {Object} apiUtils - Local utils of target API version.
* @param {Object} apiConfig - Docname & Method of ctrl.
* @param {Object} apiImpl - Controller configuration.
* @param {Object} frame
* @param {import('@tryghost/api-framework').ControllerMethod} apiImpl - Controller configuration.
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
permissions(apiUtils, apiConfig, apiImpl, frame) {
@ -145,8 +145,8 @@ const STAGES = {
*
* @param {Object} apiUtils - Local utils of target API version.
* @param {Object} apiConfig - Docname & Method of ctrl.
* @param {Object} apiImpl - Controller configuration.
* @param {Object} frame
* @param {import('@tryghost/api-framework').ControllerMethod} apiImpl - Controller configuration.
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
query(apiUtils, apiConfig, apiImpl, frame) {
@ -176,7 +176,7 @@ const controllerMap = new Map();
* 4. Controller - Execute the controller implementation & receive model response.
* 5. Output Serialisation - Output formatting, Deprecations, Extra attributes etc...
*
* @param {Object} apiController
* @param {import('@tryghost/api-framework').Controller} apiController
* @param {Object} apiUtils - Local utils (validation & serialisation) from target API version
* @param {String} [apiType] - Content or Admin API access
* @return {Object}

View File

@ -12,7 +12,7 @@ const errors = require('@tryghost/errors');
*
* @param {Object} apiConfig - Docname + method of the ctrl
* @param {Object} apiSerializers - Target API serializers
* @param {Object} frame
* @param {import('@tryghost/api-framework').Frame} frame
*/
module.exports.input = (apiConfig, apiSerializers, frame) => {
debug('input');
@ -90,7 +90,7 @@ const getBestMatchSerializer = function (apiSerializers, docName, method) {
* @param {Object} response - API response
* @param {Object} apiConfig - Docname + method of the ctrl
* @param {Object} apiSerializers - Target API serializers
* @param {Object} frame
* @param {import('@tryghost/api-framework').Frame} frame
*/
module.exports.output = (response = {}, apiConfig, apiSerializers, frame) => {
debug('output');

View File

@ -12,7 +12,7 @@ const {sequence} = require('@tryghost/promise');
*
* @param {Object} apiConfig - Docname + method of the ctrl
* @param {Object} apiValidators - Target API validators
* @param {Object} frame
* @param {import('@tryghost/api-framework').Frame} frame
*/
module.exports.input = (apiConfig, apiValidators, frame) => {
debug('input begin');

View File

@ -90,6 +90,10 @@ const validate = (config, attrs) => {
};
module.exports = {
/**
* @param {object} apiConfig
* @param {import('@tryghost/api-framework').Frame} frame
*/
all(apiConfig, frame) {
debug('validate all');
@ -102,6 +106,10 @@ module.exports = {
return Promise.resolve();
},
/**
* @param {object} apiConfig
* @param {import('@tryghost/api-framework').Frame} frame
*/
browse(apiConfig, frame) {
debug('validate browse');
@ -121,6 +129,10 @@ module.exports = {
return this.browse(...arguments);
},
/**
* @param {object} apiConfig
* @param {import('@tryghost/api-framework').Frame} frame
*/
add(apiConfig, frame) {
debug('validate add');
@ -168,6 +180,10 @@ module.exports = {
}
},
/**
* @param {object} apiConfig
* @param {import('@tryghost/api-framework').Frame} frame
*/
edit(apiConfig, frame) {
debug('validate edit');
const result = this.add(...arguments);

View File

@ -19,17 +19,25 @@ module.exports = {
* is a Content API implementation - see index.js file.
*
* @TODO: Move this helper function into a utils.js file.
* @param {Object} frame
* @param {import('@tryghost/api-framework').Frame} frame
* @return {boolean}
*/
isContentAPI: (frame) => {
return frame.apiType === 'content';
},
/**
* @param {import('@tryghost/api-framework').Frame} frame
* @returns {boolean}
*/
isMembersAPI: (frame) => {
return frame.apiType === 'members';
},
/**
* @param {import('@tryghost/api-framework').Frame} frame
* @returns {boolean}
*/
isInternal: (frame) => {
return frame.options.context && frame.options.context.internal;
}

View File

@ -12,7 +12,7 @@ const messages = {
* @description Handle requests, which need authentication.
*
* @param {Object} apiConfig - Docname & method of API ctrl
* @param {Object} frame
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
const nonePublicAuth = (apiConfig, frame) => {
@ -81,7 +81,7 @@ module.exports = {
* @description Handle permission stage for API.
*
* @param {Object} apiConfig - Docname & method of target ctrl.
* @param {Object} frame
* @param {import('@tryghost/api-framework').Frame} frame
* @return {Promise}
*/
handle(apiConfig, frame) {

View File

@ -28,7 +28,7 @@ module.exports = {
*
* @param {{data: import('bookshelf').Model[], meta: PageMeta}} page
* @param {APIConfig} _apiConfig
* @param {Frame} frame
* @param {import('@tryghost/api-framework').Frame} frame
*
* @returns {{members: SerializedMember[], meta: PageMeta}}
*/
@ -42,7 +42,7 @@ function paginatedMembers(page, _apiConfig, frame) {
/**
* @param {import('bookshelf').Model} model
* @param {APIConfig} _apiConfig
* @param {Frame} frame
* @param {import('@tryghost/api-framework').Frame} frame
*
* @returns {{members: SerializedMember[]}}
*/
@ -55,7 +55,7 @@ function singleMember(model, _apiConfig, frame) {
/**
* @param {object} bulkActionResult
* @param {APIConfig} _apiConfig
* @param {Frame} frame
* @param {import('@tryghost/api-framework').Frame} frame
*
* @returns {{bulk: SerializedBulkAction}}
*/
@ -219,9 +219,9 @@ function passthrough(data) {
* @template Data
* @template Response
* @param {string} debugString
* @param {(data: Data, apiConfig: APIConfig, frame: Frame) => Response} serialize - A function to serialize the data into an object suitable for API response
* @param {(data: Data, apiConfig: APIConfig, frame: import('@tryghost/api-framework').Frame) => Response} serialize
*
* @returns {(data: Data, apiConfig: APIConfig, frame: Frame) => void}
* @returns {(data: Data, apiConfig: APIConfig, frame: import('@tryghost/api-framework').Frame) => void}
*/
function createSerializer(debugString, serialize) {
return function serializer(data, apiConfig, frame) {
@ -355,8 +355,3 @@ function createSerializer(debugString, serialize) {
* @prop {string} docName
* @prop {string} method
*/
/**
* @typedef {Object<string, any>} Frame
* @prop {Object} options
*/

View File

@ -2,6 +2,8 @@ const _ = require('lodash');
const utils = require('../../index');
const mappers = require('./mappers');
/** @typedef {import('@tryghost/api-framework').Frame} Frame */
/**
* Filters an object based on a given filter object
* @private
@ -25,7 +27,7 @@ function settingsFilter(settings, filter) {
*
* @param {Object} models
* @param {Object} apiConfig
* @param {Object} frame
* @param {Frame} frame
*/
function serializeSettings(models, apiConfig, frame) {
let filteredSettings;
@ -79,7 +81,7 @@ function passthrough(data) {
* @template Data
* @param {Data} data
* @param {Object} apiConfig
* @param {Object} frame
* @param {Frame} frame
*/
function serializeData(data, apiConfig, frame) {
frame.response = data;

View File

@ -131,7 +131,4 @@ function createSerializer(debugString, serialize) {
* @prop {string} method
*/
/**
* @typedef {Object<string, any>} Frame
* @prop {Object} options
*/
/** @typedef {import('@tryghost/api-framework').Frame} Frame */

View File

@ -5,8 +5,7 @@ const jsonSchema = require('@tryghost/admin-api-schema');
* @param {Object} apiConfig "frame" api configuration object
* @param {string} apiConfig.docName the name of the resource
* @param {string} apiConfig.method API's method name
* @param {Object} frame "frame" object with data attached to it
* @param {Object} frame.data request data to validate
* @param {import('@tryghost/api-framework').Frame} frame "frame" object with data attached to it
*/
const validate = async (apiConfig, frame) => await jsonSchema.validate({
data: frame.data,

View File

@ -2,7 +2,7 @@ const _ = require('lodash');
const errors = require('@tryghost/errors');
/**
* @typedef {import('../../api/shared/frame')} Frame
* @typedef {import('@tryghost/api-framework').Frame} Frame
*/
const {MethodNotAllowedError} = require('@tryghost/errors');

View File

@ -110,7 +110,7 @@ class PostsService {
/**
*
* @param {any} frame
* @param {import('@tryghost/api-framework').Frame} frame
* @param {object} [options]
* @param {(event: EventString, dto: any) => Promise<void> | void} [options.eventHandler] - Called before the editPost method resolves with an event string
* @returns