@thornfe/jql2iql 0.0.1
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/LICENSE +21 -0
- package/README.md +248 -0
- package/dist/index.cjs +1532 -0
- package/dist/index.d.cts +221 -0
- package/dist/index.d.mts +221 -0
- package/dist/index.mjs +1526 -0
- package/package.json +73 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { ParseTree } from "antlr4ts/tree/ParseTree";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* JQL AST 节点类型定义
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 基础 AST 节点
|
|
9
|
+
*/
|
|
10
|
+
interface BaseASTNode {
|
|
11
|
+
type: string;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 二元表达式节点 (如: field = value, field in list)
|
|
16
|
+
*/
|
|
17
|
+
interface BinaryExpression extends BaseASTNode {
|
|
18
|
+
type: 'BinaryExpression';
|
|
19
|
+
operator: string;
|
|
20
|
+
left: ASTNode;
|
|
21
|
+
right: ASTNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 逻辑表达式节点 (如: expr AND expr, expr OR expr, NOT expr)
|
|
25
|
+
*/
|
|
26
|
+
interface LogicalExpression extends BaseASTNode {
|
|
27
|
+
type: 'LogicalExpression';
|
|
28
|
+
operator: 'AND' | 'OR' | 'NOT';
|
|
29
|
+
left: ASTNode;
|
|
30
|
+
right?: ASTNode;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 字段节点 (如: project, status, issuetype)
|
|
34
|
+
*/
|
|
35
|
+
interface Field extends BaseASTNode {
|
|
36
|
+
type: 'Field';
|
|
37
|
+
value: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 字面量节点 (如: "value", 123, Done)
|
|
41
|
+
*/
|
|
42
|
+
interface Literal extends BaseASTNode {
|
|
43
|
+
type: 'Literal';
|
|
44
|
+
value: string | number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 标识符节点
|
|
48
|
+
*/
|
|
49
|
+
interface Identifier extends BaseASTNode {
|
|
50
|
+
type: 'Identifier';
|
|
51
|
+
value: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 列表节点 (如: (value1, value2, value3))
|
|
55
|
+
*/
|
|
56
|
+
interface List extends BaseASTNode {
|
|
57
|
+
type: 'List';
|
|
58
|
+
elements: ASTNode[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 函数节点 (如: currentUser(), membersOf("group"))
|
|
62
|
+
*/
|
|
63
|
+
interface FunctionNode extends BaseASTNode {
|
|
64
|
+
type: 'Function';
|
|
65
|
+
name: string;
|
|
66
|
+
arguments: any[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 排序方向
|
|
70
|
+
*/
|
|
71
|
+
type OrderDirection = 'ASC' | 'DESC';
|
|
72
|
+
/**
|
|
73
|
+
* 排序字段节点 (如: priority DESC, updated ASC)
|
|
74
|
+
*/
|
|
75
|
+
interface OrderByField extends BaseASTNode {
|
|
76
|
+
type: 'OrderByField';
|
|
77
|
+
field: string;
|
|
78
|
+
direction: OrderDirection;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* ORDER BY 子句节点
|
|
82
|
+
*/
|
|
83
|
+
interface OrderByClause extends BaseASTNode {
|
|
84
|
+
type: 'OrderByClause';
|
|
85
|
+
fields: OrderByField[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 完整的 JQL 查询结构
|
|
89
|
+
*/
|
|
90
|
+
interface JQLQuery extends BaseASTNode {
|
|
91
|
+
type: 'JQLQuery';
|
|
92
|
+
where: ASTNode | null;
|
|
93
|
+
orderBy: OrderByClause | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 联合类型:所有可能的 AST 节点类型
|
|
97
|
+
*/
|
|
98
|
+
type ASTNode = BinaryExpression | LogicalExpression | Field | Literal | Identifier | List | FunctionNode | OrderByField | OrderByClause | JQLQuery;
|
|
99
|
+
/**
|
|
100
|
+
* Jira 字段类型键
|
|
101
|
+
*/
|
|
102
|
+
type FieldTypeKey = 'createdBy' | 'updatedBy' | 'Assignee' | 'Reporter' | 'User' | 'Status' | 'Version' | 'CustomVersion' | 'Sprint' | 'Priority' | 'Workspace' | 'ItemType' | 'Name' | 'Text' | 'LongText' | 'Key' | 'StoryPoint' | 'Number' | 'Date' | 'updatedAt' | 'createdAt' | 'UserGroup' | 'Tree' | 'Tag' | 'Cascade' | 'Checkbox' | 'Dropdown' | 'Radio' | 'HyperLink' | 'BindWorkspace' | 'StatusType' | 'File';
|
|
103
|
+
/**
|
|
104
|
+
* Jira 字段映射配置
|
|
105
|
+
*/
|
|
106
|
+
interface JiraFieldConfig {
|
|
107
|
+
objectId: string;
|
|
108
|
+
customFieldKey: string;
|
|
109
|
+
fieldTypeKey: FieldTypeKey;
|
|
110
|
+
fieldTypeId?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Jira 字段映射表
|
|
114
|
+
*/
|
|
115
|
+
type JiraFieldMap = Record<string, JiraFieldConfig>;
|
|
116
|
+
/**
|
|
117
|
+
* 常量映射配置
|
|
118
|
+
*/
|
|
119
|
+
interface ConstantsMap {
|
|
120
|
+
/**
|
|
121
|
+
* 项目映射:JQL project key -> IQL 空间名称
|
|
122
|
+
*/
|
|
123
|
+
projectMap?: Record<string, string>;
|
|
124
|
+
/**
|
|
125
|
+
* 版本映射:JQL 版本名称 -> IQL 版本 objectId 数组
|
|
126
|
+
*/
|
|
127
|
+
versionMap?: Record<string, string[]>;
|
|
128
|
+
/**
|
|
129
|
+
* 模块映射:JQL component 名称 -> IQL 模块 objectId
|
|
130
|
+
*/
|
|
131
|
+
component?: Record<string, string>;
|
|
132
|
+
/**
|
|
133
|
+
* 级联选项映射:cascadeOption value -> label
|
|
134
|
+
* 例如:{ "10011": "广东" }
|
|
135
|
+
*/
|
|
136
|
+
cascade?: Record<string, string>;
|
|
137
|
+
/**
|
|
138
|
+
* 字段映射配置
|
|
139
|
+
*/
|
|
140
|
+
fieldMap?: JiraFieldMap;
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/field-transformer.d.ts
|
|
144
|
+
/**
|
|
145
|
+
* 原始字段对象接口
|
|
146
|
+
*/
|
|
147
|
+
interface RawField {
|
|
148
|
+
key: string;
|
|
149
|
+
name: string;
|
|
150
|
+
objectId: string;
|
|
151
|
+
fieldType: {
|
|
152
|
+
objectId: string;
|
|
153
|
+
};
|
|
154
|
+
data?: {
|
|
155
|
+
customData?: Array<{
|
|
156
|
+
label?: string;
|
|
157
|
+
value?: string;
|
|
158
|
+
title?: string;
|
|
159
|
+
}>;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 将原始字段数组转换为 ConstantsMap 格式
|
|
164
|
+
* 这个函数应该在外部调用一次,然后重复使用返回的 ConstantsMap 进行多次转换
|
|
165
|
+
*
|
|
166
|
+
* @param fields 原始字段数组
|
|
167
|
+
* @param projectMap 项目映射(可选)
|
|
168
|
+
* @param versionMap 版本映射(可选)
|
|
169
|
+
* @returns ConstantsMap 对象,可直接传给 jql2iql 使用
|
|
170
|
+
*/
|
|
171
|
+
declare function transformFieldsToConstantsMap(fields: RawField[], projectMap?: Record<string, string>, versionMap?: Record<string, string[]>): ConstantsMap;
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/jql-to-ast/parser-utils.d.ts
|
|
174
|
+
/**
|
|
175
|
+
* 遍历回调函数类型
|
|
176
|
+
* @param node 当前节点
|
|
177
|
+
* @param depth 当前深度
|
|
178
|
+
* @param parent 父节点
|
|
179
|
+
*/
|
|
180
|
+
type TraverseCallback = (node: ParseTree, depth: number, parent?: ParseTree) => void | boolean;
|
|
181
|
+
/**
|
|
182
|
+
* 遍历 JQL 解析树
|
|
183
|
+
* @param tree 解析树根节点
|
|
184
|
+
* @param callback 遍历回调函数,返回 false 可以跳过子节点
|
|
185
|
+
* @param depth 当前深度(内部使用)
|
|
186
|
+
* @param parent 父节点(内部使用)
|
|
187
|
+
*/
|
|
188
|
+
declare function traverseJQLTree(tree: ParseTree, callback: TraverseCallback, depth?: number, parent?: ParseTree): void;
|
|
189
|
+
/**
|
|
190
|
+
* 获取节点信息
|
|
191
|
+
*/
|
|
192
|
+
declare function getNodeInfo(node: ParseTree): {
|
|
193
|
+
type: 'rule' | 'terminal';
|
|
194
|
+
text: string;
|
|
195
|
+
ruleName?: string;
|
|
196
|
+
tokenType?: string;
|
|
197
|
+
};
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/jql-to-ast/ast-builder.d.ts
|
|
200
|
+
/**
|
|
201
|
+
* 将 JQL 解析树转换为精简的 AST
|
|
202
|
+
*/
|
|
203
|
+
declare function buildAST(node: ParseTree | undefined): ASTNode | null;
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/ast-to-iql/iql-converter.d.ts
|
|
206
|
+
/**
|
|
207
|
+
* 将 AST 节点转换为 IQL 查询字符串
|
|
208
|
+
*/
|
|
209
|
+
declare function astToIQL(ast: ASTNode, constantsMap: ConstantsMap): string;
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/index.d.ts
|
|
212
|
+
/**
|
|
213
|
+
* 解析 JQL 查询字符串为 AST
|
|
214
|
+
*/
|
|
215
|
+
declare function parseJQL(jqlText: string): ASTNode | null;
|
|
216
|
+
/**
|
|
217
|
+
* 将 JQL 转换为 IQL
|
|
218
|
+
*/
|
|
219
|
+
declare function jql2iql(jqlText: string, constantsMap: ConstantsMap): string;
|
|
220
|
+
//#endregion
|
|
221
|
+
export { ASTNode, BaseASTNode, BinaryExpression, ConstantsMap, Field, FieldTypeKey, FunctionNode, Identifier, JQLQuery, JiraFieldConfig, JiraFieldMap, List, Literal, LogicalExpression, OrderByClause, OrderByField, OrderDirection, type RawField, astToIQL, buildAST, getNodeInfo, jql2iql, parseJQL, transformFieldsToConstantsMap, traverseJQLTree };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { ParseTree } from "antlr4ts/tree/ParseTree";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* JQL AST 节点类型定义
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 基础 AST 节点
|
|
9
|
+
*/
|
|
10
|
+
interface BaseASTNode {
|
|
11
|
+
type: string;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 二元表达式节点 (如: field = value, field in list)
|
|
16
|
+
*/
|
|
17
|
+
interface BinaryExpression extends BaseASTNode {
|
|
18
|
+
type: 'BinaryExpression';
|
|
19
|
+
operator: string;
|
|
20
|
+
left: ASTNode;
|
|
21
|
+
right: ASTNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 逻辑表达式节点 (如: expr AND expr, expr OR expr, NOT expr)
|
|
25
|
+
*/
|
|
26
|
+
interface LogicalExpression extends BaseASTNode {
|
|
27
|
+
type: 'LogicalExpression';
|
|
28
|
+
operator: 'AND' | 'OR' | 'NOT';
|
|
29
|
+
left: ASTNode;
|
|
30
|
+
right?: ASTNode;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 字段节点 (如: project, status, issuetype)
|
|
34
|
+
*/
|
|
35
|
+
interface Field extends BaseASTNode {
|
|
36
|
+
type: 'Field';
|
|
37
|
+
value: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 字面量节点 (如: "value", 123, Done)
|
|
41
|
+
*/
|
|
42
|
+
interface Literal extends BaseASTNode {
|
|
43
|
+
type: 'Literal';
|
|
44
|
+
value: string | number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 标识符节点
|
|
48
|
+
*/
|
|
49
|
+
interface Identifier extends BaseASTNode {
|
|
50
|
+
type: 'Identifier';
|
|
51
|
+
value: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 列表节点 (如: (value1, value2, value3))
|
|
55
|
+
*/
|
|
56
|
+
interface List extends BaseASTNode {
|
|
57
|
+
type: 'List';
|
|
58
|
+
elements: ASTNode[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 函数节点 (如: currentUser(), membersOf("group"))
|
|
62
|
+
*/
|
|
63
|
+
interface FunctionNode extends BaseASTNode {
|
|
64
|
+
type: 'Function';
|
|
65
|
+
name: string;
|
|
66
|
+
arguments: any[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 排序方向
|
|
70
|
+
*/
|
|
71
|
+
type OrderDirection = 'ASC' | 'DESC';
|
|
72
|
+
/**
|
|
73
|
+
* 排序字段节点 (如: priority DESC, updated ASC)
|
|
74
|
+
*/
|
|
75
|
+
interface OrderByField extends BaseASTNode {
|
|
76
|
+
type: 'OrderByField';
|
|
77
|
+
field: string;
|
|
78
|
+
direction: OrderDirection;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* ORDER BY 子句节点
|
|
82
|
+
*/
|
|
83
|
+
interface OrderByClause extends BaseASTNode {
|
|
84
|
+
type: 'OrderByClause';
|
|
85
|
+
fields: OrderByField[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 完整的 JQL 查询结构
|
|
89
|
+
*/
|
|
90
|
+
interface JQLQuery extends BaseASTNode {
|
|
91
|
+
type: 'JQLQuery';
|
|
92
|
+
where: ASTNode | null;
|
|
93
|
+
orderBy: OrderByClause | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 联合类型:所有可能的 AST 节点类型
|
|
97
|
+
*/
|
|
98
|
+
type ASTNode = BinaryExpression | LogicalExpression | Field | Literal | Identifier | List | FunctionNode | OrderByField | OrderByClause | JQLQuery;
|
|
99
|
+
/**
|
|
100
|
+
* Jira 字段类型键
|
|
101
|
+
*/
|
|
102
|
+
type FieldTypeKey = 'createdBy' | 'updatedBy' | 'Assignee' | 'Reporter' | 'User' | 'Status' | 'Version' | 'CustomVersion' | 'Sprint' | 'Priority' | 'Workspace' | 'ItemType' | 'Name' | 'Text' | 'LongText' | 'Key' | 'StoryPoint' | 'Number' | 'Date' | 'updatedAt' | 'createdAt' | 'UserGroup' | 'Tree' | 'Tag' | 'Cascade' | 'Checkbox' | 'Dropdown' | 'Radio' | 'HyperLink' | 'BindWorkspace' | 'StatusType' | 'File';
|
|
103
|
+
/**
|
|
104
|
+
* Jira 字段映射配置
|
|
105
|
+
*/
|
|
106
|
+
interface JiraFieldConfig {
|
|
107
|
+
objectId: string;
|
|
108
|
+
customFieldKey: string;
|
|
109
|
+
fieldTypeKey: FieldTypeKey;
|
|
110
|
+
fieldTypeId?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Jira 字段映射表
|
|
114
|
+
*/
|
|
115
|
+
type JiraFieldMap = Record<string, JiraFieldConfig>;
|
|
116
|
+
/**
|
|
117
|
+
* 常量映射配置
|
|
118
|
+
*/
|
|
119
|
+
interface ConstantsMap {
|
|
120
|
+
/**
|
|
121
|
+
* 项目映射:JQL project key -> IQL 空间名称
|
|
122
|
+
*/
|
|
123
|
+
projectMap?: Record<string, string>;
|
|
124
|
+
/**
|
|
125
|
+
* 版本映射:JQL 版本名称 -> IQL 版本 objectId 数组
|
|
126
|
+
*/
|
|
127
|
+
versionMap?: Record<string, string[]>;
|
|
128
|
+
/**
|
|
129
|
+
* 模块映射:JQL component 名称 -> IQL 模块 objectId
|
|
130
|
+
*/
|
|
131
|
+
component?: Record<string, string>;
|
|
132
|
+
/**
|
|
133
|
+
* 级联选项映射:cascadeOption value -> label
|
|
134
|
+
* 例如:{ "10011": "广东" }
|
|
135
|
+
*/
|
|
136
|
+
cascade?: Record<string, string>;
|
|
137
|
+
/**
|
|
138
|
+
* 字段映射配置
|
|
139
|
+
*/
|
|
140
|
+
fieldMap?: JiraFieldMap;
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/field-transformer.d.ts
|
|
144
|
+
/**
|
|
145
|
+
* 原始字段对象接口
|
|
146
|
+
*/
|
|
147
|
+
interface RawField {
|
|
148
|
+
key: string;
|
|
149
|
+
name: string;
|
|
150
|
+
objectId: string;
|
|
151
|
+
fieldType: {
|
|
152
|
+
objectId: string;
|
|
153
|
+
};
|
|
154
|
+
data?: {
|
|
155
|
+
customData?: Array<{
|
|
156
|
+
label?: string;
|
|
157
|
+
value?: string;
|
|
158
|
+
title?: string;
|
|
159
|
+
}>;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 将原始字段数组转换为 ConstantsMap 格式
|
|
164
|
+
* 这个函数应该在外部调用一次,然后重复使用返回的 ConstantsMap 进行多次转换
|
|
165
|
+
*
|
|
166
|
+
* @param fields 原始字段数组
|
|
167
|
+
* @param projectMap 项目映射(可选)
|
|
168
|
+
* @param versionMap 版本映射(可选)
|
|
169
|
+
* @returns ConstantsMap 对象,可直接传给 jql2iql 使用
|
|
170
|
+
*/
|
|
171
|
+
declare function transformFieldsToConstantsMap(fields: RawField[], projectMap?: Record<string, string>, versionMap?: Record<string, string[]>): ConstantsMap;
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/jql-to-ast/parser-utils.d.ts
|
|
174
|
+
/**
|
|
175
|
+
* 遍历回调函数类型
|
|
176
|
+
* @param node 当前节点
|
|
177
|
+
* @param depth 当前深度
|
|
178
|
+
* @param parent 父节点
|
|
179
|
+
*/
|
|
180
|
+
type TraverseCallback = (node: ParseTree, depth: number, parent?: ParseTree) => void | boolean;
|
|
181
|
+
/**
|
|
182
|
+
* 遍历 JQL 解析树
|
|
183
|
+
* @param tree 解析树根节点
|
|
184
|
+
* @param callback 遍历回调函数,返回 false 可以跳过子节点
|
|
185
|
+
* @param depth 当前深度(内部使用)
|
|
186
|
+
* @param parent 父节点(内部使用)
|
|
187
|
+
*/
|
|
188
|
+
declare function traverseJQLTree(tree: ParseTree, callback: TraverseCallback, depth?: number, parent?: ParseTree): void;
|
|
189
|
+
/**
|
|
190
|
+
* 获取节点信息
|
|
191
|
+
*/
|
|
192
|
+
declare function getNodeInfo(node: ParseTree): {
|
|
193
|
+
type: 'rule' | 'terminal';
|
|
194
|
+
text: string;
|
|
195
|
+
ruleName?: string;
|
|
196
|
+
tokenType?: string;
|
|
197
|
+
};
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/jql-to-ast/ast-builder.d.ts
|
|
200
|
+
/**
|
|
201
|
+
* 将 JQL 解析树转换为精简的 AST
|
|
202
|
+
*/
|
|
203
|
+
declare function buildAST(node: ParseTree | undefined): ASTNode | null;
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/ast-to-iql/iql-converter.d.ts
|
|
206
|
+
/**
|
|
207
|
+
* 将 AST 节点转换为 IQL 查询字符串
|
|
208
|
+
*/
|
|
209
|
+
declare function astToIQL(ast: ASTNode, constantsMap: ConstantsMap): string;
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/index.d.ts
|
|
212
|
+
/**
|
|
213
|
+
* 解析 JQL 查询字符串为 AST
|
|
214
|
+
*/
|
|
215
|
+
declare function parseJQL(jqlText: string): ASTNode | null;
|
|
216
|
+
/**
|
|
217
|
+
* 将 JQL 转换为 IQL
|
|
218
|
+
*/
|
|
219
|
+
declare function jql2iql(jqlText: string, constantsMap: ConstantsMap): string;
|
|
220
|
+
//#endregion
|
|
221
|
+
export { ASTNode, BaseASTNode, BinaryExpression, ConstantsMap, Field, FieldTypeKey, FunctionNode, Identifier, JQLQuery, JiraFieldConfig, JiraFieldMap, List, Literal, LogicalExpression, OrderByClause, OrderByField, OrderDirection, type RawField, astToIQL, buildAST, getNodeInfo, jql2iql, parseJQL, transformFieldsToConstantsMap, traverseJQLTree };
|