nicot 1.4.2 → 1.4.4
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-CN.md +4 -3
- package/README.md +5 -4
- package/dist/index.cjs +63 -16
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +62 -16
- package/dist/index.mjs.map +3 -3
- package/dist/src/decorators/property.d.ts +2 -0
- package/dist/src/decorators/query.d.ts +12 -7
- package/dist/src/utility/base64-binary.d.ts +11 -5
- package/package.json +1 -1
package/README-CN.md
CHANGED
|
@@ -207,8 +207,9 @@ OpenAPI 层面统统“伪装成”一个普通的 base64 `string` 字段:
|
|
|
207
207
|
|
|
208
208
|
- 实体属性类型是 `string`(base64 字符串)。
|
|
209
209
|
- OpenAPI 中以 `{ type: String, format: 'byte' }` 展示。
|
|
210
|
-
- 通过 TypeORM `ValueTransformer`:写库时把 base64 字符串解码成
|
|
211
|
-
|
|
210
|
+
- 通过 TypeORM `ValueTransformer`:写库时把 base64 字符串解码成
|
|
211
|
+
PostgreSQL 安全的 bytea 参数(默认列类型 `bytea`),读取时再编码回
|
|
212
|
+
base64 字符串。
|
|
212
213
|
|
|
213
214
|
```ts
|
|
214
215
|
@Entity()
|
|
@@ -229,7 +230,7 @@ export class Attachment extends IdBase() {
|
|
|
229
230
|
**查询。** base64 二进制列本身就是可查询字段(不需要 `GetMutator`)。想在
|
|
230
231
|
`findAll` 中按它过滤,给它挂上 `@QueryBase64Equal()`(或
|
|
231
232
|
`@QueryBase64NotEqual()`)即可:传入的 base64 查询串会在绑定参数前被解码成
|
|
232
|
-
|
|
233
|
+
PostgreSQL 安全的 bytea 参数,从而与列里存的二进制匹配。
|
|
233
234
|
|
|
234
235
|
```ts
|
|
235
236
|
@Base64BinaryColumn()
|
package/README.md
CHANGED
|
@@ -309,8 +309,9 @@ entity / DTO / OpenAPI surface all behave like a plain **base64 `string`**:
|
|
|
309
309
|
|
|
310
310
|
- The TS property type is `string` (a base64 string).
|
|
311
311
|
- It is exposed to OpenAPI as `{ type: String, format: 'byte' }`.
|
|
312
|
-
- A TypeORM `ValueTransformer` decodes the base64 string into a
|
|
313
|
-
way into the DB (`bytea` by default) and encodes it
|
|
312
|
+
- A TypeORM `ValueTransformer` decodes the base64 string into a PostgreSQL-safe
|
|
313
|
+
bytea parameter on the way into the DB (`bytea` by default) and encodes it
|
|
314
|
+
back to base64 on read.
|
|
314
315
|
|
|
315
316
|
```ts
|
|
316
317
|
@Entity()
|
|
@@ -333,8 +334,8 @@ API.
|
|
|
333
334
|
**Querying.** A base64 binary column is a normal queryable field (no
|
|
334
335
|
`GetMutator` required). To filter on it in `findAll`, attach
|
|
335
336
|
`@QueryBase64Equal()` (or `@QueryBase64NotEqual()`); the incoming base64 query
|
|
336
|
-
string is decoded to a
|
|
337
|
-
binary stored in the column:
|
|
337
|
+
string is decoded to a PostgreSQL-safe bytea parameter right before it is bound,
|
|
338
|
+
so it matches the binary stored in the column:
|
|
338
339
|
|
|
339
340
|
```ts
|
|
340
341
|
@Base64BinaryColumn()
|
package/dist/index.cjs
CHANGED
|
@@ -665,7 +665,10 @@ __export(index_exports, {
|
|
|
665
665
|
applyQueryPropertyLike: () => applyQueryPropertyLike,
|
|
666
666
|
applyQueryPropertySearch: () => applyQueryPropertySearch,
|
|
667
667
|
applyQueryPropertyZeroNullable: () => applyQueryPropertyZeroNullable,
|
|
668
|
+
base64OrBinaryToBuffer: () => base64OrBinaryToBuffer,
|
|
669
|
+
base64OrBinaryToDatabaseValue: () => base64OrBinaryToDatabaseValue,
|
|
668
670
|
binaryToBuffer: () => binaryToBuffer,
|
|
671
|
+
binaryToPostgresByteaHex: () => binaryToPostgresByteaHex,
|
|
669
672
|
createGetMutator: () => createGetMutator,
|
|
670
673
|
createQueryArrayify: () => createQueryArrayify,
|
|
671
674
|
createQueryBase64Operator: () => createQueryBase64Operator,
|
|
@@ -935,15 +938,31 @@ function binaryToBuffer(value) {
|
|
|
935
938
|
}
|
|
936
939
|
return Buffer.from(new Uint8Array(value));
|
|
937
940
|
}
|
|
941
|
+
function binaryToPostgresByteaHex(value) {
|
|
942
|
+
return `\\x${binaryToBuffer(value).toString("hex")}`;
|
|
943
|
+
}
|
|
944
|
+
function base64OrBinaryToBuffer(value) {
|
|
945
|
+
if (isBinaryLike(value)) {
|
|
946
|
+
return binaryToBuffer(value);
|
|
947
|
+
}
|
|
948
|
+
return Buffer.from(String(value), "base64");
|
|
949
|
+
}
|
|
950
|
+
function base64OrBinaryToDatabaseValue(value, storage = "postgres-bytea") {
|
|
951
|
+
const buffer = base64OrBinaryToBuffer(value);
|
|
952
|
+
if (storage === "postgres-bytea") {
|
|
953
|
+
return binaryToPostgresByteaHex(buffer);
|
|
954
|
+
}
|
|
955
|
+
return buffer;
|
|
956
|
+
}
|
|
938
957
|
var Base64BinaryTransformer = class {
|
|
958
|
+
constructor(storage = "postgres-bytea") {
|
|
959
|
+
this.storage = storage;
|
|
960
|
+
}
|
|
939
961
|
to(entValue) {
|
|
940
962
|
if (entValue == null) {
|
|
941
963
|
return entValue;
|
|
942
964
|
}
|
|
943
|
-
|
|
944
|
-
return binaryToBuffer(entValue);
|
|
945
|
-
}
|
|
946
|
-
return Buffer.from(String(entValue), "base64");
|
|
965
|
+
return base64OrBinaryToDatabaseValue(entValue, this.storage);
|
|
947
966
|
}
|
|
948
967
|
from(dbValue) {
|
|
949
968
|
if (dbValue == null) {
|
|
@@ -952,7 +971,11 @@ var Base64BinaryTransformer = class {
|
|
|
952
971
|
if (isBinaryLike(dbValue)) {
|
|
953
972
|
return binaryToBuffer(dbValue).toString("base64");
|
|
954
973
|
}
|
|
955
|
-
|
|
974
|
+
const text = String(dbValue);
|
|
975
|
+
if (/^\\x[0-9a-f]*$/i.test(text)) {
|
|
976
|
+
return Buffer.from(text.slice(2), "hex").toString("base64");
|
|
977
|
+
}
|
|
978
|
+
return Buffer.from(text).toString("base64");
|
|
956
979
|
}
|
|
957
980
|
};
|
|
958
981
|
|
|
@@ -1158,12 +1181,30 @@ var BoolColumn = (options = {}) => (0, import_nesties4.MergePropertyDecorators)(
|
|
|
1158
1181
|
swaggerDecorator(options, { type: Boolean }),
|
|
1159
1182
|
GetMutatorBool()
|
|
1160
1183
|
]);
|
|
1184
|
+
var jsonColumnValidators = (definition) => {
|
|
1185
|
+
const isArray = Array.isArray(definition);
|
|
1186
|
+
const cl = (0, import_nesties5.getClassFromClassOrArray)(definition);
|
|
1187
|
+
const validationOptions = isArray ? { each: true } : {};
|
|
1188
|
+
const decorators = isArray ? [(0, import_class_validator3.IsArray)()] : [];
|
|
1189
|
+
if (cl === String) {
|
|
1190
|
+
decorators.push((0, import_class_validator3.IsString)(validationOptions));
|
|
1191
|
+
} else if (cl === Number) {
|
|
1192
|
+
decorators.push((0, import_class_validator3.IsNumber)({}, validationOptions));
|
|
1193
|
+
} else if (cl === Boolean) {
|
|
1194
|
+
decorators.push((0, import_class_validator3.IsBoolean)(validationOptions));
|
|
1195
|
+
} else if (cl === Date) {
|
|
1196
|
+
decorators.push((0, import_class_validator3.IsDate)(validationOptions));
|
|
1197
|
+
} else {
|
|
1198
|
+
decorators.push((0, import_class_validator3.ValidateNested)(validationOptions));
|
|
1199
|
+
}
|
|
1200
|
+
return decorators;
|
|
1201
|
+
};
|
|
1161
1202
|
var createJsonColumnDef = (columnType = "jsonb", typeTransformerClass = TypeTransformer) => (definition, options = {}) => {
|
|
1162
1203
|
const cl = (0, import_nesties5.getClassFromClassOrArray)(definition);
|
|
1163
1204
|
return (0, import_nesties4.MergePropertyDecorators)([
|
|
1164
1205
|
RequireGetMutator(),
|
|
1165
1206
|
(0, import_class_transformer2.Type)(() => cl),
|
|
1166
|
-
(
|
|
1207
|
+
...jsonColumnValidators(definition),
|
|
1167
1208
|
(0, import_typeorm.Column)(options.columnType || columnType, {
|
|
1168
1209
|
...columnDecoratorOptions(options),
|
|
1169
1210
|
transformer: new typeTransformerClass(definition)
|
|
@@ -1195,7 +1236,9 @@ var Base64BinaryColumn = (options = {}) => (0, import_nesties4.MergePropertyDeco
|
|
|
1195
1236
|
(0, import_typeorm.Column)(options.columnType || "bytea", {
|
|
1196
1237
|
...columnDecoratorOptions(options),
|
|
1197
1238
|
default: void 0,
|
|
1198
|
-
transformer: new Base64BinaryTransformer(
|
|
1239
|
+
transformer: new Base64BinaryTransformer(
|
|
1240
|
+
options.binaryStorage ?? (options.columnType && options.columnType !== "bytea" ? "binary" : "postgres-bytea")
|
|
1241
|
+
)
|
|
1199
1242
|
}),
|
|
1200
1243
|
IsBase64OrBinary(),
|
|
1201
1244
|
validatorDecorator(options),
|
|
@@ -1424,19 +1467,20 @@ var createQueryOperatorArrayify = (operator, singleFallback) => createQueryArray
|
|
|
1424
1467
|
);
|
|
1425
1468
|
var QueryIn = createQueryOperatorArrayify("IN", "=");
|
|
1426
1469
|
var QueryNotIn = createQueryOperatorArrayify("NOT IN", "!=");
|
|
1427
|
-
var
|
|
1470
|
+
var normalizeQueryBase64Options = (fieldOrOptions) => typeof fieldOrOptions === "string" ? { field: fieldOrOptions } : fieldOrOptions ?? {};
|
|
1471
|
+
var toBase64QueryValue = (value, storage = "postgres-bytea") => {
|
|
1428
1472
|
if (value == null) {
|
|
1429
1473
|
return value;
|
|
1430
1474
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1475
|
+
return base64OrBinaryToDatabaseValue(value, storage);
|
|
1476
|
+
};
|
|
1477
|
+
var createQueryBase64Operator = (operator) => (fieldOrOptions) => {
|
|
1478
|
+
const options = normalizeQueryBase64Options(fieldOrOptions);
|
|
1479
|
+
return QueryWrap((entityExpr, varExpr, info) => {
|
|
1480
|
+
info.mutateValue(toBase64QueryValue(info.value, options.binaryStorage));
|
|
1481
|
+
return `${entityExpr} ${operator} ${varExpr}`;
|
|
1482
|
+
}, options.field);
|
|
1435
1483
|
};
|
|
1436
|
-
var createQueryBase64Operator = (operator) => (field) => QueryWrap((entityExpr, varExpr, info) => {
|
|
1437
|
-
info.mutateValue(toBase64QueryBuffer(info.value));
|
|
1438
|
-
return `${entityExpr} ${operator} ${varExpr}`;
|
|
1439
|
-
}, field);
|
|
1440
1484
|
var QueryBase64Equal = createQueryBase64Operator("=");
|
|
1441
1485
|
var QueryBase64NotEqual = createQueryBase64Operator("!=");
|
|
1442
1486
|
var QueryFullText = (options = {}) => {
|
|
@@ -4366,7 +4410,10 @@ TransactionalTypeOrmModule = __decorateClass([
|
|
|
4366
4410
|
applyQueryPropertyLike,
|
|
4367
4411
|
applyQueryPropertySearch,
|
|
4368
4412
|
applyQueryPropertyZeroNullable,
|
|
4413
|
+
base64OrBinaryToBuffer,
|
|
4414
|
+
base64OrBinaryToDatabaseValue,
|
|
4369
4415
|
binaryToBuffer,
|
|
4416
|
+
binaryToPostgresByteaHex,
|
|
4370
4417
|
createGetMutator,
|
|
4371
4418
|
createQueryArrayify,
|
|
4372
4419
|
createQueryBase64Operator,
|