@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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FileMigrationProvider, Migrator } from 'kysely';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { closeAllConnectionsForConnectionName } from '../../../../db/DreamDbConnection.js';
|
|
5
|
+
import db from '../../../../db/index.js';
|
|
6
|
+
import migrationFolderPath from './migrationFolderPath.js';
|
|
7
|
+
export default async function checkForNeedToBeRunMigrations({ connectionName, dialectProvider, }) {
|
|
8
|
+
const migrationFolder = migrationFolderPath(connectionName);
|
|
9
|
+
// Ensure the migration folder exists
|
|
10
|
+
await fs.mkdir(migrationFolder, { recursive: true });
|
|
11
|
+
const kyselyDb = db(connectionName, 'primary', dialectProvider);
|
|
12
|
+
const migrator = new Migrator({
|
|
13
|
+
db: kyselyDb,
|
|
14
|
+
allowUnorderedMigrations: true,
|
|
15
|
+
provider: new FileMigrationProvider({
|
|
16
|
+
fs,
|
|
17
|
+
path,
|
|
18
|
+
migrationFolder,
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
21
|
+
const result = (await migrator.getMigrations()).some(migrationInfo => !migrationInfo.executedAt);
|
|
22
|
+
await closeAllConnectionsForConnectionName(connectionName);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import DreamApp from '../../../../dream-app/index.js';
|
|
3
|
+
export default function migrationFolderPath(connectionName) {
|
|
4
|
+
const dreamApp = DreamApp.getOrFail();
|
|
5
|
+
return connectionName === 'default'
|
|
6
|
+
? path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations')
|
|
7
|
+
: path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations', connectionName);
|
|
8
|
+
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { FileMigrationProvider, Migrator } from 'kysely';
|
|
2
2
|
import * as fs from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
+
import DreamCLI from '../../../../cli/index.js';
|
|
4
5
|
import colorize from '../../../../cli/logger/loggable/colorize.js';
|
|
5
6
|
import { closeAllConnectionsForConnectionName, closeAllDbConnections, } from '../../../../db/DreamDbConnection.js';
|
|
6
7
|
import db from '../../../../db/index.js';
|
|
7
8
|
import DreamApp from '../../../../dream-app/index.js';
|
|
8
|
-
import
|
|
9
|
+
import migrationFolderPath from './migrationFolderPath.js';
|
|
9
10
|
export default async function runMigration({ connectionName, mode = 'migrate', dialectProvider, }) {
|
|
10
|
-
const
|
|
11
|
-
const migrationFolder = connectionName === 'default'
|
|
12
|
-
? path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations')
|
|
13
|
-
: path.join(dreamApp.projectRoot, dreamApp.paths.db, 'migrations', connectionName);
|
|
11
|
+
const migrationFolder = migrationFolderPath(connectionName);
|
|
14
12
|
// Ensure the migration folder exists
|
|
15
13
|
await fs.mkdir(migrationFolder, { recursive: true });
|
|
16
14
|
const kyselyDb = db(connectionName, 'primary', dialectProvider);
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { sql } from 'kysely';
|
|
2
1
|
export default function orderByDirection(dir) {
|
|
3
2
|
switch (dir) {
|
|
4
3
|
case 'asc':
|
|
5
4
|
case null:
|
|
6
|
-
return
|
|
5
|
+
return (obj) => obj.asc().nullsFirst();
|
|
7
6
|
case 'desc':
|
|
8
|
-
return
|
|
7
|
+
return (obj) => obj.desc().nullsLast();
|
|
9
8
|
default: {
|
|
10
9
|
// protection so that if a new OrderDir is ever added, this will throw a type error at build time
|
|
11
10
|
const _never = dir;
|
|
@@ -49,8 +49,8 @@ async function undestroyDreamWithTransaction(dream, txn, options) {
|
|
|
49
49
|
* deleting by one of the beforeDestroy model hooks
|
|
50
50
|
*/
|
|
51
51
|
async function doUndestroyDream(dream, txn) {
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const updateStatement = txn.kyselyTransaction.updateTable(dream.table);
|
|
53
|
+
let query = updateStatement
|
|
54
54
|
.where(dream['_primaryKey'], '=', dream.primaryKeyValue())
|
|
55
55
|
.set({ [dream['_deletedAtField']]: null });
|
|
56
56
|
const dreamClass = dream.constructor;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as util from 'node:util';
|
|
2
2
|
import validateTable from '../db/validators/validateTable.js';
|
|
3
3
|
import Query from '../dream/Query.js';
|
|
4
|
+
import PostgresQueryDriver from '../dream/QueryDriver/Postgres.js';
|
|
4
5
|
import Encrypt from '../encrypt/index.js';
|
|
5
6
|
import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppInitMissingCallToLoadModels.js';
|
|
6
7
|
import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
|
|
@@ -10,7 +11,6 @@ import EnvInternal from '../helpers/EnvInternal.js';
|
|
|
10
11
|
import { cacheDreamApp, getCachedDreamAppOrFail } from './cache.js';
|
|
11
12
|
import importModels, { getModelsOrFail } from './helpers/importers/importModels.js';
|
|
12
13
|
import importSerializers, { getSerializersOrFail, setCachedSerializers, } from './helpers/importers/importSerializers.js';
|
|
13
|
-
import PostgresQueryDriver from '../dream/QueryDriver/Postgres.js';
|
|
14
14
|
// this needs to be done top-level to ensure proper configuration
|
|
15
15
|
Settings.defaultZone = 'UTC';
|
|
16
16
|
export default class DreamApp {
|
|
@@ -40,7 +40,7 @@ export default class DreamApp {
|
|
|
40
40
|
await plugin(dreamApp);
|
|
41
41
|
}
|
|
42
42
|
dreamApp.validateAppBuildIntegrity({
|
|
43
|
-
|
|
43
|
+
bypassDreamIntegrityChecks: opts.bypassDreamIntegrityChecks || false,
|
|
44
44
|
});
|
|
45
45
|
return dreamApp;
|
|
46
46
|
}
|
|
@@ -51,14 +51,14 @@ export default class DreamApp {
|
|
|
51
51
|
* that would render it in an invalid state
|
|
52
52
|
*
|
|
53
53
|
*/
|
|
54
|
-
validateAppBuildIntegrity({
|
|
54
|
+
validateAppBuildIntegrity({ bypassDreamIntegrityChecks }) {
|
|
55
55
|
if (!this.projectRoot)
|
|
56
56
|
throw new DreamAppInitMissingMissingProjectRoot();
|
|
57
57
|
if (!this.loadedModels)
|
|
58
58
|
throw new DreamAppInitMissingCallToLoadModels();
|
|
59
59
|
if (this.encryption?.columns?.current)
|
|
60
60
|
DreamApp.checkKey('columns', this.encryption.columns.current.key, this.encryption.columns.current.algorithm);
|
|
61
|
-
if (!
|
|
61
|
+
if (!bypassDreamIntegrityChecks)
|
|
62
62
|
this.validateApplicationModels();
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
@@ -13,11 +13,10 @@ export class InvalidComputedForeignKey extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
get message() {
|
|
15
15
|
return `
|
|
16
|
-
Add an explicit
|
|
16
|
+
Add an explicit \`on\` declaration to this association definition:
|
|
17
17
|
Dream class: ${this.dreamClass.sanitizedName}
|
|
18
18
|
Association: ${this.partialAssociation.as}
|
|
19
|
-
Dream tried ${this.computedForeignKey} automatically, but it isn't a column in table ${this.table}
|
|
20
|
-
`;
|
|
19
|
+
Dream tried ${this.computedForeignKey} automatically, but it isn't a column in table ${this.table}.`;
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
22
|
export class ExplicitForeignKeyRequired extends Error {
|
|
@@ -47,7 +46,7 @@ export function checkForeignKey(explicitForeignKey, computedForeignKey, dreamCla
|
|
|
47
46
|
table = dreamClass.table;
|
|
48
47
|
else
|
|
49
48
|
table = modelCBtoSingleDreamClass(dreamClass, partialAssociation).table;
|
|
50
|
-
const tableColumns = Object.keys(dreamClass.prototype.schema[table]?.columns);
|
|
49
|
+
const tableColumns = Object.keys(dreamClass.prototype.schema[table]?.columns ?? {});
|
|
51
50
|
const validForeignKey = tableColumns.includes(computedForeignKey);
|
|
52
51
|
if (validForeignKey)
|
|
53
52
|
return;
|
|
@@ -5,6 +5,7 @@ import dbTypesFilenameForConnection from '../../db/helpers/dbTypesFilenameForCon
|
|
|
5
5
|
import DreamApp from '../../dream-app/index.js';
|
|
6
6
|
import { DreamConst } from '../../dream/constants.js';
|
|
7
7
|
import Query from '../../dream/Query.js';
|
|
8
|
+
import { ExplicitForeignKeyRequired, InvalidComputedForeignKey, } from '../../errors/associations/InvalidComputedForeignKey.js';
|
|
8
9
|
import FailedToIdentifyAssociation from '../../errors/schema-builder/FailedToIdentifyAssociation.js';
|
|
9
10
|
import camelize from '../camelize.js';
|
|
10
11
|
import compact from '../compact.js';
|
|
@@ -263,33 +264,39 @@ may need to update the table getter in the corresponding Dream.
|
|
|
263
264
|
this.hasForeignKeyError = true;
|
|
264
265
|
// console.error(err)
|
|
265
266
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
267
|
+
try {
|
|
268
|
+
tableAssociationData[associationName] ||= {
|
|
269
|
+
tables: [],
|
|
270
|
+
type: associationMetaData.type,
|
|
271
|
+
polymorphic: associationMetaData.polymorphic,
|
|
272
|
+
foreignKey,
|
|
273
|
+
foreignKeyTypeColumn: associationMetaData.polymorphic
|
|
274
|
+
? associationMetaData?.foreignKeyTypeField?.() || null
|
|
275
|
+
: null,
|
|
276
|
+
optional,
|
|
277
|
+
where,
|
|
278
|
+
};
|
|
279
|
+
if (foreignKey)
|
|
280
|
+
tableAssociationData[associationName]['foreignKey'] = foreignKey;
|
|
281
|
+
if (Array.isArray(dreamClassOrClasses)) {
|
|
282
|
+
const tables = dreamClassOrClasses.map(dreamClass => dreamClass.table);
|
|
283
|
+
tableAssociationData[associationName].tables = [
|
|
284
|
+
...tableAssociationData[associationName].tables,
|
|
285
|
+
...tables,
|
|
286
|
+
];
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
tableAssociationData[associationName].tables.push(dreamClassOrClasses.table);
|
|
290
|
+
}
|
|
291
|
+
// guarantee unique
|
|
281
292
|
tableAssociationData[associationName].tables = [
|
|
282
|
-
...tableAssociationData[associationName].tables,
|
|
283
|
-
...tables,
|
|
293
|
+
...new Set(tableAssociationData[associationName].tables),
|
|
284
294
|
];
|
|
285
295
|
}
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
catch (error) {
|
|
297
|
+
if (!(error instanceof ExplicitForeignKeyRequired || error instanceof InvalidComputedForeignKey))
|
|
298
|
+
throw error;
|
|
288
299
|
}
|
|
289
|
-
// guarantee unique
|
|
290
|
-
tableAssociationData[associationName].tables = [
|
|
291
|
-
...new Set(tableAssociationData[associationName].tables),
|
|
292
|
-
];
|
|
293
300
|
}
|
|
294
301
|
}
|
|
295
302
|
return Object.keys(tableAssociationData)
|
|
@@ -2,11 +2,11 @@ import pluralize from 'pluralize-esm';
|
|
|
2
2
|
import serializerGlobalNameFromFullyQualifiedModelName from '../../serializer/helpers/serializerGlobalNameFromFullyQualifiedModelName.js';
|
|
3
3
|
import camelize from '../camelize.js';
|
|
4
4
|
import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
|
|
5
|
+
import pascalize from '../pascalize.js';
|
|
5
6
|
import relativeDreamPath from '../path/relativeDreamPath.js';
|
|
6
7
|
import snakeify from '../snakeify.js';
|
|
7
8
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
8
9
|
import uniq from '../uniq.js';
|
|
9
|
-
import pascalize from '../pascalize.js';
|
|
10
10
|
export default function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, includeAdminSerializers, connectionName = 'default', }) {
|
|
11
11
|
fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
|
|
12
12
|
const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
|
|
@@ -32,17 +32,19 @@ export default function generateDreamContent({ fullyQualifiedModelName, columnsW
|
|
|
32
32
|
const fullyQualifiedAssociatedModelName = standardizeFullyQualifiedModelName(attributeName);
|
|
33
33
|
const associationModelName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedAssociatedModelName);
|
|
34
34
|
const associationImportStatement = importStatementForModel(fullyQualifiedModelName, fullyQualifiedAssociatedModelName);
|
|
35
|
-
const associationName = camelize(associationModelName);
|
|
36
35
|
if (!attributeType)
|
|
37
36
|
throw new Error(`must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
38
37
|
switch (attributeType) {
|
|
39
|
-
case 'belongs_to':
|
|
38
|
+
case 'belongs_to': {
|
|
40
39
|
modelImportStatements.push(associationImportStatement);
|
|
40
|
+
const associationName = camelize(fullyQualifiedAssociatedModelName.split('/').pop());
|
|
41
|
+
const associationForeignKey = `${associationName}Id`;
|
|
41
42
|
return `
|
|
42
|
-
@deco.BelongsTo('${fullyQualifiedAssociatedModelName}'${descriptors.includes('optional') ? ',
|
|
43
|
+
@deco.BelongsTo('${fullyQualifiedAssociatedModelName}', { on: '${associationForeignKey}'${descriptors.includes('optional') ? ', optional: true' : ''} })
|
|
43
44
|
public ${associationName}: ${associationModelName}${descriptors.includes('optional') ? ' | null' : ''}
|
|
44
|
-
public ${
|
|
45
|
+
public ${associationForeignKey}: DreamColumn<${modelClassName}, '${associationName}Id'>
|
|
45
46
|
`;
|
|
47
|
+
}
|
|
46
48
|
case 'has_one':
|
|
47
49
|
case 'has_many':
|
|
48
50
|
return '';
|
|
@@ -29,6 +29,7 @@ export default function generateFactoryContent({ fullyQualifiedModelName, column
|
|
|
29
29
|
throw new Error(`Must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
30
30
|
switch (attributeType) {
|
|
31
31
|
case 'belongs_to': {
|
|
32
|
+
const attributeVariable = camelize(attributeName.split('/').pop());
|
|
32
33
|
const fullyQualifiedAssociatedModelName = standardizeFullyQualifiedModelName(attributeName);
|
|
33
34
|
const associationModelName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedAssociatedModelName);
|
|
34
35
|
const associationFactoryImportStatement = `import create${associationModelName} from '${relativeDreamPath('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
|
|
@@ -17,30 +17,20 @@ export default function generateMigrationContent({ connectionName = 'default', t
|
|
|
17
17
|
// instead, we'll add a check constraint that uses the STI child class name
|
|
18
18
|
const optional = userWantsThisOptional || !!stiChildClassName;
|
|
19
19
|
const sqlAttributeType = getAttributeType(attributeType, descriptors);
|
|
20
|
-
let attributeName = snakeify(nonStandardAttributeName);
|
|
21
|
-
if (attributeName === undefined)
|
|
22
|
-
return acc;
|
|
23
20
|
if (attributeType !== undefined && ['has_one', 'has_many'].includes(attributeType))
|
|
24
21
|
return acc;
|
|
25
22
|
if (attributeType === 'citext')
|
|
26
23
|
requireCitextExtension = true;
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await db.schema
|
|
31
|
-
.alterTable('${table}')
|
|
32
|
-
.addCheckConstraint(
|
|
33
|
-
'${table}_not_null_${attributeName}',
|
|
34
|
-
sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
|
|
35
|
-
)
|
|
36
|
-
.execute()`);
|
|
37
|
-
}
|
|
24
|
+
if (nonStandardAttributeName === undefined)
|
|
25
|
+
return acc;
|
|
26
|
+
let attributeName = snakeify(nonStandardAttributeName);
|
|
38
27
|
switch (attributeType) {
|
|
39
28
|
case 'belongs_to':
|
|
40
29
|
columnDefs.push(generateBelongsToStr(connectionName, attributeName, {
|
|
41
30
|
primaryKeyType,
|
|
42
31
|
optional,
|
|
43
32
|
}));
|
|
33
|
+
attributeName = snakeify(nonStandardAttributeName.split('/').pop());
|
|
44
34
|
attributeName = associationNameToForeignKey(attributeName);
|
|
45
35
|
break;
|
|
46
36
|
case 'enum':
|
|
@@ -74,7 +64,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
|
|
|
74
64
|
break;
|
|
75
65
|
}
|
|
76
66
|
columnDrops.push(`.dropColumn('${attributeName}')`);
|
|
77
|
-
if (COLUMNS_TO_INDEX.includes(attributeName)) {
|
|
67
|
+
if (attributeType === 'belongs_to' || COLUMNS_TO_INDEX.includes(attributeName)) {
|
|
78
68
|
const indexName = `${table}_${attributeName}`;
|
|
79
69
|
indexDefs.push(`await db.schema
|
|
80
70
|
.createIndex('${indexName}')
|
|
@@ -83,6 +73,17 @@ export default function generateMigrationContent({ connectionName = 'default', t
|
|
|
83
73
|
.execute()`);
|
|
84
74
|
indexDrops.push(`await db.schema.dropIndex('${indexName}').execute()`);
|
|
85
75
|
}
|
|
76
|
+
if (stiChildClassName && !userWantsThisOptional) {
|
|
77
|
+
checkConstraints.push(`
|
|
78
|
+
|
|
79
|
+
await db.schema
|
|
80
|
+
.alterTable('${table}')
|
|
81
|
+
.addCheckConstraint(
|
|
82
|
+
'${table}_not_null_${attributeName}',
|
|
83
|
+
sql\`type != '${stiChildClassName}' OR ${attributeName} IS NOT NULL\`,
|
|
84
|
+
)
|
|
85
|
+
.execute()`);
|
|
86
|
+
}
|
|
86
87
|
return acc;
|
|
87
88
|
}, { columnDefs: [], columnDrops: [], indexDefs: [], indexDrops: [] });
|
|
88
89
|
if (!table) {
|
|
@@ -252,7 +253,7 @@ function generateBelongsToStr(connectionName, associationName, { primaryKeyType,
|
|
|
252
253
|
const dbDriverClass = Query.dbDriverClass(connectionName);
|
|
253
254
|
const dataType = dbDriverClass.foreignKeyTypeFromPrimaryKey(primaryKeyType);
|
|
254
255
|
const references = pluralize(associationName.replace(/\//g, '_').replace(/_id$/, ''));
|
|
255
|
-
return `.addColumn('${associationNameToForeignKey(associationName)}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
|
|
256
|
+
return `.addColumn('${associationNameToForeignKey(associationName.split('/').pop())}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
|
|
256
257
|
}
|
|
257
258
|
function generateIdStr({ primaryKeyType }) {
|
|
258
259
|
switch (primaryKeyType) {
|
|
@@ -51,7 +51,7 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
|
|
|
51
51
|
return '';
|
|
52
52
|
if (['belongs_to', 'has_one', 'has_many'].includes(type))
|
|
53
53
|
return '';
|
|
54
|
-
return `\n ${attribute(name, type, attr, stiBaseSerializer)}`;
|
|
54
|
+
return `\n ${attribute(modelClassName, name, type, attr, stiBaseSerializer)}`;
|
|
55
55
|
})
|
|
56
56
|
.join('')}`;
|
|
57
57
|
return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
|
|
@@ -66,9 +66,9 @@ ${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerCl
|
|
|
66
66
|
${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}
|
|
67
67
|
`;
|
|
68
68
|
}
|
|
69
|
-
function attribute(name, type, attr, stiBaseSerializer) {
|
|
69
|
+
function attribute(modelClassName, name, type, attr, stiBaseSerializer) {
|
|
70
70
|
if (name === 'type' && stiBaseSerializer) {
|
|
71
|
-
return `.attribute('type', { openapi: { type: 'string', enum: [StiChildClass.sanitizedName] } })`;
|
|
71
|
+
return `.attribute('type', { openapi: { type: 'string', enum: [(StiChildClass ?? ${modelClassName}).sanitizedName] } })`;
|
|
72
72
|
}
|
|
73
73
|
switch (type) {
|
|
74
74
|
case 'json':
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import Dream from '../Dream.js';
|
|
2
2
|
export default function comparisonKey(val, toKey = undefined) {
|
|
3
|
-
|
|
3
|
+
if (val instanceof Dream)
|
|
4
|
+
return val.comparisonKey;
|
|
5
|
+
if (toKey)
|
|
6
|
+
return toKey(val);
|
|
7
|
+
if (val === null)
|
|
8
|
+
return null;
|
|
9
|
+
if (val === undefined)
|
|
10
|
+
return undefined;
|
|
11
|
+
switch (typeof val) {
|
|
12
|
+
case 'number':
|
|
13
|
+
case 'string':
|
|
14
|
+
case 'bigint':
|
|
15
|
+
return val;
|
|
16
|
+
default:
|
|
17
|
+
return val.toString();
|
|
18
|
+
}
|
|
4
19
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import CalendarDate from './CalendarDate.js';
|
|
2
|
+
import { DateTime } from './DateTime.js';
|
|
1
3
|
/**
|
|
2
4
|
* 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
|
|
3
5
|
* Returns a copy of the array sorted by the return value of the function passed as the second argument.
|
|
@@ -22,10 +24,17 @@ export default function sortBy(array, valueToCompare) {
|
|
|
22
24
|
return arrayClone.sort((a, b) => {
|
|
23
25
|
const aPrime = valueToCompare(a);
|
|
24
26
|
const bPrime = valueToCompare(b);
|
|
25
|
-
if (typeof aPrime === 'string' && typeof bPrime === 'string')
|
|
26
|
-
return aPrime.localeCompare(bPrime);
|
|
27
27
|
if (typeof aPrime === 'number' && typeof bPrime === 'number')
|
|
28
28
|
return aPrime - bPrime;
|
|
29
|
+
if (typeof aPrime === 'bigint' && typeof bPrime === 'bigint')
|
|
30
|
+
return aPrime > bPrime ? 1 : aPrime < bPrime ? -1 : 0;
|
|
31
|
+
if (typeof aPrime === 'string' && typeof bPrime === 'string')
|
|
32
|
+
return aPrime.localeCompare(bPrime);
|
|
33
|
+
if (aPrime instanceof DateTime && bPrime instanceof DateTime)
|
|
34
|
+
return aPrime.valueOf() - bPrime.valueOf();
|
|
35
|
+
if ((aPrime instanceof DateTime || aPrime instanceof CalendarDate) &&
|
|
36
|
+
(bPrime instanceof DateTime || bPrime instanceof CalendarDate))
|
|
37
|
+
return (aPrime.toISO() ?? '').localeCompare(bPrime.toISO() ?? '');
|
|
29
38
|
throw new UnsupportedValueFromComparisonFunction(aPrime, bPrime);
|
|
30
39
|
});
|
|
31
40
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import comparisonKey from './comparisonKey.js';
|
|
2
2
|
export default function uniq(arr, toKey = undefined) {
|
|
3
3
|
const map = arr.reduce((acc, val) => {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// order in which they were added, but in ascending numerical order.
|
|
8
|
-
const key = typeof baseKey === 'string' ? baseKey : `_${baseKey}`;
|
|
9
|
-
acc[key] ||= val;
|
|
4
|
+
const key = comparisonKey(val, toKey);
|
|
5
|
+
if (!acc.has(key))
|
|
6
|
+
acc.set(key, val);
|
|
10
7
|
return acc;
|
|
11
|
-
},
|
|
12
|
-
return
|
|
8
|
+
}, new Map());
|
|
9
|
+
return [...map.values()];
|
|
13
10
|
}
|
package/dist/esm/src/index.js
CHANGED
|
@@ -54,6 +54,7 @@ export { default as pascalize } from './helpers/pascalize.js';
|
|
|
54
54
|
export { default as dreamPath } from './helpers/path/dreamPath.js';
|
|
55
55
|
export { default as relativeDreamPath } from './helpers/path/relativeDreamPath.js';
|
|
56
56
|
export { default as sharedPathPrefix } from './helpers/path/sharedPathPrefix.js';
|
|
57
|
+
export { default as percent } from './helpers/percent.js';
|
|
57
58
|
export { Range, default as range } from './helpers/range.js';
|
|
58
59
|
export { default as round } from './helpers/round.js';
|
|
59
60
|
export { default as snakeify } from './helpers/snakeify.js';
|
|
@@ -8,7 +8,7 @@ import LoadBuilder from './dream/LoadBuilder.js';
|
|
|
8
8
|
import Query from './dream/Query.js';
|
|
9
9
|
import { PassthroughOnClause, WhereStatement } from './types/associations/shared.js';
|
|
10
10
|
import { AssociationTableNames, DbConnectionType } from './types/db.js';
|
|
11
|
-
import { AllDefaultScopeNames, AssociationNameToDream, AttributeKeys, CreateOrFindByExtraOpts, DefaultOrNamedScopeName, DreamAssociationNames, DreamAssociationNamesWithoutRequiredOnClauses, DreamAttributes, DreamColumnNames, DreamParamSafeColumnNames, DreamPrimaryKeyType, DreamSerializerKey, GlobalModelNames, GlobalSerializerName, JoinAndStatements,
|
|
11
|
+
import { AllDefaultScopeNames, AssociationNameToDream, AttributeKeys, CreateOrFindByExtraOpts, DefaultOrNamedScopeName, DreamAssociationNames, DreamAssociationNamesWithoutRequiredOnClauses, DreamAttributes, DreamBelongsToAssociationNames, DreamColumnNames, DreamHasManyAssociationNames, DreamHasOneAssociationNames, DreamModelAssociationNames, DreamParamSafeColumnNames, DreamPrimaryKeyType, DreamSerializerKey, GlobalModelNames, GlobalSerializerName, JoinAndStatements, OrderDir, PassthroughColumnNames, PluckEachArgs, PrimaryKeyForFind, TableColumnNames, UpdateableAssociationProperties, UpdateableProperties, UpdateablePropertiesForClass, UpdateOrCreateByExtraOpts } from './types/dream.js';
|
|
12
12
|
import { BaseModelColumnTypes, DefaultQueryTypeOptions, FindEachOpts, LoadForModifierFn, PaginatedDreamQueryOptions, PaginatedDreamQueryResult, QueryWithJoinedAssociationsType, QueryWithJoinedAssociationsTypeAndNoPreload } from './types/query.js';
|
|
13
13
|
import { DreamModelSerializerType, SimpleObjectSerializerType } from './types/serializer.js';
|
|
14
14
|
import { ValidationType } from './types/validation.js';
|
|
@@ -2343,6 +2343,45 @@ export default class Dream {
|
|
|
2343
2343
|
* @returns A chainable LoadBuilder instance
|
|
2344
2344
|
*/
|
|
2345
2345
|
load<I extends Dream, DB extends I['DB'], TableName extends I['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLoadArgs<DB, Schema, TableName, Arr>]): LoadBuilder<I>;
|
|
2346
|
+
/**
|
|
2347
|
+
* If the association is already loaded on the instance, it returns the loaded value
|
|
2348
|
+
* immediately without making a database query. If the association is not loaded,
|
|
2349
|
+
* it performs a database query to fetch the association.
|
|
2350
|
+
*
|
|
2351
|
+
* If a query is performed, the association is set on the model so that future calls to
|
|
2352
|
+
* access this association can access the already loaded value.
|
|
2353
|
+
*
|
|
2354
|
+
* ```ts
|
|
2355
|
+
* // return the already loaded user if it exists or fetch it from the database otherwise
|
|
2356
|
+
* const user = await post.associationOrFail('user')
|
|
2357
|
+
* ```
|
|
2358
|
+
*
|
|
2359
|
+
* @param associationName - The name of the BelongsTo or HasOne association
|
|
2360
|
+
* @returns The associated model instance or null
|
|
2361
|
+
*/
|
|
2362
|
+
association<I extends Dream, AssociationName extends DreamBelongsToAssociationNames<I> | DreamHasOneAssociationNames<I> | DreamHasManyAssociationNames<I>, ReturnType extends AssociationName extends DreamHasManyAssociationNames<I> ? AssociationNameToDream<I, AssociationName>[] : AssociationNameToDream<I, AssociationName> | null>(this: I, associationName: AssociationName): Promise<ReturnType>;
|
|
2363
|
+
/**
|
|
2364
|
+
* If the association is already loaded on the instance, it returns the loaded value
|
|
2365
|
+
* immediately without making a database query. If the association is not loaded,
|
|
2366
|
+
* it performs a database query to fetch the association.
|
|
2367
|
+
*
|
|
2368
|
+
* Unlike `association`, this method throws an exception if no associated
|
|
2369
|
+
* record is found, guaranteeing a non-null result.
|
|
2370
|
+
*
|
|
2371
|
+
* If a query is performed, the association is set on the model so that future calls to
|
|
2372
|
+
* access this association can access the already loaded value.
|
|
2373
|
+
*
|
|
2374
|
+
* ```ts
|
|
2375
|
+
* // return the already loaded user if it exists or fetch it from the database otherwise,
|
|
2376
|
+
* // throwing RecordNotFound either way if the associated model does not exist
|
|
2377
|
+
* const user = await post.associationOrFail('user')
|
|
2378
|
+
* ```
|
|
2379
|
+
*
|
|
2380
|
+
* @param associationName - The name of the BelongsTo or HasOne association
|
|
2381
|
+
* @returns The associated model instance (never null)
|
|
2382
|
+
* @throws RecordNotFound if no associated record exists
|
|
2383
|
+
*/
|
|
2384
|
+
associationOrFail<I extends Dream, AssociationName extends DreamBelongsToAssociationNames<I> | DreamHasOneAssociationNames<I> | DreamHasManyAssociationNames<I>, ReturnType extends AssociationName extends DreamHasManyAssociationNames<I> ? AssociationNameToDream<I, AssociationName>[] : AssociationNameToDream<I, AssociationName>>(this: I, associationName: AssociationName): Promise<ReturnType>;
|
|
2346
2385
|
/**
|
|
2347
2386
|
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
2348
2387
|
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
@@ -2401,8 +2440,8 @@ export default class Dream {
|
|
|
2401
2440
|
* 4. the individual query becomes more complex the more associations are included
|
|
2402
2441
|
* 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
|
|
2403
2442
|
*
|
|
2404
|
-
*
|
|
2405
|
-
*
|
|
2443
|
+
* Note: Left join loading loads all data in a single SQL query but has trade-offs compared
|
|
2444
|
+
* to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
|
|
2406
2445
|
*
|
|
2407
2446
|
* ```ts
|
|
2408
2447
|
* await user
|
|
@@ -2436,6 +2475,9 @@ export default class Dream {
|
|
|
2436
2475
|
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
2437
2476
|
* automatically preloads all associations that will be needed during serialization.
|
|
2438
2477
|
*
|
|
2478
|
+
* Note: Left join loading loads all data in a single SQL query but has trade-offs compared
|
|
2479
|
+
* to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
|
|
2480
|
+
*
|
|
2439
2481
|
* ```ts
|
|
2440
2482
|
* // Instead of manually specifying all associations:
|
|
2441
2483
|
* await User.preload('posts', 'comments', 'replies').all()
|
|
@@ -2488,7 +2530,7 @@ export default class Dream {
|
|
|
2488
2530
|
* @param associationName - the association name you wish to check the loading of
|
|
2489
2531
|
* @returns A boolean
|
|
2490
2532
|
*/
|
|
2491
|
-
loaded<I extends Dream, TableName extends I['table'], Schema extends I['schema'], AssociationName extends
|
|
2533
|
+
loaded<I extends Dream, TableName extends I['table'], Schema extends I['schema'], AssociationName extends DreamModelAssociationNames<Schema, TableName>>(this: I, associationName: AssociationName): boolean;
|
|
2492
2534
|
/**
|
|
2493
2535
|
* Reloads an instance, refreshing all it's attribute values
|
|
2494
2536
|
* to those in the database.
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { Kysely } 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 renameTable(db: Kysely<any>, from: string, to: string): Promise<void>;
|
|
3
19
|
/**
|
|
4
20
|
* Unique indexes cannot be populated by the same value even within a transaction,
|
|
5
21
|
* but deferrable unique constraints can.
|
|
@@ -12,5 +12,5 @@ export default function setPosition({ position, previousPosition, dream, positio
|
|
|
12
12
|
scope: string | string[] | undefined;
|
|
13
13
|
txn: DreamTransaction<any> | undefined;
|
|
14
14
|
}): Promise<void>;
|
|
15
|
-
export declare function applySortableScopesToQuery<QB extends UpdateQueryBuilder<any,
|
|
15
|
+
export declare function applySortableScopesToQuery<QB extends UpdateQueryBuilder<any, any, any, any> | SelectQueryBuilder<any, any, any>>(dream: Dream, kyselyQuery: QB, whereValueCB: (column: string) => any, scope?: string | string[]): QB;
|
|
16
16
|
export declare function getPostgresQueryDriver(connectionName: string): typeof PostgresQueryDriver;
|
|
@@ -20,6 +20,7 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
|
|
|
20
20
|
*/
|
|
21
21
|
protected readonly innerJoinDreamClasses: readonly (typeof Dream)[];
|
|
22
22
|
constructor(query: Query<DreamInstance, any>);
|
|
23
|
+
static ensureAllMigrationsHaveBeenRun(connectionName: string): Promise<void>;
|
|
23
24
|
/**
|
|
24
25
|
* migrate the database. Must respond to the NODE_ENV value.
|
|
25
26
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeleteQueryBuilder, Kysely, Transaction as KyselyTransaction, SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
|
|
1
|
+
import { DeleteQueryBuilder, Kysely, Transaction as KyselyTransaction, OrderByItemBuilder, SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
|
|
2
2
|
import { DialectProviderCb } from '../../db/DreamDbConnection.js';
|
|
3
3
|
import Dream from '../../Dream.js';
|
|
4
4
|
import { SchemaBuilderInformationSchemaRow } from '../../helpers/cli/SchemaBuilder.js';
|
|
@@ -13,6 +13,7 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
|
|
|
13
13
|
dbFor(sqlCommandType: SqlCommandType): Kysely<DreamInstance['DB']> | KyselyTransaction<DreamInstance['DB']>;
|
|
14
14
|
static dbFor<I extends Dream>(connectionName: string, dbConnectionType: DbConnectionType, dreamTransaction?: DreamTransaction<I> | null): Kysely<I['DB']> | KyselyTransaction<I['DB']>;
|
|
15
15
|
static dialectProvider(connectionName: string, dbConnectionType: DbConnectionType): DialectProviderCb;
|
|
16
|
+
static ensureAllMigrationsHaveBeenRun(connectionName: string): Promise<void>;
|
|
16
17
|
/**
|
|
17
18
|
* migrate the database. Must respond to the NODE_ENV value.
|
|
18
19
|
*/
|
|
@@ -266,7 +267,7 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
|
|
|
266
267
|
}>;
|
|
267
268
|
private buildDelete;
|
|
268
269
|
private buildSelect;
|
|
269
|
-
orderByDirection(direction: OrderDir | null):
|
|
270
|
+
orderByDirection(direction: OrderDir | null): (obj: OrderByItemBuilder) => OrderByItemBuilder;
|
|
270
271
|
private buildUpdate;
|
|
271
272
|
/**
|
|
272
273
|
* @internal
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DialectProviderCb } from '../../../../db/DreamDbConnection.js';
|
|
2
|
+
type MigrationModes = 'migrate' | 'rollback';
|
|
3
|
+
interface MigrationOpts {
|
|
4
|
+
connectionName: string;
|
|
5
|
+
dialectProvider: DialectProviderCb;
|
|
6
|
+
mode?: MigrationModes;
|
|
7
|
+
}
|
|
8
|
+
export default function checkForNeedToBeRunMigrations({ connectionName, dialectProvider, }: MigrationOpts): Promise<boolean>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function migrationFolderPath(connectionName: string): string;
|