@rvoh/dream 1.5.0 → 1.5.2

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.
Files changed (201) hide show
  1. package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +36 -0
  2. package/dist/cjs/src/decorators/field/sortable/helpers/setPosition.js +7 -1
  3. package/dist/cjs/src/dream/QueryDriver/Kysely.js +4 -4
  4. package/dist/cjs/src/dream/QueryDriver/helpers/kysely/runMigration.js +2 -1
  5. package/dist/cjs/src/helpers/sanitizeString.js +49 -0
  6. package/dist/cjs/src/index.js +3 -1
  7. package/dist/cjs/src/serializer/SerializerRenderer.js +7 -2
  8. package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +36 -0
  9. package/dist/esm/src/decorators/field/sortable/helpers/setPosition.js +7 -1
  10. package/dist/esm/src/dream/QueryDriver/Kysely.js +4 -4
  11. package/dist/esm/src/dream/QueryDriver/helpers/kysely/runMigration.js +2 -1
  12. package/dist/esm/src/helpers/sanitizeString.js +46 -0
  13. package/dist/esm/src/index.js +1 -0
  14. package/dist/esm/src/serializer/SerializerRenderer.js +7 -2
  15. package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +36 -0
  16. package/dist/types/src/helpers/sanitizeString.d.ts +2 -0
  17. package/dist/types/src/index.d.ts +1 -0
  18. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +6 -3
  19. package/dist/types/src/types/associations/shared.d.ts +1 -1
  20. package/dist/types/src/types/associations/shared.ts +4 -2
  21. package/dist/types/src/types/serializer.d.ts +9 -0
  22. package/dist/types/src/types/serializer.ts +10 -0
  23. package/docs/assets/navigation.js +1 -1
  24. package/docs/assets/search.js +1 -1
  25. package/docs/classes/Benchmark.html +2 -2
  26. package/docs/classes/CalendarDate.html +2 -2
  27. package/docs/classes/CheckConstraintViolation.html +3 -3
  28. package/docs/classes/CliFileWriter.html +2 -2
  29. package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
  30. package/docs/classes/DataTypeColumnTypeMismatch.html +3 -3
  31. package/docs/classes/Decorators.html +19 -19
  32. package/docs/classes/Dream.html +113 -113
  33. package/docs/classes/DreamApp.html +4 -4
  34. package/docs/classes/DreamBin.html +2 -2
  35. package/docs/classes/DreamCLI.html +4 -4
  36. package/docs/classes/DreamImporter.html +2 -2
  37. package/docs/classes/DreamLogos.html +2 -2
  38. package/docs/classes/DreamMigrationHelpers.html +19 -7
  39. package/docs/classes/DreamSerializerBuilder.html +17 -17
  40. package/docs/classes/DreamTransaction.html +2 -2
  41. package/docs/classes/Encrypt.html +2 -2
  42. package/docs/classes/Env.html +2 -2
  43. package/docs/classes/GlobalNameNotSet.html +3 -3
  44. package/docs/classes/KyselyQueryDriver.html +30 -30
  45. package/docs/classes/NonLoadedAssociation.html +3 -3
  46. package/docs/classes/NotNullViolation.html +3 -3
  47. package/docs/classes/ObjectSerializerBuilder.html +8 -8
  48. package/docs/classes/PostgresQueryDriver.html +31 -31
  49. package/docs/classes/Query.html +53 -53
  50. package/docs/classes/QueryDriverBase.html +29 -29
  51. package/docs/classes/Range.html +2 -2
  52. package/docs/classes/RecordNotFound.html +3 -3
  53. package/docs/classes/ValidationError.html +3 -3
  54. package/docs/functions/DreamSerializer.html +1 -1
  55. package/docs/functions/ObjectSerializer.html +1 -1
  56. package/docs/functions/ReplicaSafe.html +1 -1
  57. package/docs/functions/STI.html +1 -1
  58. package/docs/functions/SoftDelete.html +1 -1
  59. package/docs/functions/camelize.html +1 -1
  60. package/docs/functions/capitalize.html +1 -1
  61. package/docs/functions/cloneDeepSafe.html +1 -1
  62. package/docs/functions/closeAllDbConnections.html +1 -1
  63. package/docs/functions/compact.html +1 -1
  64. package/docs/functions/dreamDbConnections.html +1 -1
  65. package/docs/functions/dreamPath.html +1 -1
  66. package/docs/functions/expandStiClasses.html +1 -1
  67. package/docs/functions/generateDream.html +1 -1
  68. package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
  69. package/docs/functions/groupBy.html +1 -1
  70. package/docs/functions/hyphenize.html +1 -1
  71. package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
  72. package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
  73. package/docs/functions/intersection.html +1 -1
  74. package/docs/functions/isDreamSerializer.html +1 -1
  75. package/docs/functions/isEmpty.html +1 -1
  76. package/docs/functions/loadRepl.html +1 -1
  77. package/docs/functions/lookupClassByGlobalName.html +1 -1
  78. package/docs/functions/normalizeUnicode.html +1 -1
  79. package/docs/functions/pascalize.html +1 -1
  80. package/docs/functions/pgErrorType.html +1 -1
  81. package/docs/functions/range-1.html +1 -1
  82. package/docs/functions/relativeDreamPath.html +1 -1
  83. package/docs/functions/round.html +1 -1
  84. package/docs/functions/sanitizeString.html +1 -0
  85. package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
  86. package/docs/functions/sharedPathPrefix.html +1 -1
  87. package/docs/functions/snakeify.html +1 -1
  88. package/docs/functions/sort.html +1 -1
  89. package/docs/functions/sortBy.html +1 -1
  90. package/docs/functions/sortObjectByKey.html +1 -1
  91. package/docs/functions/sortObjectByValue.html +1 -1
  92. package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
  93. package/docs/functions/uncapitalize.html +1 -1
  94. package/docs/functions/uniq.html +1 -1
  95. package/docs/functions/untypedDb.html +1 -1
  96. package/docs/functions/validateColumn.html +1 -1
  97. package/docs/functions/validateTable.html +1 -1
  98. package/docs/interfaces/BelongsToStatement.html +2 -2
  99. package/docs/interfaces/DecoratorContext.html +2 -2
  100. package/docs/interfaces/DreamAppInitOptions.html +2 -2
  101. package/docs/interfaces/DreamAppOpts.html +2 -2
  102. package/docs/interfaces/EncryptOptions.html +2 -2
  103. package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
  104. package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
  105. package/docs/interfaces/OpenapiDescription.html +2 -2
  106. package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
  107. package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
  108. package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
  109. package/docs/interfaces/SerializerRendererOpts.html +2 -2
  110. package/docs/modules.html +1 -0
  111. package/docs/types/Camelized.html +1 -1
  112. package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
  113. package/docs/types/DateTime.html +1 -1
  114. package/docs/types/DbConnectionType.html +1 -1
  115. package/docs/types/DbTypes.html +1 -1
  116. package/docs/types/DreamAppAllowedPackageManagersEnum.html +1 -1
  117. package/docs/types/DreamAssociationMetadata.html +1 -1
  118. package/docs/types/DreamAttributes.html +1 -1
  119. package/docs/types/DreamClassAssociationAndStatement.html +1 -1
  120. package/docs/types/DreamClassColumn.html +1 -1
  121. package/docs/types/DreamColumn.html +1 -1
  122. package/docs/types/DreamColumnNames.html +1 -1
  123. package/docs/types/DreamLogLevel.html +1 -1
  124. package/docs/types/DreamLogger.html +1 -1
  125. package/docs/types/DreamModelSerializerType.html +1 -1
  126. package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
  127. package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
  128. package/docs/types/DreamParamSafeAttributes.html +1 -1
  129. package/docs/types/DreamParamSafeColumnNames.html +1 -1
  130. package/docs/types/DreamSerializable.html +1 -1
  131. package/docs/types/DreamSerializableArray.html +1 -1
  132. package/docs/types/DreamSerializerKey.html +1 -1
  133. package/docs/types/DreamSerializers.html +1 -1
  134. package/docs/types/DreamVirtualColumns.html +1 -1
  135. package/docs/types/EncryptAlgorithm.html +1 -1
  136. package/docs/types/HasManyStatement.html +1 -1
  137. package/docs/types/HasOneStatement.html +1 -1
  138. package/docs/types/Hyphenized.html +1 -1
  139. package/docs/types/OpenapiAllTypes.html +1 -1
  140. package/docs/types/OpenapiFormats.html +1 -1
  141. package/docs/types/OpenapiNumberFormats.html +1 -1
  142. package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
  143. package/docs/types/OpenapiPrimitiveTypes.html +1 -1
  144. package/docs/types/OpenapiSchemaArray.html +1 -1
  145. package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
  146. package/docs/types/OpenapiSchemaBase.html +1 -1
  147. package/docs/types/OpenapiSchemaBody.html +1 -1
  148. package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
  149. package/docs/types/OpenapiSchemaCommonFields.html +1 -1
  150. package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
  151. package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
  152. package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
  153. package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
  154. package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
  155. package/docs/types/OpenapiSchemaInteger.html +1 -1
  156. package/docs/types/OpenapiSchemaNull.html +1 -1
  157. package/docs/types/OpenapiSchemaNumber.html +1 -1
  158. package/docs/types/OpenapiSchemaObject.html +1 -1
  159. package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
  160. package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
  161. package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
  162. package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  163. package/docs/types/OpenapiSchemaObjectBase.html +1 -1
  164. package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
  165. package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
  166. package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
  167. package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
  168. package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
  169. package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  170. package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  171. package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  172. package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
  173. package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
  174. package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  175. package/docs/types/OpenapiSchemaString.html +1 -1
  176. package/docs/types/OpenapiShorthandAllTypes.html +1 -1
  177. package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  178. package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
  179. package/docs/types/OpenapiTypeField.html +1 -1
  180. package/docs/types/Pascalized.html +1 -1
  181. package/docs/types/RoundingPrecision.html +1 -1
  182. package/docs/types/SerializerCasing.html +1 -1
  183. package/docs/types/SimpleObjectSerializerType.html +1 -1
  184. package/docs/types/Snakeified.html +1 -1
  185. package/docs/types/UpdateableAssociationProperties.html +1 -1
  186. package/docs/types/UpdateableProperties.html +1 -1
  187. package/docs/types/ValidationType.html +1 -1
  188. package/docs/types/ViewModel.html +1 -1
  189. package/docs/types/ViewModelClass.html +1 -1
  190. package/docs/types/WhereStatementForDream.html +1 -1
  191. package/docs/types/WhereStatementForDreamClass.html +1 -1
  192. package/docs/variables/DateTime-1.html +1 -1
  193. package/docs/variables/DreamAppAllowedPackageManagersEnumValues.html +1 -1
  194. package/docs/variables/DreamConst.html +1 -1
  195. package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
  196. package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
  197. package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
  198. package/docs/variables/ops.html +1 -1
  199. package/docs/variables/primaryKeyTypes.html +1 -1
  200. package/package.json +2 -2
  201. package/CHANGELOG.md +0 -166
@@ -94,6 +94,42 @@ class DreamMigrationHelpers {
94
94
  ALTER TABLE ${kysely_1.sql.table(table)} DROP CONSTRAINT IF EXISTS ${kysely_1.sql.table(constraintName)};
95
95
  `.execute(db);
96
96
  }
97
+ /**
98
+ * Forces a new transaction boundary in migration execution.
99
+ *
100
+ * When called in a migration file, this method ensures that any existing transaction
101
+ * is committed before this migration runs, and a new transaction is started before the
102
+ * migration in this file. This is essential for migrations that depend on previously
103
+ * committed changes.
104
+ *
105
+ * Some database operations require that dependent changes be committed before they can
106
+ * be executed. For example, check constraints that reference enum values require those
107
+ * enum values to be committed to the database first.
108
+ *
109
+ * ```ts
110
+ * // first migration file: Add enum value
111
+ * export async function up(db: Kysely<any>): Promise<void> {
112
+ * await DreamMigrationHelpers.addEnumValue(db, {
113
+ * enumName: 'user_status',
114
+ * value: 'premium'
115
+ * })
116
+ * }
117
+ *
118
+ * // second migration file: Add check constraint that depends on the enum value
119
+ * export async function up(db: Kysely<any>): Promise<void> {
120
+ * DreamMigrationHelpers.newTransaction() // Ensure enum value is committed first
121
+ *
122
+ * await db.schema
123
+ * .alterTable('users')
124
+ * .addCheckConstraint(
125
+ * 'check_premium_users',
126
+ * sql`status = 'premium' OR credits < 100`
127
+ * )
128
+ * .execute()
129
+ * }
130
+ * ```
131
+ */
132
+ static newTransaction() { }
97
133
  /**
98
134
  * Drop a value from an enum and replace it (or optionally remove it from array columns)
99
135
  *
@@ -147,7 +147,13 @@ function applySortableScopesToQuery(dream, kyselyQuery, whereValueCB, scope) {
147
147
  for (const singleScope of (0, scopeArray_js_1.default)(scope)) {
148
148
  const column = (0, getColumnForSortableScope_js_1.default)(dream, singleScope);
149
149
  if (column) {
150
- kyselyQuery = kyselyQuery.where(column, '=', whereValueCB(column));
150
+ const columnValue = whereValueCB(column);
151
+ if (columnValue === null) {
152
+ kyselyQuery = kyselyQuery.where(column, 'is', null);
153
+ }
154
+ else {
155
+ kyselyQuery = kyselyQuery.where(column, '=', columnValue);
156
+ }
151
157
  }
152
158
  }
153
159
  return kyselyQuery;
@@ -61,11 +61,11 @@ const executeDatabaseQuery_js_1 = require("../internal/executeDatabaseQuery.js")
61
61
  const orderByDirection_js_1 = require("../internal/orderByDirection.js");
62
62
  const shouldBypassDefaultScope_js_1 = require("../internal/shouldBypassDefaultScope.js");
63
63
  const SimilarityBuilder_js_1 = require("../internal/similarity/SimilarityBuilder.js");
64
+ const softDeleteDream_js_1 = require("../internal/softDeleteDream.js");
64
65
  const sqlResultToDreamInstance_js_1 = require("../internal/sqlResultToDreamInstance.js");
65
66
  const Query_js_1 = require("../Query.js");
66
67
  const Base_js_1 = require("./Base.js");
67
68
  const runMigration_js_1 = require("./helpers/kysely/runMigration.js");
68
- const softDeleteDream_js_1 = require("../internal/softDeleteDream.js");
69
69
  class KyselyQueryDriver extends Base_js_1.default {
70
70
  // ATTENTION FRED
71
71
  // stop trying to make this async. You never learn...
@@ -1081,11 +1081,11 @@ class KyselyQueryDriver extends Base_js_1.default {
1081
1081
  return (0, kysely_1.sql) `FALSE`;
1082
1082
  }
1083
1083
  notInArrayWithNullExpressionBuilder(eb, a, b, c) {
1084
- const isNullStatement = eb(a, 'is not', null);
1084
+ const isNotNullStatement = eb(a, 'is not', null);
1085
1085
  const compactedC = (0, compact_js_1.default)(c);
1086
1086
  if (compactedC.length)
1087
- return eb.and([eb(a, 'not in', compactedC), isNullStatement]);
1088
- return isNullStatement;
1087
+ return eb.and([eb(a, 'not in', compactedC), isNotNullStatement]);
1088
+ return isNotNullStatement;
1089
1089
  }
1090
1090
  dreamWhereStatementToExpressionBuilderParts(attr, val) {
1091
1091
  let a;
@@ -66,7 +66,8 @@ async function findNextMigrationRequiringNewTransaction(migrator, { ignore } = {
66
66
  const notYetRunMigrations = (await migrator.getMigrations()).filter(migrationInfo => !migrationInfo.executedAt && migrationInfo.name !== ignore);
67
67
  for (const notYetRunMigration of notYetRunMigrations) {
68
68
  const upAndDownString = notYetRunMigration.migration.up.toString() + (notYetRunMigration.migration.down || '').toString();
69
- const migrationRequiresNewTransaction = upAndDownString.includes('DreamMigrationHelpers.dropEnumValue');
69
+ const migrationRequiresNewTransaction = upAndDownString.includes('DreamMigrationHelpers.dropEnumValue') ||
70
+ upAndDownString.includes('DreamMigrationHelpers.newTransaction');
70
71
  if (migrationRequiresNewTransaction)
71
72
  return notYetRunMigration;
72
73
  }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = sanitizeString;
4
+ function sanitizeString(value, sanitizationStrategy) {
5
+ switch (sanitizationStrategy) {
6
+ case 'unicodeString':
7
+ return sanitizeStringUnicodeStringStrategy(value);
8
+ case 'htmlEntity':
9
+ return sanitizeStringHtmlEntityStrategy(value);
10
+ default:
11
+ if (typeof sanitizationStrategy === 'function')
12
+ return sanitizationStrategy(value);
13
+ throw new UnrecognizedAttributeSerializationSanitizationStrategy(sanitizationStrategy);
14
+ }
15
+ }
16
+ function sanitizeStringUnicodeStringStrategy(str) {
17
+ if (str === undefined || str === null)
18
+ return str;
19
+ return str
20
+ .replace(/\\/g, '\\u005c')
21
+ .replace(/&/g, '\\u0026')
22
+ .replace(/</g, '\\u003c')
23
+ .replace(/>/g, '\\u003e')
24
+ .replace(/\//g, '\\u002f')
25
+ .replace(/'/g, '\\u0027')
26
+ .replace(/"/g, '\\u0022');
27
+ }
28
+ function sanitizeStringHtmlEntityStrategy(str) {
29
+ if (str === undefined || str === null)
30
+ return str;
31
+ return str
32
+ .replace(/&/g, '&amp;')
33
+ .replace(/</g, '&lt;')
34
+ .replace(/>/g, '&gt;')
35
+ .replace(/\//g, '&#x2F;')
36
+ .replace(/'/g, '&#x27;')
37
+ .replace(/"/g, '&quot;');
38
+ }
39
+ class UnrecognizedAttributeSerializationSanitizationStrategy extends Error {
40
+ sanitizationStrategy;
41
+ constructor(sanitizationStrategy) {
42
+ super();
43
+ this.sanitizationStrategy = sanitizationStrategy;
44
+ }
45
+ get message() {
46
+ return `Unrecognized attribute serialization sanitization strategy:
47
+ ${this.sanitizationStrategy.toString()}`;
48
+ }
49
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.intersection = exports.hyphenize = exports.groupBy = exports.globalClassNameFromFullyQualifiedModelName = exports.Env = exports.DreamLogos = exports.DateTime = exports.compact = exports.cloneDeepSafe = exports.generateDream = exports.capitalize = exports.camelize = exports.CalendarDate = exports.Benchmark = exports.ValidationError = exports.RecordNotFound = exports.GlobalNameNotSet = exports.NotNullViolation = exports.DataTypeColumnTypeMismatch = exports.CheckConstraintViolation = exports.CreateOrFindByFailedToCreateAndFind = exports.NonLoadedAssociation = exports.Encrypt = exports.PostgresQueryDriver = exports.KyselyQueryDriver = exports.QueryDriverBase = exports.Query = exports.DreamTransaction = exports.openapiShorthandPrimitiveTypes = exports.openapiPrimitiveTypes = exports.DreamConst = exports.Dream = exports.DreamAppAllowedPackageManagersEnumValues = exports.DreamApp = exports.lookupClassByGlobalName = exports.DreamImporter = exports.Decorators = exports.STI = exports.SoftDelete = exports.ReplicaSafe = exports.validateTable = exports.validateColumn = exports.DreamMigrationHelpers = exports.untypedDb = exports.pgErrorType = exports.dreamDbConnections = exports.closeAllDbConnections = exports.DreamCLI = exports.CliFileWriter = exports.DreamBin = void 0;
4
- exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = exports.sharedPathPrefix = exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = void 0;
4
+ exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.sanitizeString = exports.round = exports.range = exports.Range = exports.sharedPathPrefix = exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = void 0;
5
5
  var index_js_1 = require("./bin/index.js");
6
6
  Object.defineProperty(exports, "DreamBin", { enumerable: true, get: function () { return index_js_1.default; } });
7
7
  var CliFileWriter_js_1 = require("./cli/CliFileWriter.js");
@@ -117,6 +117,8 @@ Object.defineProperty(exports, "Range", { enumerable: true, get: function () { r
117
117
  Object.defineProperty(exports, "range", { enumerable: true, get: function () { return range_js_1.default; } });
118
118
  var round_js_1 = require("./helpers/round.js");
119
119
  Object.defineProperty(exports, "round", { enumerable: true, get: function () { return round_js_1.default; } });
120
+ var sanitizeString_js_1 = require("./helpers/sanitizeString.js");
121
+ Object.defineProperty(exports, "sanitizeString", { enumerable: true, get: function () { return sanitizeString_js_1.default; } });
120
122
  var snakeify_js_1 = require("./helpers/snakeify.js");
121
123
  Object.defineProperty(exports, "snakeify", { enumerable: true, get: function () { return snakeify_js_1.default; } });
122
124
  var sort_js_1 = require("./helpers/sort.js");
@@ -5,6 +5,7 @@ const CalendarDate_js_1 = require("../helpers/CalendarDate.js");
5
5
  const compact_js_1 = require("../helpers/compact.js");
6
6
  const DateTime_js_1 = require("../helpers/DateTime.js");
7
7
  const round_js_1 = require("../helpers/round.js");
8
+ const sanitizeString_js_1 = require("../helpers/sanitizeString.js");
8
9
  const snakeify_js_1 = require("../helpers/snakeify.js");
9
10
  const DreamSerializerBuilder_js_1 = require("./builders/DreamSerializerBuilder.js");
10
11
  const ObjectSerializerBuilder_js_1 = require("./builders/ObjectSerializerBuilder.js");
@@ -42,7 +43,9 @@ class SerializerRenderer {
42
43
  case 'attribute': {
43
44
  const outputAttributeName = this.setCase(attribute.options?.as ?? attribute.name);
44
45
  const value = data[attribute.name] ?? attribute.options?.default;
45
- accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, attribute.options, this.passthroughData, this.renderOpts);
46
+ accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(attribute.options?.sanitize && typeof value === 'string'
47
+ ? (0, sanitizeString_js_1.default)(value, attribute.options.sanitize)
48
+ : value, attribute.options, this.passthroughData, this.renderOpts);
46
49
  return accumulator;
47
50
  }
48
51
  /////////////////////
@@ -55,7 +58,9 @@ class SerializerRenderer {
55
58
  const outputAttributeName = this.setCase(attribute.options?.as ?? attribute.name);
56
59
  const target = data[attribute.targetName];
57
60
  const value = target?.[attribute.name] ?? attribute.options?.default;
58
- accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, attribute.options, this.passthroughData, this.renderOpts);
61
+ accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(attribute.options?.sanitize && typeof value === 'string'
62
+ ? (0, sanitizeString_js_1.default)(value, attribute.options.sanitize)
63
+ : value, attribute.options, this.passthroughData, this.renderOpts);
59
64
  return accumulator;
60
65
  }
61
66
  //////////////////////////////
@@ -92,6 +92,42 @@ export default class DreamMigrationHelpers {
92
92
  ALTER TABLE ${sql.table(table)} DROP CONSTRAINT IF EXISTS ${sql.table(constraintName)};
93
93
  `.execute(db);
94
94
  }
95
+ /**
96
+ * Forces a new transaction boundary in migration execution.
97
+ *
98
+ * When called in a migration file, this method ensures that any existing transaction
99
+ * is committed before this migration runs, and a new transaction is started before the
100
+ * migration in this file. This is essential for migrations that depend on previously
101
+ * committed changes.
102
+ *
103
+ * Some database operations require that dependent changes be committed before they can
104
+ * be executed. For example, check constraints that reference enum values require those
105
+ * enum values to be committed to the database first.
106
+ *
107
+ * ```ts
108
+ * // first migration file: Add enum value
109
+ * export async function up(db: Kysely<any>): Promise<void> {
110
+ * await DreamMigrationHelpers.addEnumValue(db, {
111
+ * enumName: 'user_status',
112
+ * value: 'premium'
113
+ * })
114
+ * }
115
+ *
116
+ * // second migration file: Add check constraint that depends on the enum value
117
+ * export async function up(db: Kysely<any>): Promise<void> {
118
+ * DreamMigrationHelpers.newTransaction() // Ensure enum value is committed first
119
+ *
120
+ * await db.schema
121
+ * .alterTable('users')
122
+ * .addCheckConstraint(
123
+ * 'check_premium_users',
124
+ * sql`status = 'premium' OR credits < 100`
125
+ * )
126
+ * .execute()
127
+ * }
128
+ * ```
129
+ */
130
+ static newTransaction() { }
95
131
  /**
96
132
  * Drop a value from an enum and replace it (or optionally remove it from array columns)
97
133
  *
@@ -142,7 +142,13 @@ export function applySortableScopesToQuery(dream, kyselyQuery, whereValueCB, sco
142
142
  for (const singleScope of scopeArray(scope)) {
143
143
  const column = getColumnForSortableScope(dream, singleScope);
144
144
  if (column) {
145
- kyselyQuery = kyselyQuery.where(column, '=', whereValueCB(column));
145
+ const columnValue = whereValueCB(column);
146
+ if (columnValue === null) {
147
+ kyselyQuery = kyselyQuery.where(column, 'is', null);
148
+ }
149
+ else {
150
+ kyselyQuery = kyselyQuery.where(column, '=', columnValue);
151
+ }
146
152
  }
147
153
  }
148
154
  return kyselyQuery;
@@ -59,11 +59,11 @@ import executeDatabaseQuery from '../internal/executeDatabaseQuery.js';
59
59
  import orderByDirection from '../internal/orderByDirection.js';
60
60
  import shouldBypassDefaultScope from '../internal/shouldBypassDefaultScope.js';
61
61
  import SimilarityBuilder from '../internal/similarity/SimilarityBuilder.js';
62
+ import softDeleteDream from '../internal/softDeleteDream.js';
62
63
  import sqlResultToDreamInstance from '../internal/sqlResultToDreamInstance.js';
63
64
  import Query from '../Query.js';
64
65
  import QueryDriverBase from './Base.js';
65
66
  import runMigration from './helpers/kysely/runMigration.js';
66
- import softDeleteDream from '../internal/softDeleteDream.js';
67
67
  export default class KyselyQueryDriver extends QueryDriverBase {
68
68
  // ATTENTION FRED
69
69
  // stop trying to make this async. You never learn...
@@ -1079,11 +1079,11 @@ export default class KyselyQueryDriver extends QueryDriverBase {
1079
1079
  return sql `FALSE`;
1080
1080
  }
1081
1081
  notInArrayWithNullExpressionBuilder(eb, a, b, c) {
1082
- const isNullStatement = eb(a, 'is not', null);
1082
+ const isNotNullStatement = eb(a, 'is not', null);
1083
1083
  const compactedC = compact(c);
1084
1084
  if (compactedC.length)
1085
- return eb.and([eb(a, 'not in', compactedC), isNullStatement]);
1086
- return isNullStatement;
1085
+ return eb.and([eb(a, 'not in', compactedC), isNotNullStatement]);
1086
+ return isNotNullStatement;
1087
1087
  }
1088
1088
  dreamWhereStatementToExpressionBuilderParts(attr, val) {
1089
1089
  let a;
@@ -63,7 +63,8 @@ async function findNextMigrationRequiringNewTransaction(migrator, { ignore } = {
63
63
  const notYetRunMigrations = (await migrator.getMigrations()).filter(migrationInfo => !migrationInfo.executedAt && migrationInfo.name !== ignore);
64
64
  for (const notYetRunMigration of notYetRunMigrations) {
65
65
  const upAndDownString = notYetRunMigration.migration.up.toString() + (notYetRunMigration.migration.down || '').toString();
66
- const migrationRequiresNewTransaction = upAndDownString.includes('DreamMigrationHelpers.dropEnumValue');
66
+ const migrationRequiresNewTransaction = upAndDownString.includes('DreamMigrationHelpers.dropEnumValue') ||
67
+ upAndDownString.includes('DreamMigrationHelpers.newTransaction');
67
68
  if (migrationRequiresNewTransaction)
68
69
  return notYetRunMigration;
69
70
  }
@@ -0,0 +1,46 @@
1
+ export default function sanitizeString(value, sanitizationStrategy) {
2
+ switch (sanitizationStrategy) {
3
+ case 'unicodeString':
4
+ return sanitizeStringUnicodeStringStrategy(value);
5
+ case 'htmlEntity':
6
+ return sanitizeStringHtmlEntityStrategy(value);
7
+ default:
8
+ if (typeof sanitizationStrategy === 'function')
9
+ return sanitizationStrategy(value);
10
+ throw new UnrecognizedAttributeSerializationSanitizationStrategy(sanitizationStrategy);
11
+ }
12
+ }
13
+ function sanitizeStringUnicodeStringStrategy(str) {
14
+ if (str === undefined || str === null)
15
+ return str;
16
+ return str
17
+ .replace(/\\/g, '\\u005c')
18
+ .replace(/&/g, '\\u0026')
19
+ .replace(/</g, '\\u003c')
20
+ .replace(/>/g, '\\u003e')
21
+ .replace(/\//g, '\\u002f')
22
+ .replace(/'/g, '\\u0027')
23
+ .replace(/"/g, '\\u0022');
24
+ }
25
+ function sanitizeStringHtmlEntityStrategy(str) {
26
+ if (str === undefined || str === null)
27
+ return str;
28
+ return str
29
+ .replace(/&/g, '&amp;')
30
+ .replace(/</g, '&lt;')
31
+ .replace(/>/g, '&gt;')
32
+ .replace(/\//g, '&#x2F;')
33
+ .replace(/'/g, '&#x27;')
34
+ .replace(/"/g, '&quot;');
35
+ }
36
+ class UnrecognizedAttributeSerializationSanitizationStrategy extends Error {
37
+ sanitizationStrategy;
38
+ constructor(sanitizationStrategy) {
39
+ super();
40
+ this.sanitizationStrategy = sanitizationStrategy;
41
+ }
42
+ get message() {
43
+ return `Unrecognized attribute serialization sanitization strategy:
44
+ ${this.sanitizationStrategy.toString()}`;
45
+ }
46
+ }
@@ -53,6 +53,7 @@ export { default as relativeDreamPath } from './helpers/path/relativeDreamPath.j
53
53
  export { default as sharedPathPrefix } from './helpers/path/sharedPathPrefix.js';
54
54
  export { Range, default as range } from './helpers/range.js';
55
55
  export { default as round } from './helpers/round.js';
56
+ export { default as sanitizeString } from './helpers/sanitizeString.js';
56
57
  export { default as snakeify } from './helpers/snakeify.js';
57
58
  export { default as sort } from './helpers/sort.js';
58
59
  export { default as sortBy } from './helpers/sortBy.js';
@@ -3,6 +3,7 @@ import CalendarDate from '../helpers/CalendarDate.js';
3
3
  import compact from '../helpers/compact.js';
4
4
  import { DateTime } from '../helpers/DateTime.js';
5
5
  import round from '../helpers/round.js';
6
+ import sanitizeString from '../helpers/sanitizeString.js';
6
7
  import snakeify from '../helpers/snakeify.js';
7
8
  import DreamSerializerBuilder from './builders/DreamSerializerBuilder.js';
8
9
  import ObjectSerializerBuilder from './builders/ObjectSerializerBuilder.js';
@@ -40,7 +41,9 @@ export default class SerializerRenderer {
40
41
  case 'attribute': {
41
42
  const outputAttributeName = this.setCase(attribute.options?.as ?? attribute.name);
42
43
  const value = data[attribute.name] ?? attribute.options?.default;
43
- accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, attribute.options, this.passthroughData, this.renderOpts);
44
+ accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(attribute.options?.sanitize && typeof value === 'string'
45
+ ? sanitizeString(value, attribute.options.sanitize)
46
+ : value, attribute.options, this.passthroughData, this.renderOpts);
44
47
  return accumulator;
45
48
  }
46
49
  /////////////////////
@@ -53,7 +56,9 @@ export default class SerializerRenderer {
53
56
  const outputAttributeName = this.setCase(attribute.options?.as ?? attribute.name);
54
57
  const target = data[attribute.targetName];
55
58
  const value = target?.[attribute.name] ?? attribute.options?.default;
56
- accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, attribute.options, this.passthroughData, this.renderOpts);
59
+ accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(attribute.options?.sanitize && typeof value === 'string'
60
+ ? sanitizeString(value, attribute.options.sanitize)
61
+ : value, attribute.options, this.passthroughData, this.renderOpts);
57
62
  return accumulator;
58
63
  }
59
64
  //////////////////////////////
@@ -79,6 +79,42 @@ export default class DreamMigrationHelpers {
79
79
  static dropConstraint(db: Kysely<any>, constraintName: string, { table }: {
80
80
  table: string;
81
81
  }): Promise<void>;
82
+ /**
83
+ * Forces a new transaction boundary in migration execution.
84
+ *
85
+ * When called in a migration file, this method ensures that any existing transaction
86
+ * is committed before this migration runs, and a new transaction is started before the
87
+ * migration in this file. This is essential for migrations that depend on previously
88
+ * committed changes.
89
+ *
90
+ * Some database operations require that dependent changes be committed before they can
91
+ * be executed. For example, check constraints that reference enum values require those
92
+ * enum values to be committed to the database first.
93
+ *
94
+ * ```ts
95
+ * // first migration file: Add enum value
96
+ * export async function up(db: Kysely<any>): Promise<void> {
97
+ * await DreamMigrationHelpers.addEnumValue(db, {
98
+ * enumName: 'user_status',
99
+ * value: 'premium'
100
+ * })
101
+ * }
102
+ *
103
+ * // second migration file: Add check constraint that depends on the enum value
104
+ * export async function up(db: Kysely<any>): Promise<void> {
105
+ * DreamMigrationHelpers.newTransaction() // Ensure enum value is committed first
106
+ *
107
+ * await db.schema
108
+ * .alterTable('users')
109
+ * .addCheckConstraint(
110
+ * 'check_premium_users',
111
+ * sql`status = 'premium' OR credits < 100`
112
+ * )
113
+ * .execute()
114
+ * }
115
+ * ```
116
+ */
117
+ static newTransaction(): void;
82
118
  /**
83
119
  * Drop a value from an enum and replace it (or optionally remove it from array columns)
84
120
  *
@@ -0,0 +1,2 @@
1
+ import { AttributeSerializationSanitizationStrategy } from '../types/serializer.js';
2
+ export default function sanitizeString<T extends string | null | undefined>(value: T, sanitizationStrategy: AttributeSerializationSanitizationStrategy): T;
@@ -54,6 +54,7 @@ export { default as relativeDreamPath } from './helpers/path/relativeDreamPath.j
54
54
  export { default as sharedPathPrefix } from './helpers/path/sharedPathPrefix.js';
55
55
  export { Range, default as range } from './helpers/range.js';
56
56
  export { default as round, type RoundingPrecision } from './helpers/round.js';
57
+ export { default as sanitizeString } from './helpers/sanitizeString.js';
57
58
  export { default as snakeify } from './helpers/snakeify.js';
58
59
  export { default as sort } from './helpers/sort.js';
59
60
  export { default as sortBy } from './helpers/sortBy.js';
@@ -1,6 +1,7 @@
1
1
  import Dream from '../../Dream.js';
2
- import { DreamOrViewModelSerializerKey, NonJsonDreamColumnNames, ViewModel, ViewModelClass } from '../../types/dream.js';
3
- import { AutomaticSerializerAttributeOptions, AutomaticSerializerAttributeOptionsForType, InternalAnyTypedSerializerAttribute, InternalAnyTypedSerializerCustomAttribute, InternalAnyTypedSerializerDelegatedAttribute, InternalAnyTypedSerializerRendersMany, InternalAnyTypedSerializerRendersOne, NonAutomaticSerializerAttributeOptions, NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption, SerializerType } from '../../types/serializer.js';
2
+ import { DreamOrViewModelSerializerKey, DreamVirtualColumns, NonJsonDreamColumnNames, ViewModel, ViewModelClass } from '../../types/dream.js';
3
+ import { OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes } from '../../types/openapi.js';
4
+ import { AutomaticSerializerAttributeOptions, AutomaticSerializerAttributeOptionsForType, InternalAnyTypedSerializerAttribute, InternalAnyTypedSerializerCustomAttribute, InternalAnyTypedSerializerDelegatedAttribute, InternalAnyTypedSerializerRendersMany, InternalAnyTypedSerializerRendersOne, NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption, SerializerAttributeOptionsForVirtualColumn, SerializerType } from '../../types/serializer.js';
4
5
  import { SerializerRendererOpts } from '../SerializerRenderer.js';
5
6
  export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dream, MaybeNullDataType extends Dream | null, PassthroughDataType = any, DataType extends Exclude<MaybeNullDataType, null> = Exclude<MaybeNullDataType, null>> {
6
7
  protected $typeForOpenapi: DataTypeForOpenapi;
@@ -37,6 +38,7 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
37
38
  * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
38
39
  */
39
40
  attribute<AttributeName extends NonJsonDreamColumnNames<DataType> & keyof DataType & 'type', Options extends AutomaticSerializerAttributeOptionsForType>(name: AttributeName, options?: Options): DreamSerializerBuilder<DataTypeForOpenapi, MaybeNullDataType, PassthroughDataType, DataType>;
41
+ attribute<AttributeName extends DreamVirtualColumns<DataType>[number], Options extends SerializerAttributeOptionsForVirtualColumn>(name: AttributeName, options?: Options): DreamSerializerBuilder<DataTypeForOpenapi, MaybeNullDataType, PassthroughDataType, DataType>;
40
42
  attribute<MaybeAttributeName extends NonJsonDreamColumnNames<DataType> | (keyof DataType & string), AttributeName extends MaybeAttributeName extends NonJsonDreamColumnNames<DataType> ? never : Exclude<keyof DataType, keyof Dream> & string, Options extends NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption>(name: AttributeName, options: Options): DreamSerializerBuilder<DataTypeForOpenapi, MaybeNullDataType, PassthroughDataType, DataType>;
41
43
  attribute<AttributeName extends NonJsonDreamColumnNames<DataType> & keyof DataType & string, Options extends AutomaticSerializerAttributeOptions<DataType, AttributeName>>(name: AttributeName, options?: Options): DreamSerializerBuilder<DataTypeForOpenapi, MaybeNullDataType, PassthroughDataType, DataType>;
42
44
  /**
@@ -99,7 +101,8 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
99
101
  *
100
102
  * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
101
103
  */
102
- customAttribute<Options extends Omit<NonAutomaticSerializerAttributeOptions, 'as'> & {
104
+ customAttribute<Options extends {
105
+ openapi: OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes;
103
106
  flatten?: boolean;
104
107
  }, CallbackFn extends () => unknown>(name: string, fn: CallbackFn, options: Options): this;
105
108
  /**
@@ -41,7 +41,7 @@ type OnStatementForAssociationDefinition<DB, Schema, TableName extends Associati
41
41
  export type SelfOnStatement<BaseInstance extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<Record<keyof DB[TableName], DreamColumnNames<BaseInstance>>>;
42
42
  export type WhereStatementForJoinedAssociation<JoinedAssociations extends Readonly<JoinedAssociation[]>, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = RecursiveWhereStatementForJoinedAssociation<JoinedAssociations, DB, Schema, WhereStatement<DB, Schema, TableName>>;
43
43
  type RecursiveWhereStatementForJoinedAssociation<JoinedAssociations extends Readonly<JoinedAssociation[]>, DB, Schema, OriginalOnStatement, Depth extends number = 0, CurrentJoinedAssociation = JoinedAssociations[0], TableName = CurrentJoinedAssociation extends JoinedAssociation ? CurrentJoinedAssociation['table'] : never, AssociationName = CurrentJoinedAssociation extends JoinedAssociation ? CurrentJoinedAssociation['alias'] : never, NonNamespacedAssociationOnStatement = TableName extends never ? never : AssociationName extends never ? never : WhereStatement<DB, Schema, TableName & AssociationTableNames<DB, Schema> & keyof DB>, NextOnStatement = NonNamespacedAssociationOnStatement extends never ? OriginalOnStatement : OriginalOnStatement & {
44
- [K in keyof NonNamespacedAssociationOnStatement as `${AssociationName & string}.${K & string}`]: NonNamespacedAssociationOnStatement[K & keyof NonNamespacedAssociationOnStatement];
44
+ [K in keyof NonNamespacedAssociationOnStatement as `${AssociationName & string}.${K & string}`]: NonNamespacedAssociationOnStatement[K & keyof NonNamespacedAssociationOnStatement] | null;
45
45
  }> = JoinedAssociations['length'] extends 0 ? OriginalOnStatement : Depth extends MAX_JOINED_TABLES_DEPTH ? OriginalOnStatement : TableName extends never ? OriginalOnStatement : RecursiveWhereStatementForJoinedAssociation<ReadonlyTail<JoinedAssociations>, DB, Schema, NextOnStatement, Inc<Depth>>;
46
46
  export type OrderStatement<DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = TableColumnNames<DB, TableName> | Partial<Record<TableColumnNames<DB, TableName>, OrderDir>>;
47
47
  export type LimitStatement = number;
@@ -266,8 +266,10 @@ type RecursiveWhereStatementForJoinedAssociation<
266
266
  NextOnStatement = NonNamespacedAssociationOnStatement extends never
267
267
  ? OriginalOnStatement
268
268
  : OriginalOnStatement & {
269
- [K in keyof NonNamespacedAssociationOnStatement as `${AssociationName & string}.${K & string}`]: NonNamespacedAssociationOnStatement[K &
270
- keyof NonNamespacedAssociationOnStatement]
269
+ [K in keyof NonNamespacedAssociationOnStatement as `${AssociationName & string}.${K & string}`]:
270
+ | NonNamespacedAssociationOnStatement[K & keyof NonNamespacedAssociationOnStatement]
271
+ // `| null` so that we can query for models that don't have a particular association
272
+ | null
271
273
  },
272
274
  > = JoinedAssociations['length'] extends 0
273
275
  ? OriginalOnStatement
@@ -5,6 +5,7 @@ import ObjectSerializerBuilder from '../serializer/builders/ObjectSerializerBuil
5
5
  import { DreamAttributeDbTypes, DreamSerializable, DreamSerializableArray, ViewModelClass } from './dream.js';
6
6
  import { DecimalOpenapiTypesIncludingDbTypes, OpenapiDescription, OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes } from './openapi.js';
7
7
  export type SerializerCasing = 'camel' | 'snake';
8
+ export type AttributeSerializationSanitizationStrategy = 'unicodeString' | 'htmlEntity' | ((val: any) => any);
8
9
  export type DreamsOrSerializersOrViewModels = DreamSerializable | DreamSerializableArray;
9
10
  export interface InternalAnyTypedSerializerAttribute {
10
11
  type: 'attribute';
@@ -48,6 +49,7 @@ export interface InternalAnyTypedSerializerRendersMany<DataType, AttributeName e
48
49
  export type AutomaticSerializerAttributeOptions<DreamInstance extends Dream, AttributeName extends keyof DreamInstance & string> = {
49
50
  as?: string;
50
51
  default?: any;
52
+ sanitize?: AttributeSerializationSanitizationStrategy;
51
53
  openapi?: OpenapiDescription;
52
54
  precision?: DreamAttributeDbTypes<DreamInstance>[AttributeName] extends DecimalOpenapiTypesIncludingDbTypes ? RoundingPrecision : never;
53
55
  };
@@ -58,9 +60,16 @@ export type AutomaticSerializerAttributeOptionsForType = {
58
60
  enum?: string[] | Readonly<string[]>;
59
61
  };
60
62
  };
63
+ export type SerializerAttributeOptionsForVirtualColumn = {
64
+ as?: string;
65
+ default?: any;
66
+ sanitize?: AttributeSerializationSanitizationStrategy;
67
+ openapi?: OpenapiDescription | OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes;
68
+ };
61
69
  export type NonAutomaticSerializerAttributeOptions = {
62
70
  as?: string;
63
71
  default?: any;
72
+ sanitize?: AttributeSerializationSanitizationStrategy;
64
73
  openapi: OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes;
65
74
  };
66
75
  export type NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption = NonAutomaticSerializerAttributeOptions & {
@@ -11,6 +11,7 @@ import {
11
11
  } from './openapi.js'
12
12
 
13
13
  export type SerializerCasing = 'camel' | 'snake'
14
+ export type AttributeSerializationSanitizationStrategy = 'unicodeString' | 'htmlEntity' | ((val: any) => any)
14
15
  export type DreamsOrSerializersOrViewModels = DreamSerializable | DreamSerializableArray
15
16
 
16
17
  export interface InternalAnyTypedSerializerAttribute<> {
@@ -68,6 +69,7 @@ export type AutomaticSerializerAttributeOptions<
68
69
  > = {
69
70
  as?: string
70
71
  default?: any
72
+ sanitize?: AttributeSerializationSanitizationStrategy
71
73
  openapi?: OpenapiDescription
72
74
  precision?: DreamAttributeDbTypes<DreamInstance>[AttributeName] extends DecimalOpenapiTypesIncludingDbTypes
73
75
  ? RoundingPrecision
@@ -82,9 +84,17 @@ export type AutomaticSerializerAttributeOptionsForType = {
82
84
  }
83
85
  }
84
86
 
87
+ export type SerializerAttributeOptionsForVirtualColumn = {
88
+ as?: string
89
+ default?: any
90
+ sanitize?: AttributeSerializationSanitizationStrategy
91
+ openapi?: OpenapiDescription | OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes
92
+ }
93
+
85
94
  export type NonAutomaticSerializerAttributeOptions = {
86
95
  as?: string
87
96
  default?: any
97
+ sanitize?: AttributeSerializationSanitizationStrategy
88
98
  openapi: OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes
89
99
  }
90
100
 
@@ -1 +1 @@
1
- window.navigationData = "data:application/octet-stream;base64,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"
1
+ window.navigationData = "data:application/octet-stream;base64,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"