@digitalwalletcorp/sql-builder 1.6.1 → 2.1.0
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 +226 -51
- package/lib/abstract-syntax-tree.d.ts +1 -1
- package/lib/abstract-syntax-tree.js +6 -6
- package/lib/abstract-syntax-tree.js.map +1 -1
- package/lib/common.d.ts +21 -0
- package/lib/common.js +35 -4
- package/lib/common.js.map +1 -1
- package/lib/sql-builder.d.ts +21 -1
- package/lib/sql-builder.js +295 -74
- package/lib/sql-builder.js.map +1 -1
- package/package.json +7 -2
- package/src/abstract-syntax-tree.ts +5 -6
- package/src/common.ts +40 -4
- package/src/sql-builder.ts +359 -87
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitalwalletcorp/sql-builder",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "This is a library for building SQL",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -16,8 +16,13 @@
|
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"sql",
|
|
19
|
+
"template",
|
|
20
|
+
"builder",
|
|
19
21
|
"dynamic",
|
|
20
|
-
"
|
|
22
|
+
"parameterized",
|
|
23
|
+
"placeholder",
|
|
24
|
+
"S2Dao",
|
|
25
|
+
"Doma"
|
|
21
26
|
],
|
|
22
27
|
"author": "satoshi kotaki",
|
|
23
28
|
"license": "MIT",
|
|
@@ -39,7 +39,7 @@ export class AbstractSyntaxTree {
|
|
|
39
39
|
/**
|
|
40
40
|
* 与えられた条件文字列を構文解析し、entityに対する条件として成立するか評価する
|
|
41
41
|
*
|
|
42
|
-
* @param {string} condition
|
|
42
|
+
* @param {string} condition 'params != null && params.length > 10' のような条件
|
|
43
43
|
* @param {Record<string, any>} entity
|
|
44
44
|
* @returns {boolean}
|
|
45
45
|
*/
|
|
@@ -50,9 +50,8 @@ export class AbstractSyntaxTree {
|
|
|
50
50
|
const result = this.evaluateRpn(rpnTokens, entity);
|
|
51
51
|
return result;
|
|
52
52
|
} catch (error: any) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
throw error;
|
|
53
|
+
const enhancedMessage = `[SQLBuilder] Failed to evaluate IF condition: '/*IF ${condition}*/'. ${error.message}`;
|
|
54
|
+
throw new Error(enhancedMessage);
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -239,7 +238,7 @@ export class AbstractSyntaxTree {
|
|
|
239
238
|
output.push(op);
|
|
240
239
|
}
|
|
241
240
|
if (!foundLeftParen) {
|
|
242
|
-
throw new Error(
|
|
241
|
+
throw new Error(`[SQLBuilder.AST] Mismatched parentheses: Found closing ')' without a matching '('. Check your IF condition syntax.`);;
|
|
243
242
|
}
|
|
244
243
|
}
|
|
245
244
|
break;
|
|
@@ -250,7 +249,7 @@ export class AbstractSyntaxTree {
|
|
|
250
249
|
while (operatorStack.length) {
|
|
251
250
|
const op = operatorStack.pop()!;
|
|
252
251
|
if (op.value === '(' || op.value === ')') {
|
|
253
|
-
throw new Error(
|
|
252
|
+
throw new Error(`[SQLBuilder.AST] Mismatched parentheses: An extra '${op.value}' was found or a matching '(' is missing.`);
|
|
254
253
|
}
|
|
255
254
|
output.push(op);
|
|
256
255
|
}
|
package/src/common.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
type PropertyResult = {
|
|
2
|
+
exists: boolean;
|
|
3
|
+
value: any;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* entityで指定したオブジェクトからドットで連結されたプロパティキーに該当する値を取得する
|
|
3
8
|
*
|
|
@@ -6,17 +11,45 @@
|
|
|
6
11
|
* @returns {any}
|
|
7
12
|
*/
|
|
8
13
|
export function getProperty(entity: Record<string, any>, property: string): any {
|
|
14
|
+
return getPropertyResult(entity, property).value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* entityで指定したオブジェクトからドットで連結されたプロパティキーに該当する値が存在するかチェックする
|
|
19
|
+
*
|
|
20
|
+
* @param {Record<string, any>} entity
|
|
21
|
+
* @param {string} property
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
*/
|
|
24
|
+
export function hasProperty(entity: Record<string, any>, property: string): boolean {
|
|
25
|
+
return getPropertyResult(entity, property).exists;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* entityで指定したオブジェクトからドットで連結されたプロパティキーに該当する値を取得する
|
|
30
|
+
*
|
|
31
|
+
* @param {Record<string, any>} entity
|
|
32
|
+
* @param {string} property
|
|
33
|
+
* @returns {PropertyResult}
|
|
34
|
+
*/
|
|
35
|
+
export function getPropertyResult(entity: Record<string, any>, property: string): PropertyResult {
|
|
9
36
|
// `?.` または `.` でパスを分割
|
|
10
37
|
const propertyPath = property.split(/(\?\.)|\./).filter(Boolean);
|
|
11
38
|
|
|
12
39
|
// 再帰呼び出し用のヘルパー関数
|
|
13
40
|
const get = (obj: Record<string, any>, keys: string[]): any => {
|
|
14
41
|
if (keys.length === 0) {
|
|
15
|
-
return
|
|
42
|
+
return {
|
|
43
|
+
exists: true,
|
|
44
|
+
value: obj
|
|
45
|
+
} as PropertyResult;
|
|
16
46
|
}
|
|
17
47
|
// オプショナルチェイニングのチェック
|
|
18
48
|
if (obj == null) {
|
|
19
|
-
return
|
|
49
|
+
return {
|
|
50
|
+
exists: false,
|
|
51
|
+
value: undefined
|
|
52
|
+
} as PropertyResult;
|
|
20
53
|
}
|
|
21
54
|
|
|
22
55
|
const currentKey = keys[0];
|
|
@@ -27,8 +60,11 @@ export function getProperty(entity: Record<string, any>, property: string): any
|
|
|
27
60
|
return get(obj, remainingKeys);
|
|
28
61
|
}
|
|
29
62
|
// プロパティが存在しない場合は undefined を返す
|
|
30
|
-
if (!
|
|
31
|
-
return
|
|
63
|
+
if (!Object.prototype.hasOwnProperty.call(obj, currentKey)) {
|
|
64
|
+
return {
|
|
65
|
+
exists: false,
|
|
66
|
+
value: undefined
|
|
67
|
+
} as PropertyResult;
|
|
32
68
|
}
|
|
33
69
|
return get(obj[currentKey], remainingKeys);
|
|
34
70
|
};
|