imodel 0.1.0 → 0.2.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/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.1.0
2
+ * imodel v0.2.0
3
3
  * (c) 2019-2025 undefined
4
4
  * @license undefined
5
5
  */
@@ -514,7 +514,7 @@ declare class Where {
514
514
  #private;
515
515
  }
516
516
 
517
- /** @typedef {SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now} SetValue */
517
+ /** @typedef {SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now | (string | number | bigint | boolean)[]} SetValue */
518
518
  /** @typedef {{[values.increment]: number | bigint}} SetValue.Increment */
519
519
  /** @typedef {{[values.decrement]: number | bigint}} SetValue.Decrement */
520
520
  /** @typedef {{[values.multiply]: number | bigint}} SetValue.Multiply */
@@ -540,7 +540,7 @@ declare function multiply(value: number | bigint): SetValue.Multiply;
540
540
  */
541
541
  declare function divide(value: number | bigint): SetValue.Divide;
542
542
 
543
- type SetValue = SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now;
543
+ type SetValue = SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now | (string | number | bigint | boolean)[];
544
544
  declare namespace SetValue {
545
545
  type Increment = {
546
546
  [increment$1]: number | bigint;
@@ -624,6 +624,11 @@ interface Constraint {
624
624
  }
625
625
  type MainFieldType = keyof FieldType | TableDefine;
626
626
  type ToFieldType<T> = T extends keyof FieldType ? FieldType[T] : unknown;
627
+ type FieldSpecificValue = (string | number | bigint | boolean)[] | string | number | bigint | boolean | null | typeof now;
628
+ type FieldSpecific = FieldSpecificValue | {
629
+ value: FieldSpecificValue;
630
+ computed?(): PromiseLike<FieldSpecificValue> | FieldSpecificValue;
631
+ };
627
632
  interface FieldDefineOption {
628
633
  /** 精确度 */
629
634
  precision?: number;
@@ -639,12 +644,12 @@ interface FieldDefineOption {
639
644
  unique?: boolean;
640
645
  /** 索引信息 */
641
646
  index?: string | boolean;
642
- /** 创建时,作为时间戳 */
643
- timestampCreating?: boolean;
644
- /** 更新时,作为时间戳 */
645
- timestampUpdating?: boolean;
646
- /** 伪删除时,作为时间戳 */
647
- timestampDeleting?: boolean;
647
+ /** 创建时,自定义数据 */
648
+ creating?: FieldSpecific;
649
+ /** 更新时,自定义数据 */
650
+ updating?: FieldSpecific;
651
+ /** 伪删除时,自定义数据 */
652
+ deleting?: FieldSpecific;
648
653
  /** 是否为固定值 */
649
654
  immutable?: boolean;
650
655
  /** 文本查询 */
@@ -783,7 +788,7 @@ interface PseudoDestroy {
783
788
  }
784
789
  declare const Save: unique symbol;
785
790
  interface Save {
786
- [Save](connection: Connection, run: (data: any, newData?: any) => Promise<object | null>, table: TableDefine): PromiseLike<this | null>;
791
+ [Save](connection: Connection, run: (data: any, newData?: any) => Promise<object | null>, newData: Record<string, any> | null, table: TableDefine): PromiseLike<this | null>;
787
792
  }
788
793
  declare const Create: unique symbol;
789
794
  interface Create<T = unknown> {
@@ -844,6 +849,10 @@ interface IConnection<E extends object = object> {
844
849
  dropMaterializedView(environment: Environment<E>, name: string): PromiseLike<number>;
845
850
  transaction<R>(environment: Environment<E>, fn: (t: E) => R | PromiseLike<R>): PromiseLike<R>;
846
851
  }
852
+ interface Skip {
853
+ immutable?: boolean;
854
+ specific?: boolean;
855
+ }
847
856
  interface TransactionFn {
848
857
  <T>(fn: (t: Connection) => PromiseLike<T> | T): Promise<T>;
849
858
  }
@@ -954,9 +963,10 @@ declare class Connection<E extends {} = {}> {
954
963
  * @template T
955
964
  * @param {TableDefine} model
956
965
  * @param {T} data
966
+ * @param {Record<string, any>?} [newData]
957
967
  * @returns {Promise<(T extends Save ? T : object)?>}
958
968
  */
959
- save<T>(model: TableDefine, data: T): Promise<(T extends Save ? T : object) | null>;
969
+ save<T>(model: TableDefine, data: T, newData?: Record<string, any> | null): Promise<(T extends Save ? T : object) | null>;
960
970
  /**
961
971
  *
962
972
  * @template T
@@ -970,7 +980,7 @@ declare class Connection<E extends {} = {}> {
970
980
  * @template {object} T
971
981
  * @param {TableDefine} tableDef
972
982
  * @param {T} data
973
- * @param {Record<string, SetValue>} value
983
+ * @param {Record<string, SetValue>} value
974
984
  * @returns {Promise<(T extends PseudoDestroy ? T : object)?>}
975
985
  */
976
986
  pseudoDestroy<T extends unknown>(tableDef: TableDefine, data: T, value: Record<string, SetValue>): Promise<(T extends PseudoDestroy ? T : object) | null>;
@@ -1018,29 +1028,29 @@ declare class Connection<E extends {} = {}> {
1018
1028
  * @param {TableDefine} tableDefine
1019
1029
  * @param {Record<string, any>} update
1020
1030
  * @param {WhereValue[]?} [where]
1021
- * @param {boolean} [skip]
1031
+ * @param {boolean | Skip} [skip]
1022
1032
  * @returns {Promise<number>}
1023
1033
  */
1024
- update({ table, fields }: TableDefine, update: Record<string, any>, where?: WhereValue[] | null, skip?: boolean): Promise<number>;
1034
+ update({ table, fields }: TableDefine, update: Record<string, any>, where?: WhereValue[] | null, skip?: boolean | Skip): Promise<number>;
1025
1035
  /**
1026
1036
  * @template {Fields<MainFieldType>} T
1027
1037
  * @param {TableDefine<T>} tableDefine
1028
1038
  * @param {Record<string, any>} update
1029
1039
  * @param {string[]?} [returning]
1030
1040
  * @param {WhereValue[]?} [where]
1031
- * @param {boolean} [skip]
1041
+ * @param {boolean | Skip} [skip]
1032
1042
  * @returns {Promise<any[]>}
1033
1043
  */
1034
- updateReturn<T extends Fields<MainFieldType>>({ table, fields }: TableDefine<T>, update: Record<string, any>, returning?: string[] | null, where?: WhereValue[] | null, skip?: boolean): Promise<any[]>;
1044
+ updateReturn<T extends Fields<MainFieldType>>({ table, fields }: TableDefine<T>, update: Record<string, any>, returning?: string[] | null, where?: WhereValue[] | null, skip?: boolean | Skip): Promise<any[]>;
1035
1045
  /**
1036
1046
  * @param {TableDefine} tableDefine
1037
1047
  * @param {string[]} pKeys
1038
1048
  * @param {string[]} setKeys
1039
1049
  * @param {Record<string, any>[]} list
1040
- * @param {boolean} [skip]
1050
+ * @param {boolean | Skip} [skip]
1041
1051
  * @returns {Promise<number>}
1042
1052
  */
1043
- updateMany({ table, fields }: TableDefine, pKeys: string[], setKeys: string[], list: Record<string, any>[], skip?: boolean): Promise<number>;
1053
+ updateMany({ table, fields }: TableDefine, pKeys: string[], setKeys: string[], list: Record<string, any>[], skip?: boolean | Skip): Promise<number>;
1044
1054
  /**
1045
1055
  * @template {Fields<MainFieldType>} T
1046
1056
  * @param {TableDefine<T>} tableDefine
@@ -1048,10 +1058,10 @@ declare class Connection<E extends {} = {}> {
1048
1058
  * @param {string[]} setKeys
1049
1059
  * @param {Record<string, any>[]} list
1050
1060
  * @param {string[]?} [returning]
1051
- * @param {boolean} [skip]
1061
+ * @param {boolean | Skip} [skip]
1052
1062
  * @returns {Promise<any[]>}
1053
1063
  */
1054
- updateManyReturn<T extends Fields<MainFieldType>>({ table, fields }: TableDefine<T>, pKeys: string[], setKeys: string[], list: Record<string, any>[], returning?: string[] | null, skip?: boolean): Promise<any[]>;
1064
+ updateManyReturn<T extends Fields<MainFieldType>>({ table, fields }: TableDefine<T>, pKeys: string[], setKeys: string[], list: Record<string, any>[], returning?: string[] | null, skip?: boolean | Skip): Promise<any[]>;
1055
1065
  /**
1056
1066
  * @param {TableDefine} tableDefine
1057
1067
  * @param {WhereValue[]} [where]
@@ -1971,9 +1981,10 @@ declare class Model implements Save, Destroy, PseudoDestroy {
1971
1981
  /**
1972
1982
  * @param {Connection} t
1973
1983
  * @param {(data: any, newData?: any) => Promise<object?>} run
1984
+ * @param {Record<string, any>?} newData
1974
1985
  * @returns {Promise<this?>}
1975
1986
  */
1976
- [Save](t: Connection, run: (data: any, newData?: any) => Promise<object | null>): Promise<this | null>;
1987
+ [Save](t: Connection, run: (data: any, newData?: any) => Promise<object | null>, newData: Record<string, any> | null): Promise<this | null>;
1977
1988
  /**
1978
1989
  * @param {Connection} t
1979
1990
  * @param {(data: any) => Promise<object?>} run
@@ -2176,4 +2187,4 @@ declare function field<T extends MainFieldType>(type: T, options: {
2176
2187
  declare function setDevelopment(d?: boolean): void;
2177
2188
  declare let isDevelopment: boolean;
2178
2189
 
2179
- export { Build, type BuildValue, type ClassDecorator, type Column, type ColumnOptions, Connection, type Constraint, type CountArg, Create, Destroy, type Environment, type FieldDecorator, type FieldDefine, type FieldDefineOption, type FieldDefineType, type FieldType, type FieldTypeDefine, type FieldValue, type Fields, type FindRange, type GetName, type IConnection, type Index, type IndexInfo, type IndexOptions, type Join, type JoinType, type MainFieldType, type MatchArg, type MaybePromise, Model, type Options, PseudoDestroy, type Querier, Query, type QueryOptions, type Queryable, Save, Select, type SelectArg, SetValue, Submodel, type Support, type TableDefine, type TableType, type ToFieldType, type ToType, type TransactionFn, Where, type WhereItem, type WhereLike, type WhereOr, type WhereRaw, type WhereValue, type Wheres, creating, decrement, field as define, deleted, deleting, divide, field$1 as field, getPrimaryKeys, id, immutable, increment, index, isDevelopment, isPseudo, submodel as model, multiply, now, primary, prop, pseudo, setDevelopment, sort, submodel, toNot, undeleted, updating, values, withDeleted };
2190
+ export { Build, type BuildValue, type ClassDecorator, type Column, type ColumnOptions, Connection, type Constraint, type CountArg, Create, Destroy, type Environment, type FieldDecorator, type FieldDefine, type FieldDefineOption, type FieldDefineType, type FieldSpecific, type FieldSpecificValue, type FieldType, type FieldTypeDefine, type FieldValue, type Fields, type FindRange, type GetName, type IConnection, type Index, type IndexInfo, type IndexOptions, type Join, type JoinType, type MainFieldType, type MatchArg, type MaybePromise, Model, type Options, PseudoDestroy, type Querier, Query, type QueryOptions, type Queryable, Save, Select, type SelectArg, SetValue, type Skip, Submodel, type Support, type TableDefine, type TableType, type ToFieldType, type ToType, type TransactionFn, Where, type WhereItem, type WhereLike, type WhereOr, type WhereRaw, type WhereValue, type Wheres, creating, decrement, field as define, deleted, deleting, divide, field$1 as field, getPrimaryKeys, id, immutable, increment, index, isDevelopment, isPseudo, submodel as model, multiply, now, primary, prop, pseudo, setDevelopment, sort, submodel, toNot, undeleted, updating, values, withDeleted };
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.1.0
2
+ * imodel v0.2.0
3
3
  * (c) 2019-2025 undefined
4
4
  * @license undefined
5
5
  */
@@ -127,63 +127,63 @@ function getOptions(model) {
127
127
  return options;
128
128
  }
129
129
 
130
- /** @typedef {SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now} SetValue */
131
- /** @typedef {{[values.increment]: number | bigint}} SetValue.Increment */
132
- /** @typedef {{[values.decrement]: number | bigint}} SetValue.Decrement */
133
- /** @typedef {{[values.multiply]: number | bigint}} SetValue.Multiply */
134
- /** @typedef {{[values.divide]: number | bigint}} SetValue.Divide */
135
- /**
136
- * @param {number | bigint} value
137
- * @returns {SetValue.Increment}
138
- */
139
- function increment(value) {
140
- return {
141
- [increment$1]: value
142
- };
143
- }
130
+ /** @import { FieldSpecific } from '../../types' */
144
131
  /**
145
- * @param {number | bigint} value
146
- * @returns {SetValue.Decrement}
147
- */
148
- function decrement(value) {
149
- return {
150
- [decrement$1]: value
151
- };
152
- }
153
- /**
154
- * @param {number | bigint} value
155
- * @returns {SetValue.Multiply}
156
- */
157
- function multiply(value) {
158
- return {
159
- [multiply$1]: value
160
- };
161
- }
162
- /**
163
- * @param {number | bigint} value
164
- * @returns {SetValue.Divide}
132
+ *
133
+ * @param {FieldSpecific} [val]
134
+ * @returns
165
135
  */
166
- function divide(value) {
167
- return {
168
- [divide$1]: value
169
- };
136
+ async function getSpecificValue(val) {
137
+ if (val === void 0) {
138
+ return;
139
+ }
140
+ if (!val) {
141
+ return val;
142
+ }
143
+ if (Array.isArray(val)) {
144
+ return val;
145
+ }
146
+ if (typeof val !== 'function' && typeof val !== 'object') {
147
+ return val;
148
+ }
149
+ const {
150
+ computed,
151
+ value
152
+ } = val;
153
+ if (value === void 0) {
154
+ return;
155
+ }
156
+ if (typeof computed === 'function') {
157
+ const value = await computed();
158
+ if (value !== void 0) {
159
+ return;
160
+ }
161
+ }
162
+ return value;
170
163
  }
171
164
 
172
165
  /** @import { SetValue } from '../../set.mjs' */
173
- /** @import { Fields } from '../../types' */
166
+ /** @import { Fields, Skip } from '../../types' */
174
167
  /**
175
168
  *
176
169
  * @param {Fields} fields
177
170
  * @param {Record<string, SetValue> | null | undefined} [update]
178
- * @returns {Record<string, SetValue>}
171
+ * @param {boolean | Skip} [skip]
172
+ * @returns {Promise<Record<string, SetValue>>}
179
173
  */
180
- function getSetNewValue(fields, update) {
174
+ async function getSetNewValue(fields, update, skip) {
181
175
  const data = {
182
176
  ...update
183
177
  };
184
- for (const [name, field] of Object.entries(fields)) {
185
- if (!field.primary && field.timestampUpdating) {
186
- data[name] = now;
178
+ if (!(skip === true || skip && skip.specific)) {
179
+ for (const [name, field] of Object.entries(fields)) {
180
+ if (field.primary) {
181
+ continue;
182
+ }
183
+ const updating = await getSpecificValue(field.updating);
184
+ if (updating !== void 0) {
185
+ data[name] = updating;
186
+ }
187
187
  }
188
188
  }
189
189
  return Object.fromEntries(Object.entries(data).filter(([k, v]) => {
@@ -191,7 +191,15 @@ function getSetNewValue(fields, update) {
191
191
  if (!field) {
192
192
  return;
193
193
  }
194
- if (field.immutable || field.serial && field.type === 'id') {
194
+ if (field.immutable) {
195
+ if (!skip) {
196
+ return;
197
+ }
198
+ if (skip !== true && !skip.immutable) {
199
+ return;
200
+ }
201
+ }
202
+ if (field.serial && field.type === 'id') {
195
203
  return;
196
204
  }
197
205
  return true;
@@ -203,13 +211,19 @@ function getSetNewValue(fields, update) {
203
211
  *
204
212
  * @param {Record<string, any>} data
205
213
  * @param {Fields} fields
206
- * @returns {Record<string, any>}
214
+ * @returns {Promise<Record<string, any>>}
207
215
  */
208
- function getInsertValue(data, fields) {
216
+ async function getInsertValue(data, fields) {
209
217
  const insertValue = {};
210
218
  for (const [k, field] of Object.entries(fields)) {
211
- if (field.timestampCreating) {
212
- insertValue[k] = now;
219
+ const creating = await getSpecificValue(field.creating);
220
+ if (creating !== void 0) {
221
+ insertValue[k] = creating;
222
+ continue;
223
+ }
224
+ const updating = await getSpecificValue(field.updating);
225
+ if (updating !== void 0) {
226
+ insertValue[k] = updating;
213
227
  continue;
214
228
  }
215
229
  const val = data[k];
@@ -230,21 +244,51 @@ function getInsertValue(data, fields) {
230
244
  return insertValue;
231
245
  }
232
246
 
233
- /** @import { ColumnOptions } from '../../types' */
247
+ /** @import { ColumnOptions, FieldSpecific } from '../../types' */
248
+ /**
249
+ *
250
+ * @param {FieldSpecific} [val]
251
+ * @returns
252
+ */
253
+ function getSpecificDefaultValue(val) {
254
+ if (val === void 0) {
255
+ return;
256
+ }
257
+ if (!val) {
258
+ return val;
259
+ }
260
+ if (Array.isArray(val)) {
261
+ return val;
262
+ }
263
+ if (typeof val !== 'function' && typeof val !== 'object') {
264
+ return val;
265
+ }
266
+ return val.value;
267
+ }
234
268
  /**
235
269
  * @template {ColumnOptions} T
236
270
  * @param {T} v
237
271
  * @returns {T}
238
272
  */
239
- function timestampDef(v) {
240
- const isTime = v.timestampCreating || v.timestampUpdating;
241
- if (!isTime) {
273
+ function setDefaultOptions(v) {
274
+ if (v.default !== void 0) {
242
275
  return v;
243
276
  }
244
- return {
245
- ...v,
246
- default: now
247
- };
277
+ const creating = getSpecificDefaultValue(v.creating);
278
+ if (creating !== void 0) {
279
+ return {
280
+ ...v,
281
+ default: creating
282
+ };
283
+ }
284
+ const updating = getSpecificDefaultValue(v.updating);
285
+ if (updating !== void 0) {
286
+ return {
287
+ ...v,
288
+ default: updating
289
+ };
290
+ }
291
+ return v;
248
292
  }
249
293
 
250
294
  /** @import { FieldDefine, Fields, FieldType, TableDefine } from '../../types' */
@@ -409,7 +453,7 @@ async function createSub(conn, getName, env, fields, newList, list) {
409
453
  }
410
454
  const [baseFields, tableFields] = separateFields(fields);
411
455
  const insertKeys = Object.entries(baseFields).filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0]);
412
- const insertValues = fieldValues.map(d => getInsertValue(d, fields));
456
+ const insertValues = await Promise.all(fieldValues.map(d => getInsertValue(d, fields)));
413
457
  const {
414
458
  table
415
459
  } = type;
@@ -460,7 +504,7 @@ async function create(conn, getName, env, model, p, mapDo = defaultMap) {
460
504
  records.push(data);
461
505
  }
462
506
  const [baseFields, tableFields] = separateFields(fields);
463
- const insertValues = records.map(d => getInsertValue(d, baseFields));
507
+ const insertValues = await Promise.all(records.map(d => getInsertValue(d, baseFields)));
464
508
  let insertKeys = [];
465
509
  if (!insertKeys.length && !isArray) {
466
510
  insertKeys = Object.entries(insertValues[0]).filter(([k, v]) => v !== undefined && k in baseFields).map(([k]) => k);
@@ -882,7 +926,7 @@ async function updateItem(conn, getName, env, updatedOldNewList, key, type, arra
882
926
  // 批量修改
883
927
  if (needUpdate.length) {
884
928
  const keys = new Set(needUpdate.map(v => Object.keys(v[0])).flat());
885
- const update = getSetNewValue(baseFields);
929
+ const update = await getSetNewValue(baseFields);
886
930
  for (const k of Object.keys(update)) {
887
931
  keys.delete(k);
888
932
  }
@@ -908,7 +952,7 @@ async function updateItem(conn, getName, env, updatedOldNewList, key, type, arra
908
952
  // 批量新建
909
953
  if (needCreate.length) {
910
954
  const key = Object.entries(baseFields);
911
- const list = typeof table === 'string' ? conn.insert(env, table, baseFields, needCreate.map(d => getInsertValue(d, baseFields)), key.filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0])) : table.insert(env, conn, '', baseFields, needCreate.map(d => getInsertValue(d, baseFields)), key.filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0]));
955
+ const list = typeof table === 'string' ? conn.insert(env, table, baseFields, await Promise.all(needCreate.map(d => getInsertValue(d, baseFields))), key.filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0])) : table.insert(env, conn, '', baseFields, await Promise.all(needCreate.map(d => getInsertValue(d, baseFields))), key.filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0]));
912
956
  listPromises.push(list);
913
957
  promises.push(list.then(list => createSub(conn, getName, env, tableFields, needCreate, list)));
914
958
  }
@@ -999,13 +1043,13 @@ async function updateData (conn, getName, model, data, newData, env) {
999
1043
  table: '',
1000
1044
  fields: baseFields,
1001
1045
  where
1002
- }, getSetNewValue(fields, newData), Object.keys(baseFields));
1046
+ }, await getSetNewValue(fields, newData), Object.keys(baseFields));
1003
1047
  } else {
1004
1048
  list = await conn.updateReturn(env, {
1005
1049
  table: getName(table),
1006
1050
  fields: baseFields,
1007
1051
  where
1008
- }, getSetNewValue(fields, newData), Object.keys(baseFields));
1052
+ }, await getSetNewValue(fields, newData), Object.keys(baseFields));
1009
1053
  }
1010
1054
  const oldList = [data];
1011
1055
  const newList = [newData];
@@ -1023,10 +1067,14 @@ async function updateData (conn, getName, model, data, newData, env) {
1023
1067
  * @param {Record<string, SetValue>} update
1024
1068
  * @returns
1025
1069
  */
1026
- function setDeleteTimestamp(fields, update) {
1070
+ async function setDeleteTimestamp(fields, update) {
1027
1071
  for (const [name, field] of Object.entries(fields)) {
1028
- if (!field.primary && field.timestampDeleting) {
1029
- update[name] = now;
1072
+ if (field.primary) {
1073
+ continue;
1074
+ }
1075
+ const deleting = await getSpecificValue(field.deleting);
1076
+ if (deleting !== void 0) {
1077
+ update[name] = deleting;
1030
1078
  }
1031
1079
  }
1032
1080
  return update;
@@ -1068,7 +1116,7 @@ async function pseudoDestroy (conn, getName, tableDef, data, update, env) {
1068
1116
  };
1069
1117
  const pseudoValue = Number(new Date());
1070
1118
  value[pseudo] = pseudoValue;
1071
- setDeleteTimestamp(fields, value);
1119
+ await setDeleteTimestamp(fields, value);
1072
1120
  const [dataUpdated] = table && typeof table === 'object' ? await table.updateReturn(env, conn, {
1073
1121
  table: '',
1074
1122
  fields: baseFields,
@@ -1346,7 +1394,7 @@ async function pseudoDeleteMany(conn, getName, queryable, update, env) {
1346
1394
  const pseudoValue = Number(new Date());
1347
1395
  const pseudo = queryable.pseudo || '';
1348
1396
  value[pseudo] = pseudoValue;
1349
- setDeleteTimestamp(fields, value);
1397
+ await setDeleteTimestamp(fields, value);
1350
1398
  const baseFields = toBaseFields(fields);
1351
1399
  const list = table && typeof table === 'object' ? await table.updateReturn(env, conn, {
1352
1400
  table: '',
@@ -1368,35 +1416,7 @@ async function pseudoDeleteMany(conn, getName, queryable, update, env) {
1368
1416
  /** @import { Fields, FieldType, FieldValue, IndexOptions, MainFieldType, TableDefine } from '../types/table' */
1369
1417
  /** @import { Queryable } from '../types/options' */
1370
1418
  /** @import { Column, ColumnOptions } from '../types/column' */
1371
- /** @import { GetName, TableType } from '../types/connection' */
1372
- /**
1373
- *
1374
- * @param {Record<string, any> | null | undefined} update
1375
- * @param {Fields} fields
1376
- * @param {boolean} [skip]
1377
- * @returns {Record<string, SetValue>}
1378
- */
1379
- function getSetValue$1(update, fields, skip) {
1380
- /** @type {Record<string, SetValue>} */
1381
- const data = {
1382
- ...update
1383
- };
1384
- for (const [name, field] of Object.entries(fields)) {
1385
- if (!field.primary && field.timestampUpdating) {
1386
- data[name] = now;
1387
- }
1388
- }
1389
- return Object.fromEntries(Object.entries(data).filter(([k, v]) => {
1390
- const field = k in fields && fields[k];
1391
- if (!field) {
1392
- return;
1393
- }
1394
- if (!skip && field.immutable || field.serial && field.type === 'id') {
1395
- return;
1396
- }
1397
- return true;
1398
- }));
1399
- }
1419
+ /** @import { GetName, Skip, TableType } from '../types/connection' */
1400
1420
  /**
1401
1421
  *
1402
1422
  * @param {Fields<keyof FieldType>} fields
@@ -1628,11 +1648,17 @@ class Connection {
1628
1648
  * @template T
1629
1649
  * @param {TableDefine} model
1630
1650
  * @param {T} data
1651
+ * @param {Record<string, any>?} [newData]
1631
1652
  * @returns {Promise<(T extends Save ? T : object)?>}
1632
1653
  */
1633
- async save(model, data) {
1654
+ async save(model, data, newData) {
1634
1655
  if (typeof data[Save] !== 'function') {
1635
1656
  const conn = await this.#getConnection();
1657
+ if (newData) {
1658
+ /** @type {any} */
1659
+ const doc = data;
1660
+ return updateData(conn, this.#getName, model, doc, newData, this.#env);
1661
+ }
1636
1662
  return create(conn, this.#getName, this.#env, model, data);
1637
1663
  }
1638
1664
  const r = /** @type {Save}*/data;
@@ -1643,7 +1669,7 @@ class Connection {
1643
1669
  return updateData(conn, this.#getName, model, doc, newData, this.#env);
1644
1670
  }
1645
1671
  return create(conn, this.#getName, this.#env, model, doc);
1646
- }, model);
1672
+ }, newData || null, model);
1647
1673
  }
1648
1674
  /**
1649
1675
  *
@@ -1669,7 +1695,7 @@ class Connection {
1669
1695
  * @template {object} T
1670
1696
  * @param {TableDefine} tableDef
1671
1697
  * @param {T} data
1672
- * @param {Record<string, SetValue>} value
1698
+ * @param {Record<string, SetValue>} value
1673
1699
  * @returns {Promise<(T extends PseudoDestroy ? T : object)?>}
1674
1700
  */
1675
1701
  async pseudoDestroy(tableDef, data, value) {
@@ -1772,7 +1798,7 @@ class Connection {
1772
1798
  * @param {TableDefine} tableDefine
1773
1799
  * @param {Record<string, any>} update
1774
1800
  * @param {WhereValue[]?} [where]
1775
- * @param {boolean} [skip]
1801
+ * @param {boolean | Skip} [skip]
1776
1802
  * @returns {Promise<number>}
1777
1803
  */
1778
1804
  async update({
@@ -1784,11 +1810,11 @@ class Connection {
1784
1810
  table: '',
1785
1811
  fields: toBaseFields(fields),
1786
1812
  where: where || undefined
1787
- }, getSetValue$1(update, fields, skip)) : conn.update(this.#env, {
1813
+ }, await getSetNewValue(fields, update, skip)) : conn.update(this.#env, {
1788
1814
  table: this.#getName(table),
1789
1815
  fields: toBaseFields(fields),
1790
1816
  where: where || undefined
1791
- }, getSetValue$1(update, fields, skip));
1817
+ }, await getSetNewValue(fields, update, skip));
1792
1818
  }
1793
1819
  /**
1794
1820
  * @template {Fields<MainFieldType>} T
@@ -1796,7 +1822,7 @@ class Connection {
1796
1822
  * @param {Record<string, any>} update
1797
1823
  * @param {string[]?} [returning]
1798
1824
  * @param {WhereValue[]?} [where]
1799
- * @param {boolean} [skip]
1825
+ * @param {boolean | Skip} [skip]
1800
1826
  * @returns {Promise<any[]>}
1801
1827
  */
1802
1828
  async updateReturn({
@@ -1809,18 +1835,18 @@ class Connection {
1809
1835
  table: '',
1810
1836
  fields: baseFields,
1811
1837
  where: where || undefined
1812
- }, getSetValue$1(update, fields, skip), returning?.length ? returning : Object.keys(baseFields)) : conn.updateReturn(this.#env, {
1838
+ }, await getSetNewValue(fields, update, skip), returning?.length ? returning : Object.keys(baseFields)) : conn.updateReturn(this.#env, {
1813
1839
  table: this.#getName(table),
1814
1840
  fields: baseFields,
1815
1841
  where: where || undefined
1816
- }, getSetValue$1(update, fields, skip), returning?.length ? returning : Object.keys(baseFields));
1842
+ }, await getSetNewValue(fields, update, skip), returning?.length ? returning : Object.keys(baseFields));
1817
1843
  }
1818
1844
  /**
1819
1845
  * @param {TableDefine} tableDefine
1820
1846
  * @param {string[]} pKeys
1821
1847
  * @param {string[]} setKeys
1822
1848
  * @param {Record<string, any>[]} list
1823
- * @param {boolean} [skip]
1849
+ * @param {boolean | Skip} [skip]
1824
1850
  * @returns {Promise<number>}
1825
1851
  */
1826
1852
  async updateMany({
@@ -1828,7 +1854,7 @@ class Connection {
1828
1854
  fields
1829
1855
  }, pKeys, setKeys, list, skip) {
1830
1856
  const baseFields = toBaseFields(fields);
1831
- const update = skip ? {} : getSetNewValue(fields);
1857
+ const update = await getSetNewValue(fields, null, skip);
1832
1858
  const [whereFields, setFields] = getKeys(baseFields, update, pKeys, setKeys);
1833
1859
  const conn = await this.#getConnection();
1834
1860
  return table && typeof table === 'object' ? table.updateMany(this.#env, conn, '', baseFields, update, whereFields, setFields, list, []) : conn.updateMany(this.#env, this.#getName(table), baseFields, update, whereFields, setFields, list, []);
@@ -1840,7 +1866,7 @@ class Connection {
1840
1866
  * @param {string[]} setKeys
1841
1867
  * @param {Record<string, any>[]} list
1842
1868
  * @param {string[]?} [returning]
1843
- * @param {boolean} [skip]
1869
+ * @param {boolean | Skip} [skip]
1844
1870
  * @returns {Promise<any[]>}
1845
1871
  */
1846
1872
  async updateManyReturn({
@@ -1848,7 +1874,7 @@ class Connection {
1848
1874
  fields
1849
1875
  }, pKeys, setKeys, list, returning, skip) {
1850
1876
  const baseFields = toBaseFields(fields);
1851
- const update = skip ? {} : getSetNewValue(fields);
1877
+ const update = getSetNewValue(fields, null, skip);
1852
1878
  const [whereFields, setFields] = getKeys(baseFields, update, pKeys, setKeys);
1853
1879
  const conn = await this.#getConnection();
1854
1880
  return table && typeof table === 'object' ? table.updateManyReturn(this.#env, conn, '', baseFields, update, whereFields, setFields, list, [], returning?.length ? returning : Object.keys(baseFields)) : conn.updateManyReturn(this.#env, this.#getName(table), baseFields, update, whereFields, setFields, list, [], returning?.length ? returning : Object.keys(baseFields));
@@ -1956,7 +1982,7 @@ class Connection {
1956
1982
  */
1957
1983
  async addColumn(table, column, type, options) {
1958
1984
  const conn = await this.#getConnection();
1959
- return conn.addColumn(this.#env, this.#getName(table), column, type, timestampDef(options));
1985
+ return conn.addColumn(this.#env, this.#getName(table), column, type, setDefaultOptions(options));
1960
1986
  }
1961
1987
  /**
1962
1988
  * @param {string} table
@@ -1967,7 +1993,7 @@ class Connection {
1967
1993
  */
1968
1994
  async changeColumn(table, column, type, options) {
1969
1995
  const conn = await this.#getConnection();
1970
- return conn.changeColumn(this.#env, this.#getName(table), column, type, timestampDef(options));
1996
+ return conn.changeColumn(this.#env, this.#getName(table), column, type, setDefaultOptions(options));
1971
1997
  }
1972
1998
  /**
1973
1999
  * @param {string} table
@@ -2025,7 +2051,7 @@ class Connection {
2025
2051
  */
2026
2052
  async createTable(table, fields) {
2027
2053
  const conn = await this.#getConnection();
2028
- return conn.createTable(this.#env, this.#getName(table), fields.map(timestampDef));
2054
+ return conn.createTable(this.#env, this.#getName(table), fields.map(setDefaultOptions));
2029
2055
  }
2030
2056
  /**
2031
2057
  * @param {string} table
@@ -3594,6 +3620,48 @@ class Where {
3594
3620
  }
3595
3621
  }
3596
3622
 
3623
+ /** @typedef {SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now | (string | number | bigint | boolean)[]} SetValue */
3624
+ /** @typedef {{[values.increment]: number | bigint}} SetValue.Increment */
3625
+ /** @typedef {{[values.decrement]: number | bigint}} SetValue.Decrement */
3626
+ /** @typedef {{[values.multiply]: number | bigint}} SetValue.Multiply */
3627
+ /** @typedef {{[values.divide]: number | bigint}} SetValue.Divide */
3628
+ /**
3629
+ * @param {number | bigint} value
3630
+ * @returns {SetValue.Increment}
3631
+ */
3632
+ function increment(value) {
3633
+ return {
3634
+ [increment$1]: value
3635
+ };
3636
+ }
3637
+ /**
3638
+ * @param {number | bigint} value
3639
+ * @returns {SetValue.Decrement}
3640
+ */
3641
+ function decrement(value) {
3642
+ return {
3643
+ [decrement$1]: value
3644
+ };
3645
+ }
3646
+ /**
3647
+ * @param {number | bigint} value
3648
+ * @returns {SetValue.Multiply}
3649
+ */
3650
+ function multiply(value) {
3651
+ return {
3652
+ [multiply$1]: value
3653
+ };
3654
+ }
3655
+ /**
3656
+ * @param {number | bigint} value
3657
+ * @returns {SetValue.Divide}
3658
+ */
3659
+ function divide(value) {
3660
+ return {
3661
+ [divide$1]: value
3662
+ };
3663
+ }
3664
+
3597
3665
  /** @import { Fields, Options, Queryable, Select } from './types' */
3598
3666
  /** @import { WhereValue, Wheres } from './Where.mjs' */
3599
3667
  /**
@@ -4829,13 +4897,18 @@ class Model {
4829
4897
  /**
4830
4898
  * @param {Connection} t
4831
4899
  * @param {(data: any, newData?: any) => Promise<object?>} run
4900
+ * @param {Record<string, any>?} newData
4832
4901
  * @returns {Promise<this?>}
4833
4902
  */
4834
- async [Save](t, run) {
4903
+ async [Save](t, run, newData) {
4835
4904
  const update = this.#saved;
4836
- return this.#do(() => this.$_onBeforeSave(t, update), () => update ? run(this.#data, this.#newData) : run({
4905
+ return this.#do(() => this.$_onBeforeSave(t, update), () => update ? run(this.#data, {
4906
+ ...this.#newData,
4907
+ ...newData
4908
+ }) : run({
4837
4909
  ...this.#data,
4838
- ...this.#newData
4910
+ ...this.#newData,
4911
+ ...newData
4839
4912
  }), () => this.$_onAfterSave(t, update));
4840
4913
  }
4841
4914
  /**
package/migrate.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * imodel v0.1.0
2
+ * imodel v0.2.0
3
3
  * (c) 2019-2025 undefined
4
4
  * @license undefined
5
5
  */
6
6
 
7
- import { TransactionFn, Connection, IndexOptions, ColumnOptions, Column, Index, TableDefine } from 'imodel';
7
+ import { TransactionFn, Connection, IndexOptions, FieldType, ColumnOptions, Column, Index, TableDefine } from 'imodel';
8
8
 
9
9
  /**
10
10
  *
@@ -185,7 +185,7 @@ declare class MigrationType implements Migrator$4 {
185
185
  }
186
186
  type Migrator$4 = Migrator;
187
187
 
188
- /** @import { IndexOptions, ColumnOptions } from 'imodel' */
188
+ /** @import { IndexOptions, ColumnOptions, FieldType } from 'imodel' */
189
189
  /**
190
190
  * @abstract
191
191
  */
@@ -200,11 +200,11 @@ declare class TableAdder {
200
200
  /**
201
201
  * @abstract
202
202
  * @param {string} name
203
- * @param {string} type
203
+ * @param {keyof FieldType} type
204
204
  * @param {ColumnOptions<any>} [options]
205
205
  * @returns {this}
206
206
  */
207
- field(name: string, type: string, options?: ColumnOptions<any>): this;
207
+ field(name: string, type: keyof FieldType, options?: ColumnOptions<any>): this;
208
208
  /**
209
209
  * @param {string} name
210
210
  * @param {ColumnOptions<string>} [options]
@@ -241,12 +241,6 @@ declare class TableAdder {
241
241
  * @returns {this}
242
242
  */
243
243
  i32(name: string, options?: ColumnOptions<number | bigint>): this;
244
- /**
245
- * @param {string} name
246
- * @param {ColumnOptions<number | bigint>} [options]
247
- * @returns {this}
248
- */
249
- i52(name: string, options?: ColumnOptions<number | bigint>): this;
250
244
  /**
251
245
  * @param {string} name
252
246
  * @param {ColumnOptions<number | bigint>} [options]
@@ -265,12 +259,6 @@ declare class TableAdder {
265
259
  * @returns {this}
266
260
  */
267
261
  u32(name: string, options?: ColumnOptions<number | bigint>): this;
268
- /**
269
- * @param {string} name
270
- * @param {ColumnOptions<number | bigint>} [options]
271
- * @returns {this}
272
- */
273
- u52(name: string, options?: ColumnOptions<number | bigint>): this;
274
262
  /**
275
263
  * @param {string} name
276
264
  * @param {ColumnOptions<number | bigint>} [options]
@@ -385,6 +373,12 @@ declare class TableAdder {
385
373
  * @returns {this}
386
374
  */
387
375
  object(name: string, options?: ColumnOptions<object>): this;
376
+ /**
377
+ * @param {string} name
378
+ * @param {ColumnOptions<object>} [options]
379
+ * @returns {this}
380
+ */
381
+ json(name: string, options?: ColumnOptions<object>): this;
388
382
  /**
389
383
  * @returns {this}
390
384
  */
package/migrate.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * imodel v0.1.0
2
+ * imodel v0.2.0
3
3
  * (c) 2019-2025 undefined
4
4
  * @license undefined
5
5
  */
6
6
 
7
- import { Query, define } from 'imodel';
7
+ import { now, Query, define } from 'imodel';
8
8
 
9
9
  /** @import { Connection } from 'imodel' */
10
10
  /** @typedef {import('./index.mjs').Migrator} Migrator */
@@ -55,7 +55,7 @@ class Reverter {
55
55
  }
56
56
  }
57
57
 
58
- /** @import { IndexOptions, ColumnOptions } from 'imodel' */
58
+ /** @import { IndexOptions, ColumnOptions, FieldType } from 'imodel' */
59
59
  /**
60
60
  * @abstract
61
61
  */
@@ -72,7 +72,7 @@ class TableAdder {
72
72
  /**
73
73
  * @abstract
74
74
  * @param {string} name
75
- * @param {string} type
75
+ * @param {keyof FieldType} type
76
76
  * @param {ColumnOptions<any>} [options]
77
77
  * @returns {this}
78
78
  */
@@ -127,14 +127,6 @@ class TableAdder {
127
127
  i32(name, options) {
128
128
  return this.field(name, 'i32', options);
129
129
  }
130
- /**
131
- * @param {string} name
132
- * @param {ColumnOptions<number | bigint>} [options]
133
- * @returns {this}
134
- */
135
- i52(name, options) {
136
- return this.field(name, 'i52', options);
137
- }
138
130
  /**
139
131
  * @param {string} name
140
132
  * @param {ColumnOptions<number | bigint>} [options]
@@ -159,14 +151,6 @@ class TableAdder {
159
151
  u32(name, options) {
160
152
  return this.field(name, 'u32', options);
161
153
  }
162
- /**
163
- * @param {string} name
164
- * @param {ColumnOptions<number | bigint>} [options]
165
- * @returns {this}
166
- */
167
- u52(name, options) {
168
- return this.field(name, 'u52', options);
169
- }
170
154
  /**
171
155
  * @param {string} name
172
156
  * @param {ColumnOptions<number | bigint>} [options]
@@ -221,7 +205,7 @@ class TableAdder {
221
205
  * @returns {this}
222
206
  */
223
207
  bin(name, options) {
224
- return this.field(name, 'bin', options);
208
+ return this.field(name, 'binary', options);
225
209
  }
226
210
  /**
227
211
  * @param {string} name
@@ -319,7 +303,7 @@ class TableAdder {
319
303
  * @returns {this}
320
304
  */
321
305
  uuid(name, options) {
322
- return this.field(name, 'bool', options);
306
+ return this.field(name, 'uuid', options);
323
307
  }
324
308
  /**
325
309
  * @param {string} name
@@ -327,7 +311,15 @@ class TableAdder {
327
311
  * @returns {this}
328
312
  */
329
313
  object(name, options) {
330
- return this.field(name, 'bool', options);
314
+ return this.field(name, 'object', options);
315
+ }
316
+ /**
317
+ * @param {string} name
318
+ * @param {ColumnOptions<object>} [options]
319
+ * @returns {this}
320
+ */
321
+ json(name, options) {
322
+ return this.field(name, 'json', options);
331
323
  }
332
324
  /**
333
325
  * @returns {this}
@@ -335,7 +327,7 @@ class TableAdder {
335
327
  createTime() {
336
328
  return this.field('createOn', 'timestamp', {
337
329
  nullable: true,
338
- timestampCreating: true
330
+ creating: now
339
331
  });
340
332
  }
341
333
  /**
@@ -344,7 +336,7 @@ class TableAdder {
344
336
  updateTime() {
345
337
  return this.field('updateOn', 'timestamp', {
346
338
  nullable: true,
347
- timestampUpdating: true
339
+ updating: now
348
340
  });
349
341
  }
350
342
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imodel",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "main": "index.mjs",
5
5
  "type": "module",
6
6
  "repository": {