@maiyunnet/kebab 9.15.1 → 9.15.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/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * --- 本文件用来定义每个目录实体地址的常量 ---
6
6
  */
7
7
  /** --- 当前系统版本号 --- */
8
- export declare const VER = "9.15.1";
8
+ export declare const VER = "9.15.3";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  /** --- 框架的 LIB,以 / 结尾 --- */
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '9.15.1';
9
+ export const VER = '9.15.3';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/db/conn.js CHANGED
@@ -2,6 +2,7 @@ import * as pg from 'pg';
2
2
  import * as lCore from '#kebab/lib/core.js';
3
3
  import * as lTime from '#kebab/lib/time.js';
4
4
  import * as lDb from '#kebab/lib/db.js';
5
+ import * as lSqlValue from '#kebab/lib/sql/value.js';
5
6
  // --- 注册解析器 ---
6
7
  // --- pg 库对以下类型默认返回 string,为与 MySQL 行为保持一致,在此注册解析器转为 JS 原生类型 ---
7
8
  // --- POLYGON: 返回如 ((1,1),(2,2)) 的字符串,解析为 {x, y}[] ---
@@ -155,6 +156,7 @@ export class Connection {
155
156
  'result': 1,
156
157
  };
157
158
  try {
159
+ values = lSqlValue.serializeList(values);
158
160
  this.refreshLast();
159
161
  if (this._lastSql.length === 2) {
160
162
  this._lastSql.splice(0, 1);
@@ -212,6 +214,7 @@ export class Connection {
212
214
  'result': 1,
213
215
  };
214
216
  try {
217
+ values = lSqlValue.serializeList(values);
215
218
  this.refreshLast();
216
219
  if (this._lastSql.length === 2) {
217
220
  this._lastSql.splice(0, 1);
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Project: Kebab, User: JianSuoQiYue
3
+ * --- 数据库特殊值的运行时包装与序列化 ---
4
+ */
5
+ import * as kebab from '#kebab/index.js';
6
+ /** --- JSON 数据的内部标记,不污染原始对象,也不会参与 JSON 序列化 --- */
7
+ declare const jsonValueSymbol: unique symbol;
8
+ /** --- 延迟到数据库边界序列化的 JSON 值 --- */
9
+ export interface IJsonValue<T> {
10
+ readonly [jsonValueSymbol]: true;
11
+ readonly 'value': T;
12
+ }
13
+ /**
14
+ * --- 创建延迟序列化的 JSON 值 ---
15
+ * @param value 原始 JSON 值
16
+ * @returns JSON 包装值
17
+ */
18
+ export declare function json<T>(value: T): IJsonValue<T>;
19
+ /**
20
+ * --- 判断是否为 JSON 包装值 ---
21
+ * @param value 待判断的值
22
+ * @returns 是否为 JSON 包装值
23
+ */
24
+ export declare function isJson(value: unknown): value is IJsonValue<unknown>;
25
+ /**
26
+ * --- 获取 JSON 包装值内的原始值;普通值保持不变 ---
27
+ * @param value 待解包的值
28
+ * @returns 原始值
29
+ */
30
+ export declare function unwrapJson<T>(value: T): T;
31
+ /**
32
+ * --- 将单个数据库参数转换为驱动可识别的值 ---
33
+ * @param value 数据库参数
34
+ * @returns 序列化后的数据库参数
35
+ */
36
+ export declare function serialize(value: kebab.Json): kebab.Json;
37
+ /**
38
+ * --- 在进入数据库驱动前序列化特殊参数,不修改调用方数组 ---
39
+ * @param values 数据库参数列表
40
+ * @returns 可直接交给数据库驱动的参数列表
41
+ */
42
+ export declare function serializeList(values?: kebab.DbValue[]): kebab.DbValue[] | undefined;
43
+ export {};
@@ -0,0 +1,59 @@
1
+ import * as lText from '#kebab/lib/text.js';
2
+ /** --- JSON 数据的内部标记,不污染原始对象,也不会参与 JSON 序列化 --- */
3
+ const jsonValueSymbol = Symbol('kebab.db.json');
4
+ /**
5
+ * --- 创建延迟序列化的 JSON 值 ---
6
+ * @param value 原始 JSON 值
7
+ * @returns JSON 包装值
8
+ */
9
+ export function json(value) {
10
+ return {
11
+ [jsonValueSymbol]: true,
12
+ 'value': value,
13
+ };
14
+ }
15
+ /**
16
+ * --- 判断是否为 JSON 包装值 ---
17
+ * @param value 待判断的值
18
+ * @returns 是否为 JSON 包装值
19
+ */
20
+ export function isJson(value) {
21
+ return value !== null && typeof value === 'object' &&
22
+ !!value[jsonValueSymbol];
23
+ }
24
+ /**
25
+ * --- 获取 JSON 包装值内的原始值;普通值保持不变 ---
26
+ * @param value 待解包的值
27
+ * @returns 原始值
28
+ */
29
+ export function unwrapJson(value) {
30
+ return (isJson(value) ? value.value : value);
31
+ }
32
+ /**
33
+ * --- 将单个数据库参数转换为驱动可识别的值 ---
34
+ * @param value 数据库参数
35
+ * @returns 序列化后的数据库参数
36
+ */
37
+ export function serialize(value) {
38
+ return isJson(value) ? lText.stringifyJson(value.value) : value;
39
+ }
40
+ /**
41
+ * --- 在进入数据库驱动前序列化特殊参数,不修改调用方数组 ---
42
+ * @param values 数据库参数列表
43
+ * @returns 可直接交给数据库驱动的参数列表
44
+ */
45
+ export function serializeList(values) {
46
+ if (!values) {
47
+ return undefined;
48
+ }
49
+ let serialized;
50
+ for (let i = 0; i < values.length; ++i) {
51
+ const value = values[i];
52
+ if (!isJson(value)) {
53
+ continue;
54
+ }
55
+ serialized ??= [...values];
56
+ serialized[i] = lText.stringifyJson(value.value);
57
+ }
58
+ return serialized ?? values;
59
+ }
package/lib/s3.d.ts CHANGED
@@ -101,6 +101,13 @@ export declare class S3 {
101
101
  * @param bucket bucket 名
102
102
  */
103
103
  getObject(key: string, bucket?: string): Promise<false | (stream.Readable & import("@smithy/types").SdkStreamMixin) | (Blob & import("@smithy/types").SdkStreamMixin) | (ReadableStream<any> & import("@smithy/types").SdkStreamMixin) | undefined>;
104
+ /**
105
+ * --- 获取对象 Buffer ---
106
+ * @param key 对象路径
107
+ * @param bucket bucket 名
108
+ * @returns 对象内容,获取失败或对象无内容时返回 false
109
+ */
110
+ getObjectBuffer(key: string, bucket?: string): Promise<Buffer | false>;
104
111
  /**
105
112
  * --- 删除对象 ---
106
113
  * @param key 对象路径
package/lib/s3.js CHANGED
@@ -163,6 +163,29 @@ export class S3 {
163
163
  return false;
164
164
  }
165
165
  }
166
+ /**
167
+ * --- 获取对象 Buffer ---
168
+ * @param key 对象路径
169
+ * @param bucket bucket 名
170
+ * @returns 对象内容,获取失败或对象无内容时返回 false
171
+ */
172
+ async getObjectBuffer(key, bucket) {
173
+ try {
174
+ const go = new s3.GetObjectCommand({
175
+ 'Bucket': bucket ?? this._bucket,
176
+ 'Key': key
177
+ });
178
+ const r = await this._link.send(go);
179
+ if (!r.Body) {
180
+ return false;
181
+ }
182
+ return Buffer.from(await r.Body.transformToByteArray());
183
+ }
184
+ catch (e) {
185
+ lCore.log(this._ctr, '[LIB][S3][getObjectBuffer] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
186
+ return false;
187
+ }
188
+ }
166
189
  /**
167
190
  * --- 删除对象 ---
168
191
  * @param key 对象路径
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Project: Kebab, User: JianSuoQiYue
3
+ * --- SQL 特殊参数的运行时包装与序列化 ---
4
+ */
5
+ import * as kebab from '#kebab/index.js';
6
+ /** --- JSON 参数的内部标记,不污染原始对象,也不会参与 JSON 序列化 --- */
7
+ declare const jsonValueSymbol: unique symbol;
8
+ /** --- 延迟到数据库边界序列化的 JSON 参数 --- */
9
+ export interface IJsonValue<T> {
10
+ readonly [jsonValueSymbol]: true;
11
+ readonly 'value': T;
12
+ }
13
+ /**
14
+ * --- 创建延迟序列化的 JSON 参数 ---
15
+ * @param value 原始 JSON 值
16
+ * @returns JSON 包装值
17
+ */
18
+ export declare function json<T>(value: T): IJsonValue<T>;
19
+ /**
20
+ * --- 判断是否为 JSON 包装值 ---
21
+ * @param value 待判断的值
22
+ * @returns 是否为 JSON 包装值
23
+ */
24
+ export declare function isJson(value: unknown): value is IJsonValue<unknown>;
25
+ /**
26
+ * --- 获取 JSON 包装值内的原始值;普通值保持不变 ---
27
+ * @param value 待解包的值
28
+ * @returns 原始值
29
+ */
30
+ export declare function unwrapJson<T>(value: T): T;
31
+ /**
32
+ * --- 将单个 SQL 参数转换为数据库驱动可识别的值 ---
33
+ * @param value SQL 参数
34
+ * @returns 序列化后的数据库参数
35
+ */
36
+ export declare function serialize(value: kebab.Json): kebab.Json;
37
+ /**
38
+ * --- 在进入数据库驱动前序列化特殊参数,不修改调用方数组 ---
39
+ * @param values SQL 参数列表
40
+ * @returns 可直接交给数据库驱动的参数列表
41
+ */
42
+ export declare function serializeList(values?: kebab.DbValue[]): kebab.DbValue[] | undefined;
43
+ export {};
@@ -0,0 +1,59 @@
1
+ import * as lText from '#kebab/lib/text.js';
2
+ /** --- JSON 参数的内部标记,不污染原始对象,也不会参与 JSON 序列化 --- */
3
+ const jsonValueSymbol = Symbol('kebab.sql.json');
4
+ /**
5
+ * --- 创建延迟序列化的 JSON 参数 ---
6
+ * @param value 原始 JSON 值
7
+ * @returns JSON 包装值
8
+ */
9
+ export function json(value) {
10
+ return {
11
+ [jsonValueSymbol]: true,
12
+ 'value': value,
13
+ };
14
+ }
15
+ /**
16
+ * --- 判断是否为 JSON 包装值 ---
17
+ * @param value 待判断的值
18
+ * @returns 是否为 JSON 包装值
19
+ */
20
+ export function isJson(value) {
21
+ return value !== null && typeof value === 'object' &&
22
+ !!value[jsonValueSymbol];
23
+ }
24
+ /**
25
+ * --- 获取 JSON 包装值内的原始值;普通值保持不变 ---
26
+ * @param value 待解包的值
27
+ * @returns 原始值
28
+ */
29
+ export function unwrapJson(value) {
30
+ return (isJson(value) ? value.value : value);
31
+ }
32
+ /**
33
+ * --- 将单个 SQL 参数转换为数据库驱动可识别的值 ---
34
+ * @param value SQL 参数
35
+ * @returns 序列化后的数据库参数
36
+ */
37
+ export function serialize(value) {
38
+ return isJson(value) ? lText.stringifyJson(value.value) : value;
39
+ }
40
+ /**
41
+ * --- 在进入数据库驱动前序列化特殊参数,不修改调用方数组 ---
42
+ * @param values SQL 参数列表
43
+ * @returns 可直接交给数据库驱动的参数列表
44
+ */
45
+ export function serializeList(values) {
46
+ if (!values) {
47
+ return undefined;
48
+ }
49
+ let serialized;
50
+ for (let i = 0; i < values.length; ++i) {
51
+ const value = values[i];
52
+ if (!isJson(value)) {
53
+ continue;
54
+ }
55
+ serialized ??= [...values];
56
+ serialized[i] = lText.stringifyJson(value.value);
57
+ }
58
+ return serialized ?? values;
59
+ }
package/lib/sql.d.ts CHANGED
@@ -98,7 +98,7 @@ export declare class Sql {
98
98
  /**
99
99
  * --- 批量 UPDATE,以子查询作为数据源,纯更新语义(不会插入新行)---
100
100
  * --- MySQL: UPDATE t INNER JOIN (SELECT col AS alias ... UNION ALL SELECT ...) AS tmp ON t.key=tmp.key SET t.c=tmp.c ---
101
- * --- PostgreSQL: UPDATE t SET c=tmp.c FROM (VALUES ($1,...)) AS tmp(cols) WHERE t.key=tmp.key ---
101
+ * --- PostgreSQL: UPDATE t SET c=tmp.c FROM (VALUES (typed nulls), ($1,...)) AS tmp(cols) WHERE t.key=tmp.key ---
102
102
  * @param table 表名
103
103
  * @param key 用于定位待更新记录的字段名,通常为主键或唯一键,至少必须建立索引;
104
104
  * 该参数是字段名而不是索引名,仅参与 ON / WHERE 匹配,不会被更新
@@ -192,14 +192,13 @@ export declare class Sql {
192
192
  private _whereDataPosition;
193
193
  /**
194
194
  * --- 筛选器 ---
195
- * --- 1. 'city': 'bj', 'type': '2' ---
196
- * --- 2. ['type', '>', '1'] ---
197
- * --- 3. ['type', 'in', ['1', '2']] ---
198
- * --- 4. 'type': ['1', '2'] ---
199
- * --- 5. '$or': [{'city': 'bj'}, {'city': 'sh'}, [['age', '>', '10']]], 'type': '2' ---
200
- * --- 6. 'city_in': column('city_out') ---
201
- * --- 7. ['JSON_CONTAINS(`uid`, ?)', ['hello']] ---
202
- * --- 8. ['info', 'json', {'a': 1}] ---
195
+ * --- 标量相等:'city': 'bj', 'type': '2' ---
196
+ * --- 运算符条件:['type', '>', '1'] ---
197
+ * --- 集合条件:['type', 'in', ['1', '2']] 或 'type': ['1', '2'] ---
198
+ * --- 逻辑分组:'$or': [{'city': 'bj'}, {'city': 'sh'}, [['age', '>', '10']]] ---
199
+ * --- 字段比较:'city_in': column('city_out') ---
200
+ * --- 原始条件:['JSON_CONTAINS(`uid`, ?)', ['hello']] ---
201
+ * --- JSON 条件:['info', 'json', {'a': 1}] ---
203
202
  * @param s 筛选数据
204
203
  */
205
204
  where(s: string | kebab.Json): this;
@@ -274,11 +273,6 @@ export declare class Sql {
274
273
  private _isValue;
275
274
  /** --- 获取占位符 --- */
276
275
  private _placeholder;
277
- /**
278
- * --- 返回 PostgreSQL VALUES 第一行的显式类型转换后缀,用于帮助 PostgreSQL 推断 VALUES 派生表列类型 ---
279
- * @param v 要处理的值
280
- */
281
- private _pgCastSuffix;
282
276
  /**
283
277
  * --- 处理单个值,检测数据类型并返回 SQL 和 data ---
284
278
  * @param v 要处理的值
@@ -326,7 +320,8 @@ export declare function value(val: kebab.DbValue): {
326
320
  'value': kebab.DbValue;
327
321
  };
328
322
  /**
329
- * --- 将对象转换为 JSON 字符串并避开类型检查,用于适配 PostgreSQL 的 jsonb 字段 ---
330
- * @param obj 要转换的 JSON 对象
323
+ * --- 标记需要写入 JSON/jsonb 字段的值;实际序列化延迟到数据库边界 ---
324
+ * @param obj 原始 JSON 值
325
+ * @returns 类型保持不变的 JSON 包装值
331
326
  */
332
327
  export declare function json<T>(obj: T): T;