@rvoh/dream 2.40.1 → 2.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/dist/cjs/src/Dream.js +3 -2
  2. package/dist/cjs/src/dream/internal/findOrCreateBy.js +2 -3
  3. package/dist/cjs/src/dream/internal/findOrCreateLookupStatement.js +19 -0
  4. package/dist/cjs/src/dream/internal/updateOrCreateBy.js +2 -3
  5. package/dist/cjs/src/dream-app/index.js +17 -10
  6. package/dist/cjs/src/helpers/db/normalizeDataForDb.js +16 -2
  7. package/dist/cjs/src/ops/index.js +7 -3
  8. package/dist/cjs/src/serializer/DreamSerializer.js +15 -9
  9. package/dist/cjs/src/serializer/ObjectSerializer.js +15 -9
  10. package/dist/cjs/src/serializer/SerializerRenderer.js +2 -2
  11. package/dist/cjs/src/serializer/helpers/nullFlattenedSerializerKeys.js +6 -5
  12. package/dist/esm/src/Dream.js +3 -2
  13. package/dist/esm/src/dream/internal/findOrCreateBy.js +2 -3
  14. package/dist/esm/src/dream/internal/findOrCreateLookupStatement.js +19 -0
  15. package/dist/esm/src/dream/internal/updateOrCreateBy.js +2 -3
  16. package/dist/esm/src/dream-app/index.js +17 -10
  17. package/dist/esm/src/helpers/db/normalizeDataForDb.js +16 -2
  18. package/dist/esm/src/ops/index.js +7 -3
  19. package/dist/esm/src/serializer/DreamSerializer.js +15 -9
  20. package/dist/esm/src/serializer/ObjectSerializer.js +15 -9
  21. package/dist/esm/src/serializer/SerializerRenderer.js +2 -2
  22. package/dist/esm/src/serializer/helpers/nullFlattenedSerializerKeys.js +6 -5
  23. package/dist/types/src/dream/internal/findOrCreateLookupStatement.d.ts +14 -0
  24. package/dist/types/src/dream-app/index.d.ts +17 -10
  25. package/dist/types/src/ops/index.d.ts +7 -3
  26. package/dist/types/src/serializer/DreamSerializer.d.ts +15 -9
  27. package/dist/types/src/serializer/ObjectSerializer.d.ts +15 -9
  28. package/dist/types/src/serializer/helpers/nullFlattenedSerializerKeys.d.ts +3 -3
  29. package/dist/types/src/types/associations/shared.d.ts +7 -5
  30. package/dist/types/src/types/types/associations/shared.ts +27 -5
  31. package/docs/classes/db.DreamMigrationHelpers.html +11 -11
  32. package/docs/classes/db.KyselyQueryDriver.html +49 -49
  33. package/docs/classes/db.PostgresQueryDriver.html +49 -49
  34. package/docs/classes/db.QueryDriverBase.html +49 -49
  35. package/docs/classes/errors.CannotSaveMissingDream.html +2 -2
  36. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  37. package/docs/classes/errors.ColumnOverflow.html +3 -3
  38. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  39. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  40. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  41. package/docs/classes/errors.DecryptionError.html +2 -2
  42. package/docs/classes/errors.DecryptionParseError.html +2 -2
  43. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  44. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  45. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  46. package/docs/classes/errors.InvalidClockTime.html +2 -2
  47. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  48. package/docs/classes/errors.InvalidDateTime.html +2 -2
  49. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  50. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  51. package/docs/classes/errors.NotNullViolation.html +3 -3
  52. package/docs/classes/errors.RecordNotFound.html +3 -3
  53. package/docs/classes/errors.SortableScopeDidNotStabilize.html +3 -3
  54. package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +3 -3
  55. package/docs/classes/errors.ValidationError.html +3 -3
  56. package/docs/classes/index.CalendarDate.html +33 -33
  57. package/docs/classes/index.ClockTime.html +32 -32
  58. package/docs/classes/index.ClockTimeTz.html +35 -35
  59. package/docs/classes/index.DateTime.html +86 -86
  60. package/docs/classes/index.Decorators.html +19 -19
  61. package/docs/classes/index.Dream.html +126 -126
  62. package/docs/classes/index.DreamApp.html +24 -21
  63. package/docs/classes/index.DreamTransaction.html +3 -3
  64. package/docs/classes/index.Env.html +5 -5
  65. package/docs/classes/index.Query.html +65 -65
  66. package/docs/classes/system.CliFileWriter.html +4 -4
  67. package/docs/classes/system.DreamBin.html +3 -3
  68. package/docs/classes/system.DreamCLI.html +7 -7
  69. package/docs/classes/system.DreamImporter.html +2 -2
  70. package/docs/classes/system.DreamLogos.html +2 -2
  71. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  72. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  73. package/docs/classes/system.PathHelpers.html +3 -3
  74. package/docs/classes/utils.Encrypt.html +4 -4
  75. package/docs/classes/utils.Range.html +2 -2
  76. package/docs/functions/db.closeAllDbConnections.html +1 -1
  77. package/docs/functions/db.dreamDbConnections.html +1 -1
  78. package/docs/functions/db.untypedDb.html +1 -1
  79. package/docs/functions/db.validateColumn.html +1 -1
  80. package/docs/functions/db.validateTable.html +1 -1
  81. package/docs/functions/errors.pgErrorType.html +1 -1
  82. package/docs/functions/index.DreamSerializer.html +16 -10
  83. package/docs/functions/index.ObjectSerializer.html +16 -10
  84. package/docs/functions/index.ReplicaSafe.html +1 -1
  85. package/docs/functions/index.STI.html +1 -1
  86. package/docs/functions/index.SoftDelete.html +1 -1
  87. package/docs/functions/utils.camelize.html +1 -1
  88. package/docs/functions/utils.capitalize.html +1 -1
  89. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  90. package/docs/functions/utils.compact.html +1 -1
  91. package/docs/functions/utils.groupBy.html +1 -1
  92. package/docs/functions/utils.hyphenize.html +1 -1
  93. package/docs/functions/utils.intersection.html +1 -1
  94. package/docs/functions/utils.isEmpty.html +1 -1
  95. package/docs/functions/utils.normalizeUnicode.html +1 -1
  96. package/docs/functions/utils.pascalize.html +1 -1
  97. package/docs/functions/utils.percent.html +1 -1
  98. package/docs/functions/utils.range.html +1 -1
  99. package/docs/functions/utils.round.html +1 -1
  100. package/docs/functions/utils.sanitizeString.html +1 -1
  101. package/docs/functions/utils.snakeify.html +1 -1
  102. package/docs/functions/utils.sort.html +1 -1
  103. package/docs/functions/utils.sortBy.html +1 -1
  104. package/docs/functions/utils.sortObjectByKey.html +1 -1
  105. package/docs/functions/utils.sortObjectByValue.html +1 -1
  106. package/docs/functions/utils.uncapitalize.html +1 -1
  107. package/docs/functions/utils.uniq.html +1 -1
  108. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  109. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  110. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  111. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  112. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  113. package/docs/interfaces/types.DecoratorContext.html +2 -2
  114. package/docs/interfaces/types.DecryptCallbacks.html +2 -2
  115. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  116. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  117. package/docs/interfaces/types.DreamDbConfig.html +6 -6
  118. package/docs/interfaces/types.DurationObject.html +2 -2
  119. package/docs/interfaces/types.EncryptOptions.html +2 -2
  120. package/docs/interfaces/types.EncryptionLegacyKeyUsedEvent.html +4 -4
  121. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  122. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  123. package/docs/interfaces/types.IntrospectedColumn.html +7 -7
  124. package/docs/interfaces/types.IntrospectedDatabase.html +2 -2
  125. package/docs/interfaces/types.IntrospectedEnum.html +2 -2
  126. package/docs/interfaces/types.IntrospectedTable.html +5 -5
  127. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  128. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  129. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  130. package/docs/types/openapi.OpenapiFormats.html +1 -1
  131. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  132. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  133. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  134. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  135. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  136. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  137. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  138. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  139. package/docs/types/openapi.OpenapiSchemaCombinatorFields.html +1 -1
  140. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  141. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
  142. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
  143. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
  144. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  145. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  146. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  147. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  148. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  149. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  150. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  151. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  152. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  153. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  154. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  155. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  156. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  157. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  158. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  159. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  160. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  161. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  162. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  163. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  164. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  165. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  166. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  167. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  168. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  169. package/docs/types/types.CalendarDateObject.html +1 -1
  170. package/docs/types/types.Camelized.html +1 -1
  171. package/docs/types/types.ClockTimeObject.html +1 -1
  172. package/docs/types/types.DbConnectionType.html +1 -1
  173. package/docs/types/types.DbTypes.html +1 -1
  174. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  175. package/docs/types/types.DreamAttributes.html +1 -1
  176. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  177. package/docs/types/types.DreamClassColumn.html +1 -1
  178. package/docs/types/types.DreamColumn.html +1 -1
  179. package/docs/types/types.DreamColumnNames.html +1 -1
  180. package/docs/types/types.DreamLogLevel.html +1 -1
  181. package/docs/types/types.DreamLogger.html +2 -2
  182. package/docs/types/types.DreamModelSerializerType.html +1 -1
  183. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  184. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  185. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  186. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  187. package/docs/types/types.DreamSerializable.html +1 -1
  188. package/docs/types/types.DreamSerializableArray.html +1 -1
  189. package/docs/types/types.DreamSerializerKey.html +1 -1
  190. package/docs/types/types.DreamSerializers.html +1 -1
  191. package/docs/types/types.DreamVirtualColumns.html +1 -1
  192. package/docs/types/types.DurationUnit.html +1 -1
  193. package/docs/types/types.EncryptAlgorithm.html +1 -1
  194. package/docs/types/types.HasManyStatement.html +1 -1
  195. package/docs/types/types.HasOneStatement.html +1 -1
  196. package/docs/types/types.Hyphenized.html +1 -1
  197. package/docs/types/types.IntrospectedValueType.html +1 -1
  198. package/docs/types/types.Pascalized.html +1 -1
  199. package/docs/types/types.PrimaryKeyType.html +1 -1
  200. package/docs/types/types.RoundingPrecision.html +1 -1
  201. package/docs/types/types.SerializerCasing.html +1 -1
  202. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  203. package/docs/types/types.Snakeified.html +1 -1
  204. package/docs/types/types.StrictInterface.html +1 -1
  205. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  206. package/docs/types/types.UpdateableProperties.html +1 -1
  207. package/docs/types/types.ValidationType.html +1 -1
  208. package/docs/types/types.ViewModel.html +2 -2
  209. package/docs/types/types.ViewModelClass.html +1 -1
  210. package/docs/types/types.WeekdayName.html +1 -1
  211. package/docs/types/types.WhereStatementForDream.html +1 -1
  212. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  213. package/docs/variables/index.DreamConst.html +1 -1
  214. package/docs/variables/index.ops.html +8 -4
  215. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  216. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  217. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  218. package/docs/variables/system.primaryKeyTypes.html +1 -1
  219. package/package.json +1 -1
@@ -0,0 +1,14 @@
1
+ import Dream from '../../Dream.js';
2
+ import { WhereStatement } from '../../types/associations/shared.js';
3
+ import { UpdateablePropertiesForClass } from '../../types/dream.js';
4
+ /**
5
+ * Builds the `findBy` statement that findOrCreateBy, createOrFindBy,
6
+ * updateOrCreateBy and createOrUpdateBy use to look up an existing record.
7
+ * Their attributes are both the lookup and the values to persist, so an array
8
+ * given for an array column is the whole array to store: the lookup compares
9
+ * it with `ops.equal`, matching only a record whose array equals it
10
+ * element-for-element, in order, instead of the `IN` a plain list means in a
11
+ * where clause. PostgreSQL defines no equality operator for `json`, so on a
12
+ * `json[]` column this lookup raises at the database, as `ops.equal` does.
13
+ */
14
+ export default function findOrCreateLookupStatement<T extends typeof Dream>(dreamClass: T, attributes: UpdateablePropertiesForClass<T>): WhereStatement<InstanceType<T>>;
@@ -159,25 +159,32 @@ export default class DreamApp {
159
159
  private _packageManager;
160
160
  get packageManager(): "pnpm" | "yarn" | "npm" | "bun" | "deno";
161
161
  private _importExtension;
162
+ /**
163
+ * The import suffix the CLI generators write: `.js`, `.ts` or `none`.
164
+ *
165
+ * In a Psychic app, set it in conf/app.ts with
166
+ * `psy.set('importExtension', …)`. Psychic forwards it here, and a different
167
+ * value set in conf/dream.ts throws at boot. In a Dream-only app, set it in
168
+ * conf/dream.ts with `dreamApp.set('importExtension', …)`.
169
+ *
170
+ * Defaults to `.js`.
171
+ */
162
172
  get importExtension(): ".js" | ".ts" | "none";
163
173
  private _importAliasPrefix;
164
174
  /**
165
175
  * The prefix of the import aliases the CLI generators write: the `@` in
166
176
  * `@models/User.js`, `@serializers/UserSerializer.js` and
167
- * `@spec/factories/UserFactory.js`. Set with
168
- * `dreamApp.set('importAliasPrefix', '#')` to have them write
177
+ * `@spec/factories/UserFactory.js`. Set it to `#` to have them write
169
178
  * `#models/User.js` and so on, which Node resolves as subpath imports
170
179
  * declared under `imports` in the app's package.json.
171
180
  *
181
+ * In a Psychic app, set it in conf/app.ts with
182
+ * `psy.set('importAliasPrefix', '#')`. Psychic forwards it here, and a
183
+ * different value set in conf/dream.ts throws at boot. In a Dream-only app,
184
+ * set it in conf/dream.ts with `dreamApp.set('importAliasPrefix', '#')`.
185
+ *
172
186
  * Defaults to `@`. The default becomes `#` in Dream 3; an app that wants
173
- * to keep `@` should set it explicitly with
174
- * `dreamApp.set('importAliasPrefix', '@')`.
175
- *
176
- * Psychic's resource controller-spec generator still writes its
177
- * `@spec/unit/helpers/authentication.js` import with a literal `@` until
178
- * Psychic reads this setting (planned for 3.17.0), so a Psychic app should
179
- * keep its `@spec` alias, or wait for that release, before switching to
180
- * `#` only.
187
+ * to keep `@` should set it to `@` explicitly.
181
188
  */
182
189
  get importAliasPrefix(): "@" | "#";
183
190
  /**
@@ -114,9 +114,13 @@ declare const ops: {
114
114
  *
115
115
  * **Array columns:** passing an array means literal array equality — the
116
116
  * whole array is bound as a single parameter, so the column must match
117
- * element-for-element, in order. This is the opt-in counterpart to a bare
118
- * array in a where clause (`Post.where({ tags: ['a', 'b'] })`), which means
119
- * `IN`, and to `ops.any`, which tests for containment of a single element.
117
+ * element-for-element, in order. The plain value form of a where clause
118
+ * targets regular (scalar) columns, so comparing an array column against an
119
+ * array value goes through `ops`: a flat list against an array column
120
+ * (`Post.where({ tags: ['a', 'b'] })`) is a compile error. A list of whole
121
+ * arrays (`Post.where({ tags: [['a', 'b'], ['c']] })`) means `IN`, matching
122
+ * rows whose column equals any one of them, and `ops.any` tests for
123
+ * containment of a single element.
120
124
  * Element types are constrained by the column, so an enum array column
121
125
  * rejects a string that is not a member of its enum.
122
126
  *
@@ -9,18 +9,24 @@ import DreamSerializerBuilder from './builders/DreamSerializerBuilder.js';
9
9
  * DreamSerializer(User, user).attribute('email').rendersMany('posts')
10
10
  * ```
11
11
  *
12
- * A serializer must not read its data while being built: what it declares may not
13
- * depend on its data. Dream and Psychic build it without data to read its shape (the
14
- * OpenAPI schema, and the keys a flattened association or `customAttribute` that uses
15
- * it renders as `null` where its value does not supply them), so a serializer that
16
- * reads its data while being built throws when a flattened association or
17
- * `customAttribute` that uses it is rendered. Read the data inside a `customAttribute`
18
- * callback, which runs only when the serializer renders, not while it is built.
12
+ * A serializer must not read its data or its passthrough data while being built: what it
13
+ * declares (which keys, under which names, and which associations it renders) may not
14
+ * depend on either. Dream and Psychic build it without data to read its shape (the OpenAPI
15
+ * schema, the associations `preloadFor` loads, and the keys a flattened association or
16
+ * `customAttribute` that uses it renders as `null` where its value does not supply them),
17
+ * and without passthrough data when registering it, preloading and generating OpenAPI. A
18
+ * serializer that reads its data while being built throws when a flattened association or
19
+ * `customAttribute` that uses it is rendered; one that reads its passthrough data is never
20
+ * registered, or renders keys and associations its OpenAPI schema and `preloadFor` do not
21
+ * describe. Read either inside a `customAttribute` callback, which runs only when the
22
+ * serializer renders, not while it is built, and hand passthrough data on to the
23
+ * serializers it renders.
19
24
  *
20
25
  * @param dreamClass - The Dream model class the serializer renders
21
26
  * @param data - The Dream instance to render
22
- * @param passthroughData - Data available to this serializer and passed down to the serializers
23
- * it renders
27
+ * @param passthroughData - Data available to this serializer's callbacks when it renders,
28
+ * and passed down to the serializers it renders. It must not decide what the serializer
29
+ * declares.
24
30
  * @returns The serializer builder for method chaining
25
31
  */
26
32
  export default function DreamSerializer<DreamClass extends typeof Dream, DataType extends Dream | null, PassthroughDataType extends object | undefined = undefined>(dreamClass: DreamClass, data: DataType, passthroughData?: PassthroughDataType): DreamSerializerBuilder<DreamClass, DataType, PassthroughDataType, Exclude<DataType, null>>;
@@ -8,17 +8,23 @@ import ObjectSerializerBuilder from './builders/ObjectSerializerBuilder.js';
8
8
  * ObjectSerializer(address).attribute('city', { openapi: 'string' })
9
9
  * ```
10
10
  *
11
- * A serializer must not read its data while being built: what it declares may not
12
- * depend on its data. Dream and Psychic build it without data to read its shape (the
13
- * OpenAPI schema, and the keys a flattened association or `customAttribute` that uses
14
- * it renders as `null` where its value does not supply them), so a serializer that
15
- * reads its data while being built throws when a flattened association or
16
- * `customAttribute` that uses it is rendered. Read the data inside a `customAttribute`
17
- * callback, which runs only when the serializer renders, not while it is built.
11
+ * A serializer must not read its data or its passthrough data while being built: what it
12
+ * declares (which keys, under which names, and which associations it renders) may not
13
+ * depend on either. Dream and Psychic build it without data to read its shape (the OpenAPI
14
+ * schema, the associations `preloadFor` loads, and the keys a flattened association or
15
+ * `customAttribute` that uses it renders as `null` where its value does not supply them),
16
+ * and without passthrough data when registering it, preloading and generating OpenAPI. A
17
+ * serializer that reads its data while being built throws when a flattened association or
18
+ * `customAttribute` that uses it is rendered; one that reads its passthrough data is never
19
+ * registered, or renders keys and associations its OpenAPI schema and `preloadFor` do not
20
+ * describe. Read either inside a `customAttribute` callback, which runs only when the
21
+ * serializer renders, not while it is built, and hand passthrough data on to the
22
+ * serializers it renders.
18
23
  *
19
24
  * @param data - The object to render
20
- * @param passthroughData - Data available to this serializer and passed down to the serializers
21
- * it renders
25
+ * @param passthroughData - Data available to this serializer's callbacks when it renders,
26
+ * and passed down to the serializers it renders. It must not decide what the serializer
27
+ * declares.
22
28
  * @returns The serializer builder for method chaining
23
29
  */
24
30
  export default function ObjectSerializer<DataType extends object | null, PassthroughDataType extends object | undefined = undefined>(data: DataType, passthroughData?: PassthroughDataType): ObjectSerializerBuilder<DataType, PassthroughDataType, Exclude<DataType, null>>;
@@ -2,7 +2,6 @@ import { OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes } from '../.
2
2
  import { DreamModelSerializerType, SerializerCasing, SimpleObjectSerializerType } from '../../types/serializer.js';
3
3
  export interface NullFlattenedSerializerKeysOptions {
4
4
  casing?: SerializerCasing;
5
- passthroughData?: object;
6
5
  }
7
6
  /**
8
7
  * The keys a flattened `rendersOne` always adds to the parent's payload, returned as an object
@@ -32,8 +31,9 @@ export interface NullFlattenedSerializerKeysOptions {
32
31
  * flattens itself, adds nothing, so the walk always terminates; one reached again along another
33
32
  * path is walked again, so each path adds its keys and their requirements.
34
33
  *
35
- * `passthroughData` is handed to each serializer as it is built, as when rendering; outside a
36
- * render it may be left out.
34
+ * Each serializer is built with empty passthrough data, as Psychic's OpenAPI generation builds it,
35
+ * so the keys are the same whatever passthrough data a render carries: what a serializer declares
36
+ * must not depend on its passthrough data.
37
37
  */
38
38
  export declare function nullFlattenedSerializerKeys(serializers: (DreamModelSerializerType | SimpleObjectSerializerType)[], options?: NullFlattenedSerializerKeysOptions): Record<string, null>;
39
39
  /**
@@ -25,23 +25,25 @@ export type PassthroughOnClause<PassthroughColumns extends string[]> = Partial<R
25
25
  type DreamSelectable<DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<{
26
26
  [ColumnName in keyof DB[TableName]]: NonKyselySupportedSupplementalWhereClauseValues<DB, Schema, TableName, ColumnName>;
27
27
  }>;
28
- type NonKyselySupportedSupplementalWhereClauseValues<DB, Schema, TableName, Column, ModelPropertyType = ModelColumnType<Schema, TableName, Column>, ColumnType = TableColumnType<Schema, TableName, Column>, EnumTypeArray extends string[] | null = TableColumnEnumTypeArray<Schema, TableName, Column>, IsArrayColumn = TableColumnIsArray<Schema, TableName, Column>, PermanentOpsValTypes = null | readonly [], ArrayElementType = ModelPropertyType extends readonly (infer ElementType)[] ? ElementType : never, ArrayOpsValType = readonly ArrayElementType[] | PermanentOpsValTypes | RawBuilder<unknown>, OpsValType = IsArrayColumn extends true ? ArrayElementType | PermanentOpsValTypes : EnumTypeArray extends null ? ColumnType extends 'bigint' ? TypesAllowedForBigintAgainstTheDb | PermanentOpsValTypes : ModelPropertyType extends DateTime | CalendarDate ? DateTime | CalendarDate | null : ModelPropertyType extends ClockTime ? ClockTime | null : ModelPropertyType extends ClockTimeTz ? ClockTimeTz | null : ModelPropertyType extends number | string ? ModelPropertyType | PermanentOpsValTypes : never : EnumTypeArray extends string[] ? EnumTypeArray[number] | PermanentOpsValTypes : never, ResolvedOpsValType = OpsValType | RawBuilder<unknown>, PartialTypes = IsArrayColumn extends true ? (EnumTypeArray extends string[] ? EnumTypeArray : never) | OpsStatement<'=' | '!=' | '<>', ArrayOpsValType, any> | OpsStatement<KyselyComparisonOperatorExpression, PermanentOpsValTypes | RawBuilder<unknown>, any> : EnumTypeArray extends null ? ModelPropertyType extends DateTime ? Range<DateTime | CalendarDate> | Range<null, DateTime | CalendarDate> | (() => Range<DateTime | CalendarDate>) | (() => Range<null, DateTime | CalendarDate>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends ClockTime ? Range<ClockTime> | Range<null, ClockTime> | (() => Range<ClockTime>) | (() => Range<null, ClockTime>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends ClockTimeTz ? Range<ClockTimeTz> | Range<null, ClockTimeTz> | (() => Range<ClockTimeTz>) | (() => Range<null, ClockTimeTz>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends CalendarDate ? Range<DateTime | CalendarDate> | Range<null, DateTime | CalendarDate> | (() => Range<DateTime | CalendarDate>) | (() => Range<null, DateTime | CalendarDate>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType> : ColumnType extends 'bigint' ? Range<TypesAllowedForBigintAgainstTheDb> | Range<null, TypesAllowedForBigintAgainstTheDb> | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends number ? Range<ModelPropertyType> | Range<null, ModelPropertyType> | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends string ? Range<string> | Range<null, string> | OpsStatement<KyselyComparisonOperatorExpression, string, any> | OpsStatement<TrigramOperator, ResolvedOpsValType, ExtraSimilarityArgs> : never : EnumTypeArray extends string[] ? EnumTypeArray | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : never> = PartialTypes extends never ? OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> | CurriedOpsStatement<any, any, any, ResolvedOpsValType> | SelectQueryBuilder<DB, keyof DB, any> : PartialTypes | CurriedOpsStatement<any, any, any, ResolvedOpsValType> | SelectQueryBuilder<DB, keyof DB, any>;
28
+ type NonKyselySupportedSupplementalWhereClauseValues<DB, Schema, TableName, Column, ModelPropertyType = ModelColumnType<Schema, TableName, Column>, ColumnType = TableColumnType<Schema, TableName, Column>, EnumTypeArray extends string[] | null = TableColumnEnumTypeArray<Schema, TableName, Column>, IsArrayColumn = TableColumnIsArray<Schema, TableName, Column>, PermanentOpsValTypes = null | readonly [], ArrayElementType = ModelPropertyType extends readonly (infer ElementType)[] ? ElementType : never, ArrayOpsValType = readonly ArrayElementType[] | PermanentOpsValTypes | RawBuilder<unknown>, OpsValType = IsArrayColumn extends true ? ArrayElementType | PermanentOpsValTypes : EnumTypeArray extends null ? ColumnType extends 'bigint' ? TypesAllowedForBigintAgainstTheDb | PermanentOpsValTypes : ModelPropertyType extends DateTime | CalendarDate ? DateTime | CalendarDate | null : ModelPropertyType extends ClockTime ? ClockTime | null : ModelPropertyType extends ClockTimeTz ? ClockTimeTz | null : ModelPropertyType extends number | string ? ModelPropertyType | PermanentOpsValTypes : never : EnumTypeArray extends string[] ? EnumTypeArray[number] | PermanentOpsValTypes : never, ResolvedOpsValType = OpsValType | RawBuilder<unknown>, PartialTypes = IsArrayColumn extends true ? OpsStatement<'=' | '!=' | '<>', ArrayOpsValType, any> | OpsStatement<KyselyComparisonOperatorExpression, PermanentOpsValTypes | RawBuilder<unknown>, any> : EnumTypeArray extends null ? ModelPropertyType extends DateTime ? Range<DateTime | CalendarDate> | Range<null, DateTime | CalendarDate> | (() => Range<DateTime | CalendarDate>) | (() => Range<null, DateTime | CalendarDate>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends ClockTime ? Range<ClockTime> | Range<null, ClockTime> | (() => Range<ClockTime>) | (() => Range<null, ClockTime>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends ClockTimeTz ? Range<ClockTimeTz> | Range<null, ClockTimeTz> | (() => Range<ClockTimeTz>) | (() => Range<null, ClockTimeTz>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends CalendarDate ? Range<DateTime | CalendarDate> | Range<null, DateTime | CalendarDate> | (() => Range<DateTime | CalendarDate>) | (() => Range<null, DateTime | CalendarDate>) | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType> : ColumnType extends 'bigint' ? Range<TypesAllowedForBigintAgainstTheDb> | Range<null, TypesAllowedForBigintAgainstTheDb> | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends number ? Range<ModelPropertyType> | Range<null, ModelPropertyType> | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : ModelPropertyType extends string ? Range<string> | Range<null, string> | OpsStatement<KyselyComparisonOperatorExpression, string, any> | OpsStatement<TrigramOperator, ResolvedOpsValType, ExtraSimilarityArgs> : never : EnumTypeArray extends string[] ? EnumTypeArray | OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> : never> = PartialTypes extends never ? OpsStatement<KyselyComparisonOperatorExpression, ResolvedOpsValType, any> | CurriedOpsStatement<any, any, any, ResolvedOpsValType> | SelectQueryBuilder<DB, keyof DB, any> : PartialTypes | CurriedOpsStatement<any, any, any, ResolvedOpsValType> | SelectQueryBuilder<DB, keyof DB, any>;
29
29
  export type WhereStatementForDreamClass<DreamClass extends typeof Dream> = WhereStatement<InstanceType<DreamClass>>;
30
30
  export type WhereStatementForDream<DreamInstance extends Dream> = WhereStatement<DreamInstance>;
31
31
  type AssociationNameToDotReferencedColumns<DB, TableName extends keyof DB, AssociationName> = `${AssociationName & string}.${TableColumnNames<DB, TableName>}`;
32
32
  export type ColumnNamesAccountingForJoinedAssociations<JoinedAssociations extends Readonly<JoinedAssociation[]>, DB, RootTableName extends keyof DB, RootTableAlias extends string> = JoinedAssociations['length'] extends 0 ? TableColumnNames<DB, RootTableName> : TableColumnNames<DB, RootTableName> | JoinedAssociationColumnNames<JoinedAssociations, DB, AssociationNameToDotReferencedColumns<DB, RootTableName & keyof DB, RootTableAlias>>;
33
33
  type JoinedAssociationColumnNames<JoinedAssociations extends Readonly<JoinedAssociation[]>, DB, AllColumnNames, Depth extends number = 0, CurrentJoinedAssociation = Readonly<JoinedAssociations[0]>, NextTableName = CurrentJoinedAssociation extends Readonly<JoinedAssociation> ? CurrentJoinedAssociation['table'] : never, NextAssociationName = CurrentJoinedAssociation extends Readonly<JoinedAssociation> ? CurrentJoinedAssociation['alias'] : never> = JoinedAssociations['length'] extends 0 ? AllColumnNames : Depth extends MAX_JOINED_TABLES_DEPTH ? AllColumnNames : JoinedAssociationColumnNames<ReadonlyTail<JoinedAssociations>, DB, AllColumnNames | AssociationNameToDotReferencedColumns<DB, NextTableName & keyof DB, NextAssociationName>, Inc<Depth>>;
34
- type Whereable<R> = {
35
- [K in keyof Selectable<R>]?: Selectable<R>[K] | Selectable<R>[K][];
34
+ type Whereable<DB, Schema, TableName extends keyof DB, R = DB[TableName]> = {
35
+ [K in keyof Selectable<R>]?: TableColumnIsArray<Schema, TableName, K> extends true ? Extract<Selectable<R>[K], null> | Selectable<R>[K][] : Selectable<R>[K] | Selectable<R>[K][];
36
36
  };
37
37
  type WhereableAssociatedModelParam<I extends Dream> = {
38
38
  [K in keyof AssociatedModelParam<I>]: AssociatedModelParam<I>[K] | NonNullable<AssociatedModelParam<I>[K]>[];
39
39
  };
40
40
  export type WhereStatement<I extends Dream> = InternalWhereStatement<I, I['DB'], I['schema'], I['table']>;
41
- export type InternalWhereStatement<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Whereable<DB[TableName]> | DreamSelectable<DB, Schema, TableName> | WhereableAssociatedModelParam<I>>>;
41
+ export type InternalWhereStatement<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Whereable<DB, Schema, TableName> | DreamSelectable<DB, Schema, TableName> | WhereableAssociatedModelParam<I>>>;
42
42
  export type OnStatementForAssociation<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB, RequiredOnClauseKeysForThisAssociation, OnStatement extends InternalWhereStatement<I, DB, Schema, TableName> = InternalWhereStatement<I, DB, Schema, TableName>> = RequiredOnClauseKeysForThisAssociation extends null ? InternalWhereStatement<I, DB, Schema, TableName> : RequiredOnClauseKeysForThisAssociation extends string[] ? Required<Pick<OnStatement, RequiredOnClauseKeysForThisAssociation[number] & keyof OnStatement>> & Partial<Omit<OnStatement, RequiredOnClauseKeysForThisAssociation[number] & keyof OnStatement>> : never;
43
43
  export type OnStatementForSpecificColumns<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB, Columns extends string[], OnStatement extends InternalWhereStatement<I, DB, Schema, TableName> = InternalWhereStatement<I, DB, Schema, TableName>> = Pick<OnStatement, Columns[number] & keyof OnStatement>;
44
- type OnStatementForAssociationDefinition<DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Partial<Selectable<DB[TableName]>> | Partial<{
44
+ type OnStatementForAssociationDefinition<DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Partial<{
45
+ [K in keyof Selectable<DB[TableName]>]: TableColumnIsArray<Schema, TableName, K> extends true ? Extract<Selectable<DB[TableName]>[K], null> | readonly [] : Selectable<DB[TableName]>[K];
46
+ }> | Partial<{
45
47
  [ColumnName in keyof DB[TableName]]: NonKyselySupportedSupplementalWhereClauseValues<DB, Schema, TableName, ColumnName> | typeof DreamConst.passthrough | typeof DreamConst.required;
46
48
  }>>>;
47
49
  export type SelfOnStatement<BaseInstance extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<Record<keyof DB[TableName], DreamColumnNames<BaseInstance>>>;
@@ -134,7 +134,6 @@ type NonKyselySupportedSupplementalWhereClauseValues<
134
134
  // a database error.
135
135
  PartialTypes = IsArrayColumn extends true
136
136
  ?
137
- | (EnumTypeArray extends string[] ? EnumTypeArray : never)
138
137
  | OpsStatement<'=' | '!=' | '<>', ArrayOpsValType, any>
139
138
  | OpsStatement<KyselyComparisonOperatorExpression, PermanentOpsValTypes | RawBuilder<unknown>, any>
140
139
  : EnumTypeArray extends null
@@ -248,8 +247,22 @@ type JoinedAssociationColumnNames<
248
247
  Inc<Depth>
249
248
  >
250
249
 
251
- type Whereable<R> = {
252
- [K in keyof Selectable<R>]?: Selectable<R>[K] | Selectable<R>[K][]
250
+ // The plain value form of a where clause targets regular (scalar) columns: a
251
+ // value means `=`, a list of values means `IN`, and `null` means `IS NULL`.
252
+ // Comparing an array column against an array value goes through `ops`, e.g.
253
+ // `Post.where({ tags: ops.equal(['a', 'b']) })`. An array column's plain value
254
+ // is therefore limited to `null` and a list whose entries are each a whole
255
+ // array or `null` (an `IN` of whole arrays, where `[]` matches nothing). A flat
256
+ // list of elements against an array column, e.g.
257
+ // `Post.where({ tags: ['a', 'b'] })`, is a compile error, since it is rendered
258
+ // as the value list `IN ('a', 'b')`, which PostgreSQL rejects for an array
259
+ // column unless every element is itself an array literal such as `'{a}'`.
260
+ // Array-ness comes from the schema (`TableColumnIsArray`), not from the
261
+ // Kysely column type, which also admits arrays for jsonb columns.
262
+ type Whereable<DB, Schema, TableName extends keyof DB, R = DB[TableName]> = {
263
+ [K in keyof Selectable<R>]?: TableColumnIsArray<Schema, TableName, K> extends true
264
+ ? Extract<Selectable<R>[K], null> | Selectable<R>[K][]
265
+ : Selectable<R>[K] | Selectable<R>[K][]
253
266
  }
254
267
 
255
268
  // For filtering by BelongsTo model instance(s) in a where/and statement, e.g.
@@ -270,7 +283,9 @@ export type InternalWhereStatement<
270
283
  TableName extends AssociationTableNames<DB, Schema> & keyof DB,
271
284
  > = Partial<
272
285
  MergeUnionOfRecordTypes<
273
- Whereable<DB[TableName]> | DreamSelectable<DB, Schema, TableName> | WhereableAssociatedModelParam<I>
286
+ | Whereable<DB, Schema, TableName>
287
+ | DreamSelectable<DB, Schema, TableName>
288
+ | WhereableAssociatedModelParam<I>
274
289
  >
275
290
  >
276
291
 
@@ -314,7 +329,14 @@ type OnStatementForAssociationDefinition<
314
329
  TableName extends AssociationTableNames<DB, Schema> & keyof DB,
315
330
  > = Partial<
316
331
  MergeUnionOfRecordTypes<
317
- | Partial<Selectable<DB[TableName]>>
332
+ // As in `Whereable`, the plain value form targets regular (scalar) columns.
333
+ // An array column accepts only `null` and `[]` as a plain value here;
334
+ // every other comparison against it goes through `ops`.
335
+ | Partial<{
336
+ [K in keyof Selectable<DB[TableName]>]: TableColumnIsArray<Schema, TableName, K> extends true
337
+ ? Extract<Selectable<DB[TableName]>[K], null> | readonly []
338
+ : Selectable<DB[TableName]>[K]
339
+ }>
318
340
  | Partial<{
319
341
  [ColumnName in keyof DB[TableName]]:
320
342
  | NonKyselySupportedSupplementalWhereClauseValues<DB, Schema, TableName, ColumnName>