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.mjs
CHANGED
|
@@ -2054,12 +2054,14 @@ function tupleInPredicate(dialect, table, columns, pgElementTypes) {
|
|
|
2054
2054
|
function encodeJsonArrayParam(dialect, values) {
|
|
2055
2055
|
return encodeJsonParam(dialect, values);
|
|
2056
2056
|
}
|
|
2057
|
+
var BIGINT_SENTINEL = "\0int:";
|
|
2057
2058
|
function encodeJsonParam(dialect, payload) {
|
|
2058
|
-
|
|
2059
|
-
if (typeof v === "bigint") return
|
|
2059
|
+
const tagged = JSON.stringify(payload, (_key, v) => {
|
|
2060
|
+
if (typeof v === "bigint") return `${BIGINT_SENTINEL}${v.toString()}`;
|
|
2060
2061
|
if (dialect === "mysql" && typeof v === "boolean") return v ? 1 : 0;
|
|
2061
2062
|
return v;
|
|
2062
2063
|
});
|
|
2064
|
+
return tagged.replace(/"\\u0000int:(-?\d+)"/g, "$1");
|
|
2063
2065
|
}
|
|
2064
2066
|
var JsonArrayConditions = class extends DBConditions {
|
|
2065
2067
|
_dialect;
|
|
@@ -3426,8 +3428,8 @@ function sqlTypeToMaterializeClass(sqlType) {
|
|
|
3426
3428
|
return "passthrough";
|
|
3427
3429
|
}
|
|
3428
3430
|
switch (t) {
|
|
3429
|
-
//
|
|
3430
|
-
//
|
|
3431
|
+
// Integer family. The PostgreSQL SERIAL types are the same integers under an auto-increment
|
|
3432
|
+
// default (SERIAL/SERIAL4=int4, SMALLSERIAL/SERIAL2=int2, BIGSERIAL/SERIAL8=int8).
|
|
3431
3433
|
case "INTEGER":
|
|
3432
3434
|
case "INT":
|
|
3433
3435
|
case "SMALLINT":
|
|
@@ -3439,13 +3441,11 @@ function sqlTypeToMaterializeClass(sqlType) {
|
|
|
3439
3441
|
case "SERIAL4":
|
|
3440
3442
|
case "SMALLSERIAL":
|
|
3441
3443
|
case "SERIAL2":
|
|
3442
|
-
return "int32";
|
|
3443
|
-
// 64-bit int: needs JS bigint for exactness.
|
|
3444
3444
|
case "BIGINT":
|
|
3445
3445
|
case "INT8":
|
|
3446
3446
|
case "BIGSERIAL":
|
|
3447
3447
|
case "SERIAL8":
|
|
3448
|
-
return "
|
|
3448
|
+
return "int";
|
|
3449
3449
|
case "BOOLEAN":
|
|
3450
3450
|
case "BOOL":
|
|
3451
3451
|
return "bool";
|
|
@@ -3482,44 +3482,45 @@ function sqlTypeToMaterializeClass(sqlType) {
|
|
|
3482
3482
|
}
|
|
3483
3483
|
function keyArrayElemScalar(sqlType) {
|
|
3484
3484
|
switch (sqlTypeToMaterializeClass(sqlType)) {
|
|
3485
|
-
case "
|
|
3486
|
-
return "
|
|
3487
|
-
// materializes to a JS
|
|
3488
|
-
case "int64":
|
|
3485
|
+
case "int":
|
|
3486
|
+
return "int";
|
|
3487
|
+
// materializes to a JS bigint → bc int
|
|
3489
3488
|
case "date":
|
|
3490
3489
|
return "string";
|
|
3491
|
-
// materializes to a
|
|
3490
|
+
// materializes to a TZ string → bc string
|
|
3492
3491
|
case "bool":
|
|
3493
3492
|
return "bool";
|
|
3494
3493
|
case "passthrough":
|
|
3495
3494
|
return sqlTypeToBcScalar(sqlType) === "float" ? "float" : "string";
|
|
3496
3495
|
}
|
|
3497
3496
|
}
|
|
3497
|
+
var I64_MIN = -(2n ** 63n);
|
|
3498
|
+
var I64_MAX = 2n ** 63n - 1n;
|
|
3499
|
+
function checkI64(v) {
|
|
3500
|
+
if (v < I64_MIN || v > I64_MAX) {
|
|
3501
|
+
throw new Error(`materialize int: ${v} is outside the i64 range behavior-contracts' \`int\` admits`);
|
|
3502
|
+
}
|
|
3503
|
+
return v;
|
|
3504
|
+
}
|
|
3498
3505
|
function materializeCell(value, klass) {
|
|
3499
3506
|
if (value === null || value === void 0) return value;
|
|
3500
3507
|
switch (klass) {
|
|
3501
|
-
case "
|
|
3502
|
-
if (typeof value === "bigint") return value
|
|
3508
|
+
case "int": {
|
|
3509
|
+
if (typeof value === "bigint") return checkI64(value);
|
|
3503
3510
|
if (typeof value === "string") {
|
|
3504
|
-
if (!/^-?\d+$/.test(value)) throw new Error(`materialize
|
|
3505
|
-
return value;
|
|
3511
|
+
if (!/^-?\d+$/.test(value)) throw new Error(`materialize int: driver returned a non-integer string '${value}'`);
|
|
3512
|
+
return checkI64(BigInt(value));
|
|
3506
3513
|
}
|
|
3507
3514
|
if (typeof value === "number") {
|
|
3508
|
-
if (!Number.isInteger(value)) throw new Error(`materialize
|
|
3515
|
+
if (!Number.isInteger(value)) throw new Error(`materialize int: driver returned a non-integer number ${value} for an integer column`);
|
|
3509
3516
|
if (!Number.isSafeInteger(value)) {
|
|
3510
3517
|
throw new Error(
|
|
3511
|
-
`materialize
|
|
3518
|
+
`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).`
|
|
3512
3519
|
);
|
|
3513
3520
|
}
|
|
3514
|
-
return value
|
|
3521
|
+
return BigInt(value);
|
|
3515
3522
|
}
|
|
3516
|
-
throw new Error(`materialize
|
|
3517
|
-
}
|
|
3518
|
-
case "int32": {
|
|
3519
|
-
if (typeof value === "number") return value;
|
|
3520
|
-
if (typeof value === "bigint") return Number(value);
|
|
3521
|
-
if (typeof value === "string" && /^-?\d+$/.test(value)) return Number(value);
|
|
3522
|
-
throw new Error(`materialize int32: unexpected driver JS type ${typeof value} (${String(value)})`);
|
|
3523
|
+
throw new Error(`materialize int: unexpected driver JS type ${typeof value}`);
|
|
3523
3524
|
}
|
|
3524
3525
|
case "date": {
|
|
3525
3526
|
if (typeof value === "string") return value;
|
|
@@ -5008,8 +5009,7 @@ function onConflictTail(dialect, ports, cols) {
|
|
|
5008
5009
|
}
|
|
5009
5010
|
function pgTypeSpecimen(sqlType) {
|
|
5010
5011
|
const klass = sqlTypeToMaterializeClass(sqlType);
|
|
5011
|
-
if (klass === "
|
|
5012
|
-
if (klass === "int64") return 0n;
|
|
5012
|
+
if (klass === "int") return 0n;
|
|
5013
5013
|
if (klass === "bool") return false;
|
|
5014
5014
|
if (klass === "date") return /* @__PURE__ */ new Date(0);
|
|
5015
5015
|
const scalar = sqlTypeToBcScalar(sqlType);
|
|
@@ -5601,10 +5601,6 @@ function materializeChildRows(rows, cols) {
|
|
|
5601
5601
|
row[key] = materializeCell(row[key], klass);
|
|
5602
5602
|
continue;
|
|
5603
5603
|
}
|
|
5604
|
-
if (typeof row[key] === "bigint") {
|
|
5605
|
-
const v = row[key];
|
|
5606
|
-
row[key] = v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(v) : v.toString();
|
|
5607
|
-
}
|
|
5608
5604
|
}
|
|
5609
5605
|
}
|
|
5610
5606
|
return rows;
|
|
@@ -5744,133 +5740,108 @@ function compileDeleteManyBundle(name, options, dialectName = "sqlite") {
|
|
|
5744
5740
|
var import_reflect_metadata = __toESM(require_Reflect());
|
|
5745
5741
|
var COLUMNS_KEY = /* @__PURE__ */ Symbol("litedbmodel:columns");
|
|
5746
5742
|
var RELATIONS_KEY = /* @__PURE__ */ Symbol("litedbmodel:relations");
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
return materializeCell(v, "date");
|
|
5765
|
-
},
|
|
5766
|
-
// Delegate to driver-specific serializeDatetime
|
|
5767
|
-
serialize: (val, typeCast) => {
|
|
5768
|
-
if (val === null || val === void 0) return null;
|
|
5769
|
-
if (val instanceof Date) {
|
|
5770
|
-
return typeCast?.serializeDatetime(val) ?? val;
|
|
5771
|
-
}
|
|
5772
|
-
return val;
|
|
5773
|
-
},
|
|
5774
|
-
sqlCast: "timestamp"
|
|
5775
|
-
};
|
|
5776
|
-
case Number:
|
|
5777
|
-
return {
|
|
5778
|
-
typeCast: (v) => {
|
|
5779
|
-
if (v === void 0) return void 0;
|
|
5780
|
-
if (v === null) return null;
|
|
5781
|
-
const n = Number(v);
|
|
5782
|
-
return isNaN(n) ? null : n;
|
|
5783
|
-
}
|
|
5784
|
-
};
|
|
5785
|
-
case BigInt:
|
|
5786
|
-
return {
|
|
5787
|
-
// v2 read contract: BIGINT/INT8 → EXACT decimal STRING (no i64 rounding, JSON-safe), via the
|
|
5788
|
-
// shared materializer. NOTE: the TS field type stays `bigint` in existing models for source
|
|
5789
|
-
// compat, but the VALUE is now the exact string — the whole point of the #9 realignment.
|
|
5790
|
-
typeCast: (v) => {
|
|
5791
|
-
if (v === void 0) return void 0;
|
|
5792
|
-
return materializeCell(v, "int64");
|
|
5793
|
-
},
|
|
5794
|
-
sqlCast: "bigint"
|
|
5795
|
-
};
|
|
5796
|
-
// Array, Object, String, and other types require explicit specification
|
|
5797
|
-
default:
|
|
5798
|
-
return void 0;
|
|
5799
|
-
}
|
|
5800
|
-
}
|
|
5801
|
-
function inferBaseSqlTypeFromDesignType(target, propertyKey) {
|
|
5802
|
-
const designType = Reflect.getMetadata("design:type", target, propertyKey);
|
|
5803
|
-
if (!designType) return void 0;
|
|
5804
|
-
switch (designType) {
|
|
5805
|
-
case String:
|
|
5806
|
-
return "TEXT";
|
|
5807
|
-
case Number:
|
|
5808
|
-
return "INTEGER";
|
|
5809
|
-
case Boolean:
|
|
5810
|
-
return "BOOLEAN";
|
|
5811
|
-
case Date:
|
|
5812
|
-
return "TIMESTAMP";
|
|
5813
|
-
case BigInt:
|
|
5814
|
-
return "BIGINT";
|
|
5815
|
-
default:
|
|
5816
|
-
return void 0;
|
|
5743
|
+
if (typeof Symbol === "function" && !Symbol.metadata) {
|
|
5744
|
+
Object.defineProperty(Symbol, "metadata", {
|
|
5745
|
+
value: /* @__PURE__ */ Symbol.for("Symbol.metadata"),
|
|
5746
|
+
writable: false,
|
|
5747
|
+
enumerable: false,
|
|
5748
|
+
configurable: true
|
|
5749
|
+
});
|
|
5750
|
+
}
|
|
5751
|
+
function isStandardContext(second) {
|
|
5752
|
+
return typeof second === "object" && second !== null && typeof second.kind === "string";
|
|
5753
|
+
}
|
|
5754
|
+
function classMetadataBag(context, propertyKey) {
|
|
5755
|
+
const bag = context.metadata;
|
|
5756
|
+
if (bag === void 0) {
|
|
5757
|
+
throw new Error(
|
|
5758
|
+
`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.`
|
|
5759
|
+
);
|
|
5817
5760
|
}
|
|
5761
|
+
return bag;
|
|
5818
5762
|
}
|
|
5819
|
-
function
|
|
5820
|
-
const
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
if (!finalSqlCast) finalSqlCast = inferred.sqlCast;
|
|
5831
|
-
}
|
|
5763
|
+
function legacyColumnMap(constructor) {
|
|
5764
|
+
const own = Reflect.getOwnMetadata(COLUMNS_KEY, constructor);
|
|
5765
|
+
if (own !== void 0) return own;
|
|
5766
|
+
const inherited = Reflect.getMetadata(COLUMNS_KEY, constructor);
|
|
5767
|
+
const map = new Map(inherited);
|
|
5768
|
+
Reflect.defineMetadata(COLUMNS_KEY, map, constructor);
|
|
5769
|
+
return map;
|
|
5770
|
+
}
|
|
5771
|
+
function standardColumnMap(bag) {
|
|
5772
|
+
if (!Object.prototype.hasOwnProperty.call(bag, COLUMNS_KEY)) {
|
|
5773
|
+
bag[COLUMNS_KEY] = new Map(bag[COLUMNS_KEY]);
|
|
5832
5774
|
}
|
|
5833
|
-
|
|
5775
|
+
return bag[COLUMNS_KEY];
|
|
5776
|
+
}
|
|
5777
|
+
function registerColumn(columns, propertyKey, options) {
|
|
5834
5778
|
columns.set(propertyKey, {
|
|
5835
5779
|
columnName: options.columnName,
|
|
5836
|
-
typeCast:
|
|
5837
|
-
serialize:
|
|
5780
|
+
typeCast: options.typeCast,
|
|
5781
|
+
serialize: options.serialize,
|
|
5838
5782
|
primaryKey: options.primaryKey,
|
|
5839
5783
|
autoIncrement: options.autoIncrement,
|
|
5840
|
-
sqlCast:
|
|
5841
|
-
...baseSqlType !== void 0 ? { baseSqlType } : {}
|
|
5784
|
+
sqlCast: options.sqlCast,
|
|
5785
|
+
...options.baseSqlType !== void 0 ? { baseSqlType: options.baseSqlType } : {}
|
|
5842
5786
|
});
|
|
5843
|
-
Reflect.defineMetadata(COLUMNS_KEY, columns, constructor);
|
|
5844
5787
|
}
|
|
5845
|
-
function
|
|
5788
|
+
function parseColumnOptions(columnNameOrOptions, propKey) {
|
|
5789
|
+
if (typeof columnNameOrOptions === "string") return { columnName: columnNameOrOptions };
|
|
5790
|
+
if (columnNameOrOptions) {
|
|
5791
|
+
return {
|
|
5792
|
+
columnName: columnNameOrOptions.columnName || propKey,
|
|
5793
|
+
primaryKey: columnNameOrOptions.primaryKey,
|
|
5794
|
+
autoIncrement: columnNameOrOptions.autoIncrement
|
|
5795
|
+
};
|
|
5796
|
+
}
|
|
5797
|
+
return { columnName: propKey };
|
|
5798
|
+
}
|
|
5799
|
+
function rejectNonText(family, val) {
|
|
5800
|
+
if (val === null || val === void 0) return null;
|
|
5801
|
+
if (val instanceof Date) {
|
|
5802
|
+
throw new Error(
|
|
5803
|
+
`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.`
|
|
5804
|
+
);
|
|
5805
|
+
}
|
|
5806
|
+
if (typeof val === "object") {
|
|
5807
|
+
throw new Error(
|
|
5808
|
+
`litedbmodel: @column.${family}() received an object. Use @column.json<T>() for a JSON column, or @column.custom() with a serializer.`
|
|
5809
|
+
);
|
|
5810
|
+
}
|
|
5811
|
+
return val;
|
|
5812
|
+
}
|
|
5813
|
+
function createColumnDecorator(typeCast, serialize, sqlCast, baseSqlType) {
|
|
5846
5814
|
return function(columnNameOrOptions) {
|
|
5847
|
-
return function(
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
} else {
|
|
5860
|
-
columnName = propKey;
|
|
5815
|
+
return function(targetOrValue, keyOrContext) {
|
|
5816
|
+
if (isStandardContext(keyOrContext)) {
|
|
5817
|
+
const propKey2 = String(keyOrContext.name);
|
|
5818
|
+
const parsed2 = parseColumnOptions(columnNameOrOptions, propKey2);
|
|
5819
|
+
registerColumn(standardColumnMap(classMetadataBag(keyOrContext, propKey2)), propKey2, {
|
|
5820
|
+
...parsed2,
|
|
5821
|
+
typeCast,
|
|
5822
|
+
serialize,
|
|
5823
|
+
sqlCast,
|
|
5824
|
+
baseSqlType
|
|
5825
|
+
});
|
|
5826
|
+
return;
|
|
5861
5827
|
}
|
|
5862
|
-
|
|
5863
|
-
|
|
5828
|
+
const propKey = String(keyOrContext);
|
|
5829
|
+
const parsed = parseColumnOptions(columnNameOrOptions, propKey);
|
|
5830
|
+
registerColumn(legacyColumnMap(targetOrValue.constructor), propKey, {
|
|
5831
|
+
...parsed,
|
|
5864
5832
|
typeCast,
|
|
5865
5833
|
serialize,
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
autoIncrement,
|
|
5869
|
-
sqlCast
|
|
5834
|
+
sqlCast,
|
|
5835
|
+
baseSqlType
|
|
5870
5836
|
});
|
|
5871
5837
|
};
|
|
5872
5838
|
};
|
|
5873
5839
|
}
|
|
5840
|
+
function requireColumnFamily() {
|
|
5841
|
+
throw new Error(
|
|
5842
|
+
"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."
|
|
5843
|
+
);
|
|
5844
|
+
}
|
|
5874
5845
|
function serializeArray(val, typeCast) {
|
|
5875
5846
|
if (val === null || val === void 0) return null;
|
|
5876
5847
|
if (!Array.isArray(val)) return val;
|
|
@@ -5908,19 +5879,44 @@ function serializeJson(val, typeCast) {
|
|
|
5908
5879
|
return JSON.stringify(val);
|
|
5909
5880
|
}
|
|
5910
5881
|
var column = Object.assign(
|
|
5911
|
-
//
|
|
5912
|
-
|
|
5882
|
+
// The bare `@column()` declared no type — it is rejected, with the migration in the message.
|
|
5883
|
+
(_columnNameOrOptions) => requireColumnFamily(),
|
|
5913
5884
|
{
|
|
5914
5885
|
// ============================================
|
|
5915
5886
|
// Primitive Types
|
|
5916
5887
|
// ============================================
|
|
5888
|
+
/**
|
|
5889
|
+
* Text type (TEXT / VARCHAR / CHAR / ENUM / citext) — the driver value is already a string, so no
|
|
5890
|
+
* cast is applied. The family still DECLARES the column so the typed read types it as `TEXT`.
|
|
5891
|
+
* @example @column.text() name?: string;
|
|
5892
|
+
* @example @column.text('user_name') name?: string;
|
|
5893
|
+
*/
|
|
5894
|
+
text: (columnNameOrOptions) => createColumnDecorator(
|
|
5895
|
+
// The family DECLARES `string`, so it must hand back one. Most drivers already do, but SQLite
|
|
5896
|
+
// is dynamically typed: it returns a JS number for a `NUMERIC`/`DECIMAL` column whatever the
|
|
5897
|
+
// declaration says, and the declared type would be a lie on that dialect alone.
|
|
5898
|
+
(v) => {
|
|
5899
|
+
if (v === void 0 || v === null) return v;
|
|
5900
|
+
if (typeof v === "string") return v;
|
|
5901
|
+
if (typeof v === "number" || typeof v === "bigint" || typeof v === "boolean") return String(v);
|
|
5902
|
+
throw new Error(
|
|
5903
|
+
`materialize text: driver returned ${typeof v} for a text column. Use @column.passthrough() for a BYTEA/BLOB column, or @column.json<T>() for JSON.`
|
|
5904
|
+
);
|
|
5905
|
+
},
|
|
5906
|
+
(val) => rejectNonText("text", val),
|
|
5907
|
+
// …and it cannot SERIALIZE a Date or an object
|
|
5908
|
+
void 0,
|
|
5909
|
+
// no sqlCast family (a text literal needs no SQL cast)
|
|
5910
|
+
"TEXT"
|
|
5911
|
+
// §4.1 token: types the SCP typed read
|
|
5912
|
+
)(columnNameOrOptions),
|
|
5917
5913
|
/**
|
|
5918
5914
|
* Boolean type conversion
|
|
5919
5915
|
* Converts 't'/'f', 'true'/'false', 1/0 to boolean
|
|
5920
5916
|
* Preserves null for nullable columns, undefined stays undefined
|
|
5921
5917
|
* @example @column.boolean() is_active?: boolean;
|
|
5922
5918
|
*/
|
|
5923
|
-
boolean: (
|
|
5919
|
+
boolean: (columnNameOrOptions) => createColumnDecorator(
|
|
5924
5920
|
// v2 read contract: BOOLEAN → boolean, via the shared materializer (issue #9).
|
|
5925
5921
|
(v) => {
|
|
5926
5922
|
if (v === void 0) return void 0;
|
|
@@ -5928,42 +5924,38 @@ var column = Object.assign(
|
|
|
5928
5924
|
},
|
|
5929
5925
|
void 0,
|
|
5930
5926
|
// no custom serialize
|
|
5931
|
-
false,
|
|
5932
|
-
// allow auto-inference
|
|
5933
5927
|
"boolean"
|
|
5934
5928
|
// sqlCast for updateMany type inference
|
|
5935
|
-
)(
|
|
5929
|
+
)(columnNameOrOptions),
|
|
5936
5930
|
/**
|
|
5937
5931
|
* Number type conversion (from string)
|
|
5938
5932
|
* Preserves null for nullable columns, undefined stays undefined
|
|
5939
5933
|
* @example @column.number() amount?: number;
|
|
5940
5934
|
*/
|
|
5941
|
-
number: (
|
|
5935
|
+
number: (columnNameOrOptions) => createColumnDecorator((v) => {
|
|
5942
5936
|
if (v === void 0) return void 0;
|
|
5943
5937
|
if (v === null) return null;
|
|
5944
5938
|
const n = Number(v);
|
|
5945
5939
|
return isNaN(n) ? null : n;
|
|
5946
|
-
})(
|
|
5940
|
+
})(columnNameOrOptions),
|
|
5947
5941
|
/**
|
|
5948
5942
|
* BigInt type conversion
|
|
5949
5943
|
* Preserves null for nullable columns, undefined stays undefined
|
|
5950
|
-
* @example @column.bigint() large_id?: bigint;
|
|
5944
|
+
* @example @column.bigint() large_id?: bigint; // bc `int` — a JS bigint, checked i64
|
|
5951
5945
|
*/
|
|
5952
|
-
bigint: (
|
|
5953
|
-
//
|
|
5954
|
-
//
|
|
5955
|
-
//
|
|
5946
|
+
bigint: (columnNameOrOptions) => createColumnDecorator(
|
|
5947
|
+
// An integer column reads back as a JS `bigint` — behavior-contracts' `int` value model
|
|
5948
|
+
// (`int` = bigint, checked i64), which is what the drivers already hand over. `JSON.stringify`
|
|
5949
|
+
// does not serialize a bigint: give the field a `toJSON`, or convert at the boundary.
|
|
5956
5950
|
(v) => {
|
|
5957
5951
|
if (v === void 0) return void 0;
|
|
5958
|
-
return materializeCell(v, "
|
|
5952
|
+
return materializeCell(v, "int");
|
|
5959
5953
|
},
|
|
5960
5954
|
void 0,
|
|
5961
5955
|
// no custom serialize
|
|
5962
|
-
false,
|
|
5963
|
-
// allow auto-inference
|
|
5964
5956
|
"bigint"
|
|
5965
5957
|
// sqlCast for WHERE/INSERT type casting
|
|
5966
|
-
)(
|
|
5958
|
+
)(columnNameOrOptions),
|
|
5967
5959
|
// ============================================
|
|
5968
5960
|
// Date/Time Types
|
|
5969
5961
|
// ============================================
|
|
@@ -5975,9 +5967,9 @@ var column = Object.assign(
|
|
|
5975
5967
|
* - PostgreSQL: Serializes to ISO 8601 UTC string with 'Z' suffix for explicit timezone
|
|
5976
5968
|
* - MySQL/SQLite: Passes Date object to driver (driver-dependent timezone handling)
|
|
5977
5969
|
*
|
|
5978
|
-
* @example @column.datetime() created_at?: Date
|
|
5970
|
+
* @example @column.datetime() created_at?: string; // TZ-attached string, NOT a JS Date
|
|
5979
5971
|
*/
|
|
5980
|
-
datetime: (
|
|
5972
|
+
datetime: (columnNameOrOptions) => createColumnDecorator(
|
|
5981
5973
|
// v2 read contract: DATE/TIMESTAMP/TIMESTAMPTZ/DATETIME/TIME → TZ-attached STRING (NOT a
|
|
5982
5974
|
// TZ-shifted JS Date), via the shared materializer (issue #9). A driver already returning the
|
|
5983
5975
|
// native textual form passes through; a JS Date is rendered to its lossless ISO instant.
|
|
@@ -5993,11 +5985,9 @@ var column = Object.assign(
|
|
|
5993
5985
|
}
|
|
5994
5986
|
return val;
|
|
5995
5987
|
},
|
|
5996
|
-
false,
|
|
5997
|
-
// allow auto-inference
|
|
5998
5988
|
"timestamp"
|
|
5999
5989
|
// sqlCast for updateMany type inference
|
|
6000
|
-
)(
|
|
5990
|
+
)(columnNameOrOptions),
|
|
6001
5991
|
/**
|
|
6002
5992
|
* Date type conversion — returns YYYY-MM-DD string.
|
|
6003
5993
|
* Preserves null for nullable columns, undefined stays undefined.
|
|
@@ -6005,9 +5995,9 @@ var column = Object.assign(
|
|
|
6005
5995
|
* DB values (Date object or string) are normalized to 'YYYY-MM-DD' string.
|
|
6006
5996
|
* On write, string values are passed through; Date objects are formatted as 'YYYY-MM-DD'.
|
|
6007
5997
|
*
|
|
6008
|
-
* @example @column.date() birth_date?: string;
|
|
5998
|
+
* @example @column.date() birth_date?: string; // 'YYYY-MM-DD'
|
|
6009
5999
|
*/
|
|
6010
|
-
date: (
|
|
6000
|
+
date: (columnNameOrOptions) => createColumnDecorator(
|
|
6011
6001
|
(v) => {
|
|
6012
6002
|
if (v === void 0) return void 0;
|
|
6013
6003
|
if (v === null) return null;
|
|
@@ -6032,11 +6022,9 @@ var column = Object.assign(
|
|
|
6032
6022
|
}
|
|
6033
6023
|
return val;
|
|
6034
6024
|
},
|
|
6035
|
-
false,
|
|
6036
|
-
// allow auto-inference
|
|
6037
6025
|
"date"
|
|
6038
6026
|
// sqlCast for updateMany type inference
|
|
6039
|
-
)(
|
|
6027
|
+
)(columnNameOrOptions),
|
|
6040
6028
|
// ============================================
|
|
6041
6029
|
// Array Types
|
|
6042
6030
|
// ============================================
|
|
@@ -6045,71 +6033,71 @@ var column = Object.assign(
|
|
|
6045
6033
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6046
6034
|
* @example @column.stringArray() tags?: string[];
|
|
6047
6035
|
*/
|
|
6048
|
-
stringArray: (
|
|
6036
|
+
stringArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6049
6037
|
(v) => {
|
|
6050
6038
|
if (v === void 0) return void 0;
|
|
6051
6039
|
if (v === null) return null;
|
|
6052
6040
|
return castToStringArray(v);
|
|
6053
6041
|
},
|
|
6054
6042
|
serializeArray,
|
|
6055
|
-
false,
|
|
6056
6043
|
"text[]"
|
|
6057
|
-
)(
|
|
6044
|
+
)(columnNameOrOptions),
|
|
6058
6045
|
/**
|
|
6059
6046
|
* Integer array type conversion (integer[])
|
|
6060
6047
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6061
6048
|
* @example @column.intArray() scores?: number[];
|
|
6062
6049
|
*/
|
|
6063
|
-
intArray: (
|
|
6050
|
+
intArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6064
6051
|
(v) => {
|
|
6065
6052
|
if (v === void 0) return void 0;
|
|
6066
6053
|
if (v === null) return null;
|
|
6067
6054
|
return castToIntegerArray(v);
|
|
6068
6055
|
},
|
|
6069
6056
|
serializeArray,
|
|
6070
|
-
false,
|
|
6071
6057
|
"int[]"
|
|
6072
|
-
)(
|
|
6058
|
+
)(columnNameOrOptions),
|
|
6073
6059
|
/**
|
|
6074
6060
|
* Numeric array type conversion (numeric[], allows null elements)
|
|
6075
6061
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6076
6062
|
* @example @column.numericArray() values?: (number | null)[];
|
|
6077
6063
|
*/
|
|
6078
|
-
numericArray: (
|
|
6064
|
+
numericArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6079
6065
|
(v) => {
|
|
6080
6066
|
if (v === void 0) return void 0;
|
|
6081
6067
|
if (v === null) return null;
|
|
6082
6068
|
return castToNumericArray(v);
|
|
6083
6069
|
},
|
|
6084
6070
|
serializeArray,
|
|
6085
|
-
false,
|
|
6086
6071
|
"numeric[]"
|
|
6087
|
-
)(
|
|
6072
|
+
)(columnNameOrOptions),
|
|
6088
6073
|
/**
|
|
6089
6074
|
* Boolean array type conversion (boolean[])
|
|
6090
6075
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6091
6076
|
* @example @column.booleanArray() flags?: (boolean | null)[];
|
|
6092
6077
|
*/
|
|
6093
|
-
booleanArray: (
|
|
6078
|
+
booleanArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6094
6079
|
(v) => {
|
|
6095
6080
|
if (v === void 0) return void 0;
|
|
6096
6081
|
if (v === null) return null;
|
|
6097
6082
|
return castToBooleanArray(v);
|
|
6098
6083
|
},
|
|
6099
6084
|
serializeBooleanArray,
|
|
6100
|
-
false,
|
|
6101
6085
|
"boolean[]"
|
|
6102
|
-
)(
|
|
6086
|
+
)(columnNameOrOptions),
|
|
6103
6087
|
/**
|
|
6104
6088
|
* DateTime array type conversion (timestamp[])
|
|
6105
6089
|
* Preserves null for nullable columns, undefined stays undefined
|
|
6106
|
-
* @example @column.datetimeArray() event_dates?: (
|
|
6090
|
+
* @example @column.datetimeArray() event_dates?: (string | null)[];
|
|
6107
6091
|
*/
|
|
6108
|
-
datetimeArray: (
|
|
6092
|
+
datetimeArray: (columnNameOrOptions) => createColumnDecorator(
|
|
6093
|
+
// Element-wise the SAME contract as `@column.datetime()`: a TZ-attached STRING, never a
|
|
6094
|
+
// TZ-shifted JS Date. The array family used to be the one place a `Date` still came back, so
|
|
6095
|
+
// `JSON.stringify` of a row silently re-rendered those elements in UTC — the exact hazard #9
|
|
6096
|
+
// closed for the scalar.
|
|
6109
6097
|
(v) => {
|
|
6110
6098
|
if (v === void 0) return void 0;
|
|
6111
6099
|
if (v === null) return null;
|
|
6112
|
-
return castToDatetimeArray(v);
|
|
6100
|
+
return castToDatetimeArray(v).map((d) => d === null ? null : materializeCell(d, "date"));
|
|
6113
6101
|
},
|
|
6114
6102
|
// DateTime arrays serialize each Date to ISO string
|
|
6115
6103
|
(val) => {
|
|
@@ -6118,7 +6106,7 @@ var column = Object.assign(
|
|
|
6118
6106
|
const mapped = val.map((v) => v === null ? "NULL" : v instanceof Date ? v.toISOString() : String(v));
|
|
6119
6107
|
return `{${mapped.join(",")}}`;
|
|
6120
6108
|
}
|
|
6121
|
-
)(
|
|
6109
|
+
)(columnNameOrOptions),
|
|
6122
6110
|
// ============================================
|
|
6123
6111
|
// JSON Types
|
|
6124
6112
|
// ============================================
|
|
@@ -6128,16 +6116,15 @@ var column = Object.assign(
|
|
|
6128
6116
|
* @example @column.json() metadata?: Record<string, unknown>;
|
|
6129
6117
|
* @example @column.json<UserSettings>() settings?: UserSettings;
|
|
6130
6118
|
*/
|
|
6131
|
-
json: (
|
|
6119
|
+
json: (columnNameOrOptions) => createColumnDecorator(
|
|
6132
6120
|
(v) => {
|
|
6133
6121
|
if (v === void 0) return void 0;
|
|
6134
6122
|
if (v === null) return null;
|
|
6135
6123
|
return castToJson(v);
|
|
6136
6124
|
},
|
|
6137
6125
|
serializeJson,
|
|
6138
|
-
false,
|
|
6139
6126
|
"jsonb"
|
|
6140
|
-
)(
|
|
6127
|
+
)(columnNameOrOptions),
|
|
6141
6128
|
// ============================================
|
|
6142
6129
|
// UUID Type (PostgreSQL)
|
|
6143
6130
|
// ============================================
|
|
@@ -6166,22 +6153,28 @@ var column = Object.assign(
|
|
|
6166
6153
|
if (v === null) return null;
|
|
6167
6154
|
return String(v);
|
|
6168
6155
|
},
|
|
6169
|
-
|
|
6170
|
-
//
|
|
6171
|
-
true,
|
|
6172
|
-
// Skip auto-inference
|
|
6156
|
+
(val) => rejectNonText("uuid", val),
|
|
6157
|
+
// the ::uuid cast handles the rest
|
|
6173
6158
|
"uuid"
|
|
6174
6159
|
// SQL type for casting
|
|
6175
6160
|
)(columnNameOrOptions),
|
|
6176
6161
|
// ============================================
|
|
6177
6162
|
// Custom Type Conversion
|
|
6178
6163
|
// ============================================
|
|
6164
|
+
/**
|
|
6165
|
+
* The driver's value, UNCAST — for a column whose type the library has no cast for (`BYTEA` /
|
|
6166
|
+
* `BLOB` arrives as a driver Buffer, a vendor type as whatever the driver decodes). It states
|
|
6167
|
+
* "this column is passed through", which is a DECLARATION; the removed bare `@column()` was the
|
|
6168
|
+
* absence of one, and produced this same passthrough by accident for every unresolvable type.
|
|
6169
|
+
* @example @column.passthrough() payload?: unknown;
|
|
6170
|
+
*/
|
|
6171
|
+
passthrough: (columnNameOrOptions) => createColumnDecorator()(columnNameOrOptions),
|
|
6179
6172
|
/**
|
|
6180
6173
|
* Custom type conversion with user-provided function
|
|
6181
6174
|
* @example @column.custom((v) => String(v).toUpperCase()) status?: string;
|
|
6182
6175
|
* @example @column.custom((v) => v, (v) => JSON.stringify(v)) data?: MyType; // with serializer
|
|
6183
6176
|
*/
|
|
6184
|
-
custom: (castFn, serializeFn,
|
|
6177
|
+
custom: (castFn, serializeFn, columnNameOrOptions) => createColumnDecorator(castFn, serializeFn)(columnNameOrOptions)
|
|
6185
6178
|
}
|
|
6186
6179
|
);
|
|
6187
6180
|
function getRelationMeta(modelClass) {
|
|
@@ -122,6 +122,12 @@ export declare function encodeJsonArrayParam(dialect: Dialect, values: readonly
|
|
|
122
122
|
* the batch record sets in {@link import('./json-batch')} alike. Both bind values that came OFF a read, so
|
|
123
123
|
* both meet the same two cases (a bc `int` is a `BigInt`, which `JSON.stringify` refuses; a MySQL boolean
|
|
124
124
|
* must ride as 1/0), and a second bare `JSON.stringify` would silently diverge on either.
|
|
125
|
+
*
|
|
126
|
+
* A bc `int` is written as a JSON NUMBER TOKEN carrying every digit — `JSON.stringify` cannot emit one
|
|
127
|
+
* (it throws on a BigInt), and routing it through `Number` LOSES the value: an id past 2^53 was rounded
|
|
128
|
+
* inside the JSON text and the rounded id is what MySQL/SQLite stored, silently. JSON numbers are
|
|
129
|
+
* arbitrary-precision by grammar, and both `JSON_TABLE` (MySQL) and `json_each` (SQLite) read an
|
|
130
|
+
* integer literal within i64 exactly — which is the whole range bc's `int` admits.
|
|
125
131
|
*/
|
|
126
132
|
export declare function encodeJsonParam(dialect: Dialect, payload: unknown): string;
|
|
127
133
|
/**
|