@cicctencent/json-orm 0.1.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/README.md +154 -0
- package/dist/cjs/index.d.ts +25 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +66 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/json-backend-fs.d.ts +26 -0
- package/dist/cjs/json-backend-fs.d.ts.map +1 -0
- package/dist/cjs/json-backend-fs.js +278 -0
- package/dist/cjs/json-backend-fs.js.map +1 -0
- package/dist/cjs/json-collection.d.ts +70 -0
- package/dist/cjs/json-collection.d.ts.map +1 -0
- package/dist/cjs/json-collection.js +385 -0
- package/dist/cjs/json-collection.js.map +1 -0
- package/dist/cjs/json-config.d.ts +87 -0
- package/dist/cjs/json-config.d.ts.map +1 -0
- package/dist/cjs/json-config.js +77 -0
- package/dist/cjs/json-config.js.map +1 -0
- package/dist/cjs/json-datasource.d.ts +35 -0
- package/dist/cjs/json-datasource.d.ts.map +1 -0
- package/dist/cjs/json-datasource.js +131 -0
- package/dist/cjs/json-datasource.js.map +1 -0
- package/dist/cjs/json-entity-meta.d.ts +42 -0
- package/dist/cjs/json-entity-meta.d.ts.map +1 -0
- package/dist/cjs/json-entity-meta.js +128 -0
- package/dist/cjs/json-entity-meta.js.map +1 -0
- package/dist/cjs/json-query-builder.d.ts +83 -0
- package/dist/cjs/json-query-builder.d.ts.map +1 -0
- package/dist/cjs/json-query-builder.js +477 -0
- package/dist/cjs/json-query-builder.js.map +1 -0
- package/dist/cjs/json-repository.d.ts +59 -0
- package/dist/cjs/json-repository.d.ts.map +1 -0
- package/dist/cjs/json-repository.js +309 -0
- package/dist/cjs/json-repository.js.map +1 -0
- package/dist/cjs/json-sql-expr.d.ts +107 -0
- package/dist/cjs/json-sql-expr.d.ts.map +1 -0
- package/dist/cjs/json-sql-expr.js +857 -0
- package/dist/cjs/json-sql-expr.js.map +1 -0
- package/dist/cjs/json-sql-select.d.ts +9 -0
- package/dist/cjs/json-sql-select.d.ts.map +1 -0
- package/dist/cjs/json-sql-select.js +434 -0
- package/dist/cjs/json-sql-select.js.map +1 -0
- package/dist/cjs/json-sql-shared.d.ts +16 -0
- package/dist/cjs/json-sql-shared.d.ts.map +1 -0
- package/dist/cjs/json-sql-shared.js +12 -0
- package/dist/cjs/json-sql-shared.js.map +1 -0
- package/dist/cjs/json-sql.d.ts +8 -0
- package/dist/cjs/json-sql.d.ts.map +1 -0
- package/dist/cjs/json-sql.js +322 -0
- package/dist/cjs/json-sql.js.map +1 -0
- package/dist/cjs/json-where.d.ts +54 -0
- package/dist/cjs/json-where.d.ts.map +1 -0
- package/dist/cjs/json-where.js +352 -0
- package/dist/cjs/json-where.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/esm/index.d.ts +25 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +26 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/json-backend-fs.d.ts +26 -0
- package/dist/esm/json-backend-fs.d.ts.map +1 -0
- package/dist/esm/json-backend-fs.js +241 -0
- package/dist/esm/json-backend-fs.js.map +1 -0
- package/dist/esm/json-collection.d.ts +70 -0
- package/dist/esm/json-collection.d.ts.map +1 -0
- package/dist/esm/json-collection.js +346 -0
- package/dist/esm/json-collection.js.map +1 -0
- package/dist/esm/json-config.d.ts +87 -0
- package/dist/esm/json-config.d.ts.map +1 -0
- package/dist/esm/json-config.js +69 -0
- package/dist/esm/json-config.js.map +1 -0
- package/dist/esm/json-datasource.d.ts +35 -0
- package/dist/esm/json-datasource.d.ts.map +1 -0
- package/dist/esm/json-datasource.js +123 -0
- package/dist/esm/json-datasource.js.map +1 -0
- package/dist/esm/json-entity-meta.d.ts +42 -0
- package/dist/esm/json-entity-meta.d.ts.map +1 -0
- package/dist/esm/json-entity-meta.js +120 -0
- package/dist/esm/json-entity-meta.js.map +1 -0
- package/dist/esm/json-query-builder.d.ts +83 -0
- package/dist/esm/json-query-builder.d.ts.map +1 -0
- package/dist/esm/json-query-builder.js +473 -0
- package/dist/esm/json-query-builder.js.map +1 -0
- package/dist/esm/json-repository.d.ts +59 -0
- package/dist/esm/json-repository.d.ts.map +1 -0
- package/dist/esm/json-repository.js +304 -0
- package/dist/esm/json-repository.js.map +1 -0
- package/dist/esm/json-sql-expr.d.ts +107 -0
- package/dist/esm/json-sql-expr.d.ts.map +1 -0
- package/dist/esm/json-sql-expr.js +847 -0
- package/dist/esm/json-sql-expr.js.map +1 -0
- package/dist/esm/json-sql-select.d.ts +9 -0
- package/dist/esm/json-sql-select.d.ts.map +1 -0
- package/dist/esm/json-sql-select.js +429 -0
- package/dist/esm/json-sql-select.js.map +1 -0
- package/dist/esm/json-sql-shared.d.ts +16 -0
- package/dist/esm/json-sql-shared.d.ts.map +1 -0
- package/dist/esm/json-sql-shared.js +9 -0
- package/dist/esm/json-sql-shared.js.map +1 -0
- package/dist/esm/json-sql.d.ts +8 -0
- package/dist/esm/json-sql.d.ts.map +1 -0
- package/dist/esm/json-sql.js +319 -0
- package/dist/esm/json-sql.js.map +1 -0
- package/dist/esm/json-where.d.ts +54 -0
- package/dist/esm/json-where.d.ts.map +1 -0
- package/dist/esm/json-where.js +342 -0
- package/dist/esm/json-where.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/examples/01-basic-entity.ts +89 -0
- package/examples/02-query-builder.ts +114 -0
- package/examples/03-raw-sql.ts +105 -0
- package/examples/04-non-entity-table.ts +70 -0
- package/examples/05-custom-backend.ts +145 -0
- package/examples/06-find-operators.ts +75 -0
- package/examples/README.md +73 -0
- package/examples/tsconfig.json +20 -0
- package/package.json +53 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 跨 typeorm 多副本安全的 FindOperator 判定。
|
|
3
|
+
* 本包与消费方(如 app/work-space)常因 pnpm 解析到不同 typeorm 副本,
|
|
4
|
+
* 导致 `instanceof FindOperator` 跨模块实例失效;改用运行时类名鸭子类型检测,
|
|
5
|
+
* 避免把 FindOperator 误判为普通值。
|
|
6
|
+
*/
|
|
7
|
+
export function isFindOperator(value) {
|
|
8
|
+
return (value != null &&
|
|
9
|
+
typeof value === 'object' &&
|
|
10
|
+
!Array.isArray(value) &&
|
|
11
|
+
value.constructor?.name === 'FindOperator' &&
|
|
12
|
+
typeof value.type === 'string');
|
|
13
|
+
}
|
|
14
|
+
// 按长度降序:确保 `->>` 不被 `->` 抢先切分(否则 `->>` 永不可达且解析抛错)
|
|
15
|
+
const MULTI_OPS = ['>=', '<=', '<>', '!=', '->>', '->'];
|
|
16
|
+
const SINGLE_OPS = '=<>+-*/%';
|
|
17
|
+
export function tokenizeSql(sql) {
|
|
18
|
+
const tokens = [];
|
|
19
|
+
let i = 0;
|
|
20
|
+
while (i < sql.length) {
|
|
21
|
+
const ch = sql[i];
|
|
22
|
+
if (/\s/.test(ch)) {
|
|
23
|
+
i += 1;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
// 行注释
|
|
27
|
+
if (ch === '-' && sql[i + 1] === '-') {
|
|
28
|
+
while (i < sql.length && sql[i] !== '\n')
|
|
29
|
+
i += 1;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
// 字符串(单引号,'' 转义)与双引号字符串
|
|
33
|
+
if (ch === "'" || ch === '"') {
|
|
34
|
+
const quote = ch;
|
|
35
|
+
let v = '';
|
|
36
|
+
i += 1;
|
|
37
|
+
while (i < sql.length) {
|
|
38
|
+
if (sql[i] === quote) {
|
|
39
|
+
if (sql[i + 1] === quote) {
|
|
40
|
+
v += quote;
|
|
41
|
+
i += 2;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
i += 1;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
v += sql[i];
|
|
48
|
+
i += 1;
|
|
49
|
+
}
|
|
50
|
+
tokens.push({ type: 'string', value: v, pos: i });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// 反引号标识符
|
|
54
|
+
if (ch === '`') {
|
|
55
|
+
const end = sql.indexOf('`', i + 1);
|
|
56
|
+
if (end < 0)
|
|
57
|
+
throw new Error(`[json-storage] SQL 分词失败:未闭合的反引号(${sql.slice(i, i + 20)}…)`);
|
|
58
|
+
tokens.push({ type: 'ident', value: sql.slice(i + 1, end), pos: i });
|
|
59
|
+
i = end + 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// 命名参数 :name / 展开参数 :...name
|
|
63
|
+
if (ch === ':') {
|
|
64
|
+
let j = i + 1;
|
|
65
|
+
let spread = false;
|
|
66
|
+
if (sql.slice(j, j + 3) === '...') {
|
|
67
|
+
spread = true;
|
|
68
|
+
j += 3;
|
|
69
|
+
}
|
|
70
|
+
let name = '';
|
|
71
|
+
while (j < sql.length && /[A-Za-z0-9_$]/.test(sql[j])) {
|
|
72
|
+
name += sql[j];
|
|
73
|
+
j += 1;
|
|
74
|
+
}
|
|
75
|
+
if (!name)
|
|
76
|
+
throw new Error(`[json-storage] SQL 分词失败:非法参数占位符(位置 ${i})`);
|
|
77
|
+
tokens.push({ type: 'param', value: spread ? `...${name}` : name, pos: i });
|
|
78
|
+
i = j;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (ch === '?') {
|
|
82
|
+
tokens.push({ type: 'qmark', value: '?', pos: i });
|
|
83
|
+
i += 1;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (/[0-9]/.test(ch)) {
|
|
87
|
+
let v = '';
|
|
88
|
+
while (i < sql.length && /[0-9.]/.test(sql[i])) {
|
|
89
|
+
v += sql[i];
|
|
90
|
+
i += 1;
|
|
91
|
+
}
|
|
92
|
+
tokens.push({ type: 'number', value: v, pos: i });
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (/[A-Za-z_$]/.test(ch)) {
|
|
96
|
+
let v = '';
|
|
97
|
+
while (i < sql.length && /[A-Za-z0-9_$]/.test(sql[i])) {
|
|
98
|
+
v += sql[i];
|
|
99
|
+
i += 1;
|
|
100
|
+
}
|
|
101
|
+
tokens.push({ type: 'ident', value: v, pos: i });
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const two = sql.slice(i, i + 3);
|
|
105
|
+
const multi = MULTI_OPS.find(op => two.startsWith(op));
|
|
106
|
+
if (multi) {
|
|
107
|
+
tokens.push({ type: 'op', value: multi, pos: i });
|
|
108
|
+
i += multi.length;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (SINGLE_OPS.includes(ch)) {
|
|
112
|
+
tokens.push({ type: 'op', value: ch, pos: i });
|
|
113
|
+
i += 1;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (ch === '(') {
|
|
117
|
+
tokens.push({ type: 'lparen', value: ch, pos: i });
|
|
118
|
+
i += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (ch === ')') {
|
|
122
|
+
tokens.push({ type: 'rparen', value: ch, pos: i });
|
|
123
|
+
i += 1;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (ch === ',') {
|
|
127
|
+
tokens.push({ type: 'comma', value: ch, pos: i });
|
|
128
|
+
i += 1;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (ch === '.') {
|
|
132
|
+
tokens.push({ type: 'dot', value: ch, pos: i });
|
|
133
|
+
i += 1;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
throw new Error(`[json-storage] SQL 分词失败:不支持的字符 "${ch}"(位置 ${i})`);
|
|
137
|
+
}
|
|
138
|
+
tokens.push({ type: 'eof', value: '', pos: sql.length });
|
|
139
|
+
return tokens;
|
|
140
|
+
}
|
|
141
|
+
/** 分词游标(供条件/表达式解析共用) */
|
|
142
|
+
export class TokenCursor {
|
|
143
|
+
tokens;
|
|
144
|
+
idx = 0;
|
|
145
|
+
constructor(tokens) {
|
|
146
|
+
this.tokens = tokens;
|
|
147
|
+
}
|
|
148
|
+
peek(offset = 0) {
|
|
149
|
+
return this.tokens[Math.min(this.idx + offset, this.tokens.length - 1)];
|
|
150
|
+
}
|
|
151
|
+
next() {
|
|
152
|
+
const t = this.tokens[this.idx];
|
|
153
|
+
if (t.type !== 'eof')
|
|
154
|
+
this.idx += 1;
|
|
155
|
+
return t;
|
|
156
|
+
}
|
|
157
|
+
/** 当前 ident 是否关键字(大小写不敏感) */
|
|
158
|
+
isKeyword(word, offset = 0) {
|
|
159
|
+
const t = this.peek(offset);
|
|
160
|
+
return t.type === 'ident' && t.value.toUpperCase() === word;
|
|
161
|
+
}
|
|
162
|
+
expectKeyword(word) {
|
|
163
|
+
if (!this.isKeyword(word)) {
|
|
164
|
+
throw new Error(`[json-storage] 解析失败:期望 ${word},实际 "${this.peek().value || this.peek().type}"`);
|
|
165
|
+
}
|
|
166
|
+
this.next();
|
|
167
|
+
}
|
|
168
|
+
expect(type, value) {
|
|
169
|
+
const t = this.peek();
|
|
170
|
+
if (t.type !== type || (value !== undefined && t.value !== value)) {
|
|
171
|
+
throw new Error(`[json-storage] 解析失败:期望 ${value ?? type},实际 "${t.value || t.type}"`);
|
|
172
|
+
}
|
|
173
|
+
return this.next();
|
|
174
|
+
}
|
|
175
|
+
atEnd() {
|
|
176
|
+
return this.peek().type === 'eof';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// ---------------- 值比较 / LIKE ----------------
|
|
180
|
+
/** 稳健比较:数字按数值、日期按时间戳、字符串按字典序;类型不可比时按字符串 */
|
|
181
|
+
export function compareValues(a, b) {
|
|
182
|
+
// 任一侧为 Date:统一换算为时间戳比较(字符串先尝试 Date.parse,兼容 MySQL datetime 文本)
|
|
183
|
+
if (a instanceof Date || b instanceof Date) {
|
|
184
|
+
const ta = dateToTs(a);
|
|
185
|
+
const tb = dateToTs(b);
|
|
186
|
+
if (ta !== null && tb !== null)
|
|
187
|
+
return ta < tb ? -1 : ta > tb ? 1 : 0;
|
|
188
|
+
}
|
|
189
|
+
const na = toNumber(a);
|
|
190
|
+
const nb = toNumber(b);
|
|
191
|
+
if (na !== null && nb !== null) {
|
|
192
|
+
return na < nb ? -1 : na > nb ? 1 : 0;
|
|
193
|
+
}
|
|
194
|
+
const sa = String(a ?? '');
|
|
195
|
+
const sb = String(b ?? '');
|
|
196
|
+
return sa < sb ? -1 : sa > sb ? 1 : 0;
|
|
197
|
+
}
|
|
198
|
+
function dateToTs(v) {
|
|
199
|
+
if (v instanceof Date)
|
|
200
|
+
return Number.isNaN(v.getTime()) ? null : v.getTime();
|
|
201
|
+
if (typeof v === 'number')
|
|
202
|
+
return v;
|
|
203
|
+
if (typeof v === 'string' && v.trim() !== '') {
|
|
204
|
+
const t = Date.parse(v.replace(' ', 'T'));
|
|
205
|
+
return Number.isNaN(t) ? null : t;
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
function toNumber(v) {
|
|
210
|
+
if (typeof v === 'number')
|
|
211
|
+
return v;
|
|
212
|
+
if (typeof v === 'boolean')
|
|
213
|
+
return v ? 1 : 0;
|
|
214
|
+
if (v instanceof Date)
|
|
215
|
+
return v.getTime();
|
|
216
|
+
if (typeof v === 'string' && v.trim() !== '' && !Number.isNaN(Number(v)))
|
|
217
|
+
return Number(v);
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
/** SQL LIKE:`%` 任意串、`_` 单字符 */
|
|
221
|
+
export function likeMatch(input, pattern) {
|
|
222
|
+
const escaped = pattern
|
|
223
|
+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
224
|
+
.replace(/%/g, '.*')
|
|
225
|
+
.replace(/_/g, '.');
|
|
226
|
+
// 转义已覆盖全部正则元字符,构造不会失败;不再保留「去 % 后子串包含」的误判兜底
|
|
227
|
+
return new RegExp(`^${escaped}$`, 'is').test(input);
|
|
228
|
+
}
|
|
229
|
+
/** 宽松等值(Date/ISO 字符串、数字/字符串数字) */
|
|
230
|
+
export function looseEqual(a, b) {
|
|
231
|
+
if (a === b)
|
|
232
|
+
return true;
|
|
233
|
+
if (a === null || a === undefined || b === null || b === undefined)
|
|
234
|
+
return false;
|
|
235
|
+
if (a instanceof Date || b instanceof Date) {
|
|
236
|
+
const ta = a instanceof Date ? a.getTime() : Date.parse(String(a));
|
|
237
|
+
const tb = b instanceof Date ? b.getTime() : Date.parse(String(b));
|
|
238
|
+
return ta === tb && !Number.isNaN(ta);
|
|
239
|
+
}
|
|
240
|
+
const na = toNumber(a);
|
|
241
|
+
const nb = toNumber(b);
|
|
242
|
+
if (na !== null && nb !== null)
|
|
243
|
+
return na === nb;
|
|
244
|
+
// 对象/数组不得退化为 String() 比较:任意两个 {} 会得到 '[object Object]' 而误判相等,
|
|
245
|
+
// 使 upsert 冲突检测与唯一索引匹配把不相关的行判为冲突并错误合并到首行
|
|
246
|
+
if (typeof a === 'object' || typeof b === 'object')
|
|
247
|
+
return deepEqual(a, b);
|
|
248
|
+
return String(a) === String(b);
|
|
249
|
+
}
|
|
250
|
+
/** 结构化深比较(供 looseEqual 对对象/数组值使用) */
|
|
251
|
+
function deepEqual(a, b) {
|
|
252
|
+
if (a === b)
|
|
253
|
+
return true;
|
|
254
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
255
|
+
return false;
|
|
256
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
257
|
+
return false;
|
|
258
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
259
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
260
|
+
}
|
|
261
|
+
const ra = a;
|
|
262
|
+
const rb = b;
|
|
263
|
+
const ka = Object.keys(ra);
|
|
264
|
+
const kb = Object.keys(rb);
|
|
265
|
+
if (ka.length !== kb.length)
|
|
266
|
+
return false;
|
|
267
|
+
return ka.every(k => k in rb && deepEqual(ra[k], rb[k]));
|
|
268
|
+
}
|
|
269
|
+
// ---------------- FindOptionsWhere 对象匹配 ----------------
|
|
270
|
+
/**
|
|
271
|
+
* 匹配 FindOptionsWhere(对象或对象数组=OR)。
|
|
272
|
+
* 键为属性名(若为数据库列名则经 meta 映射),值支持原始值与 FindOperator。
|
|
273
|
+
*/
|
|
274
|
+
export function matchesWhere(row, where, meta) {
|
|
275
|
+
if (where === null || where === undefined)
|
|
276
|
+
return true;
|
|
277
|
+
if (Array.isArray(where))
|
|
278
|
+
return where.some(w => matchesWhere(row, w, meta));
|
|
279
|
+
if (typeof where !== 'object') {
|
|
280
|
+
throw new Error(`[json-storage] 不支持的 where 形式:${JSON.stringify(where)}`);
|
|
281
|
+
}
|
|
282
|
+
for (const [key, expected] of Object.entries(where)) {
|
|
283
|
+
const prop = meta?.columnByDbName.get(key) ?? key;
|
|
284
|
+
const actual = row[prop];
|
|
285
|
+
if (isFindOperator(expected)) {
|
|
286
|
+
if (!evalFindOperator(expected, actual))
|
|
287
|
+
return false;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (expected !== null && expected !== undefined && typeof expected === 'object' && !(expected instanceof Date)) {
|
|
291
|
+
throw new Error(`[json-storage] 不支持的 where 嵌套对象(属性 ${key})——JSON 回退模式暂不支持关系嵌套查询`);
|
|
292
|
+
}
|
|
293
|
+
if (expected === null || expected === undefined) {
|
|
294
|
+
if (actual !== null && actual !== undefined)
|
|
295
|
+
return false;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (!looseEqual(actual, expected))
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
function evalFindOperator(op, actual) {
|
|
304
|
+
const type = op.type;
|
|
305
|
+
const child = op.child;
|
|
306
|
+
switch (type) {
|
|
307
|
+
case 'equal':
|
|
308
|
+
return looseEqual(actual, op.value);
|
|
309
|
+
case 'not':
|
|
310
|
+
if (child)
|
|
311
|
+
return !evalFindOperator(child, actual);
|
|
312
|
+
return !looseEqual(actual, op.value);
|
|
313
|
+
case 'like':
|
|
314
|
+
return likeMatch(String(actual ?? ''), String(op.value ?? ''));
|
|
315
|
+
case 'ilike':
|
|
316
|
+
return likeMatch(String(actual ?? '').toLowerCase(), String(op.value ?? '').toLowerCase());
|
|
317
|
+
case 'in':
|
|
318
|
+
case 'any': {
|
|
319
|
+
const arr = Array.isArray(op.value) ? op.value : [op.value];
|
|
320
|
+
return arr.some(v => looseEqual(actual, v));
|
|
321
|
+
}
|
|
322
|
+
case 'between': {
|
|
323
|
+
const arr = Array.isArray(op.value) ? op.value : [op.value];
|
|
324
|
+
return compareValues(actual, arr[0]) >= 0 && compareValues(actual, arr[1]) <= 0;
|
|
325
|
+
}
|
|
326
|
+
case 'lessThan':
|
|
327
|
+
return actual !== null && actual !== undefined && compareValues(actual, op.value) < 0;
|
|
328
|
+
case 'lessThanOrEqual':
|
|
329
|
+
return actual !== null && actual !== undefined && compareValues(actual, op.value) <= 0;
|
|
330
|
+
case 'moreThan':
|
|
331
|
+
return actual !== null && actual !== undefined && compareValues(actual, op.value) > 0;
|
|
332
|
+
case 'moreThanOrEqual':
|
|
333
|
+
return actual !== null && actual !== undefined && compareValues(actual, op.value) >= 0;
|
|
334
|
+
case 'isNull':
|
|
335
|
+
return actual === null || actual === undefined;
|
|
336
|
+
case 'raw':
|
|
337
|
+
throw new Error('[json-storage] Raw() 操作符在 JSON 回退模式不受支持(fail-loud)');
|
|
338
|
+
default:
|
|
339
|
+
throw new Error(`[json-storage] 不支持的 FindOperator 类型:${type}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
//# sourceMappingURL=json-where.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-where.js","sourceRoot":"","sources":["../../src/json-where.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 示例 01:定义实体 + 通过 DataSource 仓储读写
|
|
3
|
+
*
|
|
4
|
+
* 演示:
|
|
5
|
+
* - 用 TypeORM 装饰器定义实体(表名 + 列名映射)
|
|
6
|
+
* - 首次访问前经 configureJsonStorage 注入存储根目录
|
|
7
|
+
* - Repository 的 save / find / findOneBy / findAndCount / update / delete
|
|
8
|
+
*
|
|
9
|
+
* 运行(需先产出 dist,或直接在本仓库内运行):
|
|
10
|
+
* npx tsx examples/01-basic-entity.ts
|
|
11
|
+
*
|
|
12
|
+
* 消费已发布包时,把下方 import 改为:
|
|
13
|
+
* import { configureJsonStorage, getJsonDataSource } from '@cicctencent/json-orm';
|
|
14
|
+
*/
|
|
15
|
+
import 'reflect-metadata';
|
|
16
|
+
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
|
17
|
+
import * as os from 'os';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import { configureJsonStorage, getJsonDataSource } from '@cicctencent/json-orm';
|
|
20
|
+
|
|
21
|
+
@Entity('t_user')
|
|
22
|
+
class User {
|
|
23
|
+
@PrimaryGeneratedColumn()
|
|
24
|
+
id!: number;
|
|
25
|
+
|
|
26
|
+
@Column({ name: 'Fname', type: 'varchar' })
|
|
27
|
+
name!: string;
|
|
28
|
+
|
|
29
|
+
@Column({ name: 'Fage', type: 'int', nullable: true })
|
|
30
|
+
age!: number;
|
|
31
|
+
|
|
32
|
+
@Column({ name: 'Fcity', type: 'varchar', nullable: true })
|
|
33
|
+
city!: string;
|
|
34
|
+
|
|
35
|
+
@CreateDateColumn({ name: 'Fcreate_time' })
|
|
36
|
+
createTime!: Date;
|
|
37
|
+
|
|
38
|
+
@UpdateDateColumn({ name: 'Fmodify_time' })
|
|
39
|
+
modifyTime!: Date;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function main(): Promise<void> {
|
|
43
|
+
// 1) 首次访问前注入存储根目录(自动构造 FsStorageBackend)
|
|
44
|
+
configureJsonStorage({ dbDir: path.join(os.tmpdir(), 'json-orm-example-01') });
|
|
45
|
+
|
|
46
|
+
const ds = getJsonDataSource();
|
|
47
|
+
const userRepo = ds.getRepository(User);
|
|
48
|
+
|
|
49
|
+
// 2) 新增:save 自动按主键合并 + 填充 createTime / modifyTime;
|
|
50
|
+
// 自增主键下可不传 id(传 0 也视为未赋值)。
|
|
51
|
+
const u1 = await userRepo.save({ name: 'Alice', age: 30, city: 'Beijing' });
|
|
52
|
+
const u2 = await userRepo.save({ name: 'Bob', age: 25, city: 'Shanghai' });
|
|
53
|
+
console.log('saved ids:', u1.id, u2.id);
|
|
54
|
+
|
|
55
|
+
// 3) 全表查询(返回深拷贝,原地修改不会污染磁盘/内存,须 save 才落库)
|
|
56
|
+
const all = await userRepo.find();
|
|
57
|
+
console.log('all users:', all);
|
|
58
|
+
|
|
59
|
+
// 4) 条件 + 排序 + 分页
|
|
60
|
+
const beijing = await userRepo.find({
|
|
61
|
+
where: { city: 'Beijing' },
|
|
62
|
+
order: { age: 'DESC' },
|
|
63
|
+
take: 10,
|
|
64
|
+
});
|
|
65
|
+
console.log('beijing users:', beijing);
|
|
66
|
+
|
|
67
|
+
// 5) 计数 + 分页:findAndCount 返回 [行, 总数]
|
|
68
|
+
const [page, total] = await userRepo.findAndCount({ skip: 0, take: 1 });
|
|
69
|
+
console.log('page:', page, 'total:', total);
|
|
70
|
+
|
|
71
|
+
// 6) 主键查询
|
|
72
|
+
const one = await userRepo.findOneBy({ id: u1.id });
|
|
73
|
+
console.log('findOneBy id:', one);
|
|
74
|
+
|
|
75
|
+
// 7) 部分更新:partial 中 undefined 视为「不修改」,不会擦除其它列
|
|
76
|
+
// (等价于 TypeORM update 语义,自动刷新 modifyTime)
|
|
77
|
+
await userRepo.update({ id: u1.id }, { age: 31 });
|
|
78
|
+
const refreshed = await userRepo.findOneBy({ id: u1.id });
|
|
79
|
+
console.log('after update:', refreshed);
|
|
80
|
+
|
|
81
|
+
// 8) 删除(硬删除)
|
|
82
|
+
await userRepo.delete({ id: u2.id });
|
|
83
|
+
console.log('after delete count:', await userRepo.count());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
main().catch((e) => {
|
|
87
|
+
console.error(e);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 示例 02:QueryBuilder(SELECT / 联表 / 聚合)
|
|
3
|
+
*
|
|
4
|
+
* 演示:
|
|
5
|
+
* - repo.createQueryBuilder(alias) 链式拼装 SELECT
|
|
6
|
+
* - 字符串条件用「别名.属性名」,对象条件用属性名(等价 FindOptionsWhere)
|
|
7
|
+
* - getMany / getManyAndCount / getRawMany / getRawOne
|
|
8
|
+
* - LEFT JOIN + GROUP BY + 聚合函数(COUNT/SUM/MAX/CASE WHEN)
|
|
9
|
+
*
|
|
10
|
+
* 运行:
|
|
11
|
+
* npx tsx examples/02-query-builder.ts
|
|
12
|
+
*/
|
|
13
|
+
import 'reflect-metadata';
|
|
14
|
+
import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm';
|
|
15
|
+
import * as os from 'os';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { configureJsonStorage, getJsonDataSource } from '@cicctencent/json-orm';
|
|
18
|
+
|
|
19
|
+
@Entity('t_article')
|
|
20
|
+
class Article {
|
|
21
|
+
@PrimaryGeneratedColumn()
|
|
22
|
+
id!: number;
|
|
23
|
+
|
|
24
|
+
@Column({ name: 'Ftitle', type: 'varchar' })
|
|
25
|
+
title!: string;
|
|
26
|
+
|
|
27
|
+
@Column({ name: 'Fauthor', type: 'varchar' })
|
|
28
|
+
author!: string;
|
|
29
|
+
|
|
30
|
+
@Column({ name: 'Fviews', type: 'int', default: 0 })
|
|
31
|
+
views!: number;
|
|
32
|
+
|
|
33
|
+
@Column({ name: 'Fstatus', type: 'varchar', default: 'draft' })
|
|
34
|
+
status!: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Entity('t_article_tag')
|
|
38
|
+
class ArticleTag {
|
|
39
|
+
@PrimaryGeneratedColumn()
|
|
40
|
+
id!: number;
|
|
41
|
+
|
|
42
|
+
@Column({ name: 'Farticle_id', type: 'int' })
|
|
43
|
+
articleId!: number;
|
|
44
|
+
|
|
45
|
+
@Column({ name: 'Ftag', type: 'varchar' })
|
|
46
|
+
tag!: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function main(): Promise<void> {
|
|
50
|
+
configureJsonStorage({ dbDir: path.join(os.tmpdir(), 'json-orm-example-02') });
|
|
51
|
+
const ds = getJsonDataSource();
|
|
52
|
+
const articleRepo = ds.getRepository(Article);
|
|
53
|
+
const tagRepo = ds.getRepository(ArticleTag);
|
|
54
|
+
|
|
55
|
+
await articleRepo.save([
|
|
56
|
+
{ title: 'Hello', author: 'Alice', views: 10, status: 'published' },
|
|
57
|
+
{ title: 'World', author: 'Bob', views: 5, status: 'draft' },
|
|
58
|
+
{ title: 'Foo', author: 'Alice', views: 20, status: 'published' },
|
|
59
|
+
]);
|
|
60
|
+
await tagRepo.save([
|
|
61
|
+
{ articleId: 1, tag: 'ts' },
|
|
62
|
+
{ articleId: 1, tag: 'db' },
|
|
63
|
+
{ articleId: 3, tag: 'ts' },
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
// 1) 命名参数 + 排序 + 分页 + 计数
|
|
67
|
+
const [rows, total] = await articleRepo
|
|
68
|
+
.createQueryBuilder('a')
|
|
69
|
+
.where('a.author = :author', { author: 'Alice' })
|
|
70
|
+
.andWhere('a.status = :status', { status: 'published' })
|
|
71
|
+
.orderBy('a.views', 'DESC')
|
|
72
|
+
.skip(0)
|
|
73
|
+
.take(10)
|
|
74
|
+
.getManyAndCount();
|
|
75
|
+
console.log('Alice 已发布文章:', rows, 'total =', total);
|
|
76
|
+
|
|
77
|
+
// 2) 对象条件(属性名,等价于 FindOptionsWhere):未发布草稿
|
|
78
|
+
const drafts = await articleRepo
|
|
79
|
+
.createQueryBuilder('a')
|
|
80
|
+
.where({ status: 'draft' })
|
|
81
|
+
.getMany();
|
|
82
|
+
console.log('drafts:', drafts);
|
|
83
|
+
|
|
84
|
+
// 3) LEFT JOIN 取每篇文章的标签(原始列投影)
|
|
85
|
+
const withTags = await articleRepo
|
|
86
|
+
.createQueryBuilder('a')
|
|
87
|
+
.leftJoin(ArticleTag, 't', 't.articleId = a.id')
|
|
88
|
+
.select(['a.id AS id', 'a.title AS title', 't.tag AS tag'])
|
|
89
|
+
.where('a.author = :author', { author: 'Alice' })
|
|
90
|
+
.getRawMany();
|
|
91
|
+
console.log('articles + tags:', withTags);
|
|
92
|
+
|
|
93
|
+
// 4) GROUP BY + 聚合:按作者统计文章数与总阅读量
|
|
94
|
+
const stats = await articleRepo
|
|
95
|
+
.createQueryBuilder('a')
|
|
96
|
+
.select('a.author', 'author')
|
|
97
|
+
.addSelect('COUNT(*)', 'cnt')
|
|
98
|
+
.addSelect('SUM(a.views)', 'totalViews')
|
|
99
|
+
.groupBy('a.author')
|
|
100
|
+
.getRawMany();
|
|
101
|
+
console.log('per-author stats:', stats);
|
|
102
|
+
|
|
103
|
+
// 5) 单值聚合
|
|
104
|
+
const maxViews = await articleRepo
|
|
105
|
+
.createQueryBuilder('a')
|
|
106
|
+
.select('MAX(a.views)', 'maxViews')
|
|
107
|
+
.getRawOne();
|
|
108
|
+
console.log('max views:', maxViews);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
main().catch((e) => {
|
|
112
|
+
console.error(e);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 示例 03:原生 SQL(TypeORM DataSource.query 兼容)
|
|
3
|
+
*
|
|
4
|
+
* 演示:
|
|
5
|
+
* - ds.query(sql, params) 执行内存 SQL 求值器(MySQL 方言子集)
|
|
6
|
+
* - 位置参数(?)与命名参数(:name)两种占位符
|
|
7
|
+
* - SELECT / INSERT / UPDATE / DELETE / INSERT ... ON DUPLICATE KEY UPDATE / TRUNCATE
|
|
8
|
+
* - 原生 SQL 字符串中的列名使用「数据库列名」(Fxxx),与实体 @Column({ name }) 对应
|
|
9
|
+
* - Repository.upsert 冲突合并(conflictPaths)
|
|
10
|
+
*
|
|
11
|
+
* 运行:
|
|
12
|
+
* npx tsx examples/03-raw-sql.ts
|
|
13
|
+
*/
|
|
14
|
+
import 'reflect-metadata';
|
|
15
|
+
import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm';
|
|
16
|
+
import * as os from 'os';
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
import { configureJsonStorage, getJsonDataSource } from '@cicctencent/json-orm';
|
|
19
|
+
|
|
20
|
+
@Entity('t_product')
|
|
21
|
+
@Index('uk_product_sku', ['sku'], { unique: true })
|
|
22
|
+
class Product {
|
|
23
|
+
@PrimaryGeneratedColumn()
|
|
24
|
+
id!: number;
|
|
25
|
+
|
|
26
|
+
@Column({ name: 'Fsku', type: 'varchar' })
|
|
27
|
+
sku!: string;
|
|
28
|
+
|
|
29
|
+
@Column({ name: 'Fname', type: 'varchar' })
|
|
30
|
+
name!: string;
|
|
31
|
+
|
|
32
|
+
@Column({ name: 'Fprice', type: 'int' })
|
|
33
|
+
price!: number;
|
|
34
|
+
|
|
35
|
+
@Column({ name: 'Fstock', type: 'int', default: 0 })
|
|
36
|
+
stock!: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function main(): Promise<void> {
|
|
40
|
+
configureJsonStorage({ dbDir: path.join(os.tmpdir(), 'json-orm-example-03') });
|
|
41
|
+
const ds = getJsonDataSource();
|
|
42
|
+
|
|
43
|
+
// 通过 Repository 写入几行基线数据(落盘属性名键、SQL 用列名)
|
|
44
|
+
const repo = ds.getRepository(Product);
|
|
45
|
+
await repo.save([
|
|
46
|
+
{ sku: 'K1', name: 'A', price: 10, stock: 3 },
|
|
47
|
+
{ sku: 'K2', name: 'B', price: 80, stock: 1 },
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
// 1) SELECT:位置参数 + 排序
|
|
51
|
+
const cheap = await ds.query('SELECT * FROM t_product WHERE Fprice < ? ORDER BY Fprice ASC', [50]);
|
|
52
|
+
console.log('price < 50:', cheap);
|
|
53
|
+
|
|
54
|
+
// 2) SELECT:命名参数(params 显式标注为 Record<string, unknown>,避免与位置参数数组类型混淆)
|
|
55
|
+
const bySkuParams: Record<string, unknown> = { sku: 'K1' };
|
|
56
|
+
const bySku = await ds.query('SELECT * FROM t_product WHERE Fsku = :sku', bySkuParams);
|
|
57
|
+
console.log('sku=K1:', bySku);
|
|
58
|
+
|
|
59
|
+
// 3) INSERT
|
|
60
|
+
await ds.query(
|
|
61
|
+
'INSERT INTO t_product (Fsku, Fname, Fprice, Fstock) VALUES (?, ?, ?, ?)',
|
|
62
|
+
['K3', 'C', 9, 0],
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// 4) UPDATE:返回 OkPacket 形态(含 affectedRows);列名做算术。
|
|
66
|
+
// 位置参数(?)按 SQL 文本顺序绑定:SET 的 ? 取第 1 个参数、WHERE 的 ? 取第 2 个。
|
|
67
|
+
// 这里改用命名参数(:inc / :sku),两种写法都支持。
|
|
68
|
+
const updParams: Record<string, unknown> = { inc: 5, sku: 'K1' };
|
|
69
|
+
const upd = await ds.query(
|
|
70
|
+
'UPDATE t_product SET Fstock = Fstock + :inc WHERE Fsku = :sku',
|
|
71
|
+
updParams,
|
|
72
|
+
);
|
|
73
|
+
console.log('update affectedRows:', upd.affectedRows);
|
|
74
|
+
|
|
75
|
+
// 5) DELETE
|
|
76
|
+
await ds.query('DELETE FROM t_product WHERE Fprice >= ?', [100]);
|
|
77
|
+
console.log('after delete count:', await repo.count());
|
|
78
|
+
|
|
79
|
+
// 6) INSERT ... ON DUPLICATE KEY UPDATE(按唯一列 upsert)
|
|
80
|
+
await ds.query(
|
|
81
|
+
`INSERT INTO t_product (Fsku, Fname, Fprice, Fstock) VALUES (?, ?, ?, ?)
|
|
82
|
+
ON DUPLICATE KEY UPDATE Fname = VALUES(Fname), Fprice = VALUES(Fprice), Fstock = Fstock + VALUES(Fstock)`,
|
|
83
|
+
['K1', 'A2', 12, 7],
|
|
84
|
+
);
|
|
85
|
+
console.log('after ODKU:', await ds.query('SELECT * FROM t_product WHERE Fsku = ?', ['K1']));
|
|
86
|
+
|
|
87
|
+
// 7) Repository.upsert:按 conflictPaths 冲突合并(undefined 视为不修改)
|
|
88
|
+
await repo.upsert(
|
|
89
|
+
[
|
|
90
|
+
{ sku: 'K2', name: 'B2', stock: 9 },
|
|
91
|
+
{ sku: 'K9', name: 'New', price: 5, stock: 2 },
|
|
92
|
+
],
|
|
93
|
+
{ conflictPaths: ['sku'] },
|
|
94
|
+
);
|
|
95
|
+
console.log('after repo.upsert:', await ds.query('SELECT Fsku, Fname, Fprice, Fstock FROM t_product'));
|
|
96
|
+
|
|
97
|
+
// 8) TRUNCATE:返回时已清空落盘
|
|
98
|
+
await ds.query('TRUNCATE TABLE t_product');
|
|
99
|
+
console.log('after truncate count:', await repo.count());
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main().catch((e) => {
|
|
103
|
+
console.error(e);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|