UNPKG

eslint-plugin-next-route-params

Version:

eslint rule to enforce correct route parameters for Next.js

109 lines (108 loc) 5.41 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createGenerateStaticParamsReturntypeString = exports.createGenerateStaticParamsReturntypeArrayArgumentString = exports.SEARCHPARAMS_TYPE_NODE_STRING = void 0; exports.createParamsTypeNodeString = createParamsTypeNodeString; const typescript_1 = __importDefault(require("typescript")); function wrapTypeWithIdentifier({ type, identifier, }) { return typescript_1.default.factory.createTypeReferenceNode(typescript_1.default.factory.createIdentifier(identifier), [type]); } function wrapTypeWithPromise({ type }) { return wrapTypeWithIdentifier({ type, identifier: "Promise" }); } function wrapTypeWithArray({ type }) { return typescript_1.default.factory.createArrayTypeNode(type); } function makeUnionType(...types) { return typescript_1.default.factory.createUnionTypeNode(types); } function makeRecordType(from, to) { return typescript_1.default.factory.createTypeReferenceNode(typescript_1.default.factory.createIdentifier("Record"), [from, to]); } const STRING_TYPE_NODE = typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.StringKeyword); /** * will equal to ```[key: string]``` */ const SEARCHPARAMS_KEY_TYPE_NODE = typescript_1.default.factory.createParameterDeclaration(undefined, undefined, typescript_1.default.factory.createIdentifier("key"), undefined, STRING_TYPE_NODE); /** * will equal to ```string | string[] | undefined``` */ const SEARCHPARAMS_VALUE_TYPE_NODE = makeUnionType(STRING_TYPE_NODE, wrapTypeWithArray({ type: STRING_TYPE_NODE }), typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.UndefinedKeyword)); /** * will equal to ```[key :string]: string | string[] | undefined``` */ const SEARCHPARAMS_TYPE_NODE = (asyncRequestAPI) => { const searchParamsType = typescript_1.default.factory.createTypeLiteralNode([ typescript_1.default.factory.createIndexSignature(undefined, [SEARCHPARAMS_KEY_TYPE_NODE], SEARCHPARAMS_VALUE_TYPE_NODE), ]); if (!asyncRequestAPI) { return searchParamsType; } return wrapTypeWithPromise({ type: searchParamsType }); }; /** * will equal to ```Record<string, never>``` */ const createEmptyParamsTypeNode = ({ asyncRequestAPI }) => { const recordType = makeRecordType(STRING_TYPE_NODE, typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NeverKeyword)); if (asyncRequestAPI) { return wrapTypeWithPromise({ type: recordType }); } return recordType; }; /** * will equal to an object literal * * ```[ {name: "postId", catchAll: false } , { name: "userId", catchAll: true }]``` will equal to * ``` * { postId: string, * userId: string[] * } * ``` * */ function createParamsTypeNode({ asyncRequestAPI, params }) { const paramsType = typescript_1.default.factory.createTypeLiteralNode(params.map((param) => typescript_1.default.factory.createPropertySignature(undefined, typescript_1.default.factory.createIdentifier(param.name), undefined, !param.catchAll ? STRING_TYPE_NODE : typescript_1.default.factory.createArrayTypeNode(STRING_TYPE_NODE)))); if (!asyncRequestAPI) { return paramsType; } return wrapTypeWithPromise({ type: paramsType }); } const createGenerateStaticParamsReturntypeArrayArgument = (params) => typescript_1.default.factory.createTypeLiteralNode(params.map((param) => typescript_1.default.factory.createPropertySignature(undefined, typescript_1.default.factory.createIdentifier(param.name), !param.current ? typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionToken) : undefined, !param.catchAll ? STRING_TYPE_NODE : typescript_1.default.factory.createArrayTypeNode(STRING_TYPE_NODE)))); const createGenerateStaticParamsReturntype = (async, params) => { const type = wrapTypeWithArray({ type: createGenerateStaticParamsReturntypeArrayArgument(params), }); if (async) { return wrapTypeWithPromise({ type }); } return type; }; function stringify(typeNodeOrFactory) { const stringifier = (typeNode) => typescript_1.default .createPrinter() .printNode(typescript_1.default.EmitHint.Unspecified, typeNode, undefined); if (typeof typeNodeOrFactory === "function") { return (...params) => stringifier(typeNodeOrFactory(...params)); } return stringifier(typeNodeOrFactory); } /***************** STRINGIFIED TYPES******************/ exports.SEARCHPARAMS_TYPE_NODE_STRING = stringify(SEARCHPARAMS_TYPE_NODE); const creatEmptyParamsTypeNodeString = stringify(createEmptyParamsTypeNode); function createParamsTypeNodeString(generatorParams) { return generatorParams.params.length === 0 ? creatEmptyParamsTypeNodeString(generatorParams) : stringify(createParamsTypeNode)(generatorParams); } exports.createGenerateStaticParamsReturntypeArrayArgumentString = stringify(createGenerateStaticParamsReturntypeArrayArgument); const createGenerateStaticParamsReturntypeString = (async, params) => `${stringify(createGenerateStaticParamsReturntype(async, params))} `; exports.createGenerateStaticParamsReturntypeString = createGenerateStaticParamsReturntypeString;