@longzai-intelligence-oxlint/presets 0.2.2 → 0.2.3
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/plugins/code-style.js +1 -1
- package/package.json +28 -28
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../rolldown-runtime-BqT_7tdF.js";import"../rolldown-runtime-BqT_7tdF-BqT_7tdF.js";import{n as e,r as t,t as n}from"../dist-CskvMq7J.js";import{defineRule as r,eslintCompatPlugin as i}from"@oxlint/plugins";import{existsSync as a,readFileSync as ee}from"node:fs";import{dirname as o,join as te}from"node:path";import*as s from"zod/mini";function c(e){return e.endsWith(`Class`)}const l=r({meta:{type:`problem`,docs:{description:`禁止在 import 别名中使用 "Class" 后缀`}},createOnce(e){return{ImportSpecifier(t){let n=t.local.name,r=t.imported.type===`Identifier`?t.imported.name:n;n!==r&&c(n)&&e.report({node:t,message:`导入别名 "${n}" 使用了 "Class" 后缀,这是不允许的命名方式。请使用更具描述性的名称,或直接使用原始名称 "${r}"`})}}}}),u=/* @__PURE__ */ new Set([`console.log`,`console.warn`,`console.error`,`console.info`,`console.debug`,`console.trace`,`console.dir`,`console.table`]);function d(e){let t=e.callee;return t.type===`Identifier`?t.name:t.type===`MemberExpression`&&t.property.type===`Identifier`&&t.object.type===`Identifier`?`${t.object.name}.${t.property.name}`:null}const f=r({meta:{type:`problem`,docs:{description:`禁止使用 console 方法,必须使用 @longzai-intelligence/logger-preset-* 或 react-devtools(ADR 0038)`}},createOnce(e){return{CallExpression(t){if(t.type!==`CallExpression`)return;let n=d(t);n&&u.has(n)&&e.report({node:t,message:`检测到 '${n}' — 必须使用 @longzai-intelligence/logger-preset-* 代替(ADR 0038)`})}}}}),p=/\/src\/(index|main|cli)\.(ts|mts|cts)$/,m=/(^|\/)dist\//;function ne(e){return e.replace(/\\/g,`/`)}function h(e){return typeof e==`object`&&!!e}function re(e){return e.startsWith(`#!`)}function g(e){return p.test(ne(e))}function ie(e){let t=e;for(let e=0;e<4;e+=1){let e=te(t,`package.json`);if(a(e))try{let t=JSON.parse(ee(e,`utf8`));return h(t)?t:null}catch{return null}let n=o(t);if(n===t)break;t=n}return null}function ae(e){let t=e.bin;return(typeof t==`string`?[t]:h(t)?Object.values(t).filter(e=>typeof e==`string`):[]).some(e=>m.test(e.replace(/^\.\//,``)))}const _={noHandwrittenShebang:`入口源码手写 shebang 属被裁定的错误方式,bin 产物首行 shebang 应由 "lzi-builder.config.ts" 的 banner 在构建期注入。请删除源码首行的 "#!" 行并补 banner 配置。`},v=r({meta:{type:`problem`,docs:{description:`禁止所属包 bin 指向 dist 产物的入口源码手写 shebang`}},createOnce(e){return{before(){let t=e.filename;if(!g(t))return!1},Program(t){let n=e.sourceCode.text;if(!re(n))return;let r=ie(o(o(e.filename)));r!==null&&ae(r)&&e.report({node:t,message:_.noHandwrittenShebang})}}}}),y=s.object({type:s.literal(`TSTypeLiteral`)}),b=s.object({type:s.literal(`TSFunctionType`)}),x=s.object({type:s.literal(`TSUnionType`),types:s.array(s.unknown())}),oe=s.object({type:s.literal(`TSIntersectionType`),types:s.array(s.unknown())}),se=s.object({type:s.literal(`Identifier`),name:s.string()}),ce=s.object({type:s.literal(`RestElement`),argument:s.object({name:s.string()})}),le=s.union([se,ce]),S=s.object({typeAnnotation:s.unknown()}),ue=s.object({type:s.literal(`MethodDefinition`),key:s.object({type:s.string(),name:s.optional(s.string())}),value:s.object({params:s.optional(s.array(s.unknown())),returnType:s.optional(s.union([S,s.null()]))}),kind:s.enum([`method`,`constructor`,`get`,`set`])}),de=s.object({returnType:S}),fe=s.object({id:s.optional(s.object({name:s.optional(s.string())})),params:s.optional(s.array(s.unknown())),returnType:s.optional(s.unknown())}),pe=s.object({params:s.optional(s.array(s.unknown()))});function C(e){return y.safeParse(e).success}function w(e){return b.safeParse(e).success}function T(e){return x.safeParse(e).success}function E(e){return oe.safeParse(e).success}function D(e){return le.safeParse(e).success}function O(e){if(typeof e!=`object`||!e||!(`type`in e))return!1;let t=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`MethodDefinition`],n=e.type;return typeof n==`string`&&t.includes(n)}function k(e){return ue.safeParse(e).success}function A(e){return de.safeParse(e).success}function j(e){return fe.safeParse(e).success}function M(e){return pe.safeParse(e).success}function N(e){return C(e)||w(e)?!0:T(e)||E(e)?e.types.some(N):!1}function P(e){return C(e)?`对象类型`:w(e)?`函数类型`:`内联类型`}function F(e){return D(e)?e.type===`Identifier`?e.name:e.type===`RestElement`?e.argument.name:null:null}function I(e,t,n,r,i,a){i?e.report({node:t,message:`参数 "${n}" 使用了内联${r}定义。请将其提取为具名的 type。`}):a?e.report({node:t,message:`方法 "${a}" 的参数 "${n}" 使用了内联${r}定义。请将其提取为具名的 type。`}):e.report({node:t,message:`参数 "${n}" 使用了内联${r}定义。请将其提取为具名的 type。`})}function L(e,t,n,r,i){i?e.report({node:t,message:`方法 "${i}" 的返回值使用了内联${n}定义。请将其提取为具名的 type。`}):r?e.report({node:t,message:`函数 "${r}" 的返回值使用了内联${n}定义。请将其提取为具名的 type。`}):e.report({node:t,message:`匿名函数的返回值使用了内联${n}定义。请将其提取为具名的 type。`})}function R(e,t,n,r,i){if(typeof e!=`object`||!e||!(`typeAnnotation`in e)||e.typeAnnotation===null||typeof e.typeAnnotation!=`object`||!(`typeAnnotation`in e.typeAnnotation))return;let a=e.typeAnnotation.typeAnnotation;N(a)&&I(t,n,F(e)??`未知参数`,P(a),r,i)}function z(e,t,n,r,i){for(let a of e)R(a,t,n,i??!1,r)}function B(e,t,n,r,i){if(typeof e!=`object`||!e||!(`typeAnnotation`in e))return;let a=e.typeAnnotation;N(a)&&L(t,n,P(a),r,i)}function V(e,t){if(!O(e)||!j(e))return;let n=null;`id`in e&&e.id!==null&&typeof e.id==`object`&&`name`in e.id&&typeof e.id.name==`string`&&(n=e.id.name),M(e)&&z(e.params??[],t,e),A(e)&&B(e.returnType,t,e,n??void 0)}function me(e,t){O(e)&&M(e)&&(M(e)&&z(e.params??[],t,e),A(e)&&B(e.returnType,t,e))}function he(e,t){if(!k(e))return;let n=e.key,r=n&&`name`in n&&typeof n.name==`string`?n.name:`未知方法`,i=e.value;if(i&&`params`in i&&Array.isArray(i.params)&&z(i.params,t,e,r,e.kind===`constructor`),i&&`returnType`in i&&i.returnType&&typeof i.returnType==`object`&&`typeAnnotation`in i.returnType){let n=i.returnType;B(n,t,e,void 0,r)}}const H=r({meta:{type:`suggestion`,docs:{description:`禁止在函数参数和返回值中使用内联类型定义,强制使用具名类型`}},createOnce(e){return{FunctionDeclaration(t){V(t,e)},FunctionExpression(t){V(t,e)},ArrowFunctionExpression(t){me(t,e)},MethodDefinition(t){he(t,e)}}}});function ge(e){let t=[];if(e.type===`Identifier`&&t.push(e.name),e.type===`ObjectPattern`)for(let n of e.properties)n.type===`Property`&&`value`in n?n.value.type===`Identifier`&&t.push(n.value.name):n.type===`RestElement`&&n.argument.type===`Identifier`&&t.push(n.argument.name);if(e.type===`ArrayPattern`)for(let n of e.elements)n&&n.type===`Identifier`&&t.push(n.name);return t}const U=r({meta:{type:`suggestion`,docs:{description:`将 export const/let/var 拆分为独立的声明和导出语句`}},createOnce(e){return{ExportNamedDeclaration(t){if(!t.declaration||t.declaration.type!==`VariableDeclaration`)return;let n=t.declaration;if(n.kind!==`const`&&n.kind!==`let`&&n.kind!==`var`||n.declarations.length===0)return;let r=[];for(let e of n.declarations)r.push(...ge(e.id));r.length!==0&&e.report({node:t,message:`应将 \`export ${n.kind} ${r.join(`, `)}\` 拆分为独立的声明和导出语句`})}}}}),W=[{suffix:`.service.drizzle.ts`,classSuffix:`Service`,isInterface:!1,isPrefix:!1},{suffix:`.service.memory.ts`,classSuffix:`Service`,isInterface:!1,isPrefix:!1},{suffix:`.service.ts`,classSuffix:`Service`,isInterface:!1,isPrefix:!1},{suffix:`.controller.ts`,classSuffix:`Controller`,isInterface:!1,isPrefix:!1},{suffix:`.module.ts`,classSuffix:`Module`,isInterface:!1,isPrefix:!1},{suffix:`.repository.drizzle.ts`,classSuffix:`Repository`,isInterface:!1,isPrefix:!1},{suffix:`.repository.memory.ts`,classSuffix:`Repository`,isInterface:!1,isPrefix:!1},{suffix:`.repository.interface.ts`,classSuffix:`Repository`,isInterface:!0,isPrefix:!0},{suffix:`.repository.ts`,classSuffix:`Repository`,isInterface:!1,isPrefix:!1},{suffix:`.entity.ts`,classSuffix:`Entity`,isInterface:!1,isPrefix:!1},{suffix:`.orm-entity.ts`,classSuffix:`OrmEntity`,isInterface:!1,isPrefix:!1},{suffix:`.dto.ts`,classSuffix:`DTO`,isInterface:!1,isPrefix:!1},{suffix:`.port.interface.ts`,classSuffix:`Port`,isInterface:!0,isPrefix:!0},{suffix:`.interface.ts`,classSuffix:``,isInterface:!0,isPrefix:!0},{suffix:`.port.ts`,classSuffix:`Port`,isInterface:!0,isPrefix:!1},{suffix:`.port.adapter.ts`,classSuffix:`PortAdapter`,isInterface:!1,isPrefix:!1},{suffix:`.adapter.ts`,classSuffix:`Adapter`,isInterface:!1,isPrefix:!1},{suffix:`.events.ts`,classSuffix:`Event`,isInterface:!1,isPrefix:!1},{suffix:`.mapper.ts`,classSuffix:`Mapper`,isInterface:!1,isPrefix:!1},{suffix:`.vo.ts`,classSuffix:`VO`,isInterface:!1,isPrefix:!1},{suffix:`.usecase.ts`,classSuffix:`UseCase`,isInterface:!1,isPrefix:!1},{suffix:`.errors.ts`,classSuffix:`Error`,isInterface:!1,isPrefix:!1}];function G(e){for(let t of W)if(e.endsWith(t.suffix))return t;return null}function K(e,t){if(t.isPrefix&&t.isInterface){if(t.classSuffix){let n=t.classSuffix;return e.startsWith(`I`)&&e.endsWith(n)&&e.length>1+n.length}return e.startsWith(`I`)&&e.length>1}return t.isPrefix?e.startsWith(`I`)&&e.length>1:e.endsWith(t.classSuffix)&&e.length>t.classSuffix.length}function q(e){return e.isPrefix&&e.isInterface?e.classSuffix?`I${e.classSuffix}(如 IUser${e.classSuffix})`:`I 前缀(如 IUser)`:e.isPrefix?`I 前缀(如 IUser)`:`${e.classSuffix} 后缀`}const J=r({meta:{type:`problem`,docs:{description:`强制执行类名与文件类型后缀的一致性`}},createOnce(e){return{before(){let t=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``;if(t.endsWith(`.test.ts`)||t.endsWith(`.spec.ts`)||!G(t))return!1},ClassDeclaration(t){let n=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``,r=G(n);if(!r||r.isInterface||!t.id)return;let i=t.id.name;K(i,r)||e.report({node:t,message:`类名 "${i}" 不符合命名规范。文件 "${n}" 中的类应使用 ${q(r)}`})},TSInterfaceDeclaration(t){let n=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``,r=G(n);if(!r||!r.isInterface)return;let i=t.id.name;K(i,r)||e.report({node:t,message:`接口名 "${i}" 不符合命名规范。文件 "${n}" 中的接口应使用 ${q(r)}`})}}}});function Y(e){return e.endsWith(`.dto.ts`)}function X(e){return e.endsWith(`DTO`)}const Z=r({meta:{type:`problem`,docs:{description:`强制执行 DTO 文件中的接口命名规范(Dto 后缀,驼峰式)`}},createOnce(e){return{before(){let t=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``;if(t.endsWith(`.test.ts`)||t.endsWith(`.spec.ts`)||!Y(t))return!1},TSInterfaceDeclaration(n){let r=n.id.name;X(r)?e.report({node:n,message:`接口名 "${r}" 后缀应使用 Dto(驼峰式)而非 DTO(全大写)`}):t(r)||e.report({node:n,message:`DTO 文件中的接口名 "${r}" 应以 Dto 结尾(如 UserResponseDto)`})}}}}),_e=[`types.ts`,`types.d.ts`],ve=[`.port.interface.ts`,`.repository.interface.ts`,`.types.ts`,`.types.d.ts`,`.events.ts`,`.d.ts`];function ye(t,r){return e(t)?!1:!r.endsWith(`.dto.ts`)||n(t)}function be(e){return e.endsWith(`.dto.ts`)?`DTO 后缀(如 UserDTO),禁止 I 前缀`:`PascalCase(如 User、UserRepository),禁止 I 前缀`}function xe(e){if(_e.includes(e))return!0;for(let t of ve)if(e.endsWith(t))return!0;return!1}function Se(e){return e.endsWith(`.port.ts`)?e.replace(`.port.ts`,`.port.interface.ts`):e.endsWith(`.repository.ts`)?e.replace(`.repository.ts`,`.repository.interface.ts`):e.replace(`.ts`,`.interface.ts`)}const Q=r({meta:{type:`problem`,docs:{description:`强制执行接口命名规范(禁止 I 前缀,使用 PascalCase)和文件命名规范`}},createOnce(t){return{before(){let e=t.filename.replace(/\\/g,`/`).split(`/`).pop()??``;if(e.endsWith(`.test.ts`)||e.endsWith(`.spec.ts`)||xe(e))return!1},TSInterfaceDeclaration(n){let r=t.filename.replace(/\\/g,`/`).split(`/`).pop()??``,i=r.endsWith(`.interface.ts`)||r.endsWith(`.interface.tsx`),a=n.id.name;ye(a,r)||(e(a)?t.report({node:n,message:`接口名 "${a}" 使用了 I 前缀。现代 TypeScript 不推荐使用匈牙利命名法,建议使用 "${a.substring(1)}"`}):r.endsWith(`.dto.ts`)&&a.endsWith(`Dto`)?t.report({node:n,message:`接口名 "${a}" 后缀应使用 DTO(全大写)而非 Dto(驼峰式)`}):t.report({node:n,message:`接口名 "${a}" 不符合命名规范。接口名应使用 ${be(r)}`})),!i&&!r.endsWith(`.dto.ts`)&&!r.endsWith(`.tsx`)&&t.report({node:n,message:`包含接口 "${a}" 的文件 "${r}" 应命名为 "${Se(r)}"`})}}}}),$=i({meta:{name:`@longzai-intelligence-oxlint/code-style-plugin`},rules:{"no-console":f,"no-inline-type-definition":H,"prefer-split-export-const":U,"require-interface-naming":Q,"require-dto-naming":Z,"require-class-suffix":J,"no-class-suffix-alias":l,"no-handwritten-shebang":v}});export{W as SUFFIX_MAPPINGS,$ as codeStylePlugin,$ as default,P as getInlineTypeDescription,F as getParamName,e as hasIPrefix,N as hasInlineType,Y as isDtoFile,O as isFunctionNode,k as isMethodDefinition,w as isTSFunctionType,E as isTSIntersectionType,C as isTSTypeLiteral,T as isTSUnionType,l as noClassSuffixAliasRule,f as noConsoleRule,v as noHandwrittenShebangRule,H as noInlineTypeDefinitionRule,U as preferSplitExportConstRule,J as requireClassSuffixRule,Z as requireDtoNamingRule,Q as requireInterfaceNamingRule};
|
|
1
|
+
import"../rolldown-runtime-BqT_7tdF.js";import"../rolldown-runtime-BqT_7tdF-BqT_7tdF.js";import{n as e,r as t,t as n}from"../dist-CskvMq7J.js";import{defineRule as r,eslintCompatPlugin as i}from"@oxlint/plugins";import{existsSync as a,readFileSync as ee}from"node:fs";import{dirname as o,join as te}from"node:path";import*as s from"zod/mini";function c(e){return e.endsWith(`Class`)}const l=r({meta:{type:`problem`,docs:{description:`禁止在 import 别名中使用 "Class" 后缀`}},createOnce(e){return{ImportSpecifier(t){let n=t.local.name,r=t.imported.type===`Identifier`?t.imported.name:n;n!==r&&c(n)&&e.report({node:t,message:`导入别名 "${n}" 使用了 "Class" 后缀,这是不允许的命名方式。请使用更具描述性的名称,或直接使用原始名称 "${r}"`})}}}}),u=/* @__PURE__ */ new Set([`console.log`,`console.warn`,`console.error`,`console.info`,`console.debug`,`console.trace`,`console.dir`,`console.table`]);function d(e){let t=e.callee;return t.type===`Identifier`?t.name:t.type===`MemberExpression`&&t.property.type===`Identifier`&&t.object.type===`Identifier`?`${t.object.name}.${t.property.name}`:null}const f=r({meta:{type:`problem`,docs:{description:`禁止使用 console 方法,必须使用 @longzai-intelligence/logger-preset-* 或 react-devtools(ADR 0038)`}},createOnce(e){return{CallExpression(t){if(t.type!==`CallExpression`)return;let n=d(t);n&&u.has(n)&&e.report({node:t,message:`检测到 '${n}' — 必须使用 @longzai-intelligence/logger-preset-* 代替(ADR 0038)`})}}}}),p=/\/src\/(index|main|cli)\.(ts|mts|cts)$/,m=/(^|\/)dist\//;function ne(e){return e.replace(/\\/g,`/`)}function h(e){return typeof e==`object`&&!!e}function re(e){return e.startsWith(`#!`)}function g(e){return p.test(ne(e))}function ie(e){let t=e;for(let e=0;e<4;e+=1){let e=te(t,`package.json`);if(a(e))try{let t=JSON.parse(ee(e,`utf8`));return h(t)?t:null}catch{return null}let n=o(t);if(n===t)break;t=n}return null}function ae(e){let t=e.bin;return(typeof t==`string`?[t]:h(t)?Object.values(t).filter(e=>typeof e==`string`):[]).some(e=>m.test(e.replace(/^\.\//,``)))}const oe={noHandwrittenShebang:`入口源码手写 shebang 属被裁定的错误方式,bin 产物首行 shebang 应由 "lzi-builder.config.ts" 的 banner 在构建期注入。请删除源码首行的 "#!" 行并补 banner 配置。`},_=r({meta:{type:`problem`,docs:{description:`禁止所属包 bin 指向 dist 产物的入口源码手写 shebang`}},createOnce(e){return{before(){let t=e.filename;if(!g(t))return!1},Program(t){let n=e.sourceCode.text;if(!re(n))return;let r=ie(o(o(e.filename)));r!==null&&ae(r)&&e.report({node:t,message:oe.noHandwrittenShebang})}}}}),v=s.object({type:s.literal(`TSTypeLiteral`)}),y=s.object({type:s.literal(`TSFunctionType`)}),b=s.object({type:s.literal(`TSUnionType`),types:s.array(s.unknown())}),se=s.object({type:s.literal(`TSIntersectionType`),types:s.array(s.unknown())}),ce=s.object({type:s.literal(`Identifier`),name:s.string()}),le=s.object({type:s.literal(`RestElement`),argument:s.object({name:s.string()})}),ue=s.union([ce,le]),x=s.object({typeAnnotation:s.unknown()}),de=s.object({type:s.literal(`MethodDefinition`),key:s.object({type:s.string(),name:s.optional(s.string())}),value:s.object({params:s.optional(s.array(s.unknown())),returnType:s.optional(s.union([x,s.null()]))}),kind:s.enum([`method`,`constructor`,`get`,`set`])}),fe=s.object({returnType:x}),pe=s.object({id:s.optional(s.object({name:s.optional(s.string())})),params:s.optional(s.array(s.unknown())),returnType:s.optional(s.unknown())}),me=s.object({params:s.optional(s.array(s.unknown()))});function S(e){return v.safeParse(e).success}function C(e){return y.safeParse(e).success}function w(e){return b.safeParse(e).success}function T(e){return se.safeParse(e).success}function E(e){return ue.safeParse(e).success}function D(e){if(typeof e!=`object`||!e||!(`type`in e))return!1;let t=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`MethodDefinition`],n=e.type;return typeof n==`string`&&t.includes(n)}function O(e){return de.safeParse(e).success}function k(e){return fe.safeParse(e).success}function A(e){return pe.safeParse(e).success}function j(e){return me.safeParse(e).success}function M(e){return S(e)||C(e)?!0:w(e)||T(e)?e.types.some(M):!1}function N(e){return S(e)?`对象类型`:C(e)?`函数类型`:`内联类型`}function P(e){return E(e)?e.type===`Identifier`?e.name:e.type===`RestElement`?e.argument.name:null:null}function F(e,t,n,r,i,a){i?e.report({node:t,message:`参数 "${n}" 使用了内联${r}定义。请将其提取为具名的 type。`}):a?e.report({node:t,message:`方法 "${a}" 的参数 "${n}" 使用了内联${r}定义。请将其提取为具名的 type。`}):e.report({node:t,message:`参数 "${n}" 使用了内联${r}定义。请将其提取为具名的 type。`})}function I(e,t,n,r,i){i?e.report({node:t,message:`方法 "${i}" 的返回值使用了内联${n}定义。请将其提取为具名的 type。`}):r?e.report({node:t,message:`函数 "${r}" 的返回值使用了内联${n}定义。请将其提取为具名的 type。`}):e.report({node:t,message:`匿名函数的返回值使用了内联${n}定义。请将其提取为具名的 type。`})}function L(e,t,n,r,i){if(typeof e!=`object`||!e||!(`typeAnnotation`in e)||e.typeAnnotation===null||typeof e.typeAnnotation!=`object`||!(`typeAnnotation`in e.typeAnnotation))return;let a=e.typeAnnotation.typeAnnotation;M(a)&&F(t,n,P(e)??`未知参数`,N(a),r,i)}function R(e,t,n,r,i){for(let a of e)L(a,t,n,i??!1,r)}function z(e,t,n,r,i){if(typeof e!=`object`||!e||!(`typeAnnotation`in e))return;let a=e.typeAnnotation;M(a)&&I(t,n,N(a),r,i)}function B(e,t){if(!D(e)||!A(e))return;let n=null;`id`in e&&e.id!==null&&typeof e.id==`object`&&`name`in e.id&&typeof e.id.name==`string`&&(n=e.id.name),j(e)&&R(e.params??[],t,e),k(e)&&z(e.returnType,t,e,n??void 0)}function he(e,t){D(e)&&j(e)&&(j(e)&&R(e.params??[],t,e),k(e)&&z(e.returnType,t,e))}function ge(e,t){if(!O(e))return;let n=e.key,r=n&&`name`in n&&typeof n.name==`string`?n.name:`未知方法`,i=e.value;if(i&&`params`in i&&Array.isArray(i.params)&&R(i.params,t,e,r,e.kind===`constructor`),i&&`returnType`in i&&i.returnType&&typeof i.returnType==`object`&&`typeAnnotation`in i.returnType){let n=i.returnType;z(n,t,e,void 0,r)}}const V=r({meta:{type:`suggestion`,docs:{description:`禁止在函数参数和返回值中使用内联类型定义,强制使用具名类型`}},createOnce(e){return{FunctionDeclaration(t){B(t,e)},FunctionExpression(t){B(t,e)},ArrowFunctionExpression(t){he(t,e)},MethodDefinition(t){ge(t,e)}}}}),H=/^(?:eslint-disable(?:-next-line|-line)?|eslint-enable|oxlint-disable(?:-next-line|-line)?|oxlint-enable|biome-ignore|stylelint-disable(?:-next-line|-line)?|stylelint-enable|@ts-ignore|@ts-nocheck)(?=[\s,]|$)/;function _e(e){let t=e.trimStart();return H.exec(t)?.[0]??null}const U=r({meta:{type:`problem`,docs:{description:`禁止 eslint-disable、oxlint-disable、biome-ignore、stylelint-disable、@ts-ignore、@ts-nocheck 等抑制注释`}},createOnce(e){return{Program(){let t=e.sourceCode.getAllComments();for(let n of t){if(n.type===`Shebang`)continue;let t=_e(n.value);t!==null&&e.report({node:n,message:`检测到抑制指令 ${t},抑制注释不是合法豁免手段,请从源头消除违例或在包级 oxlint.config.ts 的 ignorePatterns 登记路径豁免`})}}}}});function ve(e){let t=[];if(e.type===`Identifier`&&t.push(e.name),e.type===`ObjectPattern`)for(let n of e.properties)n.type===`Property`&&`value`in n?n.value.type===`Identifier`&&t.push(n.value.name):n.type===`RestElement`&&n.argument.type===`Identifier`&&t.push(n.argument.name);if(e.type===`ArrayPattern`)for(let n of e.elements)n&&n.type===`Identifier`&&t.push(n.name);return t}const W=r({meta:{type:`suggestion`,docs:{description:`将 export const/let/var 拆分为独立的声明和导出语句`}},createOnce(e){return{ExportNamedDeclaration(t){if(!t.declaration||t.declaration.type!==`VariableDeclaration`)return;let n=t.declaration;if(n.kind!==`const`&&n.kind!==`let`&&n.kind!==`var`||n.declarations.length===0)return;let r=[];for(let e of n.declarations)r.push(...ve(e.id));r.length!==0&&e.report({node:t,message:`应将 \`export ${n.kind} ${r.join(`, `)}\` 拆分为独立的声明和导出语句`})}}}}),G=[{suffix:`.service.drizzle.ts`,classSuffix:`Service`,isInterface:!1,isPrefix:!1},{suffix:`.service.memory.ts`,classSuffix:`Service`,isInterface:!1,isPrefix:!1},{suffix:`.service.ts`,classSuffix:`Service`,isInterface:!1,isPrefix:!1},{suffix:`.controller.ts`,classSuffix:`Controller`,isInterface:!1,isPrefix:!1},{suffix:`.module.ts`,classSuffix:`Module`,isInterface:!1,isPrefix:!1},{suffix:`.repository.drizzle.ts`,classSuffix:`Repository`,isInterface:!1,isPrefix:!1},{suffix:`.repository.memory.ts`,classSuffix:`Repository`,isInterface:!1,isPrefix:!1},{suffix:`.repository.interface.ts`,classSuffix:`Repository`,isInterface:!0,isPrefix:!0},{suffix:`.repository.ts`,classSuffix:`Repository`,isInterface:!1,isPrefix:!1},{suffix:`.entity.ts`,classSuffix:`Entity`,isInterface:!1,isPrefix:!1},{suffix:`.orm-entity.ts`,classSuffix:`OrmEntity`,isInterface:!1,isPrefix:!1},{suffix:`.dto.ts`,classSuffix:`DTO`,isInterface:!1,isPrefix:!1},{suffix:`.port.interface.ts`,classSuffix:`Port`,isInterface:!0,isPrefix:!0},{suffix:`.interface.ts`,classSuffix:``,isInterface:!0,isPrefix:!0},{suffix:`.port.ts`,classSuffix:`Port`,isInterface:!0,isPrefix:!1},{suffix:`.port.adapter.ts`,classSuffix:`PortAdapter`,isInterface:!1,isPrefix:!1},{suffix:`.adapter.ts`,classSuffix:`Adapter`,isInterface:!1,isPrefix:!1},{suffix:`.events.ts`,classSuffix:`Event`,isInterface:!1,isPrefix:!1},{suffix:`.mapper.ts`,classSuffix:`Mapper`,isInterface:!1,isPrefix:!1},{suffix:`.vo.ts`,classSuffix:`VO`,isInterface:!1,isPrefix:!1},{suffix:`.usecase.ts`,classSuffix:`UseCase`,isInterface:!1,isPrefix:!1},{suffix:`.errors.ts`,classSuffix:`Error`,isInterface:!1,isPrefix:!1}];function K(e){for(let t of G)if(e.endsWith(t.suffix))return t;return null}function q(e,t){if(t.isPrefix&&t.isInterface){if(t.classSuffix){let n=t.classSuffix;return e.startsWith(`I`)&&e.endsWith(n)&&e.length>1+n.length}return e.startsWith(`I`)&&e.length>1}return t.isPrefix?e.startsWith(`I`)&&e.length>1:e.endsWith(t.classSuffix)&&e.length>t.classSuffix.length}function J(e){return e.isPrefix&&e.isInterface?e.classSuffix?`I${e.classSuffix}(如 IUser${e.classSuffix})`:`I 前缀(如 IUser)`:e.isPrefix?`I 前缀(如 IUser)`:`${e.classSuffix} 后缀`}const Y=r({meta:{type:`problem`,docs:{description:`强制执行类名与文件类型后缀的一致性`}},createOnce(e){return{before(){let t=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``;if(t.endsWith(`.test.ts`)||t.endsWith(`.spec.ts`)||!K(t))return!1},ClassDeclaration(t){let n=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``,r=K(n);if(!r||r.isInterface||!t.id)return;let i=t.id.name;q(i,r)||e.report({node:t,message:`类名 "${i}" 不符合命名规范。文件 "${n}" 中的类应使用 ${J(r)}`})},TSInterfaceDeclaration(t){let n=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``,r=K(n);if(!r||!r.isInterface)return;let i=t.id.name;q(i,r)||e.report({node:t,message:`接口名 "${i}" 不符合命名规范。文件 "${n}" 中的接口应使用 ${J(r)}`})}}}});function X(e){return e.endsWith(`.dto.ts`)}function ye(e){return e.endsWith(`DTO`)}const Z=r({meta:{type:`problem`,docs:{description:`强制执行 DTO 文件中的接口命名规范(Dto 后缀,驼峰式)`}},createOnce(e){return{before(){let t=e.filename.replace(/\\/g,`/`).split(`/`).pop()??``;if(t.endsWith(`.test.ts`)||t.endsWith(`.spec.ts`)||!X(t))return!1},TSInterfaceDeclaration(n){let r=n.id.name;ye(r)?e.report({node:n,message:`接口名 "${r}" 后缀应使用 Dto(驼峰式)而非 DTO(全大写)`}):t(r)||e.report({node:n,message:`DTO 文件中的接口名 "${r}" 应以 Dto 结尾(如 UserResponseDto)`})}}}}),be=[`types.ts`,`types.d.ts`],xe=[`.port.interface.ts`,`.repository.interface.ts`,`.types.ts`,`.types.d.ts`,`.events.ts`,`.d.ts`];function Se(t,r){return e(t)?!1:!r.endsWith(`.dto.ts`)||n(t)}function Ce(e){return e.endsWith(`.dto.ts`)?`DTO 后缀(如 UserDTO),禁止 I 前缀`:`PascalCase(如 User、UserRepository),禁止 I 前缀`}function we(e){if(be.includes(e))return!0;for(let t of xe)if(e.endsWith(t))return!0;return!1}function Te(e){return e.endsWith(`.port.ts`)?e.replace(`.port.ts`,`.port.interface.ts`):e.endsWith(`.repository.ts`)?e.replace(`.repository.ts`,`.repository.interface.ts`):e.replace(`.ts`,`.interface.ts`)}const Q=r({meta:{type:`problem`,docs:{description:`强制执行接口命名规范(禁止 I 前缀,使用 PascalCase)和文件命名规范`}},createOnce(t){return{before(){let e=t.filename.replace(/\\/g,`/`).split(`/`).pop()??``;if(e.endsWith(`.test.ts`)||e.endsWith(`.spec.ts`)||we(e))return!1},TSInterfaceDeclaration(n){let r=t.filename.replace(/\\/g,`/`).split(`/`).pop()??``,i=r.endsWith(`.interface.ts`)||r.endsWith(`.interface.tsx`),a=n.id.name;Se(a,r)||(e(a)?t.report({node:n,message:`接口名 "${a}" 使用了 I 前缀。现代 TypeScript 不推荐使用匈牙利命名法,建议使用 "${a.substring(1)}"`}):r.endsWith(`.dto.ts`)&&a.endsWith(`Dto`)?t.report({node:n,message:`接口名 "${a}" 后缀应使用 DTO(全大写)而非 Dto(驼峰式)`}):t.report({node:n,message:`接口名 "${a}" 不符合命名规范。接口名应使用 ${Ce(r)}`})),!i&&!r.endsWith(`.dto.ts`)&&!r.endsWith(`.tsx`)&&t.report({node:n,message:`包含接口 "${a}" 的文件 "${r}" 应命名为 "${Te(r)}"`})}}}}),$=i({meta:{name:`@longzai-intelligence-oxlint/code-style-plugin`},rules:{"no-console":f,"no-inline-type-definition":V,"prefer-split-export-const":W,"require-interface-naming":Q,"require-dto-naming":Z,"require-class-suffix":Y,"no-class-suffix-alias":l,"no-handwritten-shebang":_,"no-lint-suppression":U}});export{G as SUFFIX_MAPPINGS,$ as codeStylePlugin,$ as default,N as getInlineTypeDescription,P as getParamName,e as hasIPrefix,M as hasInlineType,X as isDtoFile,D as isFunctionNode,O as isMethodDefinition,C as isTSFunctionType,T as isTSIntersectionType,S as isTSTypeLiteral,w as isTSUnionType,l as noClassSuffixAliasRule,f as noConsoleRule,_ as noHandwrittenShebangRule,V as noInlineTypeDefinitionRule,U as noLintSuppressionRule,W as preferSplitExportConstRule,Y as requireClassSuffixRule,Z as requireDtoNamingRule,Q as requireInterfaceNamingRule};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longzai-intelligence-oxlint/presets",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Longzai Intelligence oxlint 配置预设",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"config",
|
|
@@ -100,33 +100,33 @@
|
|
|
100
100
|
"zod": "^4.4.3"
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@longzai-intelligence-oxlint/architecture-core-plugin": "0.2.
|
|
104
|
-
"@longzai-intelligence-oxlint/architecture-electron-plugin": "0.2.
|
|
105
|
-
"@longzai-intelligence-oxlint/architecture-library-plugin": "0.2.
|
|
106
|
-
"@longzai-intelligence-oxlint/code-style-plugin": "0.2.
|
|
107
|
-
"@longzai-intelligence-oxlint/composer-plugin": "0.2.
|
|
108
|
-
"@longzai-intelligence-oxlint/core": "0.2.
|
|
109
|
-
"@longzai-intelligence-oxlint/design-rules-plugin": "0.2.
|
|
110
|
-
"@longzai-intelligence-oxlint/elysia-route-plugin": "0.2.
|
|
111
|
-
"@longzai-intelligence-oxlint/eslint-config-plugin": "0.2.
|
|
112
|
-
"@longzai-intelligence-oxlint/file-naming-plugin": "0.2.
|
|
113
|
-
"@longzai-intelligence-oxlint/lzi-builder-config-plugin": "0.2.
|
|
114
|
-
"@longzai-intelligence-oxlint/lzi-config-plugin": "0.2.
|
|
115
|
-
"@longzai-intelligence-oxlint/nestjs-route-plugin": "0.2.
|
|
116
|
-
"@longzai-intelligence-oxlint/package-json-plugin": "0.2.
|
|
117
|
-
"@longzai-intelligence-oxlint/perfectionist-plugin": "0.2.
|
|
118
|
-
"@longzai-intelligence-oxlint/react-plugin": "0.2.
|
|
119
|
-
"@longzai-intelligence-oxlint/schema-type-separation-plugin": "0.2.
|
|
120
|
-
"@longzai-intelligence-oxlint/stylistic-plugin": "0.2.
|
|
121
|
-
"@longzai-intelligence-oxlint/tsconfig-plugin": "0.2.
|
|
122
|
-
"@longzai-intelligence-oxlint/tsdoc-plugin": "0.2.
|
|
123
|
-
"@longzai-intelligence-oxlint/tsdown-config-plugin": "0.2.
|
|
124
|
-
"@longzai-intelligence-oxlint/tsup-config-plugin": "0.2.
|
|
125
|
-
"@longzai-intelligence-oxlint/typeorm-plugin": "0.2.
|
|
126
|
-
"@longzai-intelligence-oxlint/typescript-eslint-plugin": "0.2.
|
|
127
|
-
"@longzai-intelligence-oxlint/utils": "0.2.
|
|
128
|
-
"@longzai-intelligence-oxlint/vitest-config-plugin": "0.2.
|
|
129
|
-
"@longzai-intelligence-oxlint/zod-plugin": "0.2.
|
|
103
|
+
"@longzai-intelligence-oxlint/architecture-core-plugin": "0.2.3",
|
|
104
|
+
"@longzai-intelligence-oxlint/architecture-electron-plugin": "0.2.3",
|
|
105
|
+
"@longzai-intelligence-oxlint/architecture-library-plugin": "0.2.3",
|
|
106
|
+
"@longzai-intelligence-oxlint/code-style-plugin": "0.2.3",
|
|
107
|
+
"@longzai-intelligence-oxlint/composer-plugin": "0.2.3",
|
|
108
|
+
"@longzai-intelligence-oxlint/core": "0.2.3",
|
|
109
|
+
"@longzai-intelligence-oxlint/design-rules-plugin": "0.2.3",
|
|
110
|
+
"@longzai-intelligence-oxlint/elysia-route-plugin": "0.2.3",
|
|
111
|
+
"@longzai-intelligence-oxlint/eslint-config-plugin": "0.2.3",
|
|
112
|
+
"@longzai-intelligence-oxlint/file-naming-plugin": "0.2.3",
|
|
113
|
+
"@longzai-intelligence-oxlint/lzi-builder-config-plugin": "0.2.3",
|
|
114
|
+
"@longzai-intelligence-oxlint/lzi-config-plugin": "0.2.3",
|
|
115
|
+
"@longzai-intelligence-oxlint/nestjs-route-plugin": "0.2.3",
|
|
116
|
+
"@longzai-intelligence-oxlint/package-json-plugin": "0.2.3",
|
|
117
|
+
"@longzai-intelligence-oxlint/perfectionist-plugin": "0.2.3",
|
|
118
|
+
"@longzai-intelligence-oxlint/react-plugin": "0.2.3",
|
|
119
|
+
"@longzai-intelligence-oxlint/schema-type-separation-plugin": "0.2.3",
|
|
120
|
+
"@longzai-intelligence-oxlint/stylistic-plugin": "0.2.3",
|
|
121
|
+
"@longzai-intelligence-oxlint/tsconfig-plugin": "0.2.3",
|
|
122
|
+
"@longzai-intelligence-oxlint/tsdoc-plugin": "0.2.3",
|
|
123
|
+
"@longzai-intelligence-oxlint/tsdown-config-plugin": "0.2.3",
|
|
124
|
+
"@longzai-intelligence-oxlint/tsup-config-plugin": "0.2.3",
|
|
125
|
+
"@longzai-intelligence-oxlint/typeorm-plugin": "0.2.3",
|
|
126
|
+
"@longzai-intelligence-oxlint/typescript-eslint-plugin": "0.2.3",
|
|
127
|
+
"@longzai-intelligence-oxlint/utils": "0.2.3",
|
|
128
|
+
"@longzai-intelligence-oxlint/vitest-config-plugin": "0.2.3",
|
|
129
|
+
"@longzai-intelligence-oxlint/zod-plugin": "0.2.3",
|
|
130
130
|
"@vitest/coverage-v8": "^4.1.10"
|
|
131
131
|
},
|
|
132
132
|
"peerDependencies": {
|