New:Socket for Asana Is Now Available.Learn more
Get Started

@tanstack/eslint-plugin-router

Package Overview
Dependencies
Maintainers
6
Versions
72
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/eslint-plugin-router - npm Package Compare versions

Comparing version
1.161.5
to
1.161.6
+22
-27
dist/cjs/index.cjs

@@ -1,31 +0,26 @@

"use strict";
const rules = require("./rules.cjs");
const plugin = {
meta: {
name: "@tanstack/eslint-plugin-router"
},
configs: {},
rules: rules.rules
//#region src/index.ts
var plugin = {
meta: { name: "@tanstack/eslint-plugin-router" },
configs: {},
rules: require("./rules.cjs").rules
};
Object.assign(plugin.configs, {
recommended: {
plugins: ["@tanstack/eslint-plugin-router"],
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
},
"flat/recommended": [
{
plugins: {
"@tanstack/router": plugin
},
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
}
]
recommended: {
plugins: ["@tanstack/eslint-plugin-router"],
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
},
"flat/recommended": [{
plugins: { "@tanstack/router": plugin },
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
}]
});
//#endregion
module.exports = plugin;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import { rules } from './rules'\nimport type { ESLint, Linter } from 'eslint'\nimport type { RuleModule } from '@typescript-eslint/utils/ts-eslint'\n\ntype RuleKey = keyof typeof rules\n\ninterface Plugin extends Omit<ESLint.Plugin, 'rules'> {\n rules: Record<RuleKey, RuleModule<any, any, any>>\n configs: {\n recommended: ESLint.ConfigData\n 'flat/recommended': Array<Linter.FlatConfig>\n }\n}\n\nconst plugin: Plugin = {\n meta: {\n name: '@tanstack/eslint-plugin-router',\n },\n configs: {} as Plugin['configs'],\n rules,\n}\n\n// Assign configs here so we can reference `plugin`\nObject.assign(plugin.configs, {\n recommended: {\n plugins: ['@tanstack/eslint-plugin-router'],\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n 'flat/recommended': [\n {\n plugins: {\n '@tanstack/router': plugin,\n },\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n ],\n})\n\nexport default plugin\n"],"names":["rules"],"mappings":";;AAcA,MAAM,SAAiB;AAAA,EACrB,MAAM;AAAA,IACJ,MAAM;AAAA,EAAA;AAAA,EAER,SAAS,CAAA;AAAA,EAAC,OACVA,MAAAA;AACF;AAGA,OAAO,OAAO,OAAO,SAAS;AAAA,EAC5B,aAAa;AAAA,IACX,SAAS,CAAC,gCAAgC;AAAA,IAC1C,OAAO;AAAA,MACL,gDAAgD;AAAA,MAChD,sCAAsC;AAAA,IAAA;AAAA,EACxC;AAAA,EAEF,oBAAoB;AAAA,IAClB;AAAA,MACE,SAAS;AAAA,QACP,oBAAoB;AAAA,MAAA;AAAA,MAEtB,OAAO;AAAA,QACL,gDAAgD;AAAA,QAChD,sCAAsC;AAAA,MAAA;AAAA,IACxC;AAAA,EACF;AAEJ,CAAC;;"}
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import { rules } from './rules'\nimport type { ESLint, Linter } from 'eslint'\nimport type { RuleModule } from '@typescript-eslint/utils/ts-eslint'\n\ntype RuleKey = keyof typeof rules\n\ninterface Plugin extends Omit<ESLint.Plugin, 'rules'> {\n rules: Record<RuleKey, RuleModule<any, any, any>>\n configs: {\n recommended: ESLint.ConfigData\n 'flat/recommended': Array<Linter.FlatConfig>\n }\n}\n\nconst plugin: Plugin = {\n meta: {\n name: '@tanstack/eslint-plugin-router',\n },\n configs: {} as Plugin['configs'],\n rules,\n}\n\n// Assign configs here so we can reference `plugin`\nObject.assign(plugin.configs, {\n recommended: {\n plugins: ['@tanstack/eslint-plugin-router'],\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n 'flat/recommended': [\n {\n plugins: {\n '@tanstack/router': plugin,\n },\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n ],\n})\n\nexport default plugin\n"],"mappings":";AAcA,IAAM,SAAiB;CACrB,MAAM,EACJ,MAAM,kCACP;CACD,SAAS,EAAE;CACX,8BAAA;CACD;AAGD,OAAO,OAAO,OAAO,SAAS;CAC5B,aAAa;EACX,SAAS,CAAC,iCAAiC;EAC3C,OAAO;GACL,gDAAgD;GAChD,sCAAsC;GACvC;EACF;CACD,oBAAoB,CAClB;EACE,SAAS,EACP,oBAAoB,QACrB;EACD,OAAO;GACL,gDAAgD;GAChD,sCAAsC;GACvC;EACF,CACF;CACF,CAAC"}

@@ -1,10 +0,11 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const createRoutePropertyOrder_rule = require("./rules/create-route-property-order/create-route-property-order.rule.cjs");
const routeParamNames_rule = require("./rules/route-param-names/route-param-names.rule.cjs");
const rules = {
[createRoutePropertyOrder_rule.name]: createRoutePropertyOrder_rule.rule,
[routeParamNames_rule.name]: routeParamNames_rule.rule
const require_create_route_property_order_rule = require("./rules/create-route-property-order/create-route-property-order.rule.cjs");
const require_route_param_names_rule = require("./rules/route-param-names/route-param-names.rule.cjs");
//#region src/rules.ts
var rules = {
[require_create_route_property_order_rule.name]: require_create_route_property_order_rule.rule,
[require_route_param_names_rule.name]: require_route_param_names_rule.rule
};
//#endregion
exports.rules = rules;
//# sourceMappingURL=rules.cjs.map
//# sourceMappingURL=rules.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"rules.cjs","sources":["../../src/rules.ts"],"sourcesContent":["import * as createRoutePropertyOrder from './rules/create-route-property-order/create-route-property-order.rule'\nimport * as routeParamNames from './rules/route-param-names/route-param-names.rule'\nimport type { ESLintUtils } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from './types'\n\nexport const rules: Record<\n string,\n ESLintUtils.RuleModule<\n string,\n ReadonlyArray<unknown>,\n ExtraRuleDocs,\n ESLintUtils.RuleListener\n >\n> = {\n [createRoutePropertyOrder.name]: createRoutePropertyOrder.rule,\n [routeParamNames.name]: routeParamNames.rule,\n}\n"],"names":["createRoutePropertyOrder.name","createRoutePropertyOrder.rule","routeParamNames.name","routeParamNames.rule"],"mappings":";;;;AAKO,MAAM,QAQT;AAAA,EACF,CAACA,8BAAAA,IAA6B,GAAGC,8BAAAA;AAAAA,EACjC,CAACC,yBAAoB,GAAGC,qBAAAA;AAC1B;;"}
{"version":3,"file":"rules.cjs","names":[],"sources":["../../src/rules.ts"],"sourcesContent":["import * as createRoutePropertyOrder from './rules/create-route-property-order/create-route-property-order.rule'\nimport * as routeParamNames from './rules/route-param-names/route-param-names.rule'\nimport type { ESLintUtils } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from './types'\n\nexport const rules: Record<\n string,\n ESLintUtils.RuleModule<\n string,\n ReadonlyArray<unknown>,\n ExtraRuleDocs,\n ESLintUtils.RuleListener\n >\n> = {\n [createRoutePropertyOrder.name]: createRoutePropertyOrder.rule,\n [routeParamNames.name]: routeParamNames.rule,\n}\n"],"mappings":";;;AAKA,IAAa,QAQT;;;CAGH"}

@@ -1,40 +0,27 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const createRoutePropertyOrder_utils = require("./create-route-property-order.utils.cjs");
const createRouteFunctionsIndirect = [
"createFileRoute",
"createRootRouteWithContext"
const require_create_route_property_order_utils = require("./create-route-property-order.utils.cjs");
//#region src/rules/create-route-property-order/constants.ts
var createRouteFunctionsIndirect = ["createFileRoute", "createRootRouteWithContext"];
var createRouteFunctions = [...["createRootRoute", "createRoute"], ...createRouteFunctionsIndirect];
var sortRules = [
[["params", "validateSearch"], ["search"]],
[["search"], ["loaderDeps", "ssr"]],
[["loaderDeps"], ["context"]],
[["context"], ["beforeLoad"]],
[["beforeLoad"], ["loader"]],
[["loader"], [
"onEnter",
"onStay",
"onLeave",
"head",
"scripts",
"headers",
"remountDeps"
]]
];
const createRouteFunctionsDirect = [
"createRootRoute",
"createRoute"
];
const createRouteFunctions = [
...createRouteFunctionsDirect,
...createRouteFunctionsIndirect
];
const sortRules = [
[["params", "validateSearch"], ["search"]],
[["search"], ["loaderDeps", "ssr"]],
[["loaderDeps"], ["context"]],
[["context"], ["beforeLoad"]],
[["beforeLoad"], ["loader"]],
[
["loader"],
[
"onEnter",
"onStay",
"onLeave",
"head",
"scripts",
"headers",
"remountDeps"
]
]
];
createRoutePropertyOrder_utils.getCheckedProperties(sortRules);
require_create_route_property_order_utils.getCheckedProperties(sortRules);
//#endregion
exports.createRouteFunctions = createRouteFunctions;
exports.createRouteFunctionsDirect = createRouteFunctionsDirect;
exports.createRouteFunctionsIndirect = createRouteFunctionsIndirect;
exports.sortRules = sortRules;
//# sourceMappingURL=constants.cjs.map
//# sourceMappingURL=constants.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"constants.cjs","sources":["../../../../src/rules/create-route-property-order/constants.ts"],"sourcesContent":["import { getCheckedProperties } from './create-route-property-order.utils'\n\nexport const createRouteFunctionsIndirect = [\n 'createFileRoute',\n 'createRootRouteWithContext',\n] as const\nexport const createRouteFunctionsDirect = [\n 'createRootRoute',\n 'createRoute',\n] as const\n\nexport const createRouteFunctions = [\n ...createRouteFunctionsDirect,\n ...createRouteFunctionsIndirect,\n] as const\n\nexport type CreateRouteFunction = (typeof createRouteFunctions)[number]\n\nexport const sortRules = [\n [['params', 'validateSearch'], ['search']],\n [['search'], ['loaderDeps', 'ssr']],\n [['loaderDeps'], ['context']],\n [['context'], ['beforeLoad']],\n [['beforeLoad'], ['loader']],\n [\n ['loader'],\n [\n 'onEnter',\n 'onStay',\n 'onLeave',\n 'head',\n 'scripts',\n 'headers',\n 'remountDeps',\n ],\n ],\n] as const\n\nexport type CheckedProperties = (typeof sortRules)[number][number][number]\nexport const checkedProperties = getCheckedProperties(sortRules)\n"],"names":["getCheckedProperties"],"mappings":";;;AAEO,MAAM,+BAA+B;AAAA,EAC1C;AAAA,EACA;AACF;AACO,MAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AACF;AAEO,MAAM,uBAAuB;AAAA,EAClC,GAAG;AAAA,EACH,GAAG;AACL;AAIO,MAAM,YAAY;AAAA,EACvB,CAAC,CAAC,UAAU,gBAAgB,GAAG,CAAC,QAAQ,CAAC;AAAA,EACzC,CAAC,CAAC,QAAQ,GAAG,CAAC,cAAc,KAAK,CAAC;AAAA,EAClC,CAAC,CAAC,YAAY,GAAG,CAAC,SAAS,CAAC;AAAA,EAC5B,CAAC,CAAC,SAAS,GAAG,CAAC,YAAY,CAAC;AAAA,EAC5B,CAAC,CAAC,YAAY,GAAG,CAAC,QAAQ,CAAC;AAAA,EAC3B;AAAA,IACE,CAAC,QAAQ;AAAA,IACT;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAEJ;AAGiCA,+BAAAA,qBAAqB,SAAS;;;;;"}
{"version":3,"file":"constants.cjs","names":[],"sources":["../../../../src/rules/create-route-property-order/constants.ts"],"sourcesContent":["import { getCheckedProperties } from './create-route-property-order.utils'\n\nexport const createRouteFunctionsIndirect = [\n 'createFileRoute',\n 'createRootRouteWithContext',\n] as const\nexport const createRouteFunctionsDirect = [\n 'createRootRoute',\n 'createRoute',\n] as const\n\nexport const createRouteFunctions = [\n ...createRouteFunctionsDirect,\n ...createRouteFunctionsIndirect,\n] as const\n\nexport type CreateRouteFunction = (typeof createRouteFunctions)[number]\n\nexport const sortRules = [\n [['params', 'validateSearch'], ['search']],\n [['search'], ['loaderDeps', 'ssr']],\n [['loaderDeps'], ['context']],\n [['context'], ['beforeLoad']],\n [['beforeLoad'], ['loader']],\n [\n ['loader'],\n [\n 'onEnter',\n 'onStay',\n 'onLeave',\n 'head',\n 'scripts',\n 'headers',\n 'remountDeps',\n ],\n ],\n] as const\n\nexport type CheckedProperties = (typeof sortRules)[number][number][number]\nexport const checkedProperties = getCheckedProperties(sortRules)\n"],"mappings":";;AAEA,IAAa,+BAA+B,CAC1C,mBACA,6BACD;AAMD,IAAa,uBAAuB,CAClC,GANwC,CACxC,mBACA,cACD,EAIC,GAAG,6BACJ;AAID,IAAa,YAAY;CACvB,CAAC,CAAC,UAAU,iBAAiB,EAAE,CAAC,SAAS,CAAC;CAC1C,CAAC,CAAC,SAAS,EAAE,CAAC,cAAc,MAAM,CAAC;CACnC,CAAC,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC;CAC7B,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,CAAC;CAC7B,CAAC,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC;CAC5B,CACE,CAAC,SAAS,EACV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;CACF;AAGgC,0CAAA,qBAAqB,UAAU"}

@@ -1,103 +0,73 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const utils = require("@typescript-eslint/utils");
const getDocsUrl = require("../../utils/get-docs-url.cjs");
const detectRouterImports = require("../../utils/detect-router-imports.cjs");
const createRoutePropertyOrder_utils = require("./create-route-property-order.utils.cjs");
const constants = require("./constants.cjs");
const createRule = utils.ESLintUtils.RuleCreator(getDocsUrl.getDocsUrl);
const createRouteFunctionSet = new Set(constants.createRouteFunctions);
const require_get_docs_url = require("../../utils/get-docs-url.cjs");
const require_detect_router_imports = require("../../utils/detect-router-imports.cjs");
const require_create_route_property_order_utils = require("./create-route-property-order.utils.cjs");
const require_constants = require("./constants.cjs");
let _typescript_eslint_utils = require("@typescript-eslint/utils");
//#region src/rules/create-route-property-order/create-route-property-order.rule.ts
var createRule = _typescript_eslint_utils.ESLintUtils.RuleCreator(require_get_docs_url.getDocsUrl);
var createRouteFunctionSet = new Set(require_constants.createRouteFunctions);
function isCreateRouteFunction(node) {
return createRouteFunctionSet.has(node);
return createRouteFunctionSet.has(node);
}
const name = "create-route-property-order";
const rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure correct order of inference sensitive properties for createRoute functions",
recommended: "error"
},
messages: {
invalidOrder: "Invalid order of properties for `{{function}}`."
},
schema: [],
hasSuggestions: true,
fixable: "code"
},
defaultOptions: [],
create: detectRouterImports.detectTanstackRouterImports((context) => {
return {
CallExpression(node) {
if (node.callee.type !== utils.AST_NODE_TYPES.Identifier) {
return;
}
const createRouteFunction = node.callee.name;
if (!isCreateRouteFunction(createRouteFunction)) {
return;
}
let args = node.arguments;
if (constants.createRouteFunctionsIndirect.includes(createRouteFunction)) {
if (node.parent.type === utils.AST_NODE_TYPES.CallExpression) {
args = node.parent.arguments;
} else {
return;
}
}
const argument = args[0];
if (argument === void 0 || argument.type !== "ObjectExpression") {
return;
}
const allProperties = argument.properties;
if (allProperties.length < 2) {
return;
}
const properties = allProperties.flatMap((p) => {
if (p.type === utils.AST_NODE_TYPES.Property && p.key.type === utils.AST_NODE_TYPES.Identifier) {
return { name: p.key.name, property: p };
} else if (p.type === utils.AST_NODE_TYPES.SpreadElement) {
if (p.argument.type === utils.AST_NODE_TYPES.Identifier) {
return { name: p.argument.name, property: p };
} else {
throw new Error("Unsupported spread element");
}
}
return [];
});
const sortedProperties = createRoutePropertyOrder_utils.sortDataByOrder(properties, constants.sortRules, "name");
if (sortedProperties === null) {
return;
}
context.report({
node: argument,
data: { function: node.callee.name },
messageId: "invalidOrder",
fix(fixer) {
const sourceCode = context.sourceCode;
const text = sortedProperties.reduce(
(sourceText, specifier, index) => {
let text2 = "";
if (index < allProperties.length - 1) {
text2 = sourceCode.getText().slice(
allProperties[index].range[1],
allProperties[index + 1].range[0]
);
}
return sourceText + sourceCode.getText(specifier.property) + text2;
},
""
);
return fixer.replaceTextRange(
[allProperties[0].range[0], allProperties.at(-1).range[1]],
text
);
}
});
}
};
})
var name = "create-route-property-order";
var rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure correct order of inference sensitive properties for createRoute functions",
recommended: "error"
},
messages: { invalidOrder: "Invalid order of properties for `{{function}}`." },
schema: [],
hasSuggestions: true,
fixable: "code"
},
defaultOptions: [],
create: require_detect_router_imports.detectTanstackRouterImports((context) => {
return { CallExpression(node) {
if (node.callee.type !== _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return;
const createRouteFunction = node.callee.name;
if (!isCreateRouteFunction(createRouteFunction)) return;
let args = node.arguments;
if (require_constants.createRouteFunctionsIndirect.includes(createRouteFunction)) if (node.parent.type === _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) args = node.parent.arguments;
else return;
const argument = args[0];
if (argument === void 0 || argument.type !== "ObjectExpression") return;
const allProperties = argument.properties;
if (allProperties.length < 2) return;
const sortedProperties = require_create_route_property_order_utils.sortDataByOrder(allProperties.flatMap((p) => {
if (p.type === _typescript_eslint_utils.AST_NODE_TYPES.Property && p.key.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return {
name: p.key.name,
property: p
};
else if (p.type === _typescript_eslint_utils.AST_NODE_TYPES.SpreadElement) if (p.argument.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return {
name: p.argument.name,
property: p
};
else throw new Error("Unsupported spread element");
return [];
}), require_constants.sortRules, "name");
if (sortedProperties === null) return;
context.report({
node: argument,
data: { function: node.callee.name },
messageId: "invalidOrder",
fix(fixer) {
const sourceCode = context.sourceCode;
const text = sortedProperties.reduce((sourceText, specifier, index) => {
let text = "";
if (index < allProperties.length - 1) text = sourceCode.getText().slice(allProperties[index].range[1], allProperties[index + 1].range[0]);
return sourceText + sourceCode.getText(specifier.property) + text;
}, "");
return fixer.replaceTextRange([allProperties[0].range[0], allProperties.at(-1).range[1]], text);
}
});
} };
})
});
//#endregion
exports.name = name;
exports.rule = rule;
//# sourceMappingURL=create-route-property-order.rule.cjs.map
//# sourceMappingURL=create-route-property-order.rule.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-route-property-order.rule.cjs","sources":["../../../../src/rules/create-route-property-order/create-route-property-order.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { sortDataByOrder } from './create-route-property-order.utils'\nimport {\n createRouteFunctions,\n createRouteFunctionsIndirect,\n sortRules,\n} from './constants'\nimport type { CreateRouteFunction } from './constants'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst createRouteFunctionSet = new Set(createRouteFunctions)\nfunction isCreateRouteFunction(node: any): node is CreateRouteFunction {\n return createRouteFunctionSet.has(node)\n}\n\nexport const name = 'create-route-property-order'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Ensure correct order of inference sensitive properties for createRoute functions',\n recommended: 'error',\n },\n messages: {\n invalidOrder: 'Invalid order of properties for `{{function}}`.',\n },\n schema: [],\n hasSuggestions: true,\n fixable: 'code',\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context) => {\n return {\n CallExpression(node) {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) {\n return\n }\n const createRouteFunction = node.callee.name\n if (!isCreateRouteFunction(createRouteFunction)) {\n return\n }\n let args = node.arguments\n if (createRouteFunctionsIndirect.includes(createRouteFunction as any)) {\n if (node.parent.type === AST_NODE_TYPES.CallExpression) {\n args = node.parent.arguments\n } else {\n return\n }\n }\n\n const argument = args[0]\n if (argument === undefined || argument.type !== 'ObjectExpression') {\n return\n }\n\n const allProperties = argument.properties\n // no need to sort if there is at max 1 property\n if (allProperties.length < 2) {\n return\n }\n\n const properties = allProperties.flatMap((p) => {\n if (\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier\n ) {\n return { name: p.key.name, property: p }\n } else if (p.type === AST_NODE_TYPES.SpreadElement) {\n if (p.argument.type === AST_NODE_TYPES.Identifier) {\n return { name: p.argument.name, property: p }\n } else {\n throw new Error('Unsupported spread element')\n }\n }\n return []\n })\n\n const sortedProperties = sortDataByOrder(properties, sortRules, 'name')\n if (sortedProperties === null) {\n return\n }\n context.report({\n node: argument,\n data: { function: node.callee.name },\n messageId: 'invalidOrder',\n fix(fixer) {\n const sourceCode = context.sourceCode\n\n const text = sortedProperties.reduce(\n (sourceText, specifier, index) => {\n let text = ''\n if (index < allProperties.length - 1) {\n text = sourceCode\n .getText()\n .slice(\n allProperties[index]!.range[1],\n allProperties[index + 1]!.range[0],\n )\n }\n return (\n sourceText + sourceCode.getText(specifier.property) + text\n )\n },\n '',\n )\n return fixer.replaceTextRange(\n [allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],\n text,\n )\n },\n })\n },\n }\n }),\n})\n"],"names":["ESLintUtils","getDocsUrl","createRouteFunctions","detectTanstackRouterImports","AST_NODE_TYPES","createRouteFunctionsIndirect","sortDataByOrder","sortRules","text"],"mappings":";;;;;;;AAaA,MAAM,aAAaA,MAAAA,YAAY,YAA2BC,qBAAU;AAEpE,MAAM,yBAAyB,IAAI,IAAIC,8BAAoB;AAC3D,SAAS,sBAAsB,MAAwC;AACrE,SAAO,uBAAuB,IAAI,IAAI;AACxC;AAEO,MAAM,OAAO;AAEb,MAAM,OAAO,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aACE;AAAA,MACF,aAAa;AAAA,IAAA;AAAA,IAEf,UAAU;AAAA,MACR,cAAc;AAAA,IAAA;AAAA,IAEhB,QAAQ,CAAA;AAAA,IACR,gBAAgB;AAAA,IAChB,SAAS;AAAA,EAAA;AAAA,EAEX,gBAAgB,CAAA;AAAA,EAEhB,QAAQC,oBAAAA,4BAA4B,CAAC,YAAY;AAC/C,WAAO;AAAA,MACL,eAAe,MAAM;AACnB,YAAI,KAAK,OAAO,SAASC,MAAAA,eAAe,YAAY;AAClD;AAAA,QACF;AACA,cAAM,sBAAsB,KAAK,OAAO;AACxC,YAAI,CAAC,sBAAsB,mBAAmB,GAAG;AAC/C;AAAA,QACF;AACA,YAAI,OAAO,KAAK;AAChB,YAAIC,UAAAA,6BAA6B,SAAS,mBAA0B,GAAG;AACrE,cAAI,KAAK,OAAO,SAASD,MAAAA,eAAe,gBAAgB;AACtD,mBAAO,KAAK,OAAO;AAAA,UACrB,OAAO;AACL;AAAA,UACF;AAAA,QACF;AAEA,cAAM,WAAW,KAAK,CAAC;AACvB,YAAI,aAAa,UAAa,SAAS,SAAS,oBAAoB;AAClE;AAAA,QACF;AAEA,cAAM,gBAAgB,SAAS;AAE/B,YAAI,cAAc,SAAS,GAAG;AAC5B;AAAA,QACF;AAEA,cAAM,aAAa,cAAc,QAAQ,CAAC,MAAM;AAC9C,cACE,EAAE,SAASA,MAAAA,eAAe,YAC1B,EAAE,IAAI,SAASA,MAAAA,eAAe,YAC9B;AACA,mBAAO,EAAE,MAAM,EAAE,IAAI,MAAM,UAAU,EAAA;AAAA,UACvC,WAAW,EAAE,SAASA,MAAAA,eAAe,eAAe;AAClD,gBAAI,EAAE,SAAS,SAASA,MAAAA,eAAe,YAAY;AACjD,qBAAO,EAAE,MAAM,EAAE,SAAS,MAAM,UAAU,EAAA;AAAA,YAC5C,OAAO;AACL,oBAAM,IAAI,MAAM,4BAA4B;AAAA,YAC9C;AAAA,UACF;AACA,iBAAO,CAAA;AAAA,QACT,CAAC;AAED,cAAM,mBAAmBE,+BAAAA,gBAAgB,YAAYC,UAAAA,WAAW,MAAM;AACtE,YAAI,qBAAqB,MAAM;AAC7B;AAAA,QACF;AACA,gBAAQ,OAAO;AAAA,UACb,MAAM;AAAA,UACN,MAAM,EAAE,UAAU,KAAK,OAAO,KAAA;AAAA,UAC9B,WAAW;AAAA,UACX,IAAI,OAAO;AACT,kBAAM,aAAa,QAAQ;AAE3B,kBAAM,OAAO,iBAAiB;AAAA,cAC5B,CAAC,YAAY,WAAW,UAAU;AAChC,oBAAIC,QAAO;AACX,oBAAI,QAAQ,cAAc,SAAS,GAAG;AACpCA,0BAAO,WACJ,QAAA,EACA;AAAA,oBACC,cAAc,KAAK,EAAG,MAAM,CAAC;AAAA,oBAC7B,cAAc,QAAQ,CAAC,EAAG,MAAM,CAAC;AAAA,kBAAA;AAAA,gBAEvC;AACA,uBACE,aAAa,WAAW,QAAQ,UAAU,QAAQ,IAAIA;AAAAA,cAE1D;AAAA,cACA;AAAA,YAAA;AAEF,mBAAO,MAAM;AAAA,cACX,CAAC,cAAc,CAAC,EAAG,MAAM,CAAC,GAAG,cAAc,GAAG,EAAE,EAAG,MAAM,CAAC,CAAC;AAAA,cAC3D;AAAA,YAAA;AAAA,UAEJ;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH,CAAC;;;"}
{"version":3,"file":"create-route-property-order.rule.cjs","names":[],"sources":["../../../../src/rules/create-route-property-order/create-route-property-order.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { sortDataByOrder } from './create-route-property-order.utils'\nimport {\n createRouteFunctions,\n createRouteFunctionsIndirect,\n sortRules,\n} from './constants'\nimport type { CreateRouteFunction } from './constants'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst createRouteFunctionSet = new Set(createRouteFunctions)\nfunction isCreateRouteFunction(node: any): node is CreateRouteFunction {\n return createRouteFunctionSet.has(node)\n}\n\nexport const name = 'create-route-property-order'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Ensure correct order of inference sensitive properties for createRoute functions',\n recommended: 'error',\n },\n messages: {\n invalidOrder: 'Invalid order of properties for `{{function}}`.',\n },\n schema: [],\n hasSuggestions: true,\n fixable: 'code',\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context) => {\n return {\n CallExpression(node) {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) {\n return\n }\n const createRouteFunction = node.callee.name\n if (!isCreateRouteFunction(createRouteFunction)) {\n return\n }\n let args = node.arguments\n if (createRouteFunctionsIndirect.includes(createRouteFunction as any)) {\n if (node.parent.type === AST_NODE_TYPES.CallExpression) {\n args = node.parent.arguments\n } else {\n return\n }\n }\n\n const argument = args[0]\n if (argument === undefined || argument.type !== 'ObjectExpression') {\n return\n }\n\n const allProperties = argument.properties\n // no need to sort if there is at max 1 property\n if (allProperties.length < 2) {\n return\n }\n\n const properties = allProperties.flatMap((p) => {\n if (\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier\n ) {\n return { name: p.key.name, property: p }\n } else if (p.type === AST_NODE_TYPES.SpreadElement) {\n if (p.argument.type === AST_NODE_TYPES.Identifier) {\n return { name: p.argument.name, property: p }\n } else {\n throw new Error('Unsupported spread element')\n }\n }\n return []\n })\n\n const sortedProperties = sortDataByOrder(properties, sortRules, 'name')\n if (sortedProperties === null) {\n return\n }\n context.report({\n node: argument,\n data: { function: node.callee.name },\n messageId: 'invalidOrder',\n fix(fixer) {\n const sourceCode = context.sourceCode\n\n const text = sortedProperties.reduce(\n (sourceText, specifier, index) => {\n let text = ''\n if (index < allProperties.length - 1) {\n text = sourceCode\n .getText()\n .slice(\n allProperties[index]!.range[1],\n allProperties[index + 1]!.range[0],\n )\n }\n return (\n sourceText + sourceCode.getText(specifier.property) + text\n )\n },\n '',\n )\n return fixer.replaceTextRange(\n [allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],\n text,\n )\n },\n })\n },\n }\n }),\n})\n"],"mappings":";;;;;;AAaA,IAAM,aAAa,yBAAA,YAAY,YAA2B,qBAAA,WAAW;AAErE,IAAM,yBAAyB,IAAI,IAAI,kBAAA,qBAAqB;AAC5D,SAAS,sBAAsB,MAAwC;AACrE,QAAO,uBAAuB,IAAI,KAAK;;AAGzC,IAAa,OAAO;AAEpB,IAAa,OAAO,WAAW;CAC7B;CACA,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aACE;GACF,aAAa;GACd;EACD,UAAU,EACR,cAAc,mDACf;EACD,QAAQ,EAAE;EACV,gBAAgB;EAChB,SAAS;EACV;CACD,gBAAgB,EAAE;CAElB,QAAQ,8BAAA,6BAA6B,YAAY;AAC/C,SAAO,EACL,eAAe,MAAM;AACnB,OAAI,KAAK,OAAO,SAAS,yBAAA,eAAe,WACtC;GAEF,MAAM,sBAAsB,KAAK,OAAO;AACxC,OAAI,CAAC,sBAAsB,oBAAoB,CAC7C;GAEF,IAAI,OAAO,KAAK;AAChB,OAAI,kBAAA,6BAA6B,SAAS,oBAA2B,CACnE,KAAI,KAAK,OAAO,SAAS,yBAAA,eAAe,eACtC,QAAO,KAAK,OAAO;OAEnB;GAIJ,MAAM,WAAW,KAAK;AACtB,OAAI,aAAa,KAAA,KAAa,SAAS,SAAS,mBAC9C;GAGF,MAAM,gBAAgB,SAAS;AAE/B,OAAI,cAAc,SAAS,EACzB;GAmBF,MAAM,mBAAmB,0CAAA,gBAhBN,cAAc,SAAS,MAAM;AAC9C,QACE,EAAE,SAAS,yBAAA,eAAe,YAC1B,EAAE,IAAI,SAAS,yBAAA,eAAe,WAE9B,QAAO;KAAE,MAAM,EAAE,IAAI;KAAM,UAAU;KAAG;aAC/B,EAAE,SAAS,yBAAA,eAAe,cACnC,KAAI,EAAE,SAAS,SAAS,yBAAA,eAAe,WACrC,QAAO;KAAE,MAAM,EAAE,SAAS;KAAM,UAAU;KAAG;QAE7C,OAAM,IAAI,MAAM,6BAA6B;AAGjD,WAAO,EAAE;KACT,EAEmD,kBAAA,WAAW,OAAO;AACvE,OAAI,qBAAqB,KACvB;AAEF,WAAQ,OAAO;IACb,MAAM;IACN,MAAM,EAAE,UAAU,KAAK,OAAO,MAAM;IACpC,WAAW;IACX,IAAI,OAAO;KACT,MAAM,aAAa,QAAQ;KAE3B,MAAM,OAAO,iBAAiB,QAC3B,YAAY,WAAW,UAAU;MAChC,IAAI,OAAO;AACX,UAAI,QAAQ,cAAc,SAAS,EACjC,QAAO,WACJ,SAAS,CACT,MACC,cAAc,OAAQ,MAAM,IAC5B,cAAc,QAAQ,GAAI,MAAM,GACjC;AAEL,aACE,aAAa,WAAW,QAAQ,UAAU,SAAS,GAAG;QAG1D,GACD;AACD,YAAO,MAAM,iBACX,CAAC,cAAc,GAAI,MAAM,IAAI,cAAc,GAAG,GAAG,CAAE,MAAM,GAAG,EAC5D,KACD;;IAEJ,CAAC;KAEL;GACD;CACH,CAAC"}

@@ -1,50 +0,39 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/rules/create-route-property-order/create-route-property-order.utils.ts
function sortDataByOrder(data, orderRules, key) {
const getSubsetIndex = (item, subsets) => {
for (let i = 0; i < subsets.length; i++) {
if (subsets[i]?.includes(item)) {
return i;
}
}
return null;
};
const orderSets = orderRules.reduce(
(sets, [A, B]) => [...sets, A, B],
[]
);
const inOrderArray = data.filter(
(item) => getSubsetIndex(item[key], orderSets) !== null
);
let wasResorted = false;
const sortedArray = inOrderArray.sort((a, b) => {
const aKey = a[key], bKey = b[key];
const aSubsetIndex = getSubsetIndex(aKey, orderSets);
const bSubsetIndex = getSubsetIndex(bKey, orderSets);
if (aSubsetIndex !== null && bSubsetIndex !== null && aSubsetIndex !== bSubsetIndex) {
return aSubsetIndex - bSubsetIndex;
}
return 0;
});
const inOrderIterator = sortedArray.values();
const result = data.map((item) => {
if (getSubsetIndex(item[key], orderSets) !== null) {
const sortedItem = inOrderIterator.next().value;
if (sortedItem[key] !== item[key]) {
wasResorted = true;
}
return sortedItem;
}
return item;
});
if (!wasResorted) {
return null;
}
return result;
const getSubsetIndex = (item, subsets) => {
for (let i = 0; i < subsets.length; i++) if (subsets[i]?.includes(item)) return i;
return null;
};
const orderSets = orderRules.reduce((sets, [A, B]) => [
...sets,
A,
B
], []);
const inOrderArray = data.filter((item) => getSubsetIndex(item[key], orderSets) !== null);
let wasResorted = false;
const inOrderIterator = inOrderArray.sort((a, b) => {
const aKey = a[key], bKey = b[key];
const aSubsetIndex = getSubsetIndex(aKey, orderSets);
const bSubsetIndex = getSubsetIndex(bKey, orderSets);
if (aSubsetIndex !== null && bSubsetIndex !== null && aSubsetIndex !== bSubsetIndex) return aSubsetIndex - bSubsetIndex;
return 0;
}).values();
const result = data.map((item) => {
if (getSubsetIndex(item[key], orderSets) !== null) {
const sortedItem = inOrderIterator.next().value;
if (sortedItem[key] !== item[key]) wasResorted = true;
return sortedItem;
}
return item;
});
if (!wasResorted) return null;
return result;
}
function getCheckedProperties(orderRules) {
return [...new Set(orderRules.flat(2))];
return [...new Set(orderRules.flat(2))];
}
//#endregion
exports.getCheckedProperties = getCheckedProperties;
exports.sortDataByOrder = sortDataByOrder;
//# sourceMappingURL=create-route-property-order.utils.cjs.map
//# sourceMappingURL=create-route-property-order.utils.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-route-property-order.utils.cjs","sources":["../../../../src/rules/create-route-property-order/create-route-property-order.utils.ts"],"sourcesContent":["export function sortDataByOrder<T, TKey extends keyof T>(\n data: Array<T> | ReadonlyArray<T>,\n orderRules: ReadonlyArray<\n Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>\n >,\n key: TKey,\n): Array<T> | null {\n const getSubsetIndex = (\n item: T[TKey],\n subsets: ReadonlyArray<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n ): number | null => {\n for (let i = 0; i < subsets.length; i++) {\n if (subsets[i]?.includes(item)) {\n return i\n }\n }\n return null\n }\n\n const orderSets = orderRules.reduce(\n (sets, [A, B]) => [...sets, A, B],\n [] as Array<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n )\n\n const inOrderArray = data.filter(\n (item) => getSubsetIndex(item[key], orderSets) !== null,\n )\n\n let wasResorted = false as boolean\n\n // Sort by the relative order defined by the rules\n const sortedArray = inOrderArray.sort((a, b) => {\n const aKey = a[key],\n bKey = b[key]\n const aSubsetIndex = getSubsetIndex(aKey, orderSets)\n const bSubsetIndex = getSubsetIndex(bKey, orderSets)\n\n // If both items belong to different subsets, sort by their subset order\n if (\n aSubsetIndex !== null &&\n bSubsetIndex !== null &&\n aSubsetIndex !== bSubsetIndex\n ) {\n return aSubsetIndex - bSubsetIndex\n }\n\n // If both items belong to the same subset or neither is in the subset, keep their relative order\n return 0\n })\n\n const inOrderIterator = sortedArray.values()\n const result = data.map((item) => {\n if (getSubsetIndex(item[key], orderSets) !== null) {\n const sortedItem = inOrderIterator.next().value!\n if (sortedItem[key] !== item[key]) {\n wasResorted = true\n }\n return sortedItem\n }\n return item\n })\n\n if (!wasResorted) {\n return null\n }\n return result\n}\n\nexport function getCheckedProperties<T>(\n orderRules: ReadonlyArray<ReadonlyArray<ReadonlyArray<T>>>,\n): ReadonlyArray<T> {\n return [...new Set<T>(orderRules.flat(2))]\n}\n"],"names":[],"mappings":";;AAAO,SAAS,gBACd,MACA,YAGA,KACiB;AACjB,QAAM,iBAAiB,CACrB,MACA,YACkB;AAClB,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAI,QAAQ,CAAC,GAAG,SAAS,IAAI,GAAG;AAC9B,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,WAAW;AAAA,IAC3B,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,IAChC,CAAA;AAAA,EAAC;AAGH,QAAM,eAAe,KAAK;AAAA,IACxB,CAAC,SAAS,eAAe,KAAK,GAAG,GAAG,SAAS,MAAM;AAAA,EAAA;AAGrD,MAAI,cAAc;AAGlB,QAAM,cAAc,aAAa,KAAK,CAAC,GAAG,MAAM;AAC9C,UAAM,OAAO,EAAE,GAAG,GAChB,OAAO,EAAE,GAAG;AACd,UAAM,eAAe,eAAe,MAAM,SAAS;AACnD,UAAM,eAAe,eAAe,MAAM,SAAS;AAGnD,QACE,iBAAiB,QACjB,iBAAiB,QACjB,iBAAiB,cACjB;AACA,aAAO,eAAe;AAAA,IACxB;AAGA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,kBAAkB,YAAY,OAAA;AACpC,QAAM,SAAS,KAAK,IAAI,CAAC,SAAS;AAChC,QAAI,eAAe,KAAK,GAAG,GAAG,SAAS,MAAM,MAAM;AACjD,YAAM,aAAa,gBAAgB,KAAA,EAAO;AAC1C,UAAI,WAAW,GAAG,MAAM,KAAK,GAAG,GAAG;AACjC,sBAAc;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,qBACd,YACkB;AAClB,SAAO,CAAC,GAAG,IAAI,IAAO,WAAW,KAAK,CAAC,CAAC,CAAC;AAC3C;;;"}
{"version":3,"file":"create-route-property-order.utils.cjs","names":[],"sources":["../../../../src/rules/create-route-property-order/create-route-property-order.utils.ts"],"sourcesContent":["export function sortDataByOrder<T, TKey extends keyof T>(\n data: Array<T> | ReadonlyArray<T>,\n orderRules: ReadonlyArray<\n Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>\n >,\n key: TKey,\n): Array<T> | null {\n const getSubsetIndex = (\n item: T[TKey],\n subsets: ReadonlyArray<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n ): number | null => {\n for (let i = 0; i < subsets.length; i++) {\n if (subsets[i]?.includes(item)) {\n return i\n }\n }\n return null\n }\n\n const orderSets = orderRules.reduce(\n (sets, [A, B]) => [...sets, A, B],\n [] as Array<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n )\n\n const inOrderArray = data.filter(\n (item) => getSubsetIndex(item[key], orderSets) !== null,\n )\n\n let wasResorted = false as boolean\n\n // Sort by the relative order defined by the rules\n const sortedArray = inOrderArray.sort((a, b) => {\n const aKey = a[key],\n bKey = b[key]\n const aSubsetIndex = getSubsetIndex(aKey, orderSets)\n const bSubsetIndex = getSubsetIndex(bKey, orderSets)\n\n // If both items belong to different subsets, sort by their subset order\n if (\n aSubsetIndex !== null &&\n bSubsetIndex !== null &&\n aSubsetIndex !== bSubsetIndex\n ) {\n return aSubsetIndex - bSubsetIndex\n }\n\n // If both items belong to the same subset or neither is in the subset, keep their relative order\n return 0\n })\n\n const inOrderIterator = sortedArray.values()\n const result = data.map((item) => {\n if (getSubsetIndex(item[key], orderSets) !== null) {\n const sortedItem = inOrderIterator.next().value!\n if (sortedItem[key] !== item[key]) {\n wasResorted = true\n }\n return sortedItem\n }\n return item\n })\n\n if (!wasResorted) {\n return null\n }\n return result\n}\n\nexport function getCheckedProperties<T>(\n orderRules: ReadonlyArray<ReadonlyArray<ReadonlyArray<T>>>,\n): ReadonlyArray<T> {\n return [...new Set<T>(orderRules.flat(2))]\n}\n"],"mappings":";AAAA,SAAgB,gBACd,MACA,YAGA,KACiB;CACjB,MAAM,kBACJ,MACA,YACkB;AAClB,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAClC,KAAI,QAAQ,IAAI,SAAS,KAAK,CAC5B,QAAO;AAGX,SAAO;;CAGT,MAAM,YAAY,WAAW,QAC1B,MAAM,CAAC,GAAG,OAAO;EAAC,GAAG;EAAM;EAAG;EAAE,EACjC,EAAE,CACH;CAED,MAAM,eAAe,KAAK,QACvB,SAAS,eAAe,KAAK,MAAM,UAAU,KAAK,KACpD;CAED,IAAI,cAAc;CAsBlB,MAAM,kBAnBc,aAAa,MAAM,GAAG,MAAM;EAC9C,MAAM,OAAO,EAAE,MACb,OAAO,EAAE;EACX,MAAM,eAAe,eAAe,MAAM,UAAU;EACpD,MAAM,eAAe,eAAe,MAAM,UAAU;AAGpD,MACE,iBAAiB,QACjB,iBAAiB,QACjB,iBAAiB,aAEjB,QAAO,eAAe;AAIxB,SAAO;GACP,CAEkC,QAAQ;CAC5C,MAAM,SAAS,KAAK,KAAK,SAAS;AAChC,MAAI,eAAe,KAAK,MAAM,UAAU,KAAK,MAAM;GACjD,MAAM,aAAa,gBAAgB,MAAM,CAAC;AAC1C,OAAI,WAAW,SAAS,KAAK,KAC3B,eAAc;AAEhB,UAAO;;AAET,SAAO;GACP;AAEF,KAAI,CAAC,YACH,QAAO;AAET,QAAO;;AAGT,SAAgB,qBACd,YACkB;AAClB,QAAO,CAAC,GAAG,IAAI,IAAO,WAAW,KAAK,EAAE,CAAC,CAAC"}

@@ -1,13 +0,28 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const pathAsFirstArgFunctions = [
"createFileRoute",
"createLazyFileRoute",
"createLazyRoute"
//#region src/rules/route-param-names/constants.ts
/**
* Functions where the path is passed as the first argument (string literal)
* e.g., createFileRoute('/path/$param')(...)
*/
var pathAsFirstArgFunctions = [
"createFileRoute",
"createLazyFileRoute",
"createLazyRoute"
];
const pathAsPropertyFunctions = ["createRoute"];
const VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
/**
* Functions where the path is a property in the options object
* e.g., createRoute({ path: '/path/$param' })
*/
var pathAsPropertyFunctions = ["createRoute"];
[...pathAsFirstArgFunctions, ...pathAsPropertyFunctions];
/**
* Regex for valid JavaScript identifier (param name)
* Must start with letter, underscore, or dollar sign
* Can contain letters, numbers, underscores, or dollar signs
*/
var VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
//#endregion
exports.VALID_PARAM_NAME_REGEX = VALID_PARAM_NAME_REGEX;
exports.pathAsFirstArgFunctions = pathAsFirstArgFunctions;
exports.pathAsPropertyFunctions = pathAsPropertyFunctions;
//# sourceMappingURL=constants.cjs.map
//# sourceMappingURL=constants.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"constants.cjs","sources":["../../../../src/rules/route-param-names/constants.ts"],"sourcesContent":["/**\n * Functions where the path is passed as the first argument (string literal)\n * e.g., createFileRoute('/path/$param')(...)\n */\nexport const pathAsFirstArgFunctions = [\n 'createFileRoute',\n 'createLazyFileRoute',\n 'createLazyRoute',\n] as const\n\nexport type PathAsFirstArgFunction = (typeof pathAsFirstArgFunctions)[number]\n\n/**\n * Functions where the path is a property in the options object\n * e.g., createRoute({ path: '/path/$param' })\n */\nexport const pathAsPropertyFunctions = ['createRoute'] as const\n\nexport type PathAsPropertyFunction = (typeof pathAsPropertyFunctions)[number]\n\n/**\n * All route functions that need param name validation\n */\nexport const allRouteFunctions = [\n ...pathAsFirstArgFunctions,\n ...pathAsPropertyFunctions,\n] as const\n\nexport type RouteFunction = (typeof allRouteFunctions)[number]\n\n/**\n * Regex for valid JavaScript identifier (param name)\n * Must start with letter, underscore, or dollar sign\n * Can contain letters, numbers, underscores, or dollar signs\n */\nexport const VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/\n"],"names":[],"mappings":";;AAIO,MAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,0BAA0B,CAAC,aAAa;AAmB9C,MAAM,yBAAyB;;;;"}
{"version":3,"file":"constants.cjs","names":[],"sources":["../../../../src/rules/route-param-names/constants.ts"],"sourcesContent":["/**\n * Functions where the path is passed as the first argument (string literal)\n * e.g., createFileRoute('/path/$param')(...)\n */\nexport const pathAsFirstArgFunctions = [\n 'createFileRoute',\n 'createLazyFileRoute',\n 'createLazyRoute',\n] as const\n\nexport type PathAsFirstArgFunction = (typeof pathAsFirstArgFunctions)[number]\n\n/**\n * Functions where the path is a property in the options object\n * e.g., createRoute({ path: '/path/$param' })\n */\nexport const pathAsPropertyFunctions = ['createRoute'] as const\n\nexport type PathAsPropertyFunction = (typeof pathAsPropertyFunctions)[number]\n\n/**\n * All route functions that need param name validation\n */\nexport const allRouteFunctions = [\n ...pathAsFirstArgFunctions,\n ...pathAsPropertyFunctions,\n] as const\n\nexport type RouteFunction = (typeof allRouteFunctions)[number]\n\n/**\n * Regex for valid JavaScript identifier (param name)\n * Must start with letter, underscore, or dollar sign\n * Can contain letters, numbers, underscores, or dollar signs\n */\nexport const VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/\n"],"mappings":";;;;;AAIA,IAAa,0BAA0B;CACrC;CACA;CACA;CACD;;;;;AAQD,IAAa,0BAA0B,CAAC,cAAc;AAOrB,CAC/B,GAAG,yBACH,GAAG,wBACJ;;;;;;AASD,IAAa,yBAAyB"}

@@ -1,98 +0,78 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const utils = require("@typescript-eslint/utils");
const getDocsUrl = require("../../utils/get-docs-url.cjs");
const detectRouterImports = require("../../utils/detect-router-imports.cjs");
const routeParamNames_utils = require("./route-param-names.utils.cjs");
const constants = require("./constants.cjs");
const createRule = utils.ESLintUtils.RuleCreator(getDocsUrl.getDocsUrl);
const pathAsFirstArgSet = new Set(constants.pathAsFirstArgFunctions);
const pathAsPropertySet = new Set(constants.pathAsPropertyFunctions);
const name = "route-param-names";
const rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure route param names are valid JavaScript identifiers",
recommended: "error"
},
messages: {
invalidParamName: 'Invalid param name "{{paramName}}" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/).'
},
schema: []
},
defaultOptions: [],
create: detectRouterImports.detectTanstackRouterImports((context, _, helpers) => {
function reportInvalidParams(node, path) {
const invalidParams = routeParamNames_utils.getInvalidParams(path);
for (const param of invalidParams) {
context.report({
node,
messageId: "invalidParamName",
data: { paramName: param.paramName }
});
}
}
function getStringLiteralValue(node) {
if (node.type === utils.AST_NODE_TYPES.Literal && typeof node.value === "string") {
return node.value;
}
if (node.type === utils.AST_NODE_TYPES.TemplateLiteral && node.quasis.length === 1) {
const cooked = node.quasis[0]?.value.cooked;
if (cooked != null) {
return cooked;
}
}
return null;
}
return {
CallExpression(node) {
if (node.callee.type === utils.AST_NODE_TYPES.Identifier) {
const funcName = node.callee.name;
if (!helpers.isTanstackRouterImport(node.callee)) {
return;
}
if (pathAsPropertySet.has(funcName)) {
const arg = node.arguments[0];
if (arg?.type === utils.AST_NODE_TYPES.ObjectExpression) {
for (const prop of arg.properties) {
if (prop.type === utils.AST_NODE_TYPES.Property) {
const isPathKey = prop.key.type === utils.AST_NODE_TYPES.Identifier && prop.key.name === "path" || prop.key.type === utils.AST_NODE_TYPES.Literal && prop.key.value === "path";
if (isPathKey) {
const pathValue = getStringLiteralValue(prop.value);
if (pathValue) {
reportInvalidParams(prop.value, pathValue);
}
}
}
}
}
return;
}
}
if (node.callee.type === utils.AST_NODE_TYPES.CallExpression) {
const innerCall = node.callee;
if (innerCall.callee.type === utils.AST_NODE_TYPES.Identifier) {
const funcName = innerCall.callee.name;
if (!helpers.isTanstackRouterImport(innerCall.callee)) {
return;
}
if (pathAsFirstArgSet.has(funcName)) {
const pathArg = innerCall.arguments[0];
if (pathArg) {
const pathValue = getStringLiteralValue(pathArg);
if (pathValue) {
reportInvalidParams(pathArg, pathValue);
}
}
}
}
}
}
};
})
const require_get_docs_url = require("../../utils/get-docs-url.cjs");
const require_detect_router_imports = require("../../utils/detect-router-imports.cjs");
const require_constants = require("./constants.cjs");
const require_route_param_names_utils = require("./route-param-names.utils.cjs");
let _typescript_eslint_utils = require("@typescript-eslint/utils");
//#region src/rules/route-param-names/route-param-names.rule.ts
var createRule = _typescript_eslint_utils.ESLintUtils.RuleCreator(require_get_docs_url.getDocsUrl);
var pathAsFirstArgSet = new Set(require_constants.pathAsFirstArgFunctions);
var pathAsPropertySet = new Set(require_constants.pathAsPropertyFunctions);
var name = "route-param-names";
var rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure route param names are valid JavaScript identifiers",
recommended: "error"
},
messages: { invalidParamName: "Invalid param name \"{{paramName}}\" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/)." },
schema: []
},
defaultOptions: [],
create: require_detect_router_imports.detectTanstackRouterImports((context, _, helpers) => {
function reportInvalidParams(node, path) {
const invalidParams = require_route_param_names_utils.getInvalidParams(path);
for (const param of invalidParams) context.report({
node,
messageId: "invalidParamName",
data: { paramName: param.paramName }
});
}
function getStringLiteralValue(node) {
if (node.type === _typescript_eslint_utils.AST_NODE_TYPES.Literal && typeof node.value === "string") return node.value;
if (node.type === _typescript_eslint_utils.AST_NODE_TYPES.TemplateLiteral && node.quasis.length === 1) {
const cooked = node.quasis[0]?.value.cooked;
if (cooked != null) return cooked;
}
return null;
}
return { CallExpression(node) {
if (node.callee.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) {
const funcName = node.callee.name;
if (!helpers.isTanstackRouterImport(node.callee)) return;
if (pathAsPropertySet.has(funcName)) {
const arg = node.arguments[0];
if (arg?.type === _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression) {
for (const prop of arg.properties) if (prop.type === _typescript_eslint_utils.AST_NODE_TYPES.Property) {
if (prop.key.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier && prop.key.name === "path" || prop.key.type === _typescript_eslint_utils.AST_NODE_TYPES.Literal && prop.key.value === "path") {
const pathValue = getStringLiteralValue(prop.value);
if (pathValue) reportInvalidParams(prop.value, pathValue);
}
}
}
return;
}
}
if (node.callee.type === _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) {
const innerCall = node.callee;
if (innerCall.callee.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) {
const funcName = innerCall.callee.name;
if (!helpers.isTanstackRouterImport(innerCall.callee)) return;
if (pathAsFirstArgSet.has(funcName)) {
const pathArg = innerCall.arguments[0];
if (pathArg) {
const pathValue = getStringLiteralValue(pathArg);
if (pathValue) reportInvalidParams(pathArg, pathValue);
}
}
}
}
} };
})
});
//#endregion
exports.name = name;
exports.rule = rule;
//# sourceMappingURL=route-param-names.rule.cjs.map
//# sourceMappingURL=route-param-names.rule.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"route-param-names.rule.cjs","sources":["../../../../src/rules/route-param-names/route-param-names.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { getInvalidParams } from './route-param-names.utils'\nimport { pathAsFirstArgFunctions, pathAsPropertyFunctions } from './constants'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst pathAsFirstArgSet = new Set<string>(pathAsFirstArgFunctions)\nconst pathAsPropertySet = new Set<string>(pathAsPropertyFunctions)\n\nexport const name = 'route-param-names'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Ensure route param names are valid JavaScript identifiers',\n recommended: 'error',\n },\n messages: {\n invalidParamName:\n 'Invalid param name \"{{paramName}}\" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/).',\n },\n schema: [],\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context, _, helpers) => {\n function reportInvalidParams(node: TSESTree.Node, path: string) {\n const invalidParams = getInvalidParams(path)\n\n for (const param of invalidParams) {\n context.report({\n node,\n messageId: 'invalidParamName',\n data: { paramName: param.paramName },\n })\n }\n }\n\n function getStringLiteralValue(node: TSESTree.Node): string | null {\n if (\n node.type === AST_NODE_TYPES.Literal &&\n typeof node.value === 'string'\n ) {\n return node.value\n }\n if (\n node.type === AST_NODE_TYPES.TemplateLiteral &&\n node.quasis.length === 1\n ) {\n const cooked = node.quasis[0]?.value.cooked\n if (cooked != null) {\n return cooked\n }\n }\n return null\n }\n\n return {\n CallExpression(node) {\n // Handle direct function call: createRoute({ path: '...' })\n if (node.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = node.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(node.callee)) {\n return\n }\n\n // Case: createRoute({ path: '/path/$param' }) or createRoute({ 'path': '/path/$param' })\n if (pathAsPropertySet.has(funcName)) {\n const arg = node.arguments[0]\n if (arg?.type === AST_NODE_TYPES.ObjectExpression) {\n for (const prop of arg.properties) {\n if (prop.type === AST_NODE_TYPES.Property) {\n const isPathKey =\n (prop.key.type === AST_NODE_TYPES.Identifier &&\n prop.key.name === 'path') ||\n (prop.key.type === AST_NODE_TYPES.Literal &&\n prop.key.value === 'path')\n if (isPathKey) {\n const pathValue = getStringLiteralValue(prop.value)\n if (pathValue) {\n reportInvalidParams(prop.value, pathValue)\n }\n }\n }\n }\n }\n return\n }\n }\n\n // Handle curried function call: createFileRoute('/path')({ ... })\n if (node.callee.type === AST_NODE_TYPES.CallExpression) {\n const innerCall = node.callee\n\n if (innerCall.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = innerCall.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(innerCall.callee)) {\n return\n }\n\n // Case: createFileRoute('/path/$param')(...) or similar\n if (pathAsFirstArgSet.has(funcName)) {\n const pathArg = innerCall.arguments[0]\n if (pathArg) {\n const pathValue = getStringLiteralValue(pathArg)\n if (pathValue) {\n reportInvalidParams(pathArg, pathValue)\n }\n }\n }\n }\n }\n },\n }\n }),\n})\n"],"names":["ESLintUtils","getDocsUrl","pathAsFirstArgFunctions","pathAsPropertyFunctions","detectTanstackRouterImports","getInvalidParams","AST_NODE_TYPES"],"mappings":";;;;;;;AASA,MAAM,aAAaA,MAAAA,YAAY,YAA2BC,qBAAU;AAEpE,MAAM,oBAAoB,IAAI,IAAYC,iCAAuB;AACjE,MAAM,oBAAoB,IAAI,IAAYC,iCAAuB;AAE1D,MAAM,OAAO;AAEb,MAAM,OAAO,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf,UAAU;AAAA,MACR,kBACE;AAAA,IAAA;AAAA,IAEJ,QAAQ,CAAA;AAAA,EAAC;AAAA,EAEX,gBAAgB,CAAA;AAAA,EAEhB,QAAQC,oBAAAA,4BAA4B,CAAC,SAAS,GAAG,YAAY;AAC3D,aAAS,oBAAoB,MAAqB,MAAc;AAC9D,YAAM,gBAAgBC,sBAAAA,iBAAiB,IAAI;AAE3C,iBAAW,SAAS,eAAe;AACjC,gBAAQ,OAAO;AAAA,UACb;AAAA,UACA,WAAW;AAAA,UACX,MAAM,EAAE,WAAW,MAAM,UAAA;AAAA,QAAU,CACpC;AAAA,MACH;AAAA,IACF;AAEA,aAAS,sBAAsB,MAAoC;AACjE,UACE,KAAK,SAASC,MAAAA,eAAe,WAC7B,OAAO,KAAK,UAAU,UACtB;AACA,eAAO,KAAK;AAAA,MACd;AACA,UACE,KAAK,SAASA,qBAAe,mBAC7B,KAAK,OAAO,WAAW,GACvB;AACA,cAAM,SAAS,KAAK,OAAO,CAAC,GAAG,MAAM;AACrC,YAAI,UAAU,MAAM;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,eAAe,MAAM;AAEnB,YAAI,KAAK,OAAO,SAASA,MAAAA,eAAe,YAAY;AAClD,gBAAM,WAAW,KAAK,OAAO;AAG7B,cAAI,CAAC,QAAQ,uBAAuB,KAAK,MAAM,GAAG;AAChD;AAAA,UACF;AAGA,cAAI,kBAAkB,IAAI,QAAQ,GAAG;AACnC,kBAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,gBAAI,KAAK,SAASA,MAAAA,eAAe,kBAAkB;AACjD,yBAAW,QAAQ,IAAI,YAAY;AACjC,oBAAI,KAAK,SAASA,MAAAA,eAAe,UAAU;AACzC,wBAAM,YACH,KAAK,IAAI,SAASA,MAAAA,eAAe,cAChC,KAAK,IAAI,SAAS,UACnB,KAAK,IAAI,SAASA,MAAAA,eAAe,WAChC,KAAK,IAAI,UAAU;AACvB,sBAAI,WAAW;AACb,0BAAM,YAAY,sBAAsB,KAAK,KAAK;AAClD,wBAAI,WAAW;AACb,0CAAoB,KAAK,OAAO,SAAS;AAAA,oBAC3C;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AACA;AAAA,UACF;AAAA,QACF;AAGA,YAAI,KAAK,OAAO,SAASA,MAAAA,eAAe,gBAAgB;AACtD,gBAAM,YAAY,KAAK;AAEvB,cAAI,UAAU,OAAO,SAASA,MAAAA,eAAe,YAAY;AACvD,kBAAM,WAAW,UAAU,OAAO;AAGlC,gBAAI,CAAC,QAAQ,uBAAuB,UAAU,MAAM,GAAG;AACrD;AAAA,YACF;AAGA,gBAAI,kBAAkB,IAAI,QAAQ,GAAG;AACnC,oBAAM,UAAU,UAAU,UAAU,CAAC;AACrC,kBAAI,SAAS;AACX,sBAAM,YAAY,sBAAsB,OAAO;AAC/C,oBAAI,WAAW;AACb,sCAAoB,SAAS,SAAS;AAAA,gBACxC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH,CAAC;;;"}
{"version":3,"file":"route-param-names.rule.cjs","names":[],"sources":["../../../../src/rules/route-param-names/route-param-names.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { getInvalidParams } from './route-param-names.utils'\nimport { pathAsFirstArgFunctions, pathAsPropertyFunctions } from './constants'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst pathAsFirstArgSet = new Set<string>(pathAsFirstArgFunctions)\nconst pathAsPropertySet = new Set<string>(pathAsPropertyFunctions)\n\nexport const name = 'route-param-names'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Ensure route param names are valid JavaScript identifiers',\n recommended: 'error',\n },\n messages: {\n invalidParamName:\n 'Invalid param name \"{{paramName}}\" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/).',\n },\n schema: [],\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context, _, helpers) => {\n function reportInvalidParams(node: TSESTree.Node, path: string) {\n const invalidParams = getInvalidParams(path)\n\n for (const param of invalidParams) {\n context.report({\n node,\n messageId: 'invalidParamName',\n data: { paramName: param.paramName },\n })\n }\n }\n\n function getStringLiteralValue(node: TSESTree.Node): string | null {\n if (\n node.type === AST_NODE_TYPES.Literal &&\n typeof node.value === 'string'\n ) {\n return node.value\n }\n if (\n node.type === AST_NODE_TYPES.TemplateLiteral &&\n node.quasis.length === 1\n ) {\n const cooked = node.quasis[0]?.value.cooked\n if (cooked != null) {\n return cooked\n }\n }\n return null\n }\n\n return {\n CallExpression(node) {\n // Handle direct function call: createRoute({ path: '...' })\n if (node.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = node.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(node.callee)) {\n return\n }\n\n // Case: createRoute({ path: '/path/$param' }) or createRoute({ 'path': '/path/$param' })\n if (pathAsPropertySet.has(funcName)) {\n const arg = node.arguments[0]\n if (arg?.type === AST_NODE_TYPES.ObjectExpression) {\n for (const prop of arg.properties) {\n if (prop.type === AST_NODE_TYPES.Property) {\n const isPathKey =\n (prop.key.type === AST_NODE_TYPES.Identifier &&\n prop.key.name === 'path') ||\n (prop.key.type === AST_NODE_TYPES.Literal &&\n prop.key.value === 'path')\n if (isPathKey) {\n const pathValue = getStringLiteralValue(prop.value)\n if (pathValue) {\n reportInvalidParams(prop.value, pathValue)\n }\n }\n }\n }\n }\n return\n }\n }\n\n // Handle curried function call: createFileRoute('/path')({ ... })\n if (node.callee.type === AST_NODE_TYPES.CallExpression) {\n const innerCall = node.callee\n\n if (innerCall.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = innerCall.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(innerCall.callee)) {\n return\n }\n\n // Case: createFileRoute('/path/$param')(...) or similar\n if (pathAsFirstArgSet.has(funcName)) {\n const pathArg = innerCall.arguments[0]\n if (pathArg) {\n const pathValue = getStringLiteralValue(pathArg)\n if (pathValue) {\n reportInvalidParams(pathArg, pathValue)\n }\n }\n }\n }\n }\n },\n }\n }),\n})\n"],"mappings":";;;;;;AASA,IAAM,aAAa,yBAAA,YAAY,YAA2B,qBAAA,WAAW;AAErE,IAAM,oBAAoB,IAAI,IAAY,kBAAA,wBAAwB;AAClE,IAAM,oBAAoB,IAAI,IAAY,kBAAA,wBAAwB;AAElE,IAAa,OAAO;AAEpB,IAAa,OAAO,WAAW;CAC7B;CACA,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,UAAU,EACR,kBACE,4IACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAElB,QAAQ,8BAAA,6BAA6B,SAAS,GAAG,YAAY;EAC3D,SAAS,oBAAoB,MAAqB,MAAc;GAC9D,MAAM,gBAAgB,gCAAA,iBAAiB,KAAK;AAE5C,QAAK,MAAM,SAAS,cAClB,SAAQ,OAAO;IACb;IACA,WAAW;IACX,MAAM,EAAE,WAAW,MAAM,WAAW;IACrC,CAAC;;EAIN,SAAS,sBAAsB,MAAoC;AACjE,OACE,KAAK,SAAS,yBAAA,eAAe,WAC7B,OAAO,KAAK,UAAU,SAEtB,QAAO,KAAK;AAEd,OACE,KAAK,SAAS,yBAAA,eAAe,mBAC7B,KAAK,OAAO,WAAW,GACvB;IACA,MAAM,SAAS,KAAK,OAAO,IAAI,MAAM;AACrC,QAAI,UAAU,KACZ,QAAO;;AAGX,UAAO;;AAGT,SAAO,EACL,eAAe,MAAM;AAEnB,OAAI,KAAK,OAAO,SAAS,yBAAA,eAAe,YAAY;IAClD,MAAM,WAAW,KAAK,OAAO;AAG7B,QAAI,CAAC,QAAQ,uBAAuB,KAAK,OAAO,CAC9C;AAIF,QAAI,kBAAkB,IAAI,SAAS,EAAE;KACnC,MAAM,MAAM,KAAK,UAAU;AAC3B,SAAI,KAAK,SAAS,yBAAA,eAAe;WAC1B,MAAM,QAAQ,IAAI,WACrB,KAAI,KAAK,SAAS,yBAAA,eAAe;WAE5B,KAAK,IAAI,SAAS,yBAAA,eAAe,cAChC,KAAK,IAAI,SAAS,UACnB,KAAK,IAAI,SAAS,yBAAA,eAAe,WAChC,KAAK,IAAI,UAAU,QACR;QACb,MAAM,YAAY,sBAAsB,KAAK,MAAM;AACnD,YAAI,UACF,qBAAoB,KAAK,OAAO,UAAU;;;;AAMpD;;;AAKJ,OAAI,KAAK,OAAO,SAAS,yBAAA,eAAe,gBAAgB;IACtD,MAAM,YAAY,KAAK;AAEvB,QAAI,UAAU,OAAO,SAAS,yBAAA,eAAe,YAAY;KACvD,MAAM,WAAW,UAAU,OAAO;AAGlC,SAAI,CAAC,QAAQ,uBAAuB,UAAU,OAAO,CACnD;AAIF,SAAI,kBAAkB,IAAI,SAAS,EAAE;MACnC,MAAM,UAAU,UAAU,UAAU;AACpC,UAAI,SAAS;OACX,MAAM,YAAY,sBAAsB,QAAQ;AAChD,WAAI,UACF,qBAAoB,SAAS,UAAU;;;;;KAOpD;GACD;CACH,CAAC"}

@@ -1,61 +0,72 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const constants = require("./constants.cjs");
const require_constants = require("./constants.cjs");
//#region src/rules/route-param-names/route-param-names.utils.ts
/**
* Extracts param names from a route path segment.
*
* Handles these patterns:
* - $paramName -> extract "paramName"
* - {$paramName} -> extract "paramName"
* - prefix{$paramName}suffix -> extract "paramName"
* - {-$paramName} -> extract "paramName" (optional)
* - prefix{-$paramName}suffix -> extract "paramName" (optional)
* - $ or {$} -> wildcard, skip validation
*/
function extractParamsFromSegment(segment) {
const params = [];
if (!segment || !segment.includes("$")) {
return params;
}
if (segment === "$" || segment === "{$}") {
return params;
}
if (segment.startsWith("$") && !segment.includes("{")) {
const paramName = segment.slice(1);
if (paramName) {
params.push({
fullParam: segment,
paramName,
isOptional: false,
isValid: constants.VALID_PARAM_NAME_REGEX.test(paramName)
});
}
return params;
}
const bracePattern = /\{(-?\$)([^}]*)\}/g;
let match;
while ((match = bracePattern.exec(segment)) !== null) {
const prefix = match[1];
const paramName = match[2];
if (!paramName) {
continue;
}
const isOptional = prefix === "-$";
params.push({
fullParam: `${prefix}${paramName}`,
paramName,
isOptional,
isValid: constants.VALID_PARAM_NAME_REGEX.test(paramName)
});
}
return params;
const params = [];
if (!segment || !segment.includes("$")) return params;
if (segment === "$" || segment === "{$}") return params;
if (segment.startsWith("$") && !segment.includes("{")) {
const paramName = segment.slice(1);
if (paramName) params.push({
fullParam: segment,
paramName,
isOptional: false,
isValid: require_constants.VALID_PARAM_NAME_REGEX.test(paramName)
});
return params;
}
const bracePattern = /\{(-?\$)([^}]*)\}/g;
let match;
while ((match = bracePattern.exec(segment)) !== null) {
const prefix = match[1];
const paramName = match[2];
if (!paramName) continue;
const isOptional = prefix === "-$";
params.push({
fullParam: `${prefix}${paramName}`,
paramName,
isOptional,
isValid: require_constants.VALID_PARAM_NAME_REGEX.test(paramName)
});
}
return params;
}
/**
* Extracts all params from a route path.
*
* @param path - The route path (e.g., "/users/$userId/posts/$postId")
* @returns Array of extracted params with validation info
*/
function extractParamsFromPath(path) {
if (!path || !path.includes("$")) {
return [];
}
const segments = path.split("/");
const allParams = [];
for (const segment of segments) {
const params = extractParamsFromSegment(segment);
allParams.push(...params);
}
return allParams;
if (!path || !path.includes("$")) return [];
const segments = path.split("/");
const allParams = [];
for (const segment of segments) {
const params = extractParamsFromSegment(segment);
allParams.push(...params);
}
return allParams;
}
/**
* Gets all invalid params from a route path.
*
* @param path - The route path
* @returns Array of invalid param info
*/
function getInvalidParams(path) {
const params = extractParamsFromPath(path);
return params.filter((p) => !p.isValid);
return extractParamsFromPath(path).filter((p) => !p.isValid);
}
exports.extractParamsFromPath = extractParamsFromPath;
exports.extractParamsFromSegment = extractParamsFromSegment;
//#endregion
exports.getInvalidParams = getInvalidParams;
//# sourceMappingURL=route-param-names.utils.cjs.map
//# sourceMappingURL=route-param-names.utils.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"route-param-names.utils.cjs","sources":["../../../../src/rules/route-param-names/route-param-names.utils.ts"],"sourcesContent":["import { VALID_PARAM_NAME_REGEX } from './constants'\n\nexport interface ExtractedParam {\n /** The full param string including $ prefix (e.g., \"$userId\", \"-$optional\") */\n fullParam: string\n /** The param name without $ prefix (e.g., \"userId\", \"optional\") */\n paramName: string\n /** Whether this is an optional param (prefixed with -$) */\n isOptional: boolean\n /** Whether this param name is valid */\n isValid: boolean\n}\n\n/**\n * Extracts param names from a route path segment.\n *\n * Handles these patterns:\n * - $paramName -> extract \"paramName\"\n * - {$paramName} -> extract \"paramName\"\n * - prefix{$paramName}suffix -> extract \"paramName\"\n * - {-$paramName} -> extract \"paramName\" (optional)\n * - prefix{-$paramName}suffix -> extract \"paramName\" (optional)\n * - $ or {$} -> wildcard, skip validation\n */\nexport function extractParamsFromSegment(\n segment: string,\n): Array<ExtractedParam> {\n const params: Array<ExtractedParam> = []\n\n // Skip empty segments\n if (!segment || !segment.includes('$')) {\n return params\n }\n\n // Check for wildcard ($ alone or {$})\n if (segment === '$' || segment === '{$}') {\n return params // Wildcard, no param name to validate\n }\n\n // Pattern 1: Simple $paramName (entire segment starts with $)\n if (segment.startsWith('$') && !segment.includes('{')) {\n const paramName = segment.slice(1)\n if (paramName) {\n params.push({\n fullParam: segment,\n paramName,\n isOptional: false,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n return params\n }\n\n // Pattern 2: Braces pattern {$paramName} or {-$paramName} with optional prefix/suffix\n // Match patterns like: prefix{$param}suffix, {$param}, {-$param}\n const bracePattern = /\\{(-?\\$)([^}]*)\\}/g\n let match\n\n while ((match = bracePattern.exec(segment)) !== null) {\n const prefix = match[1] // \"$\" or \"-$\"\n const paramName = match[2] // The param name after $ or -$\n\n if (!paramName) {\n // This is a wildcard {$} or {-$}, skip\n continue\n }\n\n const isOptional = prefix === '-$'\n\n params.push({\n fullParam: `${prefix}${paramName}`,\n paramName,\n isOptional,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n\n return params\n}\n\n/**\n * Extracts all params from a route path.\n *\n * @param path - The route path (e.g., \"/users/$userId/posts/$postId\")\n * @returns Array of extracted params with validation info\n */\nexport function extractParamsFromPath(path: string): Array<ExtractedParam> {\n if (!path || !path.includes('$')) {\n return []\n }\n\n const segments = path.split('/')\n const allParams: Array<ExtractedParam> = []\n\n for (const segment of segments) {\n const params = extractParamsFromSegment(segment)\n allParams.push(...params)\n }\n\n return allParams\n}\n\n/**\n * Validates a single param name.\n *\n * @param paramName - The param name to validate (without $ prefix)\n * @returns Whether the param name is valid\n */\nexport function isValidParamName(paramName: string): boolean {\n return VALID_PARAM_NAME_REGEX.test(paramName)\n}\n\n/**\n * Gets all invalid params from a route path.\n *\n * @param path - The route path\n * @returns Array of invalid param info\n */\nexport function getInvalidParams(path: string): Array<ExtractedParam> {\n const params = extractParamsFromPath(path)\n return params.filter((p) => !p.isValid)\n}\n"],"names":["VALID_PARAM_NAME_REGEX"],"mappings":";;;AAwBO,SAAS,yBACd,SACuB;AACvB,QAAM,SAAgC,CAAA;AAGtC,MAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,GAAG,GAAG;AACtC,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,OAAO,YAAY,OAAO;AACxC,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,SAAS,GAAG,GAAG;AACrD,UAAM,YAAY,QAAQ,MAAM,CAAC;AACjC,QAAI,WAAW;AACb,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX;AAAA,QACA,YAAY;AAAA,QACZ,SAASA,UAAAA,uBAAuB,KAAK,SAAS;AAAA,MAAA,CAC/C;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAIA,QAAM,eAAe;AACrB,MAAI;AAEJ,UAAQ,QAAQ,aAAa,KAAK,OAAO,OAAO,MAAM;AACpD,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,YAAY,MAAM,CAAC;AAEzB,QAAI,CAAC,WAAW;AAEd;AAAA,IACF;AAEA,UAAM,aAAa,WAAW;AAE9B,WAAO,KAAK;AAAA,MACV,WAAW,GAAG,MAAM,GAAG,SAAS;AAAA,MAChC;AAAA,MACA;AAAA,MACA,SAASA,UAAAA,uBAAuB,KAAK,SAAS;AAAA,IAAA,CAC/C;AAAA,EACH;AAEA,SAAO;AACT;AAQO,SAAS,sBAAsB,MAAqC;AACzE,MAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,GAAG,GAAG;AAChC,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,QAAM,YAAmC,CAAA;AAEzC,aAAW,WAAW,UAAU;AAC9B,UAAM,SAAS,yBAAyB,OAAO;AAC/C,cAAU,KAAK,GAAG,MAAM;AAAA,EAC1B;AAEA,SAAO;AACT;AAkBO,SAAS,iBAAiB,MAAqC;AACpE,QAAM,SAAS,sBAAsB,IAAI;AACzC,SAAO,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO;AACxC;;;;"}
{"version":3,"file":"route-param-names.utils.cjs","names":[],"sources":["../../../../src/rules/route-param-names/route-param-names.utils.ts"],"sourcesContent":["import { VALID_PARAM_NAME_REGEX } from './constants'\n\nexport interface ExtractedParam {\n /** The full param string including $ prefix (e.g., \"$userId\", \"-$optional\") */\n fullParam: string\n /** The param name without $ prefix (e.g., \"userId\", \"optional\") */\n paramName: string\n /** Whether this is an optional param (prefixed with -$) */\n isOptional: boolean\n /** Whether this param name is valid */\n isValid: boolean\n}\n\n/**\n * Extracts param names from a route path segment.\n *\n * Handles these patterns:\n * - $paramName -> extract \"paramName\"\n * - {$paramName} -> extract \"paramName\"\n * - prefix{$paramName}suffix -> extract \"paramName\"\n * - {-$paramName} -> extract \"paramName\" (optional)\n * - prefix{-$paramName}suffix -> extract \"paramName\" (optional)\n * - $ or {$} -> wildcard, skip validation\n */\nexport function extractParamsFromSegment(\n segment: string,\n): Array<ExtractedParam> {\n const params: Array<ExtractedParam> = []\n\n // Skip empty segments\n if (!segment || !segment.includes('$')) {\n return params\n }\n\n // Check for wildcard ($ alone or {$})\n if (segment === '$' || segment === '{$}') {\n return params // Wildcard, no param name to validate\n }\n\n // Pattern 1: Simple $paramName (entire segment starts with $)\n if (segment.startsWith('$') && !segment.includes('{')) {\n const paramName = segment.slice(1)\n if (paramName) {\n params.push({\n fullParam: segment,\n paramName,\n isOptional: false,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n return params\n }\n\n // Pattern 2: Braces pattern {$paramName} or {-$paramName} with optional prefix/suffix\n // Match patterns like: prefix{$param}suffix, {$param}, {-$param}\n const bracePattern = /\\{(-?\\$)([^}]*)\\}/g\n let match\n\n while ((match = bracePattern.exec(segment)) !== null) {\n const prefix = match[1] // \"$\" or \"-$\"\n const paramName = match[2] // The param name after $ or -$\n\n if (!paramName) {\n // This is a wildcard {$} or {-$}, skip\n continue\n }\n\n const isOptional = prefix === '-$'\n\n params.push({\n fullParam: `${prefix}${paramName}`,\n paramName,\n isOptional,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n\n return params\n}\n\n/**\n * Extracts all params from a route path.\n *\n * @param path - The route path (e.g., \"/users/$userId/posts/$postId\")\n * @returns Array of extracted params with validation info\n */\nexport function extractParamsFromPath(path: string): Array<ExtractedParam> {\n if (!path || !path.includes('$')) {\n return []\n }\n\n const segments = path.split('/')\n const allParams: Array<ExtractedParam> = []\n\n for (const segment of segments) {\n const params = extractParamsFromSegment(segment)\n allParams.push(...params)\n }\n\n return allParams\n}\n\n/**\n * Validates a single param name.\n *\n * @param paramName - The param name to validate (without $ prefix)\n * @returns Whether the param name is valid\n */\nexport function isValidParamName(paramName: string): boolean {\n return VALID_PARAM_NAME_REGEX.test(paramName)\n}\n\n/**\n * Gets all invalid params from a route path.\n *\n * @param path - The route path\n * @returns Array of invalid param info\n */\nexport function getInvalidParams(path: string): Array<ExtractedParam> {\n const params = extractParamsFromPath(path)\n return params.filter((p) => !p.isValid)\n}\n"],"mappings":";;;;;;;;;;;;;AAwBA,SAAgB,yBACd,SACuB;CACvB,MAAM,SAAgC,EAAE;AAGxC,KAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,IAAI,CACpC,QAAO;AAIT,KAAI,YAAY,OAAO,YAAY,MACjC,QAAO;AAIT,KAAI,QAAQ,WAAW,IAAI,IAAI,CAAC,QAAQ,SAAS,IAAI,EAAE;EACrD,MAAM,YAAY,QAAQ,MAAM,EAAE;AAClC,MAAI,UACF,QAAO,KAAK;GACV,WAAW;GACX;GACA,YAAY;GACZ,SAAS,kBAAA,uBAAuB,KAAK,UAAU;GAChD,CAAC;AAEJ,SAAO;;CAKT,MAAM,eAAe;CACrB,IAAI;AAEJ,SAAQ,QAAQ,aAAa,KAAK,QAAQ,MAAM,MAAM;EACpD,MAAM,SAAS,MAAM;EACrB,MAAM,YAAY,MAAM;AAExB,MAAI,CAAC,UAEH;EAGF,MAAM,aAAa,WAAW;AAE9B,SAAO,KAAK;GACV,WAAW,GAAG,SAAS;GACvB;GACA;GACA,SAAS,kBAAA,uBAAuB,KAAK,UAAU;GAChD,CAAC;;AAGJ,QAAO;;;;;;;;AAST,SAAgB,sBAAsB,MAAqC;AACzE,KAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,CAC9B,QAAO,EAAE;CAGX,MAAM,WAAW,KAAK,MAAM,IAAI;CAChC,MAAM,YAAmC,EAAE;AAE3C,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,yBAAyB,QAAQ;AAChD,YAAU,KAAK,GAAG,OAAO;;AAG3B,QAAO;;;;;;;;AAmBT,SAAgB,iBAAiB,MAAqC;AAEpE,QADe,sBAAsB,KAAK,CAC5B,QAAQ,MAAM,CAAC,EAAE,QAAQ"}

@@ -1,54 +0,38 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const utils = require("@typescript-eslint/utils");
let _typescript_eslint_utils = require("@typescript-eslint/utils");
//#region src/utils/detect-router-imports.ts
function detectTanstackRouterImports(create) {
return (context, optionsWithDefault) => {
const tanstackRouterImportSpecifiers = [];
const helpers = {
isSpecificTanstackRouterImport(node, source) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === utils.TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.parent.type === utils.TSESTree.AST_NODE_TYPES.ImportDeclaration && specifier.parent.source.value === source) {
return node.name === specifier.local.name;
}
return false;
});
},
isTanstackRouterImport(node) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === utils.TSESTree.AST_NODE_TYPES.ImportSpecifier) {
return node.name === specifier.local.name;
}
return false;
});
}
};
const detectionInstructions = {
ImportDeclaration(node) {
if (node.specifiers.length > 0 && // `importKind` is parser-dependent and can be undefined (eg. Espree)
node.importKind !== "type" && node.source.value.startsWith("@tanstack/") && node.source.value.endsWith("-router")) {
tanstackRouterImportSpecifiers.push(...node.specifiers);
}
}
};
const ruleInstructions = create(context, optionsWithDefault, helpers);
const enhancedRuleInstructions = {};
const allKeys = new Set(
Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions))
);
allKeys.forEach((instruction) => {
enhancedRuleInstructions[instruction] = (node) => {
if (instruction in detectionInstructions) {
detectionInstructions[instruction]?.(node);
}
const ruleFunction = ruleInstructions[instruction];
if (ruleFunction !== void 0) {
return ruleFunction(node);
}
return void 0;
};
});
return enhancedRuleInstructions;
};
return (context, optionsWithDefault) => {
const tanstackRouterImportSpecifiers = [];
const helpers = {
isSpecificTanstackRouterImport(node, source) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === _typescript_eslint_utils.TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.parent.type === _typescript_eslint_utils.TSESTree.AST_NODE_TYPES.ImportDeclaration && specifier.parent.source.value === source) return node.name === specifier.local.name;
return false;
});
},
isTanstackRouterImport(node) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === _typescript_eslint_utils.TSESTree.AST_NODE_TYPES.ImportSpecifier) return node.name === specifier.local.name;
return false;
});
}
};
const detectionInstructions = { ImportDeclaration(node) {
if (node.specifiers.length > 0 && node.importKind !== "type" && node.source.value.startsWith("@tanstack/") && node.source.value.endsWith("-router")) tanstackRouterImportSpecifiers.push(...node.specifiers);
} };
const ruleInstructions = create(context, optionsWithDefault, helpers);
const enhancedRuleInstructions = {};
new Set(Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions))).forEach((instruction) => {
enhancedRuleInstructions[instruction] = (node) => {
if (instruction in detectionInstructions) detectionInstructions[instruction]?.(node);
const ruleFunction = ruleInstructions[instruction];
if (ruleFunction !== void 0) return ruleFunction(node);
};
});
return enhancedRuleInstructions;
};
}
//#endregion
exports.detectTanstackRouterImports = detectTanstackRouterImports;
//# sourceMappingURL=detect-router-imports.cjs.map
//# sourceMappingURL=detect-router-imports.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"detect-router-imports.cjs","sources":["../../../src/utils/detect-router-imports.ts"],"sourcesContent":["import { TSESTree } from '@typescript-eslint/utils'\nimport type { ESLintUtils, TSESLint } from '@typescript-eslint/utils'\n\ntype Create = Parameters<\n ReturnType<typeof ESLintUtils.RuleCreator>\n>[0]['create']\n\ntype Context = Parameters<Create>[0]\ntype Options = Parameters<Create>[1]\ntype Helpers = {\n isSpecificTanstackRouterImport: (\n node: TSESTree.Identifier,\n source: string,\n ) => boolean\n isTanstackRouterImport: (node: TSESTree.Identifier) => boolean\n}\n\ntype EnhancedCreate = (\n context: Context,\n options: Options,\n helpers: Helpers,\n) => ReturnType<Create>\n\nexport function detectTanstackRouterImports(create: EnhancedCreate): Create {\n return (context, optionsWithDefault) => {\n const tanstackRouterImportSpecifiers: Array<TSESTree.ImportClause> = []\n\n const helpers: Helpers = {\n isSpecificTanstackRouterImport(node, source) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (\n specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier &&\n specifier.parent.type ===\n TSESTree.AST_NODE_TYPES.ImportDeclaration &&\n specifier.parent.source.value === source\n ) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n isTanstackRouterImport(node) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n }\n\n const detectionInstructions: TSESLint.RuleListener = {\n ImportDeclaration(node) {\n if (\n node.specifiers.length > 0 &&\n // `importKind` is parser-dependent and can be undefined (eg. Espree)\n node.importKind !== 'type' &&\n node.source.value.startsWith('@tanstack/') &&\n node.source.value.endsWith('-router')\n ) {\n tanstackRouterImportSpecifiers.push(...node.specifiers)\n }\n },\n }\n\n // Call original rule definition\n const ruleInstructions = create(context, optionsWithDefault, helpers)\n const enhancedRuleInstructions: TSESLint.RuleListener = {}\n\n const allKeys = new Set(\n Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions)),\n )\n\n // Iterate over ALL instructions keys so we can override original rule instructions\n // to prevent their execution if conditions to report errors are not met.\n allKeys.forEach((instruction) => {\n enhancedRuleInstructions[instruction] = (node) => {\n if (instruction in detectionInstructions) {\n detectionInstructions[instruction]?.(node)\n }\n\n const ruleFunction = ruleInstructions[instruction]\n if (ruleFunction !== undefined) {\n return ruleFunction(node)\n }\n\n return undefined\n }\n })\n\n return enhancedRuleInstructions\n }\n}\n"],"names":["TSESTree"],"mappings":";;;AAuBO,SAAS,4BAA4B,QAAgC;AAC1E,SAAO,CAAC,SAAS,uBAAuB;AACtC,UAAM,iCAA+D,CAAA;AAErE,UAAM,UAAmB;AAAA,MACvB,+BAA+B,MAAM,QAAQ;AAC3C,eAAO,CAAC,CAAC,+BAA+B,KAAK,CAAC,cAAc;AAC1D,cACE,UAAU,SAASA,MAAAA,SAAS,eAAe,mBAC3C,UAAU,OAAO,SACfA,MAAAA,SAAS,eAAe,qBAC1B,UAAU,OAAO,OAAO,UAAU,QAClC;AACA,mBAAO,KAAK,SAAS,UAAU,MAAM;AAAA,UACvC;AAEA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,MACA,uBAAuB,MAAM;AAC3B,eAAO,CAAC,CAAC,+BAA+B,KAAK,CAAC,cAAc;AAC1D,cAAI,UAAU,SAASA,eAAS,eAAe,iBAAiB;AAC9D,mBAAO,KAAK,SAAS,UAAU,MAAM;AAAA,UACvC;AAEA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IAAA;AAGF,UAAM,wBAA+C;AAAA,MACnD,kBAAkB,MAAM;AACtB,YACE,KAAK,WAAW,SAAS;AAAA,QAEzB,KAAK,eAAe,UACpB,KAAK,OAAO,MAAM,WAAW,YAAY,KACzC,KAAK,OAAO,MAAM,SAAS,SAAS,GACpC;AACA,yCAA+B,KAAK,GAAG,KAAK,UAAU;AAAA,QACxD;AAAA,MACF;AAAA,IAAA;AAIF,UAAM,mBAAmB,OAAO,SAAS,oBAAoB,OAAO;AACpE,UAAM,2BAAkD,CAAA;AAExD,UAAM,UAAU,IAAI;AAAA,MAClB,OAAO,KAAK,qBAAqB,EAAE,OAAO,OAAO,KAAK,gBAAgB,CAAC;AAAA,IAAA;AAKzE,YAAQ,QAAQ,CAAC,gBAAgB;AAC/B,+BAAyB,WAAW,IAAI,CAAC,SAAS;AAChD,YAAI,eAAe,uBAAuB;AACxC,gCAAsB,WAAW,IAAI,IAAI;AAAA,QAC3C;AAEA,cAAM,eAAe,iBAAiB,WAAW;AACjD,YAAI,iBAAiB,QAAW;AAC9B,iBAAO,aAAa,IAAI;AAAA,QAC1B;AAEA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;;"}
{"version":3,"file":"detect-router-imports.cjs","names":[],"sources":["../../../src/utils/detect-router-imports.ts"],"sourcesContent":["import { TSESTree } from '@typescript-eslint/utils'\nimport type { ESLintUtils, TSESLint } from '@typescript-eslint/utils'\n\ntype Create = Parameters<\n ReturnType<typeof ESLintUtils.RuleCreator>\n>[0]['create']\n\ntype Context = Parameters<Create>[0]\ntype Options = Parameters<Create>[1]\ntype Helpers = {\n isSpecificTanstackRouterImport: (\n node: TSESTree.Identifier,\n source: string,\n ) => boolean\n isTanstackRouterImport: (node: TSESTree.Identifier) => boolean\n}\n\ntype EnhancedCreate = (\n context: Context,\n options: Options,\n helpers: Helpers,\n) => ReturnType<Create>\n\nexport function detectTanstackRouterImports(create: EnhancedCreate): Create {\n return (context, optionsWithDefault) => {\n const tanstackRouterImportSpecifiers: Array<TSESTree.ImportClause> = []\n\n const helpers: Helpers = {\n isSpecificTanstackRouterImport(node, source) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (\n specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier &&\n specifier.parent.type ===\n TSESTree.AST_NODE_TYPES.ImportDeclaration &&\n specifier.parent.source.value === source\n ) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n isTanstackRouterImport(node) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n }\n\n const detectionInstructions: TSESLint.RuleListener = {\n ImportDeclaration(node) {\n if (\n node.specifiers.length > 0 &&\n // `importKind` is parser-dependent and can be undefined (eg. Espree)\n node.importKind !== 'type' &&\n node.source.value.startsWith('@tanstack/') &&\n node.source.value.endsWith('-router')\n ) {\n tanstackRouterImportSpecifiers.push(...node.specifiers)\n }\n },\n }\n\n // Call original rule definition\n const ruleInstructions = create(context, optionsWithDefault, helpers)\n const enhancedRuleInstructions: TSESLint.RuleListener = {}\n\n const allKeys = new Set(\n Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions)),\n )\n\n // Iterate over ALL instructions keys so we can override original rule instructions\n // to prevent their execution if conditions to report errors are not met.\n allKeys.forEach((instruction) => {\n enhancedRuleInstructions[instruction] = (node) => {\n if (instruction in detectionInstructions) {\n detectionInstructions[instruction]?.(node)\n }\n\n const ruleFunction = ruleInstructions[instruction]\n if (ruleFunction !== undefined) {\n return ruleFunction(node)\n }\n\n return undefined\n }\n })\n\n return enhancedRuleInstructions\n }\n}\n"],"mappings":";;AAuBA,SAAgB,4BAA4B,QAAgC;AAC1E,SAAQ,SAAS,uBAAuB;EACtC,MAAM,iCAA+D,EAAE;EAEvE,MAAM,UAAmB;GACvB,+BAA+B,MAAM,QAAQ;AAC3C,WAAO,CAAC,CAAC,+BAA+B,MAAM,cAAc;AAC1D,SACE,UAAU,SAAS,yBAAA,SAAS,eAAe,mBAC3C,UAAU,OAAO,SACf,yBAAA,SAAS,eAAe,qBAC1B,UAAU,OAAO,OAAO,UAAU,OAElC,QAAO,KAAK,SAAS,UAAU,MAAM;AAGvC,YAAO;MACP;;GAEJ,uBAAuB,MAAM;AAC3B,WAAO,CAAC,CAAC,+BAA+B,MAAM,cAAc;AAC1D,SAAI,UAAU,SAAS,yBAAA,SAAS,eAAe,gBAC7C,QAAO,KAAK,SAAS,UAAU,MAAM;AAGvC,YAAO;MACP;;GAEL;EAED,MAAM,wBAA+C,EACnD,kBAAkB,MAAM;AACtB,OACE,KAAK,WAAW,SAAS,KAEzB,KAAK,eAAe,UACpB,KAAK,OAAO,MAAM,WAAW,aAAa,IAC1C,KAAK,OAAO,MAAM,SAAS,UAAU,CAErC,gCAA+B,KAAK,GAAG,KAAK,WAAW;KAG5D;EAGD,MAAM,mBAAmB,OAAO,SAAS,oBAAoB,QAAQ;EACrE,MAAM,2BAAkD,EAAE;AAE1C,MAAI,IAClB,OAAO,KAAK,sBAAsB,CAAC,OAAO,OAAO,KAAK,iBAAiB,CAAC,CACzE,CAIO,SAAS,gBAAgB;AAC/B,4BAAyB,gBAAgB,SAAS;AAChD,QAAI,eAAe,sBACjB,uBAAsB,eAAe,KAAK;IAG5C,MAAM,eAAe,iBAAiB;AACtC,QAAI,iBAAiB,KAAA,EACnB,QAAO,aAAa,KAAK;;IAK7B;AAEF,SAAO"}

@@ -1,5 +0,6 @@

"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const getDocsUrl = (ruleName) => `https://tanstack.com/router/latest/docs/eslint/${ruleName}`;
//#region src/utils/get-docs-url.ts
var getDocsUrl = (ruleName) => `https://tanstack.com/router/latest/docs/eslint/${ruleName}`;
//#endregion
exports.getDocsUrl = getDocsUrl;
//# sourceMappingURL=get-docs-url.cjs.map
//# sourceMappingURL=get-docs-url.cjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"get-docs-url.cjs","sources":["../../../src/utils/get-docs-url.ts"],"sourcesContent":["export const getDocsUrl = (ruleName: string): string =>\n `https://tanstack.com/router/latest/docs/eslint/${ruleName}`\n"],"names":[],"mappings":";;AAAO,MAAM,aAAa,CAAC,aACzB,kDAAkD,QAAQ;;"}
{"version":3,"file":"get-docs-url.cjs","names":[],"sources":["../../../src/utils/get-docs-url.ts"],"sourcesContent":["export const getDocsUrl = (ruleName: string): string =>\n `https://tanstack.com/router/latest/docs/eslint/${ruleName}`\n"],"mappings":";AAAA,IAAa,cAAc,aACzB,kDAAkD"}
import { rules } from "./rules.js";
const plugin = {
meta: {
name: "@tanstack/eslint-plugin-router"
},
configs: {},
rules
//#region src/index.ts
var plugin = {
meta: { name: "@tanstack/eslint-plugin-router" },
configs: {},
rules
};
Object.assign(plugin.configs, {
recommended: {
plugins: ["@tanstack/eslint-plugin-router"],
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
},
"flat/recommended": [
{
plugins: {
"@tanstack/router": plugin
},
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
}
]
recommended: {
plugins: ["@tanstack/eslint-plugin-router"],
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
},
"flat/recommended": [{
plugins: { "@tanstack/router": plugin },
rules: {
"@tanstack/router/create-route-property-order": "warn",
"@tanstack/router/route-param-names": "error"
}
}]
});
export {
plugin as default
};
//# sourceMappingURL=index.js.map
//#endregion
export { plugin as default };
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import { rules } from './rules'\nimport type { ESLint, Linter } from 'eslint'\nimport type { RuleModule } from '@typescript-eslint/utils/ts-eslint'\n\ntype RuleKey = keyof typeof rules\n\ninterface Plugin extends Omit<ESLint.Plugin, 'rules'> {\n rules: Record<RuleKey, RuleModule<any, any, any>>\n configs: {\n recommended: ESLint.ConfigData\n 'flat/recommended': Array<Linter.FlatConfig>\n }\n}\n\nconst plugin: Plugin = {\n meta: {\n name: '@tanstack/eslint-plugin-router',\n },\n configs: {} as Plugin['configs'],\n rules,\n}\n\n// Assign configs here so we can reference `plugin`\nObject.assign(plugin.configs, {\n recommended: {\n plugins: ['@tanstack/eslint-plugin-router'],\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n 'flat/recommended': [\n {\n plugins: {\n '@tanstack/router': plugin,\n },\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n ],\n})\n\nexport default plugin\n"],"names":[],"mappings":";AAcA,MAAM,SAAiB;AAAA,EACrB,MAAM;AAAA,IACJ,MAAM;AAAA,EAAA;AAAA,EAER,SAAS,CAAA;AAAA,EACT;AACF;AAGA,OAAO,OAAO,OAAO,SAAS;AAAA,EAC5B,aAAa;AAAA,IACX,SAAS,CAAC,gCAAgC;AAAA,IAC1C,OAAO;AAAA,MACL,gDAAgD;AAAA,MAChD,sCAAsC;AAAA,IAAA;AAAA,EACxC;AAAA,EAEF,oBAAoB;AAAA,IAClB;AAAA,MACE,SAAS;AAAA,QACP,oBAAoB;AAAA,MAAA;AAAA,MAEtB,OAAO;AAAA,QACL,gDAAgD;AAAA,QAChD,sCAAsC;AAAA,MAAA;AAAA,IACxC;AAAA,EACF;AAEJ,CAAC;"}
{"version":3,"file":"index.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import { rules } from './rules'\nimport type { ESLint, Linter } from 'eslint'\nimport type { RuleModule } from '@typescript-eslint/utils/ts-eslint'\n\ntype RuleKey = keyof typeof rules\n\ninterface Plugin extends Omit<ESLint.Plugin, 'rules'> {\n rules: Record<RuleKey, RuleModule<any, any, any>>\n configs: {\n recommended: ESLint.ConfigData\n 'flat/recommended': Array<Linter.FlatConfig>\n }\n}\n\nconst plugin: Plugin = {\n meta: {\n name: '@tanstack/eslint-plugin-router',\n },\n configs: {} as Plugin['configs'],\n rules,\n}\n\n// Assign configs here so we can reference `plugin`\nObject.assign(plugin.configs, {\n recommended: {\n plugins: ['@tanstack/eslint-plugin-router'],\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n 'flat/recommended': [\n {\n plugins: {\n '@tanstack/router': plugin,\n },\n rules: {\n '@tanstack/router/create-route-property-order': 'warn',\n '@tanstack/router/route-param-names': 'error',\n },\n },\n ],\n})\n\nexport default plugin\n"],"mappings":";;AAcA,IAAM,SAAiB;CACrB,MAAM,EACJ,MAAM,kCACP;CACD,SAAS,EAAE;CACX;CACD;AAGD,OAAO,OAAO,OAAO,SAAS;CAC5B,aAAa;EACX,SAAS,CAAC,iCAAiC;EAC3C,OAAO;GACL,gDAAgD;GAChD,sCAAsC;GACvC;EACF;CACD,oBAAoB,CAClB;EACE,SAAS,EACP,oBAAoB,QACrB;EACD,OAAO;GACL,gDAAgD;GAChD,sCAAsC;GACvC;EACF,CACF;CACF,CAAC"}

@@ -1,10 +0,11 @@

import { rule as rule$1, name as name$1 } from "./rules/create-route-property-order/create-route-property-order.rule.js";
import { rule, name } from "./rules/route-param-names/route-param-names.rule.js";
const rules = {
[name$1]: rule$1,
[name]: rule
import { name, rule } from "./rules/create-route-property-order/create-route-property-order.rule.js";
import { name as name$1, rule as rule$1 } from "./rules/route-param-names/route-param-names.rule.js";
//#region src/rules.ts
var rules = {
[name]: rule,
[name$1]: rule$1
};
export {
rules
};
//# sourceMappingURL=rules.js.map
//#endregion
export { rules };
//# sourceMappingURL=rules.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"rules.js","sources":["../../src/rules.ts"],"sourcesContent":["import * as createRoutePropertyOrder from './rules/create-route-property-order/create-route-property-order.rule'\nimport * as routeParamNames from './rules/route-param-names/route-param-names.rule'\nimport type { ESLintUtils } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from './types'\n\nexport const rules: Record<\n string,\n ESLintUtils.RuleModule<\n string,\n ReadonlyArray<unknown>,\n ExtraRuleDocs,\n ESLintUtils.RuleListener\n >\n> = {\n [createRoutePropertyOrder.name]: createRoutePropertyOrder.rule,\n [routeParamNames.name]: routeParamNames.rule,\n}\n"],"names":["createRoutePropertyOrder.name","createRoutePropertyOrder.rule","routeParamNames.name","routeParamNames.rule"],"mappings":";;AAKO,MAAM,QAQT;AAAA,EACF,CAACA,MAA6B,GAAGC;AAAAA,EACjC,CAACC,IAAoB,GAAGC;AAC1B;"}
{"version":3,"file":"rules.js","names":[],"sources":["../../src/rules.ts"],"sourcesContent":["import * as createRoutePropertyOrder from './rules/create-route-property-order/create-route-property-order.rule'\nimport * as routeParamNames from './rules/route-param-names/route-param-names.rule'\nimport type { ESLintUtils } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from './types'\n\nexport const rules: Record<\n string,\n ESLintUtils.RuleModule<\n string,\n ReadonlyArray<unknown>,\n ExtraRuleDocs,\n ESLintUtils.RuleListener\n >\n> = {\n [createRoutePropertyOrder.name]: createRoutePropertyOrder.rule,\n [routeParamNames.name]: routeParamNames.rule,\n}\n"],"mappings":";;;AAKA,IAAa,QAQT;EACD,OAAgC;EAChC,SAAuB;CACzB"}
import { getCheckedProperties } from "./create-route-property-order.utils.js";
const createRouteFunctionsIndirect = [
"createFileRoute",
"createRootRouteWithContext"
//#region src/rules/create-route-property-order/constants.ts
var createRouteFunctionsIndirect = ["createFileRoute", "createRootRouteWithContext"];
var createRouteFunctions = [...["createRootRoute", "createRoute"], ...createRouteFunctionsIndirect];
var sortRules = [
[["params", "validateSearch"], ["search"]],
[["search"], ["loaderDeps", "ssr"]],
[["loaderDeps"], ["context"]],
[["context"], ["beforeLoad"]],
[["beforeLoad"], ["loader"]],
[["loader"], [
"onEnter",
"onStay",
"onLeave",
"head",
"scripts",
"headers",
"remountDeps"
]]
];
const createRouteFunctionsDirect = [
"createRootRoute",
"createRoute"
];
const createRouteFunctions = [
...createRouteFunctionsDirect,
...createRouteFunctionsIndirect
];
const sortRules = [
[["params", "validateSearch"], ["search"]],
[["search"], ["loaderDeps", "ssr"]],
[["loaderDeps"], ["context"]],
[["context"], ["beforeLoad"]],
[["beforeLoad"], ["loader"]],
[
["loader"],
[
"onEnter",
"onStay",
"onLeave",
"head",
"scripts",
"headers",
"remountDeps"
]
]
];
getCheckedProperties(sortRules);
export {
createRouteFunctions,
createRouteFunctionsDirect,
createRouteFunctionsIndirect,
sortRules
};
//# sourceMappingURL=constants.js.map
//#endregion
export { createRouteFunctions, createRouteFunctionsIndirect, sortRules };
//# sourceMappingURL=constants.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"constants.js","sources":["../../../../src/rules/create-route-property-order/constants.ts"],"sourcesContent":["import { getCheckedProperties } from './create-route-property-order.utils'\n\nexport const createRouteFunctionsIndirect = [\n 'createFileRoute',\n 'createRootRouteWithContext',\n] as const\nexport const createRouteFunctionsDirect = [\n 'createRootRoute',\n 'createRoute',\n] as const\n\nexport const createRouteFunctions = [\n ...createRouteFunctionsDirect,\n ...createRouteFunctionsIndirect,\n] as const\n\nexport type CreateRouteFunction = (typeof createRouteFunctions)[number]\n\nexport const sortRules = [\n [['params', 'validateSearch'], ['search']],\n [['search'], ['loaderDeps', 'ssr']],\n [['loaderDeps'], ['context']],\n [['context'], ['beforeLoad']],\n [['beforeLoad'], ['loader']],\n [\n ['loader'],\n [\n 'onEnter',\n 'onStay',\n 'onLeave',\n 'head',\n 'scripts',\n 'headers',\n 'remountDeps',\n ],\n ],\n] as const\n\nexport type CheckedProperties = (typeof sortRules)[number][number][number]\nexport const checkedProperties = getCheckedProperties(sortRules)\n"],"names":[],"mappings":";AAEO,MAAM,+BAA+B;AAAA,EAC1C;AAAA,EACA;AACF;AACO,MAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AACF;AAEO,MAAM,uBAAuB;AAAA,EAClC,GAAG;AAAA,EACH,GAAG;AACL;AAIO,MAAM,YAAY;AAAA,EACvB,CAAC,CAAC,UAAU,gBAAgB,GAAG,CAAC,QAAQ,CAAC;AAAA,EACzC,CAAC,CAAC,QAAQ,GAAG,CAAC,cAAc,KAAK,CAAC;AAAA,EAClC,CAAC,CAAC,YAAY,GAAG,CAAC,SAAS,CAAC;AAAA,EAC5B,CAAC,CAAC,SAAS,GAAG,CAAC,YAAY,CAAC;AAAA,EAC5B,CAAC,CAAC,YAAY,GAAG,CAAC,QAAQ,CAAC;AAAA,EAC3B;AAAA,IACE,CAAC,QAAQ;AAAA,IACT;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAEJ;AAGiC,qBAAqB,SAAS;"}
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/rules/create-route-property-order/constants.ts"],"sourcesContent":["import { getCheckedProperties } from './create-route-property-order.utils'\n\nexport const createRouteFunctionsIndirect = [\n 'createFileRoute',\n 'createRootRouteWithContext',\n] as const\nexport const createRouteFunctionsDirect = [\n 'createRootRoute',\n 'createRoute',\n] as const\n\nexport const createRouteFunctions = [\n ...createRouteFunctionsDirect,\n ...createRouteFunctionsIndirect,\n] as const\n\nexport type CreateRouteFunction = (typeof createRouteFunctions)[number]\n\nexport const sortRules = [\n [['params', 'validateSearch'], ['search']],\n [['search'], ['loaderDeps', 'ssr']],\n [['loaderDeps'], ['context']],\n [['context'], ['beforeLoad']],\n [['beforeLoad'], ['loader']],\n [\n ['loader'],\n [\n 'onEnter',\n 'onStay',\n 'onLeave',\n 'head',\n 'scripts',\n 'headers',\n 'remountDeps',\n ],\n ],\n] as const\n\nexport type CheckedProperties = (typeof sortRules)[number][number][number]\nexport const checkedProperties = getCheckedProperties(sortRules)\n"],"mappings":";;AAEA,IAAa,+BAA+B,CAC1C,mBACA,6BACD;AAMD,IAAa,uBAAuB,CAClC,GANwC,CACxC,mBACA,cACD,EAIC,GAAG,6BACJ;AAID,IAAa,YAAY;CACvB,CAAC,CAAC,UAAU,iBAAiB,EAAE,CAAC,SAAS,CAAC;CAC1C,CAAC,CAAC,SAAS,EAAE,CAAC,cAAc,MAAM,CAAC;CACnC,CAAC,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC;CAC7B,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,CAAC;CAC7B,CAAC,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC;CAC5B,CACE,CAAC,SAAS,EACV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;CACF;AAGgC,qBAAqB,UAAU"}

@@ -1,2 +0,1 @@

import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
import { getDocsUrl } from "../../utils/get-docs-url.js";

@@ -6,99 +5,69 @@ import { detectTanstackRouterImports } from "../../utils/detect-router-imports.js";

import { createRouteFunctions, createRouteFunctionsIndirect, sortRules } from "./constants.js";
const createRule = ESLintUtils.RuleCreator(getDocsUrl);
const createRouteFunctionSet = new Set(createRouteFunctions);
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
//#region src/rules/create-route-property-order/create-route-property-order.rule.ts
var createRule = ESLintUtils.RuleCreator(getDocsUrl);
var createRouteFunctionSet = new Set(createRouteFunctions);
function isCreateRouteFunction(node) {
return createRouteFunctionSet.has(node);
return createRouteFunctionSet.has(node);
}
const name = "create-route-property-order";
const rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure correct order of inference sensitive properties for createRoute functions",
recommended: "error"
},
messages: {
invalidOrder: "Invalid order of properties for `{{function}}`."
},
schema: [],
hasSuggestions: true,
fixable: "code"
},
defaultOptions: [],
create: detectTanstackRouterImports((context) => {
return {
CallExpression(node) {
if (node.callee.type !== AST_NODE_TYPES.Identifier) {
return;
}
const createRouteFunction = node.callee.name;
if (!isCreateRouteFunction(createRouteFunction)) {
return;
}
let args = node.arguments;
if (createRouteFunctionsIndirect.includes(createRouteFunction)) {
if (node.parent.type === AST_NODE_TYPES.CallExpression) {
args = node.parent.arguments;
} else {
return;
}
}
const argument = args[0];
if (argument === void 0 || argument.type !== "ObjectExpression") {
return;
}
const allProperties = argument.properties;
if (allProperties.length < 2) {
return;
}
const properties = allProperties.flatMap((p) => {
if (p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier) {
return { name: p.key.name, property: p };
} else if (p.type === AST_NODE_TYPES.SpreadElement) {
if (p.argument.type === AST_NODE_TYPES.Identifier) {
return { name: p.argument.name, property: p };
} else {
throw new Error("Unsupported spread element");
}
}
return [];
});
const sortedProperties = sortDataByOrder(properties, sortRules, "name");
if (sortedProperties === null) {
return;
}
context.report({
node: argument,
data: { function: node.callee.name },
messageId: "invalidOrder",
fix(fixer) {
const sourceCode = context.sourceCode;
const text = sortedProperties.reduce(
(sourceText, specifier, index) => {
let text2 = "";
if (index < allProperties.length - 1) {
text2 = sourceCode.getText().slice(
allProperties[index].range[1],
allProperties[index + 1].range[0]
);
}
return sourceText + sourceCode.getText(specifier.property) + text2;
},
""
);
return fixer.replaceTextRange(
[allProperties[0].range[0], allProperties.at(-1).range[1]],
text
);
}
});
}
};
})
var name = "create-route-property-order";
var rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure correct order of inference sensitive properties for createRoute functions",
recommended: "error"
},
messages: { invalidOrder: "Invalid order of properties for `{{function}}`." },
schema: [],
hasSuggestions: true,
fixable: "code"
},
defaultOptions: [],
create: detectTanstackRouterImports((context) => {
return { CallExpression(node) {
if (node.callee.type !== AST_NODE_TYPES.Identifier) return;
const createRouteFunction = node.callee.name;
if (!isCreateRouteFunction(createRouteFunction)) return;
let args = node.arguments;
if (createRouteFunctionsIndirect.includes(createRouteFunction)) if (node.parent.type === AST_NODE_TYPES.CallExpression) args = node.parent.arguments;
else return;
const argument = args[0];
if (argument === void 0 || argument.type !== "ObjectExpression") return;
const allProperties = argument.properties;
if (allProperties.length < 2) return;
const sortedProperties = sortDataByOrder(allProperties.flatMap((p) => {
if (p.type === AST_NODE_TYPES.Property && p.key.type === AST_NODE_TYPES.Identifier) return {
name: p.key.name,
property: p
};
else if (p.type === AST_NODE_TYPES.SpreadElement) if (p.argument.type === AST_NODE_TYPES.Identifier) return {
name: p.argument.name,
property: p
};
else throw new Error("Unsupported spread element");
return [];
}), sortRules, "name");
if (sortedProperties === null) return;
context.report({
node: argument,
data: { function: node.callee.name },
messageId: "invalidOrder",
fix(fixer) {
const sourceCode = context.sourceCode;
const text = sortedProperties.reduce((sourceText, specifier, index) => {
let text = "";
if (index < allProperties.length - 1) text = sourceCode.getText().slice(allProperties[index].range[1], allProperties[index + 1].range[0]);
return sourceText + sourceCode.getText(specifier.property) + text;
}, "");
return fixer.replaceTextRange([allProperties[0].range[0], allProperties.at(-1).range[1]], text);
}
});
} };
})
});
export {
name,
rule
};
//# sourceMappingURL=create-route-property-order.rule.js.map
//#endregion
export { name, rule };
//# sourceMappingURL=create-route-property-order.rule.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-route-property-order.rule.js","sources":["../../../../src/rules/create-route-property-order/create-route-property-order.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { sortDataByOrder } from './create-route-property-order.utils'\nimport {\n createRouteFunctions,\n createRouteFunctionsIndirect,\n sortRules,\n} from './constants'\nimport type { CreateRouteFunction } from './constants'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst createRouteFunctionSet = new Set(createRouteFunctions)\nfunction isCreateRouteFunction(node: any): node is CreateRouteFunction {\n return createRouteFunctionSet.has(node)\n}\n\nexport const name = 'create-route-property-order'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Ensure correct order of inference sensitive properties for createRoute functions',\n recommended: 'error',\n },\n messages: {\n invalidOrder: 'Invalid order of properties for `{{function}}`.',\n },\n schema: [],\n hasSuggestions: true,\n fixable: 'code',\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context) => {\n return {\n CallExpression(node) {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) {\n return\n }\n const createRouteFunction = node.callee.name\n if (!isCreateRouteFunction(createRouteFunction)) {\n return\n }\n let args = node.arguments\n if (createRouteFunctionsIndirect.includes(createRouteFunction as any)) {\n if (node.parent.type === AST_NODE_TYPES.CallExpression) {\n args = node.parent.arguments\n } else {\n return\n }\n }\n\n const argument = args[0]\n if (argument === undefined || argument.type !== 'ObjectExpression') {\n return\n }\n\n const allProperties = argument.properties\n // no need to sort if there is at max 1 property\n if (allProperties.length < 2) {\n return\n }\n\n const properties = allProperties.flatMap((p) => {\n if (\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier\n ) {\n return { name: p.key.name, property: p }\n } else if (p.type === AST_NODE_TYPES.SpreadElement) {\n if (p.argument.type === AST_NODE_TYPES.Identifier) {\n return { name: p.argument.name, property: p }\n } else {\n throw new Error('Unsupported spread element')\n }\n }\n return []\n })\n\n const sortedProperties = sortDataByOrder(properties, sortRules, 'name')\n if (sortedProperties === null) {\n return\n }\n context.report({\n node: argument,\n data: { function: node.callee.name },\n messageId: 'invalidOrder',\n fix(fixer) {\n const sourceCode = context.sourceCode\n\n const text = sortedProperties.reduce(\n (sourceText, specifier, index) => {\n let text = ''\n if (index < allProperties.length - 1) {\n text = sourceCode\n .getText()\n .slice(\n allProperties[index]!.range[1],\n allProperties[index + 1]!.range[0],\n )\n }\n return (\n sourceText + sourceCode.getText(specifier.property) + text\n )\n },\n '',\n )\n return fixer.replaceTextRange(\n [allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],\n text,\n )\n },\n })\n },\n }\n }),\n})\n"],"names":["text"],"mappings":";;;;;AAaA,MAAM,aAAa,YAAY,YAA2B,UAAU;AAEpE,MAAM,yBAAyB,IAAI,IAAI,oBAAoB;AAC3D,SAAS,sBAAsB,MAAwC;AACrE,SAAO,uBAAuB,IAAI,IAAI;AACxC;AAEO,MAAM,OAAO;AAEb,MAAM,OAAO,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aACE;AAAA,MACF,aAAa;AAAA,IAAA;AAAA,IAEf,UAAU;AAAA,MACR,cAAc;AAAA,IAAA;AAAA,IAEhB,QAAQ,CAAA;AAAA,IACR,gBAAgB;AAAA,IAChB,SAAS;AAAA,EAAA;AAAA,EAEX,gBAAgB,CAAA;AAAA,EAEhB,QAAQ,4BAA4B,CAAC,YAAY;AAC/C,WAAO;AAAA,MACL,eAAe,MAAM;AACnB,YAAI,KAAK,OAAO,SAAS,eAAe,YAAY;AAClD;AAAA,QACF;AACA,cAAM,sBAAsB,KAAK,OAAO;AACxC,YAAI,CAAC,sBAAsB,mBAAmB,GAAG;AAC/C;AAAA,QACF;AACA,YAAI,OAAO,KAAK;AAChB,YAAI,6BAA6B,SAAS,mBAA0B,GAAG;AACrE,cAAI,KAAK,OAAO,SAAS,eAAe,gBAAgB;AACtD,mBAAO,KAAK,OAAO;AAAA,UACrB,OAAO;AACL;AAAA,UACF;AAAA,QACF;AAEA,cAAM,WAAW,KAAK,CAAC;AACvB,YAAI,aAAa,UAAa,SAAS,SAAS,oBAAoB;AAClE;AAAA,QACF;AAEA,cAAM,gBAAgB,SAAS;AAE/B,YAAI,cAAc,SAAS,GAAG;AAC5B;AAAA,QACF;AAEA,cAAM,aAAa,cAAc,QAAQ,CAAC,MAAM;AAC9C,cACE,EAAE,SAAS,eAAe,YAC1B,EAAE,IAAI,SAAS,eAAe,YAC9B;AACA,mBAAO,EAAE,MAAM,EAAE,IAAI,MAAM,UAAU,EAAA;AAAA,UACvC,WAAW,EAAE,SAAS,eAAe,eAAe;AAClD,gBAAI,EAAE,SAAS,SAAS,eAAe,YAAY;AACjD,qBAAO,EAAE,MAAM,EAAE,SAAS,MAAM,UAAU,EAAA;AAAA,YAC5C,OAAO;AACL,oBAAM,IAAI,MAAM,4BAA4B;AAAA,YAC9C;AAAA,UACF;AACA,iBAAO,CAAA;AAAA,QACT,CAAC;AAED,cAAM,mBAAmB,gBAAgB,YAAY,WAAW,MAAM;AACtE,YAAI,qBAAqB,MAAM;AAC7B;AAAA,QACF;AACA,gBAAQ,OAAO;AAAA,UACb,MAAM;AAAA,UACN,MAAM,EAAE,UAAU,KAAK,OAAO,KAAA;AAAA,UAC9B,WAAW;AAAA,UACX,IAAI,OAAO;AACT,kBAAM,aAAa,QAAQ;AAE3B,kBAAM,OAAO,iBAAiB;AAAA,cAC5B,CAAC,YAAY,WAAW,UAAU;AAChC,oBAAIA,QAAO;AACX,oBAAI,QAAQ,cAAc,SAAS,GAAG;AACpCA,0BAAO,WACJ,QAAA,EACA;AAAA,oBACC,cAAc,KAAK,EAAG,MAAM,CAAC;AAAA,oBAC7B,cAAc,QAAQ,CAAC,EAAG,MAAM,CAAC;AAAA,kBAAA;AAAA,gBAEvC;AACA,uBACE,aAAa,WAAW,QAAQ,UAAU,QAAQ,IAAIA;AAAAA,cAE1D;AAAA,cACA;AAAA,YAAA;AAEF,mBAAO,MAAM;AAAA,cACX,CAAC,cAAc,CAAC,EAAG,MAAM,CAAC,GAAG,cAAc,GAAG,EAAE,EAAG,MAAM,CAAC,CAAC;AAAA,cAC3D;AAAA,YAAA;AAAA,UAEJ;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH,CAAC;"}
{"version":3,"file":"create-route-property-order.rule.js","names":[],"sources":["../../../../src/rules/create-route-property-order/create-route-property-order.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { sortDataByOrder } from './create-route-property-order.utils'\nimport {\n createRouteFunctions,\n createRouteFunctionsIndirect,\n sortRules,\n} from './constants'\nimport type { CreateRouteFunction } from './constants'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst createRouteFunctionSet = new Set(createRouteFunctions)\nfunction isCreateRouteFunction(node: any): node is CreateRouteFunction {\n return createRouteFunctionSet.has(node)\n}\n\nexport const name = 'create-route-property-order'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Ensure correct order of inference sensitive properties for createRoute functions',\n recommended: 'error',\n },\n messages: {\n invalidOrder: 'Invalid order of properties for `{{function}}`.',\n },\n schema: [],\n hasSuggestions: true,\n fixable: 'code',\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context) => {\n return {\n CallExpression(node) {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) {\n return\n }\n const createRouteFunction = node.callee.name\n if (!isCreateRouteFunction(createRouteFunction)) {\n return\n }\n let args = node.arguments\n if (createRouteFunctionsIndirect.includes(createRouteFunction as any)) {\n if (node.parent.type === AST_NODE_TYPES.CallExpression) {\n args = node.parent.arguments\n } else {\n return\n }\n }\n\n const argument = args[0]\n if (argument === undefined || argument.type !== 'ObjectExpression') {\n return\n }\n\n const allProperties = argument.properties\n // no need to sort if there is at max 1 property\n if (allProperties.length < 2) {\n return\n }\n\n const properties = allProperties.flatMap((p) => {\n if (\n p.type === AST_NODE_TYPES.Property &&\n p.key.type === AST_NODE_TYPES.Identifier\n ) {\n return { name: p.key.name, property: p }\n } else if (p.type === AST_NODE_TYPES.SpreadElement) {\n if (p.argument.type === AST_NODE_TYPES.Identifier) {\n return { name: p.argument.name, property: p }\n } else {\n throw new Error('Unsupported spread element')\n }\n }\n return []\n })\n\n const sortedProperties = sortDataByOrder(properties, sortRules, 'name')\n if (sortedProperties === null) {\n return\n }\n context.report({\n node: argument,\n data: { function: node.callee.name },\n messageId: 'invalidOrder',\n fix(fixer) {\n const sourceCode = context.sourceCode\n\n const text = sortedProperties.reduce(\n (sourceText, specifier, index) => {\n let text = ''\n if (index < allProperties.length - 1) {\n text = sourceCode\n .getText()\n .slice(\n allProperties[index]!.range[1],\n allProperties[index + 1]!.range[0],\n )\n }\n return (\n sourceText + sourceCode.getText(specifier.property) + text\n )\n },\n '',\n )\n return fixer.replaceTextRange(\n [allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],\n text,\n )\n },\n })\n },\n }\n }),\n})\n"],"mappings":";;;;;;AAaA,IAAM,aAAa,YAAY,YAA2B,WAAW;AAErE,IAAM,yBAAyB,IAAI,IAAI,qBAAqB;AAC5D,SAAS,sBAAsB,MAAwC;AACrE,QAAO,uBAAuB,IAAI,KAAK;;AAGzC,IAAa,OAAO;AAEpB,IAAa,OAAO,WAAW;CAC7B;CACA,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aACE;GACF,aAAa;GACd;EACD,UAAU,EACR,cAAc,mDACf;EACD,QAAQ,EAAE;EACV,gBAAgB;EAChB,SAAS;EACV;CACD,gBAAgB,EAAE;CAElB,QAAQ,6BAA6B,YAAY;AAC/C,SAAO,EACL,eAAe,MAAM;AACnB,OAAI,KAAK,OAAO,SAAS,eAAe,WACtC;GAEF,MAAM,sBAAsB,KAAK,OAAO;AACxC,OAAI,CAAC,sBAAsB,oBAAoB,CAC7C;GAEF,IAAI,OAAO,KAAK;AAChB,OAAI,6BAA6B,SAAS,oBAA2B,CACnE,KAAI,KAAK,OAAO,SAAS,eAAe,eACtC,QAAO,KAAK,OAAO;OAEnB;GAIJ,MAAM,WAAW,KAAK;AACtB,OAAI,aAAa,KAAA,KAAa,SAAS,SAAS,mBAC9C;GAGF,MAAM,gBAAgB,SAAS;AAE/B,OAAI,cAAc,SAAS,EACzB;GAmBF,MAAM,mBAAmB,gBAhBN,cAAc,SAAS,MAAM;AAC9C,QACE,EAAE,SAAS,eAAe,YAC1B,EAAE,IAAI,SAAS,eAAe,WAE9B,QAAO;KAAE,MAAM,EAAE,IAAI;KAAM,UAAU;KAAG;aAC/B,EAAE,SAAS,eAAe,cACnC,KAAI,EAAE,SAAS,SAAS,eAAe,WACrC,QAAO;KAAE,MAAM,EAAE,SAAS;KAAM,UAAU;KAAG;QAE7C,OAAM,IAAI,MAAM,6BAA6B;AAGjD,WAAO,EAAE;KACT,EAEmD,WAAW,OAAO;AACvE,OAAI,qBAAqB,KACvB;AAEF,WAAQ,OAAO;IACb,MAAM;IACN,MAAM,EAAE,UAAU,KAAK,OAAO,MAAM;IACpC,WAAW;IACX,IAAI,OAAO;KACT,MAAM,aAAa,QAAQ;KAE3B,MAAM,OAAO,iBAAiB,QAC3B,YAAY,WAAW,UAAU;MAChC,IAAI,OAAO;AACX,UAAI,QAAQ,cAAc,SAAS,EACjC,QAAO,WACJ,SAAS,CACT,MACC,cAAc,OAAQ,MAAM,IAC5B,cAAc,QAAQ,GAAI,MAAM,GACjC;AAEL,aACE,aAAa,WAAW,QAAQ,UAAU,SAAS,GAAG;QAG1D,GACD;AACD,YAAO,MAAM,iBACX,CAAC,cAAc,GAAI,MAAM,IAAI,cAAc,GAAG,GAAG,CAAE,MAAM,GAAG,EAC5D,KACD;;IAEJ,CAAC;KAEL;GACD;CACH,CAAC"}

@@ -0,50 +1,38 @@

//#region src/rules/create-route-property-order/create-route-property-order.utils.ts
function sortDataByOrder(data, orderRules, key) {
const getSubsetIndex = (item, subsets) => {
for (let i = 0; i < subsets.length; i++) {
if (subsets[i]?.includes(item)) {
return i;
}
}
return null;
};
const orderSets = orderRules.reduce(
(sets, [A, B]) => [...sets, A, B],
[]
);
const inOrderArray = data.filter(
(item) => getSubsetIndex(item[key], orderSets) !== null
);
let wasResorted = false;
const sortedArray = inOrderArray.sort((a, b) => {
const aKey = a[key], bKey = b[key];
const aSubsetIndex = getSubsetIndex(aKey, orderSets);
const bSubsetIndex = getSubsetIndex(bKey, orderSets);
if (aSubsetIndex !== null && bSubsetIndex !== null && aSubsetIndex !== bSubsetIndex) {
return aSubsetIndex - bSubsetIndex;
}
return 0;
});
const inOrderIterator = sortedArray.values();
const result = data.map((item) => {
if (getSubsetIndex(item[key], orderSets) !== null) {
const sortedItem = inOrderIterator.next().value;
if (sortedItem[key] !== item[key]) {
wasResorted = true;
}
return sortedItem;
}
return item;
});
if (!wasResorted) {
return null;
}
return result;
const getSubsetIndex = (item, subsets) => {
for (let i = 0; i < subsets.length; i++) if (subsets[i]?.includes(item)) return i;
return null;
};
const orderSets = orderRules.reduce((sets, [A, B]) => [
...sets,
A,
B
], []);
const inOrderArray = data.filter((item) => getSubsetIndex(item[key], orderSets) !== null);
let wasResorted = false;
const inOrderIterator = inOrderArray.sort((a, b) => {
const aKey = a[key], bKey = b[key];
const aSubsetIndex = getSubsetIndex(aKey, orderSets);
const bSubsetIndex = getSubsetIndex(bKey, orderSets);
if (aSubsetIndex !== null && bSubsetIndex !== null && aSubsetIndex !== bSubsetIndex) return aSubsetIndex - bSubsetIndex;
return 0;
}).values();
const result = data.map((item) => {
if (getSubsetIndex(item[key], orderSets) !== null) {
const sortedItem = inOrderIterator.next().value;
if (sortedItem[key] !== item[key]) wasResorted = true;
return sortedItem;
}
return item;
});
if (!wasResorted) return null;
return result;
}
function getCheckedProperties(orderRules) {
return [...new Set(orderRules.flat(2))];
return [...new Set(orderRules.flat(2))];
}
export {
getCheckedProperties,
sortDataByOrder
};
//# sourceMappingURL=create-route-property-order.utils.js.map
//#endregion
export { getCheckedProperties, sortDataByOrder };
//# sourceMappingURL=create-route-property-order.utils.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-route-property-order.utils.js","sources":["../../../../src/rules/create-route-property-order/create-route-property-order.utils.ts"],"sourcesContent":["export function sortDataByOrder<T, TKey extends keyof T>(\n data: Array<T> | ReadonlyArray<T>,\n orderRules: ReadonlyArray<\n Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>\n >,\n key: TKey,\n): Array<T> | null {\n const getSubsetIndex = (\n item: T[TKey],\n subsets: ReadonlyArray<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n ): number | null => {\n for (let i = 0; i < subsets.length; i++) {\n if (subsets[i]?.includes(item)) {\n return i\n }\n }\n return null\n }\n\n const orderSets = orderRules.reduce(\n (sets, [A, B]) => [...sets, A, B],\n [] as Array<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n )\n\n const inOrderArray = data.filter(\n (item) => getSubsetIndex(item[key], orderSets) !== null,\n )\n\n let wasResorted = false as boolean\n\n // Sort by the relative order defined by the rules\n const sortedArray = inOrderArray.sort((a, b) => {\n const aKey = a[key],\n bKey = b[key]\n const aSubsetIndex = getSubsetIndex(aKey, orderSets)\n const bSubsetIndex = getSubsetIndex(bKey, orderSets)\n\n // If both items belong to different subsets, sort by their subset order\n if (\n aSubsetIndex !== null &&\n bSubsetIndex !== null &&\n aSubsetIndex !== bSubsetIndex\n ) {\n return aSubsetIndex - bSubsetIndex\n }\n\n // If both items belong to the same subset or neither is in the subset, keep their relative order\n return 0\n })\n\n const inOrderIterator = sortedArray.values()\n const result = data.map((item) => {\n if (getSubsetIndex(item[key], orderSets) !== null) {\n const sortedItem = inOrderIterator.next().value!\n if (sortedItem[key] !== item[key]) {\n wasResorted = true\n }\n return sortedItem\n }\n return item\n })\n\n if (!wasResorted) {\n return null\n }\n return result\n}\n\nexport function getCheckedProperties<T>(\n orderRules: ReadonlyArray<ReadonlyArray<ReadonlyArray<T>>>,\n): ReadonlyArray<T> {\n return [...new Set<T>(orderRules.flat(2))]\n}\n"],"names":[],"mappings":"AAAO,SAAS,gBACd,MACA,YAGA,KACiB;AACjB,QAAM,iBAAiB,CACrB,MACA,YACkB;AAClB,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAI,QAAQ,CAAC,GAAG,SAAS,IAAI,GAAG;AAC9B,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,WAAW;AAAA,IAC3B,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC;AAAA,IAChC,CAAA;AAAA,EAAC;AAGH,QAAM,eAAe,KAAK;AAAA,IACxB,CAAC,SAAS,eAAe,KAAK,GAAG,GAAG,SAAS,MAAM;AAAA,EAAA;AAGrD,MAAI,cAAc;AAGlB,QAAM,cAAc,aAAa,KAAK,CAAC,GAAG,MAAM;AAC9C,UAAM,OAAO,EAAE,GAAG,GAChB,OAAO,EAAE,GAAG;AACd,UAAM,eAAe,eAAe,MAAM,SAAS;AACnD,UAAM,eAAe,eAAe,MAAM,SAAS;AAGnD,QACE,iBAAiB,QACjB,iBAAiB,QACjB,iBAAiB,cACjB;AACA,aAAO,eAAe;AAAA,IACxB;AAGA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,kBAAkB,YAAY,OAAA;AACpC,QAAM,SAAS,KAAK,IAAI,CAAC,SAAS;AAChC,QAAI,eAAe,KAAK,GAAG,GAAG,SAAS,MAAM,MAAM;AACjD,YAAM,aAAa,gBAAgB,KAAA,EAAO;AAC1C,UAAI,WAAW,GAAG,MAAM,KAAK,GAAG,GAAG;AACjC,sBAAc;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,qBACd,YACkB;AAClB,SAAO,CAAC,GAAG,IAAI,IAAO,WAAW,KAAK,CAAC,CAAC,CAAC;AAC3C;"}
{"version":3,"file":"create-route-property-order.utils.js","names":[],"sources":["../../../../src/rules/create-route-property-order/create-route-property-order.utils.ts"],"sourcesContent":["export function sortDataByOrder<T, TKey extends keyof T>(\n data: Array<T> | ReadonlyArray<T>,\n orderRules: ReadonlyArray<\n Readonly<[ReadonlyArray<T[TKey]>, ReadonlyArray<T[TKey]>]>\n >,\n key: TKey,\n): Array<T> | null {\n const getSubsetIndex = (\n item: T[TKey],\n subsets: ReadonlyArray<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n ): number | null => {\n for (let i = 0; i < subsets.length; i++) {\n if (subsets[i]?.includes(item)) {\n return i\n }\n }\n return null\n }\n\n const orderSets = orderRules.reduce(\n (sets, [A, B]) => [...sets, A, B],\n [] as Array<ReadonlyArray<T[TKey]> | Array<T[TKey]>>,\n )\n\n const inOrderArray = data.filter(\n (item) => getSubsetIndex(item[key], orderSets) !== null,\n )\n\n let wasResorted = false as boolean\n\n // Sort by the relative order defined by the rules\n const sortedArray = inOrderArray.sort((a, b) => {\n const aKey = a[key],\n bKey = b[key]\n const aSubsetIndex = getSubsetIndex(aKey, orderSets)\n const bSubsetIndex = getSubsetIndex(bKey, orderSets)\n\n // If both items belong to different subsets, sort by their subset order\n if (\n aSubsetIndex !== null &&\n bSubsetIndex !== null &&\n aSubsetIndex !== bSubsetIndex\n ) {\n return aSubsetIndex - bSubsetIndex\n }\n\n // If both items belong to the same subset or neither is in the subset, keep their relative order\n return 0\n })\n\n const inOrderIterator = sortedArray.values()\n const result = data.map((item) => {\n if (getSubsetIndex(item[key], orderSets) !== null) {\n const sortedItem = inOrderIterator.next().value!\n if (sortedItem[key] !== item[key]) {\n wasResorted = true\n }\n return sortedItem\n }\n return item\n })\n\n if (!wasResorted) {\n return null\n }\n return result\n}\n\nexport function getCheckedProperties<T>(\n orderRules: ReadonlyArray<ReadonlyArray<ReadonlyArray<T>>>,\n): ReadonlyArray<T> {\n return [...new Set<T>(orderRules.flat(2))]\n}\n"],"mappings":";AAAA,SAAgB,gBACd,MACA,YAGA,KACiB;CACjB,MAAM,kBACJ,MACA,YACkB;AAClB,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAClC,KAAI,QAAQ,IAAI,SAAS,KAAK,CAC5B,QAAO;AAGX,SAAO;;CAGT,MAAM,YAAY,WAAW,QAC1B,MAAM,CAAC,GAAG,OAAO;EAAC,GAAG;EAAM;EAAG;EAAE,EACjC,EAAE,CACH;CAED,MAAM,eAAe,KAAK,QACvB,SAAS,eAAe,KAAK,MAAM,UAAU,KAAK,KACpD;CAED,IAAI,cAAc;CAsBlB,MAAM,kBAnBc,aAAa,MAAM,GAAG,MAAM;EAC9C,MAAM,OAAO,EAAE,MACb,OAAO,EAAE;EACX,MAAM,eAAe,eAAe,MAAM,UAAU;EACpD,MAAM,eAAe,eAAe,MAAM,UAAU;AAGpD,MACE,iBAAiB,QACjB,iBAAiB,QACjB,iBAAiB,aAEjB,QAAO,eAAe;AAIxB,SAAO;GACP,CAEkC,QAAQ;CAC5C,MAAM,SAAS,KAAK,KAAK,SAAS;AAChC,MAAI,eAAe,KAAK,MAAM,UAAU,KAAK,MAAM;GACjD,MAAM,aAAa,gBAAgB,MAAM,CAAC;AAC1C,OAAI,WAAW,SAAS,KAAK,KAC3B,eAAc;AAEhB,UAAO;;AAET,SAAO;GACP;AAEF,KAAI,CAAC,YACH,QAAO;AAET,QAAO;;AAGT,SAAgB,qBACd,YACkB;AAClB,QAAO,CAAC,GAAG,IAAI,IAAO,WAAW,KAAK,EAAE,CAAC,CAAC"}

@@ -1,13 +0,26 @@

const pathAsFirstArgFunctions = [
"createFileRoute",
"createLazyFileRoute",
"createLazyRoute"
//#region src/rules/route-param-names/constants.ts
/**
* Functions where the path is passed as the first argument (string literal)
* e.g., createFileRoute('/path/$param')(...)
*/
var pathAsFirstArgFunctions = [
"createFileRoute",
"createLazyFileRoute",
"createLazyRoute"
];
const pathAsPropertyFunctions = ["createRoute"];
const VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
export {
VALID_PARAM_NAME_REGEX,
pathAsFirstArgFunctions,
pathAsPropertyFunctions
};
//# sourceMappingURL=constants.js.map
/**
* Functions where the path is a property in the options object
* e.g., createRoute({ path: '/path/$param' })
*/
var pathAsPropertyFunctions = ["createRoute"];
[...pathAsFirstArgFunctions, ...pathAsPropertyFunctions];
/**
* Regex for valid JavaScript identifier (param name)
* Must start with letter, underscore, or dollar sign
* Can contain letters, numbers, underscores, or dollar signs
*/
var VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
//#endregion
export { VALID_PARAM_NAME_REGEX, pathAsFirstArgFunctions, pathAsPropertyFunctions };
//# sourceMappingURL=constants.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"constants.js","sources":["../../../../src/rules/route-param-names/constants.ts"],"sourcesContent":["/**\n * Functions where the path is passed as the first argument (string literal)\n * e.g., createFileRoute('/path/$param')(...)\n */\nexport const pathAsFirstArgFunctions = [\n 'createFileRoute',\n 'createLazyFileRoute',\n 'createLazyRoute',\n] as const\n\nexport type PathAsFirstArgFunction = (typeof pathAsFirstArgFunctions)[number]\n\n/**\n * Functions where the path is a property in the options object\n * e.g., createRoute({ path: '/path/$param' })\n */\nexport const pathAsPropertyFunctions = ['createRoute'] as const\n\nexport type PathAsPropertyFunction = (typeof pathAsPropertyFunctions)[number]\n\n/**\n * All route functions that need param name validation\n */\nexport const allRouteFunctions = [\n ...pathAsFirstArgFunctions,\n ...pathAsPropertyFunctions,\n] as const\n\nexport type RouteFunction = (typeof allRouteFunctions)[number]\n\n/**\n * Regex for valid JavaScript identifier (param name)\n * Must start with letter, underscore, or dollar sign\n * Can contain letters, numbers, underscores, or dollar signs\n */\nexport const VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/\n"],"names":[],"mappings":"AAIO,MAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF;AAQO,MAAM,0BAA0B,CAAC,aAAa;AAmB9C,MAAM,yBAAyB;"}
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/rules/route-param-names/constants.ts"],"sourcesContent":["/**\n * Functions where the path is passed as the first argument (string literal)\n * e.g., createFileRoute('/path/$param')(...)\n */\nexport const pathAsFirstArgFunctions = [\n 'createFileRoute',\n 'createLazyFileRoute',\n 'createLazyRoute',\n] as const\n\nexport type PathAsFirstArgFunction = (typeof pathAsFirstArgFunctions)[number]\n\n/**\n * Functions where the path is a property in the options object\n * e.g., createRoute({ path: '/path/$param' })\n */\nexport const pathAsPropertyFunctions = ['createRoute'] as const\n\nexport type PathAsPropertyFunction = (typeof pathAsPropertyFunctions)[number]\n\n/**\n * All route functions that need param name validation\n */\nexport const allRouteFunctions = [\n ...pathAsFirstArgFunctions,\n ...pathAsPropertyFunctions,\n] as const\n\nexport type RouteFunction = (typeof allRouteFunctions)[number]\n\n/**\n * Regex for valid JavaScript identifier (param name)\n * Must start with letter, underscore, or dollar sign\n * Can contain letters, numbers, underscores, or dollar signs\n */\nexport const VALID_PARAM_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/\n"],"mappings":";;;;;AAIA,IAAa,0BAA0B;CACrC;CACA;CACA;CACD;;;;;AAQD,IAAa,0BAA0B,CAAC,cAAc;AAOrB,CAC/B,GAAG,yBACH,GAAG,wBACJ;;;;;;AASD,IAAa,yBAAyB"}

@@ -1,98 +0,77 @@

import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
import { getDocsUrl } from "../../utils/get-docs-url.js";
import { detectTanstackRouterImports } from "../../utils/detect-router-imports.js";
import { pathAsFirstArgFunctions, pathAsPropertyFunctions } from "./constants.js";
import { getInvalidParams } from "./route-param-names.utils.js";
import { pathAsFirstArgFunctions, pathAsPropertyFunctions } from "./constants.js";
const createRule = ESLintUtils.RuleCreator(getDocsUrl);
const pathAsFirstArgSet = new Set(pathAsFirstArgFunctions);
const pathAsPropertySet = new Set(pathAsPropertyFunctions);
const name = "route-param-names";
const rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure route param names are valid JavaScript identifiers",
recommended: "error"
},
messages: {
invalidParamName: 'Invalid param name "{{paramName}}" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/).'
},
schema: []
},
defaultOptions: [],
create: detectTanstackRouterImports((context, _, helpers) => {
function reportInvalidParams(node, path) {
const invalidParams = getInvalidParams(path);
for (const param of invalidParams) {
context.report({
node,
messageId: "invalidParamName",
data: { paramName: param.paramName }
});
}
}
function getStringLiteralValue(node) {
if (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") {
return node.value;
}
if (node.type === AST_NODE_TYPES.TemplateLiteral && node.quasis.length === 1) {
const cooked = node.quasis[0]?.value.cooked;
if (cooked != null) {
return cooked;
}
}
return null;
}
return {
CallExpression(node) {
if (node.callee.type === AST_NODE_TYPES.Identifier) {
const funcName = node.callee.name;
if (!helpers.isTanstackRouterImport(node.callee)) {
return;
}
if (pathAsPropertySet.has(funcName)) {
const arg = node.arguments[0];
if (arg?.type === AST_NODE_TYPES.ObjectExpression) {
for (const prop of arg.properties) {
if (prop.type === AST_NODE_TYPES.Property) {
const isPathKey = prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === "path" || prop.key.type === AST_NODE_TYPES.Literal && prop.key.value === "path";
if (isPathKey) {
const pathValue = getStringLiteralValue(prop.value);
if (pathValue) {
reportInvalidParams(prop.value, pathValue);
}
}
}
}
}
return;
}
}
if (node.callee.type === AST_NODE_TYPES.CallExpression) {
const innerCall = node.callee;
if (innerCall.callee.type === AST_NODE_TYPES.Identifier) {
const funcName = innerCall.callee.name;
if (!helpers.isTanstackRouterImport(innerCall.callee)) {
return;
}
if (pathAsFirstArgSet.has(funcName)) {
const pathArg = innerCall.arguments[0];
if (pathArg) {
const pathValue = getStringLiteralValue(pathArg);
if (pathValue) {
reportInvalidParams(pathArg, pathValue);
}
}
}
}
}
}
};
})
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
//#region src/rules/route-param-names/route-param-names.rule.ts
var createRule = ESLintUtils.RuleCreator(getDocsUrl);
var pathAsFirstArgSet = new Set(pathAsFirstArgFunctions);
var pathAsPropertySet = new Set(pathAsPropertyFunctions);
var name = "route-param-names";
var rule = createRule({
name,
meta: {
type: "problem",
docs: {
description: "Ensure route param names are valid JavaScript identifiers",
recommended: "error"
},
messages: { invalidParamName: "Invalid param name \"{{paramName}}\" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/)." },
schema: []
},
defaultOptions: [],
create: detectTanstackRouterImports((context, _, helpers) => {
function reportInvalidParams(node, path) {
const invalidParams = getInvalidParams(path);
for (const param of invalidParams) context.report({
node,
messageId: "invalidParamName",
data: { paramName: param.paramName }
});
}
function getStringLiteralValue(node) {
if (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") return node.value;
if (node.type === AST_NODE_TYPES.TemplateLiteral && node.quasis.length === 1) {
const cooked = node.quasis[0]?.value.cooked;
if (cooked != null) return cooked;
}
return null;
}
return { CallExpression(node) {
if (node.callee.type === AST_NODE_TYPES.Identifier) {
const funcName = node.callee.name;
if (!helpers.isTanstackRouterImport(node.callee)) return;
if (pathAsPropertySet.has(funcName)) {
const arg = node.arguments[0];
if (arg?.type === AST_NODE_TYPES.ObjectExpression) {
for (const prop of arg.properties) if (prop.type === AST_NODE_TYPES.Property) {
if (prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === "path" || prop.key.type === AST_NODE_TYPES.Literal && prop.key.value === "path") {
const pathValue = getStringLiteralValue(prop.value);
if (pathValue) reportInvalidParams(prop.value, pathValue);
}
}
}
return;
}
}
if (node.callee.type === AST_NODE_TYPES.CallExpression) {
const innerCall = node.callee;
if (innerCall.callee.type === AST_NODE_TYPES.Identifier) {
const funcName = innerCall.callee.name;
if (!helpers.isTanstackRouterImport(innerCall.callee)) return;
if (pathAsFirstArgSet.has(funcName)) {
const pathArg = innerCall.arguments[0];
if (pathArg) {
const pathValue = getStringLiteralValue(pathArg);
if (pathValue) reportInvalidParams(pathArg, pathValue);
}
}
}
}
} };
})
});
export {
name,
rule
};
//# sourceMappingURL=route-param-names.rule.js.map
//#endregion
export { name, rule };
//# sourceMappingURL=route-param-names.rule.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"route-param-names.rule.js","sources":["../../../../src/rules/route-param-names/route-param-names.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { getInvalidParams } from './route-param-names.utils'\nimport { pathAsFirstArgFunctions, pathAsPropertyFunctions } from './constants'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst pathAsFirstArgSet = new Set<string>(pathAsFirstArgFunctions)\nconst pathAsPropertySet = new Set<string>(pathAsPropertyFunctions)\n\nexport const name = 'route-param-names'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Ensure route param names are valid JavaScript identifiers',\n recommended: 'error',\n },\n messages: {\n invalidParamName:\n 'Invalid param name \"{{paramName}}\" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/).',\n },\n schema: [],\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context, _, helpers) => {\n function reportInvalidParams(node: TSESTree.Node, path: string) {\n const invalidParams = getInvalidParams(path)\n\n for (const param of invalidParams) {\n context.report({\n node,\n messageId: 'invalidParamName',\n data: { paramName: param.paramName },\n })\n }\n }\n\n function getStringLiteralValue(node: TSESTree.Node): string | null {\n if (\n node.type === AST_NODE_TYPES.Literal &&\n typeof node.value === 'string'\n ) {\n return node.value\n }\n if (\n node.type === AST_NODE_TYPES.TemplateLiteral &&\n node.quasis.length === 1\n ) {\n const cooked = node.quasis[0]?.value.cooked\n if (cooked != null) {\n return cooked\n }\n }\n return null\n }\n\n return {\n CallExpression(node) {\n // Handle direct function call: createRoute({ path: '...' })\n if (node.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = node.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(node.callee)) {\n return\n }\n\n // Case: createRoute({ path: '/path/$param' }) or createRoute({ 'path': '/path/$param' })\n if (pathAsPropertySet.has(funcName)) {\n const arg = node.arguments[0]\n if (arg?.type === AST_NODE_TYPES.ObjectExpression) {\n for (const prop of arg.properties) {\n if (prop.type === AST_NODE_TYPES.Property) {\n const isPathKey =\n (prop.key.type === AST_NODE_TYPES.Identifier &&\n prop.key.name === 'path') ||\n (prop.key.type === AST_NODE_TYPES.Literal &&\n prop.key.value === 'path')\n if (isPathKey) {\n const pathValue = getStringLiteralValue(prop.value)\n if (pathValue) {\n reportInvalidParams(prop.value, pathValue)\n }\n }\n }\n }\n }\n return\n }\n }\n\n // Handle curried function call: createFileRoute('/path')({ ... })\n if (node.callee.type === AST_NODE_TYPES.CallExpression) {\n const innerCall = node.callee\n\n if (innerCall.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = innerCall.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(innerCall.callee)) {\n return\n }\n\n // Case: createFileRoute('/path/$param')(...) or similar\n if (pathAsFirstArgSet.has(funcName)) {\n const pathArg = innerCall.arguments[0]\n if (pathArg) {\n const pathValue = getStringLiteralValue(pathArg)\n if (pathValue) {\n reportInvalidParams(pathArg, pathValue)\n }\n }\n }\n }\n }\n },\n }\n }),\n})\n"],"names":[],"mappings":";;;;;AASA,MAAM,aAAa,YAAY,YAA2B,UAAU;AAEpE,MAAM,oBAAoB,IAAI,IAAY,uBAAuB;AACjE,MAAM,oBAAoB,IAAI,IAAY,uBAAuB;AAE1D,MAAM,OAAO;AAEb,MAAM,OAAO,WAAW;AAAA,EAC7B;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf,UAAU;AAAA,MACR,kBACE;AAAA,IAAA;AAAA,IAEJ,QAAQ,CAAA;AAAA,EAAC;AAAA,EAEX,gBAAgB,CAAA;AAAA,EAEhB,QAAQ,4BAA4B,CAAC,SAAS,GAAG,YAAY;AAC3D,aAAS,oBAAoB,MAAqB,MAAc;AAC9D,YAAM,gBAAgB,iBAAiB,IAAI;AAE3C,iBAAW,SAAS,eAAe;AACjC,gBAAQ,OAAO;AAAA,UACb;AAAA,UACA,WAAW;AAAA,UACX,MAAM,EAAE,WAAW,MAAM,UAAA;AAAA,QAAU,CACpC;AAAA,MACH;AAAA,IACF;AAEA,aAAS,sBAAsB,MAAoC;AACjE,UACE,KAAK,SAAS,eAAe,WAC7B,OAAO,KAAK,UAAU,UACtB;AACA,eAAO,KAAK;AAAA,MACd;AACA,UACE,KAAK,SAAS,eAAe,mBAC7B,KAAK,OAAO,WAAW,GACvB;AACA,cAAM,SAAS,KAAK,OAAO,CAAC,GAAG,MAAM;AACrC,YAAI,UAAU,MAAM;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,eAAe,MAAM;AAEnB,YAAI,KAAK,OAAO,SAAS,eAAe,YAAY;AAClD,gBAAM,WAAW,KAAK,OAAO;AAG7B,cAAI,CAAC,QAAQ,uBAAuB,KAAK,MAAM,GAAG;AAChD;AAAA,UACF;AAGA,cAAI,kBAAkB,IAAI,QAAQ,GAAG;AACnC,kBAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,gBAAI,KAAK,SAAS,eAAe,kBAAkB;AACjD,yBAAW,QAAQ,IAAI,YAAY;AACjC,oBAAI,KAAK,SAAS,eAAe,UAAU;AACzC,wBAAM,YACH,KAAK,IAAI,SAAS,eAAe,cAChC,KAAK,IAAI,SAAS,UACnB,KAAK,IAAI,SAAS,eAAe,WAChC,KAAK,IAAI,UAAU;AACvB,sBAAI,WAAW;AACb,0BAAM,YAAY,sBAAsB,KAAK,KAAK;AAClD,wBAAI,WAAW;AACb,0CAAoB,KAAK,OAAO,SAAS;AAAA,oBAC3C;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AACA;AAAA,UACF;AAAA,QACF;AAGA,YAAI,KAAK,OAAO,SAAS,eAAe,gBAAgB;AACtD,gBAAM,YAAY,KAAK;AAEvB,cAAI,UAAU,OAAO,SAAS,eAAe,YAAY;AACvD,kBAAM,WAAW,UAAU,OAAO;AAGlC,gBAAI,CAAC,QAAQ,uBAAuB,UAAU,MAAM,GAAG;AACrD;AAAA,YACF;AAGA,gBAAI,kBAAkB,IAAI,QAAQ,GAAG;AACnC,oBAAM,UAAU,UAAU,UAAU,CAAC;AACrC,kBAAI,SAAS;AACX,sBAAM,YAAY,sBAAsB,OAAO;AAC/C,oBAAI,WAAW;AACb,sCAAoB,SAAS,SAAS;AAAA,gBACxC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH,CAAC;"}
{"version":3,"file":"route-param-names.rule.js","names":[],"sources":["../../../../src/rules/route-param-names/route-param-names.rule.ts"],"sourcesContent":["import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'\n\nimport { getDocsUrl } from '../../utils/get-docs-url'\nimport { detectTanstackRouterImports } from '../../utils/detect-router-imports'\nimport { getInvalidParams } from './route-param-names.utils'\nimport { pathAsFirstArgFunctions, pathAsPropertyFunctions } from './constants'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { ExtraRuleDocs } from '../../types'\n\nconst createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)\n\nconst pathAsFirstArgSet = new Set<string>(pathAsFirstArgFunctions)\nconst pathAsPropertySet = new Set<string>(pathAsPropertyFunctions)\n\nexport const name = 'route-param-names'\n\nexport const rule = createRule({\n name,\n meta: {\n type: 'problem',\n docs: {\n description: 'Ensure route param names are valid JavaScript identifiers',\n recommended: 'error',\n },\n messages: {\n invalidParamName:\n 'Invalid param name \"{{paramName}}\" in route path. Param names must be valid JavaScript identifiers (match /[a-zA-Z_$][a-zA-Z0-9_$]*/).',\n },\n schema: [],\n },\n defaultOptions: [],\n\n create: detectTanstackRouterImports((context, _, helpers) => {\n function reportInvalidParams(node: TSESTree.Node, path: string) {\n const invalidParams = getInvalidParams(path)\n\n for (const param of invalidParams) {\n context.report({\n node,\n messageId: 'invalidParamName',\n data: { paramName: param.paramName },\n })\n }\n }\n\n function getStringLiteralValue(node: TSESTree.Node): string | null {\n if (\n node.type === AST_NODE_TYPES.Literal &&\n typeof node.value === 'string'\n ) {\n return node.value\n }\n if (\n node.type === AST_NODE_TYPES.TemplateLiteral &&\n node.quasis.length === 1\n ) {\n const cooked = node.quasis[0]?.value.cooked\n if (cooked != null) {\n return cooked\n }\n }\n return null\n }\n\n return {\n CallExpression(node) {\n // Handle direct function call: createRoute({ path: '...' })\n if (node.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = node.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(node.callee)) {\n return\n }\n\n // Case: createRoute({ path: '/path/$param' }) or createRoute({ 'path': '/path/$param' })\n if (pathAsPropertySet.has(funcName)) {\n const arg = node.arguments[0]\n if (arg?.type === AST_NODE_TYPES.ObjectExpression) {\n for (const prop of arg.properties) {\n if (prop.type === AST_NODE_TYPES.Property) {\n const isPathKey =\n (prop.key.type === AST_NODE_TYPES.Identifier &&\n prop.key.name === 'path') ||\n (prop.key.type === AST_NODE_TYPES.Literal &&\n prop.key.value === 'path')\n if (isPathKey) {\n const pathValue = getStringLiteralValue(prop.value)\n if (pathValue) {\n reportInvalidParams(prop.value, pathValue)\n }\n }\n }\n }\n }\n return\n }\n }\n\n // Handle curried function call: createFileRoute('/path')({ ... })\n if (node.callee.type === AST_NODE_TYPES.CallExpression) {\n const innerCall = node.callee\n\n if (innerCall.callee.type === AST_NODE_TYPES.Identifier) {\n const funcName = innerCall.callee.name\n\n // Skip if not imported from TanStack Router\n if (!helpers.isTanstackRouterImport(innerCall.callee)) {\n return\n }\n\n // Case: createFileRoute('/path/$param')(...) or similar\n if (pathAsFirstArgSet.has(funcName)) {\n const pathArg = innerCall.arguments[0]\n if (pathArg) {\n const pathValue = getStringLiteralValue(pathArg)\n if (pathValue) {\n reportInvalidParams(pathArg, pathValue)\n }\n }\n }\n }\n }\n },\n }\n }),\n})\n"],"mappings":";;;;;;AASA,IAAM,aAAa,YAAY,YAA2B,WAAW;AAErE,IAAM,oBAAoB,IAAI,IAAY,wBAAwB;AAClE,IAAM,oBAAoB,IAAI,IAAY,wBAAwB;AAElE,IAAa,OAAO;AAEpB,IAAa,OAAO,WAAW;CAC7B;CACA,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,UAAU,EACR,kBACE,4IACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAElB,QAAQ,6BAA6B,SAAS,GAAG,YAAY;EAC3D,SAAS,oBAAoB,MAAqB,MAAc;GAC9D,MAAM,gBAAgB,iBAAiB,KAAK;AAE5C,QAAK,MAAM,SAAS,cAClB,SAAQ,OAAO;IACb;IACA,WAAW;IACX,MAAM,EAAE,WAAW,MAAM,WAAW;IACrC,CAAC;;EAIN,SAAS,sBAAsB,MAAoC;AACjE,OACE,KAAK,SAAS,eAAe,WAC7B,OAAO,KAAK,UAAU,SAEtB,QAAO,KAAK;AAEd,OACE,KAAK,SAAS,eAAe,mBAC7B,KAAK,OAAO,WAAW,GACvB;IACA,MAAM,SAAS,KAAK,OAAO,IAAI,MAAM;AACrC,QAAI,UAAU,KACZ,QAAO;;AAGX,UAAO;;AAGT,SAAO,EACL,eAAe,MAAM;AAEnB,OAAI,KAAK,OAAO,SAAS,eAAe,YAAY;IAClD,MAAM,WAAW,KAAK,OAAO;AAG7B,QAAI,CAAC,QAAQ,uBAAuB,KAAK,OAAO,CAC9C;AAIF,QAAI,kBAAkB,IAAI,SAAS,EAAE;KACnC,MAAM,MAAM,KAAK,UAAU;AAC3B,SAAI,KAAK,SAAS,eAAe;WAC1B,MAAM,QAAQ,IAAI,WACrB,KAAI,KAAK,SAAS,eAAe;WAE5B,KAAK,IAAI,SAAS,eAAe,cAChC,KAAK,IAAI,SAAS,UACnB,KAAK,IAAI,SAAS,eAAe,WAChC,KAAK,IAAI,UAAU,QACR;QACb,MAAM,YAAY,sBAAsB,KAAK,MAAM;AACnD,YAAI,UACF,qBAAoB,KAAK,OAAO,UAAU;;;;AAMpD;;;AAKJ,OAAI,KAAK,OAAO,SAAS,eAAe,gBAAgB;IACtD,MAAM,YAAY,KAAK;AAEvB,QAAI,UAAU,OAAO,SAAS,eAAe,YAAY;KACvD,MAAM,WAAW,UAAU,OAAO;AAGlC,SAAI,CAAC,QAAQ,uBAAuB,UAAU,OAAO,CACnD;AAIF,SAAI,kBAAkB,IAAI,SAAS,EAAE;MACnC,MAAM,UAAU,UAAU,UAAU;AACpC,UAAI,SAAS;OACX,MAAM,YAAY,sBAAsB,QAAQ;AAChD,WAAI,UACF,qBAAoB,SAAS,UAAU;;;;;KAOpD;GACD;CACH,CAAC"}
import { VALID_PARAM_NAME_REGEX } from "./constants.js";
//#region src/rules/route-param-names/route-param-names.utils.ts
/**
* Extracts param names from a route path segment.
*
* Handles these patterns:
* - $paramName -> extract "paramName"
* - {$paramName} -> extract "paramName"
* - prefix{$paramName}suffix -> extract "paramName"
* - {-$paramName} -> extract "paramName" (optional)
* - prefix{-$paramName}suffix -> extract "paramName" (optional)
* - $ or {$} -> wildcard, skip validation
*/
function extractParamsFromSegment(segment) {
const params = [];
if (!segment || !segment.includes("$")) {
return params;
}
if (segment === "$" || segment === "{$}") {
return params;
}
if (segment.startsWith("$") && !segment.includes("{")) {
const paramName = segment.slice(1);
if (paramName) {
params.push({
fullParam: segment,
paramName,
isOptional: false,
isValid: VALID_PARAM_NAME_REGEX.test(paramName)
});
}
return params;
}
const bracePattern = /\{(-?\$)([^}]*)\}/g;
let match;
while ((match = bracePattern.exec(segment)) !== null) {
const prefix = match[1];
const paramName = match[2];
if (!paramName) {
continue;
}
const isOptional = prefix === "-$";
params.push({
fullParam: `${prefix}${paramName}`,
paramName,
isOptional,
isValid: VALID_PARAM_NAME_REGEX.test(paramName)
});
}
return params;
const params = [];
if (!segment || !segment.includes("$")) return params;
if (segment === "$" || segment === "{$}") return params;
if (segment.startsWith("$") && !segment.includes("{")) {
const paramName = segment.slice(1);
if (paramName) params.push({
fullParam: segment,
paramName,
isOptional: false,
isValid: VALID_PARAM_NAME_REGEX.test(paramName)
});
return params;
}
const bracePattern = /\{(-?\$)([^}]*)\}/g;
let match;
while ((match = bracePattern.exec(segment)) !== null) {
const prefix = match[1];
const paramName = match[2];
if (!paramName) continue;
const isOptional = prefix === "-$";
params.push({
fullParam: `${prefix}${paramName}`,
paramName,
isOptional,
isValid: VALID_PARAM_NAME_REGEX.test(paramName)
});
}
return params;
}
/**
* Extracts all params from a route path.
*
* @param path - The route path (e.g., "/users/$userId/posts/$postId")
* @returns Array of extracted params with validation info
*/
function extractParamsFromPath(path) {
if (!path || !path.includes("$")) {
return [];
}
const segments = path.split("/");
const allParams = [];
for (const segment of segments) {
const params = extractParamsFromSegment(segment);
allParams.push(...params);
}
return allParams;
if (!path || !path.includes("$")) return [];
const segments = path.split("/");
const allParams = [];
for (const segment of segments) {
const params = extractParamsFromSegment(segment);
allParams.push(...params);
}
return allParams;
}
/**
* Gets all invalid params from a route path.
*
* @param path - The route path
* @returns Array of invalid param info
*/
function getInvalidParams(path) {
const params = extractParamsFromPath(path);
return params.filter((p) => !p.isValid);
return extractParamsFromPath(path).filter((p) => !p.isValid);
}
export {
extractParamsFromPath,
extractParamsFromSegment,
getInvalidParams
};
//# sourceMappingURL=route-param-names.utils.js.map
//#endregion
export { getInvalidParams };
//# sourceMappingURL=route-param-names.utils.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"route-param-names.utils.js","sources":["../../../../src/rules/route-param-names/route-param-names.utils.ts"],"sourcesContent":["import { VALID_PARAM_NAME_REGEX } from './constants'\n\nexport interface ExtractedParam {\n /** The full param string including $ prefix (e.g., \"$userId\", \"-$optional\") */\n fullParam: string\n /** The param name without $ prefix (e.g., \"userId\", \"optional\") */\n paramName: string\n /** Whether this is an optional param (prefixed with -$) */\n isOptional: boolean\n /** Whether this param name is valid */\n isValid: boolean\n}\n\n/**\n * Extracts param names from a route path segment.\n *\n * Handles these patterns:\n * - $paramName -> extract \"paramName\"\n * - {$paramName} -> extract \"paramName\"\n * - prefix{$paramName}suffix -> extract \"paramName\"\n * - {-$paramName} -> extract \"paramName\" (optional)\n * - prefix{-$paramName}suffix -> extract \"paramName\" (optional)\n * - $ or {$} -> wildcard, skip validation\n */\nexport function extractParamsFromSegment(\n segment: string,\n): Array<ExtractedParam> {\n const params: Array<ExtractedParam> = []\n\n // Skip empty segments\n if (!segment || !segment.includes('$')) {\n return params\n }\n\n // Check for wildcard ($ alone or {$})\n if (segment === '$' || segment === '{$}') {\n return params // Wildcard, no param name to validate\n }\n\n // Pattern 1: Simple $paramName (entire segment starts with $)\n if (segment.startsWith('$') && !segment.includes('{')) {\n const paramName = segment.slice(1)\n if (paramName) {\n params.push({\n fullParam: segment,\n paramName,\n isOptional: false,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n return params\n }\n\n // Pattern 2: Braces pattern {$paramName} or {-$paramName} with optional prefix/suffix\n // Match patterns like: prefix{$param}suffix, {$param}, {-$param}\n const bracePattern = /\\{(-?\\$)([^}]*)\\}/g\n let match\n\n while ((match = bracePattern.exec(segment)) !== null) {\n const prefix = match[1] // \"$\" or \"-$\"\n const paramName = match[2] // The param name after $ or -$\n\n if (!paramName) {\n // This is a wildcard {$} or {-$}, skip\n continue\n }\n\n const isOptional = prefix === '-$'\n\n params.push({\n fullParam: `${prefix}${paramName}`,\n paramName,\n isOptional,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n\n return params\n}\n\n/**\n * Extracts all params from a route path.\n *\n * @param path - The route path (e.g., \"/users/$userId/posts/$postId\")\n * @returns Array of extracted params with validation info\n */\nexport function extractParamsFromPath(path: string): Array<ExtractedParam> {\n if (!path || !path.includes('$')) {\n return []\n }\n\n const segments = path.split('/')\n const allParams: Array<ExtractedParam> = []\n\n for (const segment of segments) {\n const params = extractParamsFromSegment(segment)\n allParams.push(...params)\n }\n\n return allParams\n}\n\n/**\n * Validates a single param name.\n *\n * @param paramName - The param name to validate (without $ prefix)\n * @returns Whether the param name is valid\n */\nexport function isValidParamName(paramName: string): boolean {\n return VALID_PARAM_NAME_REGEX.test(paramName)\n}\n\n/**\n * Gets all invalid params from a route path.\n *\n * @param path - The route path\n * @returns Array of invalid param info\n */\nexport function getInvalidParams(path: string): Array<ExtractedParam> {\n const params = extractParamsFromPath(path)\n return params.filter((p) => !p.isValid)\n}\n"],"names":[],"mappings":";AAwBO,SAAS,yBACd,SACuB;AACvB,QAAM,SAAgC,CAAA;AAGtC,MAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,GAAG,GAAG;AACtC,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,OAAO,YAAY,OAAO;AACxC,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,SAAS,GAAG,GAAG;AACrD,UAAM,YAAY,QAAQ,MAAM,CAAC;AACjC,QAAI,WAAW;AACb,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX;AAAA,QACA,YAAY;AAAA,QACZ,SAAS,uBAAuB,KAAK,SAAS;AAAA,MAAA,CAC/C;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAIA,QAAM,eAAe;AACrB,MAAI;AAEJ,UAAQ,QAAQ,aAAa,KAAK,OAAO,OAAO,MAAM;AACpD,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,YAAY,MAAM,CAAC;AAEzB,QAAI,CAAC,WAAW;AAEd;AAAA,IACF;AAEA,UAAM,aAAa,WAAW;AAE9B,WAAO,KAAK;AAAA,MACV,WAAW,GAAG,MAAM,GAAG,SAAS;AAAA,MAChC;AAAA,MACA;AAAA,MACA,SAAS,uBAAuB,KAAK,SAAS;AAAA,IAAA,CAC/C;AAAA,EACH;AAEA,SAAO;AACT;AAQO,SAAS,sBAAsB,MAAqC;AACzE,MAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,GAAG,GAAG;AAChC,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,QAAM,YAAmC,CAAA;AAEzC,aAAW,WAAW,UAAU;AAC9B,UAAM,SAAS,yBAAyB,OAAO;AAC/C,cAAU,KAAK,GAAG,MAAM;AAAA,EAC1B;AAEA,SAAO;AACT;AAkBO,SAAS,iBAAiB,MAAqC;AACpE,QAAM,SAAS,sBAAsB,IAAI;AACzC,SAAO,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO;AACxC;"}
{"version":3,"file":"route-param-names.utils.js","names":[],"sources":["../../../../src/rules/route-param-names/route-param-names.utils.ts"],"sourcesContent":["import { VALID_PARAM_NAME_REGEX } from './constants'\n\nexport interface ExtractedParam {\n /** The full param string including $ prefix (e.g., \"$userId\", \"-$optional\") */\n fullParam: string\n /** The param name without $ prefix (e.g., \"userId\", \"optional\") */\n paramName: string\n /** Whether this is an optional param (prefixed with -$) */\n isOptional: boolean\n /** Whether this param name is valid */\n isValid: boolean\n}\n\n/**\n * Extracts param names from a route path segment.\n *\n * Handles these patterns:\n * - $paramName -> extract \"paramName\"\n * - {$paramName} -> extract \"paramName\"\n * - prefix{$paramName}suffix -> extract \"paramName\"\n * - {-$paramName} -> extract \"paramName\" (optional)\n * - prefix{-$paramName}suffix -> extract \"paramName\" (optional)\n * - $ or {$} -> wildcard, skip validation\n */\nexport function extractParamsFromSegment(\n segment: string,\n): Array<ExtractedParam> {\n const params: Array<ExtractedParam> = []\n\n // Skip empty segments\n if (!segment || !segment.includes('$')) {\n return params\n }\n\n // Check for wildcard ($ alone or {$})\n if (segment === '$' || segment === '{$}') {\n return params // Wildcard, no param name to validate\n }\n\n // Pattern 1: Simple $paramName (entire segment starts with $)\n if (segment.startsWith('$') && !segment.includes('{')) {\n const paramName = segment.slice(1)\n if (paramName) {\n params.push({\n fullParam: segment,\n paramName,\n isOptional: false,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n return params\n }\n\n // Pattern 2: Braces pattern {$paramName} or {-$paramName} with optional prefix/suffix\n // Match patterns like: prefix{$param}suffix, {$param}, {-$param}\n const bracePattern = /\\{(-?\\$)([^}]*)\\}/g\n let match\n\n while ((match = bracePattern.exec(segment)) !== null) {\n const prefix = match[1] // \"$\" or \"-$\"\n const paramName = match[2] // The param name after $ or -$\n\n if (!paramName) {\n // This is a wildcard {$} or {-$}, skip\n continue\n }\n\n const isOptional = prefix === '-$'\n\n params.push({\n fullParam: `${prefix}${paramName}`,\n paramName,\n isOptional,\n isValid: VALID_PARAM_NAME_REGEX.test(paramName),\n })\n }\n\n return params\n}\n\n/**\n * Extracts all params from a route path.\n *\n * @param path - The route path (e.g., \"/users/$userId/posts/$postId\")\n * @returns Array of extracted params with validation info\n */\nexport function extractParamsFromPath(path: string): Array<ExtractedParam> {\n if (!path || !path.includes('$')) {\n return []\n }\n\n const segments = path.split('/')\n const allParams: Array<ExtractedParam> = []\n\n for (const segment of segments) {\n const params = extractParamsFromSegment(segment)\n allParams.push(...params)\n }\n\n return allParams\n}\n\n/**\n * Validates a single param name.\n *\n * @param paramName - The param name to validate (without $ prefix)\n * @returns Whether the param name is valid\n */\nexport function isValidParamName(paramName: string): boolean {\n return VALID_PARAM_NAME_REGEX.test(paramName)\n}\n\n/**\n * Gets all invalid params from a route path.\n *\n * @param path - The route path\n * @returns Array of invalid param info\n */\nexport function getInvalidParams(path: string): Array<ExtractedParam> {\n const params = extractParamsFromPath(path)\n return params.filter((p) => !p.isValid)\n}\n"],"mappings":";;;;;;;;;;;;;AAwBA,SAAgB,yBACd,SACuB;CACvB,MAAM,SAAgC,EAAE;AAGxC,KAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,IAAI,CACpC,QAAO;AAIT,KAAI,YAAY,OAAO,YAAY,MACjC,QAAO;AAIT,KAAI,QAAQ,WAAW,IAAI,IAAI,CAAC,QAAQ,SAAS,IAAI,EAAE;EACrD,MAAM,YAAY,QAAQ,MAAM,EAAE;AAClC,MAAI,UACF,QAAO,KAAK;GACV,WAAW;GACX;GACA,YAAY;GACZ,SAAS,uBAAuB,KAAK,UAAU;GAChD,CAAC;AAEJ,SAAO;;CAKT,MAAM,eAAe;CACrB,IAAI;AAEJ,SAAQ,QAAQ,aAAa,KAAK,QAAQ,MAAM,MAAM;EACpD,MAAM,SAAS,MAAM;EACrB,MAAM,YAAY,MAAM;AAExB,MAAI,CAAC,UAEH;EAGF,MAAM,aAAa,WAAW;AAE9B,SAAO,KAAK;GACV,WAAW,GAAG,SAAS;GACvB;GACA;GACA,SAAS,uBAAuB,KAAK,UAAU;GAChD,CAAC;;AAGJ,QAAO;;;;;;;;AAST,SAAgB,sBAAsB,MAAqC;AACzE,KAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,CAC9B,QAAO,EAAE;CAGX,MAAM,WAAW,KAAK,MAAM,IAAI;CAChC,MAAM,YAAmC,EAAE;AAE3C,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,yBAAyB,QAAQ;AAChD,YAAU,KAAK,GAAG,OAAO;;AAG3B,QAAO;;;;;;;;AAmBT,SAAgB,iBAAiB,MAAqC;AAEpE,QADe,sBAAsB,KAAK,CAC5B,QAAQ,MAAM,CAAC,EAAE,QAAQ"}
import { TSESTree } from "@typescript-eslint/utils";
//#region src/utils/detect-router-imports.ts
function detectTanstackRouterImports(create) {
return (context, optionsWithDefault) => {
const tanstackRouterImportSpecifiers = [];
const helpers = {
isSpecificTanstackRouterImport(node, source) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.parent.type === TSESTree.AST_NODE_TYPES.ImportDeclaration && specifier.parent.source.value === source) {
return node.name === specifier.local.name;
}
return false;
});
},
isTanstackRouterImport(node) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {
return node.name === specifier.local.name;
}
return false;
});
}
};
const detectionInstructions = {
ImportDeclaration(node) {
if (node.specifiers.length > 0 && // `importKind` is parser-dependent and can be undefined (eg. Espree)
node.importKind !== "type" && node.source.value.startsWith("@tanstack/") && node.source.value.endsWith("-router")) {
tanstackRouterImportSpecifiers.push(...node.specifiers);
}
}
};
const ruleInstructions = create(context, optionsWithDefault, helpers);
const enhancedRuleInstructions = {};
const allKeys = new Set(
Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions))
);
allKeys.forEach((instruction) => {
enhancedRuleInstructions[instruction] = (node) => {
if (instruction in detectionInstructions) {
detectionInstructions[instruction]?.(node);
}
const ruleFunction = ruleInstructions[instruction];
if (ruleFunction !== void 0) {
return ruleFunction(node);
}
return void 0;
};
});
return enhancedRuleInstructions;
};
return (context, optionsWithDefault) => {
const tanstackRouterImportSpecifiers = [];
const helpers = {
isSpecificTanstackRouterImport(node, source) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier && specifier.parent.type === TSESTree.AST_NODE_TYPES.ImportDeclaration && specifier.parent.source.value === source) return node.name === specifier.local.name;
return false;
});
},
isTanstackRouterImport(node) {
return !!tanstackRouterImportSpecifiers.find((specifier) => {
if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) return node.name === specifier.local.name;
return false;
});
}
};
const detectionInstructions = { ImportDeclaration(node) {
if (node.specifiers.length > 0 && node.importKind !== "type" && node.source.value.startsWith("@tanstack/") && node.source.value.endsWith("-router")) tanstackRouterImportSpecifiers.push(...node.specifiers);
} };
const ruleInstructions = create(context, optionsWithDefault, helpers);
const enhancedRuleInstructions = {};
new Set(Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions))).forEach((instruction) => {
enhancedRuleInstructions[instruction] = (node) => {
if (instruction in detectionInstructions) detectionInstructions[instruction]?.(node);
const ruleFunction = ruleInstructions[instruction];
if (ruleFunction !== void 0) return ruleFunction(node);
};
});
return enhancedRuleInstructions;
};
}
export {
detectTanstackRouterImports
};
//# sourceMappingURL=detect-router-imports.js.map
//#endregion
export { detectTanstackRouterImports };
//# sourceMappingURL=detect-router-imports.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"detect-router-imports.js","sources":["../../../src/utils/detect-router-imports.ts"],"sourcesContent":["import { TSESTree } from '@typescript-eslint/utils'\nimport type { ESLintUtils, TSESLint } from '@typescript-eslint/utils'\n\ntype Create = Parameters<\n ReturnType<typeof ESLintUtils.RuleCreator>\n>[0]['create']\n\ntype Context = Parameters<Create>[0]\ntype Options = Parameters<Create>[1]\ntype Helpers = {\n isSpecificTanstackRouterImport: (\n node: TSESTree.Identifier,\n source: string,\n ) => boolean\n isTanstackRouterImport: (node: TSESTree.Identifier) => boolean\n}\n\ntype EnhancedCreate = (\n context: Context,\n options: Options,\n helpers: Helpers,\n) => ReturnType<Create>\n\nexport function detectTanstackRouterImports(create: EnhancedCreate): Create {\n return (context, optionsWithDefault) => {\n const tanstackRouterImportSpecifiers: Array<TSESTree.ImportClause> = []\n\n const helpers: Helpers = {\n isSpecificTanstackRouterImport(node, source) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (\n specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier &&\n specifier.parent.type ===\n TSESTree.AST_NODE_TYPES.ImportDeclaration &&\n specifier.parent.source.value === source\n ) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n isTanstackRouterImport(node) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n }\n\n const detectionInstructions: TSESLint.RuleListener = {\n ImportDeclaration(node) {\n if (\n node.specifiers.length > 0 &&\n // `importKind` is parser-dependent and can be undefined (eg. Espree)\n node.importKind !== 'type' &&\n node.source.value.startsWith('@tanstack/') &&\n node.source.value.endsWith('-router')\n ) {\n tanstackRouterImportSpecifiers.push(...node.specifiers)\n }\n },\n }\n\n // Call original rule definition\n const ruleInstructions = create(context, optionsWithDefault, helpers)\n const enhancedRuleInstructions: TSESLint.RuleListener = {}\n\n const allKeys = new Set(\n Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions)),\n )\n\n // Iterate over ALL instructions keys so we can override original rule instructions\n // to prevent their execution if conditions to report errors are not met.\n allKeys.forEach((instruction) => {\n enhancedRuleInstructions[instruction] = (node) => {\n if (instruction in detectionInstructions) {\n detectionInstructions[instruction]?.(node)\n }\n\n const ruleFunction = ruleInstructions[instruction]\n if (ruleFunction !== undefined) {\n return ruleFunction(node)\n }\n\n return undefined\n }\n })\n\n return enhancedRuleInstructions\n }\n}\n"],"names":[],"mappings":";AAuBO,SAAS,4BAA4B,QAAgC;AAC1E,SAAO,CAAC,SAAS,uBAAuB;AACtC,UAAM,iCAA+D,CAAA;AAErE,UAAM,UAAmB;AAAA,MACvB,+BAA+B,MAAM,QAAQ;AAC3C,eAAO,CAAC,CAAC,+BAA+B,KAAK,CAAC,cAAc;AAC1D,cACE,UAAU,SAAS,SAAS,eAAe,mBAC3C,UAAU,OAAO,SACf,SAAS,eAAe,qBAC1B,UAAU,OAAO,OAAO,UAAU,QAClC;AACA,mBAAO,KAAK,SAAS,UAAU,MAAM;AAAA,UACvC;AAEA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,MACA,uBAAuB,MAAM;AAC3B,eAAO,CAAC,CAAC,+BAA+B,KAAK,CAAC,cAAc;AAC1D,cAAI,UAAU,SAAS,SAAS,eAAe,iBAAiB;AAC9D,mBAAO,KAAK,SAAS,UAAU,MAAM;AAAA,UACvC;AAEA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IAAA;AAGF,UAAM,wBAA+C;AAAA,MACnD,kBAAkB,MAAM;AACtB,YACE,KAAK,WAAW,SAAS;AAAA,QAEzB,KAAK,eAAe,UACpB,KAAK,OAAO,MAAM,WAAW,YAAY,KACzC,KAAK,OAAO,MAAM,SAAS,SAAS,GACpC;AACA,yCAA+B,KAAK,GAAG,KAAK,UAAU;AAAA,QACxD;AAAA,MACF;AAAA,IAAA;AAIF,UAAM,mBAAmB,OAAO,SAAS,oBAAoB,OAAO;AACpE,UAAM,2BAAkD,CAAA;AAExD,UAAM,UAAU,IAAI;AAAA,MAClB,OAAO,KAAK,qBAAqB,EAAE,OAAO,OAAO,KAAK,gBAAgB,CAAC;AAAA,IAAA;AAKzE,YAAQ,QAAQ,CAAC,gBAAgB;AAC/B,+BAAyB,WAAW,IAAI,CAAC,SAAS;AAChD,YAAI,eAAe,uBAAuB;AACxC,gCAAsB,WAAW,IAAI,IAAI;AAAA,QAC3C;AAEA,cAAM,eAAe,iBAAiB,WAAW;AACjD,YAAI,iBAAiB,QAAW;AAC9B,iBAAO,aAAa,IAAI;AAAA,QAC1B;AAEA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;"}
{"version":3,"file":"detect-router-imports.js","names":[],"sources":["../../../src/utils/detect-router-imports.ts"],"sourcesContent":["import { TSESTree } from '@typescript-eslint/utils'\nimport type { ESLintUtils, TSESLint } from '@typescript-eslint/utils'\n\ntype Create = Parameters<\n ReturnType<typeof ESLintUtils.RuleCreator>\n>[0]['create']\n\ntype Context = Parameters<Create>[0]\ntype Options = Parameters<Create>[1]\ntype Helpers = {\n isSpecificTanstackRouterImport: (\n node: TSESTree.Identifier,\n source: string,\n ) => boolean\n isTanstackRouterImport: (node: TSESTree.Identifier) => boolean\n}\n\ntype EnhancedCreate = (\n context: Context,\n options: Options,\n helpers: Helpers,\n) => ReturnType<Create>\n\nexport function detectTanstackRouterImports(create: EnhancedCreate): Create {\n return (context, optionsWithDefault) => {\n const tanstackRouterImportSpecifiers: Array<TSESTree.ImportClause> = []\n\n const helpers: Helpers = {\n isSpecificTanstackRouterImport(node, source) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (\n specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier &&\n specifier.parent.type ===\n TSESTree.AST_NODE_TYPES.ImportDeclaration &&\n specifier.parent.source.value === source\n ) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n isTanstackRouterImport(node) {\n return !!tanstackRouterImportSpecifiers.find((specifier) => {\n if (specifier.type === TSESTree.AST_NODE_TYPES.ImportSpecifier) {\n return node.name === specifier.local.name\n }\n\n return false\n })\n },\n }\n\n const detectionInstructions: TSESLint.RuleListener = {\n ImportDeclaration(node) {\n if (\n node.specifiers.length > 0 &&\n // `importKind` is parser-dependent and can be undefined (eg. Espree)\n node.importKind !== 'type' &&\n node.source.value.startsWith('@tanstack/') &&\n node.source.value.endsWith('-router')\n ) {\n tanstackRouterImportSpecifiers.push(...node.specifiers)\n }\n },\n }\n\n // Call original rule definition\n const ruleInstructions = create(context, optionsWithDefault, helpers)\n const enhancedRuleInstructions: TSESLint.RuleListener = {}\n\n const allKeys = new Set(\n Object.keys(detectionInstructions).concat(Object.keys(ruleInstructions)),\n )\n\n // Iterate over ALL instructions keys so we can override original rule instructions\n // to prevent their execution if conditions to report errors are not met.\n allKeys.forEach((instruction) => {\n enhancedRuleInstructions[instruction] = (node) => {\n if (instruction in detectionInstructions) {\n detectionInstructions[instruction]?.(node)\n }\n\n const ruleFunction = ruleInstructions[instruction]\n if (ruleFunction !== undefined) {\n return ruleFunction(node)\n }\n\n return undefined\n }\n })\n\n return enhancedRuleInstructions\n }\n}\n"],"mappings":";;AAuBA,SAAgB,4BAA4B,QAAgC;AAC1E,SAAQ,SAAS,uBAAuB;EACtC,MAAM,iCAA+D,EAAE;EAEvE,MAAM,UAAmB;GACvB,+BAA+B,MAAM,QAAQ;AAC3C,WAAO,CAAC,CAAC,+BAA+B,MAAM,cAAc;AAC1D,SACE,UAAU,SAAS,SAAS,eAAe,mBAC3C,UAAU,OAAO,SACf,SAAS,eAAe,qBAC1B,UAAU,OAAO,OAAO,UAAU,OAElC,QAAO,KAAK,SAAS,UAAU,MAAM;AAGvC,YAAO;MACP;;GAEJ,uBAAuB,MAAM;AAC3B,WAAO,CAAC,CAAC,+BAA+B,MAAM,cAAc;AAC1D,SAAI,UAAU,SAAS,SAAS,eAAe,gBAC7C,QAAO,KAAK,SAAS,UAAU,MAAM;AAGvC,YAAO;MACP;;GAEL;EAED,MAAM,wBAA+C,EACnD,kBAAkB,MAAM;AACtB,OACE,KAAK,WAAW,SAAS,KAEzB,KAAK,eAAe,UACpB,KAAK,OAAO,MAAM,WAAW,aAAa,IAC1C,KAAK,OAAO,MAAM,SAAS,UAAU,CAErC,gCAA+B,KAAK,GAAG,KAAK,WAAW;KAG5D;EAGD,MAAM,mBAAmB,OAAO,SAAS,oBAAoB,QAAQ;EACrE,MAAM,2BAAkD,EAAE;AAE1C,MAAI,IAClB,OAAO,KAAK,sBAAsB,CAAC,OAAO,OAAO,KAAK,iBAAiB,CAAC,CACzE,CAIO,SAAS,gBAAgB;AAC/B,4BAAyB,gBAAgB,SAAS;AAChD,QAAI,eAAe,sBACjB,uBAAsB,eAAe,KAAK;IAG5C,MAAM,eAAe,iBAAiB;AACtC,QAAI,iBAAiB,KAAA,EACnB,QAAO,aAAa,KAAK;;IAK7B;AAEF,SAAO"}

@@ -1,5 +0,6 @@

const getDocsUrl = (ruleName) => `https://tanstack.com/router/latest/docs/eslint/${ruleName}`;
export {
getDocsUrl
};
//# sourceMappingURL=get-docs-url.js.map
//#region src/utils/get-docs-url.ts
var getDocsUrl = (ruleName) => `https://tanstack.com/router/latest/docs/eslint/${ruleName}`;
//#endregion
export { getDocsUrl };
//# sourceMappingURL=get-docs-url.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"get-docs-url.js","sources":["../../../src/utils/get-docs-url.ts"],"sourcesContent":["export const getDocsUrl = (ruleName: string): string =>\n `https://tanstack.com/router/latest/docs/eslint/${ruleName}`\n"],"names":[],"mappings":"AAAO,MAAM,aAAa,CAAC,aACzB,kDAAkD,QAAQ;"}
{"version":3,"file":"get-docs-url.js","names":[],"sources":["../../../src/utils/get-docs-url.ts"],"sourcesContent":["export const getDocsUrl = (ruleName: string): string =>\n `https://tanstack.com/router/latest/docs/eslint/${ruleName}`\n"],"mappings":";AAAA,IAAa,cAAc,aACzB,kDAAkD"}
{
"name": "@tanstack/eslint-plugin-router",
"version": "1.161.5",
"version": "1.161.6",
"description": "ESLint plugin for TanStack Router",

@@ -5,0 +5,0 @@ "author": "Manuel Schiller",