@rvoh/dream 0.29.1
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/LICENSE +21 -0
- package/README.md +382 -0
- package/boilerplate/app/models/ApplicationModel.ts +14 -0
- package/boilerplate/app/serializers/.gitkeep +0 -0
- package/boilerplate/bin/esm.js +19 -0
- package/boilerplate/cli/helpers/initializeDreamApplication.ts +6 -0
- package/boilerplate/cli/index.ts +22 -0
- package/boilerplate/conf/inflections.ts +5 -0
- package/boilerplate/conf/loadEnv.ts +4 -0
- package/boilerplate/conf/repl.ts +11 -0
- package/boilerplate/eslint.config.js +21 -0
- package/boilerplate/package.json +42 -0
- package/boilerplate/tsconfig.build.json +41 -0
- package/boilerplate/tsconfig.json +12 -0
- package/boilerplate/types/db.ts +5 -0
- package/boilerplate/types/dream.ts +3 -0
- package/dist/cjs/boilerplate/package.json +42 -0
- package/dist/cjs/src/Dream.js +2984 -0
- package/dist/cjs/src/bin/helpers/sync.js +109 -0
- package/dist/cjs/src/bin/index.js +107 -0
- package/dist/cjs/src/cli/index.js +155 -0
- package/dist/cjs/src/db/ConnectedToDB.js +43 -0
- package/dist/cjs/src/db/ConnectionConfRetriever.js +22 -0
- package/dist/cjs/src/db/DreamDbConnection.js +77 -0
- package/dist/cjs/src/db/dataTypes.js +58 -0
- package/dist/cjs/src/db/errors.js +17 -0
- package/dist/cjs/src/db/index.js +12 -0
- package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +193 -0
- package/dist/cjs/src/db/reflections.js +2 -0
- package/dist/cjs/src/db/types.js +2 -0
- package/dist/cjs/src/db/validators/validateColumn.js +11 -0
- package/dist/cjs/src/db/validators/validateTable.js +9 -0
- package/dist/cjs/src/db/validators/validateTableAlias.js +55 -0
- package/dist/cjs/src/decorators/DecoratorContextType.js +2 -0
- package/dist/cjs/src/decorators/Decorators.js +326 -0
- package/dist/cjs/src/decorators/Encrypted.js +83 -0
- package/dist/cjs/src/decorators/ReplicaSafe.js +12 -0
- package/dist/cjs/src/decorators/STI.js +35 -0
- package/dist/cjs/src/decorators/Scope.js +31 -0
- package/dist/cjs/src/decorators/SoftDelete.js +54 -0
- package/dist/cjs/src/decorators/Virtual.js +28 -0
- package/dist/cjs/src/decorators/associations/BelongsTo.js +77 -0
- package/dist/cjs/src/decorators/associations/HasMany.js +100 -0
- package/dist/cjs/src/decorators/associations/HasOne.js +96 -0
- package/dist/cjs/src/decorators/associations/associationToGetterSetterProp.js +6 -0
- package/dist/cjs/src/decorators/associations/shared.js +132 -0
- package/dist/cjs/src/decorators/helpers/freezeBaseClassArrayMap.js +10 -0
- package/dist/cjs/src/decorators/hooks/AfterCreate.js +26 -0
- package/dist/cjs/src/decorators/hooks/AfterCreateCommit.js +43 -0
- package/dist/cjs/src/decorators/hooks/AfterDestroy.js +25 -0
- package/dist/cjs/src/decorators/hooks/AfterDestroyCommit.js +40 -0
- package/dist/cjs/src/decorators/hooks/AfterSave.js +26 -0
- package/dist/cjs/src/decorators/hooks/AfterSaveCommit.js +43 -0
- package/dist/cjs/src/decorators/hooks/AfterUpdate.js +26 -0
- package/dist/cjs/src/decorators/hooks/AfterUpdateCommit.js +43 -0
- package/dist/cjs/src/decorators/hooks/BeforeCreate.js +26 -0
- package/dist/cjs/src/decorators/hooks/BeforeDestroy.js +25 -0
- package/dist/cjs/src/decorators/hooks/BeforeSave.js +26 -0
- package/dist/cjs/src/decorators/hooks/BeforeUpdate.js +26 -0
- package/dist/cjs/src/decorators/hooks/shared.js +23 -0
- package/dist/cjs/src/decorators/sortable/Sortable.js +160 -0
- package/dist/cjs/src/decorators/sortable/helpers/applySortableScopeToQuery.js +17 -0
- package/dist/cjs/src/decorators/sortable/helpers/clearCachedSortableValues.js +11 -0
- package/dist/cjs/src/decorators/sortable/helpers/decrementScopedRecordsGreaterThanPosition.js +26 -0
- package/dist/cjs/src/decorators/sortable/helpers/getColumnForSortableScope.js +18 -0
- package/dist/cjs/src/decorators/sortable/helpers/isSortedCorrectly.js +7 -0
- package/dist/cjs/src/decorators/sortable/helpers/positionIsInvalid.js +11 -0
- package/dist/cjs/src/decorators/sortable/helpers/resortAllRecords.js +38 -0
- package/dist/cjs/src/decorators/sortable/helpers/scopeArray.js +10 -0
- package/dist/cjs/src/decorators/sortable/helpers/setPosition.js +158 -0
- package/dist/cjs/src/decorators/sortable/helpers/sortableCacheKeyName.js +7 -0
- package/dist/cjs/src/decorators/sortable/helpers/sortableCacheValuesName.js +7 -0
- package/dist/cjs/src/decorators/sortable/helpers/sortableQueryExcludingDream.js +10 -0
- package/dist/cjs/src/decorators/sortable/hooks/afterSortableCreate.js +18 -0
- package/dist/cjs/src/decorators/sortable/hooks/afterSortableDestroy.js +14 -0
- package/dist/cjs/src/decorators/sortable/hooks/afterSortableUpdate.js +31 -0
- package/dist/cjs/src/decorators/sortable/hooks/beforeSortableSave.js +65 -0
- package/dist/cjs/src/decorators/validations/Validate.js +22 -0
- package/dist/cjs/src/decorators/validations/Validates.js +70 -0
- package/dist/cjs/src/decorators/validations/shared.js +2 -0
- package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +592 -0
- package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +480 -0
- package/dist/cjs/src/dream/DreamTransaction.js +26 -0
- package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +77 -0
- package/dist/cjs/src/dream/LoadBuilder.js +68 -0
- package/dist/cjs/src/dream/Query.js +2618 -0
- package/dist/cjs/src/dream/internal/applyScopeBypassingSettingsToQuery.js +11 -0
- package/dist/cjs/src/dream/internal/associations/associationQuery.js +23 -0
- package/dist/cjs/src/dream/internal/associations/associationUpdateQuery.js +36 -0
- package/dist/cjs/src/dream/internal/associations/createAssociation.js +55 -0
- package/dist/cjs/src/dream/internal/associations/destroyAssociation.js +17 -0
- package/dist/cjs/src/dream/internal/associations/undestroyAssociation.js +12 -0
- package/dist/cjs/src/dream/internal/checkSingleValidation.js +52 -0
- package/dist/cjs/src/dream/internal/destroyAssociatedRecords.js +21 -0
- package/dist/cjs/src/dream/internal/destroyDream.js +72 -0
- package/dist/cjs/src/dream/internal/destroyOptions.js +32 -0
- package/dist/cjs/src/dream/internal/ensureSTITypeFieldIsSet.js +10 -0
- package/dist/cjs/src/dream/internal/executeDatabaseQuery.js +24 -0
- package/dist/cjs/src/dream/internal/extractAssociationMetadataFromAssociationName.js +8 -0
- package/dist/cjs/src/dream/internal/orderByDirection.js +15 -0
- package/dist/cjs/src/dream/internal/reload.js +21 -0
- package/dist/cjs/src/dream/internal/runHooksFor.js +99 -0
- package/dist/cjs/src/dream/internal/runValidations.js +16 -0
- package/dist/cjs/src/dream/internal/safelyRunCommitHooks.js +15 -0
- package/dist/cjs/src/dream/internal/saveDream.js +67 -0
- package/dist/cjs/src/dream/internal/scopeHelpers.js +13 -0
- package/dist/cjs/src/dream/internal/shouldBypassDefaultScope.js +12 -0
- package/dist/cjs/src/dream/internal/similarity/SimilarityBuilder.js +331 -0
- package/dist/cjs/src/dream/internal/similarity/similaritySelectSql.js +21 -0
- package/dist/cjs/src/dream/internal/similarity/similarityWhereSql.js +21 -0
- package/dist/cjs/src/dream/internal/softDeleteDream.js +22 -0
- package/dist/cjs/src/dream/internal/sqlResultToDreamInstance.js +38 -0
- package/dist/cjs/src/dream/internal/undestroyDream.js +90 -0
- package/dist/cjs/src/dream/types.js +98 -0
- package/dist/cjs/src/dream-application/cache.js +13 -0
- package/dist/cjs/src/dream-application/helpers/DreamImporter.js +52 -0
- package/dist/cjs/src/dream-application/helpers/globalModelKeyFromPath.js +10 -0
- package/dist/cjs/src/dream-application/helpers/globalSerializerKeyFromPath.js +17 -0
- package/dist/cjs/src/dream-application/helpers/globalServiceKeyFromPath.js +11 -0
- package/dist/cjs/src/dream-application/helpers/importers/importModels.js +81 -0
- package/dist/cjs/src/dream-application/helpers/importers/importSerializers.js +63 -0
- package/dist/cjs/src/dream-application/helpers/importers/importServices.js +43 -0
- package/dist/cjs/src/dream-application/helpers/lookupClassByGlobalName.js +17 -0
- package/dist/cjs/src/dream-application/helpers/lookupModelByGlobalName.js +13 -0
- package/dist/cjs/src/dream-application/helpers/lookupModelByGlobalNameOrNames.js +10 -0
- package/dist/cjs/src/dream-application/index.js +284 -0
- package/dist/cjs/src/encrypt/InternalEncrypt.js +32 -0
- package/dist/cjs/src/encrypt/algorithms/aes-gcm/decryptAESGCM.js +26 -0
- package/dist/cjs/src/encrypt/algorithms/aes-gcm/encryptAESGCM.js +12 -0
- package/dist/cjs/src/encrypt/algorithms/aes-gcm/generateKeyAESGCM.js +7 -0
- package/dist/cjs/src/encrypt/algorithms/aes-gcm/validateKeyAESGCM.js +11 -0
- package/dist/cjs/src/encrypt/index.js +95 -0
- package/dist/cjs/src/errors/AttemptingToMarshalInvalidArrayType.js +20 -0
- package/dist/cjs/src/errors/CannotCallUndestroyOnANonSoftDeleteModel.js +21 -0
- package/dist/cjs/src/errors/CannotDefineAssociationWithBothDependentAndPassthrough.js +19 -0
- package/dist/cjs/src/errors/CannotDefineAssociationWithBothDependentAndRequiredOnClause.js +19 -0
- package/dist/cjs/src/errors/CannotNegateSimilarityClause.js +22 -0
- package/dist/cjs/src/errors/CannotPassAdditionalFieldsToPluckEachAfterCallback.js +22 -0
- package/dist/cjs/src/errors/CannotPassUndefinedAsAValueToAWhereClause.js +20 -0
- package/dist/cjs/src/errors/CannotReloadUnsavedDream.js +16 -0
- package/dist/cjs/src/errors/ConstructorOnlyForInternalUse.js +9 -0
- package/dist/cjs/src/errors/CreateOrFindByFailedToCreateAndFind.js +18 -0
- package/dist/cjs/src/errors/DoNotSetEncryptedFieldsDirectly.js +23 -0
- package/dist/cjs/src/errors/InvalidColumnName.js +19 -0
- package/dist/cjs/src/errors/InvalidDecimalFieldPassedToGenerator.js +19 -0
- package/dist/cjs/src/errors/InvalidTableAlias.js +30 -0
- package/dist/cjs/src/errors/InvalidTableName.js +23 -0
- package/dist/cjs/src/errors/LeftJoinPreloadIncompatibleWithFindEach.js +12 -0
- package/dist/cjs/src/errors/MissingDB.js +10 -0
- package/dist/cjs/src/errors/MissingDeletedAtFieldForSoftDelete.js +24 -0
- package/dist/cjs/src/errors/MissingRequiredCallbackFunctionToPluckEach.js +22 -0
- package/dist/cjs/src/errors/MissingSerializersDefinition.js +26 -0
- package/dist/cjs/src/errors/MissingTable.js +27 -0
- package/dist/cjs/src/errors/NoUpdateAllOnJoins.js +13 -0
- package/dist/cjs/src/errors/NoUpdateOnAssociationQuery.js +10 -0
- package/dist/cjs/src/errors/NonBelongsToAssociationProvidedAsSortableDecoratorScope.js +23 -0
- package/dist/cjs/src/errors/NonExistentScopeProvidedToResort.js +23 -0
- package/dist/cjs/src/errors/PrototypePollutingAssignment.js +13 -0
- package/dist/cjs/src/errors/RecordNotFound.js +15 -0
- package/dist/cjs/src/errors/SortableDecoratorRequiresColumnOrBelongsToAssociation.js +26 -0
- package/dist/cjs/src/errors/ValidationError.js +19 -0
- package/dist/cjs/src/errors/associations/CanOnlyPassBelongsToModelParam.js +20 -0
- package/dist/cjs/src/errors/associations/CannotAssociateThroughPolymorphic.js +19 -0
- package/dist/cjs/src/errors/associations/CannotCreateAssociationWithThroughContext.js +19 -0
- package/dist/cjs/src/errors/associations/CannotJoinPolymorphicBelongsToError.js +27 -0
- package/dist/cjs/src/errors/associations/CannotPassNullOrUndefinedToRequiredBelongsTo.js +19 -0
- package/dist/cjs/src/errors/associations/InvalidComputedForeignKey.js +64 -0
- package/dist/cjs/src/errors/associations/JoinAttemptedOnMissingAssociation.js +27 -0
- package/dist/cjs/src/errors/associations/MissingRequiredAssociationOnClause.js +19 -0
- package/dist/cjs/src/errors/associations/MissingRequiredPassthroughForAssociationOnClause.js +16 -0
- package/dist/cjs/src/errors/associations/MissingThroughAssociation.js +27 -0
- package/dist/cjs/src/errors/associations/MissingThroughAssociationSource.js +42 -0
- package/dist/cjs/src/errors/associations/NonLoadedAssociation.js +18 -0
- package/dist/cjs/src/errors/dream-application/DreamApplicationInitMissingCallToLoadModels.js +18 -0
- package/dist/cjs/src/errors/dream-application/DreamApplicationInitMissingMissingProjectRoot.js +19 -0
- package/dist/cjs/src/errors/dream-application/GlobalNameNotSet.js +14 -0
- package/dist/cjs/src/errors/dream-application/SerializerNameConflict.js +15 -0
- package/dist/cjs/src/errors/encrypt/MissingColumnEncryptionOpts.js +27 -0
- package/dist/cjs/src/errors/encrypt/MissingEncryptionKey.js +12 -0
- package/dist/cjs/src/errors/environment/MissingRequiredEnvironmentVariable.js +13 -0
- package/dist/cjs/src/errors/ops/AnyRequiresArrayColumn.js +18 -0
- package/dist/cjs/src/errors/ops/ScoreMustBeANormalNumber.js +17 -0
- package/dist/cjs/src/errors/schema-builder/FailedToIdentifyAssociation.js +80 -0
- package/dist/cjs/src/errors/serializers/FailedToRenderThroughAssociationForSerializer.js +17 -0
- package/dist/cjs/src/errors/sortable/CannotCallSortableOnSTIChild.js +18 -0
- package/dist/cjs/src/errors/sti/STIChildMissing.js +23 -0
- package/dist/cjs/src/errors/sti/StiChildCannotDefineNewAssociations.js +20 -0
- package/dist/cjs/src/errors/sti/StiChildIncompatibleWithReplicaSafeDecorator.js +17 -0
- package/dist/cjs/src/errors/sti/StiChildIncompatibleWithSoftDeleteDecorator.js +17 -0
- package/dist/cjs/src/global-cli/dream.js +46 -0
- package/dist/cjs/src/global-cli/file-builders/DreamtsBuilder.js +69 -0
- package/dist/cjs/src/global-cli/file-builders/EnvBuilder.js +27 -0
- package/dist/cjs/src/global-cli/file-builders/EslintConfBuilder.js +29 -0
- package/dist/cjs/src/global-cli/file-builders/PackagejsonBuilder.js +9 -0
- package/dist/cjs/src/global-cli/helpers/argAndValue.js +15 -0
- package/dist/cjs/src/global-cli/helpers/autogeneratedFileMessage.js +71 -0
- package/dist/cjs/src/global-cli/helpers/buildNewDreamApp.js +63 -0
- package/dist/cjs/src/global-cli/helpers/copyRecursive.js +20 -0
- package/dist/cjs/src/global-cli/helpers/filterObjectByKey.js +23 -0
- package/dist/cjs/src/global-cli/helpers/generateEncryptionKey.js +26 -0
- package/dist/cjs/src/global-cli/helpers/globalCliSnakeify.js +1 -0
- package/dist/cjs/src/global-cli/helpers/initDreamAppIntoExistingProject.js +85 -0
- package/dist/cjs/src/global-cli/helpers/log.js +28 -0
- package/dist/cjs/src/global-cli/helpers/logo.js +81 -0
- package/dist/cjs/src/global-cli/helpers/primaryKeyTypes.js +13 -0
- package/dist/cjs/src/global-cli/helpers/prompt.js +33 -0
- package/dist/cjs/src/global-cli/helpers/select.js +113 -0
- package/dist/cjs/src/global-cli/helpers/sleep.js +10 -0
- package/dist/cjs/src/global-cli/helpers/sspawn.js +21 -0
- package/dist/cjs/src/global-cli/helpers/welcomeMessage.js +41 -0
- package/dist/cjs/src/global-cli/init.js +56 -0
- package/dist/cjs/src/global-cli/new.js +10 -0
- package/dist/cjs/src/helpers/CalendarDate.js +172 -0
- package/dist/cjs/src/helpers/Env.js +78 -0
- package/dist/cjs/src/helpers/EnvInternal.js +5 -0
- package/dist/cjs/src/helpers/allNestedObjectKeys.js +12 -0
- package/dist/cjs/src/helpers/benchmark.js +18 -0
- package/dist/cjs/src/helpers/camelize.js +15 -0
- package/dist/cjs/src/helpers/capitalize.js +6 -0
- package/dist/cjs/src/helpers/cli/SchemaBuilder.js +378 -0
- package/dist/cjs/src/helpers/cli/generateDream.js +48 -0
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +107 -0
- package/dist/cjs/src/helpers/cli/generateFactory.js +26 -0
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +58 -0
- package/dist/cjs/src/helpers/cli/generateMigration.js +56 -0
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +196 -0
- package/dist/cjs/src/helpers/cli/generateSerializer.js +26 -0
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +130 -0
- package/dist/cjs/src/helpers/cli/generateStiMigrationContent.js +7 -0
- package/dist/cjs/src/helpers/cli/generateUnitSpec.js +26 -0
- package/dist/cjs/src/helpers/cli/generateUnitSpecContent.js +10 -0
- package/dist/cjs/src/helpers/cloneDeepSafe.js +69 -0
- package/dist/cjs/src/helpers/compact.js +14 -0
- package/dist/cjs/src/helpers/customPgParsers.js +39 -0
- package/dist/cjs/src/helpers/db/cachedTypeForAttribute.js +6 -0
- package/dist/cjs/src/helpers/db/createDb.js +20 -0
- package/dist/cjs/src/helpers/db/dropDb.js +36 -0
- package/dist/cjs/src/helpers/db/foreignKeyTypeFromPrimaryKey.js +11 -0
- package/dist/cjs/src/helpers/db/loadPgClient.js +20 -0
- package/dist/cjs/src/helpers/db/primaryKeyType.js +23 -0
- package/dist/cjs/src/helpers/db/runMigration.js +97 -0
- package/dist/cjs/src/helpers/db/truncateDb.js +27 -0
- package/dist/cjs/src/helpers/db/types/isDatabaseArrayColumn.js +6 -0
- package/dist/cjs/src/helpers/db/types/isDateColumn.js +6 -0
- package/dist/cjs/src/helpers/db/types/isDateTimeColumn.js +6 -0
- package/dist/cjs/src/helpers/db/types/isJsonColumn.js +6 -0
- package/dist/cjs/src/helpers/debug.js +11 -0
- package/dist/cjs/src/helpers/dreamOrPsychicCoreDevelopment.js +10 -0
- package/dist/cjs/src/helpers/filterObjectByKey.js +14 -0
- package/dist/cjs/src/helpers/getFiles.js +20 -0
- package/dist/cjs/src/helpers/globalClassNameFromFullyQualifiedModelName.js +7 -0
- package/dist/cjs/src/helpers/hyphenize.js +11 -0
- package/dist/cjs/src/helpers/inferSerializerFromDreamOrViewModel.js +16 -0
- package/dist/cjs/src/helpers/isEmpty.js +8 -0
- package/dist/cjs/src/helpers/loadEnv.js +37 -0
- package/dist/cjs/src/helpers/loadRepl.js +25 -0
- package/dist/cjs/src/helpers/migrationVersion.js +6 -0
- package/dist/cjs/src/helpers/namespaceColumn.js +8 -0
- package/dist/cjs/src/helpers/objectPathsToArrays.js +19 -0
- package/dist/cjs/src/helpers/pascalize.js +12 -0
- package/dist/cjs/src/helpers/pascalizePath.js +10 -0
- package/dist/cjs/src/helpers/path/dreamFileAndDirPaths.js +16 -0
- package/dist/cjs/src/helpers/path/dreamPath.js +25 -0
- package/dist/cjs/src/helpers/path/relativeDreamPath.js +50 -0
- package/dist/cjs/src/helpers/path/sharedPathPrefix.js +14 -0
- package/dist/cjs/src/helpers/propertyNameFromFullyQualifiedModelName.js +8 -0
- package/dist/cjs/src/helpers/protectAgainstPollutingAssignment.js +14 -0
- package/dist/cjs/src/helpers/range.js +20 -0
- package/dist/cjs/src/helpers/round.js +7 -0
- package/dist/cjs/src/helpers/serializerNameFromFullyQualifiedModelName.js +13 -0
- package/dist/cjs/src/helpers/snakeify.js +14 -0
- package/dist/cjs/src/helpers/sortBy.js +31 -0
- package/dist/cjs/src/helpers/sqlAttributes.js +28 -0
- package/dist/cjs/src/helpers/sspawn.js +21 -0
- package/dist/cjs/src/helpers/standardizeFullyQualifiedModelName.js +10 -0
- package/dist/cjs/src/helpers/stringCasing.js +34 -0
- package/dist/cjs/src/helpers/typechecks.js +16 -0
- package/dist/cjs/src/helpers/typeutils.js +2 -0
- package/dist/cjs/src/helpers/uncapitalize.js +6 -0
- package/dist/cjs/src/helpers/uniq.js +21 -0
- package/dist/cjs/src/index.js +154 -0
- package/dist/cjs/src/openapi/types.js +26 -0
- package/dist/cjs/src/ops/curried-ops-statement.js +12 -0
- package/dist/cjs/src/ops/index.js +42 -0
- package/dist/cjs/src/ops/ops-statement.js +38 -0
- package/dist/cjs/src/serializer/decorators/associations/RendersMany.js +84 -0
- package/dist/cjs/src/serializer/decorators/associations/RendersOne.js +87 -0
- package/dist/cjs/src/serializer/decorators/associations/shared.js +10 -0
- package/dist/cjs/src/serializer/decorators/attribute.js +161 -0
- package/dist/cjs/src/serializer/decorators/helpers/dreamAttributeOpenapiShape.js +78 -0
- package/dist/cjs/src/serializer/decorators/helpers/hasSerializersGetter.js +11 -0
- package/dist/cjs/src/serializer/decorators/helpers/maybeSerializableToDreamSerializerCallbackFunction.js +20 -0
- package/dist/cjs/src/serializer/index.js +271 -0
- package/dist/esm/boilerplate/package.json +42 -0
- package/dist/esm/src/Dream.js +2981 -0
- package/dist/esm/src/bin/helpers/sync.js +106 -0
- package/dist/esm/src/bin/index.js +104 -0
- package/dist/esm/src/cli/index.js +152 -0
- package/dist/esm/src/db/ConnectedToDB.js +40 -0
- package/dist/esm/src/db/ConnectionConfRetriever.js +19 -0
- package/dist/esm/src/db/DreamDbConnection.js +72 -0
- package/dist/esm/src/db/dataTypes.js +53 -0
- package/dist/esm/src/db/errors.js +13 -0
- package/dist/esm/src/db/index.js +9 -0
- package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +190 -0
- package/dist/esm/src/db/reflections.js +1 -0
- package/dist/esm/src/db/types.js +1 -0
- package/dist/esm/src/db/validators/validateColumn.js +8 -0
- package/dist/esm/src/db/validators/validateTable.js +6 -0
- package/dist/esm/src/db/validators/validateTableAlias.js +52 -0
- package/dist/esm/src/decorators/DecoratorContextType.js +1 -0
- package/dist/esm/src/decorators/Decorators.js +323 -0
- package/dist/esm/src/decorators/Encrypted.js +80 -0
- package/dist/esm/src/decorators/ReplicaSafe.js +9 -0
- package/dist/esm/src/decorators/STI.js +31 -0
- package/dist/esm/src/decorators/Scope.js +27 -0
- package/dist/esm/src/decorators/SoftDelete.js +50 -0
- package/dist/esm/src/decorators/Virtual.js +25 -0
- package/dist/esm/src/decorators/associations/BelongsTo.js +74 -0
- package/dist/esm/src/decorators/associations/HasMany.js +97 -0
- package/dist/esm/src/decorators/associations/HasOne.js +93 -0
- package/dist/esm/src/decorators/associations/associationToGetterSetterProp.js +3 -0
- package/dist/esm/src/decorators/associations/shared.js +123 -0
- package/dist/esm/src/decorators/helpers/freezeBaseClassArrayMap.js +7 -0
- package/dist/esm/src/decorators/hooks/AfterCreate.js +22 -0
- package/dist/esm/src/decorators/hooks/AfterCreateCommit.js +39 -0
- package/dist/esm/src/decorators/hooks/AfterDestroy.js +21 -0
- package/dist/esm/src/decorators/hooks/AfterDestroyCommit.js +36 -0
- package/dist/esm/src/decorators/hooks/AfterSave.js +22 -0
- package/dist/esm/src/decorators/hooks/AfterSaveCommit.js +39 -0
- package/dist/esm/src/decorators/hooks/AfterUpdate.js +22 -0
- package/dist/esm/src/decorators/hooks/AfterUpdateCommit.js +39 -0
- package/dist/esm/src/decorators/hooks/BeforeCreate.js +22 -0
- package/dist/esm/src/decorators/hooks/BeforeDestroy.js +21 -0
- package/dist/esm/src/decorators/hooks/BeforeSave.js +22 -0
- package/dist/esm/src/decorators/hooks/BeforeUpdate.js +22 -0
- package/dist/esm/src/decorators/hooks/shared.js +20 -0
- package/dist/esm/src/decorators/sortable/Sortable.js +157 -0
- package/dist/esm/src/decorators/sortable/helpers/applySortableScopeToQuery.js +14 -0
- package/dist/esm/src/decorators/sortable/helpers/clearCachedSortableValues.js +8 -0
- package/dist/esm/src/decorators/sortable/helpers/decrementScopedRecordsGreaterThanPosition.js +23 -0
- package/dist/esm/src/decorators/sortable/helpers/getColumnForSortableScope.js +15 -0
- package/dist/esm/src/decorators/sortable/helpers/isSortedCorrectly.js +4 -0
- package/dist/esm/src/decorators/sortable/helpers/positionIsInvalid.js +8 -0
- package/dist/esm/src/decorators/sortable/helpers/resortAllRecords.js +35 -0
- package/dist/esm/src/decorators/sortable/helpers/scopeArray.js +7 -0
- package/dist/esm/src/decorators/sortable/helpers/setPosition.js +154 -0
- package/dist/esm/src/decorators/sortable/helpers/sortableCacheKeyName.js +4 -0
- package/dist/esm/src/decorators/sortable/helpers/sortableCacheValuesName.js +4 -0
- package/dist/esm/src/decorators/sortable/helpers/sortableQueryExcludingDream.js +7 -0
- package/dist/esm/src/decorators/sortable/hooks/afterSortableCreate.js +15 -0
- package/dist/esm/src/decorators/sortable/hooks/afterSortableDestroy.js +11 -0
- package/dist/esm/src/decorators/sortable/hooks/afterSortableUpdate.js +28 -0
- package/dist/esm/src/decorators/sortable/hooks/beforeSortableSave.js +62 -0
- package/dist/esm/src/decorators/validations/Validate.js +19 -0
- package/dist/esm/src/decorators/validations/Validates.js +64 -0
- package/dist/esm/src/decorators/validations/shared.js +1 -0
- package/dist/esm/src/dream/DreamClassTransactionBuilder.js +589 -0
- package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +477 -0
- package/dist/esm/src/dream/DreamTransaction.js +23 -0
- package/dist/esm/src/dream/LeftJoinLoadBuilder.js +74 -0
- package/dist/esm/src/dream/LoadBuilder.js +65 -0
- package/dist/esm/src/dream/Query.js +2615 -0
- package/dist/esm/src/dream/internal/applyScopeBypassingSettingsToQuery.js +8 -0
- package/dist/esm/src/dream/internal/associations/associationQuery.js +20 -0
- package/dist/esm/src/dream/internal/associations/associationUpdateQuery.js +33 -0
- package/dist/esm/src/dream/internal/associations/createAssociation.js +52 -0
- package/dist/esm/src/dream/internal/associations/destroyAssociation.js +14 -0
- package/dist/esm/src/dream/internal/associations/undestroyAssociation.js +9 -0
- package/dist/esm/src/dream/internal/checkSingleValidation.js +49 -0
- package/dist/esm/src/dream/internal/destroyAssociatedRecords.js +18 -0
- package/dist/esm/src/dream/internal/destroyDream.js +69 -0
- package/dist/esm/src/dream/internal/destroyOptions.js +27 -0
- package/dist/esm/src/dream/internal/ensureSTITypeFieldIsSet.js +7 -0
- package/dist/esm/src/dream/internal/executeDatabaseQuery.js +21 -0
- package/dist/esm/src/dream/internal/extractAssociationMetadataFromAssociationName.js +5 -0
- package/dist/esm/src/dream/internal/orderByDirection.js +12 -0
- package/dist/esm/src/dream/internal/reload.js +18 -0
- package/dist/esm/src/dream/internal/runHooksFor.js +95 -0
- package/dist/esm/src/dream/internal/runValidations.js +13 -0
- package/dist/esm/src/dream/internal/safelyRunCommitHooks.js +12 -0
- package/dist/esm/src/dream/internal/saveDream.js +64 -0
- package/dist/esm/src/dream/internal/scopeHelpers.js +9 -0
- package/dist/esm/src/dream/internal/shouldBypassDefaultScope.js +9 -0
- package/dist/esm/src/dream/internal/similarity/SimilarityBuilder.js +327 -0
- package/dist/esm/src/dream/internal/similarity/similaritySelectSql.js +18 -0
- package/dist/esm/src/dream/internal/similarity/similarityWhereSql.js +18 -0
- package/dist/esm/src/dream/internal/softDeleteDream.js +19 -0
- package/dist/esm/src/dream/internal/sqlResultToDreamInstance.js +34 -0
- package/dist/esm/src/dream/internal/undestroyDream.js +87 -0
- package/dist/esm/src/dream/types.js +95 -0
- package/dist/esm/src/dream-application/cache.js +9 -0
- package/dist/esm/src/dream-application/helpers/DreamImporter.js +49 -0
- package/dist/esm/src/dream-application/helpers/globalModelKeyFromPath.js +7 -0
- package/dist/esm/src/dream-application/helpers/globalSerializerKeyFromPath.js +14 -0
- package/dist/esm/src/dream-application/helpers/globalServiceKeyFromPath.js +8 -0
- package/dist/esm/src/dream-application/helpers/importers/importModels.js +75 -0
- package/dist/esm/src/dream-application/helpers/importers/importSerializers.js +57 -0
- package/dist/esm/src/dream-application/helpers/importers/importServices.js +37 -0
- package/dist/esm/src/dream-application/helpers/lookupClassByGlobalName.js +14 -0
- package/dist/esm/src/dream-application/helpers/lookupModelByGlobalName.js +10 -0
- package/dist/esm/src/dream-application/helpers/lookupModelByGlobalNameOrNames.js +7 -0
- package/dist/esm/src/dream-application/index.js +281 -0
- package/dist/esm/src/encrypt/InternalEncrypt.js +29 -0
- package/dist/esm/src/encrypt/algorithms/aes-gcm/decryptAESGCM.js +23 -0
- package/dist/esm/src/encrypt/algorithms/aes-gcm/encryptAESGCM.js +9 -0
- package/dist/esm/src/encrypt/algorithms/aes-gcm/generateKeyAESGCM.js +4 -0
- package/dist/esm/src/encrypt/algorithms/aes-gcm/validateKeyAESGCM.js +8 -0
- package/dist/esm/src/encrypt/index.js +92 -0
- package/dist/esm/src/errors/AttemptingToMarshalInvalidArrayType.js +17 -0
- package/dist/esm/src/errors/CannotCallUndestroyOnANonSoftDeleteModel.js +18 -0
- package/dist/esm/src/errors/CannotDefineAssociationWithBothDependentAndPassthrough.js +16 -0
- package/dist/esm/src/errors/CannotDefineAssociationWithBothDependentAndRequiredOnClause.js +16 -0
- package/dist/esm/src/errors/CannotNegateSimilarityClause.js +19 -0
- package/dist/esm/src/errors/CannotPassAdditionalFieldsToPluckEachAfterCallback.js +19 -0
- package/dist/esm/src/errors/CannotPassUndefinedAsAValueToAWhereClause.js +17 -0
- package/dist/esm/src/errors/CannotReloadUnsavedDream.js +13 -0
- package/dist/esm/src/errors/ConstructorOnlyForInternalUse.js +6 -0
- package/dist/esm/src/errors/CreateOrFindByFailedToCreateAndFind.js +15 -0
- package/dist/esm/src/errors/DoNotSetEncryptedFieldsDirectly.js +20 -0
- package/dist/esm/src/errors/InvalidColumnName.js +16 -0
- package/dist/esm/src/errors/InvalidDecimalFieldPassedToGenerator.js +16 -0
- package/dist/esm/src/errors/InvalidTableAlias.js +27 -0
- package/dist/esm/src/errors/InvalidTableName.js +20 -0
- package/dist/esm/src/errors/LeftJoinPreloadIncompatibleWithFindEach.js +9 -0
- package/dist/esm/src/errors/MissingDB.js +7 -0
- package/dist/esm/src/errors/MissingDeletedAtFieldForSoftDelete.js +21 -0
- package/dist/esm/src/errors/MissingRequiredCallbackFunctionToPluckEach.js +19 -0
- package/dist/esm/src/errors/MissingSerializersDefinition.js +23 -0
- package/dist/esm/src/errors/MissingTable.js +24 -0
- package/dist/esm/src/errors/NoUpdateAllOnJoins.js +10 -0
- package/dist/esm/src/errors/NoUpdateOnAssociationQuery.js +7 -0
- package/dist/esm/src/errors/NonBelongsToAssociationProvidedAsSortableDecoratorScope.js +20 -0
- package/dist/esm/src/errors/NonExistentScopeProvidedToResort.js +20 -0
- package/dist/esm/src/errors/PrototypePollutingAssignment.js +10 -0
- package/dist/esm/src/errors/RecordNotFound.js +12 -0
- package/dist/esm/src/errors/SortableDecoratorRequiresColumnOrBelongsToAssociation.js +23 -0
- package/dist/esm/src/errors/ValidationError.js +16 -0
- package/dist/esm/src/errors/associations/CanOnlyPassBelongsToModelParam.js +17 -0
- package/dist/esm/src/errors/associations/CannotAssociateThroughPolymorphic.js +16 -0
- package/dist/esm/src/errors/associations/CannotCreateAssociationWithThroughContext.js +16 -0
- package/dist/esm/src/errors/associations/CannotJoinPolymorphicBelongsToError.js +24 -0
- package/dist/esm/src/errors/associations/CannotPassNullOrUndefinedToRequiredBelongsTo.js +16 -0
- package/dist/esm/src/errors/associations/InvalidComputedForeignKey.js +58 -0
- package/dist/esm/src/errors/associations/JoinAttemptedOnMissingAssociation.js +24 -0
- package/dist/esm/src/errors/associations/MissingRequiredAssociationOnClause.js +16 -0
- package/dist/esm/src/errors/associations/MissingRequiredPassthroughForAssociationOnClause.js +13 -0
- package/dist/esm/src/errors/associations/MissingThroughAssociation.js +24 -0
- package/dist/esm/src/errors/associations/MissingThroughAssociationSource.js +39 -0
- package/dist/esm/src/errors/associations/NonLoadedAssociation.js +15 -0
- package/dist/esm/src/errors/dream-application/DreamApplicationInitMissingCallToLoadModels.js +15 -0
- package/dist/esm/src/errors/dream-application/DreamApplicationInitMissingMissingProjectRoot.js +16 -0
- package/dist/esm/src/errors/dream-application/GlobalNameNotSet.js +11 -0
- package/dist/esm/src/errors/dream-application/SerializerNameConflict.js +12 -0
- package/dist/esm/src/errors/encrypt/MissingColumnEncryptionOpts.js +24 -0
- package/dist/esm/src/errors/encrypt/MissingEncryptionKey.js +9 -0
- package/dist/esm/src/errors/environment/MissingRequiredEnvironmentVariable.js +10 -0
- package/dist/esm/src/errors/ops/AnyRequiresArrayColumn.js +15 -0
- package/dist/esm/src/errors/ops/ScoreMustBeANormalNumber.js +14 -0
- package/dist/esm/src/errors/schema-builder/FailedToIdentifyAssociation.js +77 -0
- package/dist/esm/src/errors/serializers/FailedToRenderThroughAssociationForSerializer.js +14 -0
- package/dist/esm/src/errors/sortable/CannotCallSortableOnSTIChild.js +15 -0
- package/dist/esm/src/errors/sti/STIChildMissing.js +20 -0
- package/dist/esm/src/errors/sti/StiChildCannotDefineNewAssociations.js +17 -0
- package/dist/esm/src/errors/sti/StiChildIncompatibleWithReplicaSafeDecorator.js +14 -0
- package/dist/esm/src/errors/sti/StiChildIncompatibleWithSoftDeleteDecorator.js +14 -0
- package/dist/esm/src/global-cli/dream.js +44 -0
- package/dist/esm/src/global-cli/file-builders/DreamtsBuilder.js +66 -0
- package/dist/esm/src/global-cli/file-builders/EnvBuilder.js +24 -0
- package/dist/esm/src/global-cli/file-builders/EslintConfBuilder.js +26 -0
- package/dist/esm/src/global-cli/file-builders/PackagejsonBuilder.js +6 -0
- package/dist/esm/src/global-cli/helpers/argAndValue.js +12 -0
- package/dist/esm/src/global-cli/helpers/autogeneratedFileMessage.js +68 -0
- package/dist/esm/src/global-cli/helpers/buildNewDreamApp.js +60 -0
- package/dist/esm/src/global-cli/helpers/copyRecursive.js +17 -0
- package/dist/esm/src/global-cli/helpers/filterObjectByKey.js +20 -0
- package/dist/esm/src/global-cli/helpers/generateEncryptionKey.js +23 -0
- package/dist/esm/src/global-cli/helpers/globalCliSnakeify.js +1 -0
- package/dist/esm/src/global-cli/helpers/initDreamAppIntoExistingProject.js +82 -0
- package/dist/esm/src/global-cli/helpers/log.js +24 -0
- package/dist/esm/src/global-cli/helpers/logo.js +77 -0
- package/dist/esm/src/global-cli/helpers/primaryKeyTypes.js +10 -0
- package/dist/esm/src/global-cli/helpers/prompt.js +30 -0
- package/dist/esm/src/global-cli/helpers/select.js +110 -0
- package/dist/esm/src/global-cli/helpers/sleep.js +7 -0
- package/dist/esm/src/global-cli/helpers/sspawn.js +17 -0
- package/dist/esm/src/global-cli/helpers/welcomeMessage.js +38 -0
- package/dist/esm/src/global-cli/init.js +53 -0
- package/dist/esm/src/global-cli/new.js +7 -0
- package/dist/esm/src/helpers/CalendarDate.js +169 -0
- package/dist/esm/src/helpers/Env.js +75 -0
- package/dist/esm/src/helpers/EnvInternal.js +3 -0
- package/dist/esm/src/helpers/allNestedObjectKeys.js +9 -0
- package/dist/esm/src/helpers/benchmark.js +15 -0
- package/dist/esm/src/helpers/camelize.js +11 -0
- package/dist/esm/src/helpers/capitalize.js +3 -0
- package/dist/esm/src/helpers/cli/SchemaBuilder.js +375 -0
- package/dist/esm/src/helpers/cli/generateDream.js +45 -0
- package/dist/esm/src/helpers/cli/generateDreamContent.js +104 -0
- package/dist/esm/src/helpers/cli/generateFactory.js +23 -0
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +55 -0
- package/dist/esm/src/helpers/cli/generateMigration.js +53 -0
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +193 -0
- package/dist/esm/src/helpers/cli/generateSerializer.js +23 -0
- package/dist/esm/src/helpers/cli/generateSerializerContent.js +127 -0
- package/dist/esm/src/helpers/cli/generateStiMigrationContent.js +4 -0
- package/dist/esm/src/helpers/cli/generateUnitSpec.js +23 -0
- package/dist/esm/src/helpers/cli/generateUnitSpecContent.js +7 -0
- package/dist/esm/src/helpers/cloneDeepSafe.js +64 -0
- package/dist/esm/src/helpers/compact.js +11 -0
- package/dist/esm/src/helpers/customPgParsers.js +31 -0
- package/dist/esm/src/helpers/db/cachedTypeForAttribute.js +3 -0
- package/dist/esm/src/helpers/db/createDb.js +17 -0
- package/dist/esm/src/helpers/db/dropDb.js +33 -0
- package/dist/esm/src/helpers/db/foreignKeyTypeFromPrimaryKey.js +8 -0
- package/dist/esm/src/helpers/db/loadPgClient.js +17 -0
- package/dist/esm/src/helpers/db/primaryKeyType.js +20 -0
- package/dist/esm/src/helpers/db/runMigration.js +94 -0
- package/dist/esm/src/helpers/db/truncateDb.js +24 -0
- package/dist/esm/src/helpers/db/types/isDatabaseArrayColumn.js +3 -0
- package/dist/esm/src/helpers/db/types/isDateColumn.js +3 -0
- package/dist/esm/src/helpers/db/types/isDateTimeColumn.js +3 -0
- package/dist/esm/src/helpers/db/types/isJsonColumn.js +3 -0
- package/dist/esm/src/helpers/debug.js +8 -0
- package/dist/esm/src/helpers/dreamOrPsychicCoreDevelopment.js +7 -0
- package/dist/esm/src/helpers/filterObjectByKey.js +11 -0
- package/dist/esm/src/helpers/getFiles.js +17 -0
- package/dist/esm/src/helpers/globalClassNameFromFullyQualifiedModelName.js +4 -0
- package/dist/esm/src/helpers/hyphenize.js +8 -0
- package/dist/esm/src/helpers/inferSerializerFromDreamOrViewModel.js +12 -0
- package/dist/esm/src/helpers/isEmpty.js +5 -0
- package/dist/esm/src/helpers/loadEnv.js +35 -0
- package/dist/esm/src/helpers/loadRepl.js +22 -0
- package/dist/esm/src/helpers/migrationVersion.js +3 -0
- package/dist/esm/src/helpers/namespaceColumn.js +5 -0
- package/dist/esm/src/helpers/objectPathsToArrays.js +16 -0
- package/dist/esm/src/helpers/pascalize.js +9 -0
- package/dist/esm/src/helpers/pascalizePath.js +7 -0
- package/dist/esm/src/helpers/path/dreamFileAndDirPaths.js +13 -0
- package/dist/esm/src/helpers/path/dreamPath.js +22 -0
- package/dist/esm/src/helpers/path/relativeDreamPath.js +46 -0
- package/dist/esm/src/helpers/path/sharedPathPrefix.js +11 -0
- package/dist/esm/src/helpers/propertyNameFromFullyQualifiedModelName.js +5 -0
- package/dist/esm/src/helpers/protectAgainstPollutingAssignment.js +11 -0
- package/dist/esm/src/helpers/range.js +15 -0
- package/dist/esm/src/helpers/round.js +4 -0
- package/dist/esm/src/helpers/serializerNameFromFullyQualifiedModelName.js +10 -0
- package/dist/esm/src/helpers/snakeify.js +10 -0
- package/dist/esm/src/helpers/sortBy.js +26 -0
- package/dist/esm/src/helpers/sqlAttributes.js +25 -0
- package/dist/esm/src/helpers/sspawn.js +17 -0
- package/dist/esm/src/helpers/standardizeFullyQualifiedModelName.js +7 -0
- package/dist/esm/src/helpers/stringCasing.js +31 -0
- package/dist/esm/src/helpers/typechecks.js +12 -0
- package/dist/esm/src/helpers/typeutils.js +1 -0
- package/dist/esm/src/helpers/uncapitalize.js +3 -0
- package/dist/esm/src/helpers/uniq.js +18 -0
- package/dist/esm/src/index.js +73 -0
- package/dist/esm/src/openapi/types.js +23 -0
- package/dist/esm/src/ops/curried-ops-statement.js +9 -0
- package/dist/esm/src/ops/index.js +40 -0
- package/dist/esm/src/ops/ops-statement.js +35 -0
- package/dist/esm/src/serializer/decorators/associations/RendersMany.js +81 -0
- package/dist/esm/src/serializer/decorators/associations/RendersOne.js +84 -0
- package/dist/esm/src/serializer/decorators/associations/shared.js +7 -0
- package/dist/esm/src/serializer/decorators/attribute.js +158 -0
- package/dist/esm/src/serializer/decorators/helpers/dreamAttributeOpenapiShape.js +73 -0
- package/dist/esm/src/serializer/decorators/helpers/hasSerializersGetter.js +8 -0
- package/dist/esm/src/serializer/decorators/helpers/maybeSerializableToDreamSerializerCallbackFunction.js +17 -0
- package/dist/esm/src/serializer/index.js +268 -0
- package/dist/types/src/Dream.d.ts +2211 -0
- package/dist/types/src/bin/helpers/sync.d.ts +2 -0
- package/dist/types/src/bin/index.d.ts +20 -0
- package/dist/types/src/cli/index.d.ts +20 -0
- package/dist/types/src/db/ConnectedToDB.d.ts +26 -0
- package/dist/types/src/db/ConnectionConfRetriever.d.ts +6 -0
- package/dist/types/src/db/DreamDbConnection.d.ts +10 -0
- package/dist/types/src/db/dataTypes.d.ts +6 -0
- package/dist/types/src/db/errors.d.ts +6 -0
- package/dist/types/src/db/index.d.ts +5 -0
- package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +116 -0
- package/dist/types/src/db/reflections.d.ts +5 -0
- package/dist/types/src/db/types.d.ts +1 -0
- package/dist/types/src/db/validators/validateColumn.d.ts +1 -0
- package/dist/types/src/db/validators/validateTable.d.ts +1 -0
- package/dist/types/src/db/validators/validateTableAlias.d.ts +1 -0
- package/dist/types/src/decorators/DecoratorContextType.d.ts +13 -0
- package/dist/types/src/decorators/Decorators.d.ts +214 -0
- package/dist/types/src/decorators/Encrypted.d.ts +5 -0
- package/dist/types/src/decorators/ReplicaSafe.d.ts +1 -0
- package/dist/types/src/decorators/STI.d.ts +5 -0
- package/dist/types/src/decorators/Scope.d.ts +11 -0
- package/dist/types/src/decorators/SoftDelete.d.ts +37 -0
- package/dist/types/src/decorators/Virtual.d.ts +6 -0
- package/dist/types/src/decorators/associations/BelongsTo.d.ts +33 -0
- package/dist/types/src/decorators/associations/HasMany.d.ts +19 -0
- package/dist/types/src/decorators/associations/HasOne.d.ts +11 -0
- package/dist/types/src/decorators/associations/associationToGetterSetterProp.d.ts +5 -0
- package/dist/types/src/decorators/associations/shared.d.ts +118 -0
- package/dist/types/src/decorators/helpers/freezeBaseClassArrayMap.d.ts +1 -0
- package/dist/types/src/decorators/hooks/AfterCreate.d.ts +4 -0
- package/dist/types/src/decorators/hooks/AfterCreateCommit.d.ts +21 -0
- package/dist/types/src/decorators/hooks/AfterDestroy.d.ts +3 -0
- package/dist/types/src/decorators/hooks/AfterDestroyCommit.d.ts +18 -0
- package/dist/types/src/decorators/hooks/AfterSave.d.ts +4 -0
- package/dist/types/src/decorators/hooks/AfterSaveCommit.d.ts +21 -0
- package/dist/types/src/decorators/hooks/AfterUpdate.d.ts +4 -0
- package/dist/types/src/decorators/hooks/AfterUpdateCommit.d.ts +21 -0
- package/dist/types/src/decorators/hooks/BeforeCreate.d.ts +4 -0
- package/dist/types/src/decorators/hooks/BeforeDestroy.d.ts +3 -0
- package/dist/types/src/decorators/hooks/BeforeSave.d.ts +4 -0
- package/dist/types/src/decorators/hooks/BeforeUpdate.d.ts +4 -0
- package/dist/types/src/decorators/hooks/shared.d.ts +34 -0
- package/dist/types/src/decorators/sortable/Sortable.d.ts +9 -0
- package/dist/types/src/decorators/sortable/helpers/applySortableScopeToQuery.d.ts +9 -0
- package/dist/types/src/decorators/sortable/helpers/clearCachedSortableValues.d.ts +2 -0
- package/dist/types/src/decorators/sortable/helpers/decrementScopedRecordsGreaterThanPosition.d.ts +8 -0
- package/dist/types/src/decorators/sortable/helpers/getColumnForSortableScope.d.ts +2 -0
- package/dist/types/src/decorators/sortable/helpers/isSortedCorrectly.d.ts +1 -0
- package/dist/types/src/decorators/sortable/helpers/positionIsInvalid.d.ts +8 -0
- package/dist/types/src/decorators/sortable/helpers/resortAllRecords.d.ts +2 -0
- package/dist/types/src/decorators/sortable/helpers/scopeArray.d.ts +1 -0
- package/dist/types/src/decorators/sortable/helpers/setPosition.d.ts +14 -0
- package/dist/types/src/decorators/sortable/helpers/sortableCacheKeyName.d.ts +1 -0
- package/dist/types/src/decorators/sortable/helpers/sortableCacheValuesName.d.ts +1 -0
- package/dist/types/src/decorators/sortable/helpers/sortableQueryExcludingDream.d.ts +9 -0
- package/dist/types/src/decorators/sortable/hooks/afterSortableCreate.d.ts +10 -0
- package/dist/types/src/decorators/sortable/hooks/afterSortableDestroy.d.ts +8 -0
- package/dist/types/src/decorators/sortable/hooks/afterSortableUpdate.d.ts +10 -0
- package/dist/types/src/decorators/sortable/hooks/beforeSortableSave.d.ts +8 -0
- package/dist/types/src/decorators/validations/Validate.d.ts +1 -0
- package/dist/types/src/decorators/validations/Validates.d.ts +18 -0
- package/dist/types/src/decorators/validations/shared.d.ts +19 -0
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +549 -0
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +316 -0
- package/dist/types/src/dream/DreamTransaction.d.ts +15 -0
- package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +48 -0
- package/dist/types/src/dream/LoadBuilder.d.ts +47 -0
- package/dist/types/src/dream/Query.d.ts +1132 -0
- package/dist/types/src/dream/internal/applyScopeBypassingSettingsToQuery.d.ts +13 -0
- package/dist/types/src/dream/internal/associations/associationQuery.d.ts +9 -0
- package/dist/types/src/dream/internal/associations/associationUpdateQuery.d.ts +9 -0
- package/dist/types/src/dream/internal/associations/createAssociation.d.ts +4 -0
- package/dist/types/src/dream/internal/associations/destroyAssociation.d.ts +11 -0
- package/dist/types/src/dream/internal/associations/undestroyAssociation.d.ts +10 -0
- package/dist/types/src/dream/internal/checkSingleValidation.d.ts +3 -0
- package/dist/types/src/dream/internal/destroyAssociatedRecords.d.ts +10 -0
- package/dist/types/src/dream/internal/destroyDream.d.ts +19 -0
- package/dist/types/src/dream/internal/destroyOptions.d.ts +46 -0
- package/dist/types/src/dream/internal/ensureSTITypeFieldIsSet.d.ts +2 -0
- package/dist/types/src/dream/internal/executeDatabaseQuery.d.ts +1 -0
- package/dist/types/src/dream/internal/extractAssociationMetadataFromAssociationName.d.ts +4 -0
- package/dist/types/src/dream/internal/orderByDirection.d.ts +2 -0
- package/dist/types/src/dream/internal/reload.d.ts +3 -0
- package/dist/types/src/dream/internal/runHooksFor.d.ts +8 -0
- package/dist/types/src/dream/internal/runValidations.d.ts +2 -0
- package/dist/types/src/dream/internal/safelyRunCommitHooks.d.ts +7 -0
- package/dist/types/src/dream/internal/saveDream.d.ts +5 -0
- package/dist/types/src/dream/internal/scopeHelpers.d.ts +7 -0
- package/dist/types/src/dream/internal/shouldBypassDefaultScope.d.ts +4 -0
- package/dist/types/src/dream/internal/similarity/SimilarityBuilder.d.ts +38 -0
- package/dist/types/src/dream/internal/similarity/similaritySelectSql.d.ts +11 -0
- package/dist/types/src/dream/internal/similarity/similarityWhereSql.d.ts +10 -0
- package/dist/types/src/dream/internal/softDeleteDream.d.ts +3 -0
- package/dist/types/src/dream/internal/sqlResultToDreamInstance.d.ts +4 -0
- package/dist/types/src/dream/internal/undestroyDream.d.ts +16 -0
- package/dist/types/src/dream/types.d.ts +184 -0
- package/dist/types/src/dream-application/cache.d.ts +3 -0
- package/dist/types/src/dream-application/helpers/DreamImporter.d.ts +8 -0
- package/dist/types/src/dream-application/helpers/globalModelKeyFromPath.d.ts +1 -0
- package/dist/types/src/dream-application/helpers/globalSerializerKeyFromPath.d.ts +1 -0
- package/dist/types/src/dream-application/helpers/globalServiceKeyFromPath.d.ts +1 -0
- package/dist/types/src/dream-application/helpers/importers/importModels.d.ts +5 -0
- package/dist/types/src/dream-application/helpers/importers/importSerializers.d.ts +5 -0
- package/dist/types/src/dream-application/helpers/importers/importServices.d.ts +4 -0
- package/dist/types/src/dream-application/helpers/lookupClassByGlobalName.d.ts +1 -0
- package/dist/types/src/dream-application/helpers/lookupModelByGlobalName.d.ts +1 -0
- package/dist/types/src/dream-application/helpers/lookupModelByGlobalNameOrNames.d.ts +1 -0
- package/dist/types/src/dream-application/index.d.ts +143 -0
- package/dist/types/src/encrypt/InternalEncrypt.d.ts +6 -0
- package/dist/types/src/encrypt/algorithms/aes-gcm/decryptAESGCM.d.ts +2 -0
- package/dist/types/src/encrypt/algorithms/aes-gcm/encryptAESGCM.d.ts +2 -0
- package/dist/types/src/encrypt/algorithms/aes-gcm/generateKeyAESGCM.d.ts +2 -0
- package/dist/types/src/encrypt/algorithms/aes-gcm/validateKeyAESGCM.d.ts +2 -0
- package/dist/types/src/encrypt/index.d.ts +26 -0
- package/dist/types/src/errors/AttemptingToMarshalInvalidArrayType.d.ts +5 -0
- package/dist/types/src/errors/CannotCallUndestroyOnANonSoftDeleteModel.d.ts +6 -0
- package/dist/types/src/errors/CannotDefineAssociationWithBothDependentAndPassthrough.d.ts +7 -0
- package/dist/types/src/errors/CannotDefineAssociationWithBothDependentAndRequiredOnClause.d.ts +7 -0
- package/dist/types/src/errors/CannotNegateSimilarityClause.d.ts +7 -0
- package/dist/types/src/errors/CannotPassAdditionalFieldsToPluckEachAfterCallback.d.ts +6 -0
- package/dist/types/src/errors/CannotPassUndefinedAsAValueToAWhereClause.d.ts +7 -0
- package/dist/types/src/errors/CannotReloadUnsavedDream.d.ts +6 -0
- package/dist/types/src/errors/ConstructorOnlyForInternalUse.d.ts +3 -0
- package/dist/types/src/errors/CreateOrFindByFailedToCreateAndFind.d.ts +6 -0
- package/dist/types/src/errors/DoNotSetEncryptedFieldsDirectly.d.ts +8 -0
- package/dist/types/src/errors/InvalidColumnName.d.ts +6 -0
- package/dist/types/src/errors/InvalidDecimalFieldPassedToGenerator.d.ts +5 -0
- package/dist/types/src/errors/InvalidTableAlias.d.ts +5 -0
- package/dist/types/src/errors/InvalidTableName.d.ts +6 -0
- package/dist/types/src/errors/LeftJoinPreloadIncompatibleWithFindEach.d.ts +3 -0
- package/dist/types/src/errors/MissingDB.d.ts +3 -0
- package/dist/types/src/errors/MissingDeletedAtFieldForSoftDelete.d.ts +6 -0
- package/dist/types/src/errors/MissingRequiredCallbackFunctionToPluckEach.d.ts +6 -0
- package/dist/types/src/errors/MissingSerializersDefinition.d.ts +6 -0
- package/dist/types/src/errors/MissingTable.d.ts +6 -0
- package/dist/types/src/errors/NoUpdateAllOnJoins.d.ts +3 -0
- package/dist/types/src/errors/NoUpdateOnAssociationQuery.d.ts +3 -0
- package/dist/types/src/errors/NonBelongsToAssociationProvidedAsSortableDecoratorScope.d.ts +7 -0
- package/dist/types/src/errors/NonExistentScopeProvidedToResort.d.ts +7 -0
- package/dist/types/src/errors/PrototypePollutingAssignment.d.ts +5 -0
- package/dist/types/src/errors/RecordNotFound.d.ts +5 -0
- package/dist/types/src/errors/SortableDecoratorRequiresColumnOrBelongsToAssociation.d.ts +7 -0
- package/dist/types/src/errors/ValidationError.d.ts +11 -0
- package/dist/types/src/errors/associations/CanOnlyPassBelongsToModelParam.d.ts +9 -0
- package/dist/types/src/errors/associations/CannotAssociateThroughPolymorphic.d.ts +12 -0
- package/dist/types/src/errors/associations/CannotCreateAssociationWithThroughContext.d.ts +12 -0
- package/dist/types/src/errors/associations/CannotJoinPolymorphicBelongsToError.d.ts +15 -0
- package/dist/types/src/errors/associations/CannotPassNullOrUndefinedToRequiredBelongsTo.d.ts +8 -0
- package/dist/types/src/errors/associations/InvalidComputedForeignKey.d.ts +19 -0
- package/dist/types/src/errors/associations/JoinAttemptedOnMissingAssociation.d.ts +10 -0
- package/dist/types/src/errors/associations/MissingRequiredAssociationOnClause.d.ts +8 -0
- package/dist/types/src/errors/associations/MissingRequiredPassthroughForAssociationOnClause.d.ts +5 -0
- package/dist/types/src/errors/associations/MissingThroughAssociation.d.ts +12 -0
- package/dist/types/src/errors/associations/MissingThroughAssociationSource.d.ts +14 -0
- package/dist/types/src/errors/associations/NonLoadedAssociation.d.ts +10 -0
- package/dist/types/src/errors/dream-application/DreamApplicationInitMissingCallToLoadModels.d.ts +3 -0
- package/dist/types/src/errors/dream-application/DreamApplicationInitMissingMissingProjectRoot.d.ts +3 -0
- package/dist/types/src/errors/dream-application/GlobalNameNotSet.d.ts +5 -0
- package/dist/types/src/errors/dream-application/SerializerNameConflict.d.ts +5 -0
- package/dist/types/src/errors/encrypt/MissingColumnEncryptionOpts.d.ts +3 -0
- package/dist/types/src/errors/encrypt/MissingEncryptionKey.d.ts +3 -0
- package/dist/types/src/errors/environment/MissingRequiredEnvironmentVariable.d.ts +5 -0
- package/dist/types/src/errors/ops/AnyRequiresArrayColumn.d.ts +7 -0
- package/dist/types/src/errors/ops/ScoreMustBeANormalNumber.d.ts +5 -0
- package/dist/types/src/errors/schema-builder/FailedToIdentifyAssociation.d.ts +9 -0
- package/dist/types/src/errors/serializers/FailedToRenderThroughAssociationForSerializer.d.ts +6 -0
- package/dist/types/src/errors/sortable/CannotCallSortableOnSTIChild.d.ts +6 -0
- package/dist/types/src/errors/sti/STIChildMissing.d.ts +8 -0
- package/dist/types/src/errors/sti/StiChildCannotDefineNewAssociations.d.ts +7 -0
- package/dist/types/src/errors/sti/StiChildIncompatibleWithReplicaSafeDecorator.d.ts +6 -0
- package/dist/types/src/errors/sti/StiChildIncompatibleWithSoftDeleteDecorator.d.ts +6 -0
- package/dist/types/src/global-cli/dream.d.ts +2 -0
- package/dist/types/src/global-cli/file-builders/DreamtsBuilder.d.ts +4 -0
- package/dist/types/src/global-cli/file-builders/EnvBuilder.d.ts +6 -0
- package/dist/types/src/global-cli/file-builders/EslintConfBuilder.d.ts +3 -0
- package/dist/types/src/global-cli/file-builders/PackagejsonBuilder.d.ts +3 -0
- package/dist/types/src/global-cli/helpers/argAndValue.d.ts +1 -0
- package/dist/types/src/global-cli/helpers/autogeneratedFileMessage.d.ts +1 -0
- package/dist/types/src/global-cli/helpers/buildNewDreamApp.d.ts +2 -0
- package/dist/types/src/global-cli/helpers/copyRecursive.d.ts +1 -0
- package/dist/types/src/global-cli/helpers/filterObjectByKey.d.ts +1 -0
- package/dist/types/src/global-cli/helpers/generateEncryptionKey.d.ts +1 -0
- package/dist/types/src/global-cli/helpers/globalCliSnakeify.d.ts +0 -0
- package/dist/types/src/global-cli/helpers/initDreamAppIntoExistingProject.d.ts +2 -0
- package/dist/types/src/global-cli/helpers/log.d.ts +10 -0
- package/dist/types/src/global-cli/helpers/logo.d.ts +2 -0
- package/dist/types/src/global-cli/helpers/primaryKeyTypes.d.ts +22 -0
- package/dist/types/src/global-cli/helpers/prompt.d.ts +8 -0
- package/dist/types/src/global-cli/helpers/select.d.ts +17 -0
- package/dist/types/src/global-cli/helpers/sleep.d.ts +1 -0
- package/dist/types/src/global-cli/helpers/sspawn.d.ts +2 -0
- package/dist/types/src/global-cli/helpers/welcomeMessage.d.ts +1 -0
- package/dist/types/src/global-cli/init.d.ts +2 -0
- package/dist/types/src/global-cli/new.d.ts +2 -0
- package/dist/types/src/helpers/CalendarDate.d.ts +51 -0
- package/dist/types/src/helpers/Env.d.ts +37 -0
- package/dist/types/src/helpers/EnvInternal.d.ts +6 -0
- package/dist/types/src/helpers/allNestedObjectKeys.d.ts +1 -0
- package/dist/types/src/helpers/benchmark.d.ts +6 -0
- package/dist/types/src/helpers/camelize.d.ts +3 -0
- package/dist/types/src/helpers/capitalize.d.ts +1 -0
- package/dist/types/src/helpers/cli/SchemaBuilder.d.ts +17 -0
- package/dist/types/src/helpers/cli/generateDream.d.ts +8 -0
- package/dist/types/src/helpers/cli/generateDreamContent.d.ts +6 -0
- package/dist/types/src/helpers/cli/generateFactory.d.ts +4 -0
- package/dist/types/src/helpers/cli/generateFactoryContent.d.ts +4 -0
- package/dist/types/src/helpers/cli/generateMigration.d.ts +6 -0
- package/dist/types/src/helpers/cli/generateMigrationContent.d.ts +7 -0
- package/dist/types/src/helpers/cli/generateSerializer.d.ts +5 -0
- package/dist/types/src/helpers/cli/generateSerializerContent.d.ts +5 -0
- package/dist/types/src/helpers/cli/generateStiMigrationContent.d.ts +6 -0
- package/dist/types/src/helpers/cli/generateUnitSpec.d.ts +3 -0
- package/dist/types/src/helpers/cli/generateUnitSpecContent.d.ts +3 -0
- package/dist/types/src/helpers/cloneDeepSafe.d.ts +18 -0
- package/dist/types/src/helpers/compact.d.ts +19 -0
- package/dist/types/src/helpers/customPgParsers.d.ts +9 -0
- package/dist/types/src/helpers/db/cachedTypeForAttribute.d.ts +2 -0
- package/dist/types/src/helpers/db/createDb.d.ts +2 -0
- package/dist/types/src/helpers/db/dropDb.d.ts +2 -0
- package/dist/types/src/helpers/db/foreignKeyTypeFromPrimaryKey.d.ts +2 -0
- package/dist/types/src/helpers/db/loadPgClient.d.ts +3 -0
- package/dist/types/src/helpers/db/primaryKeyType.d.ts +1 -0
- package/dist/types/src/helpers/db/runMigration.d.ts +6 -0
- package/dist/types/src/helpers/db/truncateDb.d.ts +1 -0
- package/dist/types/src/helpers/db/types/isDatabaseArrayColumn.d.ts +2 -0
- package/dist/types/src/helpers/db/types/isDateColumn.d.ts +2 -0
- package/dist/types/src/helpers/db/types/isDateTimeColumn.d.ts +2 -0
- package/dist/types/src/helpers/db/types/isJsonColumn.d.ts +2 -0
- package/dist/types/src/helpers/debug.d.ts +4 -0
- package/dist/types/src/helpers/dreamOrPsychicCoreDevelopment.d.ts +1 -0
- package/dist/types/src/helpers/filterObjectByKey.d.ts +1 -0
- package/dist/types/src/helpers/getFiles.d.ts +1 -0
- package/dist/types/src/helpers/globalClassNameFromFullyQualifiedModelName.d.ts +1 -0
- package/dist/types/src/helpers/hyphenize.d.ts +2 -0
- package/dist/types/src/helpers/inferSerializerFromDreamOrViewModel.d.ts +4 -0
- package/dist/types/src/helpers/isEmpty.d.ts +1 -0
- package/dist/types/src/helpers/loadEnv.d.ts +1 -0
- package/dist/types/src/helpers/loadRepl.d.ts +2 -0
- package/dist/types/src/helpers/migrationVersion.d.ts +1 -0
- package/dist/types/src/helpers/namespaceColumn.d.ts +1 -0
- package/dist/types/src/helpers/objectPathsToArrays.d.ts +2 -0
- package/dist/types/src/helpers/pascalize.d.ts +2 -0
- package/dist/types/src/helpers/pascalizePath.d.ts +1 -0
- package/dist/types/src/helpers/path/dreamFileAndDirPaths.d.ts +5 -0
- package/dist/types/src/helpers/path/dreamPath.d.ts +3 -0
- package/dist/types/src/helpers/path/relativeDreamPath.d.ts +3 -0
- package/dist/types/src/helpers/path/sharedPathPrefix.d.ts +1 -0
- package/dist/types/src/helpers/propertyNameFromFullyQualifiedModelName.d.ts +1 -0
- package/dist/types/src/helpers/protectAgainstPollutingAssignment.d.ts +1 -0
- package/dist/types/src/helpers/range.d.ts +7 -0
- package/dist/types/src/helpers/round.d.ts +2 -0
- package/dist/types/src/helpers/serializerNameFromFullyQualifiedModelName.d.ts +1 -0
- package/dist/types/src/helpers/snakeify.d.ts +3 -0
- package/dist/types/src/helpers/sortBy.d.ts +8 -0
- package/dist/types/src/helpers/sqlAttributes.d.ts +4 -0
- package/dist/types/src/helpers/sspawn.d.ts +2 -0
- package/dist/types/src/helpers/standardizeFullyQualifiedModelName.d.ts +1 -0
- package/dist/types/src/helpers/stringCasing.d.ts +28 -0
- package/dist/types/src/helpers/typechecks.d.ts +2 -0
- package/dist/types/src/helpers/typeutils.d.ts +115 -0
- package/dist/types/src/helpers/uncapitalize.d.ts +1 -0
- package/dist/types/src/helpers/uniq.d.ts +1 -0
- package/dist/types/src/index.d.ts +78 -0
- package/dist/types/src/openapi/types.d.ts +139 -0
- package/dist/types/src/ops/curried-ops-statement.d.ts +7 -0
- package/dist/types/src/ops/index.d.ts +49 -0
- package/dist/types/src/ops/ops-statement.d.ts +14 -0
- package/dist/types/src/serializer/decorators/associations/RendersMany.d.ts +42 -0
- package/dist/types/src/serializer/decorators/associations/RendersOne.d.ts +46 -0
- package/dist/types/src/serializer/decorators/associations/shared.d.ts +23 -0
- package/dist/types/src/serializer/decorators/attribute.d.ts +29 -0
- package/dist/types/src/serializer/decorators/helpers/dreamAttributeOpenapiShape.d.ts +7 -0
- package/dist/types/src/serializer/decorators/helpers/hasSerializersGetter.d.ts +2 -0
- package/dist/types/src/serializer/decorators/helpers/maybeSerializableToDreamSerializerCallbackFunction.d.ts +2 -0
- package/dist/types/src/serializer/index.d.ts +56 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/highlight.css +92 -0
- package/docs/assets/icons.js +18 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +60 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1448 -0
- package/docs/classes/Benchmark.html +4 -0
- package/docs/classes/CalendarDate.html +34 -0
- package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +12 -0
- package/docs/classes/Decorators.html +81 -0
- package/docs/classes/Dream.html +896 -0
- package/docs/classes/DreamApplication.html +37 -0
- package/docs/classes/DreamBin.html +11 -0
- package/docs/classes/DreamCLI.html +7 -0
- package/docs/classes/DreamImporter.html +6 -0
- package/docs/classes/DreamMigrationHelpers.html +32 -0
- package/docs/classes/DreamSerializer.html +19 -0
- package/docs/classes/DreamTransaction.html +5 -0
- package/docs/classes/Encrypt.html +8 -0
- package/docs/classes/Env.html +20 -0
- package/docs/classes/GlobalNameNotSet.html +12 -0
- package/docs/classes/NonLoadedAssociation.html +14 -0
- package/docs/classes/Query.html +383 -0
- package/docs/classes/Range.html +5 -0
- package/docs/classes/RecordNotFound.html +13 -0
- package/docs/classes/ValidationError.html +14 -0
- package/docs/functions/AfterCreate.html +1 -0
- package/docs/functions/AfterCreateCommit.html +13 -0
- package/docs/functions/AfterDestroy.html +1 -0
- package/docs/functions/AfterDestroyCommit.html +13 -0
- package/docs/functions/AfterSave.html +1 -0
- package/docs/functions/AfterSaveCommit.html +13 -0
- package/docs/functions/AfterUpdate.html +1 -0
- package/docs/functions/AfterUpdateCommit.html +13 -0
- package/docs/functions/Attribute.html +1 -0
- package/docs/functions/BeforeCreate.html +1 -0
- package/docs/functions/BeforeDestroy.html +1 -0
- package/docs/functions/BeforeSave.html +1 -0
- package/docs/functions/BeforeUpdate.html +1 -0
- package/docs/functions/RendersMany.html +16 -0
- package/docs/functions/RendersOne.html +16 -0
- package/docs/functions/ReplicaSafe.html +1 -0
- package/docs/functions/STI.html +1 -0
- package/docs/functions/Scope.html +1 -0
- package/docs/functions/SoftDelete.html +19 -0
- package/docs/functions/Sortable.html +1 -0
- package/docs/functions/Validate.html +1 -0
- package/docs/functions/Validates.html +1 -0
- package/docs/functions/Virtual.html +1 -0
- package/docs/functions/camelize.html +1 -0
- package/docs/functions/capitalize.html +1 -0
- package/docs/functions/closeAllDbConnections.html +1 -0
- package/docs/functions/compact.html +1 -0
- package/docs/functions/db.html +1 -0
- package/docs/functions/debug.html +1 -0
- package/docs/functions/dreamDbConnections.html +1 -0
- package/docs/functions/dreamPath.html +1 -0
- package/docs/functions/generateDream.html +1 -0
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -0
- package/docs/functions/hyphenize.html +1 -0
- package/docs/functions/inferSerializerFromDreamClassOrViewModelClass.html +1 -0
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -0
- package/docs/functions/isEmpty.html +1 -0
- package/docs/functions/loadRepl.html +1 -0
- package/docs/functions/lookupClassByGlobalName.html +1 -0
- package/docs/functions/pascalize.html +1 -0
- package/docs/functions/pgErrorType.html +1 -0
- package/docs/functions/range-1.html +1 -0
- package/docs/functions/relativeDreamPath.html +1 -0
- package/docs/functions/round.html +1 -0
- package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -0
- package/docs/functions/sharedPathPrefix.html +1 -0
- package/docs/functions/snakeify.html +1 -0
- package/docs/functions/sortBy.html +1 -0
- package/docs/functions/standardizeFullyQualifiedModelName.html +1 -0
- package/docs/functions/uncapitalize.html +1 -0
- package/docs/functions/uniq.html +1 -0
- package/docs/functions/validateColumn.html +1 -0
- package/docs/functions/validateTable.html +1 -0
- package/docs/index.html +123 -0
- package/docs/interfaces/AttributeStatement.html +6 -0
- package/docs/interfaces/DecoratorContext.html +8 -0
- package/docs/interfaces/DreamApplicationInitOptions.html +2 -0
- package/docs/interfaces/DreamApplicationOpts.html +8 -0
- package/docs/interfaces/DreamSerializerAssociationStatement.html +11 -0
- package/docs/interfaces/EncryptOptions.html +3 -0
- package/docs/interfaces/OpenapiSchemaProperties.html +1 -0
- package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -0
- package/docs/interfaces/OpenapiTypeFieldObject.html +1 -0
- package/docs/modules.html +163 -0
- package/docs/types/Camelized.html +1 -0
- package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -0
- package/docs/types/DreamAssociationMetadata.html +1 -0
- package/docs/types/DreamAttributes.html +1 -0
- package/docs/types/DreamClassColumn.html +1 -0
- package/docs/types/DreamColumn.html +1 -0
- package/docs/types/DreamColumnNames.html +1 -0
- package/docs/types/DreamLogLevel.html +1 -0
- package/docs/types/DreamLogger.html +1 -0
- package/docs/types/DreamOrViewModelSerializerKey.html +1 -0
- package/docs/types/DreamParamSafeAttributes.html +1 -0
- package/docs/types/DreamParamSafeColumnNames.html +1 -0
- package/docs/types/DreamSerializerKey.html +1 -0
- package/docs/types/DreamSerializers.html +1 -0
- package/docs/types/DreamTableSchema.html +1 -0
- package/docs/types/DreamVirtualColumns.html +1 -0
- package/docs/types/EncryptAlgorithm.html +1 -0
- package/docs/types/Hyphenized.html +1 -0
- package/docs/types/IdType.html +1 -0
- package/docs/types/OpenapiAllTypes.html +1 -0
- package/docs/types/OpenapiFormats.html +1 -0
- package/docs/types/OpenapiNumberFormats.html +1 -0
- package/docs/types/OpenapiPrimitiveTypes.html +1 -0
- package/docs/types/OpenapiSchemaArray.html +1 -0
- package/docs/types/OpenapiSchemaArrayShorthand.html +1 -0
- package/docs/types/OpenapiSchemaBase.html +1 -0
- package/docs/types/OpenapiSchemaBody.html +1 -0
- package/docs/types/OpenapiSchemaBodyShorthand.html +1 -0
- package/docs/types/OpenapiSchemaCommonFields.html +1 -0
- package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -0
- package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -0
- package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -0
- package/docs/types/OpenapiSchemaExpressionRef.html +1 -0
- package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -0
- package/docs/types/OpenapiSchemaInteger.html +1 -0
- package/docs/types/OpenapiSchemaNull.html +1 -0
- package/docs/types/OpenapiSchemaNumber.html +1 -0
- package/docs/types/OpenapiSchemaObject.html +1 -0
- package/docs/types/OpenapiSchemaObjectAllOf.html +1 -0
- package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -0
- package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -0
- package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -0
- package/docs/types/OpenapiSchemaObjectBase.html +1 -0
- package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -0
- package/docs/types/OpenapiSchemaObjectOneOf.html +1 -0
- package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -0
- package/docs/types/OpenapiSchemaObjectShorthand.html +1 -0
- package/docs/types/OpenapiSchemaPartialSegment.html +1 -0
- package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -0
- package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -0
- package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -0
- package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -0
- package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -0
- package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -0
- package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -0
- package/docs/types/OpenapiSchemaString.html +1 -0
- package/docs/types/OpenapiShorthandAllTypes.html +1 -0
- package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -0
- package/docs/types/OpenapiTypeField.html +1 -0
- package/docs/types/Pascalized.html +1 -0
- package/docs/types/PrimaryKeyType.html +1 -0
- package/docs/types/RoundingPrecision.html +1 -0
- package/docs/types/SerializableClassOrSerializerCallback.html +1 -0
- package/docs/types/SerializableDreamClassOrViewModelClass.html +1 -0
- package/docs/types/SerializableDreamOrViewModel.html +1 -0
- package/docs/types/SerializableTypes.html +1 -0
- package/docs/types/Snakeified.html +1 -0
- package/docs/types/Timestamp.html +1 -0
- package/docs/types/UpdateableAssociationProperties.html +1 -0
- package/docs/types/UpdateableProperties.html +1 -0
- package/docs/types/ValidationType.html +1 -0
- package/docs/types/ViewModelSerializerKey.html +1 -0
- package/docs/types/WhereStatementForDream.html +1 -0
- package/docs/types/WhereStatementForDreamClass.html +1 -0
- package/docs/variables/DreamConst.html +1 -0
- package/docs/variables/TRIGRAM_OPERATORS.html +1 -0
- package/docs/variables/openapiPrimitiveTypes-1.html +1 -0
- package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -0
- package/docs/variables/ops.html +1 -0
- package/docs/variables/primaryKeyTypes.html +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,2615 @@
|
|
|
1
|
+
import { sql, } from 'kysely';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
import pluralize from 'pluralize-esm';
|
|
4
|
+
import ConnectedToDB from '../db/ConnectedToDB.js';
|
|
5
|
+
import associationToGetterSetterProp from '../decorators/associations/associationToGetterSetterProp.js';
|
|
6
|
+
import { SOFT_DELETE_SCOPE_NAME } from '../decorators/SoftDelete.js';
|
|
7
|
+
import CannotAssociateThroughPolymorphic from '../errors/associations/CannotAssociateThroughPolymorphic.js';
|
|
8
|
+
import CannotJoinPolymorphicBelongsToError from '../errors/associations/CannotJoinPolymorphicBelongsToError.js';
|
|
9
|
+
import JoinAttemptedOnMissingAssociation from '../errors/associations/JoinAttemptedOnMissingAssociation.js';
|
|
10
|
+
import MissingRequiredAssociationOnClause from '../errors/associations/MissingRequiredAssociationOnClause.js';
|
|
11
|
+
import MissingRequiredPassthroughForAssociationOnClause from '../errors/associations/MissingRequiredPassthroughForAssociationOnClause.js';
|
|
12
|
+
import MissingThroughAssociation from '../errors/associations/MissingThroughAssociation.js';
|
|
13
|
+
import MissingThroughAssociationSource from '../errors/associations/MissingThroughAssociationSource.js';
|
|
14
|
+
import CannotCallUndestroyOnANonSoftDeleteModel from '../errors/CannotCallUndestroyOnANonSoftDeleteModel.js';
|
|
15
|
+
import CannotNegateSimilarityClause from '../errors/CannotNegateSimilarityClause.js';
|
|
16
|
+
import CannotPassAdditionalFieldsToPluckEachAfterCallback from '../errors/CannotPassAdditionalFieldsToPluckEachAfterCallback.js';
|
|
17
|
+
import CannotPassUndefinedAsAValueToAWhereClause from '../errors/CannotPassUndefinedAsAValueToAWhereClause.js';
|
|
18
|
+
import LeftJoinPreloadIncompatibleWithFindEach from '../errors/LeftJoinPreloadIncompatibleWithFindEach.js';
|
|
19
|
+
import MissingRequiredCallbackFunctionToPluckEach from '../errors/MissingRequiredCallbackFunctionToPluckEach.js';
|
|
20
|
+
import NoUpdateAllOnJoins from '../errors/NoUpdateAllOnJoins.js';
|
|
21
|
+
import NoUpdateOnAssociationQuery from '../errors/NoUpdateOnAssociationQuery.js';
|
|
22
|
+
import RecordNotFound from '../errors/RecordNotFound.js';
|
|
23
|
+
import CalendarDate from '../helpers/CalendarDate.js';
|
|
24
|
+
import camelize from '../helpers/camelize.js';
|
|
25
|
+
import cloneDeepSafe from '../helpers/cloneDeepSafe.js';
|
|
26
|
+
import compact from '../helpers/compact.js';
|
|
27
|
+
import isEmpty from '../helpers/isEmpty.js';
|
|
28
|
+
import namespaceColumn from '../helpers/namespaceColumn.js';
|
|
29
|
+
import objectPathsToArrays from '../helpers/objectPathsToArrays.js';
|
|
30
|
+
import protectAgainstPollutingAssignment from '../helpers/protectAgainstPollutingAssignment.js';
|
|
31
|
+
import { Range } from '../helpers/range.js';
|
|
32
|
+
import snakeify from '../helpers/snakeify.js';
|
|
33
|
+
import { isObject, isString } from '../helpers/typechecks.js';
|
|
34
|
+
import uniq from '../helpers/uniq.js';
|
|
35
|
+
import CurriedOpsStatement from '../ops/curried-ops-statement.js';
|
|
36
|
+
import ops from '../ops/index.js';
|
|
37
|
+
import OpsStatement from '../ops/ops-statement.js';
|
|
38
|
+
import executeDatabaseQuery from './internal/executeDatabaseQuery.js';
|
|
39
|
+
import extractAssociationMetadataFromAssociationName from './internal/extractAssociationMetadataFromAssociationName.js';
|
|
40
|
+
import orderByDirection from './internal/orderByDirection.js';
|
|
41
|
+
import shouldBypassDefaultScope from './internal/shouldBypassDefaultScope.js';
|
|
42
|
+
import SimilarityBuilder from './internal/similarity/SimilarityBuilder.js';
|
|
43
|
+
import sqlResultToDreamInstance from './internal/sqlResultToDreamInstance.js';
|
|
44
|
+
import { DreamConst, } from './types.js';
|
|
45
|
+
export default class Query extends ConnectedToDB {
|
|
46
|
+
/**
|
|
47
|
+
* @internal
|
|
48
|
+
*
|
|
49
|
+
* stores the default batch sizes for various
|
|
50
|
+
* provided batching methods
|
|
51
|
+
*/
|
|
52
|
+
static BATCH_SIZES = {
|
|
53
|
+
FIND_EACH: 1000,
|
|
54
|
+
PLUCK_EACH: 10000,
|
|
55
|
+
PLUCK_EACH_THROUGH: 1000,
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* @internal
|
|
59
|
+
* purely for typing
|
|
60
|
+
*/
|
|
61
|
+
queryTypeOpts;
|
|
62
|
+
/**
|
|
63
|
+
* @internal
|
|
64
|
+
*
|
|
65
|
+
* stores the dream transaction applied to the
|
|
66
|
+
* current Query instance
|
|
67
|
+
*/
|
|
68
|
+
dreamTransaction = null;
|
|
69
|
+
/**
|
|
70
|
+
* @internal
|
|
71
|
+
*
|
|
72
|
+
* stores the passthrough on statements applied to the
|
|
73
|
+
* current Query instance
|
|
74
|
+
*/
|
|
75
|
+
passthroughOnStatement = Object.freeze({});
|
|
76
|
+
/**
|
|
77
|
+
* @internal
|
|
78
|
+
*
|
|
79
|
+
* stores the where statements applied to the
|
|
80
|
+
* current Query instance
|
|
81
|
+
*/
|
|
82
|
+
whereStatements = Object.freeze([]);
|
|
83
|
+
/**
|
|
84
|
+
* @internal
|
|
85
|
+
*
|
|
86
|
+
* stores the where not statements applied to the
|
|
87
|
+
* current Query instance
|
|
88
|
+
*/
|
|
89
|
+
whereNotStatements = Object.freeze([]);
|
|
90
|
+
/**
|
|
91
|
+
* @internal
|
|
92
|
+
*
|
|
93
|
+
* stores the limit statements applied to the
|
|
94
|
+
* current Query instance
|
|
95
|
+
*/
|
|
96
|
+
limitStatement;
|
|
97
|
+
/**
|
|
98
|
+
* @internal
|
|
99
|
+
*
|
|
100
|
+
* stores the offset statements applied to the
|
|
101
|
+
* current Query instance
|
|
102
|
+
*/
|
|
103
|
+
offsetStatement;
|
|
104
|
+
/**
|
|
105
|
+
* @internal
|
|
106
|
+
*
|
|
107
|
+
* stores the or statements applied to the
|
|
108
|
+
* current Query instance
|
|
109
|
+
*/
|
|
110
|
+
whereAnyStatements = Object.freeze([]);
|
|
111
|
+
/**
|
|
112
|
+
* @internal
|
|
113
|
+
*
|
|
114
|
+
* stores the order statements applied to the
|
|
115
|
+
* current Query instance
|
|
116
|
+
*/
|
|
117
|
+
orderStatements = Object.freeze([]);
|
|
118
|
+
/**
|
|
119
|
+
* @internal
|
|
120
|
+
*
|
|
121
|
+
* whether or not to turn joins into load statements
|
|
122
|
+
*/
|
|
123
|
+
joinLoadActivated = false;
|
|
124
|
+
/**
|
|
125
|
+
* @internal
|
|
126
|
+
*
|
|
127
|
+
* stores the preload statements applied to the
|
|
128
|
+
* current Query instance
|
|
129
|
+
*/
|
|
130
|
+
preloadStatements = Object.freeze({});
|
|
131
|
+
/**
|
|
132
|
+
* @internal
|
|
133
|
+
*
|
|
134
|
+
* stores the preload on statements applied to the
|
|
135
|
+
* current Query instance
|
|
136
|
+
*/
|
|
137
|
+
preloadOnStatements = Object.freeze({});
|
|
138
|
+
/**
|
|
139
|
+
* @internal
|
|
140
|
+
*
|
|
141
|
+
* stores the joins statements applied to the
|
|
142
|
+
* current Query instance
|
|
143
|
+
*/
|
|
144
|
+
innerJoinStatements = Object.freeze({});
|
|
145
|
+
/**
|
|
146
|
+
* @internal
|
|
147
|
+
*
|
|
148
|
+
* stores the joins on statements applied to the
|
|
149
|
+
* current Query instance
|
|
150
|
+
*/
|
|
151
|
+
innerJoinOnStatements = Object.freeze({});
|
|
152
|
+
/**
|
|
153
|
+
* @internal
|
|
154
|
+
*
|
|
155
|
+
* stores the joins statements applied to the
|
|
156
|
+
* current Query instance
|
|
157
|
+
*/
|
|
158
|
+
leftJoinStatements = Object.freeze({});
|
|
159
|
+
/**
|
|
160
|
+
* @internal
|
|
161
|
+
*
|
|
162
|
+
* stores the joins on statements applied to the
|
|
163
|
+
* current Query instance
|
|
164
|
+
*/
|
|
165
|
+
leftJoinOnStatements = Object.freeze({});
|
|
166
|
+
/**
|
|
167
|
+
* @internal
|
|
168
|
+
*
|
|
169
|
+
* Whether or not to bypass all default scopes for this Query
|
|
170
|
+
*/
|
|
171
|
+
bypassAllDefaultScopes = false;
|
|
172
|
+
/**
|
|
173
|
+
* @internal
|
|
174
|
+
*
|
|
175
|
+
* Whether or not to bypass all default scopes for this Query, but not associations
|
|
176
|
+
*/
|
|
177
|
+
bypassAllDefaultScopesExceptOnAssociations = false;
|
|
178
|
+
/**
|
|
179
|
+
* @internal
|
|
180
|
+
*
|
|
181
|
+
* Specific default scopes to bypass
|
|
182
|
+
*/
|
|
183
|
+
defaultScopesToBypass = [];
|
|
184
|
+
/**
|
|
185
|
+
* @internal
|
|
186
|
+
*
|
|
187
|
+
* Specific default scopes to bypass, but not associations
|
|
188
|
+
*/
|
|
189
|
+
defaultScopesToBypassExceptOnAssociations = [];
|
|
190
|
+
/**
|
|
191
|
+
* @internal
|
|
192
|
+
*
|
|
193
|
+
* Whether or not to bypass SoftDelete and really destroy a record
|
|
194
|
+
* when calling destroy.
|
|
195
|
+
*/
|
|
196
|
+
shouldReallyDestroy = false;
|
|
197
|
+
/**
|
|
198
|
+
* @internal
|
|
199
|
+
*
|
|
200
|
+
* The distinct column to apply to the Query
|
|
201
|
+
*/
|
|
202
|
+
distinctColumn = null;
|
|
203
|
+
/**
|
|
204
|
+
* @internal
|
|
205
|
+
*
|
|
206
|
+
* The base sql alias to use for the base model
|
|
207
|
+
* of this Query
|
|
208
|
+
*/
|
|
209
|
+
baseSqlAlias;
|
|
210
|
+
get tableName() {
|
|
211
|
+
return this.dreamClass.table;
|
|
212
|
+
}
|
|
213
|
+
get namespacedPrimaryKey() {
|
|
214
|
+
return namespaceColumn(this.dreamClass.primaryKey, this.baseSqlAlias);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* @internal
|
|
218
|
+
*
|
|
219
|
+
* Used for unscoping Query instances. In most cases, this will be null,
|
|
220
|
+
* but when calling `removeAllDefaultScopes`, a removeAllDefaultScopes Query is stored as
|
|
221
|
+
* baseSelectQuery.
|
|
222
|
+
*/
|
|
223
|
+
baseSelectQuery;
|
|
224
|
+
constructor(dreamInstance, opts = {}) {
|
|
225
|
+
super(dreamInstance, opts);
|
|
226
|
+
this.passthroughOnStatement = Object.freeze(opts.passthroughOnStatement || {});
|
|
227
|
+
this.whereStatements = Object.freeze(opts.where || []);
|
|
228
|
+
this.whereNotStatements = Object.freeze(opts.whereNot || []);
|
|
229
|
+
this.whereAnyStatements = Object.freeze(opts.or || []);
|
|
230
|
+
this.orderStatements = Object.freeze(opts.order || []);
|
|
231
|
+
this.joinLoadActivated = opts.loadFromJoins || false;
|
|
232
|
+
this.preloadStatements = Object.freeze(opts.preloadStatements || {});
|
|
233
|
+
this.preloadOnStatements = Object.freeze(opts.preloadOnStatements || {});
|
|
234
|
+
this.innerJoinStatements = Object.freeze(opts.innerJoinStatements || {});
|
|
235
|
+
this.innerJoinOnStatements = Object.freeze(opts.innerJoinOnStatements || {});
|
|
236
|
+
this.leftJoinStatements = Object.freeze(opts.leftJoinStatements || {});
|
|
237
|
+
this.leftJoinOnStatements = Object.freeze(opts.leftJoinOnStatements || {});
|
|
238
|
+
this.baseSqlAlias = opts.baseSqlAlias || this.tableName;
|
|
239
|
+
this.baseSelectQuery = opts.baseSelectQuery || null;
|
|
240
|
+
this.limitStatement = opts.limit || null;
|
|
241
|
+
this.offsetStatement = opts.offset || null;
|
|
242
|
+
this.bypassAllDefaultScopes = opts.bypassAllDefaultScopes || false;
|
|
243
|
+
this.bypassAllDefaultScopesExceptOnAssociations = opts.bypassAllDefaultScopesExceptOnAssociations || false;
|
|
244
|
+
this.defaultScopesToBypass = opts.defaultScopesToBypass || [];
|
|
245
|
+
this.defaultScopesToBypassExceptOnAssociations = opts.defaultScopesToBypassExceptOnAssociations || [];
|
|
246
|
+
this.dreamTransaction = opts.transaction || null;
|
|
247
|
+
this.distinctColumn = opts.distinctColumn || null;
|
|
248
|
+
this.connectionOverride = opts.connection;
|
|
249
|
+
this.shouldReallyDestroy = opts.shouldReallyDestroy || false;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Returns true. Useful for distinguishing Query instances
|
|
253
|
+
* from other objects.
|
|
254
|
+
*
|
|
255
|
+
* @returns true
|
|
256
|
+
*/
|
|
257
|
+
get isDreamQuery() {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* @internal
|
|
262
|
+
*
|
|
263
|
+
* Used for applying preload and load statements
|
|
264
|
+
*
|
|
265
|
+
* @returns An associated Query
|
|
266
|
+
*/
|
|
267
|
+
dreamClassQueryWithScopeBypasses(dreamClass, { bypassAllDefaultScopesExceptOnAssociations = false, defaultScopesToBypassExceptOnAssociations = [], } = {}) {
|
|
268
|
+
const associationQuery = dreamClass.query().clone({
|
|
269
|
+
passthroughOnStatement: this.passthroughOnStatement,
|
|
270
|
+
bypassAllDefaultScopes: this.bypassAllDefaultScopes,
|
|
271
|
+
bypassAllDefaultScopesExceptOnAssociations,
|
|
272
|
+
defaultScopesToBypass: this.defaultScopesToBypass,
|
|
273
|
+
defaultScopesToBypassExceptOnAssociations,
|
|
274
|
+
});
|
|
275
|
+
return (this.dreamTransaction ? associationQuery.txn(this.dreamTransaction) : associationQuery);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* @internal
|
|
279
|
+
*
|
|
280
|
+
* Returns a cloned version of the Query
|
|
281
|
+
*
|
|
282
|
+
* ```ts
|
|
283
|
+
* const clonedQuery = User.query().clone()
|
|
284
|
+
* ```
|
|
285
|
+
*
|
|
286
|
+
* @param opts - Statements to override when cloning the Query
|
|
287
|
+
* @returns A cloned Query with the provided overrides clause applied
|
|
288
|
+
*/
|
|
289
|
+
clone(opts = {}) {
|
|
290
|
+
return new Query(this.dreamInstance, {
|
|
291
|
+
baseSqlAlias: opts.baseSqlAlias || this.baseSqlAlias,
|
|
292
|
+
baseSelectQuery: opts.baseSelectQuery || this.baseSelectQuery,
|
|
293
|
+
passthroughOnStatement: {
|
|
294
|
+
...this.passthroughOnStatement,
|
|
295
|
+
...(opts.passthroughOnStatement || {}),
|
|
296
|
+
},
|
|
297
|
+
where: opts.where === null ? [] : [...this.whereStatements, ...(opts.where || [])],
|
|
298
|
+
whereNot: opts.whereNot === null ? [] : [...this.whereNotStatements, ...(opts.whereNot || [])],
|
|
299
|
+
limit: opts.limit === null ? null : opts.limit !== undefined ? opts.limit : this.limitStatement || null,
|
|
300
|
+
offset: opts.limit === null || opts.offset === null
|
|
301
|
+
? null
|
|
302
|
+
: opts.offset !== undefined
|
|
303
|
+
? opts.offset
|
|
304
|
+
: this.offsetStatement || null,
|
|
305
|
+
or: opts.or === null ? [] : [...this.whereAnyStatements, ...(opts.or || [])],
|
|
306
|
+
order: opts.order === null ? [] : [...this.orderStatements, ...(opts.order || [])],
|
|
307
|
+
distinctColumn: opts.distinctColumn !== undefined ? opts.distinctColumn : this.distinctColumn,
|
|
308
|
+
loadFromJoins: opts.loadFromJoins !== undefined ? opts.loadFromJoins : this.joinLoadActivated,
|
|
309
|
+
// when passed, preloadStatements, preloadOnStatements, innerJoinStatements, and innerJoinOnStatements are already
|
|
310
|
+
// cloned versions of the `this.` versions, handled in the `preload` and `joins` methods
|
|
311
|
+
preloadStatements: opts.preloadStatements || this.preloadStatements,
|
|
312
|
+
preloadOnStatements: opts.preloadOnStatements || this.preloadOnStatements,
|
|
313
|
+
innerJoinDreamClasses: opts.innerJoinDreamClasses || this.innerJoinDreamClasses,
|
|
314
|
+
innerJoinStatements: opts.innerJoinStatements || this.innerJoinStatements,
|
|
315
|
+
innerJoinOnStatements: opts.innerJoinOnStatements || this.innerJoinOnStatements,
|
|
316
|
+
leftJoinStatements: opts.leftJoinStatements || this.leftJoinStatements,
|
|
317
|
+
leftJoinOnStatements: opts.leftJoinOnStatements || this.leftJoinOnStatements,
|
|
318
|
+
// end:when passed, preloadStatements, preloadOnStatements, innerJoinStatements, and innerJoinOnStatements are already...
|
|
319
|
+
bypassAllDefaultScopes: opts.bypassAllDefaultScopes !== undefined ? opts.bypassAllDefaultScopes : this.bypassAllDefaultScopes,
|
|
320
|
+
bypassAllDefaultScopesExceptOnAssociations: opts.bypassAllDefaultScopesExceptOnAssociations !== undefined
|
|
321
|
+
? opts.bypassAllDefaultScopesExceptOnAssociations
|
|
322
|
+
: this.bypassAllDefaultScopesExceptOnAssociations,
|
|
323
|
+
defaultScopesToBypass: opts.defaultScopesToBypass !== undefined ? opts.defaultScopesToBypass : this.defaultScopesToBypass,
|
|
324
|
+
defaultScopesToBypassExceptOnAssociations: opts.defaultScopesToBypassExceptOnAssociations !== undefined
|
|
325
|
+
? opts.defaultScopesToBypassExceptOnAssociations
|
|
326
|
+
: this.defaultScopesToBypassExceptOnAssociations,
|
|
327
|
+
transaction: opts.transaction || this.dreamTransaction,
|
|
328
|
+
connection: opts.connection || this.connectionOverride,
|
|
329
|
+
shouldReallyDestroy: opts.shouldReallyDestroy !== undefined ? opts.shouldReallyDestroy : this.shouldReallyDestroy,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Finds a record matching the Query with the
|
|
334
|
+
* specified primary key. If not found, null
|
|
335
|
+
* is returned.
|
|
336
|
+
*
|
|
337
|
+
* ```ts
|
|
338
|
+
* await User.query().find(123)
|
|
339
|
+
* // User{id: 123}
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* @param primaryKey - The primary key of the record to look up
|
|
343
|
+
* @returns Either the found record, or else null
|
|
344
|
+
*/
|
|
345
|
+
async find(primaryKey) {
|
|
346
|
+
if (!primaryKey)
|
|
347
|
+
return null;
|
|
348
|
+
return await this.where({
|
|
349
|
+
[this.dreamInstance.primaryKey]: primaryKey,
|
|
350
|
+
}).first();
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Finds a record matching the Query with the
|
|
354
|
+
* specified primary key. If not found, an exception
|
|
355
|
+
* is raised.
|
|
356
|
+
*
|
|
357
|
+
* ```ts
|
|
358
|
+
* await User.query().findOrFail(123)
|
|
359
|
+
* // User{id: 123}
|
|
360
|
+
* ```
|
|
361
|
+
*
|
|
362
|
+
* @param primaryKey - The primary key of the record to look up
|
|
363
|
+
* @returns The found record
|
|
364
|
+
*/
|
|
365
|
+
async findOrFail(primaryKey) {
|
|
366
|
+
const record = await this.find(primaryKey);
|
|
367
|
+
if (!record)
|
|
368
|
+
throw new RecordNotFound(this.dreamInstance.constructor.name);
|
|
369
|
+
return record;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Finds a record matching the Query and the
|
|
373
|
+
* specified where statement. If not found, null
|
|
374
|
+
* is returned.
|
|
375
|
+
*
|
|
376
|
+
* ```ts
|
|
377
|
+
* await User.query().findBy({ email: 'how@yadoin' })
|
|
378
|
+
* // User{email: 'how@yadoin'}
|
|
379
|
+
* ```
|
|
380
|
+
*
|
|
381
|
+
* @param whereStatement - The where statement used to locate the record
|
|
382
|
+
* @returns Either the first record found matching the attributes, or else null
|
|
383
|
+
*/
|
|
384
|
+
async findBy(whereStatement) {
|
|
385
|
+
return await this._where(whereStatement, 'where').first();
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Finds a record matching the Query and the
|
|
389
|
+
* specified where statement. If not found, an exception
|
|
390
|
+
* is raised.
|
|
391
|
+
*
|
|
392
|
+
* ```ts
|
|
393
|
+
* await User.query().findOrFailBy({ email: 'how@yadoin' })
|
|
394
|
+
* // User{email: 'how@yadoin'}
|
|
395
|
+
* ```
|
|
396
|
+
*
|
|
397
|
+
* @param whereStatement - The where statement used to locate the record
|
|
398
|
+
* @returns The first record found matching the attributes
|
|
399
|
+
*/
|
|
400
|
+
async findOrFailBy(whereStatement) {
|
|
401
|
+
const record = await this.findBy(whereStatement);
|
|
402
|
+
if (!record)
|
|
403
|
+
throw new RecordNotFound(this.dreamInstance.constructor.name);
|
|
404
|
+
return record;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Finds all records matching the Query in batches,
|
|
408
|
+
* and then calls the provided callback for each found record.
|
|
409
|
+
* Once all records have been passed for a given batch, the next set of
|
|
410
|
+
* records will be fetched and passed to your callback, until all
|
|
411
|
+
* records matching the Query have been fetched.
|
|
412
|
+
*
|
|
413
|
+
* ```ts
|
|
414
|
+
* await User.order('id').findEach(user => {
|
|
415
|
+
* DreamApplication.log(user)
|
|
416
|
+
* })
|
|
417
|
+
* // User{id: 1}
|
|
418
|
+
* // User{id: 2}
|
|
419
|
+
* ```
|
|
420
|
+
*
|
|
421
|
+
* @param cb - The callback to call for each found record
|
|
422
|
+
* @param options - Options for destroying the instance
|
|
423
|
+
* @param options.batchSize - The batch size you wish to collect records in. If not provided, it will default to 1000
|
|
424
|
+
* @returns void
|
|
425
|
+
*/
|
|
426
|
+
async findEach(cb, { batchSize = Query.BATCH_SIZES.FIND_EACH } = {}) {
|
|
427
|
+
if (this.joinLoadActivated)
|
|
428
|
+
throw new LeftJoinPreloadIncompatibleWithFindEach();
|
|
429
|
+
let records;
|
|
430
|
+
const query = this.order(null)
|
|
431
|
+
.order(this.namespacedPrimaryKey)
|
|
432
|
+
.limit(batchSize);
|
|
433
|
+
let lastId = null;
|
|
434
|
+
do {
|
|
435
|
+
if (lastId)
|
|
436
|
+
records = await query.where({ [this.dreamInstance.primaryKey]: ops.greaterThan(lastId) }).all();
|
|
437
|
+
else
|
|
438
|
+
records = await query.all();
|
|
439
|
+
for (const record of records) {
|
|
440
|
+
await cb(record);
|
|
441
|
+
}
|
|
442
|
+
lastId = records[records.length - 1]?.primaryKeyValue;
|
|
443
|
+
} while (records.length > 0 && records.length === batchSize);
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Load each specified association using a single SQL query.
|
|
447
|
+
* See {@link #preload} for preloading in separate queries.
|
|
448
|
+
*
|
|
449
|
+
* Note: since leftJoinPreload loads via single query, it has
|
|
450
|
+
* some downsides and that may be avoided using {@link #preload}:
|
|
451
|
+
* 1. `limit` and `offset` will be automatically removed
|
|
452
|
+
* 2. `through` associations will bring additional namespaces into the query that can conflict with through associations from other associations, creating an invalid query
|
|
453
|
+
* 3. each nested association will result in an additional record which duplicates data from the outer record. E.g., given `.leftJoinPreload('a', 'b', 'c')`, if each `a` has 10 `b` and each `b` has 10 `c`, then for one `a`, 100 records will be returned, each of which has all of the columns of `a`. `.preload('a', 'b', 'c')` would perform three separate SQL queries, but the data for a single `a` would only be returned once.
|
|
454
|
+
* 4. the individual query becomes more complex the more associations are included
|
|
455
|
+
* 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.preload(...).findEach(...)` avoids instantiating massive amounts of data at once
|
|
456
|
+
*
|
|
457
|
+
*
|
|
458
|
+
* ```ts
|
|
459
|
+
* const posts = await user.associationQuery('posts').leftJoinPreload('comments', { visibilty: 'public' }, 'replies').all()
|
|
460
|
+
* console.log(posts[0].comments[0].replies[0])
|
|
461
|
+
* // [Reply{id: 1}, Reply{id: 2}]
|
|
462
|
+
* ```
|
|
463
|
+
*
|
|
464
|
+
* @param args - A chain of association names and on/notOn/onAny clauses
|
|
465
|
+
* @returns A cloned Query with the joinLoad statement applied
|
|
466
|
+
*/
|
|
467
|
+
leftJoinPreload(...args) {
|
|
468
|
+
const untypedArgs = [...args];
|
|
469
|
+
const lastAssociations = [untypedArgs.pop()].flat();
|
|
470
|
+
let joinedClone = this;
|
|
471
|
+
lastAssociations.forEach(associationName => {
|
|
472
|
+
joinedClone = joinedClone.leftJoin(...untypedArgs, associationName);
|
|
473
|
+
});
|
|
474
|
+
return joinedClone.clone({ loadFromJoins: true });
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Load each specified association using a separate SQL query.
|
|
478
|
+
* See {@link #leftJoinPreload} for preloading in a single query.
|
|
479
|
+
*
|
|
480
|
+
* ```ts
|
|
481
|
+
* const user = await User.query().preload('posts', 'comments', { visibilty: 'public' }, 'replies').first()
|
|
482
|
+
* console.log(user.posts[0].comments[0].replies[0])
|
|
483
|
+
* // [Reply{id: 1}, Reply{id: 2}]
|
|
484
|
+
* ```
|
|
485
|
+
*
|
|
486
|
+
* @param args - A chain of association names and on/notOn/onAny clauses
|
|
487
|
+
* @returns A cloned Query with the preload statement applied
|
|
488
|
+
*/
|
|
489
|
+
preload(...args) {
|
|
490
|
+
const preloadStatements = cloneDeepSafe(this.preloadStatements);
|
|
491
|
+
const preloadOnStatements = cloneDeepSafe(this.preloadOnStatements);
|
|
492
|
+
this.fleshOutJoinStatements([], preloadStatements, preloadOnStatements, null, [...args]);
|
|
493
|
+
return this.clone({ preloadStatements, preloadOnStatements: preloadOnStatements });
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Returns a new Query instance, with the provided
|
|
497
|
+
* joins statement attached
|
|
498
|
+
*
|
|
499
|
+
* ```ts
|
|
500
|
+
* await User.query().innerJoin('posts').first()
|
|
501
|
+
* ```
|
|
502
|
+
*
|
|
503
|
+
* @param args - A chain of association names and on/notOn/onAny clauses
|
|
504
|
+
* @returns A cloned Query with the joins clause applied
|
|
505
|
+
*/
|
|
506
|
+
innerJoin(...args) {
|
|
507
|
+
const innerJoinDreamClasses = [...this.innerJoinDreamClasses];
|
|
508
|
+
const innerJoinStatements = cloneDeepSafe(this.innerJoinStatements);
|
|
509
|
+
const innerJoinOnStatements = cloneDeepSafe(this.innerJoinOnStatements);
|
|
510
|
+
this.fleshOutJoinStatements(innerJoinDreamClasses, innerJoinStatements, innerJoinOnStatements, null, [...args]);
|
|
511
|
+
return this.clone({ innerJoinDreamClasses, innerJoinStatements, innerJoinOnStatements });
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* @internal
|
|
515
|
+
*
|
|
516
|
+
* @param args - A chain of association names and on/notOn/onAny clauses
|
|
517
|
+
* @returns A cloned Query with the joins clause applied
|
|
518
|
+
*/
|
|
519
|
+
leftJoin(...args) {
|
|
520
|
+
const innerJoinDreamClasses = [...this.innerJoinDreamClasses];
|
|
521
|
+
const leftJoinStatements = cloneDeepSafe(this.leftJoinStatements);
|
|
522
|
+
const leftJoinOnStatements = cloneDeepSafe(this.leftJoinOnStatements);
|
|
523
|
+
this.fleshOutJoinStatements(innerJoinDreamClasses, leftJoinStatements, leftJoinOnStatements, null, [
|
|
524
|
+
...args,
|
|
525
|
+
]);
|
|
526
|
+
return this.clone({ innerJoinDreamClasses, leftJoinStatements, leftJoinOnStatements });
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* @internal
|
|
530
|
+
*
|
|
531
|
+
*/
|
|
532
|
+
fleshOutJoinStatements(innerJoinDreamClasses, joinStatements, joinOnStatements, previousAssociationName, associationStatements, previousDreamClass = this.dreamClass) {
|
|
533
|
+
const nextAssociationStatement = associationStatements.shift();
|
|
534
|
+
if (nextAssociationStatement === undefined) {
|
|
535
|
+
// just satisfying typing
|
|
536
|
+
}
|
|
537
|
+
else if (isString(nextAssociationStatement)) {
|
|
538
|
+
const nextStatement = nextAssociationStatement;
|
|
539
|
+
if (!joinStatements[nextStatement])
|
|
540
|
+
joinStatements[protectAgainstPollutingAssignment(nextStatement)] = {};
|
|
541
|
+
if (!joinOnStatements[nextStatement])
|
|
542
|
+
joinOnStatements[protectAgainstPollutingAssignment(nextStatement)] = {};
|
|
543
|
+
const nextDreamClass = this.addAssociatedDreamClassToInnerJoinDreamClasses(previousDreamClass, nextStatement, innerJoinDreamClasses);
|
|
544
|
+
const nextJoinsStatements = joinStatements[nextStatement];
|
|
545
|
+
const nextJoinsOnStatements = joinOnStatements[nextStatement];
|
|
546
|
+
this.fleshOutJoinStatements(innerJoinDreamClasses, nextJoinsStatements, nextJoinsOnStatements, nextStatement, associationStatements, nextDreamClass);
|
|
547
|
+
//
|
|
548
|
+
}
|
|
549
|
+
else if (Array.isArray(nextAssociationStatement)) {
|
|
550
|
+
// this supports the final argument of load/preload statements
|
|
551
|
+
nextAssociationStatement.forEach((associationName) => {
|
|
552
|
+
this.addAssociatedDreamClassToInnerJoinDreamClasses(previousDreamClass, associationName, innerJoinDreamClasses);
|
|
553
|
+
});
|
|
554
|
+
nextAssociationStatement.forEach(associationStatement => {
|
|
555
|
+
joinStatements[protectAgainstPollutingAssignment(associationStatement)] = {};
|
|
556
|
+
});
|
|
557
|
+
//
|
|
558
|
+
}
|
|
559
|
+
else if (isObject(nextAssociationStatement) && previousAssociationName) {
|
|
560
|
+
const clonedNextAssociationStatement = cloneDeepSafe(nextAssociationStatement);
|
|
561
|
+
const keys = Object.keys(clonedNextAssociationStatement);
|
|
562
|
+
keys.forEach((key) => {
|
|
563
|
+
joinOnStatements[protectAgainstPollutingAssignment(key)] = clonedNextAssociationStatement[key];
|
|
564
|
+
});
|
|
565
|
+
this.fleshOutJoinStatements(innerJoinDreamClasses, joinStatements, joinOnStatements, previousAssociationName, associationStatements, previousDreamClass);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* @internal
|
|
570
|
+
*
|
|
571
|
+
*
|
|
572
|
+
*/
|
|
573
|
+
associationNamesToDreamClassesMap(associationNames, associationsToDreamClassesMap = {}) {
|
|
574
|
+
const namesToAssociationsAndDreamClasses = this.associationNamesToAssociationDataAndDreamClassesMap(associationNames);
|
|
575
|
+
return Object.keys(namesToAssociationsAndDreamClasses).reduce((remap, associationName) => {
|
|
576
|
+
remap[associationName] = namesToAssociationsAndDreamClasses[associationName].dreamClass;
|
|
577
|
+
return remap;
|
|
578
|
+
}, associationsToDreamClassesMap);
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* @internal
|
|
582
|
+
*
|
|
583
|
+
*
|
|
584
|
+
*/
|
|
585
|
+
associationNamesToAssociationsMap(associationNames, associationsToAssociations = {}) {
|
|
586
|
+
const namesToAssociationsAndDreamClasses = this.associationNamesToAssociationDataAndDreamClassesMap(associationNames);
|
|
587
|
+
return Object.keys(namesToAssociationsAndDreamClasses).reduce((remap, associationName) => {
|
|
588
|
+
remap[associationName] = namesToAssociationsAndDreamClasses[associationName].association;
|
|
589
|
+
return remap;
|
|
590
|
+
}, associationsToAssociations);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* @internal
|
|
594
|
+
*/
|
|
595
|
+
associationNamesToAssociationDataAndDreamClassesMap(associationNames) {
|
|
596
|
+
const associationsToDreamClassesMap = {};
|
|
597
|
+
associationNames.reduce((dreamClass, associationName) => {
|
|
598
|
+
const { name, alias } = extractAssociationMetadataFromAssociationName(associationName);
|
|
599
|
+
const association = dreamClass['getAssociationMetadata'](name);
|
|
600
|
+
const through = association.through;
|
|
601
|
+
if (through) {
|
|
602
|
+
const { throughAssociation, throughAssociationDreamClass } = this.throughAssociationDetails(dreamClass, through);
|
|
603
|
+
associationsToDreamClassesMap[through] = {
|
|
604
|
+
association: throughAssociation,
|
|
605
|
+
dreamClass: throughAssociationDreamClass,
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
const nextDreamClass = association.modelCB();
|
|
609
|
+
associationsToDreamClassesMap[alias] = { association, dreamClass: nextDreamClass };
|
|
610
|
+
return nextDreamClass;
|
|
611
|
+
}, this.dreamClass);
|
|
612
|
+
return associationsToDreamClassesMap;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* @internal
|
|
616
|
+
*/
|
|
617
|
+
throughAssociationDetails(dreamClass, through) {
|
|
618
|
+
const throughAssociation = dreamClass['getAssociationMetadata'](through);
|
|
619
|
+
const throughAssociationDreamClass = throughAssociation.modelCB();
|
|
620
|
+
return { throughAssociation, throughAssociationDreamClass };
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* @internal
|
|
624
|
+
*
|
|
625
|
+
*
|
|
626
|
+
*/
|
|
627
|
+
joinStatementsToDreamClassesMap(joinStatements) {
|
|
628
|
+
const associationsToDreamClassesMap = {};
|
|
629
|
+
objectPathsToArrays(joinStatements).forEach(associationChain => this.associationNamesToDreamClassesMap(associationChain, associationsToDreamClassesMap));
|
|
630
|
+
return associationsToDreamClassesMap;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* @internal
|
|
634
|
+
*
|
|
635
|
+
*
|
|
636
|
+
*/
|
|
637
|
+
joinStatementsToAssociationsMap(joinStatements) {
|
|
638
|
+
const associationsToAssociationsMap = {};
|
|
639
|
+
objectPathsToArrays(joinStatements).forEach(associationChain => this.associationNamesToAssociationsMap(associationChain, associationsToAssociationsMap));
|
|
640
|
+
return associationsToAssociationsMap;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* @internal
|
|
644
|
+
*
|
|
645
|
+
* Adds Dream class to temporary innerJoinDreamClasses array based on association name
|
|
646
|
+
*
|
|
647
|
+
*/
|
|
648
|
+
addAssociatedDreamClassToInnerJoinDreamClasses(previousDreamClass, associationName, innerJoinDreamClasses) {
|
|
649
|
+
if (!previousDreamClass)
|
|
650
|
+
return null;
|
|
651
|
+
const association = previousDreamClass['associationMetadataMap']()[associationName];
|
|
652
|
+
if (!association)
|
|
653
|
+
return null;
|
|
654
|
+
this.addThroughAssociatedDreamClassToInnerJoinDreamClasses(previousDreamClass, association, innerJoinDreamClasses);
|
|
655
|
+
const dreamClasses = [association.modelCB()].flat();
|
|
656
|
+
dreamClasses.forEach(dreamClass => innerJoinDreamClasses.push(dreamClass));
|
|
657
|
+
return dreamClasses[0];
|
|
658
|
+
}
|
|
659
|
+
addThroughAssociatedDreamClassToInnerJoinDreamClasses(dreamClass, _association, innerJoinDreamClasses) {
|
|
660
|
+
const association = _association;
|
|
661
|
+
const throughAssociationName = association.through;
|
|
662
|
+
if (!throughAssociationName)
|
|
663
|
+
return;
|
|
664
|
+
const throughAssociation = dreamClass['associationMetadataMap']()[throughAssociationName];
|
|
665
|
+
if (!throughAssociation)
|
|
666
|
+
return;
|
|
667
|
+
const throughDreamClass = [throughAssociation.modelCB()].flat()[0];
|
|
668
|
+
innerJoinDreamClasses.push(throughDreamClass);
|
|
669
|
+
this.addThroughAssociatedDreamClassToInnerJoinDreamClasses(dreamClass, throughAssociation, innerJoinDreamClasses);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* @internal
|
|
673
|
+
*
|
|
674
|
+
* Changes the base sql alias
|
|
675
|
+
*
|
|
676
|
+
*/
|
|
677
|
+
setBaseSQLAlias(baseSqlAlias) {
|
|
678
|
+
return this.clone({ baseSqlAlias });
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* @internal
|
|
682
|
+
*
|
|
683
|
+
* Association queries start from the table corresponding to an instance
|
|
684
|
+
* of a Dream and join the association. However, the Dream may have
|
|
685
|
+
* default scopes that would preclude finding that instance, so the
|
|
686
|
+
* Query that forms the base of an association query must be unscoped,
|
|
687
|
+
* but that unscoping should not carry through to other associations
|
|
688
|
+
* (thus the use of `removeAllDefaultScopesExceptOnAssociations` instead of
|
|
689
|
+
* `removeAllDefaultScopes`).
|
|
690
|
+
*
|
|
691
|
+
* The association that this query is loading leverages `joins`, and the
|
|
692
|
+
* joining code explicitly handles applying / omitting default scopes.
|
|
693
|
+
* We set `bypassAllDefaultScopesExceptOnAssociations: true` on this Query
|
|
694
|
+
* to let that code do its work. This keeps the implementation DRY and simpler
|
|
695
|
+
* (without `bypassAllDefaultScopesExceptOnAssociations`, the default scopes would
|
|
696
|
+
* be applied twice, and when the association attempts to remove a default
|
|
697
|
+
* association would be foiled because it would be applied outside of the context
|
|
698
|
+
* where the association is modifying the query).
|
|
699
|
+
*
|
|
700
|
+
*/
|
|
701
|
+
setAssociationQueryBase(baseSelectQuery) {
|
|
702
|
+
return this.clone({
|
|
703
|
+
baseSelectQuery: baseSelectQuery.removeAllDefaultScopesExceptOnAssociations(),
|
|
704
|
+
bypassAllDefaultScopesExceptOnAssociations: true,
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Prevents default scopes from applying when
|
|
709
|
+
* the Query is executed
|
|
710
|
+
*
|
|
711
|
+
* @returns A new Query which will prevent default scopes from applying
|
|
712
|
+
*/
|
|
713
|
+
removeAllDefaultScopes() {
|
|
714
|
+
return this.clone({
|
|
715
|
+
bypassAllDefaultScopes: true,
|
|
716
|
+
baseSelectQuery: this.baseSelectQuery?.removeAllDefaultScopes(),
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Prevents default scopes from applying when
|
|
721
|
+
* the Query is executed, but not when applying to associations
|
|
722
|
+
*
|
|
723
|
+
* @returns A new Query which will prevent default scopes from applying, but not when applying to asociations
|
|
724
|
+
*/
|
|
725
|
+
removeAllDefaultScopesExceptOnAssociations() {
|
|
726
|
+
return this.clone({
|
|
727
|
+
bypassAllDefaultScopesExceptOnAssociations: true,
|
|
728
|
+
baseSelectQuery: this.baseSelectQuery?.removeAllDefaultScopesExceptOnAssociations(),
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Prevents a specific default scope from applying when
|
|
733
|
+
* the Query is executed
|
|
734
|
+
*
|
|
735
|
+
* @returns A new Query which will prevent a specific default scope from applying
|
|
736
|
+
*/
|
|
737
|
+
removeDefaultScope(scopeName) {
|
|
738
|
+
return this.clone({
|
|
739
|
+
defaultScopesToBypass: [...this.defaultScopesToBypass, scopeName],
|
|
740
|
+
baseSelectQuery: this.baseSelectQuery?.removeDefaultScope(scopeName),
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Prevents a specific default scope from applying when
|
|
745
|
+
* the Query is executed, but not when applying to asociations
|
|
746
|
+
*
|
|
747
|
+
* @returns A new Query which will prevent a specific default scope from applying, but not when applying to asociations
|
|
748
|
+
*/
|
|
749
|
+
removeDefaultScopeExceptOnAssociations(scopeName) {
|
|
750
|
+
return this.clone({
|
|
751
|
+
defaultScopesToBypassExceptOnAssociations: [
|
|
752
|
+
...this.defaultScopesToBypassExceptOnAssociations,
|
|
753
|
+
scopeName,
|
|
754
|
+
],
|
|
755
|
+
baseSelectQuery: this.baseSelectQuery?.removeDefaultScopeExceptOnAssociations(scopeName),
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Sends data through for use as passthrough data
|
|
760
|
+
* for the associations that require it.
|
|
761
|
+
*
|
|
762
|
+
* ```ts
|
|
763
|
+
* class Post {
|
|
764
|
+
* @Deco.HasMany('LocalizedText')
|
|
765
|
+
* public localizedTexts: LocalizedText[]
|
|
766
|
+
*
|
|
767
|
+
* @Deco.HasOne('LocalizedText', {
|
|
768
|
+
* on: { locale: DreamConst.passthrough },
|
|
769
|
+
* })
|
|
770
|
+
* public currentLocalizedText: LocalizedText
|
|
771
|
+
* }
|
|
772
|
+
*
|
|
773
|
+
* await User.query().passthrough({ locale: 'es-ES' })
|
|
774
|
+
* .preload('posts', 'currentLocalizedText')
|
|
775
|
+
* .first()
|
|
776
|
+
* ```
|
|
777
|
+
*
|
|
778
|
+
* @param passthroughOnStatement - where statement used for associations that require passthrough data
|
|
779
|
+
* @returns A cloned Query with the passthrough data
|
|
780
|
+
*/
|
|
781
|
+
passthrough(passthroughOnStatement) {
|
|
782
|
+
return this.clone({ passthroughOnStatement: passthroughOnStatement });
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Applies a where statement to the Query instance
|
|
786
|
+
*
|
|
787
|
+
* ```ts
|
|
788
|
+
* await User.where({ email: 'how@yadoin' }).first()
|
|
789
|
+
* // User{email: 'how@yadoin'}
|
|
790
|
+
* ```
|
|
791
|
+
*
|
|
792
|
+
* @param whereStatement - Where statement to apply to the Query
|
|
793
|
+
* @returns A cloned Query with the where clause applied
|
|
794
|
+
*/
|
|
795
|
+
where(whereStatement) {
|
|
796
|
+
return this._where(whereStatement, 'where');
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Accepts a list of where statements, each of
|
|
800
|
+
* which is combined via `OR`
|
|
801
|
+
*
|
|
802
|
+
* ```ts
|
|
803
|
+
* await User.query().whereAny([{ email: 'how@yadoin' }, { name: 'fred' }]).first()
|
|
804
|
+
* // [User{email: 'how@yadoin'}, User{name: 'fred'}, User{name: 'fred'}]
|
|
805
|
+
* ```
|
|
806
|
+
*
|
|
807
|
+
* @param whereStatements - a list of where statements to `OR` together
|
|
808
|
+
* @returns A cloned Query with the whereAny clause applied
|
|
809
|
+
*/
|
|
810
|
+
whereAny(whereStatements) {
|
|
811
|
+
return this.clone({
|
|
812
|
+
or: whereStatements ? [whereStatements.map((obj) => ({ ...obj }))] : whereStatements,
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Applies a whereNot statement to the Query instance
|
|
817
|
+
*
|
|
818
|
+
* ```ts
|
|
819
|
+
* await User.query().whereNot({ email: 'how@yadoin' }).first()
|
|
820
|
+
* // User{email: 'hello@world'}
|
|
821
|
+
* ```
|
|
822
|
+
*
|
|
823
|
+
* @param whereStatement - A where statement to negate and apply to the Query
|
|
824
|
+
* @returns A cloned Query with the whereNot clause applied
|
|
825
|
+
*/
|
|
826
|
+
whereNot(whereStatement) {
|
|
827
|
+
return this._where(whereStatement, 'whereNot');
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* @internal
|
|
831
|
+
*
|
|
832
|
+
* Applies a where clause
|
|
833
|
+
*/
|
|
834
|
+
_where(whereStatement, typeOfWhere) {
|
|
835
|
+
return this.clone({
|
|
836
|
+
[typeOfWhere]: whereStatement === null ? null : [{ ...whereStatement }],
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Returns a new Kysely SelectQueryBuilder instance to be used
|
|
841
|
+
* in a sub Query
|
|
842
|
+
*
|
|
843
|
+
* ```ts
|
|
844
|
+
* const records = await User.where({
|
|
845
|
+
* id: Post.query().nestedSelect('userId'),
|
|
846
|
+
* }).all()
|
|
847
|
+
* // [User{id: 1}, ...]
|
|
848
|
+
* ```
|
|
849
|
+
*
|
|
850
|
+
* @param selection - the column to use for your nested Query
|
|
851
|
+
* @returns A Kysely SelectQueryBuilder instance
|
|
852
|
+
*/
|
|
853
|
+
nestedSelect(selection) {
|
|
854
|
+
const query = this.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
855
|
+
return query.select(this.namespaceColumn(selection));
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Returns a new Query instance, attaching the provided
|
|
859
|
+
* order statement
|
|
860
|
+
*
|
|
861
|
+
* ```ts
|
|
862
|
+
* await User.query().order('id').all()
|
|
863
|
+
* // [User{id: 1}, User{id: 2}, ...]
|
|
864
|
+
* ```
|
|
865
|
+
*
|
|
866
|
+
* ```ts
|
|
867
|
+
* await User.query().order({ name: 'asc', id: 'desc' }).all()
|
|
868
|
+
* // [User{name: 'a', id: 99}, User{name: 'a', id: 97}, User{ name: 'b', id: 98 } ...]
|
|
869
|
+
* ```
|
|
870
|
+
*
|
|
871
|
+
* @param orderStatement - Either a string or an object specifying order. If a string, the order is implicitly ascending. If the orderStatement is an object, statements will be provided in the order of the keys set in the object
|
|
872
|
+
* @returns A cloned Query with the order clause applied
|
|
873
|
+
*/
|
|
874
|
+
order(arg) {
|
|
875
|
+
if (arg === null)
|
|
876
|
+
return this.clone({ order: null });
|
|
877
|
+
if (isString(arg))
|
|
878
|
+
return this.clone({ order: [{ column: arg, direction: 'asc' }] });
|
|
879
|
+
let query = this.clone();
|
|
880
|
+
Object.keys(arg).forEach(key => {
|
|
881
|
+
const column = key;
|
|
882
|
+
const direction = arg[key];
|
|
883
|
+
query = query.clone({
|
|
884
|
+
order: [{ column: column, direction }],
|
|
885
|
+
});
|
|
886
|
+
});
|
|
887
|
+
return query;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Returns a new Query instance, specifying a limit
|
|
891
|
+
*
|
|
892
|
+
* ```ts
|
|
893
|
+
* await User.order('id').limit(2).all()
|
|
894
|
+
* // [User{id: 1}, User{id: 2}]
|
|
895
|
+
* ```
|
|
896
|
+
*
|
|
897
|
+
* @returns A cloned Query with the limit clause applied
|
|
898
|
+
*/
|
|
899
|
+
limit(limit) {
|
|
900
|
+
return this.clone({ limit });
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Returns a new Query instance, specifying an offset
|
|
904
|
+
*
|
|
905
|
+
* ```ts
|
|
906
|
+
* await User.order('id').offset(2).limit(2).all()
|
|
907
|
+
* // [User{id: 3}, User{id: 4}]
|
|
908
|
+
* ```
|
|
909
|
+
*
|
|
910
|
+
* @returns A cloned Query with the offset clause applied
|
|
911
|
+
*/
|
|
912
|
+
offset(offset) {
|
|
913
|
+
return this.clone({ offset });
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Returns the sql that would be executed by this Query
|
|
917
|
+
*
|
|
918
|
+
* ```ts
|
|
919
|
+
* User.where({ email: 'how@yadoin' }).sql()
|
|
920
|
+
* // {
|
|
921
|
+
* // query: {
|
|
922
|
+
* // kind: 'SelectQueryNode',
|
|
923
|
+
* // from: { kind: 'FromNode', froms: [Array] },
|
|
924
|
+
* // selections: [ [Object] ],
|
|
925
|
+
* // distinctOn: undefined,
|
|
926
|
+
* // joins: undefined,
|
|
927
|
+
* // groupBy: undefined,
|
|
928
|
+
* // orderBy: undefined,
|
|
929
|
+
* // where: { kind: 'WhereNode', where: [Object] },
|
|
930
|
+
* // frontModifiers: undefined,
|
|
931
|
+
* // endModifiers: undefined,
|
|
932
|
+
* // limit: undefined,
|
|
933
|
+
* // offset: undefined,
|
|
934
|
+
* // with: undefined,
|
|
935
|
+
* // having: undefined,
|
|
936
|
+
* // explain: undefined,
|
|
937
|
+
* // setOperations: undefined
|
|
938
|
+
* // },
|
|
939
|
+
* // sql: 'select "users".* from "users" where ("users"."email" = $1 and "users"."deleted_at" is null)',
|
|
940
|
+
* // parameters: [ 'how@yadoin' ]
|
|
941
|
+
* //}
|
|
942
|
+
* ```
|
|
943
|
+
*
|
|
944
|
+
* @returns An object representing the underlying sql statement
|
|
945
|
+
*
|
|
946
|
+
*/
|
|
947
|
+
sql() {
|
|
948
|
+
const kyselyQuery = this.buildSelect();
|
|
949
|
+
return kyselyQuery.compile();
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Converts the given dream class into a Kysely query, enabling
|
|
953
|
+
* you to build custom queries using the Kysely API
|
|
954
|
+
*
|
|
955
|
+
* ```ts
|
|
956
|
+
* await User.query().toKysely('select').where('email', '=', 'how@yadoin').execute()
|
|
957
|
+
* ```
|
|
958
|
+
*
|
|
959
|
+
* @param type - the type of Kysely query builder instance you would like to obtain
|
|
960
|
+
* @returns A Kysely query. Depending on the type passed, it will return either a SelectQueryBuilder, DeleteQueryBuilder, or an UpdateQueryBuilder
|
|
961
|
+
*/
|
|
962
|
+
toKysely(type) {
|
|
963
|
+
switch (type) {
|
|
964
|
+
case 'select':
|
|
965
|
+
return this.buildSelect();
|
|
966
|
+
case 'delete':
|
|
967
|
+
return this.buildDelete();
|
|
968
|
+
case 'update':
|
|
969
|
+
return this.buildUpdate({});
|
|
970
|
+
// TODO: in the future, we should support insert type, but don't yet, since inserts are done outside
|
|
971
|
+
// the query class for some reason.
|
|
972
|
+
default:
|
|
973
|
+
throw new Error('never');
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Applies transaction to the Query instance
|
|
978
|
+
*
|
|
979
|
+
* ```ts
|
|
980
|
+
* await ApplicationModel.transaction(async txn => {
|
|
981
|
+
* await User.query().txn(txn).create({ email: 'how@yadoin' })
|
|
982
|
+
* })
|
|
983
|
+
* ```
|
|
984
|
+
*
|
|
985
|
+
* @param txn - A DreamTransaction instance (usually collected by calling `ApplicationModel.transaction`)
|
|
986
|
+
* @returns A cloned Query with the transaction applied
|
|
987
|
+
*
|
|
988
|
+
*/
|
|
989
|
+
txn(dreamTransaction) {
|
|
990
|
+
return this.clone({ transaction: dreamTransaction });
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Retrieves the number of records in the database
|
|
994
|
+
*
|
|
995
|
+
* ```ts
|
|
996
|
+
* await User.query().count()
|
|
997
|
+
* ```
|
|
998
|
+
*
|
|
999
|
+
* @returns The number of records in the database
|
|
1000
|
+
*/
|
|
1001
|
+
async count() {
|
|
1002
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
1003
|
+
const { count } = this.dbFor('select').fn;
|
|
1004
|
+
const distinctColumn = this.distinctColumn;
|
|
1005
|
+
const query = this.clone({ distinctColumn: null });
|
|
1006
|
+
let kyselyQuery = query.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
1007
|
+
const countClause = distinctColumn
|
|
1008
|
+
? count(sql `DISTINCT ${distinctColumn}`)
|
|
1009
|
+
: count(query.namespaceColumn(query.dreamInstance.primaryKey));
|
|
1010
|
+
kyselyQuery = kyselyQuery.select(countClause.as('tablecount'));
|
|
1011
|
+
const data = await executeDatabaseQuery(kyselyQuery, 'executeTakeFirstOrThrow');
|
|
1012
|
+
return parseInt(data.tablecount.toString());
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Returns new Query with distinct clause applied
|
|
1016
|
+
*
|
|
1017
|
+
* ```ts
|
|
1018
|
+
* await User.query().distinct('name').pluck('name')
|
|
1019
|
+
* ```
|
|
1020
|
+
*
|
|
1021
|
+
* @returns A cloned Query with the distinct clause applied
|
|
1022
|
+
*/
|
|
1023
|
+
distinct(column = true) {
|
|
1024
|
+
if (column === true) {
|
|
1025
|
+
return this.clone({
|
|
1026
|
+
distinctColumn: this.namespaceColumn(this.dreamInstance.primaryKey),
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
else if (column === false) {
|
|
1030
|
+
return this.clone({ distinctColumn: null });
|
|
1031
|
+
}
|
|
1032
|
+
else {
|
|
1033
|
+
return this.clone({ distinctColumn: this.namespaceColumn(column) });
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* @internal
|
|
1038
|
+
*
|
|
1039
|
+
* Returns a namespaced column name
|
|
1040
|
+
*
|
|
1041
|
+
* @returns A string
|
|
1042
|
+
*/
|
|
1043
|
+
namespaceColumn(column, alias = this.baseSqlAlias) {
|
|
1044
|
+
return namespaceColumn(column, alias);
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Retrieves the max value of the specified column
|
|
1048
|
+
* for this Query
|
|
1049
|
+
*
|
|
1050
|
+
* ```ts
|
|
1051
|
+
* await User.query().max('id')
|
|
1052
|
+
* // 99
|
|
1053
|
+
* ```
|
|
1054
|
+
*
|
|
1055
|
+
* @param columnName - a column name on the model
|
|
1056
|
+
* @returns the max value of the specified column for this Query
|
|
1057
|
+
*
|
|
1058
|
+
*/
|
|
1059
|
+
async max(columnName) {
|
|
1060
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
1061
|
+
const { max } = this.dbFor('select').fn;
|
|
1062
|
+
let kyselyQuery = this.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
1063
|
+
kyselyQuery = kyselyQuery.select(max(columnName));
|
|
1064
|
+
const data = await executeDatabaseQuery(kyselyQuery, 'executeTakeFirstOrThrow');
|
|
1065
|
+
return data.max;
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Retrieves the min value of the specified column
|
|
1069
|
+
* for this Query
|
|
1070
|
+
*
|
|
1071
|
+
* ```ts
|
|
1072
|
+
* await User.query().min('id')
|
|
1073
|
+
* // 1
|
|
1074
|
+
* ```
|
|
1075
|
+
*
|
|
1076
|
+
* @param columnName - a column name on the model
|
|
1077
|
+
* @returns the min value of the specified column for this Query
|
|
1078
|
+
*/
|
|
1079
|
+
async min(columnName) {
|
|
1080
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
1081
|
+
const { min } = this.dbFor('select').fn;
|
|
1082
|
+
let kyselyQuery = this.buildSelect({ bypassSelectAll: true, bypassOrder: true });
|
|
1083
|
+
kyselyQuery = kyselyQuery.select(min(columnName));
|
|
1084
|
+
const data = await executeDatabaseQuery(kyselyQuery, 'executeTakeFirstOrThrow');
|
|
1085
|
+
return data.min;
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* @internal
|
|
1089
|
+
*
|
|
1090
|
+
* Runs the query and extracts plucked values
|
|
1091
|
+
*
|
|
1092
|
+
* @returns An array of plucked values
|
|
1093
|
+
*/
|
|
1094
|
+
async executePluck(...fields) {
|
|
1095
|
+
let kyselyQuery = this.removeAllDefaultScopesExceptOnAssociations().buildSelect({ bypassSelectAll: true });
|
|
1096
|
+
const aliases = [];
|
|
1097
|
+
fields.forEach((field) => {
|
|
1098
|
+
// field will already be namespaced in a join situation, but when the field to pluck is on the
|
|
1099
|
+
// base model, it will be underscored (to match the table name), but when the selected column
|
|
1100
|
+
// comes back from Kysely camelCased
|
|
1101
|
+
aliases.push(field.includes('_') ? camelize(field) : field);
|
|
1102
|
+
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(field)} as ${field}`);
|
|
1103
|
+
});
|
|
1104
|
+
return (await executeDatabaseQuery(kyselyQuery, 'execute')).map(singleResult => aliases.map(alias => singleResult[alias]));
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* @internal
|
|
1108
|
+
*
|
|
1109
|
+
*/
|
|
1110
|
+
async executeJoinLoad(options = {}) {
|
|
1111
|
+
const query = this.limit(null).offset(null);
|
|
1112
|
+
let kyselyQuery = query.buildSelect({ bypassSelectAll: true });
|
|
1113
|
+
const aliasToDreamClassesMap = {
|
|
1114
|
+
[this.baseSqlAlias]: this.dreamClass,
|
|
1115
|
+
...this.joinStatementsToDreamClassesMap(this.leftJoinStatements),
|
|
1116
|
+
};
|
|
1117
|
+
const associationAliasToColumnAliasMap = {};
|
|
1118
|
+
const aliasToAssociationsMap = this.joinStatementsToAssociationsMap(this.leftJoinStatements);
|
|
1119
|
+
const aliases = Object.keys(aliasToDreamClassesMap);
|
|
1120
|
+
let nextColumnAliasCounter = 0;
|
|
1121
|
+
aliases.forEach((aliasOrExpression) => {
|
|
1122
|
+
const alias = extractAssociationMetadataFromAssociationName(aliasOrExpression).alias;
|
|
1123
|
+
associationAliasToColumnAliasMap[alias] ||= {};
|
|
1124
|
+
const aliasedDreamClass = aliasToDreamClassesMap[alias];
|
|
1125
|
+
const association = aliasToAssociationsMap[alias];
|
|
1126
|
+
const columns = alias === this.baseSqlAlias
|
|
1127
|
+
? options.columns
|
|
1128
|
+
? this.columnsWithRequiredLoadColumns(options.columns)
|
|
1129
|
+
: this.dreamClass.columns()
|
|
1130
|
+
: aliasedDreamClass.columns();
|
|
1131
|
+
columns.forEach((column) => {
|
|
1132
|
+
const columnAlias = `dr${nextColumnAliasCounter++}`;
|
|
1133
|
+
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(column, alias)} as ${columnAlias}`);
|
|
1134
|
+
associationAliasToColumnAliasMap[alias][column] = columnAlias;
|
|
1135
|
+
});
|
|
1136
|
+
if (association?.type === 'HasOne' || association?.type === 'HasMany') {
|
|
1137
|
+
const setupPreloadData = (dbColumnName) => {
|
|
1138
|
+
const columnAlias = `dr${nextColumnAliasCounter++}`;
|
|
1139
|
+
associationAliasToColumnAliasMap[association.through][dbColumnName] = columnAlias;
|
|
1140
|
+
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(dbColumnName, association.through)} as ${columnAlias}`);
|
|
1141
|
+
};
|
|
1142
|
+
if (association.through && association.preloadThroughColumns) {
|
|
1143
|
+
if (isObject(association.preloadThroughColumns)) {
|
|
1144
|
+
const preloadMap = association.preloadThroughColumns;
|
|
1145
|
+
Object.keys(preloadMap).forEach(columnName => setupPreloadData(columnName));
|
|
1146
|
+
}
|
|
1147
|
+
else {
|
|
1148
|
+
const preloadArray = association.preloadThroughColumns;
|
|
1149
|
+
preloadArray.forEach(columnName => setupPreloadData(columnName));
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
const queryResults = await executeDatabaseQuery(kyselyQuery, 'execute');
|
|
1155
|
+
const aliasToDreamIdMap = queryResults.reduce((aliasToDreamIdMap, singleSqlResult) => {
|
|
1156
|
+
this.fleshOutJoinLoadExecutionResults({
|
|
1157
|
+
currentAlias: this.baseSqlAlias,
|
|
1158
|
+
singleSqlResult,
|
|
1159
|
+
aliasToDreamIdMap,
|
|
1160
|
+
associationAliasToColumnAliasMap,
|
|
1161
|
+
aliasToAssociationsMap,
|
|
1162
|
+
aliasToDreamClassesMap,
|
|
1163
|
+
leftJoinStatements: this.leftJoinStatements,
|
|
1164
|
+
});
|
|
1165
|
+
return aliasToDreamIdMap;
|
|
1166
|
+
}, {});
|
|
1167
|
+
const baseModelIdToDreamMap = aliasToDreamIdMap[this.baseSqlAlias] || new Map();
|
|
1168
|
+
return compact(Array.from(baseModelIdToDreamMap.values()));
|
|
1169
|
+
}
|
|
1170
|
+
fleshOutJoinLoadExecutionResults({ currentAlias, singleSqlResult, aliasToDreamIdMap, associationAliasToColumnAliasMap, aliasToAssociationsMap, aliasToDreamClassesMap, leftJoinStatements, }) {
|
|
1171
|
+
const dreamClass = aliasToDreamClassesMap[currentAlias];
|
|
1172
|
+
const columnToColumnAliasMap = associationAliasToColumnAliasMap[currentAlias];
|
|
1173
|
+
const primaryKeyValue = singleSqlResult[columnToColumnAliasMap[dreamClass.primaryKey]];
|
|
1174
|
+
if (!primaryKeyValue)
|
|
1175
|
+
return null;
|
|
1176
|
+
aliasToDreamIdMap[currentAlias] ||= new Map();
|
|
1177
|
+
if (!aliasToDreamIdMap[currentAlias].get(primaryKeyValue)) {
|
|
1178
|
+
const columnValueMap = Object.keys(columnToColumnAliasMap).reduce((columnNameValueMap, columnName) => {
|
|
1179
|
+
columnNameValueMap[columnName] = singleSqlResult[columnToColumnAliasMap[columnName]];
|
|
1180
|
+
return columnNameValueMap;
|
|
1181
|
+
}, {});
|
|
1182
|
+
const dream = sqlResultToDreamInstance(dreamClass, columnValueMap);
|
|
1183
|
+
const association = aliasToAssociationsMap[currentAlias];
|
|
1184
|
+
if (association && association.through && association.preloadThroughColumns) {
|
|
1185
|
+
const throughAssociationColumnToColumnAliasMap = associationAliasToColumnAliasMap[association.through];
|
|
1186
|
+
this.hydratePreloadedThroughColumns({
|
|
1187
|
+
association,
|
|
1188
|
+
columnToColumnAliasMap: throughAssociationColumnToColumnAliasMap,
|
|
1189
|
+
dream,
|
|
1190
|
+
singleSqlResult,
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
aliasToDreamIdMap[protectAgainstPollutingAssignment(currentAlias)].set(primaryKeyValue, dream);
|
|
1194
|
+
}
|
|
1195
|
+
const dream = aliasToDreamIdMap[currentAlias].get(primaryKeyValue);
|
|
1196
|
+
Object.keys(leftJoinStatements).forEach(nextAlias => {
|
|
1197
|
+
const { name: associationName, alias } = extractAssociationMetadataFromAssociationName(nextAlias);
|
|
1198
|
+
const association = dreamClass['getAssociationMetadata'](associationName);
|
|
1199
|
+
const associatedDream = this.fleshOutJoinLoadExecutionResults({
|
|
1200
|
+
currentAlias: alias,
|
|
1201
|
+
singleSqlResult,
|
|
1202
|
+
aliasToDreamIdMap,
|
|
1203
|
+
associationAliasToColumnAliasMap,
|
|
1204
|
+
aliasToAssociationsMap,
|
|
1205
|
+
aliasToDreamClassesMap,
|
|
1206
|
+
leftJoinStatements: leftJoinStatements[nextAlias],
|
|
1207
|
+
});
|
|
1208
|
+
const hasMany = association.type === 'HasMany';
|
|
1209
|
+
// initialize by trying to access the association, which throws an exception if not yet initialized
|
|
1210
|
+
try {
|
|
1211
|
+
;
|
|
1212
|
+
dream[association.as];
|
|
1213
|
+
}
|
|
1214
|
+
catch {
|
|
1215
|
+
if (hasMany)
|
|
1216
|
+
dream[association.as] = [];
|
|
1217
|
+
else
|
|
1218
|
+
dream[associationToGetterSetterProp(association)] = null;
|
|
1219
|
+
}
|
|
1220
|
+
if (!associatedDream)
|
|
1221
|
+
return;
|
|
1222
|
+
if (hasMany) {
|
|
1223
|
+
if (!dream[association.as].includes(associatedDream))
|
|
1224
|
+
dream[association.as].push(associatedDream);
|
|
1225
|
+
}
|
|
1226
|
+
else
|
|
1227
|
+
dream[associationToGetterSetterProp(association)] = associatedDream;
|
|
1228
|
+
});
|
|
1229
|
+
return dream;
|
|
1230
|
+
}
|
|
1231
|
+
hydratePreloadedThroughColumns({ association, columnToColumnAliasMap, dream, singleSqlResult, }) {
|
|
1232
|
+
if (!association.through)
|
|
1233
|
+
return;
|
|
1234
|
+
if (!dream.preloadedThroughColumns)
|
|
1235
|
+
return;
|
|
1236
|
+
let columnNames = [];
|
|
1237
|
+
const columnNameToPreloadedThroughColumnNameMap = {};
|
|
1238
|
+
if (isObject(association.preloadThroughColumns)) {
|
|
1239
|
+
const preloadMap = association.preloadThroughColumns;
|
|
1240
|
+
columnNames = Object.keys(preloadMap).map(columnName => {
|
|
1241
|
+
columnNameToPreloadedThroughColumnNameMap[columnName] = preloadMap[columnName];
|
|
1242
|
+
return columnName;
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
else if (Array.isArray(association.preloadThroughColumns)) {
|
|
1246
|
+
columnNames = association.preloadThroughColumns.map(columnName => {
|
|
1247
|
+
columnNameToPreloadedThroughColumnNameMap[columnName] = columnName;
|
|
1248
|
+
return columnName;
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
columnNames.forEach(columnName => (dream.preloadedThroughColumns[columnNameToPreloadedThroughColumnNameMap[columnName]] =
|
|
1252
|
+
singleSqlResult[columnToColumnAliasMap[columnName]]));
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Plucks the provided fields from the given dream class table
|
|
1256
|
+
*
|
|
1257
|
+
* ```ts
|
|
1258
|
+
* await User.order('id').pluck('id')
|
|
1259
|
+
* // [1, 2, 3]
|
|
1260
|
+
* ```
|
|
1261
|
+
*
|
|
1262
|
+
* If more than one column is requested, a multi-dimensional
|
|
1263
|
+
* array is returned:
|
|
1264
|
+
*
|
|
1265
|
+
* ```ts
|
|
1266
|
+
* await User.order('id').pluck('id', 'email')
|
|
1267
|
+
* // [[1, 'a@a.com'], [2, 'b@b.com']]
|
|
1268
|
+
* ```
|
|
1269
|
+
*
|
|
1270
|
+
* @param columnNames - The column or array of columns to pluck
|
|
1271
|
+
* @returns An array of pluck results
|
|
1272
|
+
*/
|
|
1273
|
+
async pluck(...columnNames) {
|
|
1274
|
+
const vals = await this.executePluck(...columnNames);
|
|
1275
|
+
return (columnNames.length > 1 ? vals : vals.flat());
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Plucks the specified column names from the given dream class table
|
|
1279
|
+
* in batches, passing each found columns into the
|
|
1280
|
+
* provided callback function
|
|
1281
|
+
*
|
|
1282
|
+
* ```ts
|
|
1283
|
+
* await User.order('id').pluckEach('id', (id) => {
|
|
1284
|
+
* console.log(id)
|
|
1285
|
+
* })
|
|
1286
|
+
* // 1
|
|
1287
|
+
* // 2
|
|
1288
|
+
* // 3
|
|
1289
|
+
* ```
|
|
1290
|
+
*
|
|
1291
|
+
* @param args - a list of column names to pluck, followed by a callback function to call for each set of found fields
|
|
1292
|
+
* @returns void
|
|
1293
|
+
*/
|
|
1294
|
+
async pluckEach(...args) {
|
|
1295
|
+
const providedCbIndex = args.findIndex(v => typeof v === 'function');
|
|
1296
|
+
const providedCb = args[providedCbIndex];
|
|
1297
|
+
const providedOpts = args[providedCbIndex + 1];
|
|
1298
|
+
if (!providedCb)
|
|
1299
|
+
throw new MissingRequiredCallbackFunctionToPluckEach('pluckEach', args);
|
|
1300
|
+
if (providedOpts !== undefined && !providedOpts?.batchSize)
|
|
1301
|
+
throw new CannotPassAdditionalFieldsToPluckEachAfterCallback('pluckEach', args);
|
|
1302
|
+
const onlyColumns = args.filter((_, index) => index < providedCbIndex);
|
|
1303
|
+
const batchSize = providedOpts?.batchSize || Query.BATCH_SIZES.PLUCK_EACH_THROUGH;
|
|
1304
|
+
let offset = 0;
|
|
1305
|
+
let records;
|
|
1306
|
+
do {
|
|
1307
|
+
const onlyIncludesPrimaryKey = onlyColumns.find(column => column === this.dreamClass.primaryKey || column === this.namespacedPrimaryKey);
|
|
1308
|
+
const columnsIncludingPrimaryKey = onlyIncludesPrimaryKey
|
|
1309
|
+
? onlyColumns
|
|
1310
|
+
: [this.namespacedPrimaryKey, ...onlyColumns];
|
|
1311
|
+
records = await this.offset(offset)
|
|
1312
|
+
.order(null)
|
|
1313
|
+
.order(this.namespacedPrimaryKey)
|
|
1314
|
+
.limit(batchSize)
|
|
1315
|
+
.executePluck(...columnsIncludingPrimaryKey);
|
|
1316
|
+
// In order to batch, we need to order by primary key, so the primary key must be plucked.
|
|
1317
|
+
// If the developer did not include the primary key in the columns to pluck, then we prepended it above
|
|
1318
|
+
// and need to remove it from each group of plucked columns prior to passing them into the callback functions
|
|
1319
|
+
const vals = onlyIncludesPrimaryKey ? records : records.map(valueArr => valueArr.slice(1));
|
|
1320
|
+
for (const val of vals) {
|
|
1321
|
+
await providedCb(...val);
|
|
1322
|
+
}
|
|
1323
|
+
offset += batchSize;
|
|
1324
|
+
} while (records.length > 0 && records.length === batchSize);
|
|
1325
|
+
}
|
|
1326
|
+
/**
|
|
1327
|
+
* Retrieves an array containing all records matching the Query.
|
|
1328
|
+
* Be careful using this, since it will attempt to pull every
|
|
1329
|
+
* record into memory at once. When querying might return a large
|
|
1330
|
+
* number of records, consider using `.findEach`, which will pull
|
|
1331
|
+
* the records in batches.
|
|
1332
|
+
*
|
|
1333
|
+
* ```ts
|
|
1334
|
+
* await User.query().all()
|
|
1335
|
+
* ```
|
|
1336
|
+
*
|
|
1337
|
+
* @returns an array of dreams
|
|
1338
|
+
*/
|
|
1339
|
+
async all(options = {}) {
|
|
1340
|
+
if (this.joinLoadActivated)
|
|
1341
|
+
return await this.executeJoinLoad(options);
|
|
1342
|
+
const kyselyQuery = this.buildSelect(options);
|
|
1343
|
+
const results = await executeDatabaseQuery(kyselyQuery, 'execute');
|
|
1344
|
+
const theAll = results.map(r => sqlResultToDreamInstance(this.dreamClass, r));
|
|
1345
|
+
await this.applyPreload(this.preloadStatements, this.preloadOnStatements, theAll);
|
|
1346
|
+
return theAll;
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Forces use of a database connection (e.g. 'primary') during the query.
|
|
1350
|
+
*
|
|
1351
|
+
* NOTE: all queries within a transaction always use the 'primary' replica, so
|
|
1352
|
+
* explicitly setting connection within a transaction has no effect.
|
|
1353
|
+
*
|
|
1354
|
+
* @param connection - The connection you wish to access ('primary' or 'replica')
|
|
1355
|
+
* @returns A Query with the requested connection
|
|
1356
|
+
*/
|
|
1357
|
+
connection(connection) {
|
|
1358
|
+
return this._connection(connection);
|
|
1359
|
+
}
|
|
1360
|
+
_connection(connection) {
|
|
1361
|
+
if (!connection)
|
|
1362
|
+
return this;
|
|
1363
|
+
return this.clone({ connection });
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Returns true if a record exists for the given
|
|
1367
|
+
* Query
|
|
1368
|
+
*
|
|
1369
|
+
* ```ts
|
|
1370
|
+
* await User.query().exists()
|
|
1371
|
+
* // false
|
|
1372
|
+
*
|
|
1373
|
+
* await User.create({ email: 'how@yadoin' })
|
|
1374
|
+
*
|
|
1375
|
+
* await User.query().exists()
|
|
1376
|
+
* // true
|
|
1377
|
+
* ```
|
|
1378
|
+
*
|
|
1379
|
+
* @returns boolean
|
|
1380
|
+
*/
|
|
1381
|
+
async exists() {
|
|
1382
|
+
// Implementing via `limit(1).all()`, rather than the simpler `!!(await this.first())`
|
|
1383
|
+
// because it avoids the step of finding the first. Just find any, and return
|
|
1384
|
+
// that one.
|
|
1385
|
+
return (await this.limit(1).all()).length > 0;
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Returns the first record in the database
|
|
1389
|
+
* matching the Query. If the Query is not
|
|
1390
|
+
* ordered, it will automatically order
|
|
1391
|
+
* by primary key.
|
|
1392
|
+
*
|
|
1393
|
+
* ```ts
|
|
1394
|
+
* await User.query().first()
|
|
1395
|
+
* // User{id: 1}
|
|
1396
|
+
* ```
|
|
1397
|
+
*
|
|
1398
|
+
* @returns First record in the database, or null if no record exists
|
|
1399
|
+
*/
|
|
1400
|
+
async first() {
|
|
1401
|
+
const query = this.orderStatements.length
|
|
1402
|
+
? this
|
|
1403
|
+
: this.order({ [this.namespacedPrimaryKey]: 'asc' });
|
|
1404
|
+
return await query.takeOne();
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Returns the first record in the database
|
|
1408
|
+
* matching the Query. If the Query is not
|
|
1409
|
+
* ordered, it will automatically order
|
|
1410
|
+
* by primary key. If no record is found,
|
|
1411
|
+
* an exception is raised.
|
|
1412
|
+
*
|
|
1413
|
+
* ```ts
|
|
1414
|
+
* await User.query().first()
|
|
1415
|
+
* // User{id: 1}
|
|
1416
|
+
* ```
|
|
1417
|
+
*
|
|
1418
|
+
* @returns First record in the database, or null if no record exists
|
|
1419
|
+
*/
|
|
1420
|
+
async firstOrFail() {
|
|
1421
|
+
const record = await this.first();
|
|
1422
|
+
if (!record)
|
|
1423
|
+
throw new RecordNotFound(this.dreamInstance.constructor.name);
|
|
1424
|
+
return record;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Returns the last record in the database
|
|
1428
|
+
* matching the Query. If the Query is not
|
|
1429
|
+
* ordered, it will automatically order
|
|
1430
|
+
* by primary key.
|
|
1431
|
+
*
|
|
1432
|
+
* ```ts
|
|
1433
|
+
* await User.query().last()
|
|
1434
|
+
* // User{id: 99}
|
|
1435
|
+
* ```
|
|
1436
|
+
*
|
|
1437
|
+
* @returns Last record in the database, or null if no record exists
|
|
1438
|
+
*/
|
|
1439
|
+
async last() {
|
|
1440
|
+
const query = this.orderStatements.length
|
|
1441
|
+
? this.invertOrder()
|
|
1442
|
+
: this.order({ [this.namespacedPrimaryKey]: 'desc' });
|
|
1443
|
+
return await query.takeOne();
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* Returns the last record in the database
|
|
1447
|
+
* matching the Query. If the Query is not
|
|
1448
|
+
* ordered, it will automatically order
|
|
1449
|
+
* by primary key. If no record is found,
|
|
1450
|
+
* it will raise an exception.
|
|
1451
|
+
*
|
|
1452
|
+
* ```ts
|
|
1453
|
+
* await User.where(...).lastOrFail()
|
|
1454
|
+
* // User{id: 99}
|
|
1455
|
+
* ```
|
|
1456
|
+
*
|
|
1457
|
+
* @returns Last record in the database, or null if no record exists
|
|
1458
|
+
*/
|
|
1459
|
+
async lastOrFail() {
|
|
1460
|
+
const record = await this.last();
|
|
1461
|
+
if (!record)
|
|
1462
|
+
throw new RecordNotFound(this.dreamInstance.constructor.name);
|
|
1463
|
+
return record;
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* Destroys all records matching the Query,
|
|
1467
|
+
* calling model hooks and cascading destroy
|
|
1468
|
+
* to associations with `dependent: 'destroy'`,
|
|
1469
|
+
* and returns the number of records that
|
|
1470
|
+
* were destroyed.
|
|
1471
|
+
*
|
|
1472
|
+
* To delete in a single database query,
|
|
1473
|
+
* ignoring model hooks and association
|
|
1474
|
+
* dependent-destroy declarations, use
|
|
1475
|
+
* {@link Query.delete | delete} instead.
|
|
1476
|
+
*
|
|
1477
|
+
* ```ts
|
|
1478
|
+
* await User.where({ email: ops.ilike('%burpcollaborator%') }).destroy()
|
|
1479
|
+
* // 12
|
|
1480
|
+
* ```
|
|
1481
|
+
*
|
|
1482
|
+
* @param options - Options for destroying the instance
|
|
1483
|
+
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
1484
|
+
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
1485
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses all default scopes when cascade destroying. Defaults to false
|
|
1486
|
+
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
1487
|
+
* @returns The number of records that were removed
|
|
1488
|
+
*/
|
|
1489
|
+
async destroy({ skipHooks, cascade, } = {}) {
|
|
1490
|
+
let counter = 0;
|
|
1491
|
+
const options = {
|
|
1492
|
+
bypassAllDefaultScopes: this.bypassAllDefaultScopes,
|
|
1493
|
+
defaultScopesToBypass: this.defaultScopesToBypass,
|
|
1494
|
+
skipHooks,
|
|
1495
|
+
cascade,
|
|
1496
|
+
};
|
|
1497
|
+
await this.findEach(async (result) => {
|
|
1498
|
+
const subquery = this.dreamTransaction
|
|
1499
|
+
? result.txn(this.dreamTransaction)
|
|
1500
|
+
: result;
|
|
1501
|
+
if (this.shouldReallyDestroy) {
|
|
1502
|
+
await subquery.reallyDestroy(options);
|
|
1503
|
+
}
|
|
1504
|
+
else {
|
|
1505
|
+
await subquery.destroy(options);
|
|
1506
|
+
}
|
|
1507
|
+
counter++;
|
|
1508
|
+
});
|
|
1509
|
+
return counter;
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Destroys all records matching the Query,
|
|
1513
|
+
* ignoring the SoftDelete decorator and
|
|
1514
|
+
* permanently removing records from the database.
|
|
1515
|
+
*
|
|
1516
|
+
* Calls model hooks and applies cascade destroy
|
|
1517
|
+
* to associations with `dependent: 'destroy'`,
|
|
1518
|
+
* returning the number of records that
|
|
1519
|
+
* were destroyed.
|
|
1520
|
+
*
|
|
1521
|
+
* To destroy without bypassing the SoftDelete
|
|
1522
|
+
* decorator, use {@link Query.(destroy:instance) | destroy} instead.
|
|
1523
|
+
*
|
|
1524
|
+
* ```ts
|
|
1525
|
+
* await User.where({ email: ops.ilike('%burpcollaborator%') }).reallyDestroy()
|
|
1526
|
+
* // 12
|
|
1527
|
+
* ```
|
|
1528
|
+
*
|
|
1529
|
+
* @param options - Options for destroying the instance
|
|
1530
|
+
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
1531
|
+
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
1532
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses all default scopes when cascade destroying. Defaults to false
|
|
1533
|
+
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
1534
|
+
* @returns The number of records that were removed
|
|
1535
|
+
*/
|
|
1536
|
+
async reallyDestroy({ skipHooks, cascade, } = {}) {
|
|
1537
|
+
return await this.clone({ shouldReallyDestroy: true }).destroy({ skipHooks, cascade });
|
|
1538
|
+
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Undestroys a SoftDelete model, unsetting
|
|
1541
|
+
* the `deletedAt` field in the database.
|
|
1542
|
+
*
|
|
1543
|
+
* If the model is not a SoftDelete model,
|
|
1544
|
+
* this will raise an exception.
|
|
1545
|
+
*
|
|
1546
|
+
* ```ts
|
|
1547
|
+
* await User.where({ email: ops.ilike('%burpcollaborator%') }).undestroy()
|
|
1548
|
+
* // 12
|
|
1549
|
+
* ```
|
|
1550
|
+
*
|
|
1551
|
+
* @param options - Options for undestroying the instance
|
|
1552
|
+
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
1553
|
+
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
1554
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses all default scopes when cascade undestroying. Defaults to false
|
|
1555
|
+
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade undestroying (soft delete is always bypassed). Defaults to an empty array
|
|
1556
|
+
* @returns The number of records that were removed
|
|
1557
|
+
*/
|
|
1558
|
+
async undestroy({ cascade, skipHooks, } = {}) {
|
|
1559
|
+
if (!this.dreamClass['softDelete'])
|
|
1560
|
+
throw new CannotCallUndestroyOnANonSoftDeleteModel(this.dreamClass);
|
|
1561
|
+
let counter = 0;
|
|
1562
|
+
await this.removeDefaultScope(SOFT_DELETE_SCOPE_NAME).findEach(async (result) => {
|
|
1563
|
+
const subquery = this.dreamTransaction
|
|
1564
|
+
? result.txn(this.dreamTransaction)
|
|
1565
|
+
: result;
|
|
1566
|
+
await subquery.undestroy({
|
|
1567
|
+
bypassAllDefaultScopes: this.bypassAllDefaultScopes,
|
|
1568
|
+
defaultScopesToBypass: this.defaultScopesToBypass,
|
|
1569
|
+
cascade,
|
|
1570
|
+
skipHooks,
|
|
1571
|
+
});
|
|
1572
|
+
counter++;
|
|
1573
|
+
});
|
|
1574
|
+
return counter;
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Deletes all records matching query using a single
|
|
1578
|
+
* database query, but does not call underlying callbacks.
|
|
1579
|
+
* Ignores association dependent destroy declarations,
|
|
1580
|
+
* though cascading may still happen at the database level.
|
|
1581
|
+
*
|
|
1582
|
+
* To apply model hooks and association dependent destroy,
|
|
1583
|
+
* use {@link Query.(destroy:instance) | destroy} instead.
|
|
1584
|
+
*
|
|
1585
|
+
* ```ts
|
|
1586
|
+
* await User.where({ email: ops.ilike('%burpcollaborator%').delete() })
|
|
1587
|
+
* // 12
|
|
1588
|
+
* ```
|
|
1589
|
+
*
|
|
1590
|
+
* @returns The number of records that were removed
|
|
1591
|
+
*/
|
|
1592
|
+
async delete() {
|
|
1593
|
+
const deletionResult = await executeDatabaseQuery(this.buildDelete(), 'executeTakeFirst');
|
|
1594
|
+
return Number(deletionResult?.numDeletedRows || 0);
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Updates all records matching the Query
|
|
1598
|
+
*
|
|
1599
|
+
* ```ts
|
|
1600
|
+
* await User.where({ email: ops.ilike('%burpcollaborator%') }).updateAll({ email: null })
|
|
1601
|
+
* // 12
|
|
1602
|
+
* ```
|
|
1603
|
+
* @param attributes - The attributes used to update the records
|
|
1604
|
+
* @param options - Options for updating the instance
|
|
1605
|
+
* @param options.skipHooks - If true, skips applying model hooks. Defaults to false
|
|
1606
|
+
* @returns The number of records that were updated
|
|
1607
|
+
*/
|
|
1608
|
+
async update(attributes, { skipHooks } = {}) {
|
|
1609
|
+
if (this.baseSelectQuery)
|
|
1610
|
+
throw new NoUpdateOnAssociationQuery();
|
|
1611
|
+
if (Object.keys(this.innerJoinStatements).length)
|
|
1612
|
+
throw new NoUpdateAllOnJoins();
|
|
1613
|
+
if (Object.keys(this.leftJoinStatements).length)
|
|
1614
|
+
throw new NoUpdateAllOnJoins();
|
|
1615
|
+
if (skipHooks)
|
|
1616
|
+
return await this.updateWithoutCallingModelHooks(attributes);
|
|
1617
|
+
let counter = 0;
|
|
1618
|
+
await this.findEach(async (result) => {
|
|
1619
|
+
const subquery = this.dreamTransaction
|
|
1620
|
+
? result.txn(this.dreamTransaction)
|
|
1621
|
+
: result;
|
|
1622
|
+
await subquery.update(attributes);
|
|
1623
|
+
counter++;
|
|
1624
|
+
});
|
|
1625
|
+
return counter;
|
|
1626
|
+
}
|
|
1627
|
+
async updateWithoutCallingModelHooks(attributes) {
|
|
1628
|
+
const kyselyQuery = this.buildUpdate(attributes);
|
|
1629
|
+
const res = await executeDatabaseQuery(kyselyQuery, 'execute');
|
|
1630
|
+
const resultData = Array.from(res.entries())?.[0]?.[1];
|
|
1631
|
+
return Number(resultData?.numUpdatedRows || 0);
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* @internal
|
|
1635
|
+
*
|
|
1636
|
+
* Used for applying first and last queries
|
|
1637
|
+
*
|
|
1638
|
+
* @returns A dream instance or null
|
|
1639
|
+
*/
|
|
1640
|
+
async takeOne() {
|
|
1641
|
+
if (this.joinLoadActivated) {
|
|
1642
|
+
let query;
|
|
1643
|
+
if (this.whereStatements.find(whereStatement => whereStatement[this.dreamClass.primaryKey] ||
|
|
1644
|
+
whereStatement[this.namespacedPrimaryKey])) {
|
|
1645
|
+
// the query already includes a primary key where statement
|
|
1646
|
+
query = this;
|
|
1647
|
+
}
|
|
1648
|
+
else {
|
|
1649
|
+
// otherwise find the primary key and apply it to the query
|
|
1650
|
+
const primaryKeyValue = (await this.limit(1).pluck(this.namespacedPrimaryKey))[0];
|
|
1651
|
+
if (primaryKeyValue === undefined)
|
|
1652
|
+
return null;
|
|
1653
|
+
query = this.where({ [this.namespacedPrimaryKey]: primaryKeyValue });
|
|
1654
|
+
}
|
|
1655
|
+
return (await query.executeJoinLoad())[0] || null;
|
|
1656
|
+
}
|
|
1657
|
+
const kyselyQuery = this.limit(1).buildSelect();
|
|
1658
|
+
const results = await executeDatabaseQuery(kyselyQuery, 'executeTakeFirst');
|
|
1659
|
+
if (results) {
|
|
1660
|
+
const theFirst = sqlResultToDreamInstance(this.dreamClass, results);
|
|
1661
|
+
if (theFirst)
|
|
1662
|
+
await this.applyPreload(this.preloadStatements, this.preloadOnStatements, [theFirst]);
|
|
1663
|
+
return theFirst;
|
|
1664
|
+
}
|
|
1665
|
+
else
|
|
1666
|
+
return null;
|
|
1667
|
+
}
|
|
1668
|
+
/**
|
|
1669
|
+
* @internal
|
|
1670
|
+
*
|
|
1671
|
+
* Used to hydrate dreams with the provided associations
|
|
1672
|
+
*/
|
|
1673
|
+
hydrateAssociation(dreams, association, preloadedDreamsAndWhatTheyPointTo) {
|
|
1674
|
+
switch (association.type) {
|
|
1675
|
+
case 'HasMany':
|
|
1676
|
+
dreams.forEach((dream) => {
|
|
1677
|
+
dream[association.as] = [];
|
|
1678
|
+
});
|
|
1679
|
+
break;
|
|
1680
|
+
default:
|
|
1681
|
+
dreams.forEach((dream) => {
|
|
1682
|
+
dream[associationToGetterSetterProp(association)] = null;
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
// dreams is a Rating
|
|
1686
|
+
// Rating belongs to: rateables (Posts / Compositions)
|
|
1687
|
+
// loadedAssociations is an array of Posts and Compositions
|
|
1688
|
+
// if rating.rateable_id === loadedAssociation.primaryKeyvalue
|
|
1689
|
+
// rating.rateable = loadedAssociation
|
|
1690
|
+
preloadedDreamsAndWhatTheyPointTo.forEach(preloadedDreamAndWhatItPointsTo => {
|
|
1691
|
+
dreams
|
|
1692
|
+
.filter(dream => dream.primaryKeyValue === preloadedDreamAndWhatItPointsTo.pointsToPrimaryKey)
|
|
1693
|
+
.forEach((dream) => {
|
|
1694
|
+
if (association.type === 'HasMany') {
|
|
1695
|
+
dream[association.as].push(preloadedDreamAndWhatItPointsTo.dream);
|
|
1696
|
+
}
|
|
1697
|
+
else {
|
|
1698
|
+
// in a HasOne context, order clauses will be applied in advance,
|
|
1699
|
+
// prior to hydration. Considering, we only want to set the first
|
|
1700
|
+
// result and ignore other results, so we will use ||= to set.
|
|
1701
|
+
dream[association.as] ||= preloadedDreamAndWhatItPointsTo.dream;
|
|
1702
|
+
}
|
|
1703
|
+
});
|
|
1704
|
+
});
|
|
1705
|
+
if (association.type === 'HasMany') {
|
|
1706
|
+
dreams.forEach((dream) => Object.freeze(dream[association.as]));
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
/**
|
|
1710
|
+
* @internal
|
|
1711
|
+
*
|
|
1712
|
+
* Used to bridge through associations
|
|
1713
|
+
*/
|
|
1714
|
+
followThroughAssociation(dreamClass, association) {
|
|
1715
|
+
const throughAssociation = association.through && dreamClass['getAssociationMetadata'](association.through);
|
|
1716
|
+
if (!throughAssociation)
|
|
1717
|
+
throw new MissingThroughAssociation({
|
|
1718
|
+
dreamClass,
|
|
1719
|
+
association,
|
|
1720
|
+
});
|
|
1721
|
+
const throughClass = throughAssociation.modelCB();
|
|
1722
|
+
if (Array.isArray(throughClass))
|
|
1723
|
+
throw new CannotAssociateThroughPolymorphic({
|
|
1724
|
+
dreamClass,
|
|
1725
|
+
association,
|
|
1726
|
+
});
|
|
1727
|
+
const newAssociation = getSourceAssociation(throughClass, association.source);
|
|
1728
|
+
if (!newAssociation)
|
|
1729
|
+
throw new MissingThroughAssociationSource({
|
|
1730
|
+
dreamClass,
|
|
1731
|
+
throughClass,
|
|
1732
|
+
association,
|
|
1733
|
+
});
|
|
1734
|
+
return { throughAssociation, throughClass, newAssociation };
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* @internal
|
|
1738
|
+
*
|
|
1739
|
+
* Polymorphic BelongsTo. Since polymorphic associations may point to multiple tables,
|
|
1740
|
+
* preload by loading each target class separately.
|
|
1741
|
+
*
|
|
1742
|
+
* Used to preload polymorphic belongs to associations
|
|
1743
|
+
*/
|
|
1744
|
+
async preloadPolymorphicBelongsTo(association, dreams) {
|
|
1745
|
+
if (!association.polymorphic)
|
|
1746
|
+
throw new Error(`Association ${association.as} points to an array of models but is not designated polymorphic`);
|
|
1747
|
+
if (association.type !== 'BelongsTo')
|
|
1748
|
+
throw new Error(`Polymorphic association ${association.as} points to an array of models but is ${association.type}. Only BelongsTo associations may point to an array of models.`);
|
|
1749
|
+
const associatedDreams = [];
|
|
1750
|
+
for (const associatedModel of association.modelCB()) {
|
|
1751
|
+
await this.preloadPolymorphicAssociationModel(dreams, association, associatedModel, associatedDreams);
|
|
1752
|
+
}
|
|
1753
|
+
return associatedDreams;
|
|
1754
|
+
}
|
|
1755
|
+
async preloadPolymorphicAssociationModel(dreams, association, associatedDreamClass, associatedDreams) {
|
|
1756
|
+
const relevantAssociatedModels = dreams.filter((dream) => {
|
|
1757
|
+
return dream[association.foreignKeyTypeField()] === associatedDreamClass['stiBaseClassOrOwnClass'].name;
|
|
1758
|
+
});
|
|
1759
|
+
if (relevantAssociatedModels.length) {
|
|
1760
|
+
dreams.forEach((dream) => {
|
|
1761
|
+
dream[associationToGetterSetterProp(association)] = null;
|
|
1762
|
+
});
|
|
1763
|
+
// Load all models of type associated that are associated with any of the already loaded Dream models
|
|
1764
|
+
const loadedAssociations = await this.dreamClassQueryWithScopeBypasses(associatedDreamClass, {
|
|
1765
|
+
// The association may remove specific default scopes that would otherwise preclude
|
|
1766
|
+
// certain instances of the associated class from being found.
|
|
1767
|
+
defaultScopesToBypassExceptOnAssociations: association.withoutDefaultScopes,
|
|
1768
|
+
})
|
|
1769
|
+
.where({
|
|
1770
|
+
[associatedDreamClass.primaryKey]: relevantAssociatedModels.map((dream) => dream[association.foreignKey()]),
|
|
1771
|
+
})
|
|
1772
|
+
.all();
|
|
1773
|
+
loadedAssociations.forEach((loadedAssociation) => associatedDreams.push(loadedAssociation));
|
|
1774
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
1775
|
+
// Associate each loaded association with each dream based on primary key and foreign key type
|
|
1776
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
1777
|
+
for (const loadedAssociation of loadedAssociations) {
|
|
1778
|
+
dreams
|
|
1779
|
+
.filter((dream) => {
|
|
1780
|
+
return (dream[association.foreignKeyTypeField()] === loadedAssociation['stiBaseClassOrOwnClass'].name &&
|
|
1781
|
+
dream[association.foreignKey()] === association.primaryKeyValue(loadedAssociation));
|
|
1782
|
+
})
|
|
1783
|
+
.forEach((dream) => {
|
|
1784
|
+
dream[association.as] = loadedAssociation;
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1788
|
+
// end: Associate each loaded association with each dream based on primary key and foreign key type
|
|
1789
|
+
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* @internal
|
|
1794
|
+
*
|
|
1795
|
+
* Applies a preload statement
|
|
1796
|
+
*/
|
|
1797
|
+
async applyOnePreload(associationName, dreams, onStatement = {}) {
|
|
1798
|
+
if (!Array.isArray(dreams))
|
|
1799
|
+
dreams = [dreams];
|
|
1800
|
+
const dream = dreams.find(dream => dream['getAssociationMetadata'](associationName));
|
|
1801
|
+
if (!dream)
|
|
1802
|
+
return;
|
|
1803
|
+
const association = dream['getAssociationMetadata'](associationName);
|
|
1804
|
+
const dreamClass = dream.constructor;
|
|
1805
|
+
const dreamClassToHydrate = association.modelCB();
|
|
1806
|
+
if ((association.polymorphic && association.type === 'BelongsTo') || Array.isArray(dreamClassToHydrate))
|
|
1807
|
+
return this.preloadPolymorphicBelongsTo(association, dreams);
|
|
1808
|
+
const dreamClassToHydrateColumns = [...dreamClassToHydrate.columns()];
|
|
1809
|
+
const throughColumnsToHydrate = [];
|
|
1810
|
+
const columnsToPluck = dreamClassToHydrateColumns.map(column => this.namespaceColumn(column.toString(), associationName));
|
|
1811
|
+
const asHasAssociation = association;
|
|
1812
|
+
if (asHasAssociation.through && asHasAssociation.preloadThroughColumns) {
|
|
1813
|
+
if (isObject(asHasAssociation.preloadThroughColumns)) {
|
|
1814
|
+
const preloadMap = asHasAssociation.preloadThroughColumns;
|
|
1815
|
+
Object.keys(preloadMap).forEach(preloadThroughColumn => {
|
|
1816
|
+
throughColumnsToHydrate.push(preloadMap[preloadThroughColumn]);
|
|
1817
|
+
columnsToPluck.push(this.namespaceColumn(preloadThroughColumn, asHasAssociation.through));
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
else {
|
|
1821
|
+
const preloadArray = asHasAssociation.preloadThroughColumns;
|
|
1822
|
+
preloadArray.forEach(preloadThroughColumn => {
|
|
1823
|
+
throughColumnsToHydrate.push(preloadThroughColumn);
|
|
1824
|
+
columnsToPluck.push(this.namespaceColumn(preloadThroughColumn, asHasAssociation.through));
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
columnsToPluck.push(this.namespaceColumn(dreamClass.primaryKey, dreamClass.table));
|
|
1829
|
+
const baseClass = dreamClass['stiBaseClassOrOwnClass']['getAssociationMetadata'](associationName)
|
|
1830
|
+
? dreamClass['stiBaseClassOrOwnClass']
|
|
1831
|
+
: dreamClass;
|
|
1832
|
+
const associationDataScope = this.dreamClassQueryWithScopeBypasses(baseClass, {
|
|
1833
|
+
// In order to stay DRY, preloading leverages the association logic built into
|
|
1834
|
+
// `joins` (by using `pluck`, which calls `joins`). However, baseClass may have
|
|
1835
|
+
// default scopes that would preclude finding that instance. We remove all
|
|
1836
|
+
// default scopes on baseClass, but not subsequent associations, so that the
|
|
1837
|
+
// single query will be able to find each row corresponding to a Dream in `dreams`,
|
|
1838
|
+
// regardless of default scopes on that Dream's class.
|
|
1839
|
+
bypassAllDefaultScopesExceptOnAssociations: true,
|
|
1840
|
+
}).where({
|
|
1841
|
+
[dreamClass.primaryKey]: dreams.map(obj => obj.primaryKeyValue),
|
|
1842
|
+
});
|
|
1843
|
+
const hydrationData = await associationDataScope
|
|
1844
|
+
._connection(this.connectionOverride)
|
|
1845
|
+
.innerJoin(associationName, (onStatement || {}))
|
|
1846
|
+
.pluck(...columnsToPluck);
|
|
1847
|
+
const preloadedDreamsAndWhatTheyPointTo = hydrationData.map(pluckedData => {
|
|
1848
|
+
const attributes = {};
|
|
1849
|
+
dreamClassToHydrateColumns.forEach((columnName, index) => (attributes[protectAgainstPollutingAssignment(columnName)] = pluckedData[index]));
|
|
1850
|
+
const hydratedDream = sqlResultToDreamInstance(dreamClassToHydrate, attributes);
|
|
1851
|
+
throughColumnsToHydrate.forEach((throughAssociationColumn, index) => (hydratedDream.preloadedThroughColumns[throughAssociationColumn] =
|
|
1852
|
+
pluckedData[dreamClassToHydrateColumns.length + index]));
|
|
1853
|
+
return {
|
|
1854
|
+
dream: hydratedDream,
|
|
1855
|
+
pointsToPrimaryKey: pluckedData[pluckedData.length - 1],
|
|
1856
|
+
};
|
|
1857
|
+
});
|
|
1858
|
+
this.hydrateAssociation(dreams, association, preloadedDreamsAndWhatTheyPointTo);
|
|
1859
|
+
return preloadedDreamsAndWhatTheyPointTo.map(obj => obj.dream);
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* @internal
|
|
1863
|
+
*
|
|
1864
|
+
* Used by loadBuider
|
|
1865
|
+
*/
|
|
1866
|
+
async hydratePreload(dream) {
|
|
1867
|
+
await this.applyPreload(this.preloadStatements, this.preloadOnStatements, dream);
|
|
1868
|
+
}
|
|
1869
|
+
/**
|
|
1870
|
+
* @internal
|
|
1871
|
+
*
|
|
1872
|
+
* Applies a preload statement
|
|
1873
|
+
*/
|
|
1874
|
+
async applyPreload(preloadStatement, preloadOnStatements, dream) {
|
|
1875
|
+
const keys = Object.keys(preloadStatement);
|
|
1876
|
+
for (const key of keys) {
|
|
1877
|
+
const nestedDreams = await this.applyOnePreload(key, dream, this.applyablePreloadOnStatements(preloadOnStatements[key]));
|
|
1878
|
+
if (nestedDreams) {
|
|
1879
|
+
await this.applyPreload(preloadStatement[key], preloadOnStatements[key], nestedDreams);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* @internal
|
|
1885
|
+
*
|
|
1886
|
+
* retrieves on statements that can be applied to a preload
|
|
1887
|
+
*/
|
|
1888
|
+
applyablePreloadOnStatements(preloadOnStatements) {
|
|
1889
|
+
if (preloadOnStatements === undefined)
|
|
1890
|
+
return undefined;
|
|
1891
|
+
return Object.keys(preloadOnStatements).reduce((agg, key) => {
|
|
1892
|
+
const value = preloadOnStatements[key];
|
|
1893
|
+
// filter out plain objects, but not ops and not on/notOn/onAny statements
|
|
1894
|
+
// because plain objects are just the next level of nested preload
|
|
1895
|
+
if (key === 'on' ||
|
|
1896
|
+
key === 'notOn' ||
|
|
1897
|
+
key === 'onAny' ||
|
|
1898
|
+
value === null ||
|
|
1899
|
+
value.constructor !== Object) {
|
|
1900
|
+
agg[key] = value;
|
|
1901
|
+
}
|
|
1902
|
+
return agg;
|
|
1903
|
+
}, {});
|
|
1904
|
+
}
|
|
1905
|
+
conditionallyApplyDefaultScopes() {
|
|
1906
|
+
if (this.bypassAllDefaultScopes || this.bypassAllDefaultScopesExceptOnAssociations)
|
|
1907
|
+
return this;
|
|
1908
|
+
const thisScopes = this.dreamClass['scopes'].default;
|
|
1909
|
+
let query = this;
|
|
1910
|
+
for (const scope of thisScopes) {
|
|
1911
|
+
if (!shouldBypassDefaultScope(scope.method, {
|
|
1912
|
+
defaultScopesToBypass: [
|
|
1913
|
+
...this.defaultScopesToBypass,
|
|
1914
|
+
...this.defaultScopesToBypassExceptOnAssociations,
|
|
1915
|
+
],
|
|
1916
|
+
})) {
|
|
1917
|
+
query = this.dreamClass[scope.method](query);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
return query;
|
|
1921
|
+
}
|
|
1922
|
+
// Through associations don't get written into the SQL; they
|
|
1923
|
+
// locate the next association we need to build into the SQL
|
|
1924
|
+
// AND the source to reference on the other side
|
|
1925
|
+
joinsBridgeThroughAssociations({ query, dreamClass, association, previousAssociationTableOrAlias, throughAssociations, joinType, }) {
|
|
1926
|
+
if (association.type === 'BelongsTo' || !association.through) {
|
|
1927
|
+
return {
|
|
1928
|
+
query,
|
|
1929
|
+
dreamClass,
|
|
1930
|
+
association,
|
|
1931
|
+
previousAssociationTableOrAlias,
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
else {
|
|
1935
|
+
throughAssociations.push(association);
|
|
1936
|
+
// We have entered joinsBridgeThroughAssociations with the
|
|
1937
|
+
// CompositionAssetAudits HasOne User association, which
|
|
1938
|
+
// is through compositionAsset
|
|
1939
|
+
// We now apply the compositionAsset association (a BelongsTo)
|
|
1940
|
+
// to the query
|
|
1941
|
+
const { query: queryWithThroughAssociationApplied } = this.applyOneJoin({
|
|
1942
|
+
query,
|
|
1943
|
+
dreamClass,
|
|
1944
|
+
previousAssociationTableOrAlias,
|
|
1945
|
+
currentAssociationTableOrAlias: association.through,
|
|
1946
|
+
throughAssociations,
|
|
1947
|
+
joinType,
|
|
1948
|
+
});
|
|
1949
|
+
// The through association has both a `through` and a `source`. The `source`
|
|
1950
|
+
// is the association on the model that has now been joined. In our example,
|
|
1951
|
+
// the `source` is the `user` association on the CompositionAsset model
|
|
1952
|
+
const { newAssociation, throughAssociation, throughClass } = this.followThroughAssociation(dreamClass, association);
|
|
1953
|
+
if (newAssociation.through) {
|
|
1954
|
+
// This new association is itself a through association, so we recursively
|
|
1955
|
+
// call joinsBridgeThroughAssociations
|
|
1956
|
+
return this.joinsBridgeThroughAssociations({
|
|
1957
|
+
query: queryWithThroughAssociationApplied,
|
|
1958
|
+
dreamClass: throughClass,
|
|
1959
|
+
association: newAssociation,
|
|
1960
|
+
previousAssociationTableOrAlias: throughAssociation.as,
|
|
1961
|
+
throughAssociations,
|
|
1962
|
+
joinType,
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
else {
|
|
1966
|
+
// This new association is not a through association, so
|
|
1967
|
+
// this is the target association we were looking for
|
|
1968
|
+
return {
|
|
1969
|
+
query: queryWithThroughAssociationApplied,
|
|
1970
|
+
dreamClass: association.modelCB(),
|
|
1971
|
+
association: newAssociation,
|
|
1972
|
+
throughClass,
|
|
1973
|
+
previousAssociationTableOrAlias: association.through,
|
|
1974
|
+
};
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
applyOneJoin({ query, dreamClass, previousAssociationTableOrAlias, currentAssociationTableOrAlias, joinOnStatements = {}, throughAssociations = [], joinType, }) {
|
|
1979
|
+
const { name, alias } = extractAssociationMetadataFromAssociationName(currentAssociationTableOrAlias);
|
|
1980
|
+
previousAssociationTableOrAlias = extractAssociationMetadataFromAssociationName(previousAssociationTableOrAlias).alias;
|
|
1981
|
+
currentAssociationTableOrAlias = alias;
|
|
1982
|
+
let association = dreamClass['getAssociationMetadata'](name);
|
|
1983
|
+
if (!association) {
|
|
1984
|
+
throw new JoinAttemptedOnMissingAssociation({
|
|
1985
|
+
dreamClass,
|
|
1986
|
+
associationName: currentAssociationTableOrAlias,
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
const results = this.joinsBridgeThroughAssociations({
|
|
1990
|
+
query,
|
|
1991
|
+
dreamClass,
|
|
1992
|
+
association,
|
|
1993
|
+
previousAssociationTableOrAlias,
|
|
1994
|
+
throughAssociations,
|
|
1995
|
+
joinType,
|
|
1996
|
+
});
|
|
1997
|
+
query = results.query;
|
|
1998
|
+
dreamClass = results.dreamClass;
|
|
1999
|
+
association = results.association;
|
|
2000
|
+
const timeToApplyThroughAssociations = throughAssociations.length && throughAssociations[0].source === association.as;
|
|
2001
|
+
const originalPreviousAssociationTableOrAlias = previousAssociationTableOrAlias;
|
|
2002
|
+
previousAssociationTableOrAlias = results.previousAssociationTableOrAlias;
|
|
2003
|
+
const throughClass = results.throughClass;
|
|
2004
|
+
if (timeToApplyThroughAssociations) {
|
|
2005
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
2006
|
+
// when an association is through another association, `joinsBridgeThroughAssociations`
|
|
2007
|
+
// is called, which eventually calls back to this method, passing in the original
|
|
2008
|
+
// through association as `originalAssociation`
|
|
2009
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
2010
|
+
throughAssociations.forEach((throughAssociation) => {
|
|
2011
|
+
if (throughAssociation.type === 'HasMany') {
|
|
2012
|
+
if (query?.distinctOn && throughAssociation.distinct) {
|
|
2013
|
+
query = query.distinctOn(this.distinctColumnNameForAssociation({
|
|
2014
|
+
association: throughAssociation,
|
|
2015
|
+
tableNameOrAlias: throughAssociation.as,
|
|
2016
|
+
foreignKey: throughAssociation.primaryKey(),
|
|
2017
|
+
}));
|
|
2018
|
+
}
|
|
2019
|
+
if (throughAssociation.order) {
|
|
2020
|
+
query = this.applyOrderStatementForAssociation({
|
|
2021
|
+
query,
|
|
2022
|
+
tableNameOrAlias: throughAssociation.as,
|
|
2023
|
+
association: throughAssociation,
|
|
2024
|
+
});
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
if (association.type === 'BelongsTo') {
|
|
2030
|
+
if (Array.isArray(association.modelCB()))
|
|
2031
|
+
throw new CannotJoinPolymorphicBelongsToError({
|
|
2032
|
+
dreamClass,
|
|
2033
|
+
association,
|
|
2034
|
+
innerJoinStatements: this.innerJoinStatements,
|
|
2035
|
+
leftJoinStatements: this.leftJoinStatements,
|
|
2036
|
+
});
|
|
2037
|
+
const to = association.modelCB().table;
|
|
2038
|
+
const joinTableExpression = currentAssociationTableOrAlias === to
|
|
2039
|
+
? currentAssociationTableOrAlias
|
|
2040
|
+
: `${to} as ${currentAssociationTableOrAlias}`;
|
|
2041
|
+
query = query[(joinType === 'inner' ? 'innerJoin' : 'leftJoin')](joinTableExpression, (join) => {
|
|
2042
|
+
join = join.onRef(this.namespaceColumn(association.foreignKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.primaryKey(), currentAssociationTableOrAlias));
|
|
2043
|
+
if (timeToApplyThroughAssociations) {
|
|
2044
|
+
throughAssociations.forEach((throughAssociation) => {
|
|
2045
|
+
join = this.applyAssociationOnStatementsToJoinStatement({
|
|
2046
|
+
join,
|
|
2047
|
+
association: throughAssociation,
|
|
2048
|
+
currentAssociationTableOrAlias,
|
|
2049
|
+
previousAssociationTableOrAlias: originalPreviousAssociationTableOrAlias,
|
|
2050
|
+
joinOnStatements,
|
|
2051
|
+
});
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
join = this.conditionallyApplyDefaultScopesDependentOnAssociation({
|
|
2055
|
+
join,
|
|
2056
|
+
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2057
|
+
association,
|
|
2058
|
+
});
|
|
2059
|
+
join = this.applyJoinOnStatements(join, joinOnStatements[currentAssociationTableOrAlias], currentAssociationTableOrAlias);
|
|
2060
|
+
return join;
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
else {
|
|
2064
|
+
const to = association.modelCB().table;
|
|
2065
|
+
const joinTableExpression = currentAssociationTableOrAlias === to
|
|
2066
|
+
? currentAssociationTableOrAlias
|
|
2067
|
+
: `${to} as ${currentAssociationTableOrAlias}`;
|
|
2068
|
+
query = query[(joinType === 'inner' ? 'innerJoin' : 'leftJoin')](joinTableExpression, (join) => {
|
|
2069
|
+
join = join.onRef(this.namespaceColumn(association.primaryKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.foreignKey(), currentAssociationTableOrAlias));
|
|
2070
|
+
if (association.polymorphic) {
|
|
2071
|
+
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement({
|
|
2072
|
+
[association.foreignKeyTypeField()]: throughClass
|
|
2073
|
+
? throughClass['stiBaseClassOrOwnClass'].name
|
|
2074
|
+
: dreamClass['stiBaseClassOrOwnClass'].name,
|
|
2075
|
+
}, currentAssociationTableOrAlias)));
|
|
2076
|
+
}
|
|
2077
|
+
if (timeToApplyThroughAssociations) {
|
|
2078
|
+
throughAssociations.forEach((throughAssociation) => {
|
|
2079
|
+
join = this.applyAssociationOnStatementsToJoinStatement({
|
|
2080
|
+
join,
|
|
2081
|
+
association: throughAssociation,
|
|
2082
|
+
currentAssociationTableOrAlias,
|
|
2083
|
+
previousAssociationTableOrAlias: originalPreviousAssociationTableOrAlias,
|
|
2084
|
+
joinOnStatements,
|
|
2085
|
+
});
|
|
2086
|
+
});
|
|
2087
|
+
}
|
|
2088
|
+
join = this.applyAssociationOnStatementsToJoinStatement({
|
|
2089
|
+
join,
|
|
2090
|
+
association,
|
|
2091
|
+
currentAssociationTableOrAlias,
|
|
2092
|
+
previousAssociationTableOrAlias,
|
|
2093
|
+
joinOnStatements,
|
|
2094
|
+
});
|
|
2095
|
+
join = this.conditionallyApplyDefaultScopesDependentOnAssociation({
|
|
2096
|
+
join,
|
|
2097
|
+
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2098
|
+
association,
|
|
2099
|
+
});
|
|
2100
|
+
join = this.applyJoinOnStatements(join, joinOnStatements[currentAssociationTableOrAlias], currentAssociationTableOrAlias);
|
|
2101
|
+
return join;
|
|
2102
|
+
});
|
|
2103
|
+
if (association.type === 'HasMany') {
|
|
2104
|
+
if (association.order) {
|
|
2105
|
+
query = this.applyOrderStatementForAssociation({
|
|
2106
|
+
query,
|
|
2107
|
+
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2108
|
+
association,
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
2111
|
+
if (query.distinctOn && association.distinct) {
|
|
2112
|
+
query = query.distinctOn(this.distinctColumnNameForAssociation({
|
|
2113
|
+
association,
|
|
2114
|
+
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
2115
|
+
foreignKey: association.foreignKey(),
|
|
2116
|
+
}));
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
return {
|
|
2121
|
+
query,
|
|
2122
|
+
association,
|
|
2123
|
+
previousAssociationTableOrAlias,
|
|
2124
|
+
currentAssociationTableOrAlias,
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
applyAssociationOnStatementsToJoinStatement({ join, currentAssociationTableOrAlias, previousAssociationTableOrAlias, association, joinOnStatements, }) {
|
|
2128
|
+
if (association.on) {
|
|
2129
|
+
this.throwUnlessAllRequiredWhereClausesProvided(association, currentAssociationTableOrAlias, joinOnStatements);
|
|
2130
|
+
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(association.on, currentAssociationTableOrAlias), { disallowSimilarityOperator: false }));
|
|
2131
|
+
}
|
|
2132
|
+
if (association.notOn) {
|
|
2133
|
+
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(association.notOn, currentAssociationTableOrAlias), { negate: true }));
|
|
2134
|
+
}
|
|
2135
|
+
if (association.onAny) {
|
|
2136
|
+
join = join.on((eb) => eb.or(association.onAny.map(whereAnyStatement => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(whereAnyStatement, currentAssociationTableOrAlias), { disallowSimilarityOperator: false }))));
|
|
2137
|
+
}
|
|
2138
|
+
if (association.selfOn) {
|
|
2139
|
+
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.rawifiedSelfOnClause({
|
|
2140
|
+
associationAlias: association.as,
|
|
2141
|
+
selfAlias: previousAssociationTableOrAlias,
|
|
2142
|
+
selfOnClause: association.selfOn,
|
|
2143
|
+
})));
|
|
2144
|
+
}
|
|
2145
|
+
if (association.selfNotOn) {
|
|
2146
|
+
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.rawifiedSelfOnClause({
|
|
2147
|
+
associationAlias: association.as,
|
|
2148
|
+
selfAlias: previousAssociationTableOrAlias,
|
|
2149
|
+
selfOnClause: association.selfNotOn,
|
|
2150
|
+
}), { negate: true }));
|
|
2151
|
+
}
|
|
2152
|
+
return join;
|
|
2153
|
+
}
|
|
2154
|
+
conditionallyApplyDefaultScopesDependentOnAssociation({ join, tableNameOrAlias, association, }) {
|
|
2155
|
+
let scopesQuery = new Query(this.dreamInstance);
|
|
2156
|
+
const associationClass = association.modelCB();
|
|
2157
|
+
const associationScopes = associationClass['scopes'].default;
|
|
2158
|
+
for (const scope of associationScopes) {
|
|
2159
|
+
if (!shouldBypassDefaultScope(scope.method, {
|
|
2160
|
+
bypassAllDefaultScopes: this.bypassAllDefaultScopes,
|
|
2161
|
+
defaultScopesToBypass: [...this.defaultScopesToBypass, ...(association.withoutDefaultScopes || [])],
|
|
2162
|
+
})) {
|
|
2163
|
+
const tempQuery = associationClass[scope.method](scopesQuery);
|
|
2164
|
+
// The scope method on a Dream model should return a clone of the Query it receives
|
|
2165
|
+
// (e.g. by returning `scope.where(...)`), but in case the function doesn't return,
|
|
2166
|
+
// or returns the wrong thing, we check before overriding `scopesQuery` with what the
|
|
2167
|
+
// method returned.
|
|
2168
|
+
if (tempQuery && tempQuery.constructor === scopesQuery.constructor)
|
|
2169
|
+
scopesQuery = tempQuery;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
if (scopesQuery.whereStatements.length) {
|
|
2173
|
+
join = join.on((eb) => eb.and(scopesQuery.whereStatements.flatMap(whereStatement => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement(whereStatement, tableNameOrAlias), { disallowSimilarityOperator: false }))));
|
|
2174
|
+
}
|
|
2175
|
+
return join;
|
|
2176
|
+
}
|
|
2177
|
+
distinctColumnNameForAssociation({ association, tableNameOrAlias, foreignKey, }) {
|
|
2178
|
+
if (!association.distinct)
|
|
2179
|
+
return null;
|
|
2180
|
+
if (association.distinct === true)
|
|
2181
|
+
return this.namespaceColumn(foreignKey, tableNameOrAlias);
|
|
2182
|
+
return this.namespaceColumn(association.distinct, tableNameOrAlias);
|
|
2183
|
+
}
|
|
2184
|
+
recursivelyJoin({ query, joinsStatement, joinOnStatements, dreamClass, previousAssociationTableOrAlias, joinType, }) {
|
|
2185
|
+
for (const currentAssociationTableOrAlias of Object.keys(joinsStatement)) {
|
|
2186
|
+
const results = this.applyOneJoin({
|
|
2187
|
+
query,
|
|
2188
|
+
dreamClass,
|
|
2189
|
+
previousAssociationTableOrAlias,
|
|
2190
|
+
currentAssociationTableOrAlias,
|
|
2191
|
+
joinOnStatements,
|
|
2192
|
+
joinType,
|
|
2193
|
+
});
|
|
2194
|
+
query = results.query;
|
|
2195
|
+
const association = results.association;
|
|
2196
|
+
query = this.recursivelyJoin({
|
|
2197
|
+
query,
|
|
2198
|
+
joinsStatement: joinsStatement[currentAssociationTableOrAlias],
|
|
2199
|
+
joinOnStatements: joinOnStatements[currentAssociationTableOrAlias],
|
|
2200
|
+
dreamClass: association.modelCB(),
|
|
2201
|
+
previousAssociationTableOrAlias: currentAssociationTableOrAlias,
|
|
2202
|
+
joinType,
|
|
2203
|
+
});
|
|
2204
|
+
}
|
|
2205
|
+
return query;
|
|
2206
|
+
}
|
|
2207
|
+
throwUnlessAllRequiredWhereClausesProvided(association, namespace, joinOnStatements) {
|
|
2208
|
+
const whereStatement = association.on;
|
|
2209
|
+
const columnsRequiringWhereStatements = Object.keys(whereStatement).reduce((agg, column) => {
|
|
2210
|
+
if (whereStatement[column] === DreamConst.required)
|
|
2211
|
+
agg.push(column);
|
|
2212
|
+
return agg;
|
|
2213
|
+
}, []);
|
|
2214
|
+
const missingRequiredWhereStatements = columnsRequiringWhereStatements.filter(column => joinOnStatements[namespace]?.on?.[column] === undefined);
|
|
2215
|
+
if (missingRequiredWhereStatements.length)
|
|
2216
|
+
throw new MissingRequiredAssociationOnClause(association, missingRequiredWhereStatements[0]);
|
|
2217
|
+
}
|
|
2218
|
+
applyOrderStatementForAssociation({ query, tableNameOrAlias, association, }) {
|
|
2219
|
+
if (!query.orderBy)
|
|
2220
|
+
return query;
|
|
2221
|
+
let selectQuery = query;
|
|
2222
|
+
const orderStatement = association.order;
|
|
2223
|
+
if (isString(orderStatement)) {
|
|
2224
|
+
selectQuery = selectQuery.orderBy(this.namespaceColumn(orderStatement, tableNameOrAlias), 'asc');
|
|
2225
|
+
}
|
|
2226
|
+
else {
|
|
2227
|
+
Object.keys(orderStatement).forEach(column => {
|
|
2228
|
+
const direction = orderStatement[column];
|
|
2229
|
+
selectQuery = selectQuery.orderBy(this.namespaceColumn(column, tableNameOrAlias), direction);
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
return selectQuery;
|
|
2233
|
+
}
|
|
2234
|
+
inArrayWithNull_or_notInArrayWithoutNull_ExpressionBuilder(eb, a, b, c) {
|
|
2235
|
+
const isNullStatement = eb(a, 'is', null);
|
|
2236
|
+
const compactedC = compact(c);
|
|
2237
|
+
if (compactedC.length)
|
|
2238
|
+
return eb.or([eb(a, b, compactedC), isNullStatement]);
|
|
2239
|
+
// not in an empty array means match everything
|
|
2240
|
+
if (b === 'not in')
|
|
2241
|
+
return sql `TRUE`;
|
|
2242
|
+
return isNullStatement;
|
|
2243
|
+
}
|
|
2244
|
+
inArrayWithoutNullExpressionBuilder(eb, a, b, c) {
|
|
2245
|
+
const isNotNullStatement = eb(a, 'is not', null);
|
|
2246
|
+
const compactedC = compact(c);
|
|
2247
|
+
if (compactedC.length)
|
|
2248
|
+
return eb.and([eb(a, 'in', compactedC), isNotNullStatement]);
|
|
2249
|
+
// in an empty array means match nothing
|
|
2250
|
+
return sql `FALSE`;
|
|
2251
|
+
}
|
|
2252
|
+
notInArrayWithNullExpressionBuilder(eb, a, b, c) {
|
|
2253
|
+
const isNullStatement = eb(a, 'is not', null);
|
|
2254
|
+
const compactedC = compact(c);
|
|
2255
|
+
if (compactedC.length)
|
|
2256
|
+
return eb.and([eb(a, 'not in', compactedC), isNullStatement]);
|
|
2257
|
+
return isNullStatement;
|
|
2258
|
+
}
|
|
2259
|
+
whereStatementToExpressionWrapper(eb, whereStatement, { negate = false, disallowSimilarityOperator = true, } = {}) {
|
|
2260
|
+
const clauses = compact(Object.keys(whereStatement)
|
|
2261
|
+
.filter(key => whereStatement[key] !== DreamConst.required)
|
|
2262
|
+
.map(attr => {
|
|
2263
|
+
const val = whereStatement[attr];
|
|
2264
|
+
if (val?.isOpsStatement &&
|
|
2265
|
+
val.shouldBypassWhereStatement) {
|
|
2266
|
+
if (disallowSimilarityOperator)
|
|
2267
|
+
throw new Error('Similarity operator may not be used in whereAny');
|
|
2268
|
+
// some ops statements are handled specifically in the select portion of the query,
|
|
2269
|
+
// and should be ommited from the where clause directly
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
const { a, b, c, a2, b2, c2 } = this.dreamWhereStatementToExpressionBuilderParts(attr, val);
|
|
2273
|
+
// postgres is unable to handle WHERE IN statements with blank arrays, such as in
|
|
2274
|
+
// "WHERE id IN ()", meaning that:
|
|
2275
|
+
// 1. If we receive a blank array during an IN comparison,
|
|
2276
|
+
// then we need to simply regurgitate a where statement which
|
|
2277
|
+
// guarantees no records.
|
|
2278
|
+
// 2. If we receive a blank array during a NOT IN comparison,
|
|
2279
|
+
// then it is the same as the where statement not being present at all,
|
|
2280
|
+
// resulting in a noop on our end
|
|
2281
|
+
//
|
|
2282
|
+
if (Array.isArray(c)) {
|
|
2283
|
+
if ((b === 'in' && c.includes(null)) || (b === 'not in' && !c.includes(null))) {
|
|
2284
|
+
return this.inArrayWithNull_or_notInArrayWithoutNull_ExpressionBuilder(eb, a, b, c);
|
|
2285
|
+
}
|
|
2286
|
+
else if (negate && b === 'in' && !c.includes(null)) {
|
|
2287
|
+
return this.inArrayWithoutNullExpressionBuilder(eb, a, b, c);
|
|
2288
|
+
}
|
|
2289
|
+
else if (b === 'not in' && c.includes(null)) {
|
|
2290
|
+
return this.notInArrayWithNullExpressionBuilder(eb, a, b, c);
|
|
2291
|
+
}
|
|
2292
|
+
const compactedC = compact(c);
|
|
2293
|
+
if (b === 'in' && compactedC.length === 0) {
|
|
2294
|
+
// in an empty array means match nothing
|
|
2295
|
+
return sql `FALSE`;
|
|
2296
|
+
}
|
|
2297
|
+
else if (b === 'not in' && compactedC.length === 0) {
|
|
2298
|
+
// not in an empty array means match everything
|
|
2299
|
+
return sql `TRUE`;
|
|
2300
|
+
}
|
|
2301
|
+
else {
|
|
2302
|
+
return eb(a, b, compactedC);
|
|
2303
|
+
}
|
|
2304
|
+
//
|
|
2305
|
+
}
|
|
2306
|
+
else if (b === '=' && c === null) {
|
|
2307
|
+
return eb(a, 'is', null);
|
|
2308
|
+
//
|
|
2309
|
+
}
|
|
2310
|
+
else if (b === '!=' && c === null) {
|
|
2311
|
+
return eb(a, 'is not', null);
|
|
2312
|
+
//
|
|
2313
|
+
}
|
|
2314
|
+
else if (b === '=' && negate) {
|
|
2315
|
+
return eb.and([eb(a, '=', c), eb(a, 'is not', null)]);
|
|
2316
|
+
//
|
|
2317
|
+
}
|
|
2318
|
+
else if (b === '!=' && c !== null) {
|
|
2319
|
+
return eb.or([eb(a, '!=', c), eb(a, 'is', null)]);
|
|
2320
|
+
//
|
|
2321
|
+
}
|
|
2322
|
+
else {
|
|
2323
|
+
const expression = eb(a, b, c);
|
|
2324
|
+
if (b2)
|
|
2325
|
+
return expression.and(eb(a2, b2, c2));
|
|
2326
|
+
return expression;
|
|
2327
|
+
}
|
|
2328
|
+
}));
|
|
2329
|
+
return negate ? eb.not(eb.parens(eb.and(clauses))) : eb.and(clauses);
|
|
2330
|
+
}
|
|
2331
|
+
dreamWhereStatementToExpressionBuilderParts(attr, val) {
|
|
2332
|
+
let a;
|
|
2333
|
+
let b;
|
|
2334
|
+
let c;
|
|
2335
|
+
let a2 = null;
|
|
2336
|
+
let b2 = null;
|
|
2337
|
+
let c2 = null;
|
|
2338
|
+
if (val instanceof Function && val !== DreamConst.passthrough) {
|
|
2339
|
+
val = val();
|
|
2340
|
+
}
|
|
2341
|
+
else if (val === DreamConst.passthrough) {
|
|
2342
|
+
const column = attr.split('.').pop();
|
|
2343
|
+
if (this.passthroughOnStatement[column] === undefined)
|
|
2344
|
+
throw new MissingRequiredPassthroughForAssociationOnClause(column);
|
|
2345
|
+
val = this.passthroughOnStatement[column];
|
|
2346
|
+
}
|
|
2347
|
+
if (val === null) {
|
|
2348
|
+
a = attr;
|
|
2349
|
+
b = 'is';
|
|
2350
|
+
c = val;
|
|
2351
|
+
}
|
|
2352
|
+
else if (['SelectQueryBuilder', 'SelectQueryBuilderImpl'].includes(val?.constructor?.name)) {
|
|
2353
|
+
a = attr;
|
|
2354
|
+
b = 'in';
|
|
2355
|
+
c = val;
|
|
2356
|
+
}
|
|
2357
|
+
else if (Array.isArray(val)) {
|
|
2358
|
+
a = attr;
|
|
2359
|
+
b = 'in';
|
|
2360
|
+
c = val;
|
|
2361
|
+
}
|
|
2362
|
+
else if (val instanceof CurriedOpsStatement) {
|
|
2363
|
+
val = val.toOpsStatement(this.dreamClass, attr);
|
|
2364
|
+
a = attr;
|
|
2365
|
+
b = val.operator;
|
|
2366
|
+
c = val.value;
|
|
2367
|
+
}
|
|
2368
|
+
else if (val instanceof OpsStatement) {
|
|
2369
|
+
a = attr;
|
|
2370
|
+
b = val.operator;
|
|
2371
|
+
c = val.value;
|
|
2372
|
+
}
|
|
2373
|
+
else if (val instanceof Range) {
|
|
2374
|
+
const rangeStart = val.begin;
|
|
2375
|
+
const rangeEnd = val.end;
|
|
2376
|
+
const excludeEnd = val.excludeEnd;
|
|
2377
|
+
if (rangeStart && rangeEnd) {
|
|
2378
|
+
a = attr;
|
|
2379
|
+
b = '>=';
|
|
2380
|
+
c = rangeStart;
|
|
2381
|
+
a2 = attr;
|
|
2382
|
+
b2 = excludeEnd ? '<' : '<=';
|
|
2383
|
+
c2 = rangeEnd;
|
|
2384
|
+
}
|
|
2385
|
+
else if (rangeStart) {
|
|
2386
|
+
a = attr;
|
|
2387
|
+
b = '>=';
|
|
2388
|
+
c = rangeStart;
|
|
2389
|
+
}
|
|
2390
|
+
else {
|
|
2391
|
+
a = attr;
|
|
2392
|
+
b = excludeEnd ? '<' : '<=';
|
|
2393
|
+
c = rangeEnd;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
else {
|
|
2397
|
+
a = attr;
|
|
2398
|
+
b = '=';
|
|
2399
|
+
c = val;
|
|
2400
|
+
}
|
|
2401
|
+
if (c instanceof DateTime || c instanceof CalendarDate)
|
|
2402
|
+
c = c.toJSDate();
|
|
2403
|
+
if (c2 instanceof DateTime || c2 instanceof CalendarDate)
|
|
2404
|
+
c2 = c2.toJSDate();
|
|
2405
|
+
if (a && c === undefined)
|
|
2406
|
+
throw new CannotPassUndefinedAsAValueToAWhereClause(this.dreamClass, a);
|
|
2407
|
+
if (a2 && c2 === undefined)
|
|
2408
|
+
throw new CannotPassUndefinedAsAValueToAWhereClause(this.dreamClass, a2);
|
|
2409
|
+
return { a, b, c, a2, b2, c2 };
|
|
2410
|
+
}
|
|
2411
|
+
applyJoinOnStatements(join, joinOnStatement, rootTableOrAssociationAlias) {
|
|
2412
|
+
if (!joinOnStatement)
|
|
2413
|
+
return join;
|
|
2414
|
+
join = this._applyJoinOnStatements(join, joinOnStatement.on, rootTableOrAssociationAlias);
|
|
2415
|
+
join = this._applyJoinOnStatements(join, joinOnStatement.notOn, rootTableOrAssociationAlias, {
|
|
2416
|
+
negate: true,
|
|
2417
|
+
});
|
|
2418
|
+
join = this._applyJoinOnAnyStatements(join, joinOnStatement.onAny, rootTableOrAssociationAlias);
|
|
2419
|
+
return join;
|
|
2420
|
+
}
|
|
2421
|
+
_applyJoinOnStatements(join, joinOnStatement, rootTableOrAssociationAlias, { negate = false, } = {}) {
|
|
2422
|
+
if (!joinOnStatement)
|
|
2423
|
+
return join;
|
|
2424
|
+
return join.on((eb) => this.joinOnStatementToExpressionWrapper(joinOnStatement, rootTableOrAssociationAlias, eb, {
|
|
2425
|
+
negate,
|
|
2426
|
+
disallowSimilarityOperator: negate,
|
|
2427
|
+
}));
|
|
2428
|
+
}
|
|
2429
|
+
_applyJoinOnAnyStatements(join, joinOnAnyStatement, rootTableOrAssociationAlias) {
|
|
2430
|
+
if (!joinOnAnyStatement)
|
|
2431
|
+
return join;
|
|
2432
|
+
if (!joinOnAnyStatement.length)
|
|
2433
|
+
return join;
|
|
2434
|
+
return join.on((eb) => {
|
|
2435
|
+
return eb.or(joinOnAnyStatement.map(joinOnStatement => this.joinOnStatementToExpressionWrapper(joinOnStatement, rootTableOrAssociationAlias, eb)));
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
joinOnStatementToExpressionWrapper(joinOnStatement, rootTableOrAssociationAlias, eb, { negate = false, disallowSimilarityOperator = true, } = {}) {
|
|
2439
|
+
return this.whereStatementToExpressionWrapper(eb, Object.keys(joinOnStatement).reduce((agg, key) => {
|
|
2440
|
+
agg[this.namespaceColumn(key.toString(), rootTableOrAssociationAlias)] = joinOnStatement[key];
|
|
2441
|
+
return agg;
|
|
2442
|
+
}, {}), {
|
|
2443
|
+
negate,
|
|
2444
|
+
disallowSimilarityOperator,
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2447
|
+
buildCommon(kyselyQuery) {
|
|
2448
|
+
this.checkForQueryViolations();
|
|
2449
|
+
const query = this.conditionallyApplyDefaultScopes();
|
|
2450
|
+
if (!isEmpty(query.innerJoinStatements)) {
|
|
2451
|
+
kyselyQuery = query.recursivelyJoin({
|
|
2452
|
+
query: kyselyQuery,
|
|
2453
|
+
joinsStatement: query.innerJoinStatements,
|
|
2454
|
+
joinOnStatements: query.innerJoinOnStatements,
|
|
2455
|
+
dreamClass: query.dreamClass,
|
|
2456
|
+
previousAssociationTableOrAlias: this.baseSqlAlias,
|
|
2457
|
+
joinType: 'inner',
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
if (!isEmpty(query.leftJoinStatements)) {
|
|
2461
|
+
kyselyQuery = query.recursivelyJoin({
|
|
2462
|
+
query: kyselyQuery,
|
|
2463
|
+
joinsStatement: query.leftJoinStatements,
|
|
2464
|
+
joinOnStatements: query.leftJoinOnStatements,
|
|
2465
|
+
dreamClass: query.dreamClass,
|
|
2466
|
+
previousAssociationTableOrAlias: this.baseSqlAlias,
|
|
2467
|
+
joinType: 'left',
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
if (query.whereStatements.length || query.whereNotStatements.length || query.whereAnyStatements.length) {
|
|
2471
|
+
kyselyQuery = kyselyQuery.where((eb) => eb.and([
|
|
2472
|
+
...this.aliasWhereStatements(query.whereStatements, query.baseSqlAlias).map(whereStatement => this.whereStatementToExpressionWrapper(eb, whereStatement, {
|
|
2473
|
+
disallowSimilarityOperator: false,
|
|
2474
|
+
})),
|
|
2475
|
+
...this.aliasWhereStatements(query.whereNotStatements, query.baseSqlAlias).map(whereNotStatement => this.whereStatementToExpressionWrapper(eb, whereNotStatement, { negate: true })),
|
|
2476
|
+
...query.whereAnyStatements.map(whereAnyStatements => eb.or(this.aliasWhereStatements(whereAnyStatements, query.baseSqlAlias).map(whereAnyStatement => this.whereStatementToExpressionWrapper(eb, whereAnyStatement)))),
|
|
2477
|
+
]));
|
|
2478
|
+
}
|
|
2479
|
+
return kyselyQuery;
|
|
2480
|
+
}
|
|
2481
|
+
checkForQueryViolations() {
|
|
2482
|
+
const invalidWhereNotClauses = this.similarityStatementBuilder().whereNotStatementsWithSimilarityClauses();
|
|
2483
|
+
if (invalidWhereNotClauses.length) {
|
|
2484
|
+
const { tableName, columnName, opsStatement } = invalidWhereNotClauses[0];
|
|
2485
|
+
throw new CannotNegateSimilarityClause(tableName, columnName, opsStatement.value);
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
aliasWhereStatements(whereStatements, alias) {
|
|
2489
|
+
return whereStatements.map(whereStatement => this.aliasWhereStatement(whereStatement, alias));
|
|
2490
|
+
}
|
|
2491
|
+
aliasWhereStatement(whereStatement, alias) {
|
|
2492
|
+
return Object.keys(whereStatement).reduce((aliasedWhere, key) => {
|
|
2493
|
+
aliasedWhere[this.namespaceColumn(key, alias)] = whereStatement[key];
|
|
2494
|
+
return aliasedWhere;
|
|
2495
|
+
}, {});
|
|
2496
|
+
}
|
|
2497
|
+
rawifiedSelfOnClause({ associationAlias, selfAlias, selfOnClause, }) {
|
|
2498
|
+
const alphanumericUnderscoreRegexp = /[^a-zA-Z0-9_]/g;
|
|
2499
|
+
selfAlias = selfAlias.replace(alphanumericUnderscoreRegexp, '');
|
|
2500
|
+
return Object.keys(selfOnClause).reduce((acc, key) => {
|
|
2501
|
+
const selfColumn = selfOnClause[key]?.replace(alphanumericUnderscoreRegexp, '');
|
|
2502
|
+
if (!selfColumn)
|
|
2503
|
+
return acc;
|
|
2504
|
+
acc[this.namespaceColumn(key, associationAlias)] = sql.raw(`"${snakeify(selfAlias)}"."${snakeify(selfColumn)}"`);
|
|
2505
|
+
return acc;
|
|
2506
|
+
}, {});
|
|
2507
|
+
}
|
|
2508
|
+
buildDelete() {
|
|
2509
|
+
const kyselyQuery = this.dbFor('delete').deleteFrom(this.baseSqlAlias);
|
|
2510
|
+
const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
|
|
2511
|
+
return results.clone.buildCommon(results.kyselyQuery);
|
|
2512
|
+
}
|
|
2513
|
+
buildSelect({ bypassSelectAll = false, bypassOrder = false, columns, } = {}) {
|
|
2514
|
+
let kyselyQuery;
|
|
2515
|
+
if (this.baseSelectQuery) {
|
|
2516
|
+
kyselyQuery = (this.connectionOverride
|
|
2517
|
+
? this.baseSelectQuery.connection(this.connectionOverride)
|
|
2518
|
+
: this.baseSelectQuery).buildSelect({ bypassSelectAll: true });
|
|
2519
|
+
}
|
|
2520
|
+
else {
|
|
2521
|
+
const from = this.baseSqlAlias === this.tableName ? this.tableName : `${this.tableName} as ${this.baseSqlAlias}`;
|
|
2522
|
+
kyselyQuery = this.dbFor('select').selectFrom(from);
|
|
2523
|
+
}
|
|
2524
|
+
if (this.distinctColumn) {
|
|
2525
|
+
kyselyQuery = kyselyQuery.distinctOn(this.distinctColumn);
|
|
2526
|
+
}
|
|
2527
|
+
kyselyQuery = this.buildCommon(kyselyQuery);
|
|
2528
|
+
kyselyQuery = this.conditionallyAttachSimilarityColumnsToSelect(kyselyQuery, {
|
|
2529
|
+
bypassOrder: bypassOrder || !!this.distinctColumn,
|
|
2530
|
+
});
|
|
2531
|
+
if (this.orderStatements.length && !bypassOrder) {
|
|
2532
|
+
this.orderStatements.forEach(orderStatement => {
|
|
2533
|
+
kyselyQuery = kyselyQuery.orderBy(this.namespaceColumn(orderStatement.column), orderByDirection(orderStatement.direction));
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
if (this.limitStatement)
|
|
2537
|
+
kyselyQuery = kyselyQuery.limit(this.limitStatement);
|
|
2538
|
+
if (this.offsetStatement)
|
|
2539
|
+
kyselyQuery = kyselyQuery.offset(this.offsetStatement);
|
|
2540
|
+
if (columns) {
|
|
2541
|
+
kyselyQuery = kyselyQuery.select(this.columnsWithRequiredLoadColumns(columns).map(column => this.namespaceColumn(column)));
|
|
2542
|
+
}
|
|
2543
|
+
else if (!bypassSelectAll) {
|
|
2544
|
+
kyselyQuery = kyselyQuery.selectAll(this.baseSqlAlias);
|
|
2545
|
+
}
|
|
2546
|
+
return kyselyQuery;
|
|
2547
|
+
}
|
|
2548
|
+
columnsWithRequiredLoadColumns(columns) {
|
|
2549
|
+
return uniq(compact([this.dreamClass.primaryKey, this.dreamClass['isSTIBase'] ? 'type' : null, ...columns]));
|
|
2550
|
+
}
|
|
2551
|
+
buildUpdate(attributes) {
|
|
2552
|
+
let kyselyQuery = this.dbFor('update')
|
|
2553
|
+
.updateTable(this.tableName)
|
|
2554
|
+
.set(attributes);
|
|
2555
|
+
kyselyQuery = this.conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery);
|
|
2556
|
+
const results = this.attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery);
|
|
2557
|
+
return results.clone.buildCommon(results.kyselyQuery);
|
|
2558
|
+
}
|
|
2559
|
+
attachLimitAndOrderStatementsToNonSelectQuery(kyselyQuery) {
|
|
2560
|
+
if (this.limitStatement || this.orderStatements.length) {
|
|
2561
|
+
kyselyQuery = kyselyQuery.where((eb) => {
|
|
2562
|
+
const subquery = this.nestedSelect(this.dreamInstance.primaryKey);
|
|
2563
|
+
return eb(this.dreamInstance.primaryKey, 'in', subquery);
|
|
2564
|
+
});
|
|
2565
|
+
return {
|
|
2566
|
+
kyselyQuery,
|
|
2567
|
+
clone: this.clone({ where: null, whereNot: null, order: null, limit: null }),
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
return { kyselyQuery, clone: this };
|
|
2571
|
+
}
|
|
2572
|
+
get hasSimilarityClauses() {
|
|
2573
|
+
return this.similarityStatementBuilder().hasSimilarityClauses;
|
|
2574
|
+
}
|
|
2575
|
+
similarityStatementBuilder() {
|
|
2576
|
+
return new SimilarityBuilder(this.dreamInstance, {
|
|
2577
|
+
where: [...this.whereStatements],
|
|
2578
|
+
whereNot: [...this.whereNotStatements],
|
|
2579
|
+
joinOnStatements: this.innerJoinOnStatements,
|
|
2580
|
+
transaction: this.dreamTransaction,
|
|
2581
|
+
connection: this.connectionOverride,
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2584
|
+
conditionallyAttachSimilarityColumnsToSelect(kyselyQuery, { bypassOrder = false } = {}) {
|
|
2585
|
+
const similarityBuilder = this.similarityStatementBuilder();
|
|
2586
|
+
if (similarityBuilder.hasSimilarityClauses) {
|
|
2587
|
+
kyselyQuery = similarityBuilder.select(kyselyQuery, { bypassOrder });
|
|
2588
|
+
}
|
|
2589
|
+
return kyselyQuery;
|
|
2590
|
+
}
|
|
2591
|
+
conditionallyAttachSimilarityColumnsToUpdate(kyselyQuery) {
|
|
2592
|
+
const similarityBuilder = this.similarityStatementBuilder();
|
|
2593
|
+
if (similarityBuilder.hasSimilarityClauses) {
|
|
2594
|
+
kyselyQuery = similarityBuilder.update(kyselyQuery);
|
|
2595
|
+
}
|
|
2596
|
+
return kyselyQuery;
|
|
2597
|
+
}
|
|
2598
|
+
invertOrder() {
|
|
2599
|
+
let query = this.clone({ order: null });
|
|
2600
|
+
for (const orderStatement of this.orderStatements) {
|
|
2601
|
+
query = query.order({
|
|
2602
|
+
[orderStatement.column]: orderStatement.direction === 'desc' ? 'asc' : 'desc',
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
return query;
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
function getSourceAssociation(dream, sourceName) {
|
|
2609
|
+
if (!dream)
|
|
2610
|
+
return;
|
|
2611
|
+
if (!sourceName)
|
|
2612
|
+
return;
|
|
2613
|
+
return (dream['getAssociationMetadata'](sourceName) ||
|
|
2614
|
+
dream['getAssociationMetadata'](pluralize.singular(sourceName)));
|
|
2615
|
+
}
|