litedbmodel 2.2.6 → 2.2.7
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/README.md +145 -86
- package/dist/Column.d.ts +17 -4
- package/dist/Column.d.ts.map +1 -1
- package/dist/Column.js.map +1 -1
- package/dist/DBModel.d.ts +13 -14
- package/dist/DBModel.d.ts.map +1 -1
- package/dist/DBModel.js +20 -21
- package/dist/DBModel.js.map +1 -1
- package/dist/LazyRelation.d.ts +2 -2
- package/dist/LazyRelation.js +2 -2
- package/dist/decorators.d.ts +120 -60
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +379 -248
- package/dist/decorators.js.map +1 -1
- package/dist/index.cjs +283 -217
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/scp/coltype.d.ts +14 -5
- package/dist/scp/coltype.d.ts.map +1 -1
- package/dist/scp/coltype.js +35 -36
- package/dist/scp/coltype.js.map +1 -1
- package/dist/scp/decorator-adapter.d.ts +11 -15
- package/dist/scp/decorator-adapter.d.ts.map +1 -1
- package/dist/scp/decorator-adapter.js +11 -15
- package/dist/scp/decorator-adapter.js.map +1 -1
- package/dist/scp/index.cjs +186 -193
- package/dist/scp/index.mjs +186 -193
- package/dist/scp/makesql/json-array.d.ts +6 -0
- package/dist/scp/makesql/json-array.d.ts.map +1 -1
- package/dist/scp/makesql/json-array.js +17 -2
- package/dist/scp/makesql/json-array.js.map +1 -1
- package/dist/scp/makesql/tx.d.ts.map +1 -1
- package/dist/scp/makesql/tx.js +1 -3
- package/dist/scp/makesql/tx.js.map +1 -1
- package/dist/scp/relation.d.ts.map +1 -1
- package/dist/scp/relation.js +8 -10
- package/dist/scp/relation.js.map +1 -1
- package/docs/BENCHMARK.md +3 -3
- package/docs/COMPARISON.md +7 -7
- package/docs/api/README.md +18 -18
- package/docs/api/classes/Conditions.md +1 -1
- package/docs/api/classes/DBHandler.md +1 -1
- package/docs/api/classes/DBModel.md +82 -82
- package/docs/api/classes/LimitExceededError.md +1 -1
- package/docs/api/classes/Middleware.md +1 -1
- package/docs/api/classes/SqlRaw.md +1 -1
- package/docs/api/classes/SqlRef.md +1 -1
- package/docs/api/classes/Values.md +1 -1
- package/docs/api/classes/WriteInReadOnlyContextError.md +1 -1
- package/docs/api/classes/WriteOutsideTransactionError.md +1 -1
- package/docs/api/functions/belongsTo.md +10 -4
- package/docs/api/functions/closeAllPools.md +1 -1
- package/docs/api/functions/condsToRecord.md +2 -2
- package/docs/api/functions/createMiddleware.md +1 -1
- package/docs/api/functions/createPostgresDriver.md +1 -1
- package/docs/api/functions/createSqliteDriver.md +1 -1
- package/docs/api/functions/dbCast.md +1 -1
- package/docs/api/functions/dbCastIn.md +1 -1
- package/docs/api/functions/dbDynamic.md +1 -1
- package/docs/api/functions/dbFalse.md +1 -1
- package/docs/api/functions/dbImmediate.md +1 -1
- package/docs/api/functions/dbIn.md +1 -1
- package/docs/api/functions/dbNotNull.md +1 -1
- package/docs/api/functions/dbNow.md +1 -1
- package/docs/api/functions/dbNull.md +1 -1
- package/docs/api/functions/dbRaw.md +1 -1
- package/docs/api/functions/dbTrue.md +1 -1
- package/docs/api/functions/dbUuid.md +1 -1
- package/docs/api/functions/dbUuidIn.md +1 -1
- package/docs/api/functions/formatLocalDate.md +1 -1
- package/docs/api/functions/formatUTCDate.md +1 -1
- package/docs/api/functions/getDBConfig.md +1 -1
- package/docs/api/functions/getDBHandler.md +1 -1
- package/docs/api/functions/getTransactionConnection.md +1 -1
- package/docs/api/functions/getTransactionContext.md +1 -1
- package/docs/api/functions/hasMany.md +11 -5
- package/docs/api/functions/hasOne.md +10 -4
- package/docs/api/functions/initDBHandler.md +1 -1
- package/docs/api/functions/isAnySqlFragment.md +1 -1
- package/docs/api/functions/isConnectionError.md +1 -1
- package/docs/api/functions/isSqlCondition.md +1 -1
- package/docs/api/functions/isSqlFragment.md +1 -1
- package/docs/api/functions/isSqlRaw.md +1 -1
- package/docs/api/functions/isSqlRef.md +1 -1
- package/docs/api/functions/isSqlTypedFragment.md +1 -1
- package/docs/api/functions/model.md +8 -155
- package/docs/api/functions/parentRef.md +1 -1
- package/docs/api/functions/sql.md +1 -1
- package/docs/api/globals.md +96 -58
- package/docs/api/interfaces/Column.md +1 -1
- package/docs/api/interfaces/ColumnDecorator.md +81 -0
- package/docs/api/interfaces/ColumnOptions.md +6 -10
- package/docs/api/interfaces/CreatedMiddlewareClass.md +1 -1
- package/docs/api/interfaces/DBConfig.md +1 -1
- package/docs/api/interfaces/DBConfigOptions.md +1 -1
- package/docs/api/interfaces/DeleteOptions.md +1 -1
- package/docs/api/interfaces/InsertOptions.md +1 -1
- package/docs/api/interfaces/LimitConfig.md +1 -1
- package/docs/api/interfaces/MiddlewareConfig.md +1 -1
- package/docs/api/interfaces/ModelClassDecorator.md +64 -0
- package/docs/api/interfaces/ModelOptions.md +1 -1
- package/docs/api/interfaces/PkeyResult.md +1 -1
- package/docs/api/interfaces/RelationDecorator.md +72 -0
- package/docs/api/interfaces/SelectOptions.md +1 -1
- package/docs/api/interfaces/SqlCondition.md +1 -1
- package/docs/api/interfaces/SqlFragment.md +1 -1
- package/docs/api/interfaces/SqlTypedFragment.md +1 -1
- package/docs/api/interfaces/TransactionOptions.md +1 -1
- package/docs/api/interfaces/UpdateManyOptions.md +1 -1
- package/docs/api/interfaces/UpdateOptions.md +1 -1
- package/docs/api-guide.md +17 -17
- package/docs/architecture.md +3 -3
- package/docs/sql-tagged-template.md +5 -5
- package/eslint-plugin/rules/require-declare-for-relations.js +59 -4
- package/package.json +8 -7
package/dist/scp/index.cjs
CHANGED
|
@@ -2230,12 +2230,14 @@ function tupleInPredicate(dialect, table, columns, pgElementTypes) {
|
|
|
2230
2230
|
function encodeJsonArrayParam(dialect, values) {
|
|
2231
2231
|
return encodeJsonParam(dialect, values);
|
|
2232
2232
|
}
|
|
2233
|
+
var BIGINT_SENTINEL = "\0int:";
|
|
2233
2234
|
function encodeJsonParam(dialect, payload) {
|
|
2234
|
-
|
|
2235
|
-
if (typeof v === "bigint") return
|
|
2235
|
+
const tagged = JSON.stringify(payload, (_key, v) => {
|
|
2236
|
+
if (typeof v === "bigint") return `${BIGINT_SENTINEL}${v.toString()}`;
|
|
2236
2237
|
if (dialect === "mysql" && typeof v === "boolean") return v ? 1 : 0;
|
|
2237
2238
|
return v;
|
|
2238
2239
|
});
|
|
2240
|
+
return tagged.replace(/"\\u0000int:(-?\d+)"/g, "$1");
|
|
2239
2241
|
}
|
|
2240
2242
|
var JsonArrayConditions = class extends DBConditions {
|
|
2241
2243
|
_dialect;
|
|
@@ -3941,8 +3943,8 @@ function sqlTypeToMaterializeClass(sqlType) {
|
|
|
3941
3943
|
return "passthrough";
|
|
3942
3944
|
}
|
|
3943
3945
|
switch (t) {
|
|
3944
|
-
//
|
|
3945
|
-
//
|
|
3946
|
+
// Integer family. The PostgreSQL SERIAL types are the same integers under an auto-increment
|
|
3947
|
+
// default (SERIAL/SERIAL4=int4, SMALLSERIAL/SERIAL2=int2, BIGSERIAL/SERIAL8=int8).
|
|
3946
3948
|
case "INTEGER":
|
|
3947
3949
|
case "INT":
|
|
3948
3950
|
case "SMALLINT":
|
|
@@ -3954,13 +3956,11 @@ function sqlTypeToMaterializeClass(sqlType) {
|
|
|
3954
3956
|
case "SERIAL4":
|
|
3955
3957
|
case "SMALLSERIAL":
|
|
3956
3958
|
case "SERIAL2":
|
|
3957
|
-
return "int32";
|
|
3958
|
-
// 64-bit int: needs JS bigint for exactness.
|
|
3959
3959
|
case "BIGINT":
|
|
3960
3960
|
case "INT8":
|
|
3961
3961
|
case "BIGSERIAL":
|
|
3962
3962
|
case "SERIAL8":
|
|
3963
|
-
return "
|
|
3963
|
+
return "int";
|
|
3964
3964
|
case "BOOLEAN":
|
|
3965
3965
|
case "BOOL":
|
|
3966
3966
|
return "bool";
|
|
@@ -3997,44 +3997,45 @@ function sqlTypeToMaterializeClass(sqlType) {
|
|
|
3997
3997
|
}
|
|
3998
3998
|
function keyArrayElemScalar(sqlType) {
|
|
3999
3999
|
switch (sqlTypeToMaterializeClass(sqlType)) {
|
|
4000
|
-
case "
|
|
4001
|
-
return "
|
|
4002
|
-
// materializes to a JS
|
|
4003
|
-
case "int64":
|
|
4000
|
+
case "int":
|
|
4001
|
+
return "int";
|
|
4002
|
+
// materializes to a JS bigint → bc int
|
|
4004
4003
|
case "date":
|
|
4005
4004
|
return "string";
|
|
4006
|
-
// materializes to a
|
|
4005
|
+
// materializes to a TZ string → bc string
|
|
4007
4006
|
case "bool":
|
|
4008
4007
|
return "bool";
|
|
4009
4008
|
case "passthrough":
|
|
4010
4009
|
return sqlTypeToBcScalar(sqlType) === "float" ? "float" : "string";
|
|
4011
4010
|
}
|
|
4012
4011
|
}
|
|
4012
|
+
var I64_MIN2 = -(2n ** 63n);
|
|
4013
|
+
var I64_MAX2 = 2n ** 63n - 1n;
|
|
4014
|
+
function checkI642(v) {
|
|
4015
|
+
if (v < I64_MIN2 || v > I64_MAX2) {
|
|
4016
|
+
throw new Error(`materialize int: ${v} is outside the i64 range behavior-contracts' \`int\` admits`);
|
|
4017
|
+
}
|
|
4018
|
+
return v;
|
|
4019
|
+
}
|
|
4013
4020
|
function materializeCell(value, klass) {
|
|
4014
4021
|
if (value === null || value === void 0) return value;
|
|
4015
4022
|
switch (klass) {
|
|
4016
|
-
case "
|
|
4017
|
-
if (typeof value === "bigint") return value
|
|
4023
|
+
case "int": {
|
|
4024
|
+
if (typeof value === "bigint") return checkI642(value);
|
|
4018
4025
|
if (typeof value === "string") {
|
|
4019
|
-
if (!/^-?\d+$/.test(value)) throw new Error(`materialize
|
|
4020
|
-
return value;
|
|
4026
|
+
if (!/^-?\d+$/.test(value)) throw new Error(`materialize int: driver returned a non-integer string '${value}'`);
|
|
4027
|
+
return checkI642(BigInt(value));
|
|
4021
4028
|
}
|
|
4022
4029
|
if (typeof value === "number") {
|
|
4023
|
-
if (!Number.isInteger(value)) throw new Error(`materialize
|
|
4030
|
+
if (!Number.isInteger(value)) throw new Error(`materialize int: driver returned a non-integer number ${value} for an integer column`);
|
|
4024
4031
|
if (!Number.isSafeInteger(value)) {
|
|
4025
4032
|
throw new Error(
|
|
4026
|
-
`materialize
|
|
4033
|
+
`materialize int: driver returned an UNSAFE JS number ${value} for an integer column \u2014 precision was already lost before materialization (the driver must return integers as bigint/string, not a rounded double). Configure the driver (better-sqlite3 safeIntegers / mysql2 supportBigNumbers+bigNumberStrings / pg int-as-bigint).`
|
|
4027
4034
|
);
|
|
4028
4035
|
}
|
|
4029
|
-
return value
|
|
4036
|
+
return BigInt(value);
|
|
4030
4037
|
}
|
|
4031
|
-
throw new Error(`materialize
|
|
4032
|
-
}
|
|
4033
|
-
case "int32": {
|
|
4034
|
-
if (typeof value === "number") return value;
|
|
4035
|
-
if (typeof value === "bigint") return Number(value);
|
|
4036
|
-
if (typeof value === "string" && /^-?\d+$/.test(value)) return Number(value);
|
|
4037
|
-
throw new Error(`materialize int32: unexpected driver JS type ${typeof value} (${String(value)})`);
|
|
4038
|
+
throw new Error(`materialize int: unexpected driver JS type ${typeof value}`);
|
|
4038
4039
|
}
|
|
4039
4040
|
case "date": {
|
|
4040
4041
|
if (typeof value === "string") return value;
|
|
@@ -5523,8 +5524,7 @@ function onConflictTail(dialect, ports, cols) {
|
|
|
5523
5524
|
}
|
|
5524
5525
|
function pgTypeSpecimen(sqlType) {
|
|
5525
5526
|
const klass = sqlTypeToMaterializeClass(sqlType);
|
|
5526
|
-
if (klass === "
|
|
5527
|
-
if (klass === "int64") return 0n;
|
|
5527
|
+
if (klass === "int") return 0n;
|
|
5528
5528
|
if (klass === "bool") return false;
|
|
5529
5529
|
if (klass === "date") return /* @__PURE__ */ new Date(0);
|
|
5530
5530
|
const scalar = sqlTypeToBcScalar(sqlType);
|
|
@@ -6156,10 +6156,6 @@ function materializeChildRows(rows, cols) {
|
|
|
6156
6156
|
row[key] = materializeCell(row[key], klass);
|
|
6157
6157
|
continue;
|
|
6158
6158
|
}
|
|
6159
|
-
if (typeof row[key] === "bigint") {
|
|
6160
|
-
const v = row[key];
|
|
6161
|
-
row[key] = v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(v) : v.toString();
|
|
6162
|
-
}
|
|
6163
6159
|
}
|
|
6164
6160
|
}
|
|
6165
6161
|
return rows;
|
|
@@ -6299,133 +6295,108 @@ function compileDeleteManyBundle(name, options, dialectName = "sqlite") {
|
|
|
6299
6295
|
var import_reflect_metadata = __toESM(require_Reflect());
|
|
6300
6296
|
var COLUMNS_KEY = /* @__PURE__ */ Symbol("litedbmodel:columns");
|
|
6301
6297
|
var RELATIONS_KEY = /* @__PURE__ */ Symbol("litedbmodel:relations");
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
return materializeCell(v, "date");
|
|
6320
|
-
},
|
|
6321
|
-
// Delegate to driver-specific serializeDatetime
|
|
6322
|
-
serialize: (val, typeCast) => {
|
|
6323
|
-
if (val === null || val === void 0) return null;
|
|
6324
|
-
if (val instanceof Date) {
|
|
6325
|
-
return typeCast?.serializeDatetime(val) ?? val;
|
|
6326
|
-
}
|
|
6327
|
-
return val;
|
|
6328
|
-
},
|
|
6329
|
-
sqlCast: "timestamp"
|
|
6330
|
-
};
|
|
6331
|
-
case Number:
|
|
6332
|
-
return {
|
|
6333
|
-
typeCast: (v) => {
|
|
6334
|
-
if (v === void 0) return void 0;
|
|
6335
|
-
if (v === null) return null;
|
|
6336
|
-
const n = Number(v);
|
|
6337
|
-
return isNaN(n) ? null : n;
|
|
6338
|
-
}
|
|
6339
|
-
};
|
|
6340
|
-
case BigInt:
|
|
6341
|
-
return {
|
|
6342
|
-
// v2 read contract: BIGINT/INT8 → EXACT decimal STRING (no i64 rounding, JSON-safe), via the
|
|
6343
|
-
// shared materializer. NOTE: the TS field type stays `bigint` in existing models for source
|
|
6344
|
-
// compat, but the VALUE is now the exact string — the whole point of the #9 realignment.
|
|
6345
|
-
typeCast: (v) => {
|
|
6346
|
-
if (v === void 0) return void 0;
|
|
6347
|
-
return materializeCell(v, "int64");
|
|
6348
|
-
},
|
|
6349
|
-
sqlCast: "bigint"
|
|
6350
|
-
};
|
|
6351
|
-
// Array, Object, String, and other types require explicit specification
|
|
6352
|
-
default:
|
|
6353
|
-
return void 0;
|
|
6354
|
-
}
|
|
6355
|
-
}
|
|
6356
|
-
function inferBaseSqlTypeFromDesignType(target, propertyKey) {
|
|
6357
|
-
const designType = Reflect.getMetadata("design:type", target, propertyKey);
|
|
6358
|
-
if (!designType) return void 0;
|
|
6359
|
-
switch (designType) {
|
|
6360
|
-
case String:
|
|
6361
|
-
return "TEXT";
|
|
6362
|
-
case Number:
|
|
6363
|
-
return "INTEGER";
|
|
6364
|
-
case Boolean:
|
|
6365
|
-
return "BOOLEAN";
|
|
6366
|
-
case Date:
|
|
6367
|
-
return "TIMESTAMP";
|
|
6368
|
-
case BigInt:
|
|
6369
|
-
return "BIGINT";
|
|
6370
|
-
default:
|
|
6371
|
-
return void 0;
|
|
6298
|
+
if (typeof Symbol === "function" && !Symbol.metadata) {
|
|
6299
|
+
Object.defineProperty(Symbol, "metadata", {
|
|
6300
|
+
value: /* @__PURE__ */ Symbol.for("Symbol.metadata"),
|
|
6301
|
+
writable: false,
|
|
6302
|
+
enumerable: false,
|
|
6303
|
+
configurable: true
|
|
6304
|
+
});
|
|
6305
|
+
}
|
|
6306
|
+
function isStandardContext(second) {
|
|
6307
|
+
return typeof second === "object" && second !== null && typeof second.kind === "string";
|
|
6308
|
+
}
|
|
6309
|
+
function classMetadataBag(context, propertyKey) {
|
|
6310
|
+
const bag = context.metadata;
|
|
6311
|
+
if (bag === void 0) {
|
|
6312
|
+
throw new Error(
|
|
6313
|
+
`litedbmodel: the standard-decorator context for '${propertyKey}' carries no \`context.metadata\`. litedbmodel defines \`Symbol.metadata\` on import, which every current emit needs to create the bag \u2014 import litedbmodel (or 'litedbmodel/decorators') BEFORE the module that defines the model.`
|
|
6314
|
+
);
|
|
6372
6315
|
}
|
|
6316
|
+
return bag;
|
|
6373
6317
|
}
|
|
6374
|
-
function
|
|
6375
|
-
const
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
if (!finalSqlCast) finalSqlCast = inferred.sqlCast;
|
|
6386
|
-
}
|
|
6318
|
+
function legacyColumnMap(constructor) {
|
|
6319
|
+
const own = Reflect.getOwnMetadata(COLUMNS_KEY, constructor);
|
|
6320
|
+
if (own !== void 0) return own;
|
|
6321
|
+
const inherited = Reflect.getMetadata(COLUMNS_KEY, constructor);
|
|
6322
|
+
const map = new Map(inherited);
|
|
6323
|
+
Reflect.defineMetadata(COLUMNS_KEY, map, constructor);
|
|
6324
|
+
return map;
|
|
6325
|
+
}
|
|
6326
|
+
function standardColumnMap(bag) {
|
|
6327
|
+
if (!Object.prototype.hasOwnProperty.call(bag, COLUMNS_KEY)) {
|
|
6328
|
+
bag[COLUMNS_KEY] = new Map(bag[COLUMNS_KEY]);
|
|
6387
6329
|
}
|
|
6388
|
-
|
|
6330
|
+
return bag[COLUMNS_KEY];
|
|
6331
|
+
}
|
|
6332
|
+
function registerColumn(columns, propertyKey, options) {
|
|
6389
6333
|
columns.set(propertyKey, {
|
|
6390
6334
|
columnName: options.columnName,
|
|
6391
|
-
typeCast:
|
|
6392
|
-
serialize:
|
|
6335
|
+
typeCast: options.typeCast,
|
|
6336
|
+
serialize: options.serialize,
|
|
6393
6337
|
primaryKey: options.primaryKey,
|
|
6394
6338
|
autoIncrement: options.autoIncrement,
|
|
6395
|
-
sqlCast:
|
|
6396
|
-
...baseSqlType !== void 0 ? { baseSqlType } : {}
|
|
6339
|
+
sqlCast: options.sqlCast,
|
|
6340
|
+
...options.baseSqlType !== void 0 ? { baseSqlType: options.baseSqlType } : {}
|
|
6397
6341
|
});
|
|
6398
|
-
Reflect.defineMetadata(COLUMNS_KEY, columns, constructor);
|
|
6399
6342
|
}
|
|
6400
|
-
function
|
|
6343
|
+
function parseColumnOptions(columnNameOrOptions, propKey) {
|
|
6344
|
+
if (typeof columnNameOrOptions === "string") return { columnName: columnNameOrOptions };
|
|
6345
|
+
if (columnNameOrOptions) {
|
|
6346
|
+
return {
|
|
6347
|
+
columnName: columnNameOrOptions.columnName || propKey,
|
|
6348
|
+
primaryKey: columnNameOrOptions.primaryKey,
|
|
6349
|
+
autoIncrement: columnNameOrOptions.autoIncrement
|
|
6350
|
+
};
|
|
6351
|
+
}
|
|
6352
|
+
return { columnName: propKey };
|
|
6353
|
+
}
|
|
6354
|
+
function rejectNonText(family, val) {
|
|
6355
|
+
if (val === null || val === void 0) return null;
|
|
6356
|
+
if (val instanceof Date) {
|
|
6357
|
+
throw new Error(
|
|
6358
|
+
`litedbmodel: @column.${family}() received a Date. A text column cannot serialize one \u2014 the driver would store an object literal. Use @column.datetime() / @column.date() for a date column, or format the value yourself.`
|
|
6359
|
+
);
|
|
6360
|
+
}
|
|
6361
|
+
if (typeof val === "object") {
|
|
6362
|
+
throw new Error(
|
|
6363
|
+
`litedbmodel: @column.${family}() received an object. Use @column.json<T>() for a JSON column, or @column.custom() with a serializer.`
|
|
6364
|
+
);
|
|
6365
|
+
}
|
|
6366
|
+
return val;
|
|
6367
|
+
}
|
|
6368
|
+
function createColumnDecorator(typeCast, serialize, sqlCast, baseSqlType) {
|
|
6401
6369
|
return function(columnNameOrOptions) {
|
|
6402
|
-
return function(
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
} else {
|
|
6415
|
-
columnName = propKey;
|
|
6370
|
+
return function(targetOrValue, keyOrContext) {
|
|
6371
|
+
if (isStandardContext(keyOrContext)) {
|
|
6372
|
+
const propKey2 = String(keyOrContext.name);
|
|
6373
|
+
const parsed2 = parseColumnOptions(columnNameOrOptions, propKey2);
|
|
6374
|
+
registerColumn(standardColumnMap(classMetadataBag(keyOrContext, propKey2)), propKey2, {
|
|
6375
|
+
...parsed2,
|
|
6376
|
+
typeCast,
|
|
6377
|
+
serialize,
|
|
6378
|
+
sqlCast,
|
|
6379
|
+
baseSqlType
|
|
6380
|
+
});
|
|
6381
|
+
return;
|
|
6416
6382
|
}
|
|
6417
|
-
|
|
6418
|
-
|
|
6383
|
+
const propKey = String(keyOrContext);
|
|
6384
|
+
const parsed = parseColumnOptions(columnNameOrOptions, propKey);
|
|
6385
|
+
registerColumn(legacyColumnMap(targetOrValue.constructor), propKey, {
|
|
6386
|
+
...parsed,
|
|
6419
6387
|
typeCast,
|
|
6420
6388
|
serialize,
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
autoIncrement,
|
|
6424
|
-
sqlCast
|
|
6389
|
+
sqlCast,
|
|
6390
|
+
baseSqlType
|
|
6425
6391
|
});
|
|
6426
6392
|
};
|
|
6427
6393
|
};
|
|
6428
6394
|
}
|
|
6395
|
+
function requireColumnFamily() {
|
|
6396
|
+
throw new Error(
|
|
6397
|
+
"litedbmodel: `@column()` no longer declares a column \u2014 a column must state its type with a family: @column.text() / .number() / .boolean() / .bigint() / .datetime() / .date() / .uuid() / .json() / .stringArray() / .intArray() / .numericArray() / .booleanArray() / .datetimeArray() / .passthrough() / .custom(). Every family takes the same argument as `@column()` did (`@column.text('db_name')`, `@column.number({ primaryKey: true })`). The bare form inferred the type from `emitDecoratorMetadata`, which esbuild (tsx/vite/vitest) never emits and standard decorators do not have, so it silently produced untyped reads."
|
|
6398
|
+
);
|
|
6399
|
+
}
|
|
6429
6400
|
function serializeArray(val, typeCast) {
|
|
6430
6401
|
if (val === null || val === void 0) return null;
|
|
6431
6402
|
if (!Array.isArray(val)) return val;
|
|
@@ -6463,19 +6434,44 @@ function serializeJson(val, typeCast) {
|
|
|
6463
6434
|
return JSON.stringify(val);
|
|
6464
6435
|
}
|
|
6465
6436
|
var column = Object.assign(
|
|
6466
|
-
//
|
|
6467
|
-
|
|
6437
|
+
// The bare `@column()` declared no type — it is rejected, with the migration in the message.
|
|
6438
|
+
(_columnNameOrOptions) => requireColumnFamily(),
|
|
6468
6439
|
{
|
|
6469
6440
|
// ============================================
|
|
6470
6441
|
// Primitive Types
|
|
6471
6442
|
// ============================================
|
|
6443
|
+
/**
|
|
6444
|
+
* Text type (TEXT / VARCHAR / CHAR / ENUM / citext) — the driver value is already a string, so no
|
|
6445
|
+
* cast is applied. The family still DECLARES the column so the typed read types it as `TEXT`.
|
|
6446
|
+
* @example @column.text() name?: string;
|
|
6447
|
+
* @example @column.text('user_name') name?: string;
|
|
6448
|
+
*/
|
|
6449
|
+
text: (columnNameOrOptions) => createColumnDecorator(
|
|
6450
|
+
// The family DECLARES `string`, so it must hand back one. Most drivers already do, but SQLite
|
|
6451
|
+
// is dynamically typed: it returns a JS number for a `NUMERIC`/`DECIMAL` column whatever the
|
|
6452
|
+
// declaration says, and the declared type would be a lie on that dialect alone.
|
|
6453
|
+
(v) => {
|
|
6454
|
+
if (v === void 0 || v === null) return v;
|
|
6455
|
+
if (typeof v === "string") return v;
|
|
6456
|
+
if (typeof v === "number" || typeof v === "bigint" || typeof v === "boolean") return String(v);
|
|
6457
|
+
throw new Error(
|
|
6458
|
+
`materialize text: driver returned ${typeof v} for a text column. Use @column.passthrough() for a BYTEA/BLOB column, or @column.json<T>() for JSON.`
|
|
6459
|
+
);
|
|
6460
|
+
},
|
|
6461
|
+
(val) => rejectNonText("text", val),
|
|
6462
|
+
// …and it cannot SERIALIZE a Date or an object
|
|
6463
|
+
void 0,
|
|
6464
|
+
// no sqlCast family (a text literal needs no SQL cast)
|
|
6465
|
+
"TEXT"
|
|
6466
|
+
// §4.1 token: types the SCP typed read
|
|
6467
|
+
)(columnNameOrOptions),
|
|
6472
6468
|
/**
|
|
6473
6469
|
* Boolean type conversion
|
|
6474
6470
|
* Converts 't'/'f', 'true'/'false', 1/0 to boolean
|
|
6475
6471
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6476
6472
|
* @example @column.boolean() is_active?: boolean;
|
|
6477
6473
|
*/
|
|
6478
|
-
boolean: (
|
|
6474
|
+
boolean: (columnNameOrOptions) => createColumnDecorator(
|
|
6479
6475
|
// v2 read contract: BOOLEAN → boolean, via the shared materializer (issue #9).
|
|
6480
6476
|
(v) => {
|
|
6481
6477
|
if (v === void 0) return void 0;
|
|
@@ -6483,42 +6479,38 @@ var column = Object.assign(
|
|
|
6483
6479
|
},
|
|
6484
6480
|
void 0,
|
|
6485
6481
|
// no custom serialize
|
|
6486
|
-
false,
|
|
6487
|
-
// allow auto-inference
|
|
6488
6482
|
"boolean"
|
|
6489
6483
|
// sqlCast for updateMany type inference
|
|
6490
|
-
)(
|
|
6484
|
+
)(columnNameOrOptions),
|
|
6491
6485
|
/**
|
|
6492
6486
|
* Number type conversion (from string)
|
|
6493
6487
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6494
6488
|
* @example @column.number() amount?: number;
|
|
6495
6489
|
*/
|
|
6496
|
-
number: (
|
|
6490
|
+
number: (columnNameOrOptions) => createColumnDecorator((v) => {
|
|
6497
6491
|
if (v === void 0) return void 0;
|
|
6498
6492
|
if (v === null) return null;
|
|
6499
6493
|
const n = Number(v);
|
|
6500
6494
|
return isNaN(n) ? null : n;
|
|
6501
|
-
})(
|
|
6495
|
+
})(columnNameOrOptions),
|
|
6502
6496
|
/**
|
|
6503
6497
|
* BigInt type conversion
|
|
6504
6498
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6505
|
-
* @example @column.bigint() large_id?: bigint;
|
|
6499
|
+
* @example @column.bigint() large_id?: bigint; // bc `int` — a JS bigint, checked i64
|
|
6506
6500
|
*/
|
|
6507
|
-
bigint: (
|
|
6508
|
-
//
|
|
6509
|
-
//
|
|
6510
|
-
//
|
|
6501
|
+
bigint: (columnNameOrOptions) => createColumnDecorator(
|
|
6502
|
+
// An integer column reads back as a JS `bigint` — behavior-contracts' `int` value model
|
|
6503
|
+
// (`int` = bigint, checked i64), which is what the drivers already hand over. `JSON.stringify`
|
|
6504
|
+
// does not serialize a bigint: give the field a `toJSON`, or convert at the boundary.
|
|
6511
6505
|
(v) => {
|
|
6512
6506
|
if (v === void 0) return void 0;
|
|
6513
|
-
return materializeCell(v, "
|
|
6507
|
+
return materializeCell(v, "int");
|
|
6514
6508
|
},
|
|
6515
6509
|
void 0,
|
|
6516
6510
|
// no custom serialize
|
|
6517
|
-
false,
|
|
6518
|
-
// allow auto-inference
|
|
6519
6511
|
"bigint"
|
|
6520
6512
|
// sqlCast for WHERE/INSERT type casting
|
|
6521
|
-
)(
|
|
6513
|
+
)(columnNameOrOptions),
|
|
6522
6514
|
// ============================================
|
|
6523
6515
|
// Date/Time Types
|
|
6524
6516
|
// ============================================
|
|
@@ -6530,9 +6522,9 @@ var column = Object.assign(
|
|
|
6530
6522
|
* - PostgreSQL: Serializes to ISO 8601 UTC string with 'Z' suffix for explicit timezone
|
|
6531
6523
|
* - MySQL/SQLite: Passes Date object to driver (driver-dependent timezone handling)
|
|
6532
6524
|
*
|
|
6533
|
-
* @example @column.datetime() created_at?: Date
|
|
6525
|
+
* @example @column.datetime() created_at?: string; // TZ-attached string, NOT a JS Date
|
|
6534
6526
|
*/
|
|
6535
|
-
datetime: (
|
|
6527
|
+
datetime: (columnNameOrOptions) => createColumnDecorator(
|
|
6536
6528
|
// v2 read contract: DATE/TIMESTAMP/TIMESTAMPTZ/DATETIME/TIME → TZ-attached STRING (NOT a
|
|
6537
6529
|
// TZ-shifted JS Date), via the shared materializer (issue #9). A driver already returning the
|
|
6538
6530
|
// native textual form passes through; a JS Date is rendered to its lossless ISO instant.
|
|
@@ -6548,11 +6540,9 @@ var column = Object.assign(
|
|
|
6548
6540
|
}
|
|
6549
6541
|
return val;
|
|
6550
6542
|
},
|
|
6551
|
-
false,
|
|
6552
|
-
// allow auto-inference
|
|
6553
6543
|
"timestamp"
|
|
6554
6544
|
// sqlCast for updateMany type inference
|
|
6555
|
-
)(
|
|
6545
|
+
)(columnNameOrOptions),
|
|
6556
6546
|
/**
|
|
6557
6547
|
* Date type conversion — returns YYYY-MM-DD string.
|
|
6558
6548
|
* Preserves null for nullable columns, undefined stays undefined.
|
|
@@ -6560,9 +6550,9 @@ var column = Object.assign(
|
|
|
6560
6550
|
* DB values (Date object or string) are normalized to 'YYYY-MM-DD' string.
|
|
6561
6551
|
* On write, string values are passed through; Date objects are formatted as 'YYYY-MM-DD'.
|
|
6562
6552
|
*
|
|
6563
|
-
* @example @column.date() birth_date?: string;
|
|
6553
|
+
* @example @column.date() birth_date?: string; // 'YYYY-MM-DD'
|
|
6564
6554
|
*/
|
|
6565
|
-
date: (
|
|
6555
|
+
date: (columnNameOrOptions) => createColumnDecorator(
|
|
6566
6556
|
(v) => {
|
|
6567
6557
|
if (v === void 0) return void 0;
|
|
6568
6558
|
if (v === null) return null;
|
|
@@ -6587,11 +6577,9 @@ var column = Object.assign(
|
|
|
6587
6577
|
}
|
|
6588
6578
|
return val;
|
|
6589
6579
|
},
|
|
6590
|
-
false,
|
|
6591
|
-
// allow auto-inference
|
|
6592
6580
|
"date"
|
|
6593
6581
|
// sqlCast for updateMany type inference
|
|
6594
|
-
)(
|
|
6582
|
+
)(columnNameOrOptions),
|
|
6595
6583
|
// ============================================
|
|
6596
6584
|
// Array Types
|
|
6597
6585
|
// ============================================
|
|
@@ -6600,71 +6588,71 @@ var column = Object.assign(
|
|
|
6600
6588
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6601
6589
|
* @example @column.stringArray() tags?: string[];
|
|
6602
6590
|
*/
|
|
6603
|
-
stringArray: (
|
|
6591
|
+
stringArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6604
6592
|
(v) => {
|
|
6605
6593
|
if (v === void 0) return void 0;
|
|
6606
6594
|
if (v === null) return null;
|
|
6607
6595
|
return castToStringArray(v);
|
|
6608
6596
|
},
|
|
6609
6597
|
serializeArray,
|
|
6610
|
-
false,
|
|
6611
6598
|
"text[]"
|
|
6612
|
-
)(
|
|
6599
|
+
)(columnNameOrOptions),
|
|
6613
6600
|
/**
|
|
6614
6601
|
* Integer array type conversion (integer[])
|
|
6615
6602
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6616
6603
|
* @example @column.intArray() scores?: number[];
|
|
6617
6604
|
*/
|
|
6618
|
-
intArray: (
|
|
6605
|
+
intArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6619
6606
|
(v) => {
|
|
6620
6607
|
if (v === void 0) return void 0;
|
|
6621
6608
|
if (v === null) return null;
|
|
6622
6609
|
return castToIntegerArray(v);
|
|
6623
6610
|
},
|
|
6624
6611
|
serializeArray,
|
|
6625
|
-
false,
|
|
6626
6612
|
"int[]"
|
|
6627
|
-
)(
|
|
6613
|
+
)(columnNameOrOptions),
|
|
6628
6614
|
/**
|
|
6629
6615
|
* Numeric array type conversion (numeric[], allows null elements)
|
|
6630
6616
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6631
6617
|
* @example @column.numericArray() values?: (number | null)[];
|
|
6632
6618
|
*/
|
|
6633
|
-
numericArray: (
|
|
6619
|
+
numericArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6634
6620
|
(v) => {
|
|
6635
6621
|
if (v === void 0) return void 0;
|
|
6636
6622
|
if (v === null) return null;
|
|
6637
6623
|
return castToNumericArray(v);
|
|
6638
6624
|
},
|
|
6639
6625
|
serializeArray,
|
|
6640
|
-
false,
|
|
6641
6626
|
"numeric[]"
|
|
6642
|
-
)(
|
|
6627
|
+
)(columnNameOrOptions),
|
|
6643
6628
|
/**
|
|
6644
6629
|
* Boolean array type conversion (boolean[])
|
|
6645
6630
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6646
6631
|
* @example @column.booleanArray() flags?: (boolean | null)[];
|
|
6647
6632
|
*/
|
|
6648
|
-
booleanArray: (
|
|
6633
|
+
booleanArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6649
6634
|
(v) => {
|
|
6650
6635
|
if (v === void 0) return void 0;
|
|
6651
6636
|
if (v === null) return null;
|
|
6652
6637
|
return castToBooleanArray(v);
|
|
6653
6638
|
},
|
|
6654
6639
|
serializeBooleanArray,
|
|
6655
|
-
false,
|
|
6656
6640
|
"boolean[]"
|
|
6657
|
-
)(
|
|
6641
|
+
)(columnNameOrOptions),
|
|
6658
6642
|
/**
|
|
6659
6643
|
* DateTime array type conversion (timestamp[])
|
|
6660
6644
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6661
|
-
* @example @column.datetimeArray() event_dates?: (
|
|
6645
|
+
* @example @column.datetimeArray() event_dates?: (string | null)[];
|
|
6662
6646
|
*/
|
|
6663
|
-
datetimeArray: (
|
|
6647
|
+
datetimeArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6648
|
+
// Element-wise the SAME contract as `@column.datetime()`: a TZ-attached STRING, never a
|
|
6649
|
+
// TZ-shifted JS Date. The array family used to be the one place a `Date` still came back, so
|
|
6650
|
+
// `JSON.stringify` of a row silently re-rendered those elements in UTC — the exact hazard #9
|
|
6651
|
+
// closed for the scalar.
|
|
6664
6652
|
(v) => {
|
|
6665
6653
|
if (v === void 0) return void 0;
|
|
6666
6654
|
if (v === null) return null;
|
|
6667
|
-
return castToDatetimeArray(v);
|
|
6655
|
+
return castToDatetimeArray(v).map((d) => d === null ? null : materializeCell(d, "date"));
|
|
6668
6656
|
},
|
|
6669
6657
|
// DateTime arrays serialize each Date to ISO string
|
|
6670
6658
|
(val) => {
|
|
@@ -6673,7 +6661,7 @@ var column = Object.assign(
|
|
|
6673
6661
|
const mapped = val.map((v) => v === null ? "NULL" : v instanceof Date ? v.toISOString() : String(v));
|
|
6674
6662
|
return `{${mapped.join(",")}}`;
|
|
6675
6663
|
}
|
|
6676
|
-
)(
|
|
6664
|
+
)(columnNameOrOptions),
|
|
6677
6665
|
// ============================================
|
|
6678
6666
|
// JSON Types
|
|
6679
6667
|
// ============================================
|
|
@@ -6683,16 +6671,15 @@ var column = Object.assign(
|
|
|
6683
6671
|
* @example @column.json() metadata?: Record<string, unknown>;
|
|
6684
6672
|
* @example @column.json<UserSettings>() settings?: UserSettings;
|
|
6685
6673
|
*/
|
|
6686
|
-
json: (
|
|
6674
|
+
json: (columnNameOrOptions) => createColumnDecorator(
|
|
6687
6675
|
(v) => {
|
|
6688
6676
|
if (v === void 0) return void 0;
|
|
6689
6677
|
if (v === null) return null;
|
|
6690
6678
|
return castToJson(v);
|
|
6691
6679
|
},
|
|
6692
6680
|
serializeJson,
|
|
6693
|
-
false,
|
|
6694
6681
|
"jsonb"
|
|
6695
|
-
)(
|
|
6682
|
+
)(columnNameOrOptions),
|
|
6696
6683
|
// ============================================
|
|
6697
6684
|
// UUID Type (PostgreSQL)
|
|
6698
6685
|
// ============================================
|
|
@@ -6721,22 +6708,28 @@ var column = Object.assign(
|
|
|
6721
6708
|
if (v === null) return null;
|
|
6722
6709
|
return String(v);
|
|
6723
6710
|
},
|
|
6724
|
-
|
|
6725
|
-
//
|
|
6726
|
-
true,
|
|
6727
|
-
// Skip auto-inference
|
|
6711
|
+
(val) => rejectNonText("uuid", val),
|
|
6712
|
+
// the ::uuid cast handles the rest
|
|
6728
6713
|
"uuid"
|
|
6729
6714
|
// SQL type for casting
|
|
6730
6715
|
)(columnNameOrOptions),
|
|
6731
6716
|
// ============================================
|
|
6732
6717
|
// Custom Type Conversion
|
|
6733
6718
|
// ============================================
|
|
6719
|
+
/**
|
|
6720
|
+
* The driver's value, UNCAST — for a column whose type the library has no cast for (`BYTEA` /
|
|
6721
|
+
* `BLOB` arrives as a driver Buffer, a vendor type as whatever the driver decodes). It states
|
|
6722
|
+
* "this column is passed through", which is a DECLARATION; the removed bare `@column()` was the
|
|
6723
|
+
* absence of one, and produced this same passthrough by accident for every unresolvable type.
|
|
6724
|
+
* @example @column.passthrough() payload?: unknown;
|
|
6725
|
+
*/
|
|
6726
|
+
passthrough: (columnNameOrOptions) => createColumnDecorator()(columnNameOrOptions),
|
|
6734
6727
|
/**
|
|
6735
6728
|
* Custom type conversion with user-provided function
|
|
6736
6729
|
* @example @column.custom((v) => String(v).toUpperCase()) status?: string;
|
|
6737
6730
|
* @example @column.custom((v) => v, (v) => JSON.stringify(v)) data?: MyType; // with serializer
|
|
6738
6731
|
*/
|
|
6739
|
-
custom: (castFn, serializeFn,
|
|
6732
|
+
custom: (castFn, serializeFn, columnNameOrOptions) => createColumnDecorator(castFn, serializeFn)(columnNameOrOptions)
|
|
6740
6733
|
}
|
|
6741
6734
|
);
|
|
6742
6735
|
function getRelationMeta(modelClass) {
|