@longzai-intelligence-oxlint/elysia-route-plugin 0.0.0-stage → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +100 -0
- package/dist/index.js +1 -0
- package/package.json +49 -4
- package/README.md +0 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ESTree } from "@oxlint/plugins";
|
|
2
|
+
//#region src/rules/no-bare-route-path/index.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* no-bare-route-path 规则定义
|
|
5
|
+
*
|
|
6
|
+
* 检测 Elysia 路由注册与 prefix 配置中的裸路径字面量
|
|
7
|
+
*/
|
|
8
|
+
declare const noBareRoutePathRule: import("@oxlint/plugins").Rule;
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/utils/elysia-route.utils.d.ts
|
|
11
|
+
/**
|
|
12
|
+
* 判断表达式是否以给定前缀开头的路径形态
|
|
13
|
+
*
|
|
14
|
+
* 模板串与拼接表达式取其最左操作数的字符串前缀判定
|
|
15
|
+
*
|
|
16
|
+
* @param node - 表达式节点
|
|
17
|
+
* @returns 以 `/` 开头的路径表达式返回 true
|
|
18
|
+
*/
|
|
19
|
+
declare function isPathLikeExpression(node: ESTree.Node): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* 判断调用表达式是否为 Elysia 路由方法注册调用
|
|
22
|
+
*
|
|
23
|
+
* 命中方法名集合且首个参数为路径形态表达式
|
|
24
|
+
*
|
|
25
|
+
* @param node - 调用表达式节点
|
|
26
|
+
* @returns 路由注册调用返回 true
|
|
27
|
+
*/
|
|
28
|
+
declare function isRouteRegistrationCall(node: ESTree.CallExpression): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 判断新表达式是否为 Elysia 实例构造
|
|
31
|
+
*
|
|
32
|
+
* @param node - 新表达式节点
|
|
33
|
+
* @returns 构造名为 Elysia 时返回 true
|
|
34
|
+
*/
|
|
35
|
+
declare function isNewElysiaExpression(node: ESTree.NewExpression): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* 从 Elysia 构造参数中提取 prefix 属性值节点
|
|
38
|
+
*
|
|
39
|
+
* @param node - 新表达式节点
|
|
40
|
+
* @returns prefix 属性值节点,不存在时返回 undefined
|
|
41
|
+
*/
|
|
42
|
+
declare function extractPrefixPropertyNode(node: ESTree.NewExpression): ESTree.Node | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* 判断文件路径是否命中豁免后缀清单
|
|
45
|
+
*
|
|
46
|
+
* @param filename - 当前文件路径
|
|
47
|
+
* @param allowedFiles - 豁免文件路径后缀列表
|
|
48
|
+
* @returns 命中任一后缀返回 true
|
|
49
|
+
*/
|
|
50
|
+
declare function isAllowedFile(filename: string, allowedFiles: string[]): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* 判断路径字面量是否命中豁免路径清单
|
|
53
|
+
*
|
|
54
|
+
* @param path - 注册路径值
|
|
55
|
+
* @param allowedPaths - 豁免路径字面量列表
|
|
56
|
+
* @returns 完全一致命中返回 true
|
|
57
|
+
*/
|
|
58
|
+
declare function isAllowedPath(path: string, allowedPaths: string[]): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* 读取路径表达式的静态字符串值
|
|
61
|
+
*
|
|
62
|
+
* @param node - 表达式节点
|
|
63
|
+
* @returns 字符串字面量值,非字面量时返回 undefined
|
|
64
|
+
*/
|
|
65
|
+
declare function readPathValue(node: ESTree.Node): string | undefined;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/types.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* Elysia 路由管理插件类型定义
|
|
70
|
+
*
|
|
71
|
+
* 定义路由方法集合、裸路径判定与规则选项等核心类型
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* Elysia 路由注册方法名集合
|
|
75
|
+
*/
|
|
76
|
+
type ElysiaRouteMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'all' | 'route' | 'group';
|
|
77
|
+
/**
|
|
78
|
+
* no-bare-route-path 规则选项
|
|
79
|
+
*/
|
|
80
|
+
type NoBareRoutePathOptions = {
|
|
81
|
+
/**
|
|
82
|
+
* 豁免文件路径后缀列表,命中任一后缀的文件整件豁免
|
|
83
|
+
*/
|
|
84
|
+
allowedFiles?: string[];
|
|
85
|
+
/**
|
|
86
|
+
* 豁免路径字面量列表,注册路径与清单内字面量完全一致时豁免
|
|
87
|
+
*/
|
|
88
|
+
allowedPaths?: string[];
|
|
89
|
+
};
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/index.d.ts
|
|
92
|
+
/**
|
|
93
|
+
* elysia-route 插件
|
|
94
|
+
*
|
|
95
|
+
* 提供 Elysia 路由契约绑定相关的 Oxlint 规则,
|
|
96
|
+
* 通过 eslintCompatPlugin 包装以同时支持 Oxlint 和 ESLint 运行时
|
|
97
|
+
*/
|
|
98
|
+
declare const elysiaRoutePlugin: import("@oxlint/plugins").Plugin;
|
|
99
|
+
//#endregion
|
|
100
|
+
export { type ElysiaRouteMethod, type NoBareRoutePathOptions, elysiaRoutePlugin as default, elysiaRoutePlugin, extractPrefixPropertyNode, isAllowedFile, isAllowedPath, isNewElysiaExpression, isPathLikeExpression, isRouteRegistrationCall, noBareRoutePathRule, readPathValue };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";const n=[`get`,`post`,`put`,`patch`,`delete`,`all`,`route`,`group`];function r(e){if(e.type===`Literal`&&`value`in e&&typeof e.value==`string`)return e.value}function i(e){switch(e.type){case`Literal`:return r(e)?.startsWith(`/`)===!0;case`TemplateLiteral`:return e.quasis[0]?.value.raw.startsWith(`/`)===!0;case`BinaryExpression`:return e.operator===`+`&&i(e.left);default:return!1}}function a(e){if(e.callee.type!==`MemberExpression`)return!1;let t=e.callee.property;if(t.type!==`Identifier`||!n.includes(t.name))return!1;let r=e.arguments[0];return r?i(r):!1}function o(e){return e.callee.type===`Identifier`&&e.callee.name===`Elysia`}function s(e){let t=e.arguments[0];if(t&&t.type===`ObjectExpression`){for(let e of t.properties)if(e.type===`Property`&&e.key.type===`Identifier`&&e.key.name===`prefix`)return e.value}}function c(e,t){return t.some(t=>e.includes(t))}function l(e,t){return t.includes(e)}function u(e){return r(e)}const d=`Elysia 路由注册禁止裸 URL 路径字面量,路径必须取自契约 RouteDefinition 字典导出(如 xxxRoutes.operation.path)。`;function f(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function p(e){return!(typeof e!=`object`||!e||!(`allowedFiles`in e)&&!(`allowedPaths`in e)||`allowedFiles`in e&&e.allowedFiles!==void 0&&!f(e.allowedFiles)||`allowedPaths`in e&&e.allowedPaths!==void 0&&!f(e.allowedPaths))}const m=e({meta:{type:`problem`,docs:{description:`Elysia 路由注册禁止裸 URL 路径字面量,路径必须取自契约 RouteDefinition 字典导出`},schema:[{type:`object`,properties:{allowedFiles:{type:`array`,items:{type:`string`},description:`豁免文件路径后缀列表,命中文件整件豁免`},allowedPaths:{type:`array`,items:{type:`string`},description:`豁免路径字面量列表,完全一致时豁免`}},additionalProperties:!1}]},createOnce(e){let t=!1,n=[];return{Program(r){t=!1,n=[];let i=e.options?.[0];if(!p(i))return;let a=i;n=a.allowedPaths??[],a.allowedFiles!==void 0&&c(e.filename,a.allowedFiles)&&(t=!0)},CallExpression(r){if(t||!a(r))return;let i=r.arguments[0];if(!i)return;let o=u(i);o!==void 0&&l(o,n)||e.report({node:i,message:d})},NewExpression(r){if(t||!o(r))return;let a=s(r);if(!a||!i(a))return;let c=u(a);c!==void 0&&l(c,n)||e.report({node:a,message:d})}}}}),h=t({meta:{name:`@longzai-intelligence-oxlint/elysia-route-plugin`},rules:{"no-bare-route-path":m}});export{h as default,h as elysiaRoutePlugin,s as extractPrefixPropertyNode,c as isAllowedFile,l as isAllowedPath,o as isNewElysiaExpression,i as isPathLikeExpression,a as isRouteRegistrationCall,m as noBareRoutePathRule,u as readPathValue};
|
package/package.json
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longzai-intelligence-oxlint/elysia-route-plugin",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.47",
|
|
4
|
+
"description": "Longzai Intelligence oxlint Elysia 路由规则插件",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"elysia",
|
|
7
|
+
"longzai-intelligence",
|
|
8
|
+
"oxlint",
|
|
9
|
+
"route",
|
|
10
|
+
"rules"
|
|
11
|
+
],
|
|
12
|
+
"license": "UNLICENSED",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "lzi-builder",
|
|
27
|
+
"build:prod": "NODE_ENV=production bun run build",
|
|
28
|
+
"prepublishOnly": "bun run build:prod",
|
|
29
|
+
"dev": "lzi-builder --watch",
|
|
30
|
+
"clean": "lzi-dev-cli clean",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest",
|
|
33
|
+
"test:coverage": "vitest run --coverage",
|
|
34
|
+
"lint": "oxlint && oxfmt --check",
|
|
35
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
36
|
+
"typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
|
|
37
|
+
"typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
|
|
38
|
+
"typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
|
|
39
|
+
"typecheck:test": "lzi-tsgo typecheck tsconfig/test.json"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@oxlint/plugins": "^1.74.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
46
|
+
"typescript": "^6.0.3"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"oxlint": ">=1.0.0"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/README.md
DELETED