@ai0x0/utils 0.6.0 → 0.6.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.
Files changed (49) hide show
  1. package/es/backend/actions/create-delete-action.d.ts +2 -3
  2. package/es/backend/actions/create-delete-action.js +8 -44
  3. package/es/backend/actions/create-put-action.d.ts +1 -1
  4. package/es/backend/actions/create-put-action.js +15 -39
  5. package/es/backend/actions/get-list-query-core.d.ts +46 -0
  6. package/es/backend/actions/get-list-query-core.js +236 -0
  7. package/es/backend/actions/get-list-query.d.ts +5 -18
  8. package/es/backend/actions/get-list-query.js +20 -220
  9. package/es/backend/actions/write-action-core.d.ts +18 -0
  10. package/es/backend/actions/write-action-core.js +119 -0
  11. package/es/backend/schemas/common.d.ts +112 -0
  12. package/es/backend/schemas/common.js +158 -0
  13. package/es/backend/schemas/index.d.ts +735 -364
  14. package/es/backend/schemas/index.js +8 -139
  15. package/es/backend/sqlite/actions/create-delete-action.d.ts +1 -2
  16. package/es/backend/sqlite/actions/create-delete-action.js +7 -43
  17. package/es/backend/sqlite/actions/create-put-action.d.ts +1 -1
  18. package/es/backend/sqlite/actions/create-put-action.js +13 -36
  19. package/es/backend/sqlite/actions/get-list-query.d.ts +4 -9
  20. package/es/backend/sqlite/actions/get-list-query.js +20 -217
  21. package/es/backend/sqlite/errors.d.ts +1 -4
  22. package/es/backend/sqlite/errors.js +6 -31
  23. package/es/backend/sqlite/schemas/index.d.ts +1 -111
  24. package/es/backend/sqlite/schemas/index.js +8 -139
  25. package/lib/backend/actions/create-delete-action.d.ts +2 -3
  26. package/lib/backend/actions/create-delete-action.js +2 -14
  27. package/lib/backend/actions/create-put-action.d.ts +1 -1
  28. package/lib/backend/actions/create-put-action.js +3 -16
  29. package/lib/backend/actions/get-list-query-core.d.ts +46 -0
  30. package/lib/backend/actions/get-list-query-core.js +151 -0
  31. package/lib/backend/actions/get-list-query.d.ts +5 -18
  32. package/lib/backend/actions/get-list-query.js +16 -141
  33. package/lib/backend/actions/write-action-core.d.ts +18 -0
  34. package/lib/backend/actions/write-action-core.js +70 -0
  35. package/lib/backend/schemas/common.d.ts +112 -0
  36. package/lib/backend/schemas/common.js +112 -0
  37. package/lib/backend/schemas/index.d.ts +735 -364
  38. package/lib/backend/schemas/index.js +12 -83
  39. package/lib/backend/sqlite/actions/create-delete-action.d.ts +1 -2
  40. package/lib/backend/sqlite/actions/create-delete-action.js +2 -14
  41. package/lib/backend/sqlite/actions/create-put-action.d.ts +1 -1
  42. package/lib/backend/sqlite/actions/create-put-action.js +3 -16
  43. package/lib/backend/sqlite/actions/get-list-query.d.ts +4 -9
  44. package/lib/backend/sqlite/actions/get-list-query.js +16 -141
  45. package/lib/backend/sqlite/errors.d.ts +1 -4
  46. package/lib/backend/sqlite/errors.js +2 -8
  47. package/lib/backend/sqlite/schemas/index.d.ts +1 -111
  48. package/lib/backend/sqlite/schemas/index.js +12 -83
  49. package/package.json +1 -1
@@ -1,31 +1,6 @@
1
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
3
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
4
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
6
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
7
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
8
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
9
- function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
10
- function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
11
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
12
- function _isNativeFunction(fn) { try { return Function.toString.call(fn).indexOf("[native code]") !== -1; } catch (e) { return typeof fn === "function"; } }
13
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
14
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
15
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
16
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
17
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
18
- export var HttpError = /*#__PURE__*/function (_Error) {
19
- _inherits(HttpError, _Error);
20
- var _super = _createSuper(HttpError);
21
- function HttpError(status, message) {
22
- var _this;
23
- _classCallCheck(this, HttpError);
24
- _this = _super.call(this, message);
25
- _defineProperty(_assertThisInitialized(_this), "status", void 0);
26
- _this.name = "HttpError";
27
- _this.status = status;
28
- return _this;
29
- }
30
- return _createClass(HttpError);
31
- }( /*#__PURE__*/_wrapNativeSuper(Error));
1
+ // HttpError 与 pg 那套是同一个类,没有任何方言相关的东西 —— 从前这里是逐字抄的一份副本,
2
+ // 于是「同一个错误」在两棵树里是两个类:`instanceof` 互不认,而 handleOperationError 判的是
3
+ // `error.name === "HttpError"`,副本恰好蒙混过关,所以这份重复一直没被发现。
4
+ //
5
+ // 现在直接转出去。sqlite 的调用方仍然从 `@/backend/sqlite/errors` 引,import 路径不用改。
6
+ export { HttpError } from "../errors.js";
@@ -1,4 +1,3 @@
1
- import { z } from "zod";
2
1
  import { type SQLiteColumnBuilderBase, type SQLiteTableExtraConfigValue } from "drizzle-orm/sqlite-core";
3
2
  import type { BuildExtraConfigColumns } from "drizzle-orm";
4
3
  export declare const basicFields: {
@@ -9,116 +8,7 @@ export declare const basicFields: {
9
8
  createdAt: import("drizzle-orm").HasRuntimeDefault<import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/sqlite-core").SQLiteTimestampBuilderInitial<string>>>>;
10
9
  updatedAt: import("drizzle-orm").HasRuntimeDefault<import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/sqlite-core").SQLiteTimestampBuilderInitial<string>>>>;
11
10
  };
12
- /**
13
- * 业务侧 insert schema 需要从 drizzle-zod 生成的 schema 中排除的基础字段。
14
- * 这些字段由后端在 createPostAction 中自动写入。
15
- *
16
- * 使用方式(在业务 schema 中):
17
- * const insertFooSchema = createInsertSchema(foos)
18
- * .omit(BASIC_INSERT_OMIT)
19
- * .extend({ ... });
20
- *
21
- * 说明:上游导出为 const 而不是 helper function,是为了避免经过泛型
22
- * wrapper 后 TS 把 drizzle-zod 推导出的深层条件 Shape 归约成 Omit,
23
- * 从而在下游 `.extend(...)` 时丢失原有字段类型。
24
- */
25
- export declare const BASIC_INSERT_OMIT: {
26
- readonly id: true;
27
- readonly creatorId: true;
28
- readonly editorId: true;
29
- readonly accessedAt: true;
30
- readonly createdAt: true;
31
- readonly updatedAt: true;
32
- };
33
- /**
34
- * 业务侧 update schema 需要从 drizzle-zod 生成的 schema 中排除的基础字段。
35
- * update 保留 id(随后用 `.required({ id: true })` 变成必填),其余由
36
- * 后端 createPutAction 自动维护。
37
- */
38
- export declare const BASIC_UPDATE_OMIT: {
39
- readonly creatorId: true;
40
- readonly editorId: true;
41
- readonly accessedAt: true;
42
- readonly createdAt: true;
43
- readonly updatedAt: true;
44
- };
45
- export declare const queryListSchema: <Incoming extends z.ZodObject<z.core.$ZodLooseShape, z.core.$strip>>(schema: Incoming) => z.ZodObject<(("creatorId" | "orderBy" | "orderDir" | "pageSize" | "current" | "createdAtFrom" | "createdAtTo") & keyof Incoming["shape"] extends never ? {
46
- current: z.ZodDefault<z.ZodOptional<z.ZodString>>;
47
- pageSize: z.ZodDefault<z.ZodOptional<z.ZodString>>;
48
- createdAtFrom: z.ZodOptional<z.ZodString>;
49
- createdAtTo: z.ZodOptional<z.ZodString>;
50
- orderBy: z.ZodOptional<z.ZodString>;
51
- creatorId: z.ZodOptional<z.ZodString>;
52
- orderDir: z.ZodOptional<z.ZodEnum<{
53
- asc: "asc";
54
- desc: "desc";
55
- }>>;
56
- } & Incoming["shape"] : ({
57
- current: z.ZodDefault<z.ZodOptional<z.ZodString>>;
58
- pageSize: z.ZodDefault<z.ZodOptional<z.ZodString>>;
59
- createdAtFrom: z.ZodOptional<z.ZodString>;
60
- createdAtTo: z.ZodOptional<z.ZodString>;
61
- orderBy: z.ZodOptional<z.ZodString>;
62
- creatorId: z.ZodOptional<z.ZodString>;
63
- orderDir: z.ZodOptional<z.ZodEnum<{
64
- asc: "asc";
65
- desc: "desc";
66
- }>>;
67
- } extends infer T_1 extends z.core.util.SomeObject ? { [K in keyof T_1 as K extends keyof Incoming["shape"] ? never : K]: {
68
- current: z.ZodDefault<z.ZodOptional<z.ZodString>>;
69
- pageSize: z.ZodDefault<z.ZodOptional<z.ZodString>>;
70
- createdAtFrom: z.ZodOptional<z.ZodString>;
71
- createdAtTo: z.ZodOptional<z.ZodString>;
72
- orderBy: z.ZodOptional<z.ZodString>;
73
- creatorId: z.ZodOptional<z.ZodString>;
74
- orderDir: z.ZodOptional<z.ZodEnum<{
75
- asc: "asc";
76
- desc: "desc";
77
- }>>;
78
- }[K]; } : never) & (Incoming["shape"] extends infer T_2 extends z.core.util.SomeObject ? { [K_1 in keyof T_2]: Incoming["shape"][K_1]; } : never)) extends infer T ? { [k in keyof T]: (("creatorId" | "orderBy" | "orderDir" | "pageSize" | "current" | "createdAtFrom" | "createdAtTo") & keyof Incoming["shape"] extends never ? {
79
- current: z.ZodDefault<z.ZodOptional<z.ZodString>>;
80
- pageSize: z.ZodDefault<z.ZodOptional<z.ZodString>>;
81
- createdAtFrom: z.ZodOptional<z.ZodString>;
82
- createdAtTo: z.ZodOptional<z.ZodString>;
83
- orderBy: z.ZodOptional<z.ZodString>;
84
- creatorId: z.ZodOptional<z.ZodString>;
85
- orderDir: z.ZodOptional<z.ZodEnum<{
86
- asc: "asc";
87
- desc: "desc";
88
- }>>;
89
- } & Incoming["shape"] : ({
90
- current: z.ZodDefault<z.ZodOptional<z.ZodString>>;
91
- pageSize: z.ZodDefault<z.ZodOptional<z.ZodString>>;
92
- createdAtFrom: z.ZodOptional<z.ZodString>;
93
- createdAtTo: z.ZodOptional<z.ZodString>;
94
- orderBy: z.ZodOptional<z.ZodString>;
95
- creatorId: z.ZodOptional<z.ZodString>;
96
- orderDir: z.ZodOptional<z.ZodEnum<{
97
- asc: "asc";
98
- desc: "desc";
99
- }>>;
100
- } extends infer T_1 extends z.core.util.SomeObject ? { [K in keyof T_1 as K extends keyof Incoming["shape"] ? never : K]: {
101
- current: z.ZodDefault<z.ZodOptional<z.ZodString>>;
102
- pageSize: z.ZodDefault<z.ZodOptional<z.ZodString>>;
103
- createdAtFrom: z.ZodOptional<z.ZodString>;
104
- createdAtTo: z.ZodOptional<z.ZodString>;
105
- orderBy: z.ZodOptional<z.ZodString>;
106
- creatorId: z.ZodOptional<z.ZodString>;
107
- orderDir: z.ZodOptional<z.ZodEnum<{
108
- asc: "asc";
109
- desc: "desc";
110
- }>>;
111
- }[K]; } : never) & (Incoming["shape"] extends infer T_2 extends z.core.util.SomeObject ? { [K_1 in keyof T_2]: Incoming["shape"][K_1]; } : never))[k]; } : never, Incoming["_zod"]["config"]>;
112
- export declare const listBodySchema: <T extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>(schema: T) => z.ZodObject<{
113
- total: z.ZodNumber;
114
- data: z.ZodArray<T>;
115
- }, z.core.$strip>;
116
- /**
117
- * 给 schema 上已有的字段挂说明。字段不在这个 schema 里就跳过 —— 同一张表的
118
- * insert / update / select 三份含的列不一样(basicFields 只在 select 里),一份说明表要能同时
119
- * 喂给三者,就不能对「字段一定存在」有要求。**不给不存在的字段凭空造一个。**
120
- */
121
- export declare const describeFields: <T extends z.ZodObject<z.core.$ZodLooseShape, z.core.$strip>>(schema: T, notes: Record<string, string>) => T;
11
+ export { BASIC_INSERT_OMIT, BASIC_UPDATE_OMIT, describeFields, listBodySchema, queryListSchema, } from "../../schemas/common.js";
122
12
  /**
123
13
  * 基于 drizzle + drizzle-zod 快速生成带基础字段(id / 创建时间等)的
124
14
  * 表定义以及 select / insert / update / query / list zod schema。
@@ -4,12 +4,6 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
8
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
9
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
10
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
11
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
13
7
  import { z } from "zod";
14
8
  import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
15
9
  import { createInsertSchema, createSelectSchema, createUpdateSchema } from "drizzle-zod";
@@ -46,141 +40,16 @@ export var basicFields = {
46
40
  updatedAt: updatedAt()
47
41
  };
48
42
 
49
- /**
50
- * 业务侧 insert schema 需要从 drizzle-zod 生成的 schema 中排除的基础字段。
51
- * 这些字段由后端在 createPostAction 中自动写入。
52
- *
53
- * 使用方式(在业务 schema 中):
54
- * const insertFooSchema = createInsertSchema(foos)
55
- * .omit(BASIC_INSERT_OMIT)
56
- * .extend({ ... });
57
- *
58
- * 说明:上游导出为 const 而不是 helper function,是为了避免经过泛型
59
- * wrapper 后 TS 把 drizzle-zod 推导出的深层条件 Shape 归约成 Omit,
60
- * 从而在下游 `.extend(...)` 时丢失原有字段类型。
61
- */
62
- export var BASIC_INSERT_OMIT = {
63
- id: true,
64
- creatorId: true,
65
- editorId: true,
66
- accessedAt: true,
67
- createdAt: true,
68
- updatedAt: true
69
- };
70
-
71
- /**
72
- * 业务侧 update schema 需要从 drizzle-zod 生成的 schema 中排除的基础字段。
73
- * update 保留 id(随后用 `.required({ id: true })` 变成必填),其余由
74
- * 后端 createPutAction 自动维护。
75
- */
76
- export var BASIC_UPDATE_OMIT = {
77
- creatorId: true,
78
- editorId: true,
79
- accessedAt: true,
80
- createdAt: true,
81
- updatedAt: true
82
- };
83
-
84
- // =============================================================================
85
- // 列表查询字段
86
- // =============================================================================
87
- // 说明写成 `.describe()` 而不是行末注释:注释只有读源码的人看得到,而这七个字段会出现在每一个
88
- // list 端点的 OpenAPI spec 里,再从那里流进生成的 client 与 CLI 文档。写成注释的代价是下游只能
89
- // 自己再手写一份 —— 那份必然会漂,而且漂了没有任何东西会报错。
90
- //
91
- // 类型是 string 而不是 number:query 参数在线上只有字符串,服务端收下之后才转数字。默认值也
92
- // 因此是 "1" / "10"。
93
- export var queryListSchema = function queryListSchema(schema) {
94
- return z.object({
95
- current: z.string().optional().default("1").describe("Page number, starting at 1."),
96
- pageSize: z.string().optional().default("10").describe("Rows per page. Omitting it yields only 10 — pass a larger value to get the whole set."),
97
- createdAtFrom: z.string().optional().describe("Keep only rows created at or after this instant (ISO 8601, e.g. 2026-08-01T00:00:00Z)."),
98
- createdAtTo: z.string().optional().describe("Keep only rows created at or before this instant."),
99
- orderBy: z.string().optional().describe("Column to sort by — a column name of this resource (createdAt / updatedAt and the like)."),
100
- creatorId: z.string().optional().describe("Keep only rows created by this user. Useful in shared spaces to filter down to one member."),
101
- orderDir: z.enum(["asc", "desc"]).optional().describe("Sort ascending or descending.")
102
- }).merge(schema);
103
- };
104
-
105
43
  // =============================================================================
106
- // 列表返回字段
44
+ // 与方言无关的那几份助手
107
45
  // =============================================================================
108
- // 这两个字段出现在**每一个** list 端点的响应里,所以说明写在这儿一次就够 —— 下游那边它们是
109
- // 逐个 list 命令重复一遍的(在一个 101 端点的项目上是 24 行空白)。
110
- export var listBodySchema = function listBodySchema(schema) {
111
- return z.object({
112
- total: z.number().describe("Total number of rows matching the filters — not the length of `data`. Use it to decide whether another page exists."),
113
- data: z.array(schema).describe("This page's rows.")
114
- });
115
- };
116
-
117
- // =============================================================================
118
- // 给基础字段挂说明
119
- // =============================================================================
120
- // basicFields 是 drizzle 列,而 drizzle 列没有「描述」这个概念 —— 所以说明只能挂在
121
- // drizzle-zod 出来的 schema 上。值得做是因为这六个字段出现在**每一张表**的 select schema 里:
122
- // 一处写完,所有 list / get 端点的返回字段都有说明了。
123
- //
124
- // 一律只挂元数据,**不换类型**:`.describe()` / `.meta()` 返回的是带元数据的克隆,校验行为一模
125
- // 一样。selectSchema 是有人拿去 safeParse 的(本包自己的测试就在用 Date 校验它),换类型等于改
126
- // 这个包的契约。
127
- //
128
- // 时间戳那三列额外用 `.meta()` 补上 JSON Schema 表示,因为不补就是错的:drizzle-zod 给的是
129
- // `z.date()`,而 `Date` 在 JSON Schema 里表达不出来,于是这三个字段在 spec 里是**空对象** ——
130
- // 没有 `type`,照 spec 生成的 client / CLI 只能得到 `unknown`。而线上根本不可能是 Date:响应一经
131
- // JSON 序列化就是 ISO 8601 字符串。
132
- //
133
- // `.meta({ type, format })` 恰好只改「怎么描述」不改「怎么校验」:spec 里成为
134
- // `{"type":"string","format":"date-time"}`,而 `safeParse(new Date())` 照样通过。
135
- // 不用 `z.iso.datetime()` 换掉它,是因为那既改了校验(不再收 Date),又会往 JSON Schema 里塞一条
136
- // 380 字节的正则 —— 乘上每张表几十 KB,而 `format` 已经把「按日期时间解析」说清楚了。
137
- var BASIC_FIELD_NOTES = {
138
- creatorId: "User id of the creator. Stamped by the server; clients cannot send it.",
139
- editorId: "User id of whoever changed this row last. Stamped by the server; clients cannot send it.",
140
- id: "Primary key of this row (uuid)."
141
- };
142
- var BASIC_TIMESTAMP_NOTES = {
143
- accessedAt: "When this row was last accessed.",
144
- createdAt: "When this row was created.",
145
- updatedAt: "When this row was last modified."
146
- };
147
-
148
- /**
149
- * 给 schema 上已有的字段挂说明。字段不在这个 schema 里就跳过 —— 同一张表的
150
- * insert / update / select 三份含的列不一样(basicFields 只在 select 里),一份说明表要能同时
151
- * 喂给三者,就不能对「字段一定存在」有要求。**不给不存在的字段凭空造一个。**
152
- */
153
- export var describeFields = function describeFields(schema, notes) {
154
- var overlay = {};
155
- for (var _i = 0, _Object$entries = Object.entries(notes); _i < _Object$entries.length; _i++) {
156
- var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
157
- field = _Object$entries$_i[0],
158
- note = _Object$entries$_i[1];
159
- var existing = schema.shape[field];
160
- if (existing) {
161
- overlay[field] = existing.describe(note);
162
- }
163
- }
164
- return Object.keys(overlay).length ? schema.extend(overlay) : schema;
165
- };
166
- var describeBasicFields = function describeBasicFields(schema) {
167
- var withNotes = describeFields(schema, BASIC_FIELD_NOTES);
168
- var overlay = {};
169
- for (var _i2 = 0, _Object$entries2 = Object.entries(BASIC_TIMESTAMP_NOTES); _i2 < _Object$entries2.length; _i2++) {
170
- var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
171
- field = _Object$entries2$_i[0],
172
- note = _Object$entries2$_i[1];
173
- var existing = withNotes.shape[field];
174
- if (existing) {
175
- overlay[field] = existing.meta({
176
- description: note,
177
- format: "date-time",
178
- type: "string"
179
- });
180
- }
181
- }
182
- return Object.keys(overlay).length ? withNotes.extend(overlay) : withNotes;
183
- };
46
+ // BASIC_INSERT_OMIT / BASIC_UPDATE_OMIT / queryListSchema / listBodySchema / describeFields
47
+ // 都只碰 zod,两套方言逐字相同 —— 实现搬去了 schemas/common,这里原样转出去,调用方的
48
+ // import 路径一个字都不用改。
49
+ // createTableSchema 自己也要用其中几个 —— `export ... from` 只转发、不把名字带进
50
+ // 本地作用域,所以这里还得再 import 一次。
51
+ import { describeBasicFields, describeFields, queryListSchema } from "../../schemas/common.js";
52
+ export { BASIC_INSERT_OMIT, BASIC_UPDATE_OMIT, describeFields, listBodySchema, queryListSchema } from "../../schemas/common.js";
184
53
 
185
54
  // =============================================================================
186
55
  // 建表 —— 表 + 5 份 zod schema
@@ -1,11 +1,10 @@
1
1
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
2
2
  import { BaseTable } from "../types.js";
3
- import { ScopeArg } from "../scope.js";
4
3
  export declare function createDeleteAction<TTable extends BaseTable>({ table, db, }: {
5
4
  db: NodePgDatabase<Record<string, unknown>>;
6
5
  table: TTable;
7
6
  }): ({ id }: {
8
7
  id: string;
9
8
  }, { scope }: {
10
- scope: ScopeArg;
11
- }) => Promise<TTable["$inferSelect"] extends infer T ? T extends TTable["$inferSelect"] ? T extends undefined ? QueryResult<import("drizzle-orm").Assume<this["row"], QueryResultRow>> : T[] : never : never>;
9
+ scope: import("..").ScopeArg;
10
+ }) => Promise<any>;
@@ -22,24 +22,12 @@ __export(create_delete_action_exports, {
22
22
  createDeleteAction: () => createDeleteAction
23
23
  });
24
24
  module.exports = __toCommonJS(create_delete_action_exports);
25
- var import_drizzle_orm = require("drizzle-orm");
26
- var import_scope = require("../scope");
27
- var import_errors = require("../errors");
25
+ var import_write_action_core = require("./write-action-core");
28
26
  function createDeleteAction({
29
27
  table,
30
28
  db
31
29
  }) {
32
- return async ({ id }, { scope }) => {
33
- if (!id) {
34
- throw new import_errors.HttpError(400, "缺少 id");
35
- }
36
- const guard = (0, import_scope.scopeCondition)(table, scope);
37
- const rows = await db.delete(table).where(guard ? (0, import_drizzle_orm.and)((0, import_drizzle_orm.eq)(table.id, id), guard) : (0, import_drizzle_orm.eq)(table.id, id)).returning();
38
- if (rows.length === 0 && scope !== import_scope.NO_SCOPE) {
39
- throw new import_errors.HttpError(404, "未找到删除对象,或没有权限");
40
- }
41
- return rows;
42
- };
30
+ return (0, import_write_action_core.createDeleteActionCore)({ db, table });
43
31
  }
44
32
  // Annotate the CommonJS export names for ESM import in node:
45
33
  0 && (module.exports = {
@@ -6,6 +6,6 @@ export declare function createPutAction<T extends ZodSchema, TTable extends Base
6
6
  bodySchema: T;
7
7
  db: NodePgDatabase<Record<string, unknown>>;
8
8
  table: TTable;
9
- }): (body: Partial<z.infer<T>> & Record<string, unknown>, { scope }: {
9
+ }): (body: Partial<z.infer<T>> & Record<string, unknown>, options: {
10
10
  scope: ScopeArg;
11
11
  }) => Promise<z.infer<T>>;
@@ -22,26 +22,13 @@ __export(create_put_action_exports, {
22
22
  createPutAction: () => createPutAction
23
23
  });
24
24
  module.exports = __toCommonJS(create_put_action_exports);
25
- var import_transform_body = require("./transform-body");
26
- var import_drizzle_orm = require("drizzle-orm");
27
- var import_scope = require("../scope");
28
- var import_errors = require("../errors");
25
+ var import_write_action_core = require("./write-action-core");
29
26
  function createPutAction({
30
27
  db,
31
28
  table
32
29
  }) {
33
- return async (body, { scope }) => {
34
- const id = body.id;
35
- if (!id) {
36
- throw new import_errors.HttpError(400, "缺少 id");
37
- }
38
- const guard = (0, import_scope.scopeCondition)(table, scope);
39
- const [data] = await db.update(table).set((0, import_transform_body.transformBody)(body)).where(guard ? (0, import_drizzle_orm.and)((0, import_drizzle_orm.eq)(table.id, id), guard) : (0, import_drizzle_orm.eq)(table.id, id)).returning();
40
- if (!data && scope !== import_scope.NO_SCOPE) {
41
- throw new import_errors.HttpError(404, "未找到编辑对象,或没有权限");
42
- }
43
- return data;
44
- };
30
+ const run = (0, import_write_action_core.createPutActionCore)({ db, table });
31
+ return async (body, options) => await run(body, options);
45
32
  }
46
33
  // Annotate the CommonJS export names for ESM import in node:
47
34
  0 && (module.exports = {
@@ -0,0 +1,46 @@
1
+ import { Column, SQL } from "drizzle-orm";
2
+ import { ScopeArg } from "../scope.js";
3
+ /**
4
+ * 核心用得到表的哪一部分:只有 `id`(计数与分组要它)和「按列名取列」。
5
+ * 两棵树的 BaseTable 都满足它,而 dialect 各自的 Table 类型不必进来。
6
+ */
7
+ export interface ListQueryTable {
8
+ id: Column;
9
+ }
10
+ export interface ListQueryRelation {
11
+ groupBy?: boolean;
12
+ select?: Record<string, unknown>;
13
+ sql?: SQL;
14
+ table?: ListQueryTable;
15
+ }
16
+ /** 两套方言之间**全部**的差异。加第三种数据库时要写的也只有这两条。 */
17
+ export interface ListQueryDialect {
18
+ /** 大小写不敏感的「包含」。 */
19
+ contains(_column: Column, _keyword: string): SQL;
20
+ /** 「这个 JSON 数组列里有没有元素含这段文字」。 */
21
+ jsonArrayContains(_column: Column, _keyword: string): SQL;
22
+ }
23
+ export interface ListQueryParams {
24
+ [field: string]: unknown;
25
+ orderBy?: string;
26
+ orderDir?: "asc" | "desc";
27
+ page?: number;
28
+ pageSize?: number;
29
+ }
30
+ export declare function createGetListQuery(dialect: ListQueryDialect): <TTable extends ListQueryTable, TSelection extends Record<string, unknown>>({ db, fields, jsonArrayFields, params, relations, scope, table, }: {
31
+ db: any;
32
+ fields: TSelection;
33
+ jsonArrayFields?: string[] | undefined;
34
+ /**
35
+ * 行级作用域。**必填**,不想隔离就显式传 NO_SCOPE —— 写成可选的话,漏传就退化成查全表,
36
+ * 而那是静默的越权(见 scope.ts)。它不走下面 params 那条筛选通道,因为那条的规矩是
37
+ * 「空值跳过」,一个取不到值的作用域会让整条 where 消失。
38
+ */
39
+ scope: ScopeArg;
40
+ params: ListQueryParams;
41
+ relations?: ListQueryRelation[] | undefined;
42
+ table: TTable;
43
+ }) => {
44
+ countQuery: any;
45
+ query: any;
46
+ };
@@ -0,0 +1,151 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc2) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/backend/actions/get-list-query-core.ts
20
+ var get_list_query_core_exports = {};
21
+ __export(get_list_query_core_exports, {
22
+ createGetListQuery: () => createGetListQuery
23
+ });
24
+ module.exports = __toCommonJS(get_list_query_core_exports);
25
+ var import_drizzle_orm = require("drizzle-orm");
26
+ var import_scope = require("../scope");
27
+ function columnAt(table, key) {
28
+ return table[key];
29
+ }
30
+ function createGetListQuery(dialect) {
31
+ return function getListQuery({
32
+ db,
33
+ fields,
34
+ jsonArrayFields,
35
+ params,
36
+ relations,
37
+ scope,
38
+ table
39
+ }) {
40
+ const {
41
+ page = 1,
42
+ pageSize = 10,
43
+ orderBy = "createdAt",
44
+ orderDir = "desc",
45
+ ...filters
46
+ } = params;
47
+ function buildBaseQuery() {
48
+ let queryFields = { ...fields };
49
+ if (relations == null ? void 0 : relations.length) {
50
+ for (const { select } of relations) {
51
+ queryFields = { ...queryFields, ...select };
52
+ }
53
+ }
54
+ const query2 = db.select(queryFields).from(table);
55
+ if (relations == null ? void 0 : relations.length) {
56
+ query2.groupBy(
57
+ table.id,
58
+ ...relations.filter(({ groupBy }) => groupBy).filter(({ table: joined }) => joined).map(({ table: joined }) => joined.id)
59
+ );
60
+ }
61
+ return query2;
62
+ }
63
+ function findTargetColumn(key) {
64
+ return [table].concat(
65
+ (relations == null ? void 0 : relations.filter(({ table: joined }) => joined).map(({ table: joined }) => joined)) || []
66
+ ).map((candidate) => columnAt(candidate, key)).find(Boolean);
67
+ }
68
+ function addCondition(conditions2, key, value, targetColumn) {
69
+ const isIdField = /id/i.test(key);
70
+ const isJsonArray = jsonArrayFields == null ? void 0 : jsonArrayFields.includes(key);
71
+ if (typeof value !== "string") {
72
+ conditions2.push((0, import_drizzle_orm.eq)(targetColumn, value));
73
+ return;
74
+ }
75
+ if (value.includes(",")) {
76
+ const values = value.split(",").map((item) => item.trim()).filter(Boolean);
77
+ if (!values.length) {
78
+ return;
79
+ }
80
+ if (isJsonArray) {
81
+ conditions2.push(dialect.jsonArrayContains(targetColumn, values[0]));
82
+ } else if (isIdField) {
83
+ conditions2.push((0, import_drizzle_orm.inArray)(targetColumn, values));
84
+ } else {
85
+ conditions2.push(
86
+ (0, import_drizzle_orm.or)(
87
+ ...values.map((item) => dialect.contains(targetColumn, item))
88
+ )
89
+ );
90
+ }
91
+ return;
92
+ }
93
+ if (isJsonArray) {
94
+ conditions2.push(dialect.jsonArrayContains(targetColumn, value));
95
+ } else if (isIdField) {
96
+ conditions2.push((0, import_drizzle_orm.eq)(targetColumn, value));
97
+ } else {
98
+ conditions2.push(dialect.contains(targetColumn, value));
99
+ }
100
+ }
101
+ function buildConditions() {
102
+ const conditions2 = [];
103
+ for (const [key, value] of Object.entries(filters)) {
104
+ if (!value) {
105
+ continue;
106
+ }
107
+ if (key.endsWith("AtFrom") || key.endsWith("AtTo")) {
108
+ const baseFieldName = key.replace(/(AtFrom|AtTo)$/, "");
109
+ const targetColumn2 = findTargetColumn(`${baseFieldName}At`);
110
+ if (!targetColumn2) {
111
+ continue;
112
+ }
113
+ conditions2.push(
114
+ key.endsWith("AtFrom") ? (0, import_drizzle_orm.gte)(targetColumn2, new Date(value)) : (0, import_drizzle_orm.lte)(targetColumn2, new Date(value))
115
+ );
116
+ continue;
117
+ }
118
+ const targetColumn = findTargetColumn(key);
119
+ if (!targetColumn) {
120
+ continue;
121
+ }
122
+ addCondition(conditions2, key, value, targetColumn);
123
+ }
124
+ return conditions2;
125
+ }
126
+ function buildOrderBy() {
127
+ const orderColumn = columnAt(table, orderBy);
128
+ return orderDir === "asc" ? (0, import_drizzle_orm.asc)(orderColumn) : (0, import_drizzle_orm.desc)(orderColumn);
129
+ }
130
+ const baseQuery = buildBaseQuery();
131
+ const scopeSql = (0, import_scope.scopeCondition)(table, scope);
132
+ const conditions = scopeSql ? [scopeSql] : [];
133
+ conditions.push(...buildConditions());
134
+ const where = conditions.length > 0 ? (0, import_drizzle_orm.and)(...conditions) : void 0;
135
+ const query = baseQuery.where(where).orderBy(buildOrderBy()).limit(pageSize).offset((page - 1) * pageSize);
136
+ const countQuery = db.select({ count: import_drizzle_orm.sql`COUNT(DISTINCT ${table.id})` }).from(table).where(where);
137
+ if (relations == null ? void 0 : relations.length) {
138
+ for (const { table: relationTable, sql: joinSql } of relations) {
139
+ if (relationTable) {
140
+ query.leftJoin(relationTable, joinSql);
141
+ countQuery.leftJoin(relationTable, joinSql);
142
+ }
143
+ }
144
+ }
145
+ return { countQuery, query };
146
+ };
147
+ }
148
+ // Annotate the CommonJS export names for ESM import in node:
149
+ 0 && (module.exports = {
150
+ createGetListQuery
151
+ });
@@ -1,34 +1,21 @@
1
1
  import { BaseTable, GetListRelations } from "../types.js";
2
2
  import { SelectedFields } from "drizzle-orm/pg-core/query-builders/select.types";
3
- import { SQL } from "drizzle-orm";
4
3
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
5
4
  import { ScopeArg } from "../scope.js";
6
- export declare function getListQuery<TTable extends BaseTable, TSelection extends SelectedFields>({ db, fields, jsonArrayFields, params, relations, scope, table, }: {
5
+ import { type ListQueryParams } from "./get-list-query-core.js";
6
+ export declare function getListQuery<TTable extends BaseTable, TSelection extends SelectedFields>(args: {
7
7
  db: NodePgDatabase<Record<string, unknown>>;
8
8
  fields: TSelection;
9
9
  jsonArrayFields?: string[];
10
10
  /**
11
11
  * 行级作用域。**必填**,不想隔离就显式传 NO_SCOPE —— 写成可选的话,漏传就退化成查全表,
12
- * 而那是静默的越权(见 scope.ts)。它不走下面 params 那条筛选通道,因为那条的规矩是
13
- * 「空值跳过」,一个取不到值的作用域会让整条 where 消失。
12
+ * 而那是静默的越权(见 scope.ts)。
14
13
  */
15
14
  scope: ScopeArg;
16
- params: {
17
- [field: string]: unknown;
18
- orderBy?: keyof BaseTable;
19
- orderDir?: "asc" | "desc";
20
- page?: number;
21
- pageSize?: number;
22
- };
15
+ params: ListQueryParams;
23
16
  relations?: GetListRelations;
24
17
  table: TTable;
25
18
  }): {
26
- countQuery: Omit<import("drizzle-orm/pg-core").PgSelectBase<string, {
27
- count: SQL<unknown>;
28
- }, "partial", Record<string, "not-null">, false, "where", {
29
- count: unknown;
30
- }[], {
31
- count: import("drizzle-orm").DrizzleTypeError<"You cannot reference this field without assigning it an alias first - use `.as(<alias>)`">;
32
- }>, "where">;
19
+ countQuery: any;
33
20
  query: any;
34
21
  };