@rvoh/dream 1.9.4 → 1.10.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/Dream.js +61 -2
- package/dist/cjs/src/bin/index.js +6 -0
- package/dist/cjs/src/cli/index.js +19 -11
- package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +19 -0
- package/dist/cjs/src/decorators/field/association/BelongsTo.js +2 -2
- package/dist/cjs/src/decorators/field/association/HasMany.js +2 -2
- package/dist/cjs/src/decorators/field/association/HasOne.js +2 -2
- package/dist/cjs/src/dream/Query.js +4 -1
- package/dist/cjs/src/dream/QueryDriver/Base.js +6 -0
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +11 -3
- package/dist/cjs/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.js +27 -0
- package/dist/cjs/src/dream/QueryDriver/helpers/kysely/migrationFolderPath.js +11 -0
- package/dist/cjs/src/dream/QueryDriver/helpers/kysely/runMigration.js +11 -13
- package/dist/cjs/src/dream/internal/orderByDirection.js +2 -3
- package/dist/cjs/src/dream/internal/undestroyDream.js +2 -2
- package/dist/cjs/src/dream-app/index.js +4 -4
- package/dist/cjs/src/errors/associations/InvalidComputedForeignKey.js +3 -4
- package/dist/cjs/src/helpers/cli/SchemaBuilder.js +30 -23
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +7 -5
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +1 -0
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +17 -16
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +3 -3
- package/dist/cjs/src/helpers/comparisonKey.js +16 -1
- package/dist/cjs/src/helpers/percent.js +10 -0
- package/dist/cjs/src/helpers/sort.js +0 -3
- package/dist/cjs/src/helpers/sortBy.js +11 -2
- package/dist/cjs/src/helpers/uniq.js +5 -8
- package/dist/cjs/src/index.js +3 -1
- package/dist/esm/src/Dream.js +61 -2
- package/dist/esm/src/bin/index.js +6 -0
- package/dist/esm/src/cli/index.js +19 -11
- package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +19 -0
- package/dist/esm/src/decorators/field/association/BelongsTo.js +2 -2
- package/dist/esm/src/decorators/field/association/HasMany.js +2 -2
- package/dist/esm/src/decorators/field/association/HasOne.js +2 -2
- package/dist/esm/src/dream/Query.js +4 -1
- package/dist/esm/src/dream/QueryDriver/Base.js +6 -0
- package/dist/esm/src/dream/QueryDriver/Kysely.js +12 -4
- package/dist/esm/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.js +24 -0
- package/dist/esm/src/dream/QueryDriver/helpers/kysely/migrationFolderPath.js +8 -0
- package/dist/esm/src/dream/QueryDriver/helpers/kysely/runMigration.js +3 -5
- package/dist/esm/src/dream/internal/orderByDirection.js +2 -3
- package/dist/esm/src/dream/internal/undestroyDream.js +2 -2
- package/dist/esm/src/dream-app/index.js +4 -4
- package/dist/esm/src/errors/associations/InvalidComputedForeignKey.js +3 -4
- package/dist/esm/src/helpers/cli/SchemaBuilder.js +30 -23
- package/dist/esm/src/helpers/cli/generateDreamContent.js +7 -5
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +1 -0
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +17 -16
- package/dist/esm/src/helpers/cli/generateSerializerContent.js +3 -3
- package/dist/esm/src/helpers/comparisonKey.js +16 -1
- package/dist/esm/src/helpers/percent.js +7 -0
- package/dist/esm/src/helpers/sort.js +0 -3
- package/dist/esm/src/helpers/sortBy.js +11 -2
- package/dist/esm/src/helpers/uniq.js +5 -8
- package/dist/esm/src/index.js +1 -0
- package/dist/types/src/Dream.d.ts +46 -4
- package/dist/types/src/bin/index.d.ts +1 -0
- package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +16 -0
- package/dist/types/src/decorators/field/sortable/helpers/setPosition.d.ts +1 -1
- package/dist/types/src/dream/QueryDriver/Base.d.ts +1 -0
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +3 -2
- package/dist/types/src/dream/QueryDriver/helpers/kysely/checkForNeedToBeRunMigrations.d.ts +9 -0
- package/dist/types/src/dream/QueryDriver/helpers/kysely/migrationFolderPath.d.ts +1 -0
- package/dist/types/src/dream/internal/orderByDirection.d.ts +2 -1
- package/dist/types/src/dream-app/index.d.ts +2 -2
- package/dist/types/src/helpers/comparisonKey.d.ts +1 -1
- package/dist/types/src/helpers/percent.d.ts +2 -0
- package/dist/types/src/helpers/sort.d.ts +3 -1
- package/dist/types/src/helpers/sortBy.d.ts +4 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +1 -1
- package/dist/types/src/types/associations/belongsTo.d.ts +2 -2
- package/dist/types/src/types/associations/belongsTo.ts +2 -2
- package/dist/types/src/types/associations/shared.d.ts +2 -2
- package/dist/types/src/types/associations/shared.ts +2 -2
- package/dist/types/src/types/dream.d.ts +17 -4
- package/dist/types/src/types/dream.ts +38 -13
- package/dist/types/src/types/serializer.d.ts +1 -1
- package/dist/types/src/types/serializer.ts +1 -1
- package/dist/types/src/types/variadic.ts +4 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Benchmark.html +2 -2
- package/docs/classes/CalendarDate.html +2 -2
- package/docs/classes/CheckConstraintViolation.html +3 -3
- package/docs/classes/CliFileWriter.html +2 -2
- package/docs/classes/ColumnOverflow.html +3 -3
- package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/DataIncompatibleWithDatabaseField.html +3 -3
- package/docs/classes/DataTypeColumnTypeMismatch.html +3 -3
- package/docs/classes/Decorators.html +19 -19
- package/docs/classes/Dream.html +201 -174
- package/docs/classes/DreamApp.html +4 -4
- package/docs/classes/DreamBin.html +3 -2
- package/docs/classes/DreamCLI.html +4 -4
- package/docs/classes/DreamImporter.html +2 -2
- package/docs/classes/DreamLogos.html +2 -2
- package/docs/classes/DreamMigrationHelpers.html +19 -8
- package/docs/classes/DreamSerializerBuilder.html +13 -13
- package/docs/classes/DreamTransaction.html +2 -2
- package/docs/classes/Encrypt.html +2 -2
- package/docs/classes/Env.html +2 -2
- package/docs/classes/GlobalNameNotSet.html +3 -3
- package/docs/classes/KyselyQueryDriver.html +31 -30
- package/docs/classes/MissingSerializersDefinition.html +3 -3
- package/docs/classes/NonLoadedAssociation.html +3 -3
- package/docs/classes/NotNullViolation.html +3 -3
- package/docs/classes/ObjectSerializerBuilder.html +8 -8
- package/docs/classes/PostgresQueryDriver.html +32 -31
- package/docs/classes/Query.html +53 -53
- package/docs/classes/QueryDriverBase.html +30 -29
- package/docs/classes/Range.html +2 -2
- package/docs/classes/RecordNotFound.html +3 -3
- package/docs/classes/ValidationError.html +3 -3
- package/docs/functions/DreamSerializer.html +1 -1
- package/docs/functions/ObjectSerializer.html +1 -1
- package/docs/functions/ReplicaSafe.html +1 -1
- package/docs/functions/STI.html +1 -1
- package/docs/functions/SoftDelete.html +1 -1
- package/docs/functions/camelize.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeepSafe.html +1 -1
- package/docs/functions/closeAllDbConnections.html +1 -1
- package/docs/functions/compact.html +1 -1
- package/docs/functions/dreamDbConnections.html +1 -1
- package/docs/functions/dreamPath.html +1 -1
- package/docs/functions/expandStiClasses.html +1 -1
- package/docs/functions/generateDream.html +1 -1
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/groupBy.html +1 -1
- package/docs/functions/hyphenize.html +1 -1
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
- package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
- package/docs/functions/intersection.html +1 -1
- package/docs/functions/isDreamSerializer.html +1 -1
- package/docs/functions/isEmpty.html +1 -1
- package/docs/functions/loadRepl.html +1 -1
- package/docs/functions/lookupClassByGlobalName.html +1 -1
- package/docs/functions/normalizeUnicode.html +1 -1
- package/docs/functions/pascalize.html +1 -1
- package/docs/functions/percent.html +1 -0
- package/docs/functions/pgErrorType.html +1 -1
- package/docs/functions/range-1.html +1 -1
- package/docs/functions/relativeDreamPath.html +1 -1
- package/docs/functions/round.html +1 -1
- package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/sharedPathPrefix.html +1 -1
- package/docs/functions/snakeify.html +1 -1
- package/docs/functions/sort.html +1 -1
- package/docs/functions/sortBy.html +1 -1
- package/docs/functions/sortObjectByKey.html +1 -1
- package/docs/functions/sortObjectByValue.html +1 -1
- package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
- package/docs/functions/uncapitalize.html +1 -1
- package/docs/functions/uniq.html +1 -1
- package/docs/functions/untypedDb.html +1 -1
- package/docs/functions/validateColumn.html +1 -1
- package/docs/functions/validateTable.html +1 -1
- package/docs/interfaces/BelongsToStatement.html +2 -2
- package/docs/interfaces/DecoratorContext.html +2 -2
- package/docs/interfaces/DreamAppInitOptions.html +2 -2
- package/docs/interfaces/DreamAppOpts.html +2 -2
- package/docs/interfaces/EncryptOptions.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/OpenapiDescription.html +2 -2
- package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/SerializerRendererOpts.html +2 -2
- package/docs/modules.html +1 -0
- package/docs/types/Camelized.html +1 -1
- package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/DateTime.html +1 -1
- package/docs/types/DbConnectionType.html +1 -1
- package/docs/types/DbTypes.html +1 -1
- package/docs/types/DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/DreamAssociationMetadata.html +1 -1
- package/docs/types/DreamAttributes.html +1 -1
- package/docs/types/DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/DreamClassColumn.html +1 -1
- package/docs/types/DreamColumn.html +1 -1
- package/docs/types/DreamColumnNames.html +1 -1
- package/docs/types/DreamLogLevel.html +1 -1
- package/docs/types/DreamLogger.html +1 -1
- package/docs/types/DreamModelSerializerType.html +1 -1
- package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/DreamParamSafeAttributes.html +1 -1
- package/docs/types/DreamParamSafeColumnNames.html +1 -1
- package/docs/types/DreamSerializable.html +1 -1
- package/docs/types/DreamSerializableArray.html +1 -1
- package/docs/types/DreamSerializerKey.html +1 -1
- package/docs/types/DreamSerializers.html +1 -1
- package/docs/types/DreamVirtualColumns.html +1 -1
- package/docs/types/EncryptAlgorithm.html +1 -1
- package/docs/types/HasManyStatement.html +1 -1
- package/docs/types/HasOneStatement.html +1 -1
- package/docs/types/Hyphenized.html +1 -1
- package/docs/types/OpenapiAllTypes.html +1 -1
- package/docs/types/OpenapiFormats.html +1 -1
- package/docs/types/OpenapiNumberFormats.html +1 -1
- package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiSchemaArray.html +1 -1
- package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/OpenapiSchemaBase.html +1 -1
- package/docs/types/OpenapiSchemaBody.html +1 -1
- package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/OpenapiSchemaInteger.html +1 -1
- package/docs/types/OpenapiSchemaNull.html +1 -1
- package/docs/types/OpenapiSchemaNumber.html +1 -1
- package/docs/types/OpenapiSchemaObject.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaString.html +1 -1
- package/docs/types/OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiTypeField.html +1 -1
- package/docs/types/Pascalized.html +1 -1
- package/docs/types/RoundingPrecision.html +1 -1
- package/docs/types/SerializerCasing.html +1 -1
- package/docs/types/SimpleObjectSerializerType.html +1 -1
- package/docs/types/Snakeified.html +1 -1
- package/docs/types/UpdateableAssociationProperties.html +1 -1
- package/docs/types/UpdateableProperties.html +1 -1
- package/docs/types/ValidationType.html +1 -1
- package/docs/types/ViewModel.html +1 -1
- package/docs/types/ViewModelClass.html +1 -1
- package/docs/types/WhereStatementForDream.html +1 -1
- package/docs/types/WhereStatementForDreamClass.html +1 -1
- package/docs/variables/DateTime-1.html +1 -1
- package/docs/variables/DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/DreamConst.html +1 -1
- package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
- package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/ops.html +1 -1
- package/docs/variables/primaryKeyTypes.html +1 -1
- package/package.json +5 -5
|
@@ -5,11 +5,11 @@ const pluralize_esm_1 = require("pluralize-esm");
|
|
|
5
5
|
const serializerGlobalNameFromFullyQualifiedModelName_js_1 = require("../../serializer/helpers/serializerGlobalNameFromFullyQualifiedModelName.js");
|
|
6
6
|
const camelize_js_1 = require("../camelize.js");
|
|
7
7
|
const globalClassNameFromFullyQualifiedModelName_js_1 = require("../globalClassNameFromFullyQualifiedModelName.js");
|
|
8
|
+
const pascalize_js_1 = require("../pascalize.js");
|
|
8
9
|
const relativeDreamPath_js_1 = require("../path/relativeDreamPath.js");
|
|
9
10
|
const snakeify_js_1 = require("../snakeify.js");
|
|
10
11
|
const standardizeFullyQualifiedModelName_js_1 = require("../standardizeFullyQualifiedModelName.js");
|
|
11
12
|
const uniq_js_1 = require("../uniq.js");
|
|
12
|
-
const pascalize_js_1 = require("../pascalize.js");
|
|
13
13
|
function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, includeAdminSerializers, connectionName = 'default', }) {
|
|
14
14
|
fullyQualifiedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
15
15
|
const modelClassName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
@@ -35,17 +35,19 @@ function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fully
|
|
|
35
35
|
const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
|
|
36
36
|
const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
|
|
37
37
|
const associationImportStatement = importStatementForModel(fullyQualifiedModelName, fullyQualifiedAssociatedModelName);
|
|
38
|
-
const associationName = (0, camelize_js_1.default)(associationModelName);
|
|
39
38
|
if (!attributeType)
|
|
40
39
|
throw new Error(`must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
41
40
|
switch (attributeType) {
|
|
42
|
-
case 'belongs_to':
|
|
41
|
+
case 'belongs_to': {
|
|
43
42
|
modelImportStatements.push(associationImportStatement);
|
|
43
|
+
const associationName = (0, camelize_js_1.default)(fullyQualifiedAssociatedModelName.split('/').pop());
|
|
44
|
+
const associationForeignKey = `${associationName}Id`;
|
|
44
45
|
return `
|
|
45
|
-
@deco.BelongsTo('${fullyQualifiedAssociatedModelName}'${descriptors.includes('optional') ? ',
|
|
46
|
+
@deco.BelongsTo('${fullyQualifiedAssociatedModelName}', { on: '${associationForeignKey}'${descriptors.includes('optional') ? ', optional: true' : ''} })
|
|
46
47
|
public ${associationName}: ${associationModelName}${descriptors.includes('optional') ? ' | null' : ''}
|
|
47
|
-
public ${
|
|
48
|
+
public ${associationForeignKey}: DreamColumn<${modelClassName}, '${associationName}Id'>
|
|
48
49
|
`;
|
|
50
|
+
}
|
|
49
51
|
case 'has_one':
|
|
50
52
|
case 'has_many':
|
|
51
53
|
return '';
|
|
@@ -32,6 +32,7 @@ function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, })
|
|
|
32
32
|
throw new Error(`Must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
33
33
|
switch (attributeType) {
|
|
34
34
|
case 'belongs_to': {
|
|
35
|
+
const attributeVariable = (0, camelize_js_1.default)(attributeName.split('/').pop());
|
|
35
36
|
const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
|
|
36
37
|
const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
|
|
37
38
|
const associationFactoryImportStatement = `import create${associationModelName} from '${(0, relativeDreamPath_js_1.default)('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
|
|
@@ -21,30 +21,20 @@ function generateMigrationContent({ connectionName = 'default', table, columnsWi
|
|
|
21
21
|
// instead, we'll add a check constraint that uses the STI child class name
|
|
22
22
|
const optional = userWantsThisOptional || !!stiChildClassName;
|
|
23
23
|
const sqlAttributeType = getAttributeType(attributeType, descriptors);
|
|
24
|
-
let attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName);
|
|
25
|
-
if (attributeName === undefined)
|
|
26
|
-
return acc;
|
|
27
24
|
if (attributeType !== undefined && ['has_one', 'has_many'].includes(attributeType))
|
|
28
25
|
return acc;
|
|
29
26
|
if (attributeType === 'citext')
|
|
30
27
|
requireCitextExtension = true;
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
await db.schema
|
|
35
|
-
.alterTable('${table}')
|
|
36
|
-
.addCheckConstraint(
|
|
37
|
-
'${table}_not_null_${attributeName}',
|
|
38
|
-
sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
|
|
39
|
-
)
|
|
40
|
-
.execute()`);
|
|
41
|
-
}
|
|
28
|
+
if (nonStandardAttributeName === undefined)
|
|
29
|
+
return acc;
|
|
30
|
+
let attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName);
|
|
42
31
|
switch (attributeType) {
|
|
43
32
|
case 'belongs_to':
|
|
44
33
|
columnDefs.push(generateBelongsToStr(connectionName, attributeName, {
|
|
45
34
|
primaryKeyType,
|
|
46
35
|
optional,
|
|
47
36
|
}));
|
|
37
|
+
attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName.split('/').pop());
|
|
48
38
|
attributeName = associationNameToForeignKey(attributeName);
|
|
49
39
|
break;
|
|
50
40
|
case 'enum':
|
|
@@ -78,7 +68,7 @@ function generateMigrationContent({ connectionName = 'default', table, columnsWi
|
|
|
78
68
|
break;
|
|
79
69
|
}
|
|
80
70
|
columnDrops.push(`.dropColumn('${attributeName}')`);
|
|
81
|
-
if (COLUMNS_TO_INDEX.includes(attributeName)) {
|
|
71
|
+
if (attributeType === 'belongs_to' || COLUMNS_TO_INDEX.includes(attributeName)) {
|
|
82
72
|
const indexName = `${table}_${attributeName}`;
|
|
83
73
|
indexDefs.push(`await db.schema
|
|
84
74
|
.createIndex('${indexName}')
|
|
@@ -87,6 +77,17 @@ function generateMigrationContent({ connectionName = 'default', table, columnsWi
|
|
|
87
77
|
.execute()`);
|
|
88
78
|
indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
|
|
89
79
|
}
|
|
80
|
+
if (stiChildClassName && !userWantsThisOptional) {
|
|
81
|
+
checkConstraints.push(`
|
|
82
|
+
|
|
83
|
+
await db.schema
|
|
84
|
+
.alterTable('${table}')
|
|
85
|
+
.addCheckConstraint(
|
|
86
|
+
'${table}_not_null_${attributeName}',
|
|
87
|
+
sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
|
|
88
|
+
)
|
|
89
|
+
.execute()`);
|
|
90
|
+
}
|
|
90
91
|
return acc;
|
|
91
92
|
}, { columnDefs: [], columnDrops: [], indexDefs: [], indexDrops: [] });
|
|
92
93
|
if (!table) {
|
|
@@ -256,7 +257,7 @@ function generateBelongsToStr(connectionName, associationName, { primaryKeyType,
|
|
|
256
257
|
const dbDriverClass = Query_js_1.default.dbDriverClass(connectionName);
|
|
257
258
|
const dataType = dbDriverClass.foreignKeyTypeFromPrimaryKey(primaryKeyType);
|
|
258
259
|
const references = (0, pluralize_esm_1.default)(associationName.replace(/\//g, '_').replace(/_id$/, ''));
|
|
259
|
-
return `.addColumn('${associationNameToForeignKey(associationName)}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
|
|
260
|
+
return `.addColumn('${associationNameToForeignKey(associationName.split('/').pop())}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
|
|
260
261
|
}
|
|
261
262
|
function generateIdStr({ primaryKeyType }) {
|
|
262
263
|
switch (primaryKeyType) {
|
|
@@ -54,7 +54,7 @@ function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes =
|
|
|
54
54
|
return '';
|
|
55
55
|
if (['belongs_to', 'has_one', 'has_many'].includes(type))
|
|
56
56
|
return '';
|
|
57
|
-
return `\n ${attribute(name, type, attr, stiBaseSerializer)}`;
|
|
57
|
+
return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
|
|
58
58
|
})
|
|
59
59
|
.join('')}`;
|
|
60
60
|
return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
|
|
@@ -69,9 +69,9 @@ ${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerCl
|
|
|
69
69
|
${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}
|
|
70
70
|
`;
|
|
71
71
|
}
|
|
72
|
-
function attribute(name, type, attr, stiBaseSerializer) {
|
|
72
|
+
function attribute(modelClassName, name, type, attr, stiBaseSerializer) {
|
|
73
73
|
if (name === 'type' && stiBaseSerializer) {
|
|
74
|
-
return `.attribute('type', { openapi: { type: 'string', enum: [StiChildClass.sanitizedName] } })`;
|
|
74
|
+
return `.attribute('type', { openapi: { type: 'string', enum: [(StiChildClass ?? ${modelClassName}).sanitizedName] } })`;
|
|
75
75
|
}
|
|
76
76
|
switch (type) {
|
|
77
77
|
case 'json':
|
|
@@ -3,5 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = comparisonKey;
|
|
4
4
|
const Dream_js_1 = require("../Dream.js");
|
|
5
5
|
function comparisonKey(val, toKey = undefined) {
|
|
6
|
-
|
|
6
|
+
if (val instanceof Dream_js_1.default)
|
|
7
|
+
return val.comparisonKey;
|
|
8
|
+
if (toKey)
|
|
9
|
+
return toKey(val);
|
|
10
|
+
if (val === null)
|
|
11
|
+
return null;
|
|
12
|
+
if (val === undefined)
|
|
13
|
+
return undefined;
|
|
14
|
+
switch (typeof val) {
|
|
15
|
+
case 'number':
|
|
16
|
+
case 'string':
|
|
17
|
+
case 'bigint':
|
|
18
|
+
return val;
|
|
19
|
+
default:
|
|
20
|
+
return val.toString();
|
|
21
|
+
}
|
|
7
22
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = percent;
|
|
4
|
+
const round_js_1 = require("./round.js");
|
|
5
|
+
function percent(numerator, denominator, precision) {
|
|
6
|
+
if (!numerator || !denominator)
|
|
7
|
+
return 0;
|
|
8
|
+
const percent = (numerator / denominator) * 100;
|
|
9
|
+
return precision ? (0, round_js_1.default)(percent, precision) : percent;
|
|
10
|
+
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UnsupportedValueFromComparisonFunction = void 0;
|
|
4
4
|
exports.default = sortBy;
|
|
5
|
+
const CalendarDate_js_1 = require("./CalendarDate.js");
|
|
6
|
+
const DateTime_js_1 = require("./DateTime.js");
|
|
5
7
|
/**
|
|
6
8
|
* Returns a copy of the array, sorted by the value returned by calling the function in the second argument on each element in the array
|
|
7
9
|
* Returns a copy of the array sorted by the return value of the function passed as the second argument.
|
|
@@ -26,10 +28,17 @@ function sortBy(array, valueToCompare) {
|
|
|
26
28
|
return arrayClone.sort((a, b) => {
|
|
27
29
|
const aPrime = valueToCompare(a);
|
|
28
30
|
const bPrime = valueToCompare(b);
|
|
29
|
-
if (typeof aPrime === 'string' && typeof bPrime === 'string')
|
|
30
|
-
return aPrime.localeCompare(bPrime);
|
|
31
31
|
if (typeof aPrime === 'number' && typeof bPrime === 'number')
|
|
32
32
|
return aPrime - bPrime;
|
|
33
|
+
if (typeof aPrime === 'bigint' && typeof bPrime === 'bigint')
|
|
34
|
+
return aPrime > bPrime ? 1 : aPrime < bPrime ? -1 : 0;
|
|
35
|
+
if (typeof aPrime === 'string' && typeof bPrime === 'string')
|
|
36
|
+
return aPrime.localeCompare(bPrime);
|
|
37
|
+
if (aPrime instanceof DateTime_js_1.DateTime && bPrime instanceof DateTime_js_1.DateTime)
|
|
38
|
+
return aPrime.valueOf() - bPrime.valueOf();
|
|
39
|
+
if ((aPrime instanceof DateTime_js_1.DateTime || aPrime instanceof CalendarDate_js_1.default) &&
|
|
40
|
+
(bPrime instanceof DateTime_js_1.DateTime || bPrime instanceof CalendarDate_js_1.default))
|
|
41
|
+
return (aPrime.toISO() ?? '').localeCompare(bPrime.toISO() ?? '');
|
|
33
42
|
throw new UnsupportedValueFromComparisonFunction(aPrime, bPrime);
|
|
34
43
|
});
|
|
35
44
|
}
|
|
@@ -4,13 +4,10 @@ exports.default = uniq;
|
|
|
4
4
|
const comparisonKey_js_1 = require("./comparisonKey.js");
|
|
5
5
|
function uniq(arr, toKey = undefined) {
|
|
6
6
|
const map = arr.reduce((acc, val) => {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// order in which they were added, but in ascending numerical order.
|
|
11
|
-
const key = typeof baseKey === 'string' ? baseKey : `_${baseKey}`;
|
|
12
|
-
acc[key] ||= val;
|
|
7
|
+
const key = (0, comparisonKey_js_1.default)(val, toKey);
|
|
8
|
+
if (!acc.has(key))
|
|
9
|
+
acc.set(key, val);
|
|
13
10
|
return acc;
|
|
14
|
-
},
|
|
15
|
-
return
|
|
11
|
+
}, new Map());
|
|
12
|
+
return [...map.values()];
|
|
16
13
|
}
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.globalClassNameFromFullyQualifiedModelName = exports.Env = exports.DreamLogos = exports.DateTime = exports.compact = exports.cloneDeepSafe = exports.generateDream = exports.capitalize = exports.camelize = exports.CalendarDate = exports.Benchmark = exports.ValidationError = exports.MissingSerializersDefinition = exports.RecordNotFound = exports.GlobalNameNotSet = exports.NotNullViolation = exports.DataTypeColumnTypeMismatch = exports.DataIncompatibleWithDatabaseField = exports.ColumnOverflow = exports.CheckConstraintViolation = exports.CreateOrFindByFailedToCreateAndFind = exports.NonLoadedAssociation = exports.Encrypt = exports.PostgresQueryDriver = exports.KyselyQueryDriver = exports.QueryDriverBase = exports.Query = exports.DreamTransaction = exports.openapiShorthandPrimitiveTypes = exports.openapiPrimitiveTypes = exports.DreamConst = exports.Dream = exports.DreamAppAllowedPackageManagersEnumValues = exports.DreamApp = exports.lookupClassByGlobalName = exports.DreamImporter = exports.Decorators = exports.STI = exports.SoftDelete = exports.ReplicaSafe = exports.validateTable = exports.validateColumn = exports.DreamMigrationHelpers = exports.untypedDb = exports.pgErrorType = exports.dreamDbConnections = exports.closeAllDbConnections = exports.DreamCLI = exports.CliFileWriter = exports.DreamBin = void 0;
|
|
4
|
-
exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = exports.sharedPathPrefix = exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = exports.intersection = exports.hyphenize = exports.groupBy = void 0;
|
|
4
|
+
exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = exports.percent = exports.sharedPathPrefix = exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = exports.intersection = exports.hyphenize = exports.groupBy = void 0;
|
|
5
5
|
var index_js_1 = require("./bin/index.js");
|
|
6
6
|
Object.defineProperty(exports, "DreamBin", { enumerable: true, get: function () { return index_js_1.default; } });
|
|
7
7
|
var CliFileWriter_js_1 = require("./cli/CliFileWriter.js");
|
|
@@ -118,6 +118,8 @@ var relativeDreamPath_js_1 = require("./helpers/path/relativeDreamPath.js");
|
|
|
118
118
|
Object.defineProperty(exports, "relativeDreamPath", { enumerable: true, get: function () { return relativeDreamPath_js_1.default; } });
|
|
119
119
|
var sharedPathPrefix_js_1 = require("./helpers/path/sharedPathPrefix.js");
|
|
120
120
|
Object.defineProperty(exports, "sharedPathPrefix", { enumerable: true, get: function () { return sharedPathPrefix_js_1.default; } });
|
|
121
|
+
var percent_js_1 = require("./helpers/percent.js");
|
|
122
|
+
Object.defineProperty(exports, "percent", { enumerable: true, get: function () { return percent_js_1.default; } });
|
|
121
123
|
var range_js_1 = require("./helpers/range.js");
|
|
122
124
|
Object.defineProperty(exports, "Range", { enumerable: true, get: function () { return range_js_1.Range; } });
|
|
123
125
|
Object.defineProperty(exports, "range", { enumerable: true, get: function () { return range_js_1.default; } });
|
package/dist/esm/src/Dream.js
CHANGED
|
@@ -41,6 +41,7 @@ import CreateOrUpdateByFailedToCreateAndUpdate from './errors/CreateOrUpdateByFa
|
|
|
41
41
|
import GlobalNameNotSet from './errors/dream-app/GlobalNameNotSet.js';
|
|
42
42
|
import DreamMissingRequiredOverride from './errors/DreamMissingRequiredOverride.js';
|
|
43
43
|
import NonExistentScopeProvidedToResort from './errors/NonExistentScopeProvidedToResort.js';
|
|
44
|
+
import RecordNotFound from './errors/RecordNotFound.js';
|
|
44
45
|
import MissingSerializersDefinition from './errors/serializers/MissingSerializersDefinition.js';
|
|
45
46
|
import CalendarDate from './helpers/CalendarDate.js';
|
|
46
47
|
import cloneDeepSafe from './helpers/cloneDeepSafe.js';
|
|
@@ -3218,6 +3219,61 @@ export default class Dream {
|
|
|
3218
3219
|
load(...args) {
|
|
3219
3220
|
return new LoadBuilder(this).load(...args);
|
|
3220
3221
|
}
|
|
3222
|
+
/**
|
|
3223
|
+
* If the association is already loaded on the instance, it returns the loaded value
|
|
3224
|
+
* immediately without making a database query. If the association is not loaded,
|
|
3225
|
+
* it performs a database query to fetch the association.
|
|
3226
|
+
*
|
|
3227
|
+
* If a query is performed, the association is set on the model so that future calls to
|
|
3228
|
+
* access this association can access the already loaded value.
|
|
3229
|
+
*
|
|
3230
|
+
* ```ts
|
|
3231
|
+
* // return the already loaded user if it exists or fetch it from the database otherwise
|
|
3232
|
+
* const user = await post.associationOrFail('user')
|
|
3233
|
+
* ```
|
|
3234
|
+
*
|
|
3235
|
+
* @param associationName - The name of the BelongsTo or HasOne association
|
|
3236
|
+
* @returns The associated model instance or null
|
|
3237
|
+
*/
|
|
3238
|
+
async association(associationName) {
|
|
3239
|
+
if (!this.loaded(associationName)) {
|
|
3240
|
+
const association = this.getAssociationMetadata(associationName);
|
|
3241
|
+
if (association?.type === 'HasMany') {
|
|
3242
|
+
this[associationName] = (await this.associationQuery(associationName).all());
|
|
3243
|
+
}
|
|
3244
|
+
else {
|
|
3245
|
+
this[associationName] = (await this.associationQuery(associationName).first());
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
return this[associationName];
|
|
3249
|
+
}
|
|
3250
|
+
/**
|
|
3251
|
+
* If the association is already loaded on the instance, it returns the loaded value
|
|
3252
|
+
* immediately without making a database query. If the association is not loaded,
|
|
3253
|
+
* it performs a database query to fetch the association.
|
|
3254
|
+
*
|
|
3255
|
+
* Unlike `association`, this method throws an exception if no associated
|
|
3256
|
+
* record is found, guaranteeing a non-null result.
|
|
3257
|
+
*
|
|
3258
|
+
* If a query is performed, the association is set on the model so that future calls to
|
|
3259
|
+
* access this association can access the already loaded value.
|
|
3260
|
+
*
|
|
3261
|
+
* ```ts
|
|
3262
|
+
* // return the already loaded user if it exists or fetch it from the database otherwise,
|
|
3263
|
+
* // throwing RecordNotFound either way if the associated model does not exist
|
|
3264
|
+
* const user = await post.associationOrFail('user')
|
|
3265
|
+
* ```
|
|
3266
|
+
*
|
|
3267
|
+
* @param associationName - The name of the BelongsTo or HasOne association
|
|
3268
|
+
* @returns The associated model instance (never null)
|
|
3269
|
+
* @throws RecordNotFound if no associated record exists
|
|
3270
|
+
*/
|
|
3271
|
+
async associationOrFail(associationName) {
|
|
3272
|
+
const response = await this.association(associationName);
|
|
3273
|
+
if (this[associationName] === null)
|
|
3274
|
+
throw new RecordNotFound(this['sanitizedConstructorName']);
|
|
3275
|
+
return response;
|
|
3276
|
+
}
|
|
3221
3277
|
/**
|
|
3222
3278
|
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
3223
3279
|
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
@@ -3278,8 +3334,8 @@ export default class Dream {
|
|
|
3278
3334
|
* 4. the individual query becomes more complex the more associations are included
|
|
3279
3335
|
* 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.load(...).findEach(...)` avoids instantiating massive amounts of data at once
|
|
3280
3336
|
*
|
|
3281
|
-
*
|
|
3282
|
-
*
|
|
3337
|
+
* Note: Left join loading loads all data in a single SQL query but has trade-offs compared
|
|
3338
|
+
* to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
|
|
3283
3339
|
*
|
|
3284
3340
|
* ```ts
|
|
3285
3341
|
* await user
|
|
@@ -3315,6 +3371,9 @@ export default class Dream {
|
|
|
3315
3371
|
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
3316
3372
|
* automatically preloads all associations that will be needed during serialization.
|
|
3317
3373
|
*
|
|
3374
|
+
* Note: Left join loading loads all data in a single SQL query but has trade-offs compared
|
|
3375
|
+
* to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
|
|
3376
|
+
*
|
|
3318
3377
|
* ```ts
|
|
3319
3378
|
* // Instead of manually specifying all associations:
|
|
3320
3379
|
* await User.preload('posts', 'comments', 'replies').all()
|
|
@@ -22,6 +22,12 @@ export default class DreamBin {
|
|
|
22
22
|
await Query.dbDriverClass(connectionName).dbDrop(connectionName);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
static async dbEnsureAllMigrationsHaveBeenRun() {
|
|
26
|
+
const dreamApp = DreamApp.getOrFail();
|
|
27
|
+
for (const connectionName of Object.keys(dreamApp.dbCredentials)) {
|
|
28
|
+
await Query.dbDriverClass(connectionName).ensureAllMigrationsHaveBeenRun(connectionName);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
25
31
|
static async dbMigrate() {
|
|
26
32
|
const dreamApp = DreamApp.getOrFail();
|
|
27
33
|
for (const connectionName of Object.keys(dreamApp.dbCredentials)) {
|
|
@@ -32,7 +32,7 @@ ${INDENT}
|
|
|
32
32
|
${INDENT} - decimal:
|
|
33
33
|
${INDENT} - decimal[]:
|
|
34
34
|
${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
|
|
35
|
-
${INDENT}
|
|
35
|
+
${INDENT}
|
|
36
36
|
${INDENT} leveraging arrays, add the "[]" suffix, e.g.: volume:decimal[]:3,2
|
|
37
37
|
${INDENT}
|
|
38
38
|
${INDENT} - enum:
|
|
@@ -71,7 +71,7 @@ export default class DreamCLI {
|
|
|
71
71
|
.description('sync introspects your database, updating your schema to reflect, and then syncs the new schema with the installed dream node module, allowing it provide your schema to the underlying kysely integration')
|
|
72
72
|
.option('--schema-only')
|
|
73
73
|
.action(async (options = {}) => {
|
|
74
|
-
await initializeDreamApp();
|
|
74
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
75
75
|
await DreamBin.sync(() => { }, options);
|
|
76
76
|
process.exit();
|
|
77
77
|
});
|
|
@@ -93,7 +93,7 @@ export default class DreamCLI {
|
|
|
93
93
|
.option('--connection-name <connectionName>', 'the connection name you wish to use for your migration')
|
|
94
94
|
.argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
|
|
95
95
|
.action(async (migrationName, columnsWithTypes, options) => {
|
|
96
|
-
await initializeDreamApp();
|
|
96
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
97
97
|
await DreamBin.generateMigration(migrationName, columnsWithTypes, options.connectionName || 'default');
|
|
98
98
|
process.exit();
|
|
99
99
|
});
|
|
@@ -109,7 +109,7 @@ export default class DreamCLI {
|
|
|
109
109
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
110
110
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
111
111
|
.action(async (modelName, columnsWithTypes, options) => {
|
|
112
|
-
await initializeDreamApp();
|
|
112
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
113
113
|
await DreamBin.generateDream(modelName, columnsWithTypes, options);
|
|
114
114
|
process.exit();
|
|
115
115
|
});
|
|
@@ -126,7 +126,7 @@ ${INDENT} to extend the Room model in src/app/models/Room: Room
|
|
|
126
126
|
${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
|
|
127
127
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
128
128
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
129
|
-
await initializeDreamApp();
|
|
129
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
130
130
|
if (extendsWord !== 'extends')
|
|
131
131
|
throw new Error('Expecting: `<child-name> extends <parent-name> <columns-and-types>');
|
|
132
132
|
await DreamBin.generateStiChild(childModelName, parentModelName, columnsWithTypes, options);
|
|
@@ -137,16 +137,24 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
137
137
|
.description('creates a new database, seeding from local .env or .env.test if NODE_ENV=test is set for env vars')
|
|
138
138
|
.action(async () => {
|
|
139
139
|
EnvInternal.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
|
|
140
|
-
await initializeDreamApp({
|
|
140
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
141
141
|
await DreamBin.dbCreate();
|
|
142
142
|
process.exit();
|
|
143
143
|
});
|
|
144
|
+
program
|
|
145
|
+
.command('db:integrity-check')
|
|
146
|
+
.description('db:integrity-check fails if migrations need to be run')
|
|
147
|
+
.action(async () => {
|
|
148
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
149
|
+
await DreamBin.dbEnsureAllMigrationsHaveBeenRun();
|
|
150
|
+
process.exit();
|
|
151
|
+
});
|
|
144
152
|
program
|
|
145
153
|
.command('db:migrate')
|
|
146
154
|
.description('db:migrate runs any outstanding database migrations')
|
|
147
155
|
.option('--skip-sync', 'skips syncing local schema after running migrations')
|
|
148
156
|
.action(async ({ skipSync }) => {
|
|
149
|
-
await initializeDreamApp({
|
|
157
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
150
158
|
await DreamBin.dbMigrate();
|
|
151
159
|
if (EnvInternal.isDevelopmentOrTest && !skipSync) {
|
|
152
160
|
await DreamBin.sync(onSync);
|
|
@@ -159,7 +167,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
159
167
|
.option('--steps <number>', 'number of steps back to travel', myParseInt, 1)
|
|
160
168
|
.option('--skip-sync', 'skips syncing local schema after running migrations')
|
|
161
169
|
.action(async ({ steps, skipSync }) => {
|
|
162
|
-
await initializeDreamApp({
|
|
170
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
163
171
|
await DreamBin.dbRollback({ steps });
|
|
164
172
|
if (EnvInternal.isDevelopmentOrTest && !skipSync) {
|
|
165
173
|
await DreamBin.sync(onSync);
|
|
@@ -171,7 +179,7 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
171
179
|
.description('drops the database, seeding from local .env or .env.test if NODE_ENV=test is set for env vars')
|
|
172
180
|
.action(async () => {
|
|
173
181
|
EnvInternal.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
|
|
174
|
-
await initializeDreamApp({
|
|
182
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
175
183
|
await DreamBin.dbDrop();
|
|
176
184
|
process.exit();
|
|
177
185
|
});
|
|
@@ -180,11 +188,11 @@ ${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Co
|
|
|
180
188
|
.description('runs db:drop (safely), then db:create, db:migrate, and db:seed')
|
|
181
189
|
.action(async () => {
|
|
182
190
|
EnvInternal.setBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
|
|
183
|
-
await initializeDreamApp({
|
|
191
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
184
192
|
await DreamBin.dbDrop();
|
|
185
193
|
await DreamBin.dbCreate();
|
|
186
194
|
EnvInternal.unsetBoolean('BYPASS_DB_CONNECTIONS_DURING_INIT');
|
|
187
|
-
await initializeDreamApp({
|
|
195
|
+
await initializeDreamApp({ bypassDreamIntegrityChecks: true });
|
|
188
196
|
await DreamBin.dbMigrate();
|
|
189
197
|
await DreamBin.sync(onSync);
|
|
190
198
|
await seedDb();
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { sql } from 'kysely';
|
|
2
2
|
export default class DreamMigrationHelpers {
|
|
3
|
+
/**
|
|
4
|
+
* Rename a table and its associated primary key sequence.
|
|
5
|
+
*
|
|
6
|
+
* This method renames both the table and its primary key sequence to keep them
|
|
7
|
+
* in sync. When PostgreSQL creates a table with a serial or bigserial primary key,
|
|
8
|
+
* it automatically creates a sequence named `{tablename}_id_seq`. If you only rename
|
|
9
|
+
* the table, the sequence keeps the old name, which can cause confusion and issues.
|
|
10
|
+
*
|
|
11
|
+
* This method is only suitable for tables that have a serial or bigserial primary
|
|
12
|
+
* key column named 'id'.
|
|
13
|
+
*
|
|
14
|
+
* @param db - The Kysely database object passed into the migration up/down function
|
|
15
|
+
* @param from - The current name of the table to rename
|
|
16
|
+
* @param to - The new name for the table
|
|
17
|
+
*/
|
|
18
|
+
static async renameTable(db, from, to) {
|
|
19
|
+
await db.schema.alterTable(from).renameTo(to).execute();
|
|
20
|
+
await sql `ALTER SEQUENCE ${from}_id_seq RENAME TO ${to}_id_seq`.execute(db);
|
|
21
|
+
}
|
|
3
22
|
/**
|
|
4
23
|
* Unique indexes cannot be populated by the same value even within a transaction,
|
|
5
24
|
* but deferrable unique constraints can.
|
|
@@ -20,14 +20,14 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
20
20
|
* }
|
|
21
21
|
* ```
|
|
22
22
|
*
|
|
23
|
-
* @param opts.
|
|
23
|
+
* @param opts.on - A custom column name to use for joining associations on.
|
|
24
24
|
* @param opts.optional - Whether or not this association is optional. Defaults to false.
|
|
25
25
|
* @param opts.polymorphic - If true, this association will be treated as a polymorphic association.
|
|
26
26
|
* @param opts.primaryKeyOverride - A custom column name to use for the primary key.
|
|
27
27
|
* @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
|
|
28
28
|
*/
|
|
29
29
|
export default function BelongsTo(globalAssociationNameOrNames, opts = {}) {
|
|
30
|
-
const { foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
|
|
30
|
+
const { on: foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
|
|
31
31
|
return function (_, context) {
|
|
32
32
|
const key = context.name;
|
|
33
33
|
context.addInitializer(function () {
|
|
@@ -20,7 +20,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
20
20
|
*
|
|
21
21
|
* @param opts.dependent - Can be either "destroy" or undefined. If "destroy", this record will be cascade deleted if the base model is destroyed.
|
|
22
22
|
* @param opts.distinct - Can be a column name, or else a boolean. If a column name, a distinct clause will be applied to the column. If true, a distinct clause will be applied to the primary key.
|
|
23
|
-
* @param opts.
|
|
23
|
+
* @param opts.on - A custom column name to use for joining associations on.
|
|
24
24
|
* @param opts.and - An and-clause to be applied when this association is loaded
|
|
25
25
|
* @param opts.andNot - A not and-clause to be applied when this association is loaded
|
|
26
26
|
* @param opts.andAny - An andAny clause to be applied when this association is loaded
|
|
@@ -34,7 +34,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
34
34
|
* @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
|
|
35
35
|
*/
|
|
36
36
|
export default function HasMany(globalAssociationNameOrNames, opts = {}) {
|
|
37
|
-
const { dependent, distinct, foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
37
|
+
const { dependent, distinct, on: foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
38
38
|
return function (_, context) {
|
|
39
39
|
const key = context.name;
|
|
40
40
|
context.addInitializer(function () {
|
|
@@ -19,7 +19,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
19
19
|
* ```
|
|
20
20
|
*
|
|
21
21
|
* @param opts.dependent - Can be either "destroy" or undefined. If "destroy", this record will be cascade deleted if the base model is destroyed.
|
|
22
|
-
* @param opts.
|
|
22
|
+
* @param opts.on - A custom column name to use for joining associations on.
|
|
23
23
|
* @param opts.and - An and-clause to be applied when this association is loaded
|
|
24
24
|
* @param opts.andNot - A not and-clause to be applied when this association is loaded
|
|
25
25
|
* @param opts.andAny - An andAny clause to be applied when this association is loaded
|
|
@@ -32,7 +32,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
32
32
|
* @param opts.withoutDefaultScopes - A list of default scopes to bypass when loading this association
|
|
33
33
|
*/
|
|
34
34
|
export default function HasOne(globalAssociationNameOrNames, opts = {}) {
|
|
35
|
-
const { dependent, foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
35
|
+
const { dependent, on: foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
36
36
|
return function (_, context) {
|
|
37
37
|
const key = context.name;
|
|
38
38
|
context.addInitializer(function () {
|
|
@@ -1215,7 +1215,10 @@ export default class Query {
|
|
|
1215
1215
|
const recordCount = await this.count();
|
|
1216
1216
|
const pageSize = opts.pageSize || DreamApp.getOrFail().paginationPageSize;
|
|
1217
1217
|
const pageCount = Math.ceil(recordCount / pageSize);
|
|
1218
|
-
const
|
|
1218
|
+
const query = this.orderStatements.length
|
|
1219
|
+
? this
|
|
1220
|
+
: this.order({ [this.namespacedPrimaryKey]: 'asc' });
|
|
1221
|
+
const results = await query
|
|
1219
1222
|
.limit(pageSize)
|
|
1220
1223
|
.offset((page - 1) * pageSize)
|
|
1221
1224
|
.all();
|
|
@@ -20,6 +20,12 @@ export default class QueryDriverBase {
|
|
|
20
20
|
this.connectionOverride = query['originalOpts'].connection;
|
|
21
21
|
this.innerJoinDreamClasses = Object.freeze(query['originalOpts'].innerJoinDreamClasses || []);
|
|
22
22
|
}
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
24
|
+
static async ensureAllMigrationsHaveBeenRun(
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
+
connectionName) {
|
|
27
|
+
throw new Error('override ensureAllMigrationsHaveBeenRun in child class');
|
|
28
|
+
}
|
|
23
29
|
/**
|
|
24
30
|
* migrate the database. Must respond to the NODE_ENV value.
|
|
25
31
|
*/
|
|
@@ -13,7 +13,7 @@ import { CliFileWriter } from '../../cli/CliFileWriter.js';
|
|
|
13
13
|
import DreamCLI from '../../cli/index.js';
|
|
14
14
|
import { CHECK_VIOLATION, COLUMN_OVERFLOW, INVALID_INPUT_SYNTAX, NOT_NULL_VIOLATION, pgErrorType, } from '../../db/errors.js';
|
|
15
15
|
import syncDbTypesFiles from '../../db/helpers/syncDbTypesFiles.js';
|
|
16
|
-
import _db from '../../db/index.js';
|
|
16
|
+
import { default as _db } from '../../db/index.js';
|
|
17
17
|
import associationToGetterSetterProp from '../../decorators/field/association/associationToGetterSetterProp.js';
|
|
18
18
|
import PackageManager from '../../dream-app/helpers/PackageManager.js';
|
|
19
19
|
import DreamApp from '../../dream-app/index.js';
|
|
@@ -64,6 +64,7 @@ import softDeleteDream from '../internal/softDeleteDream.js';
|
|
|
64
64
|
import sqlResultToDreamInstance from '../internal/sqlResultToDreamInstance.js';
|
|
65
65
|
import Query from '../Query.js';
|
|
66
66
|
import QueryDriverBase from './Base.js';
|
|
67
|
+
import checkForNeedToBeRunMigrations from './helpers/kysely/checkForNeedToBeRunMigrations.js';
|
|
67
68
|
import runMigration from './helpers/kysely/runMigration.js';
|
|
68
69
|
export default class KyselyQueryDriver extends QueryDriverBase {
|
|
69
70
|
// ATTENTION FRED
|
|
@@ -100,6 +101,14 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
100
101
|
}),
|
|
101
102
|
});
|
|
102
103
|
}
|
|
104
|
+
static async ensureAllMigrationsHaveBeenRun(connectionName) {
|
|
105
|
+
const migrationsNeedToBeRun = await checkForNeedToBeRunMigrations({
|
|
106
|
+
connectionName,
|
|
107
|
+
dialectProvider: this.dialectProvider(connectionName, 'primary'),
|
|
108
|
+
});
|
|
109
|
+
if (migrationsNeedToBeRun)
|
|
110
|
+
throw new Error(`Migrations need to be run on ${connectionName} database`);
|
|
111
|
+
}
|
|
103
112
|
/**
|
|
104
113
|
* migrate the database. Must respond to the NODE_ENV value.
|
|
105
114
|
*/
|
|
@@ -694,9 +703,8 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
694
703
|
return orderByDirection(direction);
|
|
695
704
|
}
|
|
696
705
|
buildUpdate(attributes) {
|
|
697
|
-
let kyselyQuery = this.dbFor('update')
|
|
698
|
-
|
|
699
|
-
.set(attributes);
|
|
706
|
+
let kyselyQuery = this.dbFor('update').updateTable(this.query['tableName']);
|
|
707
|
+
kyselyQuery = kyselyQuery.set(attributes);
|
|
700
708
|
kyselyQuery = this.conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery);
|
|
701
709
|
const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
|
|
702
710
|
return new this.constructor(results.clone).buildCommon(results.kyselyQuery);
|