@ai0x0/utils 0.3.0 → 0.4.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/es/backend/schemas/index.d.ts +21 -1
- package/es/backend/schemas/index.js +29 -15
- package/es/backend/sqlite/schemas/index.d.ts +11 -0
- package/es/backend/sqlite/schemas/index.js +29 -15
- package/lib/backend/schemas/index.d.ts +21 -1
- package/lib/backend/schemas/index.js +28 -10
- package/lib/backend/sqlite/schemas/index.d.ts +11 -0
- package/lib/backend/sqlite/schemas/index.js +29 -10
- package/package.json +1 -1
|
@@ -113,13 +113,33 @@ export declare const listBodySchema: <T extends z.ZodType<unknown, unknown, z.co
|
|
|
113
113
|
total: z.ZodNumber;
|
|
114
114
|
data: z.ZodArray<T>;
|
|
115
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;
|
|
116
122
|
/**
|
|
117
123
|
* 基于 drizzle + drizzle-zod 快速生成带基础字段(id / 创建时间等)的
|
|
118
124
|
* 表定义以及 select / insert / update / query / list zod schema。
|
|
119
125
|
*/
|
|
120
|
-
export declare const createTableSchema: <TTableName extends string, TColumnsMap extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>>, TServerColumns extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>> = {}>({ name, columns, serverColumns, extraConfig, }: {
|
|
126
|
+
export declare const createTableSchema: <TTableName extends string, TColumnsMap extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>>, TServerColumns extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>> = {}>({ name, columns, serverColumns, extraConfig, describe, }: {
|
|
121
127
|
/** 客户端能写的业务列。insert / update schema 只从这里推。 */
|
|
122
128
|
columns: TColumnsMap;
|
|
129
|
+
/**
|
|
130
|
+
* 每一列的说明,键是列名。**同时挂到 insert / update / select 三份 schema 上** —— 同一列在
|
|
131
|
+
* 请求体里和响应里是同一个东西,说明没有理由写两遍。
|
|
132
|
+
*
|
|
133
|
+
* 为什么需要这个参数:drizzle 列没有「描述」这个概念,而 `.describe()` 只能挂在 zod 上。不给
|
|
134
|
+
* 这条路,业务侧就只能在每张表后面自己把三份 schema 各 `.extend()` 一遍 —— 那是三份副本,
|
|
135
|
+
* 而副本会漂。
|
|
136
|
+
*
|
|
137
|
+
* 键有类型约束(列名的联合),所以列改名了、拼错了都是编译错误,不是静默失效。
|
|
138
|
+
*
|
|
139
|
+
* 说明会出现在 OpenAPI spec 里,再流进按 spec 生成的 client 与文档 —— 所以它是写给调用方
|
|
140
|
+
* 看的:这一列是什么、合法值从哪来、不传会怎样。
|
|
141
|
+
*/
|
|
142
|
+
describe?: Partial<Record<Extract<keyof TColumnsMap, string> | Extract<keyof TServerColumns, string>, string>> | undefined;
|
|
123
143
|
name: TTableName;
|
|
124
144
|
/**
|
|
125
145
|
* 由服务端盖、**绝不接受客户端传**的业务列:承载归属的 `ownerId`(配合
|
|
@@ -136,32 +136,42 @@ var BASIC_TIMESTAMP_NOTES = {
|
|
|
136
136
|
createdAt: "When this row was created.",
|
|
137
137
|
updatedAt: "When this row was last modified."
|
|
138
138
|
};
|
|
139
|
-
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 给 schema 上已有的字段挂说明。字段不在这个 schema 里就跳过 —— 同一张表的
|
|
142
|
+
* insert / update / select 三份含的列不一样(basicFields 只在 select 里),一份说明表要能同时
|
|
143
|
+
* 喂给三者,就不能对「字段一定存在」有要求。**不给不存在的字段凭空造一个。**
|
|
144
|
+
*/
|
|
145
|
+
export var describeFields = function describeFields(schema, notes) {
|
|
140
146
|
var overlay = {};
|
|
141
|
-
for (var _i = 0, _Object$entries = Object.entries(
|
|
147
|
+
for (var _i = 0, _Object$entries = Object.entries(notes); _i < _Object$entries.length; _i++) {
|
|
142
148
|
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
143
149
|
field = _Object$entries$_i[0],
|
|
144
150
|
note = _Object$entries$_i[1];
|
|
145
151
|
var existing = schema.shape[field];
|
|
146
|
-
// 表里没这一列就跳过 —— 不给不存在的字段凭空造一个。
|
|
147
152
|
if (existing) {
|
|
148
153
|
overlay[field] = existing.describe(note);
|
|
149
154
|
}
|
|
150
155
|
}
|
|
156
|
+
return Object.keys(overlay).length ? schema.extend(overlay) : schema;
|
|
157
|
+
};
|
|
158
|
+
var describeBasicFields = function describeBasicFields(schema) {
|
|
159
|
+
var withNotes = describeFields(schema, BASIC_FIELD_NOTES);
|
|
160
|
+
var overlay = {};
|
|
151
161
|
for (var _i2 = 0, _Object$entries2 = Object.entries(BASIC_TIMESTAMP_NOTES); _i2 < _Object$entries2.length; _i2++) {
|
|
152
162
|
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
var
|
|
156
|
-
if (
|
|
157
|
-
overlay[
|
|
158
|
-
description:
|
|
163
|
+
field = _Object$entries2$_i[0],
|
|
164
|
+
note = _Object$entries2$_i[1];
|
|
165
|
+
var existing = withNotes.shape[field];
|
|
166
|
+
if (existing) {
|
|
167
|
+
overlay[field] = existing.meta({
|
|
168
|
+
description: note,
|
|
159
169
|
format: "date-time",
|
|
160
170
|
type: "string"
|
|
161
171
|
});
|
|
162
172
|
}
|
|
163
173
|
}
|
|
164
|
-
return
|
|
174
|
+
return Object.keys(overlay).length ? withNotes.extend(overlay) : withNotes;
|
|
165
175
|
};
|
|
166
176
|
|
|
167
177
|
// =============================================================================
|
|
@@ -175,17 +185,21 @@ export var createTableSchema = function createTableSchema(_ref) {
|
|
|
175
185
|
var name = _ref.name,
|
|
176
186
|
columns = _ref.columns,
|
|
177
187
|
serverColumns = _ref.serverColumns,
|
|
178
|
-
extraConfig = _ref.extraConfig
|
|
188
|
+
extraConfig = _ref.extraConfig,
|
|
189
|
+
describe = _ref.describe;
|
|
179
190
|
var mergedColumns = _objectSpread(_objectSpread(_objectSpread({}, basicFields), serverColumns), columns);
|
|
180
191
|
var table = pgTable(name, mergedColumns, extraConfig);
|
|
181
|
-
|
|
192
|
+
|
|
193
|
+
// 同一份说明喂给三份 schema:含哪些列各不相同,describeFields 会跳过不存在的。
|
|
194
|
+
var notes = describe !== null && describe !== void 0 ? describe : {};
|
|
195
|
+
var selectSchema = describeFields(describeBasicFields(createSelectSchema(table)), notes);
|
|
182
196
|
// 只从 columns 推 —— basicFields 与 serverColumns 都由服务端写,不该出现在请求体里。
|
|
183
|
-
var insertSchema = createInsertSchema(pgTable(name, columns));
|
|
184
|
-
var updateSchema = createUpdateSchema(pgTable(name, _objectSpread({
|
|
197
|
+
var insertSchema = describeFields(createInsertSchema(pgTable(name, columns)), notes);
|
|
198
|
+
var updateSchema = describeFields(createUpdateSchema(pgTable(name, _objectSpread({
|
|
185
199
|
id: uuid("id")
|
|
186
200
|
}, columns))).extend({
|
|
187
201
|
id: z.string().describe("Id of the row to update.")
|
|
188
|
-
});
|
|
202
|
+
}), notes);
|
|
189
203
|
var querySchema = z.object({
|
|
190
204
|
id: z.string().describe("Id of the row to fetch.")
|
|
191
205
|
});
|
|
@@ -113,6 +113,12 @@ export declare const listBodySchema: <T extends z.ZodType<unknown, unknown, z.co
|
|
|
113
113
|
total: z.ZodNumber;
|
|
114
114
|
data: z.ZodArray<T>;
|
|
115
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;
|
|
116
122
|
/**
|
|
117
123
|
* 基于 drizzle + drizzle-zod 快速生成带基础字段(id / 创建时间等)的
|
|
118
124
|
* 表定义以及 select / insert / update / query / list zod schema。
|
|
@@ -121,6 +127,11 @@ export declare const createTableSchema: <TTableName extends string, TColumnsMap
|
|
|
121
127
|
name: TTableName;
|
|
122
128
|
/** 客户端能写的业务列。insert / update schema 只从这里推。 */
|
|
123
129
|
columns: TColumnsMap;
|
|
130
|
+
/**
|
|
131
|
+
* 每一列的说明,键是列名。同时挂到 insert / update / select 三份 schema 上。语义与 pg 版
|
|
132
|
+
* 一致,见那边的说明。
|
|
133
|
+
*/
|
|
134
|
+
describe?: Partial<Record<string, string>>;
|
|
124
135
|
/** 由服务端盖、绝不接受客户端传的业务列(归属、租户 id 这类)。语义与 pg 版一致,见那边的说明。 */
|
|
125
136
|
serverColumns?: Record<string, SQLiteColumnBuilderBase>;
|
|
126
137
|
extraConfig?: (_self: BuildExtraConfigColumns<TTableName, typeof basicFields & TColumnsMap, "sqlite">) => SQLiteTableExtraConfigValue[];
|
|
@@ -142,32 +142,42 @@ var BASIC_TIMESTAMP_NOTES = {
|
|
|
142
142
|
createdAt: "When this row was created.",
|
|
143
143
|
updatedAt: "When this row was last modified."
|
|
144
144
|
};
|
|
145
|
-
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 给 schema 上已有的字段挂说明。字段不在这个 schema 里就跳过 —— 同一张表的
|
|
148
|
+
* insert / update / select 三份含的列不一样(basicFields 只在 select 里),一份说明表要能同时
|
|
149
|
+
* 喂给三者,就不能对「字段一定存在」有要求。**不给不存在的字段凭空造一个。**
|
|
150
|
+
*/
|
|
151
|
+
export var describeFields = function describeFields(schema, notes) {
|
|
146
152
|
var overlay = {};
|
|
147
|
-
for (var _i = 0, _Object$entries = Object.entries(
|
|
153
|
+
for (var _i = 0, _Object$entries = Object.entries(notes); _i < _Object$entries.length; _i++) {
|
|
148
154
|
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
149
155
|
field = _Object$entries$_i[0],
|
|
150
156
|
note = _Object$entries$_i[1];
|
|
151
157
|
var existing = schema.shape[field];
|
|
152
|
-
// 表里没这一列就跳过 —— 不给不存在的字段凭空造一个。
|
|
153
158
|
if (existing) {
|
|
154
159
|
overlay[field] = existing.describe(note);
|
|
155
160
|
}
|
|
156
161
|
}
|
|
162
|
+
return Object.keys(overlay).length ? schema.extend(overlay) : schema;
|
|
163
|
+
};
|
|
164
|
+
var describeBasicFields = function describeBasicFields(schema) {
|
|
165
|
+
var withNotes = describeFields(schema, BASIC_FIELD_NOTES);
|
|
166
|
+
var overlay = {};
|
|
157
167
|
for (var _i2 = 0, _Object$entries2 = Object.entries(BASIC_TIMESTAMP_NOTES); _i2 < _Object$entries2.length; _i2++) {
|
|
158
168
|
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
var
|
|
162
|
-
if (
|
|
163
|
-
overlay[
|
|
164
|
-
description:
|
|
169
|
+
field = _Object$entries2$_i[0],
|
|
170
|
+
note = _Object$entries2$_i[1];
|
|
171
|
+
var existing = withNotes.shape[field];
|
|
172
|
+
if (existing) {
|
|
173
|
+
overlay[field] = existing.meta({
|
|
174
|
+
description: note,
|
|
165
175
|
format: "date-time",
|
|
166
176
|
type: "string"
|
|
167
177
|
});
|
|
168
178
|
}
|
|
169
179
|
}
|
|
170
|
-
return
|
|
180
|
+
return Object.keys(overlay).length ? withNotes.extend(overlay) : withNotes;
|
|
171
181
|
};
|
|
172
182
|
|
|
173
183
|
// =============================================================================
|
|
@@ -181,17 +191,21 @@ export var createTableSchema = function createTableSchema(_ref) {
|
|
|
181
191
|
var name = _ref.name,
|
|
182
192
|
columns = _ref.columns,
|
|
183
193
|
serverColumns = _ref.serverColumns,
|
|
184
|
-
extraConfig = _ref.extraConfig
|
|
194
|
+
extraConfig = _ref.extraConfig,
|
|
195
|
+
describe = _ref.describe;
|
|
185
196
|
var mergedColumns = _objectSpread(_objectSpread(_objectSpread({}, basicFields), serverColumns), columns);
|
|
186
197
|
var table = sqliteTable(name, mergedColumns, extraConfig);
|
|
187
|
-
|
|
198
|
+
|
|
199
|
+
// 同一份说明喂给三份 schema:含哪些列各不相同,describeFields 会跳过不存在的。
|
|
200
|
+
var notes = describe !== null && describe !== void 0 ? describe : {};
|
|
201
|
+
var selectSchema = describeFields(describeBasicFields(createSelectSchema(table)), notes);
|
|
188
202
|
// 只从 columns 推 —— basicFields 与 serverColumns 都由服务端写,不该出现在请求体里。
|
|
189
|
-
var insertSchema = createInsertSchema(sqliteTable(name, columns));
|
|
190
|
-
var updateSchema = createUpdateSchema(sqliteTable(name, _objectSpread({
|
|
203
|
+
var insertSchema = describeFields(createInsertSchema(sqliteTable(name, columns)), notes);
|
|
204
|
+
var updateSchema = describeFields(createUpdateSchema(sqliteTable(name, _objectSpread({
|
|
191
205
|
id: text("id")
|
|
192
206
|
}, columns))).extend({
|
|
193
207
|
id: z.string().describe("Id of the row to update.")
|
|
194
|
-
});
|
|
208
|
+
}), notes);
|
|
195
209
|
var querySchema = z.object({
|
|
196
210
|
id: z.string().describe("Id of the row to fetch.")
|
|
197
211
|
});
|
|
@@ -113,13 +113,33 @@ export declare const listBodySchema: <T extends z.ZodType<unknown, unknown, z.co
|
|
|
113
113
|
total: z.ZodNumber;
|
|
114
114
|
data: z.ZodArray<T>;
|
|
115
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;
|
|
116
122
|
/**
|
|
117
123
|
* 基于 drizzle + drizzle-zod 快速生成带基础字段(id / 创建时间等)的
|
|
118
124
|
* 表定义以及 select / insert / update / query / list zod schema。
|
|
119
125
|
*/
|
|
120
|
-
export declare const createTableSchema: <TTableName extends string, TColumnsMap extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>>, TServerColumns extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>> = {}>({ name, columns, serverColumns, extraConfig, }: {
|
|
126
|
+
export declare const createTableSchema: <TTableName extends string, TColumnsMap extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>>, TServerColumns extends Record<string, PgColumnBuilderBase<import("drizzle-orm").ColumnBuilderBaseConfig<import("drizzle-orm").ColumnDataType, string>, object>> = {}>({ name, columns, serverColumns, extraConfig, describe, }: {
|
|
121
127
|
/** 客户端能写的业务列。insert / update schema 只从这里推。 */
|
|
122
128
|
columns: TColumnsMap;
|
|
129
|
+
/**
|
|
130
|
+
* 每一列的说明,键是列名。**同时挂到 insert / update / select 三份 schema 上** —— 同一列在
|
|
131
|
+
* 请求体里和响应里是同一个东西,说明没有理由写两遍。
|
|
132
|
+
*
|
|
133
|
+
* 为什么需要这个参数:drizzle 列没有「描述」这个概念,而 `.describe()` 只能挂在 zod 上。不给
|
|
134
|
+
* 这条路,业务侧就只能在每张表后面自己把三份 schema 各 `.extend()` 一遍 —— 那是三份副本,
|
|
135
|
+
* 而副本会漂。
|
|
136
|
+
*
|
|
137
|
+
* 键有类型约束(列名的联合),所以列改名了、拼错了都是编译错误,不是静默失效。
|
|
138
|
+
*
|
|
139
|
+
* 说明会出现在 OpenAPI spec 里,再流进按 spec 生成的 client 与文档 —— 所以它是写给调用方
|
|
140
|
+
* 看的:这一列是什么、合法值从哪来、不传会怎样。
|
|
141
|
+
*/
|
|
142
|
+
describe?: Partial<Record<Extract<keyof TColumnsMap, string> | Extract<keyof TServerColumns, string>, string>> | undefined;
|
|
123
143
|
name: TTableName;
|
|
124
144
|
/**
|
|
125
145
|
* 由服务端盖、**绝不接受客户端传**的业务列:承载归属的 `ownerId`(配合
|
|
@@ -23,6 +23,7 @@ __export(schemas_exports, {
|
|
|
23
23
|
BASIC_UPDATE_OMIT: () => BASIC_UPDATE_OMIT,
|
|
24
24
|
basicFields: () => basicFields,
|
|
25
25
|
createTableSchema: () => createTableSchema,
|
|
26
|
+
describeFields: () => describeFields,
|
|
26
27
|
listBodySchema: () => listBodySchema,
|
|
27
28
|
queryListSchema: () => queryListSchema
|
|
28
29
|
});
|
|
@@ -88,16 +89,21 @@ var BASIC_TIMESTAMP_NOTES = {
|
|
|
88
89
|
createdAt: "When this row was created.",
|
|
89
90
|
updatedAt: "When this row was last modified."
|
|
90
91
|
};
|
|
91
|
-
var
|
|
92
|
+
var describeFields = (schema, notes) => {
|
|
92
93
|
const overlay = {};
|
|
93
|
-
for (const [field, note] of Object.entries(
|
|
94
|
+
for (const [field, note] of Object.entries(notes)) {
|
|
94
95
|
const existing = schema.shape[field];
|
|
95
96
|
if (existing) {
|
|
96
97
|
overlay[field] = existing.describe(note);
|
|
97
98
|
}
|
|
98
99
|
}
|
|
100
|
+
return Object.keys(overlay).length ? schema.extend(overlay) : schema;
|
|
101
|
+
};
|
|
102
|
+
var describeBasicFields = (schema) => {
|
|
103
|
+
const withNotes = describeFields(schema, BASIC_FIELD_NOTES);
|
|
104
|
+
const overlay = {};
|
|
99
105
|
for (const [field, note] of Object.entries(BASIC_TIMESTAMP_NOTES)) {
|
|
100
|
-
const existing =
|
|
106
|
+
const existing = withNotes.shape[field];
|
|
101
107
|
if (existing) {
|
|
102
108
|
overlay[field] = existing.meta({
|
|
103
109
|
description: note,
|
|
@@ -106,13 +112,14 @@ var describeBasicFields = (schema) => {
|
|
|
106
112
|
});
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
|
-
return
|
|
115
|
+
return Object.keys(overlay).length ? withNotes.extend(overlay) : withNotes;
|
|
110
116
|
};
|
|
111
117
|
var createTableSchema = ({
|
|
112
118
|
name,
|
|
113
119
|
columns,
|
|
114
120
|
serverColumns,
|
|
115
|
-
extraConfig
|
|
121
|
+
extraConfig,
|
|
122
|
+
describe
|
|
116
123
|
}) => {
|
|
117
124
|
const mergedColumns = {
|
|
118
125
|
...basicFields,
|
|
@@ -120,11 +127,21 @@ var createTableSchema = ({
|
|
|
120
127
|
...columns
|
|
121
128
|
};
|
|
122
129
|
const table = (0, import_pg_core.pgTable)(name, mergedColumns, extraConfig);
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
)
|
|
130
|
+
const notes = describe ?? {};
|
|
131
|
+
const selectSchema = describeFields(
|
|
132
|
+
describeBasicFields((0, import_drizzle_zod.createSelectSchema)(table)),
|
|
133
|
+
notes
|
|
134
|
+
);
|
|
135
|
+
const insertSchema = describeFields(
|
|
136
|
+
(0, import_drizzle_zod.createInsertSchema)((0, import_pg_core.pgTable)(name, columns)),
|
|
137
|
+
notes
|
|
138
|
+
);
|
|
139
|
+
const updateSchema = describeFields(
|
|
140
|
+
(0, import_drizzle_zod.createUpdateSchema)((0, import_pg_core.pgTable)(name, { id: (0, import_pg_core.uuid)("id"), ...columns })).extend({
|
|
141
|
+
id: import_zod.z.string().describe("Id of the row to update.")
|
|
142
|
+
}),
|
|
143
|
+
notes
|
|
144
|
+
);
|
|
128
145
|
const querySchema = import_zod.z.object({
|
|
129
146
|
id: import_zod.z.string().describe("Id of the row to fetch.")
|
|
130
147
|
});
|
|
@@ -147,6 +164,7 @@ var createTableSchema = ({
|
|
|
147
164
|
BASIC_UPDATE_OMIT,
|
|
148
165
|
basicFields,
|
|
149
166
|
createTableSchema,
|
|
167
|
+
describeFields,
|
|
150
168
|
listBodySchema,
|
|
151
169
|
queryListSchema
|
|
152
170
|
});
|
|
@@ -113,6 +113,12 @@ export declare const listBodySchema: <T extends z.ZodType<unknown, unknown, z.co
|
|
|
113
113
|
total: z.ZodNumber;
|
|
114
114
|
data: z.ZodArray<T>;
|
|
115
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;
|
|
116
122
|
/**
|
|
117
123
|
* 基于 drizzle + drizzle-zod 快速生成带基础字段(id / 创建时间等)的
|
|
118
124
|
* 表定义以及 select / insert / update / query / list zod schema。
|
|
@@ -121,6 +127,11 @@ export declare const createTableSchema: <TTableName extends string, TColumnsMap
|
|
|
121
127
|
name: TTableName;
|
|
122
128
|
/** 客户端能写的业务列。insert / update schema 只从这里推。 */
|
|
123
129
|
columns: TColumnsMap;
|
|
130
|
+
/**
|
|
131
|
+
* 每一列的说明,键是列名。同时挂到 insert / update / select 三份 schema 上。语义与 pg 版
|
|
132
|
+
* 一致,见那边的说明。
|
|
133
|
+
*/
|
|
134
|
+
describe?: Partial<Record<string, string>>;
|
|
124
135
|
/** 由服务端盖、绝不接受客户端传的业务列(归属、租户 id 这类)。语义与 pg 版一致,见那边的说明。 */
|
|
125
136
|
serverColumns?: Record<string, SQLiteColumnBuilderBase>;
|
|
126
137
|
extraConfig?: (_self: BuildExtraConfigColumns<TTableName, typeof basicFields & TColumnsMap, "sqlite">) => SQLiteTableExtraConfigValue[];
|
|
@@ -23,6 +23,7 @@ __export(schemas_exports, {
|
|
|
23
23
|
BASIC_UPDATE_OMIT: () => BASIC_UPDATE_OMIT,
|
|
24
24
|
basicFields: () => basicFields,
|
|
25
25
|
createTableSchema: () => createTableSchema,
|
|
26
|
+
describeFields: () => describeFields,
|
|
26
27
|
listBodySchema: () => listBodySchema,
|
|
27
28
|
queryListSchema: () => queryListSchema
|
|
28
29
|
});
|
|
@@ -90,16 +91,21 @@ var BASIC_TIMESTAMP_NOTES = {
|
|
|
90
91
|
createdAt: "When this row was created.",
|
|
91
92
|
updatedAt: "When this row was last modified."
|
|
92
93
|
};
|
|
93
|
-
var
|
|
94
|
+
var describeFields = (schema, notes) => {
|
|
94
95
|
const overlay = {};
|
|
95
|
-
for (const [field, note] of Object.entries(
|
|
96
|
+
for (const [field, note] of Object.entries(notes)) {
|
|
96
97
|
const existing = schema.shape[field];
|
|
97
98
|
if (existing) {
|
|
98
99
|
overlay[field] = existing.describe(note);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
102
|
+
return Object.keys(overlay).length ? schema.extend(overlay) : schema;
|
|
103
|
+
};
|
|
104
|
+
var describeBasicFields = (schema) => {
|
|
105
|
+
const withNotes = describeFields(schema, BASIC_FIELD_NOTES);
|
|
106
|
+
const overlay = {};
|
|
101
107
|
for (const [field, note] of Object.entries(BASIC_TIMESTAMP_NOTES)) {
|
|
102
|
-
const existing =
|
|
108
|
+
const existing = withNotes.shape[field];
|
|
103
109
|
if (existing) {
|
|
104
110
|
overlay[field] = existing.meta({
|
|
105
111
|
description: note,
|
|
@@ -108,9 +114,9 @@ var describeBasicFields = (schema) => {
|
|
|
108
114
|
});
|
|
109
115
|
}
|
|
110
116
|
}
|
|
111
|
-
return
|
|
117
|
+
return Object.keys(overlay).length ? withNotes.extend(overlay) : withNotes;
|
|
112
118
|
};
|
|
113
|
-
var createTableSchema = ({ name, columns, serverColumns, extraConfig }) => {
|
|
119
|
+
var createTableSchema = ({ name, columns, serverColumns, extraConfig, describe }) => {
|
|
114
120
|
const mergedColumns = {
|
|
115
121
|
...basicFields,
|
|
116
122
|
...serverColumns,
|
|
@@ -121,11 +127,23 @@ var createTableSchema = ({ name, columns, serverColumns, extraConfig }) => {
|
|
|
121
127
|
mergedColumns,
|
|
122
128
|
extraConfig
|
|
123
129
|
);
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
)
|
|
130
|
+
const notes = describe ?? {};
|
|
131
|
+
const selectSchema = describeFields(
|
|
132
|
+
describeBasicFields((0, import_drizzle_zod.createSelectSchema)(table)),
|
|
133
|
+
notes
|
|
134
|
+
);
|
|
135
|
+
const insertSchema = describeFields(
|
|
136
|
+
(0, import_drizzle_zod.createInsertSchema)((0, import_sqlite_core.sqliteTable)(name, columns)),
|
|
137
|
+
notes
|
|
138
|
+
);
|
|
139
|
+
const updateSchema = describeFields(
|
|
140
|
+
(0, import_drizzle_zod.createUpdateSchema)(
|
|
141
|
+
(0, import_sqlite_core.sqliteTable)(name, { id: (0, import_sqlite_core.text)("id"), ...columns })
|
|
142
|
+
).extend({
|
|
143
|
+
id: import_zod.z.string().describe("Id of the row to update.")
|
|
144
|
+
}),
|
|
145
|
+
notes
|
|
146
|
+
);
|
|
129
147
|
const querySchema = import_zod.z.object({
|
|
130
148
|
id: import_zod.z.string().describe("Id of the row to fetch.")
|
|
131
149
|
});
|
|
@@ -148,6 +166,7 @@ var createTableSchema = ({ name, columns, serverColumns, extraConfig }) => {
|
|
|
148
166
|
BASIC_UPDATE_OMIT,
|
|
149
167
|
basicFields,
|
|
150
168
|
createTableSchema,
|
|
169
|
+
describeFields,
|
|
151
170
|
listBodySchema,
|
|
152
171
|
queryListSchema
|
|
153
172
|
});
|