@rvoh/dream 2.24.0 → 2.25.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.
- package/dist/cjs/src/cli/index.js +29 -9
- package/dist/cjs/src/dream/Query.js +247 -67
- package/dist/cjs/src/errors/BatchingIncompatibleWithLimitOrOffset.js +25 -0
- package/dist/cjs/src/errors/InvalidMigrationTableName.js +30 -0
- package/dist/cjs/src/errors/MissingRequiredLockOptionForUpdateCallback.js +16 -0
- package/dist/cjs/src/errors/NoColumnsToAlterMigration.js +35 -3
- package/dist/cjs/src/helpers/cli/generateMigration.js +33 -3
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +3 -3
- package/dist/esm/src/cli/index.js +29 -9
- package/dist/esm/src/dream/Query.js +247 -67
- package/dist/esm/src/errors/BatchingIncompatibleWithLimitOrOffset.js +25 -0
- package/dist/esm/src/errors/InvalidMigrationTableName.js +30 -0
- package/dist/esm/src/errors/MissingRequiredLockOptionForUpdateCallback.js +16 -0
- package/dist/esm/src/errors/NoColumnsToAlterMigration.js +35 -3
- package/dist/esm/src/helpers/cli/generateMigration.js +33 -3
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +3 -3
- package/dist/types/src/cli/index.d.ts +8 -0
- package/dist/types/src/dream/Query.d.ts +316 -40
- package/dist/types/src/errors/BatchingIncompatibleWithLimitOrOffset.d.ts +3 -0
- package/dist/types/src/errors/InvalidMigrationTableName.d.ts +10 -0
- package/dist/types/src/errors/MissingRequiredLockOptionForUpdateCallback.d.ts +3 -0
- package/dist/types/src/errors/NoColumnsToAlterMigration.d.ts +11 -1
- package/dist/types/src/helpers/cli/generateMigrationContent.d.ts +18 -4
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +40 -40
- package/docs/classes/db.PostgresQueryDriver.html +41 -41
- package/docs/classes/db.QueryDriverBase.html +39 -39
- 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.DecryptionError.html +2 -2
- package/docs/classes/errors.DecryptionParseError.html +2 -2
- package/docs/classes/errors.DecryptionRotationError.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 +124 -124
- package/docs/classes/index.DreamApp.html +10 -10
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +735 -73
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +7 -7
- 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 +3 -3
- 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.DreamDbConfig.html +5 -5
- 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
|
@@ -1,17 +1,49 @@
|
|
|
1
1
|
export default class NoColumnsToAlterMigration extends Error {
|
|
2
2
|
table;
|
|
3
3
|
alterDirection;
|
|
4
|
-
|
|
4
|
+
migrationName;
|
|
5
|
+
marker;
|
|
6
|
+
/**
|
|
7
|
+
* @param table - the table the migration resolved to
|
|
8
|
+
* @param alterDirection - 'add' for a `-to-` migration, 'remove' for a `-from-` migration
|
|
9
|
+
* @param migrationName - the migration name the user typed, when available. Only
|
|
10
|
+
* the standalone `g:migration` flow knows it, so the message degrades to a
|
|
11
|
+
* table-only explanation when it is omitted.
|
|
12
|
+
* @param marker - the `-to-`/`-from-` marker that matched within `migrationName`
|
|
13
|
+
*/
|
|
14
|
+
constructor(table, alterDirection, migrationName, marker) {
|
|
5
15
|
super();
|
|
6
16
|
this.table = table;
|
|
7
17
|
this.alterDirection = alterDirection;
|
|
18
|
+
this.migrationName = migrationName;
|
|
19
|
+
this.marker = marker;
|
|
8
20
|
}
|
|
9
21
|
get message() {
|
|
10
|
-
|
|
11
|
-
|
|
22
|
+
const verb = this.alterDirection === 'remove' ? 'drop from' : 'add to';
|
|
23
|
+
if (!this.migrationName || !this.marker) {
|
|
24
|
+
return `
|
|
25
|
+
no valid columns to ${verb} table '${this.table}' in this alter migration.
|
|
12
26
|
|
|
13
27
|
Pass at least one column declaration with a resolvable type, e.g.:
|
|
14
28
|
name:string
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
return `
|
|
32
|
+
no valid columns to ${verb} table '${this.table}' in this alter migration.
|
|
33
|
+
|
|
34
|
+
The migration name '${this.migrationName}' contains '${this.marker}', which selected that
|
|
35
|
+
table and the '${this.alterDirection}' direction: everything after the marker's first
|
|
36
|
+
occurrence - wherever in the name that falls - is snake-cased and pluralized
|
|
37
|
+
into the table name. A '-to-' anywhere in the name wins, even when a '-from-'
|
|
38
|
+
appears earlier; '-from-' applies only when the name contains no '-to-' at all.
|
|
39
|
+
|
|
40
|
+
Either:
|
|
41
|
+
|
|
42
|
+
- pass at least one column declaration with a resolvable type, e.g.:
|
|
43
|
+
name:string
|
|
44
|
+
|
|
45
|
+
- or, if this was meant to be a hand-written migration, rename it so that
|
|
46
|
+
neither '-to-' nor '-from-' appears anywhere in the name.
|
|
15
47
|
`;
|
|
16
48
|
}
|
|
17
49
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import pluralize from 'pluralize-esm';
|
|
3
|
+
import InvalidMigrationTableName from '../../errors/InvalidMigrationTableName.js';
|
|
3
4
|
import generateMigrationContent, { MIGRATION_TABLE_NAME_PLACEHOLDER, } from '../cli/generateMigrationContent.js';
|
|
4
5
|
import primaryKeyType from '../db/primaryKeyType.js';
|
|
5
6
|
import hyphenize from '../hyphenize.js';
|
|
@@ -21,6 +22,30 @@ function tableNameFromSuffix(migrationName, marker) {
|
|
|
21
22
|
return undefined;
|
|
22
23
|
return migrationName.slice(markerIndex + marker.length) || undefined;
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Whatever table name a generated migration ends up with is written verbatim
|
|
27
|
+
* into a single-quoted string literal in the migration file, which
|
|
28
|
+
* `db:migrate` later executes. Anything that is not a plain identifier could
|
|
29
|
+
* therefore close that literal and inject statements, so the generator fails
|
|
30
|
+
* closed instead of escaping. Every source of that table name is validated:
|
|
31
|
+
* the text after a `-to-`/`-from-` marker, the `--table-name` option, and the
|
|
32
|
+
* name derived from a model name.
|
|
33
|
+
*
|
|
34
|
+
* The pattern's job is blocking characters that can escape the generated
|
|
35
|
+
* string literal, not enforcing an SQL identifier convention: Kysely quotes
|
|
36
|
+
* identifiers, so a leading digit (`alterTable('2fa_tokens')`) is legal and is
|
|
37
|
+
* allowed here. Non-ASCII names stay rejected.
|
|
38
|
+
*
|
|
39
|
+
* This is a pure string check: it never consults the database, since the
|
|
40
|
+
* derived name legitimately need not be an existing table (e.g.
|
|
41
|
+
* `add-treehouse-to-place-styles` targets a Postgres enum).
|
|
42
|
+
*/
|
|
43
|
+
const VALID_DERIVED_TABLE_NAME = /^[a-z0-9_]+$/;
|
|
44
|
+
function validTableNameOrThrow(migrationName, table) {
|
|
45
|
+
if (!VALID_DERIVED_TABLE_NAME.test(table))
|
|
46
|
+
throw new InvalidMigrationTableName(migrationName, table);
|
|
47
|
+
return table;
|
|
48
|
+
}
|
|
24
49
|
export default async function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, tableName: explicitTableName, modelClassName, softDelete = false, }) {
|
|
25
50
|
const migrationsBasePath = connectionName === 'default'
|
|
26
51
|
? path.join(dreamPath('db'), 'migrations')
|
|
@@ -30,7 +55,7 @@ export default async function generateMigration({ migrationName, columnsWithType
|
|
|
30
55
|
let content = '';
|
|
31
56
|
if (isSTI) {
|
|
32
57
|
content = generateStiMigrationContent({
|
|
33
|
-
table: snakeify(pluralize(pascalizePath(fullyQualifiedParentName))),
|
|
58
|
+
table: validTableNameOrThrow(migrationName, snakeify(pluralize(pascalizePath(fullyQualifiedParentName)))),
|
|
34
59
|
columnsWithTypes,
|
|
35
60
|
primaryKeyType: primaryKeyType(connectionName),
|
|
36
61
|
stiChildClassName: modelClassName || pascalizePath(fullyQualifiedModelName),
|
|
@@ -38,7 +63,7 @@ export default async function generateMigration({ migrationName, columnsWithType
|
|
|
38
63
|
}
|
|
39
64
|
else if (fullyQualifiedModelName) {
|
|
40
65
|
content = generateMigrationContent({
|
|
41
|
-
table: explicitTableName || snakeify(pluralize(pascalizePath(fullyQualifiedModelName))),
|
|
66
|
+
table: validTableNameOrThrow(migrationName, explicitTableName || snakeify(pluralize(pascalizePath(fullyQualifiedModelName)))),
|
|
42
67
|
columnsWithTypes,
|
|
43
68
|
primaryKeyType: primaryKeyType(connectionName),
|
|
44
69
|
softDelete,
|
|
@@ -50,12 +75,17 @@ export default async function generateMigration({ migrationName, columnsWithType
|
|
|
50
75
|
? undefined
|
|
51
76
|
: tableNameFromSuffix(migrationName, '-from-');
|
|
52
77
|
const tableName = toTableName || fromTableName;
|
|
78
|
+
const table = tableName
|
|
79
|
+
? validTableNameOrThrow(migrationName, pluralize(snakeify(tableName)))
|
|
80
|
+
: MIGRATION_TABLE_NAME_PLACEHOLDER;
|
|
53
81
|
content = generateMigrationContent({
|
|
54
|
-
table
|
|
82
|
+
table,
|
|
55
83
|
columnsWithTypes,
|
|
56
84
|
primaryKeyType: primaryKeyType(connectionName),
|
|
57
85
|
createOrAlter: 'alter',
|
|
58
86
|
alterDirection: fromTableName ? 'remove' : 'add',
|
|
87
|
+
migrationName,
|
|
88
|
+
alterMarker: toTableName ? '-to-' : fromTableName ? '-from-' : undefined,
|
|
59
89
|
});
|
|
60
90
|
}
|
|
61
91
|
await writeGeneratedFile({
|
|
@@ -10,7 +10,7 @@ import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFu
|
|
|
10
10
|
import snakeify from '../snakeify.js';
|
|
11
11
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
12
12
|
// Sentinel table name used by generateMigration.ts when a standalone
|
|
13
|
-
// migration name
|
|
13
|
+
// migration name contains neither a `-to-<table>` nor `-from-<table>` marker.
|
|
14
14
|
// That path intentionally produces a stub the user is expected to hand-edit
|
|
15
15
|
// (e.g. an index-only migration with no column operations at all), so it's
|
|
16
16
|
// exempt from the "no valid columns" check below.
|
|
@@ -23,7 +23,7 @@ const STI_TYPE_COLUMN_NAME = 'type';
|
|
|
23
23
|
// default. See spec/unit/cli/generateMigrationContent.spec.ts
|
|
24
24
|
// ("deleted_at is deliberately NOT indexed") and the CHANGELOG.
|
|
25
25
|
const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME];
|
|
26
|
-
export default function generateMigrationContent({ connectionName = 'default', table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', alterDirection = 'add', stiChildClassName, softDelete = false, } = {}) {
|
|
26
|
+
export default function generateMigrationContent({ connectionName = 'default', table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', alterDirection = 'add', migrationName, alterMarker, stiChildClassName, softDelete = false, } = {}) {
|
|
27
27
|
const altering = createOrAlter === 'alter';
|
|
28
28
|
const removingInUp = altering && alterDirection === 'remove';
|
|
29
29
|
let requireCitextExtension = false;
|
|
@@ -205,7 +205,7 @@ export async function down(db: Kysely<any>): Promise<void> {
|
|
|
205
205
|
columnDefs.length === 0 &&
|
|
206
206
|
table !== MIGRATION_TABLE_NAME_PLACEHOLDER &&
|
|
207
207
|
!stiChildClassName) {
|
|
208
|
-
throw new NoColumnsToAlterMigration(table, alterDirection);
|
|
208
|
+
throw new NoColumnsToAlterMigration(table, alterDirection, migrationName, alterMarker);
|
|
209
209
|
}
|
|
210
210
|
const citextExtension = requireCitextExtension
|
|
211
211
|
? ` await DreamMigrationHelpers.createExtension(db, 'citext')\n\n`
|
|
@@ -105,6 +105,31 @@ ${INDENT}
|
|
|
105
105
|
${INDENT} rename the FK column with Model@alias (snake_case alias becomes the column name):
|
|
106
106
|
${INDENT} InternalUser@canceled_by:belongs_to:optional # canceled_by_id column with index
|
|
107
107
|
${INDENT} Messaging/Template@template:belongs_to # template_id column (strips the namespace from the column name)`);
|
|
108
|
+
/**
|
|
109
|
+
* The `<migrationName>` argument description for `g:migration`. Exported so
|
|
110
|
+
* that spec/unit/helpers/cli/generateMigration.spec.ts can read the example
|
|
111
|
+
* migration names out of this text and run them through the generator: a help
|
|
112
|
+
* example that drifts from what the generator actually produces then fails the
|
|
113
|
+
* suite instead of shipping.
|
|
114
|
+
*/
|
|
115
|
+
export const migrationNameArgumentDescription = `Kebab-case name describing the change. A -to-<table_name>
|
|
116
|
+
${INDENT}anywhere in the name — not just at the end — auto-generates
|
|
117
|
+
${INDENT}an add-columns alterTable scaffold for that table;
|
|
118
|
+
${INDENT}-from-<table_name> generates a remove-columns scaffold, but
|
|
119
|
+
${INDENT}only when the name contains no -to- at all. The text after
|
|
120
|
+
${INDENT}the marker's first occurrence is snake-cased and pluralized
|
|
121
|
+
${INDENT}into the table name, so add-a-to-b-to-cs targets b_to_cs. A
|
|
122
|
+
${INDENT}hand-written migration must avoid both strings anywhere in
|
|
123
|
+
${INDENT}its name.
|
|
124
|
+
${INDENT}
|
|
125
|
+
${INDENT}Examples:
|
|
126
|
+
${INDENT} add-phone-to-users phone:encrypted # scaffolds alterTable('users', ...)
|
|
127
|
+
${INDENT} remove-status-from-posts status:string # scaffolds alterTable('posts', ...)
|
|
128
|
+
${INDENT} create-many-to-many-posts-users # WRONG: selects 'many_posts_users'
|
|
129
|
+
${INDENT} # -to- inside "many-to-many" matches: with no columns
|
|
130
|
+
${INDENT} # this errors; with columns it silently scaffolds it
|
|
131
|
+
${INDENT} create-posts-users-join-table # correct: no marker match
|
|
132
|
+
${INDENT} # scaffolds alterTable('<table-name>') to hand-edit`;
|
|
108
133
|
export default class DreamCLI {
|
|
109
134
|
/**
|
|
110
135
|
* Starts the Dream console
|
|
@@ -151,22 +176,17 @@ export default class DreamCLI {
|
|
|
151
176
|
.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.
|
|
152
177
|
${INDENT}
|
|
153
178
|
${INDENT}Examples:
|
|
154
|
-
${INDENT} # Add columns to an existing table (
|
|
179
|
+
${INDENT} # Add columns to an existing table (include -to-<table_name> for auto alterTable scaffolding)
|
|
155
180
|
${INDENT} pnpm psy g:migration add-timezone-to-users timezone:string
|
|
156
181
|
${INDENT} pnpm psy g:migration add-bio-to-users bio:text:optional avatar_url:string:optional
|
|
157
182
|
${INDENT}
|
|
158
|
-
${INDENT} # Remove columns (
|
|
183
|
+
${INDENT} # Remove columns (include -from-<table_name>; columns are described with
|
|
159
184
|
${INDENT} # their types, same shorthand as -to-, so the rollback (down) can recreate them)
|
|
160
185
|
${INDENT} pnpm psy g:migration remove-legacy-fields-from-posts legacy_status:string
|
|
161
186
|
${INDENT}
|
|
162
|
-
${INDENT} # General schema change (no
|
|
187
|
+
${INDENT} # General schema change (no -to-/-from- marker — scaffolds alterTable('<table-name>') to hand-edit)
|
|
163
188
|
${INDENT} pnpm psy g:migration create-unique-index-on-invitations`)
|
|
164
|
-
.argument('<migrationName>',
|
|
165
|
-
${INDENT}
|
|
166
|
-
${INDENT}Examples:
|
|
167
|
-
${INDENT} add-phone-to-users phone:encrypted # scaffolds alterTable('users', ...)
|
|
168
|
-
${INDENT} remove-status-from-posts status:string # scaffolds alterTable('posts', ...)
|
|
169
|
-
${INDENT} create-join-table-host-places # empty migration (no table suffix match)`)
|
|
189
|
+
.argument('<migrationName>', migrationNameArgumentDescription)
|
|
170
190
|
.option('--connection-name <connectionName>', 'the database connection to use for this migration. Only needed for multi-database setups; defaults to "default"')
|
|
171
191
|
.argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
|
|
172
192
|
.action(async (migrationName, columnsWithTypes, options) => {
|