@servora/proto-utils 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.
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @servora/proto-utils — Proto/Kratos API 查询工具
3
+ *
4
+ * Kratos gRPC-gateway 的 ListRequest 约定:
5
+ * filter = JSON 序列化的过滤条件对象,空值字段会被省略
6
+ * order_by = JSON 序列化的排序字段数组,前缀 "-" 表示降序
7
+ * update_mask = 逗号分隔的字段名,用于 Proto FieldMask 部分更新
8
+ *
9
+ * 所有函数均返回新值,不修改入参。
10
+ */
11
+ /**
12
+ * 将过滤条件序列化为 Kratos ListRequest.filter 字符串。
13
+ *
14
+ * - null/undefined 入参返回 undefined(不传 filter 参数)
15
+ * - 自动过滤空值字段(null、undefined、空字符串)
16
+ * - 过滤后为空对象时返回 undefined
17
+ *
18
+ * @example
19
+ * makeFilter({ name: 'foo', status: null })
20
+ * // → '{"name":"foo"}'
21
+ *
22
+ * makeFilter({})
23
+ * // → undefined
24
+ */
25
+ export declare function makeFilter(fields?: null | Record<string, unknown>): string | undefined;
26
+ /**
27
+ * 将排序字段序列化为 Kratos ListRequest.order_by 字符串。
28
+ *
29
+ * - 前缀 "-" 表示降序,无前缀表示升序
30
+ * - 默认按 "-created_at" 降序(当入参为 null/undefined 时)
31
+ * - 空数组时返回 undefined
32
+ *
33
+ * @example
34
+ * makeOrderBy(['-created_at', 'name'])
35
+ * // → '["-created_at","name"]'
36
+ *
37
+ * makeOrderBy()
38
+ * // → '["-created_at"]'
39
+ */
40
+ export declare function makeOrderBy(fields?: null | string[]): string | undefined;
41
+ /**
42
+ * 生成 Proto FieldMask 字符串,用于 UpdateRequest.update_mask。
43
+ *
44
+ * - 自动包含 "id" 字段(Proto UpdateRequest 的标准约定)
45
+ * - 去重,保持传入顺序,id 追加到末尾
46
+ * - 不修改入参数组
47
+ *
48
+ * @example
49
+ * makeUpdateMask(['name', 'avatar'])
50
+ * // → 'name,avatar,id'
51
+ *
52
+ * makeUpdateMask(['name', 'id', 'avatar'])
53
+ * // → 'name,avatar,id' (id 不重复出现)
54
+ */
55
+ export declare function makeUpdateMask(fields: string[]): string;
56
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAIxE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAGvD"}
package/dist/query.js ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @servora/proto-utils — Proto/Kratos API 查询工具
3
+ *
4
+ * Kratos gRPC-gateway 的 ListRequest 约定:
5
+ * filter = JSON 序列化的过滤条件对象,空值字段会被省略
6
+ * order_by = JSON 序列化的排序字段数组,前缀 "-" 表示降序
7
+ * update_mask = 逗号分隔的字段名,用于 Proto FieldMask 部分更新
8
+ *
9
+ * 所有函数均返回新值,不修改入参。
10
+ */
11
+ /** 过滤掉 null、undefined、空字符串的字段 */
12
+ function omitEmpty(obj) {
13
+ return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== null && v !== undefined && v !== ''));
14
+ }
15
+ /**
16
+ * 将过滤条件序列化为 Kratos ListRequest.filter 字符串。
17
+ *
18
+ * - null/undefined 入参返回 undefined(不传 filter 参数)
19
+ * - 自动过滤空值字段(null、undefined、空字符串)
20
+ * - 过滤后为空对象时返回 undefined
21
+ *
22
+ * @example
23
+ * makeFilter({ name: 'foo', status: null })
24
+ * // → '{"name":"foo"}'
25
+ *
26
+ * makeFilter({})
27
+ * // → undefined
28
+ */
29
+ export function makeFilter(fields) {
30
+ if (fields == null)
31
+ return undefined;
32
+ const cleaned = omitEmpty(fields);
33
+ if (Object.keys(cleaned).length === 0)
34
+ return undefined;
35
+ return JSON.stringify(cleaned);
36
+ }
37
+ /**
38
+ * 将排序字段序列化为 Kratos ListRequest.order_by 字符串。
39
+ *
40
+ * - 前缀 "-" 表示降序,无前缀表示升序
41
+ * - 默认按 "-created_at" 降序(当入参为 null/undefined 时)
42
+ * - 空数组时返回 undefined
43
+ *
44
+ * @example
45
+ * makeOrderBy(['-created_at', 'name'])
46
+ * // → '["-created_at","name"]'
47
+ *
48
+ * makeOrderBy()
49
+ * // → '["-created_at"]'
50
+ */
51
+ export function makeOrderBy(fields) {
52
+ const resolved = fields ?? ['-created_at'];
53
+ if (resolved.length === 0)
54
+ return undefined;
55
+ return JSON.stringify(resolved);
56
+ }
57
+ /**
58
+ * 生成 Proto FieldMask 字符串,用于 UpdateRequest.update_mask。
59
+ *
60
+ * - 自动包含 "id" 字段(Proto UpdateRequest 的标准约定)
61
+ * - 去重,保持传入顺序,id 追加到末尾
62
+ * - 不修改入参数组
63
+ *
64
+ * @example
65
+ * makeUpdateMask(['name', 'avatar'])
66
+ * // → 'name,avatar,id'
67
+ *
68
+ * makeUpdateMask(['name', 'id', 'avatar'])
69
+ * // → 'name,avatar,id' (id 不重复出现)
70
+ */
71
+ export function makeUpdateMask(fields) {
72
+ const without = fields.filter((f) => f !== 'id');
73
+ return [...without, 'id'].join(',');
74
+ }
75
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iCAAiC;AACjC,SAAS,SAAS,CAAC,GAA4B;IAC7C,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CACxB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CACrD,CACF,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU,CACxB,MAAuC;IAEvC,IAAI,MAAM,IAAI,IAAI;QAAE,OAAO,SAAS,CAAA;IACpC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IACjC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IACvD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,CAAA;IAC1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;AACjC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,MAAgB;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;IAChD,OAAO,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACrC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@servora/proto-utils",
3
+ "version": "0.0.1",
4
+ "description": "Proto/Kratos API 查询工具:filter 序列化、order_by 编码、FieldMask 生成",
5
+ "type": "module",
6
+ "exports": {
7
+ "./query": {
8
+ "types": "./dist/query.d.ts",
9
+ "import": "./dist/query.js"
10
+ }
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "src",
15
+ "!src/**/*_test.ts"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.build.json",
19
+ "clean": "rm -rf dist",
20
+ "typecheck": "tsc --noEmit",
21
+ "prepublishOnly": "npm run clean && npm run build"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/Servora-Kit/servora-web.git",
26
+ "directory": "packages/proto-utils"
27
+ },
28
+ "homepage": "https://github.com/Servora-Kit/servora-web/tree/main/packages/proto-utils",
29
+ "bugs": {
30
+ "url": "https://github.com/Servora-Kit/servora-web/issues"
31
+ },
32
+ "license": "MIT",
33
+ "sideEffects": false,
34
+ "devDependencies": {
35
+ "typescript": "^5.7.2"
36
+ }
37
+ }
package/src/query.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @servora/proto-utils — Proto/Kratos API 查询工具
3
+ *
4
+ * Kratos gRPC-gateway 的 ListRequest 约定:
5
+ * filter = JSON 序列化的过滤条件对象,空值字段会被省略
6
+ * order_by = JSON 序列化的排序字段数组,前缀 "-" 表示降序
7
+ * update_mask = 逗号分隔的字段名,用于 Proto FieldMask 部分更新
8
+ *
9
+ * 所有函数均返回新值,不修改入参。
10
+ */
11
+
12
+ /** 过滤掉 null、undefined、空字符串的字段 */
13
+ function omitEmpty(obj: Record<string, unknown>): Record<string, unknown> {
14
+ return Object.fromEntries(
15
+ Object.entries(obj).filter(
16
+ ([, v]) => v !== null && v !== undefined && v !== '',
17
+ ),
18
+ )
19
+ }
20
+
21
+ /**
22
+ * 将过滤条件序列化为 Kratos ListRequest.filter 字符串。
23
+ *
24
+ * - null/undefined 入参返回 undefined(不传 filter 参数)
25
+ * - 自动过滤空值字段(null、undefined、空字符串)
26
+ * - 过滤后为空对象时返回 undefined
27
+ *
28
+ * @example
29
+ * makeFilter({ name: 'foo', status: null })
30
+ * // → '{"name":"foo"}'
31
+ *
32
+ * makeFilter({})
33
+ * // → undefined
34
+ */
35
+ export function makeFilter(
36
+ fields?: null | Record<string, unknown>,
37
+ ): string | undefined {
38
+ if (fields == null) return undefined
39
+ const cleaned = omitEmpty(fields)
40
+ if (Object.keys(cleaned).length === 0) return undefined
41
+ return JSON.stringify(cleaned)
42
+ }
43
+
44
+ /**
45
+ * 将排序字段序列化为 Kratos ListRequest.order_by 字符串。
46
+ *
47
+ * - 前缀 "-" 表示降序,无前缀表示升序
48
+ * - 默认按 "-created_at" 降序(当入参为 null/undefined 时)
49
+ * - 空数组时返回 undefined
50
+ *
51
+ * @example
52
+ * makeOrderBy(['-created_at', 'name'])
53
+ * // → '["-created_at","name"]'
54
+ *
55
+ * makeOrderBy()
56
+ * // → '["-created_at"]'
57
+ */
58
+ export function makeOrderBy(fields?: null | string[]): string | undefined {
59
+ const resolved = fields ?? ['-created_at']
60
+ if (resolved.length === 0) return undefined
61
+ return JSON.stringify(resolved)
62
+ }
63
+
64
+ /**
65
+ * 生成 Proto FieldMask 字符串,用于 UpdateRequest.update_mask。
66
+ *
67
+ * - 自动包含 "id" 字段(Proto UpdateRequest 的标准约定)
68
+ * - 去重,保持传入顺序,id 追加到末尾
69
+ * - 不修改入参数组
70
+ *
71
+ * @example
72
+ * makeUpdateMask(['name', 'avatar'])
73
+ * // → 'name,avatar,id'
74
+ *
75
+ * makeUpdateMask(['name', 'id', 'avatar'])
76
+ * // → 'name,avatar,id' (id 不重复出现)
77
+ */
78
+ export function makeUpdateMask(fields: string[]): string {
79
+ const without = fields.filter((f) => f !== 'id')
80
+ return [...without, 'id'].join(',')
81
+ }