@rvoh/dream 2.7.0 → 2.8.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 (182) hide show
  1. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +7 -2
  2. package/dist/cjs/src/helpers/cli/generateSerializerContent.js +53 -50
  3. package/dist/esm/src/helpers/cli/generateMigrationContent.js +7 -2
  4. package/dist/esm/src/helpers/cli/generateSerializerContent.js +53 -50
  5. package/docs/classes/db.DreamMigrationHelpers.html +9 -9
  6. package/docs/classes/db.KyselyQueryDriver.html +32 -32
  7. package/docs/classes/db.PostgresQueryDriver.html +33 -33
  8. package/docs/classes/db.QueryDriverBase.html +31 -31
  9. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  10. package/docs/classes/errors.ColumnOverflow.html +3 -3
  11. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  12. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  13. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  14. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  15. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  16. package/docs/classes/errors.InvalidClockTime.html +2 -2
  17. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  18. package/docs/classes/errors.InvalidDateTime.html +2 -2
  19. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  20. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  21. package/docs/classes/errors.NotNullViolation.html +3 -3
  22. package/docs/classes/errors.RecordNotFound.html +3 -3
  23. package/docs/classes/errors.ValidationError.html +3 -3
  24. package/docs/classes/index.CalendarDate.html +33 -33
  25. package/docs/classes/index.ClockTime.html +32 -32
  26. package/docs/classes/index.ClockTimeTz.html +35 -35
  27. package/docs/classes/index.DateTime.html +86 -86
  28. package/docs/classes/index.Decorators.html +19 -19
  29. package/docs/classes/index.Dream.html +118 -118
  30. package/docs/classes/index.DreamApp.html +5 -5
  31. package/docs/classes/index.DreamTransaction.html +2 -2
  32. package/docs/classes/index.Env.html +2 -2
  33. package/docs/classes/index.Query.html +56 -56
  34. package/docs/classes/system.CliFileWriter.html +4 -4
  35. package/docs/classes/system.DreamBin.html +2 -2
  36. package/docs/classes/system.DreamCLI.html +6 -6
  37. package/docs/classes/system.DreamImporter.html +2 -2
  38. package/docs/classes/system.DreamLogos.html +2 -2
  39. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  40. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  41. package/docs/classes/system.PathHelpers.html +3 -3
  42. package/docs/classes/utils.Encrypt.html +2 -2
  43. package/docs/classes/utils.Range.html +2 -2
  44. package/docs/functions/db.closeAllDbConnections.html +1 -1
  45. package/docs/functions/db.dreamDbConnections.html +1 -1
  46. package/docs/functions/db.untypedDb.html +1 -1
  47. package/docs/functions/db.validateColumn.html +1 -1
  48. package/docs/functions/db.validateTable.html +1 -1
  49. package/docs/functions/errors.pgErrorType.html +1 -1
  50. package/docs/functions/index.DreamSerializer.html +1 -1
  51. package/docs/functions/index.ObjectSerializer.html +1 -1
  52. package/docs/functions/index.ReplicaSafe.html +1 -1
  53. package/docs/functions/index.STI.html +1 -1
  54. package/docs/functions/index.SoftDelete.html +1 -1
  55. package/docs/functions/utils.camelize.html +1 -1
  56. package/docs/functions/utils.capitalize.html +1 -1
  57. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  58. package/docs/functions/utils.compact.html +1 -1
  59. package/docs/functions/utils.groupBy.html +1 -1
  60. package/docs/functions/utils.hyphenize.html +1 -1
  61. package/docs/functions/utils.intersection.html +1 -1
  62. package/docs/functions/utils.isEmpty.html +1 -1
  63. package/docs/functions/utils.normalizeUnicode.html +1 -1
  64. package/docs/functions/utils.pascalize.html +1 -1
  65. package/docs/functions/utils.percent.html +1 -1
  66. package/docs/functions/utils.range.html +1 -1
  67. package/docs/functions/utils.round.html +1 -1
  68. package/docs/functions/utils.sanitizeString.html +1 -1
  69. package/docs/functions/utils.snakeify.html +1 -1
  70. package/docs/functions/utils.sort.html +1 -1
  71. package/docs/functions/utils.sortBy.html +1 -1
  72. package/docs/functions/utils.sortObjectByKey.html +1 -1
  73. package/docs/functions/utils.sortObjectByValue.html +1 -1
  74. package/docs/functions/utils.uncapitalize.html +1 -1
  75. package/docs/functions/utils.uniq.html +1 -1
  76. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  77. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  78. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  79. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  80. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  81. package/docs/interfaces/types.DecoratorContext.html +2 -2
  82. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  83. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  84. package/docs/interfaces/types.DurationObject.html +2 -2
  85. package/docs/interfaces/types.EncryptOptions.html +2 -2
  86. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  87. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  88. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  89. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  90. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  91. package/docs/types/openapi.OpenapiFormats.html +1 -1
  92. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  93. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  94. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  95. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  96. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  97. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  98. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  99. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  100. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  101. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  102. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  103. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  104. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  105. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  106. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  107. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  108. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  109. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  110. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  111. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  112. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  113. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  114. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  115. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  116. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  117. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  118. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  119. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  120. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  121. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  122. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  123. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  124. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  125. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  126. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  127. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  128. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  129. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  130. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  131. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  132. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  133. package/docs/types/types.CalendarDateObject.html +1 -1
  134. package/docs/types/types.Camelized.html +1 -1
  135. package/docs/types/types.ClockTimeObject.html +1 -1
  136. package/docs/types/types.DbConnectionType.html +1 -1
  137. package/docs/types/types.DbTypes.html +1 -1
  138. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  139. package/docs/types/types.DreamAttributes.html +1 -1
  140. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  141. package/docs/types/types.DreamClassColumn.html +1 -1
  142. package/docs/types/types.DreamColumn.html +1 -1
  143. package/docs/types/types.DreamColumnNames.html +1 -1
  144. package/docs/types/types.DreamLogLevel.html +1 -1
  145. package/docs/types/types.DreamLogger.html +2 -2
  146. package/docs/types/types.DreamModelSerializerType.html +1 -1
  147. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  148. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  149. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  150. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  151. package/docs/types/types.DreamSerializable.html +1 -1
  152. package/docs/types/types.DreamSerializableArray.html +1 -1
  153. package/docs/types/types.DreamSerializerKey.html +1 -1
  154. package/docs/types/types.DreamSerializers.html +1 -1
  155. package/docs/types/types.DreamVirtualColumns.html +1 -1
  156. package/docs/types/types.DurationUnit.html +1 -1
  157. package/docs/types/types.EncryptAlgorithm.html +1 -1
  158. package/docs/types/types.HasManyStatement.html +1 -1
  159. package/docs/types/types.HasOneStatement.html +1 -1
  160. package/docs/types/types.Hyphenized.html +1 -1
  161. package/docs/types/types.Pascalized.html +1 -1
  162. package/docs/types/types.PrimaryKeyType.html +1 -1
  163. package/docs/types/types.RoundingPrecision.html +1 -1
  164. package/docs/types/types.SerializerCasing.html +1 -1
  165. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  166. package/docs/types/types.Snakeified.html +1 -1
  167. package/docs/types/types.StrictInterface.html +1 -1
  168. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  169. package/docs/types/types.UpdateableProperties.html +1 -1
  170. package/docs/types/types.ValidationType.html +1 -1
  171. package/docs/types/types.ViewModel.html +2 -2
  172. package/docs/types/types.ViewModelClass.html +1 -1
  173. package/docs/types/types.WeekdayName.html +1 -1
  174. package/docs/types/types.WhereStatementForDream.html +1 -1
  175. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  176. package/docs/variables/index.DreamConst.html +1 -1
  177. package/docs/variables/index.ops.html +1 -1
  178. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  179. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  180. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  181. package/docs/variables/system.primaryKeyTypes.html +1 -1
  182. package/package.json +1 -1
@@ -49,7 +49,12 @@ export default function generateMigrationContent({ connectionName = 'default', t
49
49
  if (attributeType === 'citext')
50
50
  requireCitextExtension = true;
51
51
  const arrayAttribute = /\[\]$/.test(attributeType);
52
- const omitInlineNonNull = userWantsThisOptional || (!!stiChildClassName && !arrayAttribute);
52
+ // Booleans always have a sensible non-null default (`false`), so in an
53
+ // STI child migration we keep the straightforward `.notNull().defaultTo(false)`
54
+ // column definition and skip the per-type check constraint — same as
55
+ // arrays, which already default to `'{}'`.
56
+ const isBooleanColumn = processedAttrType === 'boolean';
57
+ const omitInlineNonNull = userWantsThisOptional || (!!stiChildClassName && !arrayAttribute && !isBooleanColumn);
53
58
  if (nonStandardAttributeName === undefined)
54
59
  return acc;
55
60
  let attributeName = snakeify(nonStandardAttributeName);
@@ -115,7 +120,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
115
120
  .execute()`);
116
121
  indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
117
122
  }
118
- if (stiChildClassName && !userWantsThisOptional && !arrayAttribute) {
123
+ if (stiChildClassName && !userWantsThisOptional && !arrayAttribute && !isBooleanColumn) {
119
124
  checkConstraints.push(`
120
125
 
121
126
  await db.schema
@@ -1,4 +1,3 @@
1
- import serializerNameFromFullyQualifiedModelName from '../../serializer/helpers/serializerNameFromFullyQualifiedModelName.js';
2
1
  import camelize from '../camelize.js';
3
2
  import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
4
3
  import absoluteDreamPath from '../path/absoluteDreamPath.js';
@@ -9,9 +8,18 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
9
8
  const additionalImports = [];
10
9
  const dreamImports = [];
11
10
  const isSTI = !!fullyQualifiedParentName;
11
+ // Variants that should be emitted in this file. Each variant generates a
12
+ // matching summary + default serializer pair; STI children import the
13
+ // corresponding variant from the parent module so the inheritance chain
14
+ // stays within the same variant (admin → admin, internal → internal).
15
+ const variantSuffixes = [''];
16
+ if (includeAdminSerializers)
17
+ variantSuffixes.push('Admin');
18
+ if (includeInternalSerializers)
19
+ variantSuffixes.push('Internal');
12
20
  if (isSTI) {
13
21
  fullyQualifiedParentName = standardizeFullyQualifiedModelName(fullyQualifiedParentName);
14
- additionalImports.push(importStatementForSerializer(fullyQualifiedModelName, fullyQualifiedParentName));
22
+ additionalImports.push(importStatementForSerializer(fullyQualifiedModelName, fullyQualifiedParentName, variantSuffixes));
15
23
  }
16
24
  else {
17
25
  dreamImports.push('DreamSerializer');
@@ -23,58 +31,50 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
23
31
  : `(${modelInstanceName}: ${modelClassName})`;
24
32
  const modelSerializerArgs = `${modelInstanceName}`;
25
33
  const dreamSerializerArgs = `${stiBaseSerializer ? `StiChildClass ?? ${modelClassName}` : modelClassName}, ${modelInstanceName}`;
26
- const serializerClassName = serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName));
27
- const summarySerializerClassName = serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName), 'summary');
28
- const defaultSerializerExtends = isSTI
29
- ? `${serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName))}(${modelClassName}, ${modelSerializerArgs})`
30
- : `${summarySerializerClassName}(${stiBaseSerializer ? 'StiChildClass, ' : ''}${modelSerializerArgs})`;
31
- const summarySerializerExtends = isSTI
32
- ? `${serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName), 'summary')}(${modelClassName}, ${modelSerializerArgs})`
33
- : `DreamSerializer(${dreamSerializerArgs})`;
34
- // Admin variants
35
- const adminSerializerClassName = serializerClassName.replace(/Serializer$/, 'AdminSerializer');
36
- const adminSummarySerializerClassName = summarySerializerClassName.replace(/SummarySerializer$/, 'AdminSummarySerializer');
37
- // end:Admin variants
38
- // Internal variants
39
- const internalSerializerClassName = serializerClassName.replace(/Serializer$/, 'InternalSerializer');
40
- const internalSummarySerializerClassName = summarySerializerClassName.replace(/SummarySerializer$/, 'InternalSummarySerializer');
41
- // end:Internal variants
34
+ const localSerializerBase = fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName);
35
+ const parentSerializerBase = isSTI
36
+ ? fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName)
37
+ : '';
42
38
  const additionalModelImports = [];
43
39
  const dreamImport = dreamImports.length
44
40
  ? `import { ${uniq(dreamImports).join(', ')} } from '@rvoh/dream'\n`
45
41
  : '';
46
42
  const additionalImportsStr = uniq(additionalImports).join('');
47
- const summarySerializer = `export const ${summarySerializerClassName} = ${modelSerializerSignature} =>
48
- ${summarySerializerExtends}${isSTI ? '' : `\n .attribute('id')`}`;
49
- const defaultSerializer = `export const ${serializerClassName} = ${modelSerializerSignature} =>
50
- ${defaultSerializerExtends}${columnsWithTypes
51
- .map(attr => {
52
- const [name, type] = attr.split(':');
53
- if (name === undefined)
54
- return '';
55
- if (['belongsto', 'hasone', 'hasmany'].includes(camelize(type)?.toLowerCase()))
56
- return '';
57
- return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
58
- })
59
- .join('')}`;
43
+ const buildSerializerPair = (variantSuffix) => {
44
+ const summaryName = variantSerializerClassName(localSerializerBase, variantSuffix, 'summary');
45
+ const defaultName = variantSerializerClassName(localSerializerBase, variantSuffix, 'default');
46
+ const summaryExtends = isSTI
47
+ ? `${variantSerializerClassName(parentSerializerBase, variantSuffix, 'summary')}(${modelClassName}, ${modelSerializerArgs})`
48
+ : `DreamSerializer(${dreamSerializerArgs})`;
49
+ const defaultExtends = isSTI
50
+ ? `${variantSerializerClassName(parentSerializerBase, variantSuffix, 'default')}(${modelClassName}, ${modelSerializerArgs})`
51
+ : `${summaryName}(${stiBaseSerializer ? 'StiChildClass, ' : ''}${modelSerializerArgs})`;
52
+ const summary = `export const ${summaryName} = ${modelSerializerSignature} =>
53
+ ${summaryExtends}${isSTI ? '' : `\n .attribute('id')`}`;
54
+ const defaultBody = columnsWithTypes
55
+ .map(attr => {
56
+ const [name, type] = attr.split(':');
57
+ if (name === undefined)
58
+ return '';
59
+ if (['belongsto', 'hasone', 'hasmany'].includes(camelize(type)?.toLowerCase()))
60
+ return '';
61
+ return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
62
+ })
63
+ .join('');
64
+ const def = `export const ${defaultName} = ${modelSerializerSignature} =>
65
+ ${defaultExtends}${defaultBody}`;
66
+ return `${summary}\n\n${def}`;
67
+ };
68
+ const serializerBlocks = variantSuffixes.map(buildSerializerPair).join('\n\n');
60
69
  return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
61
- ${summarySerializer}
62
-
63
- ${defaultSerializer}${!includeAdminSerializers
64
- ? ''
65
- : `
66
-
67
- ${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerClassName)}
68
-
69
- ${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}${!includeInternalSerializers
70
- ? ''
71
- : `
72
-
73
- ${summarySerializer.replace(summarySerializerClassName, internalSummarySerializerClassName)}
74
-
75
- ${defaultSerializer.replace(serializerClassName, internalSerializerClassName).replace(summarySerializerClassName, internalSummarySerializerClassName)}`}
70
+ ${serializerBlocks}
76
71
  `;
77
72
  }
73
+ function variantSerializerClassName(serializerBase, variantSuffix, kind) {
74
+ return kind === 'summary'
75
+ ? `${serializerBase}${variantSuffix}SummarySerializer`
76
+ : `${serializerBase}${variantSuffix}Serializer`;
77
+ }
78
78
  function attribute(modelClassName, name, type, attr, stiBaseSerializer) {
79
79
  if (name === 'type' && stiBaseSerializer) {
80
80
  return `.attribute('type', { openapi: { type: 'string', enum: [(StiChildClass ?? ${modelClassName}).sanitizedName] } })`;
@@ -97,11 +97,14 @@ function attributeOptionsSpecifier(type, attr) {
97
97
  return '';
98
98
  }
99
99
  }
100
- function importStatementForSerializer(originModelName, destinationModelName) {
101
- const defaultSerializer = globalClassNameFromFullyQualifiedModelName(serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(destinationModelName)));
102
- const summarySerializer = globalClassNameFromFullyQualifiedModelName(serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(destinationModelName), 'summary'));
100
+ function importStatementForSerializer(originModelName, destinationModelName, variantSuffixes) {
101
+ const base = fullyQualifiedModelNameToSerializerBaseName(destinationModelName);
102
+ const names = variantSuffixes.flatMap(suffix => [
103
+ globalClassNameFromFullyQualifiedModelName(variantSerializerClassName(base, suffix, 'default')),
104
+ globalClassNameFromFullyQualifiedModelName(variantSerializerClassName(base, suffix, 'summary')),
105
+ ]);
103
106
  const importFrom = absoluteDreamPath('serializers', destinationModelName);
104
- return `import { ${defaultSerializer}, ${summarySerializer} } from '${importFrom}'\n`;
107
+ return `import { ${names.join(', ')} } from '${importFrom}'\n`;
105
108
  }
106
109
  function importStatementForModel(modelClassName, fullyQualifiedModelName) {
107
110
  const importFrom = absoluteDreamPath('models', fullyQualifiedModelName);
@@ -49,7 +49,12 @@ export default function generateMigrationContent({ connectionName = 'default', t
49
49
  if (attributeType === 'citext')
50
50
  requireCitextExtension = true;
51
51
  const arrayAttribute = /\[\]$/.test(attributeType);
52
- const omitInlineNonNull = userWantsThisOptional || (!!stiChildClassName && !arrayAttribute);
52
+ // Booleans always have a sensible non-null default (`false`), so in an
53
+ // STI child migration we keep the straightforward `.notNull().defaultTo(false)`
54
+ // column definition and skip the per-type check constraint — same as
55
+ // arrays, which already default to `'{}'`.
56
+ const isBooleanColumn = processedAttrType === 'boolean';
57
+ const omitInlineNonNull = userWantsThisOptional || (!!stiChildClassName && !arrayAttribute && !isBooleanColumn);
53
58
  if (nonStandardAttributeName === undefined)
54
59
  return acc;
55
60
  let attributeName = snakeify(nonStandardAttributeName);
@@ -115,7 +120,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
115
120
  .execute()`);
116
121
  indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
117
122
  }
118
- if (stiChildClassName && !userWantsThisOptional && !arrayAttribute) {
123
+ if (stiChildClassName && !userWantsThisOptional && !arrayAttribute && !isBooleanColumn) {
119
124
  checkConstraints.push(`
120
125
 
121
126
  await db.schema
@@ -1,4 +1,3 @@
1
- import serializerNameFromFullyQualifiedModelName from '../../serializer/helpers/serializerNameFromFullyQualifiedModelName.js';
2
1
  import camelize from '../camelize.js';
3
2
  import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
4
3
  import absoluteDreamPath from '../path/absoluteDreamPath.js';
@@ -9,9 +8,18 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
9
8
  const additionalImports = [];
10
9
  const dreamImports = [];
11
10
  const isSTI = !!fullyQualifiedParentName;
11
+ // Variants that should be emitted in this file. Each variant generates a
12
+ // matching summary + default serializer pair; STI children import the
13
+ // corresponding variant from the parent module so the inheritance chain
14
+ // stays within the same variant (admin → admin, internal → internal).
15
+ const variantSuffixes = [''];
16
+ if (includeAdminSerializers)
17
+ variantSuffixes.push('Admin');
18
+ if (includeInternalSerializers)
19
+ variantSuffixes.push('Internal');
12
20
  if (isSTI) {
13
21
  fullyQualifiedParentName = standardizeFullyQualifiedModelName(fullyQualifiedParentName);
14
- additionalImports.push(importStatementForSerializer(fullyQualifiedModelName, fullyQualifiedParentName));
22
+ additionalImports.push(importStatementForSerializer(fullyQualifiedModelName, fullyQualifiedParentName, variantSuffixes));
15
23
  }
16
24
  else {
17
25
  dreamImports.push('DreamSerializer');
@@ -23,58 +31,50 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
23
31
  : `(${modelInstanceName}: ${modelClassName})`;
24
32
  const modelSerializerArgs = `${modelInstanceName}`;
25
33
  const dreamSerializerArgs = `${stiBaseSerializer ? `StiChildClass ?? ${modelClassName}` : modelClassName}, ${modelInstanceName}`;
26
- const serializerClassName = serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName));
27
- const summarySerializerClassName = serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName), 'summary');
28
- const defaultSerializerExtends = isSTI
29
- ? `${serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName))}(${modelClassName}, ${modelSerializerArgs})`
30
- : `${summarySerializerClassName}(${stiBaseSerializer ? 'StiChildClass, ' : ''}${modelSerializerArgs})`;
31
- const summarySerializerExtends = isSTI
32
- ? `${serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName), 'summary')}(${modelClassName}, ${modelSerializerArgs})`
33
- : `DreamSerializer(${dreamSerializerArgs})`;
34
- // Admin variants
35
- const adminSerializerClassName = serializerClassName.replace(/Serializer$/, 'AdminSerializer');
36
- const adminSummarySerializerClassName = summarySerializerClassName.replace(/SummarySerializer$/, 'AdminSummarySerializer');
37
- // end:Admin variants
38
- // Internal variants
39
- const internalSerializerClassName = serializerClassName.replace(/Serializer$/, 'InternalSerializer');
40
- const internalSummarySerializerClassName = summarySerializerClassName.replace(/SummarySerializer$/, 'InternalSummarySerializer');
41
- // end:Internal variants
34
+ const localSerializerBase = fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName);
35
+ const parentSerializerBase = isSTI
36
+ ? fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName)
37
+ : '';
42
38
  const additionalModelImports = [];
43
39
  const dreamImport = dreamImports.length
44
40
  ? `import { ${uniq(dreamImports).join(', ')} } from '@rvoh/dream'\n`
45
41
  : '';
46
42
  const additionalImportsStr = uniq(additionalImports).join('');
47
- const summarySerializer = `export const ${summarySerializerClassName} = ${modelSerializerSignature} =>
48
- ${summarySerializerExtends}${isSTI ? '' : `\n .attribute('id')`}`;
49
- const defaultSerializer = `export const ${serializerClassName} = ${modelSerializerSignature} =>
50
- ${defaultSerializerExtends}${columnsWithTypes
51
- .map(attr => {
52
- const [name, type] = attr.split(':');
53
- if (name === undefined)
54
- return '';
55
- if (['belongsto', 'hasone', 'hasmany'].includes(camelize(type)?.toLowerCase()))
56
- return '';
57
- return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
58
- })
59
- .join('')}`;
43
+ const buildSerializerPair = (variantSuffix) => {
44
+ const summaryName = variantSerializerClassName(localSerializerBase, variantSuffix, 'summary');
45
+ const defaultName = variantSerializerClassName(localSerializerBase, variantSuffix, 'default');
46
+ const summaryExtends = isSTI
47
+ ? `${variantSerializerClassName(parentSerializerBase, variantSuffix, 'summary')}(${modelClassName}, ${modelSerializerArgs})`
48
+ : `DreamSerializer(${dreamSerializerArgs})`;
49
+ const defaultExtends = isSTI
50
+ ? `${variantSerializerClassName(parentSerializerBase, variantSuffix, 'default')}(${modelClassName}, ${modelSerializerArgs})`
51
+ : `${summaryName}(${stiBaseSerializer ? 'StiChildClass, ' : ''}${modelSerializerArgs})`;
52
+ const summary = `export const ${summaryName} = ${modelSerializerSignature} =>
53
+ ${summaryExtends}${isSTI ? '' : `\n .attribute('id')`}`;
54
+ const defaultBody = columnsWithTypes
55
+ .map(attr => {
56
+ const [name, type] = attr.split(':');
57
+ if (name === undefined)
58
+ return '';
59
+ if (['belongsto', 'hasone', 'hasmany'].includes(camelize(type)?.toLowerCase()))
60
+ return '';
61
+ return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
62
+ })
63
+ .join('');
64
+ const def = `export const ${defaultName} = ${modelSerializerSignature} =>
65
+ ${defaultExtends}${defaultBody}`;
66
+ return `${summary}\n\n${def}`;
67
+ };
68
+ const serializerBlocks = variantSuffixes.map(buildSerializerPair).join('\n\n');
60
69
  return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
61
- ${summarySerializer}
62
-
63
- ${defaultSerializer}${!includeAdminSerializers
64
- ? ''
65
- : `
66
-
67
- ${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerClassName)}
68
-
69
- ${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}${!includeInternalSerializers
70
- ? ''
71
- : `
72
-
73
- ${summarySerializer.replace(summarySerializerClassName, internalSummarySerializerClassName)}
74
-
75
- ${defaultSerializer.replace(serializerClassName, internalSerializerClassName).replace(summarySerializerClassName, internalSummarySerializerClassName)}`}
70
+ ${serializerBlocks}
76
71
  `;
77
72
  }
73
+ function variantSerializerClassName(serializerBase, variantSuffix, kind) {
74
+ return kind === 'summary'
75
+ ? `${serializerBase}${variantSuffix}SummarySerializer`
76
+ : `${serializerBase}${variantSuffix}Serializer`;
77
+ }
78
78
  function attribute(modelClassName, name, type, attr, stiBaseSerializer) {
79
79
  if (name === 'type' && stiBaseSerializer) {
80
80
  return `.attribute('type', { openapi: { type: 'string', enum: [(StiChildClass ?? ${modelClassName}).sanitizedName] } })`;
@@ -97,11 +97,14 @@ function attributeOptionsSpecifier(type, attr) {
97
97
  return '';
98
98
  }
99
99
  }
100
- function importStatementForSerializer(originModelName, destinationModelName) {
101
- const defaultSerializer = globalClassNameFromFullyQualifiedModelName(serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(destinationModelName)));
102
- const summarySerializer = globalClassNameFromFullyQualifiedModelName(serializerNameFromFullyQualifiedModelName(fullyQualifiedModelNameToSerializerBaseName(destinationModelName), 'summary'));
100
+ function importStatementForSerializer(originModelName, destinationModelName, variantSuffixes) {
101
+ const base = fullyQualifiedModelNameToSerializerBaseName(destinationModelName);
102
+ const names = variantSuffixes.flatMap(suffix => [
103
+ globalClassNameFromFullyQualifiedModelName(variantSerializerClassName(base, suffix, 'default')),
104
+ globalClassNameFromFullyQualifiedModelName(variantSerializerClassName(base, suffix, 'summary')),
105
+ ]);
103
106
  const importFrom = absoluteDreamPath('serializers', destinationModelName);
104
- return `import { ${defaultSerializer}, ${summarySerializer} } from '${importFrom}'\n`;
107
+ return `import { ${names.join(', ')} } from '${importFrom}'\n`;
105
108
  }
106
109
  function importStatementForModel(modelClassName, fullyQualifiedModelName) {
107
110
  const importFrom = absoluteDreamPath('models', fullyQualifiedModelName);