@lark-apaas/fullstack-presets 1.1.25 → 1.1.26-alpha.20260929135803
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/README.md +20 -0
- package/lib/custom-eslint-rules/require-number-wrapped-count.d.ts +4 -6
- package/lib/custom-eslint-rules/require-number-wrapped-count.js +5 -56
- package/lib/simple/recommend/eslint/eslint-server.d.ts +0 -1
- package/lib/simple/recommend/eslint/eslint-server.js +12 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
|
|
4
4
|
## ESLint 自定义规则
|
|
5
5
|
|
|
6
|
+
### `require-number-wrapped-count`(已弃用)
|
|
7
|
+
|
|
8
|
+
从本变更发布的新版 `@lark-apaas/fullstack-presets` 起,`eslintPresetsOfSimple.server` 不再默认启用 `@lark-apaas/require-number-wrapped-count`。公开规则 ID 仍可解析,但已标记 deprecated 且不再报告错误;这只是 **ID 的语法兼容,不是旧告警行为兼容**。旧包的精确锁定版本(如 1.1.25)不会因新包发布自动改变行为。
|
|
9
|
+
|
|
10
|
+
Drizzle 0.44.6 中 `count()` 是 `SQL<number>`,已通过 `.mapWith(Number)` 映射读回结果,可直接作为 SQLWrapper 用于 select 字段及排序表达式:
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
import { asc, count, desc } from 'drizzle-orm';
|
|
14
|
+
|
|
15
|
+
db.select({ total: count() }).from(users);
|
|
16
|
+
db.select().from(users).orderBy(desc(count()));
|
|
17
|
+
db.select().from(users).orderBy(asc(count()));
|
|
18
|
+
const expression = count(users.id);
|
|
19
|
+
db.select({ total: expression }).from(users).orderBy(desc(expression));
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
不要为 SQL 排序写 `Number(count())`:这会在 JS 阶段转换 SQL 对象,而不是生成数据库的 `count(*) desc`。**只有读取已有原生 SQL 表达式的 driver 返回值时**(例如 ``sql`count(*)` ``),才依据字段类型、驱动和精度需求决定 `.mapWith(Number)`、BigInt 等映射;这不是用原生 SQL 替换 `count()` helper 的建议。
|
|
23
|
+
|
|
24
|
+
**显式 opt-in 迁移**:若项目使用 Drizzle 0.44.6 且有 TypeScript 类型检查(例如 `tsc` / `type:check`),删除 ESLint 配置中显式的 `@lark-apaas/require-number-wrapped-count` 条目,而不是改成 warn 或依照旧报错把 count 强制包在 Number 中。非法的 `const n: number = count()`、`desc(Number(count()))` 等有类型的 JS 数值用法由现有 TypeScript 检查负责;`any` / JS 绕开类型系统时不保证被检测。使用其它未核实的 Drizzle 版本、或缺少类型守护的旧项目,先保留**当前旧精确包版本**,确认该版本的 count/驱动合同与可用检查,再决定升级/删除 opt-in;不能将新版空壳当作旧规则保护。未来若要删除公开 ID,需要另走弃用流程。
|
|
25
|
+
|
|
6
26
|
### `no-nested-styled-jsx`
|
|
7
27
|
|
|
8
28
|
检测嵌套的 styled-jsx 标签,防止编译错误。https://nextjs.org/docs/messages/nested-styled-jsx-tags
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 通过 import 追踪确认 count 来自 drizzle-orm,避免误匹配其他 count 函数。
|
|
2
|
+
* Deprecated compatibility shell for the published rule ID. In Drizzle 0.44.6,
|
|
3
|
+
* count() is a SQL<number> expression, not a JS value requiring Number(count()).
|
|
4
|
+
* Keep the ID registered so older explicit configurations remain parseable;
|
|
5
|
+
* it intentionally does not preserve the old diagnostics.
|
|
8
6
|
*/
|
|
9
7
|
import type { Rule } from 'eslint';
|
|
10
8
|
declare const rule: Rule.RuleModule;
|
|
@@ -2,66 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const rule = {
|
|
4
4
|
meta: {
|
|
5
|
-
|
|
5
|
+
deprecated: true,
|
|
6
6
|
docs: {
|
|
7
|
-
description: '
|
|
8
|
-
|
|
9
|
-
recommended: true,
|
|
7
|
+
description: 'Deprecated compatibility rule ID; no longer reports violations',
|
|
8
|
+
recommended: false,
|
|
10
9
|
},
|
|
11
10
|
schema: [],
|
|
12
|
-
messages: {
|
|
13
|
-
unwrappedCount: 'Drizzle count() returns string in postgres-js. Wrap with Number(count(...)) to get a numeric value.',
|
|
14
|
-
},
|
|
15
11
|
},
|
|
16
|
-
create(
|
|
17
|
-
|
|
18
|
-
const drizzleCountNames = new Set();
|
|
19
|
-
return {
|
|
20
|
-
// 收集 import { count } from 'drizzle-orm' 或 import { count as x } from 'drizzle-orm'
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
-
ImportDeclaration(node) {
|
|
23
|
-
if (node.source.value !== 'drizzle-orm' &&
|
|
24
|
-
!node.source.value.startsWith('drizzle-orm/')) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
for (const specifier of node.specifiers) {
|
|
28
|
-
if (specifier.type === 'ImportSpecifier' &&
|
|
29
|
-
specifier.imported.name === 'count') {
|
|
30
|
-
drizzleCountNames.add(specifier.local.name);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
// 检查 count() 调用是否被 Number(...) 包裹
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
-
CallExpression(node) {
|
|
37
|
-
// 是否是 count(...) 调用
|
|
38
|
-
if (node.callee.type !== 'Identifier' ||
|
|
39
|
-
!drizzleCountNames.has(node.callee.name)) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
// 检查父节点是否是 Number(count(...))
|
|
43
|
-
const parent = node.parent;
|
|
44
|
-
if (parent &&
|
|
45
|
-
parent.type === 'CallExpression' &&
|
|
46
|
-
parent.callee.type === 'Identifier' &&
|
|
47
|
-
parent.callee.name === 'Number') {
|
|
48
|
-
return; // 已包裹
|
|
49
|
-
}
|
|
50
|
-
// 检查是否在对象属性值位置且 key 是 count(如 { count: count() })
|
|
51
|
-
// 这种场景下 count() 是 select 的字段定义,不是直接赋值,跳过
|
|
52
|
-
if (parent &&
|
|
53
|
-
parent.type === 'Property' &&
|
|
54
|
-
parent.value === node) {
|
|
55
|
-
// 但如果整个 select result 后来被直接当 number 用,那是使用侧的问题
|
|
56
|
-
// 这里只检查 count() 的直接调用位置
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
context.report({
|
|
60
|
-
node,
|
|
61
|
-
messageId: 'unwrappedCount',
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
};
|
|
12
|
+
create() {
|
|
13
|
+
return {};
|
|
65
14
|
},
|
|
66
15
|
};
|
|
67
16
|
exports.default = rule;
|
|
@@ -53,7 +53,6 @@ declare const _default: {
|
|
|
53
53
|
'@darraghor/nestjs-typed/api-method-should-specify-api-operation': string;
|
|
54
54
|
'@darraghor/nestjs-typed/api-enum-property-best-practices': string;
|
|
55
55
|
'@darraghor/nestjs-typed/all-properties-are-whitelisted': string;
|
|
56
|
-
'@lark-apaas/require-number-wrapped-count': string;
|
|
57
56
|
'@lark-apaas/require-shared-response-type': string;
|
|
58
57
|
'no-restricted-syntax': (string | {
|
|
59
58
|
selector: string;
|
|
@@ -52,7 +52,10 @@ exports.default = {
|
|
|
52
52
|
{
|
|
53
53
|
patterns: [
|
|
54
54
|
{
|
|
55
|
-
group: [
|
|
55
|
+
group: [
|
|
56
|
+
'@lark-apaas/client-toolkit',
|
|
57
|
+
'@lark-apaas/client-toolkit/*',
|
|
58
|
+
],
|
|
56
59
|
message: 'This toolkit is for client-side use only and must not be imported or used in server-side code.',
|
|
57
60
|
},
|
|
58
61
|
],
|
|
@@ -63,7 +66,13 @@ exports.default = {
|
|
|
63
66
|
{
|
|
64
67
|
src: ['./server/**/*.ts'],
|
|
65
68
|
// 此规则自行扫描文件,不遵循 ESLint ignores;保留默认过滤并排除独立 MCP UI 工程。
|
|
66
|
-
filterFromPaths: [
|
|
69
|
+
filterFromPaths: [
|
|
70
|
+
'dist',
|
|
71
|
+
'node_modules',
|
|
72
|
+
'.test.',
|
|
73
|
+
'.spec.',
|
|
74
|
+
'server/mcp/ui/',
|
|
75
|
+
],
|
|
67
76
|
},
|
|
68
77
|
],
|
|
69
78
|
'@darraghor/nestjs-typed/api-property-returning-array-should-set-array': 'off',
|
|
@@ -75,15 +84,13 @@ exports.default = {
|
|
|
75
84
|
'@darraghor/nestjs-typed/api-method-should-specify-api-operation': 'off',
|
|
76
85
|
'@darraghor/nestjs-typed/api-enum-property-best-practices': 'off',
|
|
77
86
|
'@darraghor/nestjs-typed/all-properties-are-whitelisted': 'off',
|
|
78
|
-
// 自定义规则:Drizzle count() 必须 Number() 包裹
|
|
79
|
-
'@lark-apaas/require-number-wrapped-count': 'error',
|
|
80
87
|
// 自定义规则:Controller 返回类型必须定义在 shared/(默认关闭,需 y 位升级后对新应用开启)
|
|
81
88
|
'@lark-apaas/require-shared-response-type': 'off',
|
|
82
89
|
// Drizzle ORM 规则
|
|
83
90
|
'no-restricted-syntax': [
|
|
84
91
|
'error',
|
|
85
92
|
{
|
|
86
|
-
selector:
|
|
93
|
+
selector: 'CallExpression[callee.property.name=/^(values|set)$/] Property[key.name=/^(_created_at|_updated_at|_created_by|_updated_by)$/]',
|
|
87
94
|
message: 'Audit columns (_created_at/_updated_at/_created_by/_updated_by) are auto-populated by the platform. Do not set them in .values() or .set() calls.',
|
|
88
95
|
},
|
|
89
96
|
],
|