eslint-plugin-next-route-params
Version:
eslint rule to enforce correct route parameters for Next.js
109 lines (108 loc) • 5.41 kB
JavaScript
;
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;