@rvoh/dream 2.5.3 → 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/cli/index.js +155 -46
- package/dist/esm/src/cli/index.js +155 -46
- package/docs/classes/db.DreamMigrationHelpers.html +9 -9
- package/docs/classes/db.KyselyQueryDriver.html +32 -32
- package/docs/classes/db.PostgresQueryDriver.html +33 -33
- package/docs/classes/db.QueryDriverBase.html +31 -31
- package/docs/classes/errors.CheckConstraintViolation.html +3 -3
- package/docs/classes/errors.ColumnOverflow.html +3 -3
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.InvalidClockTime.html +2 -2
- package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
- package/docs/classes/errors.InvalidDateTime.html +2 -2
- package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
- package/docs/classes/errors.NonLoadedAssociation.html +3 -3
- package/docs/classes/errors.NotNullViolation.html +3 -3
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- package/docs/classes/index.CalendarDate.html +33 -33
- package/docs/classes/index.ClockTime.html +32 -32
- package/docs/classes/index.ClockTimeTz.html +35 -35
- package/docs/classes/index.DateTime.html +86 -86
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +118 -118
- package/docs/classes/index.DreamApp.html +5 -5
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +56 -56
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +6 -6
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +11 -11
- package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +2 -2
- package/docs/classes/utils.Range.html +2 -2
- package/docs/functions/db.closeAllDbConnections.html +1 -1
- package/docs/functions/db.dreamDbConnections.html +1 -1
- package/docs/functions/db.untypedDb.html +1 -1
- package/docs/functions/db.validateColumn.html +1 -1
- package/docs/functions/db.validateTable.html +1 -1
- package/docs/functions/errors.pgErrorType.html +1 -1
- package/docs/functions/index.DreamSerializer.html +1 -1
- package/docs/functions/index.ObjectSerializer.html +1 -1
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +1 -1
- package/docs/functions/utils.camelize.html +1 -1
- package/docs/functions/utils.capitalize.html +1 -1
- package/docs/functions/utils.cloneDeepSafe.html +1 -1
- package/docs/functions/utils.compact.html +1 -1
- package/docs/functions/utils.groupBy.html +1 -1
- package/docs/functions/utils.hyphenize.html +1 -1
- package/docs/functions/utils.intersection.html +1 -1
- package/docs/functions/utils.isEmpty.html +1 -1
- package/docs/functions/utils.normalizeUnicode.html +1 -1
- package/docs/functions/utils.pascalize.html +1 -1
- package/docs/functions/utils.percent.html +1 -1
- package/docs/functions/utils.range.html +1 -1
- package/docs/functions/utils.round.html +1 -1
- package/docs/functions/utils.sanitizeString.html +1 -1
- package/docs/functions/utils.snakeify.html +1 -1
- package/docs/functions/utils.sort.html +1 -1
- package/docs/functions/utils.sortBy.html +1 -1
- package/docs/functions/utils.sortObjectByKey.html +1 -1
- package/docs/functions/utils.sortObjectByValue.html +1 -1
- package/docs/functions/utils.uncapitalize.html +1 -1
- package/docs/functions/utils.uniq.html +1 -1
- package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
- package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/types.BelongsToStatement.html +2 -2
- package/docs/interfaces/types.DecoratorContext.html +2 -2
- package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.DurationObject.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/openapi.OpenapiAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiFormats.html +1 -1
- package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaString.html +1 -1
- package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiTypeField.html +1 -1
- package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/types.CalendarDateDurationUnit.html +1 -1
- package/docs/types/types.CalendarDateObject.html +1 -1
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.ClockTimeObject.html +1 -1
- package/docs/types/types.DbConnectionType.html +1 -1
- package/docs/types/types.DbTypes.html +1 -1
- package/docs/types/types.DreamAssociationMetadata.html +1 -1
- package/docs/types/types.DreamAttributes.html +1 -1
- package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/types.DreamClassColumn.html +1 -1
- package/docs/types/types.DreamColumn.html +1 -1
- package/docs/types/types.DreamColumnNames.html +1 -1
- package/docs/types/types.DreamLogLevel.html +1 -1
- package/docs/types/types.DreamLogger.html +2 -2
- package/docs/types/types.DreamModelSerializerType.html +1 -1
- package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/types.DreamParamSafeAttributes.html +1 -1
- package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
- package/docs/types/types.DreamSerializable.html +1 -1
- package/docs/types/types.DreamSerializableArray.html +1 -1
- package/docs/types/types.DreamSerializerKey.html +1 -1
- package/docs/types/types.DreamSerializers.html +1 -1
- package/docs/types/types.DreamVirtualColumns.html +1 -1
- package/docs/types/types.DurationUnit.html +1 -1
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.PrimaryKeyType.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +2 -2
- package/docs/types/types.ViewModelClass.html +1 -1
- package/docs/types/types.WeekdayName.html +1 -1
- package/docs/types/types.WhereStatementForDream.html +1 -1
- package/docs/types/types.WhereStatementForDreamClass.html +1 -1
- package/docs/variables/index.DreamConst.html +1 -1
- package/docs/variables/index.ops.html +1 -1
- package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/system.primaryKeyTypes.html +1 -1
- package/package.json +1 -1
|
@@ -64,18 +64,24 @@ const columnsWithTypesDescription = baseColumnsWithTypesDescription +
|
|
|
64
64
|
`
|
|
65
65
|
${INDENT}
|
|
66
66
|
${INDENT} - belongs_to:
|
|
67
|
-
${INDENT}
|
|
67
|
+
${INDENT} ALWAYS use this instead of adding a raw uuid column for foreign keys. It creates the FK column, adds a database index,
|
|
68
|
+
${INDENT} AND generates the @deco.BelongsTo association and typed property on the model. A raw uuid column does none of this.
|
|
68
69
|
${INDENT}
|
|
69
|
-
${INDENT}
|
|
70
|
-
${INDENT}
|
|
70
|
+
${INDENT} use the fully qualified model name (matching its path under src/app/models/):
|
|
71
|
+
${INDENT} User:belongs_to # creates user_id column + BelongsTo association
|
|
72
|
+
${INDENT} Health/Coach:belongs_to # creates health_coach_id column + BelongsTo association
|
|
73
|
+
${INDENT} User:belongs_to:optional # nullable foreign key (for optional associations)`;
|
|
71
74
|
const columnsWithTypesDescriptionForMigration = baseColumnsWithTypesDescription +
|
|
72
75
|
`
|
|
73
76
|
${INDENT}
|
|
74
77
|
${INDENT} - belongs_to:
|
|
75
|
-
${INDENT}
|
|
78
|
+
${INDENT} ALWAYS use this instead of adding a raw uuid column for foreign keys. It creates the FK column with an index.
|
|
79
|
+
${INDENT} Unlike in g:model/g:resource, this does NOT add a BelongsTo association (no model is generated).
|
|
76
80
|
${INDENT}
|
|
77
|
-
${INDENT}
|
|
78
|
-
${INDENT}
|
|
81
|
+
${INDENT} use the fully qualified model name (matching its path under src/app/models/):
|
|
82
|
+
${INDENT} User:belongs_to # creates user_id column with index
|
|
83
|
+
${INDENT} Health/Coach:belongs_to # creates health_coach_id column with index
|
|
84
|
+
${INDENT} User:belongs_to:optional # nullable foreign key`;
|
|
79
85
|
export default class DreamCLI {
|
|
80
86
|
/**
|
|
81
87
|
* Starts the Dream console
|
|
@@ -90,8 +96,8 @@ export default class DreamCLI {
|
|
|
90
96
|
static provide(program, { initializeDreamApp, seedDb, }) {
|
|
91
97
|
program
|
|
92
98
|
.command('sync')
|
|
93
|
-
.description('
|
|
94
|
-
.option('--schema-only', '
|
|
99
|
+
.description('Regenerates TypeScript types (types/db.ts, types/dream.ts) from the current database schema. Run this after changing associations, serializers, or enum types.')
|
|
100
|
+
.option('--schema-only', 'only regenerate database schema types, skipping any custom sync actions', false)
|
|
95
101
|
.action(async (options) => {
|
|
96
102
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
97
103
|
await DreamBin.sync(() => { }, options);
|
|
@@ -119,9 +125,25 @@ export default class DreamCLI {
|
|
|
119
125
|
program
|
|
120
126
|
.command('generate:migration')
|
|
121
127
|
.alias('g:migration')
|
|
122
|
-
.description(
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
.description(`Generates a new Kysely migration file for schema changes. Use this for altering existing tables (adding/removing columns, indexes, constraints). Prefer g:resource or g:model when creating a new model, since they generate the migration along with the model, serializer, and spec files.
|
|
129
|
+
${INDENT}
|
|
130
|
+
${INDENT}Examples:
|
|
131
|
+
${INDENT} # Add columns to an existing table (suffix with -to-<table_name> for auto alterTable scaffolding)
|
|
132
|
+
${INDENT} pnpm psy g:migration add-timezone-to-users timezone:string
|
|
133
|
+
${INDENT} pnpm psy g:migration add-bio-to-users bio:text:optional avatar_url:string:optional
|
|
134
|
+
${INDENT}
|
|
135
|
+
${INDENT} # Remove columns (suffix with -from-<table_name>)
|
|
136
|
+
${INDENT} pnpm psy g:migration remove-legacy-fields-from-posts
|
|
137
|
+
${INDENT}
|
|
138
|
+
${INDENT} # General schema change (no table suffix — generates empty up/down methods)
|
|
139
|
+
${INDENT} pnpm psy g:migration create-unique-index-on-invitations`)
|
|
140
|
+
.argument('<migrationName>', `Kebab-case name describing the change. End with -to-<table_name> or -from-<table_name> to auto-generate an alterTable scaffold for that table.
|
|
141
|
+
${INDENT}
|
|
142
|
+
${INDENT}Examples:
|
|
143
|
+
${INDENT} add-phone-to-users # scaffolds alterTable('users', ...)
|
|
144
|
+
${INDENT} remove-status-from-posts # scaffolds alterTable('posts', ...)
|
|
145
|
+
${INDENT} create-join-table-host-places # empty migration (no table suffix match)`)
|
|
146
|
+
.option('--connection-name <connectionName>', 'the database connection to use for this migration. Only needed for multi-database setups; defaults to "default"')
|
|
125
147
|
.argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
|
|
126
148
|
.action(async (migrationName, columnsWithTypes, options) => {
|
|
127
149
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true, bypassDbConnectionsDuringInit: true });
|
|
@@ -133,15 +155,47 @@ export default class DreamCLI {
|
|
|
133
155
|
.alias('g:model')
|
|
134
156
|
.alias('generate:dream')
|
|
135
157
|
.alias('g:dream')
|
|
136
|
-
.description(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
.description(`Generates a Dream model with corresponding spec factory, serializer, and migration. Use this when the model will NOT be accessible via HTTP requests (e.g., internal join tables, data models with no API). For HTTP-accessible models, prefer g:resource which also generates a controller and specs.
|
|
159
|
+
${INDENT}
|
|
160
|
+
${INDENT}Examples:
|
|
161
|
+
${INDENT} # Simple model
|
|
162
|
+
${INDENT} pnpm psy g:model Tag value:citext
|
|
163
|
+
${INDENT}
|
|
164
|
+
${INDENT} # Join table model
|
|
165
|
+
${INDENT} pnpm psy g:model HostPlace Host:belongs_to Place:belongs_to
|
|
166
|
+
${INDENT}
|
|
167
|
+
${INDENT} # STI parent model (use with g:sti-child for children)
|
|
168
|
+
${INDENT} pnpm psy g:model --sti-base-serializer Room Place:belongs_to type:enum:room_types:Bathroom,Bedroom deleted_at:datetime:optional`)
|
|
169
|
+
.option('--no-serializer', 'skip serializer generation. Useful for internal models that will never be serialized in an API response (e.g., join tables, audit logs)')
|
|
170
|
+
.option('--connection-name <connectionName>', 'the name of the database connection to use for the model. Only needed for multi-database setups; defaults to "default"', 'default')
|
|
171
|
+
.option('--sti-base-serializer', `Creates generically typed base serializers (default and summary) that accept a \`StiChildClass\` parameter and include the \`type\` attribute with a per-child enum constraint. This allows consuming applications to determine the response shape based on the STI type discriminator.
|
|
172
|
+
${INDENT}
|
|
173
|
+
${INDENT}Use this when generating the parent model of an STI hierarchy. After generating the parent, use g:sti-child for each child type.
|
|
174
|
+
${INDENT}
|
|
175
|
+
${INDENT}Example:
|
|
176
|
+
${INDENT} # CRITICAL: the type enums must exactly match the class names of the STI children
|
|
177
|
+
${INDENT} pnpm psy g:model --sti-base-serializer Rental type:enum:place_types:Apartment,House,Condo
|
|
178
|
+
${INDENT} # STI children subsequently generated using the g:sti-child generator (note the use of \`--model-name\` to generate class names that match the \`type\` column, e.g., "Apartment" instead of the "RentalApartment" default):
|
|
179
|
+
${INDENT} pnpm psy g:sti-child --model-name=Apartment Rental/Apartment extends Rental
|
|
180
|
+
${INDENT} pnpm psy g:sti-child --model-name=House Rental/House extends Rental
|
|
181
|
+
${INDENT} pnpm psy g:sti-child --model-name=Condo Rental/Condo extends Rental`, false)
|
|
182
|
+
.option('--table-name <tableName>', `Explicit table name to use instead of the auto-generated one. Useful when model namespaces produce long or awkward table names.
|
|
183
|
+
${INDENT}
|
|
184
|
+
${INDENT}Example:
|
|
185
|
+
${INDENT} pnpm psy g:model --table-name=notif_prefs Settings/NotificationPreferences User:belongs_to`)
|
|
186
|
+
.option('--model-name <modelName>', `Explicit model class name to use instead of the one auto-derived from the model path. Useful when the path segments don't match the desired class name.
|
|
187
|
+
${INDENT}
|
|
188
|
+
${INDENT}Example:
|
|
189
|
+
${INDENT} pnpm psy g:model --model-name=GroupDanceLesson Lesson/Dance/Group
|
|
190
|
+
${INDENT} # model is named GroupDanceLesson instead of LessonDanceGroup`)
|
|
191
|
+
.option('--admin-serializers', 'also generate AdminSerializer and AdminSummarySerializer variants for admin-facing API endpoints that may expose additional fields', false)
|
|
192
|
+
.option('--internal-serializers', 'also generate InternalSerializer and InternalSummarySerializer variants for internal API endpoints that may expose additional fields', false)
|
|
193
|
+
.argument('<modelName>', `The fully qualified model name, using / for namespacing. This determines the model class name (may be overridden with \`--model-name\`), table name, and file path under src/app/models/.
|
|
194
|
+
${INDENT}
|
|
195
|
+
${INDENT}Examples:
|
|
196
|
+
${INDENT} Post # src/app/models/Post.ts, table: posts
|
|
197
|
+
${INDENT} HostPlace # src/app/models/HostPlace.ts, table: host_places
|
|
198
|
+
${INDENT} Settings/CommunicationPreferences # src/app/models/Settings/CommunicationPreferences.ts`)
|
|
145
199
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
146
200
|
.action(async (modelName, columnsWithTypes, options) => {
|
|
147
201
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true, bypassDbConnectionsDuringInit: true });
|
|
@@ -151,17 +205,40 @@ export default class DreamCLI {
|
|
|
151
205
|
program
|
|
152
206
|
.command('generate:sti-child')
|
|
153
207
|
.alias('g:sti-child')
|
|
154
|
-
.description(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
${INDENT}
|
|
164
|
-
${INDENT}
|
|
208
|
+
.description(`Generates an STI (Single Table Inheritance) child model that extends an existing parent model. The child shares the parent's database table (discriminated by the \`type\` column) and can add child-specific columns. Generates a child model decorated with @STI(Parent), child serializers extending the parent's base serializers, a migration that ALTERs the parent table (not a new table), check constraints, a factory, and spec skeleton.
|
|
209
|
+
${INDENT}
|
|
210
|
+
${INDENT}The parent must already exist (typically generated with g:model --sti-base-serializer or g:resource --sti-base-serializer).
|
|
211
|
+
${INDENT}
|
|
212
|
+
${INDENT}Examples:
|
|
213
|
+
${INDENT} # Child with an enum column
|
|
214
|
+
${INDENT} pnpm psy g:sti-child --model-name=Bathroom Room/Bathroom extends Room bath_or_shower_style:enum:bath_or_shower_styles:bath,shower,none
|
|
215
|
+
${INDENT}
|
|
216
|
+
${INDENT} # Child with an enum array column
|
|
217
|
+
${INDENT} pnpm psy g:sti-child --model-name=Bedroom Room/Bedroom extends Room bed_types:enum[]:bed_types:twin,queen,king
|
|
218
|
+
${INDENT}
|
|
219
|
+
${INDENT} # Child with no additional columns
|
|
220
|
+
${INDENT} pnpm psy g:sti-child --model-name=Kitchen Room/Kitchen extends Room`)
|
|
221
|
+
.option('--no-serializer', 'skip serializer generation. Useful if the child uses the parent serializer directly or serialization is handled elsewhere')
|
|
222
|
+
.option('--connection-name', 'the name of the database connection to use for the model. Only needed for multi-database setups; defaults to "default"', 'default')
|
|
223
|
+
.option('--model-name <modelName>', `Explicit model class name to use instead of the one auto-derived from the model path. Useful when the path segments don't match the desired class name.
|
|
224
|
+
${INDENT}
|
|
225
|
+
${INDENT}Example:
|
|
226
|
+
${INDENT} pnpm psy g:sti-child --model-name=GroupDanceLesson Lesson/Dance/Group extends Lesson
|
|
227
|
+
${INDENT} # model is named GroupDanceLesson instead of LessonDanceGroup`)
|
|
228
|
+
.option('--admin-serializers', 'also generate AdminSerializer and AdminSummarySerializer variants for admin-facing API endpoints that may expose additional fields', false)
|
|
229
|
+
.option('--internal-serializers', 'also generate InternalSerializer and InternalSummarySerializer variants for internal API endpoints that may expose additional fields', false)
|
|
230
|
+
.argument('<childModelName>', `The namespaced child model path. By convention, children are nested under the parent name.
|
|
231
|
+
${INDENT}
|
|
232
|
+
${INDENT}Examples:
|
|
233
|
+
${INDENT} Room/Bathroom # src/app/models/Room/Bathroom.ts
|
|
234
|
+
${INDENT} Room/Bedroom # src/app/models/Room/Bedroom.ts
|
|
235
|
+
${INDENT} Vehicle/Truck # src/app/models/Vehicle/Truck.ts`)
|
|
236
|
+
.argument('<extends>', 'the literal word "extends" (required syntax)')
|
|
237
|
+
.argument('<parentModelName>', `Fully qualified name of the parent STI model to extend. Must match the parent's path under src/app/models/.
|
|
238
|
+
${INDENT}
|
|
239
|
+
${INDENT}Examples:
|
|
240
|
+
${INDENT} Room # extends src/app/models/Room.ts
|
|
241
|
+
${INDENT} Health/Coach # extends src/app/models/Health/Coach.ts`)
|
|
165
242
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
166
243
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
167
244
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true, bypassDbConnectionsDuringInit: true });
|
|
@@ -173,8 +250,18 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
173
250
|
program
|
|
174
251
|
.command('generate:encryption-key')
|
|
175
252
|
.alias('g:encryption-key')
|
|
176
|
-
.description(
|
|
177
|
-
|
|
253
|
+
.description(`Generates a cryptographically secure encryption key and prints it to stdout. Use this to create keys for any Dream/Psychic encryption use case:
|
|
254
|
+
${INDENT}
|
|
255
|
+
${INDENT} - @deco.Encrypted() model columns (e.g., phone numbers, SSNs)
|
|
256
|
+
${INDENT} - Cookie encryption/decryption in Psychic sessions
|
|
257
|
+
${INDENT} - General-purpose use of the Dream Encrypt library
|
|
258
|
+
${INDENT}
|
|
259
|
+
${INDENT}Store the generated key in your environment variables (e.g., ENCRYPTION_KEY). Never commit keys to source control.
|
|
260
|
+
${INDENT}
|
|
261
|
+
${INDENT}Example:
|
|
262
|
+
${INDENT} pnpm psy g:encryption-key # generates aes-256-gcm key (default)
|
|
263
|
+
${INDENT} pnpm psy g:encryption-key --algorithm=aes-128-gcm`)
|
|
264
|
+
.addOption(new Option('--algorithm <algorithm>', 'the encryption algorithm to generate a key for. aes-256-gcm (default) is recommended for most use cases')
|
|
178
265
|
.choices(['aes-256-gcm', 'aes-192-gcm', 'aes-128-gcm'])
|
|
179
266
|
.default('aes-256-gcm'))
|
|
180
267
|
.action((options) => {
|
|
@@ -184,7 +271,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
184
271
|
});
|
|
185
272
|
program
|
|
186
273
|
.command('db:create')
|
|
187
|
-
.description('Creates a new database.')
|
|
274
|
+
.description('Creates the database defined in your Dream configuration. Run this once when setting up a new development environment, or after db:drop. Safe to run if the database already exists.')
|
|
188
275
|
.action(async () => {
|
|
189
276
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true, bypassDbConnectionsDuringInit: true });
|
|
190
277
|
await DreamBin.dbCreate();
|
|
@@ -192,7 +279,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
192
279
|
});
|
|
193
280
|
program
|
|
194
281
|
.command('db:integrity-check')
|
|
195
|
-
.description('
|
|
282
|
+
.description('Checks that all migrations have been run and exits with code 1 if any are pending. Useful as a CI check or deploy gate to ensure the database schema is up to date before starting the application.')
|
|
196
283
|
.action(async () => {
|
|
197
284
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
198
285
|
await DreamBin.dbEnsureAllMigrationsHaveBeenRun();
|
|
@@ -200,8 +287,13 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
200
287
|
});
|
|
201
288
|
program
|
|
202
289
|
.command('db:migrate')
|
|
203
|
-
.description(
|
|
204
|
-
|
|
290
|
+
.description(`Runs all pending database migrations in order, then automatically syncs types (in development/test). This is the primary command for applying schema changes after generating or editing a migration.
|
|
291
|
+
${INDENT}
|
|
292
|
+
${INDENT}Example workflow:
|
|
293
|
+
${INDENT} pnpm psy g:migration add-phone-to-users phone:string:optional
|
|
294
|
+
${INDENT} # edit the migration if needed (e.g., add unique constraints)
|
|
295
|
+
${INDENT} pnpm psy db:migrate`)
|
|
296
|
+
.option('--skip-sync', 'skip the automatic sync after migrating. Useful when running migrations in production or when you plan to sync manually afterward', false)
|
|
205
297
|
.action(async ({ skipSync }) => {
|
|
206
298
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
207
299
|
await DreamBin.dbMigrate();
|
|
@@ -212,9 +304,13 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
212
304
|
});
|
|
213
305
|
program
|
|
214
306
|
.command('db:rollback')
|
|
215
|
-
.description(
|
|
216
|
-
|
|
217
|
-
|
|
307
|
+
.description(`Rolls back the most recent migration(s), then automatically syncs types (in development/test). Use this to undo a migration so you can edit and re-run it.
|
|
308
|
+
${INDENT}
|
|
309
|
+
${INDENT}Examples:
|
|
310
|
+
${INDENT} pnpm psy db:rollback # rolls back the last migration
|
|
311
|
+
${INDENT} pnpm psy db:rollback --steps=3 # rolls back the last 3 migrations`)
|
|
312
|
+
.option('--steps <number>', 'number of migration steps to roll back (default: 1)', myParseInt, 1)
|
|
313
|
+
.option('--skip-sync', 'skip the automatic sync after rolling back. Useful when you plan to immediately re-migrate or sync manually', false)
|
|
218
314
|
.action(async ({ steps, skipSync }) => {
|
|
219
315
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
220
316
|
await DreamBin.dbRollback({ steps });
|
|
@@ -225,7 +321,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
225
321
|
});
|
|
226
322
|
program
|
|
227
323
|
.command('db:drop')
|
|
228
|
-
.description('Drops the database')
|
|
324
|
+
.description('Drops the database. This is a destructive operation — all data will be lost. Primarily used as part of db:reset or when you need a clean slate during development.')
|
|
229
325
|
.action(async () => {
|
|
230
326
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true, bypassDbConnectionsDuringInit: true });
|
|
231
327
|
await DreamBin.dbDrop();
|
|
@@ -233,7 +329,13 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
233
329
|
});
|
|
234
330
|
program
|
|
235
331
|
.command('db:reset')
|
|
236
|
-
.description(
|
|
332
|
+
.description(`Completely resets the database by running db:drop, db:create, db:migrate, sync, and db:seed in sequence. Use this when:
|
|
333
|
+
${INDENT}
|
|
334
|
+
${INDENT} - Switching between branches with incompatible migrations ("corrupted migrations" error)
|
|
335
|
+
${INDENT} - Starting fresh after a schema has diverged significantly
|
|
336
|
+
${INDENT} - Setting up a clean development environment
|
|
337
|
+
${INDENT}
|
|
338
|
+
${INDENT}Warning: all existing data will be lost. The seed file (db/seed.ts) will be run to repopulate initial data.`)
|
|
237
339
|
.action(async () => {
|
|
238
340
|
await initializeDreamApp({ bypassDreamIntegrityChecks: true, bypassDbConnectionsDuringInit: true });
|
|
239
341
|
const arrows = colorize('⭣⭣⭣', { color: 'green' }) + '\n';
|
|
@@ -273,7 +375,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
273
375
|
});
|
|
274
376
|
program
|
|
275
377
|
.command('db:seed')
|
|
276
|
-
.description(
|
|
378
|
+
.description(`Seeds the database by running the seed function defined in db/seed.ts. Skipped automatically in test environments unless DREAM_SEED_DB_IN_TEST=1 is set. Runs automatically as the last step of db:reset.`)
|
|
277
379
|
.action(async () => {
|
|
278
380
|
if (process.env.NODE_ENV === 'test' && process.env.DREAM_SEED_DB_IN_TEST !== '1') {
|
|
279
381
|
DreamApp.log('skipping db seed for test env. To really seed for test, add DREAM_SEED_DB_IN_TEST=1');
|
|
@@ -286,9 +388,16 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
286
388
|
program
|
|
287
389
|
.command('inspect:serialization')
|
|
288
390
|
.alias('i:serialization')
|
|
289
|
-
.description(
|
|
290
|
-
|
|
291
|
-
|
|
391
|
+
.description(`Displays a detailed serialization map for a model, showing all attributes, associations, custom attributes, and their types. Useful for debugging serializer output, understanding what a model's API response will look like, and verifying that associations are preloaded correctly.
|
|
392
|
+
${INDENT}
|
|
393
|
+
${INDENT}Examples:
|
|
394
|
+
${INDENT} pnpm psy i:serialization Place # shows the default serializer for Place
|
|
395
|
+
${INDENT} pnpm psy i:serialization Place summary # shows the summary serializer for Place
|
|
396
|
+
${INDENT} pnpm psy i:serialization Room/Bedroom # shows serializer for an STI child`)
|
|
397
|
+
.argument('<globalName>', `The global name of the model as registered in Dream (typically matches the model class name or its fully qualified path).
|
|
398
|
+
${INDENT}
|
|
399
|
+
${INDENT}Examples: User, Place, Room/Bedroom, Settings/CommunicationPreferences`)
|
|
400
|
+
.argument('[serializerKey]', 'the serializer variant to display (e.g., "summary", "admin", "internal"). Defaults to "default" if omitted')
|
|
292
401
|
.action(async (globalName, serializerKey) => {
|
|
293
402
|
await initializeDreamApp();
|
|
294
403
|
const dreamApp = DreamApp.getOrFail();
|