@rvoh/dream 1.0.3 → 1.0.5
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/CHANGELOG.md +16 -4
- package/dist/cjs/src/bin/helpers/sync.js +3 -1
- package/dist/cjs/src/cli/CliFileWriter.js +39 -0
- package/dist/cjs/src/cli/logger/DreamCliLogger.js +5 -0
- package/dist/cjs/src/decorators/field/association/shared.js +2 -2
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +84 -34
- package/dist/cjs/src/errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.js +19 -0
- package/dist/cjs/src/errors/associations/CannotAssociateThroughMultiplePolymorphics.js +27 -0
- package/dist/cjs/src/errors/associations/MissingThroughAssociationSource.js +1 -1
- package/dist/cjs/src/helpers/cli/SchemaBuilder.js +2 -1
- package/dist/cjs/src/index.js +4 -2
- package/dist/esm/src/bin/helpers/sync.js +3 -1
- package/dist/esm/src/cli/CliFileWriter.js +35 -0
- package/dist/esm/src/cli/logger/DreamCliLogger.js +5 -0
- package/dist/esm/src/decorators/field/association/shared.js +2 -2
- package/dist/esm/src/dream/QueryDriver/Kysely.js +84 -34
- package/dist/esm/src/errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.js +16 -0
- package/dist/esm/src/errors/associations/CannotAssociateThroughMultiplePolymorphics.js +24 -0
- package/dist/esm/src/errors/associations/MissingThroughAssociationSource.js +1 -1
- package/dist/esm/src/helpers/cli/SchemaBuilder.js +2 -1
- package/dist/esm/src/index.js +1 -0
- package/dist/types/src/cli/CliFileWriter.d.ts +9 -0
- package/dist/types/src/cli/logger/DreamCliLogger.d.ts +1 -0
- package/dist/types/src/decorators/Decorators.d.ts +6 -6
- package/dist/types/src/decorators/field/association/HasMany.d.ts +3 -3
- package/dist/types/src/decorators/field/association/HasOne.d.ts +3 -3
- package/dist/types/src/errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.d.ts +12 -0
- package/dist/types/src/errors/associations/CannotAssociateThroughMultiplePolymorphics.d.ts +17 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/types/associations/belongsTo.d.ts +3 -1
- package/dist/types/src/types/associations/belongsTo.ts +4 -1
- package/dist/types/src/types/associations/hasMany.d.ts +3 -3
- package/dist/types/src/types/associations/hasMany.ts +7 -3
- package/dist/types/src/types/associations/hasOne.d.ts +3 -3
- package/dist/types/src/types/associations/hasOne.ts +6 -3
- package/dist/types/src/types/associations/shared.d.ts +6 -6
- package/dist/types/src/types/associations/shared.ts +24 -6
- package/dist/types/src/types/dream.d.ts +1 -1
- package/dist/types/src/types/dream.ts +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Benchmark.html +2 -2
- package/docs/classes/CalendarDate.html +2 -2
- package/docs/classes/CliFileWriter.html +8 -0
- package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/Decorators.html +19 -19
- package/docs/classes/Dream.html +137 -137
- package/docs/classes/DreamApp.html +4 -4
- package/docs/classes/DreamBin.html +2 -2
- package/docs/classes/DreamCLI.html +4 -4
- package/docs/classes/DreamImporter.html +2 -2
- package/docs/classes/DreamLogos.html +2 -2
- package/docs/classes/DreamMigrationHelpers.html +7 -7
- package/docs/classes/DreamSerializerBuilder.html +8 -8
- package/docs/classes/DreamTransaction.html +2 -2
- package/docs/classes/Encrypt.html +2 -2
- package/docs/classes/Env.html +2 -2
- package/docs/classes/GlobalNameNotSet.html +3 -3
- package/docs/classes/NonLoadedAssociation.html +3 -3
- package/docs/classes/ObjectSerializerBuilder.html +8 -8
- package/docs/classes/Query.html +60 -60
- package/docs/classes/Range.html +2 -2
- package/docs/classes/RecordNotFound.html +3 -3
- package/docs/classes/ValidationError.html +3 -3
- package/docs/functions/DreamSerializer.html +1 -1
- package/docs/functions/ObjectSerializer.html +1 -1
- package/docs/functions/ReplicaSafe.html +1 -1
- package/docs/functions/STI.html +1 -1
- package/docs/functions/SoftDelete.html +1 -1
- package/docs/functions/camelize.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeepSafe.html +1 -1
- package/docs/functions/closeAllDbConnections.html +1 -1
- package/docs/functions/compact.html +1 -1
- package/docs/functions/dreamDbConnections.html +1 -1
- package/docs/functions/dreamPath.html +1 -1
- package/docs/functions/expandStiClasses.html +1 -1
- package/docs/functions/generateDream.html +1 -1
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/groupBy.html +1 -1
- package/docs/functions/hyphenize.html +1 -1
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
- package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
- package/docs/functions/intersection.html +1 -1
- package/docs/functions/isDreamSerializer.html +1 -1
- package/docs/functions/isEmpty.html +1 -1
- package/docs/functions/loadRepl.html +1 -1
- package/docs/functions/lookupClassByGlobalName.html +1 -1
- package/docs/functions/normalizeUnicode.html +1 -1
- package/docs/functions/pascalize.html +1 -1
- package/docs/functions/pgErrorType.html +1 -1
- package/docs/functions/range-1.html +1 -1
- package/docs/functions/relativeDreamPath.html +1 -1
- package/docs/functions/round.html +1 -1
- package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/sharedPathPrefix.html +1 -1
- package/docs/functions/snakeify.html +1 -1
- package/docs/functions/sort.html +1 -1
- package/docs/functions/sortBy.html +1 -1
- package/docs/functions/sortObjectByKey.html +1 -1
- package/docs/functions/sortObjectByValue.html +1 -1
- package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
- package/docs/functions/uncapitalize.html +1 -1
- package/docs/functions/uniq.html +1 -1
- package/docs/functions/untypedDb.html +1 -1
- package/docs/functions/validateColumn.html +1 -1
- package/docs/functions/validateTable.html +1 -1
- package/docs/interfaces/BelongsToStatement.html +2 -2
- package/docs/interfaces/DecoratorContext.html +2 -2
- package/docs/interfaces/DreamAppInitOptions.html +2 -2
- package/docs/interfaces/DreamAppOpts.html +2 -2
- package/docs/interfaces/EncryptOptions.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/OpenapiDescription.html +2 -2
- package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/SerializerRendererOpts.html +2 -2
- package/docs/modules.html +1 -0
- package/docs/types/Camelized.html +1 -1
- package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/DateTime.html +1 -1
- package/docs/types/DbConnectionType.html +1 -1
- package/docs/types/DbTypes.html +1 -1
- package/docs/types/DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/DreamAssociationMetadata.html +1 -1
- package/docs/types/DreamAttributes.html +1 -1
- package/docs/types/DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/DreamClassColumn.html +1 -1
- package/docs/types/DreamColumn.html +1 -1
- package/docs/types/DreamColumnNames.html +1 -1
- package/docs/types/DreamLogLevel.html +1 -1
- package/docs/types/DreamLogger.html +1 -1
- package/docs/types/DreamModelSerializerType.html +1 -1
- package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/DreamParamSafeAttributes.html +1 -1
- package/docs/types/DreamParamSafeColumnNames.html +1 -1
- package/docs/types/DreamSerializable.html +1 -1
- package/docs/types/DreamSerializableArray.html +1 -1
- package/docs/types/DreamSerializerKey.html +1 -1
- package/docs/types/DreamSerializers.html +1 -1
- package/docs/types/DreamTableSchema.html +1 -1
- package/docs/types/DreamVirtualColumns.html +1 -1
- package/docs/types/EncryptAlgorithm.html +1 -1
- package/docs/types/HasManyStatement.html +1 -1
- package/docs/types/HasOneStatement.html +1 -1
- package/docs/types/Hyphenized.html +1 -1
- package/docs/types/IdType.html +1 -1
- package/docs/types/OpenapiAllTypes.html +1 -1
- package/docs/types/OpenapiFormats.html +1 -1
- package/docs/types/OpenapiNumberFormats.html +1 -1
- package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiSchemaArray.html +1 -1
- package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/OpenapiSchemaBase.html +1 -1
- package/docs/types/OpenapiSchemaBody.html +1 -1
- package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/OpenapiSchemaInteger.html +1 -1
- package/docs/types/OpenapiSchemaNull.html +1 -1
- package/docs/types/OpenapiSchemaNumber.html +1 -1
- package/docs/types/OpenapiSchemaObject.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaString.html +1 -1
- package/docs/types/OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiTypeField.html +1 -1
- package/docs/types/Pascalized.html +1 -1
- package/docs/types/PrimaryKeyType.html +1 -1
- package/docs/types/RoundingPrecision.html +1 -1
- package/docs/types/SerializerCasing.html +1 -1
- package/docs/types/SimpleObjectSerializerType.html +1 -1
- package/docs/types/Snakeified.html +1 -1
- package/docs/types/Timestamp.html +1 -1
- package/docs/types/UpdateableAssociationProperties.html +1 -1
- package/docs/types/UpdateableProperties.html +1 -1
- package/docs/types/ValidationType.html +1 -1
- package/docs/types/ViewModel.html +1 -1
- package/docs/types/ViewModelClass.html +1 -1
- package/docs/types/WhereStatementForDream.html +1 -1
- package/docs/types/WhereStatementForDreamClass.html +1 -1
- package/docs/variables/DateTime-1.html +1 -1
- package/docs/variables/DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/DreamConst.html +1 -1
- package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
- package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/ops.html +1 -1
- package/docs/variables/primaryKeyTypes.html +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
## 1.0.5
|
|
2
2
|
|
|
3
|
-
-
|
|
3
|
+
- Support HasOne/Many through polymorphic BelongsTo (trick is that it uses the associated model from the HasOne/Many to limit the BelongsTo to a single associated class / table)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- Fix HasOne/Many through source type
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- sync process is now fail-safe, leveraging a utility which caches old copies of files before writing to them. If an exception is thrown at any point during the process, dream will revert all files written using the new `CliFileWriter` class
|
|
8
|
+
|
|
9
|
+
## 1.0.4
|
|
10
|
+
|
|
11
|
+
- properly exclude type from `DreamParamSafeColumnNames`
|
|
8
12
|
|
|
9
13
|
## 1.0.3
|
|
10
14
|
|
|
11
15
|
- exclude type from `DreamParamSafeColumnNames`
|
|
16
|
+
|
|
17
|
+
## 1.0.2
|
|
18
|
+
|
|
19
|
+
- stop computing foreign keys in schema builder when building schema for through associations
|
|
20
|
+
|
|
21
|
+
## 1.0.1
|
|
22
|
+
|
|
23
|
+
- [bug] fix preloading STI model via polymporhic association (polymorphic type was being altered to the STI child rather than left as the STI base)
|
|
@@ -12,11 +12,13 @@ const EnvInternal_js_1 = require("../../helpers/EnvInternal.js");
|
|
|
12
12
|
const dreamPath_js_1 = require("../../helpers/path/dreamPath.js");
|
|
13
13
|
const snakeify_js_1 = require("../../helpers/snakeify.js");
|
|
14
14
|
const sspawn_js_1 = require("../../helpers/sspawn.js");
|
|
15
|
+
const CliFileWriter_js_1 = require("../../cli/CliFileWriter.js");
|
|
15
16
|
async function writeSyncFile() {
|
|
16
17
|
const dreamApp = index_js_2.default.getOrFail();
|
|
17
18
|
const dbConf = dreamApp.dbConnectionConfig('primary');
|
|
18
19
|
const dbSyncFilePath = path.join((0, dreamPath_js_1.default)('types'), 'db.ts');
|
|
19
20
|
const absoluteDbSyncPath = path.join(dreamApp.projectRoot, dbSyncFilePath);
|
|
21
|
+
await CliFileWriter_js_1.CliFileWriter.cache(absoluteDbSyncPath);
|
|
20
22
|
await (0, sspawn_js_1.default)(`kysely-codegen --dialect=postgres --url=postgres://${dbConf.user}:${dbConf.password}@${dbConf.host}:${dbConf.port}/${dbConf.name} --out-file=${absoluteDbSyncPath}`, {
|
|
21
23
|
onStdout: message => {
|
|
22
24
|
index_js_1.default.logger.logContinueProgress((0, colorize_js_1.default)(`[db]`, { color: 'cyan' }) + ' ' + message, {
|
|
@@ -28,7 +30,7 @@ async function writeSyncFile() {
|
|
|
28
30
|
// from the dist folder, whereas dirname here is pointing to true src folder.
|
|
29
31
|
const file = (await fs.readFile(absoluteDbSyncPath)).toString();
|
|
30
32
|
const enhancedSchema = enhanceSchema(file);
|
|
31
|
-
await
|
|
33
|
+
await CliFileWriter_js_1.CliFileWriter.write(absoluteDbSyncPath, enhancedSchema);
|
|
32
34
|
}
|
|
33
35
|
// begin: schema helpers
|
|
34
36
|
function enhanceSchema(file) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliFileWriter = void 0;
|
|
4
|
+
const fs = require("node:fs/promises");
|
|
5
|
+
const index_js_1 = require("./index.js");
|
|
6
|
+
class CliFileWriter {
|
|
7
|
+
static async write(filepath, contents) {
|
|
8
|
+
await cliFileWriter.write(filepath, contents);
|
|
9
|
+
}
|
|
10
|
+
static async revert() {
|
|
11
|
+
await cliFileWriter.revert();
|
|
12
|
+
}
|
|
13
|
+
static async cache(filepath) {
|
|
14
|
+
await cliFileWriter.cache(filepath);
|
|
15
|
+
}
|
|
16
|
+
fileCache = {};
|
|
17
|
+
async write(filepath, contents) {
|
|
18
|
+
// if we have manually backed up this file, or else this file
|
|
19
|
+
// has been written to twice in one CLI session, we want
|
|
20
|
+
// to preserve the original backup, so we do not attempt
|
|
21
|
+
// to cache a second time
|
|
22
|
+
if (!this.fileCache[filepath])
|
|
23
|
+
await this.cache(filepath);
|
|
24
|
+
await fs.writeFile(filepath, contents);
|
|
25
|
+
}
|
|
26
|
+
async revert() {
|
|
27
|
+
const filepaths = Object.keys(this.fileCache);
|
|
28
|
+
for (const filepath of filepaths) {
|
|
29
|
+
index_js_1.default.logger.logContinueProgress(`reverting ${filepath}`);
|
|
30
|
+
await fs.writeFile(filepath, this.fileCache[filepath]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async cache(filepath) {
|
|
34
|
+
const originalContents = (await fs.readFile(filepath)).toString();
|
|
35
|
+
this.fileCache[filepath] = originalContents;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.CliFileWriter = CliFileWriter;
|
|
39
|
+
const cliFileWriter = new CliFileWriter();
|
|
@@ -10,6 +10,11 @@ class DreamCliLogger {
|
|
|
10
10
|
});
|
|
11
11
|
loggable.render();
|
|
12
12
|
}
|
|
13
|
+
async logProgress(text, cb, { logPrefix = '✺ ┌', logPrefixColor, logPrefixBgColor } = {}) {
|
|
14
|
+
this.log(text, { logPrefix, logPrefixColor, logPrefixBgColor });
|
|
15
|
+
await cb();
|
|
16
|
+
this.logEndProgress();
|
|
17
|
+
}
|
|
13
18
|
logStartProgress(text, { logPrefix = '✺ ┌', logPrefixColor, logPrefixBgColor } = {}) {
|
|
14
19
|
this.log(text, { logPrefix, logPrefixColor, logPrefixBgColor });
|
|
15
20
|
}
|
|
@@ -98,12 +98,12 @@ function applyGetterAndSetter(target, partialAssociation, { foreignKeyBase, isBe
|
|
|
98
98
|
function associationPrimaryKeyAccessors(partialAssociation, dreamClass) {
|
|
99
99
|
return {
|
|
100
100
|
...partialAssociation,
|
|
101
|
-
primaryKey(associationInstance) {
|
|
101
|
+
primaryKey(associationInstance, { associatedClassOverride } = {}) {
|
|
102
102
|
if (this.primaryKeyOverride)
|
|
103
103
|
return this.primaryKeyOverride;
|
|
104
104
|
if (associationInstance)
|
|
105
105
|
return associationInstance.primaryKey;
|
|
106
|
-
const associationClass = this.modelCB();
|
|
106
|
+
const associationClass = associatedClassOverride ?? this.modelCB();
|
|
107
107
|
if (Array.isArray(associationClass)) {
|
|
108
108
|
throw new Error(`
|
|
109
109
|
Cannot lookup primaryKey on polymorphic association:
|
|
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const kysely_1 = require("kysely");
|
|
4
4
|
const pluralize_esm_1 = require("pluralize-esm");
|
|
5
5
|
const sync_js_1 = require("../../bin/helpers/sync.js");
|
|
6
|
+
const CliFileWriter_js_1 = require("../../cli/CliFileWriter.js");
|
|
6
7
|
const index_js_1 = require("../../cli/index.js");
|
|
7
8
|
const index_js_2 = require("../../db/index.js");
|
|
8
9
|
const associationToGetterSetterProp_js_1 = require("../../decorators/field/association/associationToGetterSetterProp.js");
|
|
9
10
|
const PackageManager_js_1 = require("../../dream-app/helpers/PackageManager.js");
|
|
10
11
|
const index_js_3 = require("../../dream-app/index.js");
|
|
11
|
-
const
|
|
12
|
+
const ArrayTargetsIncompatibleWithThroughAssociation_js_1 = require("../../errors/associations/ArrayTargetsIncompatibleWithThroughAssociation.js");
|
|
13
|
+
const CannotAssociateThroughMultiplePolymorphics_js_1 = require("../../errors/associations/CannotAssociateThroughMultiplePolymorphics.js");
|
|
12
14
|
const CannotJoinPolymorphicBelongsToError_js_1 = require("../../errors/associations/CannotJoinPolymorphicBelongsToError.js");
|
|
13
15
|
const JoinAttemptedOnMissingAssociation_js_1 = require("../../errors/associations/JoinAttemptedOnMissingAssociation.js");
|
|
14
16
|
const MissingRequiredAssociationAndClause_js_1 = require("../../errors/associations/MissingRequiredAssociationAndClause.js");
|
|
@@ -94,33 +96,41 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
94
96
|
await (0, generateMigration_js_1.default)({ migrationName, columnsWithTypes });
|
|
95
97
|
}
|
|
96
98
|
static async sync(onSync, options = {}) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (schemaBuilder.hasForeignKeyError && !options?.schemaOnly) {
|
|
107
|
-
index_js_1.default.logger.logStartProgress('triggering resync to correct for foreign key errors...');
|
|
108
|
-
// TODO: make this customizable to enable dream apps to separate
|
|
109
|
-
const cliCmd = EnvInternal_js_1.default.boolean('DREAM_CORE_DEVELOPMENT') ? 'dream' : 'psy';
|
|
110
|
-
await index_js_1.default.spawn(PackageManager_js_1.default.runCmd(`${cliCmd} sync --schema-only`), {
|
|
111
|
-
onStdout: str => {
|
|
112
|
-
index_js_1.default.logger.logContinueProgress(`${str}`, {
|
|
113
|
-
logPrefix: ' ├ [resync]',
|
|
114
|
-
logPrefixColor: 'blue',
|
|
115
|
-
});
|
|
116
|
-
},
|
|
99
|
+
try {
|
|
100
|
+
if (!options?.schemaOnly) {
|
|
101
|
+
await index_js_1.default.logger.logProgress('writing db schema...', async () => {
|
|
102
|
+
await (0, sync_js_1.default)();
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const schemaBuilder = new SchemaBuilder_js_1.default();
|
|
106
|
+
await index_js_1.default.logger.logProgress('building dream schema...', async () => {
|
|
107
|
+
await schemaBuilder.build();
|
|
117
108
|
});
|
|
118
|
-
|
|
109
|
+
if (schemaBuilder.hasForeignKeyError && !options?.schemaOnly) {
|
|
110
|
+
await index_js_1.default.logger.logProgress('triggering resync to correct for foreign key errors...', async () => {
|
|
111
|
+
// TODO: make this customizable to enable dream apps to separate
|
|
112
|
+
const cliCmd = EnvInternal_js_1.default.boolean('DREAM_CORE_DEVELOPMENT') ? 'dream' : 'psy';
|
|
113
|
+
await index_js_1.default.spawn(PackageManager_js_1.default.runCmd(`${cliCmd} sync --schema-only`), {
|
|
114
|
+
onStdout: str => {
|
|
115
|
+
index_js_1.default.logger.logContinueProgress(`${str}`, {
|
|
116
|
+
logPrefix: ' ├ [resync]',
|
|
117
|
+
logPrefixColor: 'blue',
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (!options?.schemaOnly) {
|
|
124
|
+
// intentionally leaving logs off here, since it allows other
|
|
125
|
+
// onSync handlers to determine their own independent logging approach
|
|
126
|
+
await onSync();
|
|
127
|
+
}
|
|
119
128
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error(error);
|
|
131
|
+
await index_js_1.default.logger.logProgress('sync failed, reverting file contents...', async () => {
|
|
132
|
+
await CliFileWriter_js_1.CliFileWriter.revert();
|
|
133
|
+
});
|
|
124
134
|
}
|
|
125
135
|
}
|
|
126
136
|
/**
|
|
@@ -1089,6 +1099,8 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1089
1099
|
currentAssociationTableOrAlias,
|
|
1090
1100
|
joinAndStatements,
|
|
1091
1101
|
joinType,
|
|
1102
|
+
baseThroughAssociation: undefined,
|
|
1103
|
+
polymorphicCount: { count: 0 },
|
|
1092
1104
|
});
|
|
1093
1105
|
query = results.query;
|
|
1094
1106
|
const association = results.association;
|
|
@@ -1284,7 +1296,7 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1284
1296
|
* the `through` association are only added when the recursion returns
|
|
1285
1297
|
* back to the association that kicked off the through associations.
|
|
1286
1298
|
*/
|
|
1287
|
-
joinsBridgeThroughAssociations({ query, dreamClass, association, previousAssociationTableOrAlias, throughAssociations, joinType, }) {
|
|
1299
|
+
joinsBridgeThroughAssociations({ query, dreamClass, association, previousAssociationTableOrAlias, throughAssociations, joinType, baseThroughAssociation, polymorphicCount, }) {
|
|
1288
1300
|
if (association.type === 'BelongsTo' || !association.through) {
|
|
1289
1301
|
return {
|
|
1290
1302
|
query,
|
|
@@ -1307,6 +1319,8 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1307
1319
|
currentAssociationTableOrAlias: association.through,
|
|
1308
1320
|
throughAssociations,
|
|
1309
1321
|
joinType,
|
|
1322
|
+
baseThroughAssociation,
|
|
1323
|
+
polymorphicCount,
|
|
1310
1324
|
});
|
|
1311
1325
|
// The through association has both a `through` and a `source`. The `source`
|
|
1312
1326
|
// is the association on the model that has now been joined. In our example,
|
|
@@ -1322,6 +1336,8 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1322
1336
|
previousAssociationTableOrAlias: throughAssociation.as,
|
|
1323
1337
|
throughAssociations,
|
|
1324
1338
|
joinType,
|
|
1339
|
+
baseThroughAssociation,
|
|
1340
|
+
polymorphicCount,
|
|
1325
1341
|
});
|
|
1326
1342
|
}
|
|
1327
1343
|
else {
|
|
@@ -1351,7 +1367,7 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1351
1367
|
});
|
|
1352
1368
|
const throughClass = throughAssociation.modelCB();
|
|
1353
1369
|
if (Array.isArray(throughClass))
|
|
1354
|
-
throw new
|
|
1370
|
+
throw new ArrayTargetsIncompatibleWithThroughAssociation_js_1.default({
|
|
1355
1371
|
dreamClass,
|
|
1356
1372
|
association,
|
|
1357
1373
|
});
|
|
@@ -1375,18 +1391,23 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1375
1391
|
* the `through` association are only added when the recursion returns
|
|
1376
1392
|
* back to the association that kicked off the through associations.
|
|
1377
1393
|
*/
|
|
1378
|
-
applyOneJoin({ query, dreamClass, previousAssociationTableOrAlias, currentAssociationTableOrAlias, joinAndStatements = {}, throughAssociations = [], joinType, }) {
|
|
1394
|
+
applyOneJoin({ query, dreamClass, previousAssociationTableOrAlias, currentAssociationTableOrAlias, joinAndStatements = {}, throughAssociations = [], joinType, baseThroughAssociation, polymorphicCount, }) {
|
|
1379
1395
|
const { name, alias } = (0, extractAssociationMetadataFromAssociationName_js_1.default)(currentAssociationTableOrAlias);
|
|
1380
1396
|
const joinAndStatement = joinAndStatements[currentAssociationTableOrAlias];
|
|
1381
1397
|
previousAssociationTableOrAlias = (0, extractAssociationMetadataFromAssociationName_js_1.default)(previousAssociationTableOrAlias).alias;
|
|
1382
1398
|
currentAssociationTableOrAlias = alias;
|
|
1383
1399
|
let association = dreamClass['getAssociationMetadata'](name);
|
|
1400
|
+
if (association?.polymorphic)
|
|
1401
|
+
polymorphicCount.count++;
|
|
1384
1402
|
if (!association) {
|
|
1385
1403
|
throw new JoinAttemptedOnMissingAssociation_js_1.default({
|
|
1386
1404
|
dreamClass,
|
|
1387
1405
|
associationName: currentAssociationTableOrAlias,
|
|
1388
1406
|
});
|
|
1389
1407
|
}
|
|
1408
|
+
baseThroughAssociation ??= association.through
|
|
1409
|
+
? association
|
|
1410
|
+
: undefined;
|
|
1390
1411
|
const results = this.joinsBridgeThroughAssociations({
|
|
1391
1412
|
query,
|
|
1392
1413
|
dreamClass,
|
|
@@ -1394,11 +1415,23 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1394
1415
|
previousAssociationTableOrAlias,
|
|
1395
1416
|
throughAssociations,
|
|
1396
1417
|
joinType,
|
|
1418
|
+
baseThroughAssociation,
|
|
1419
|
+
polymorphicCount,
|
|
1397
1420
|
});
|
|
1398
1421
|
query = results.query;
|
|
1399
1422
|
dreamClass = results.dreamClass;
|
|
1400
1423
|
association = results.association;
|
|
1424
|
+
if (association?.polymorphic)
|
|
1425
|
+
polymorphicCount.count++;
|
|
1401
1426
|
const timeToApplyThroughAssociations = throughAssociations.length && throughAssociations[0]?.source === association.as;
|
|
1427
|
+
const baseThroughAssociationToApply = association.polymorphic ? baseThroughAssociation : undefined;
|
|
1428
|
+
if (baseThroughAssociationToApply && polymorphicCount.count > 1)
|
|
1429
|
+
throw new CannotAssociateThroughMultiplePolymorphics_js_1.default({
|
|
1430
|
+
dreamClass,
|
|
1431
|
+
association,
|
|
1432
|
+
innerJoinStatements: this.query['innerJoinStatements'],
|
|
1433
|
+
leftJoinStatements: this.query['leftJoinStatements'],
|
|
1434
|
+
});
|
|
1402
1435
|
const originalPreviousAssociationTableOrAlias = previousAssociationTableOrAlias;
|
|
1403
1436
|
previousAssociationTableOrAlias = results.previousAssociationTableOrAlias;
|
|
1404
1437
|
const throughClass = results.throughClass;
|
|
@@ -1436,19 +1469,34 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1436
1469
|
});
|
|
1437
1470
|
}
|
|
1438
1471
|
if (association.type === 'BelongsTo') {
|
|
1439
|
-
if (Array.isArray(association.modelCB()))
|
|
1472
|
+
if (!baseThroughAssociationToApply && Array.isArray(association.modelCB()))
|
|
1440
1473
|
throw new CannotJoinPolymorphicBelongsToError_js_1.default({
|
|
1441
1474
|
dreamClass,
|
|
1442
1475
|
association,
|
|
1443
1476
|
innerJoinStatements: this.query['innerJoinStatements'],
|
|
1444
1477
|
leftJoinStatements: this.query['leftJoinStatements'],
|
|
1445
1478
|
});
|
|
1446
|
-
const to = association.modelCB().table;
|
|
1479
|
+
const to = (baseThroughAssociationToApply ?? association).modelCB().table;
|
|
1447
1480
|
const joinTableExpression = currentAssociationTableOrAlias === to
|
|
1448
1481
|
? currentAssociationTableOrAlias
|
|
1449
1482
|
: `${to} as ${currentAssociationTableOrAlias}`;
|
|
1450
1483
|
query = query[(joinType === 'inner' ? 'innerJoin' : 'leftJoin')](joinTableExpression, (join) => {
|
|
1451
|
-
join = join.onRef(this.namespaceColumn(association.foreignKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.primaryKey(
|
|
1484
|
+
join = join.onRef(this.namespaceColumn(association.foreignKey(), previousAssociationTableOrAlias), '=', this.namespaceColumn(association.primaryKey(undefined, {
|
|
1485
|
+
associatedClassOverride: baseThroughAssociationToApply?.modelCB(),
|
|
1486
|
+
}), currentAssociationTableOrAlias));
|
|
1487
|
+
if (baseThroughAssociationToApply) {
|
|
1488
|
+
/**
|
|
1489
|
+
* At this point, all `through` associations have been bridged and a
|
|
1490
|
+
* real association has been reached that is a polymorphic BelongsTo (it
|
|
1491
|
+
* is polymorphic and has an array of target models). Join with that
|
|
1492
|
+
* table conditionally based on the polymorphic foreign key type,
|
|
1493
|
+
* namespaced to the name of that association (which we know from the
|
|
1494
|
+
* target of the final `through` association)
|
|
1495
|
+
*/
|
|
1496
|
+
join = join.on((eb) => this.whereStatementToExpressionWrapper(eb, this.aliasWhereStatement({
|
|
1497
|
+
[association.foreignKeyTypeField()]: baseThroughAssociationToApply.modelCB().sanitizedName,
|
|
1498
|
+
}, throughAssociations.at(-1).through)));
|
|
1499
|
+
}
|
|
1452
1500
|
if (timeToApplyThroughAssociations) {
|
|
1453
1501
|
throughAssociations.forEach((throughAssociation) => {
|
|
1454
1502
|
join = this.applyAssociationAndStatementsToJoinStatement({
|
|
@@ -1464,6 +1512,7 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1464
1512
|
join,
|
|
1465
1513
|
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
1466
1514
|
association,
|
|
1515
|
+
throughAssociatedClassOverride: baseThroughAssociationToApply?.modelCB(),
|
|
1467
1516
|
});
|
|
1468
1517
|
join = this.applyJoinAndStatement(join, joinAndStatement, currentAssociationTableOrAlias);
|
|
1469
1518
|
return join;
|
|
@@ -1505,6 +1554,7 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1505
1554
|
join,
|
|
1506
1555
|
tableNameOrAlias: currentAssociationTableOrAlias,
|
|
1507
1556
|
association,
|
|
1557
|
+
throughAssociatedClassOverride: baseThroughAssociationToApply?.modelCB(),
|
|
1508
1558
|
});
|
|
1509
1559
|
join = this.applyJoinAndStatement(join, joinAndStatement, currentAssociationTableOrAlias);
|
|
1510
1560
|
return join;
|
|
@@ -1594,9 +1644,9 @@ class KyselyQueryDriver extends Base_js_1.default {
|
|
|
1594
1644
|
if (missingRequiredWhereStatements.length)
|
|
1595
1645
|
throw new MissingRequiredAssociationAndClause_js_1.default(association, missingRequiredWhereStatements[0]);
|
|
1596
1646
|
}
|
|
1597
|
-
conditionallyApplyDefaultScopesDependentOnAssociation({ join, tableNameOrAlias, association, }) {
|
|
1647
|
+
conditionallyApplyDefaultScopesDependentOnAssociation({ join, tableNameOrAlias, association, throughAssociatedClassOverride, }) {
|
|
1598
1648
|
let scopesQuery = new Query_js_1.default(this.dreamInstance);
|
|
1599
|
-
const associationClass = association.modelCB();
|
|
1649
|
+
const associationClass = throughAssociatedClassOverride ?? association.modelCB();
|
|
1600
1650
|
const associationScopes = associationClass['scopes'].default;
|
|
1601
1651
|
for (const scope of associationScopes) {
|
|
1602
1652
|
if (!(0, shouldBypassDefaultScope_js_1.default)(scope.method, {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class ArrayTargetsIncompatibleWithThroughAssociation extends Error {
|
|
4
|
+
dreamClass;
|
|
5
|
+
association;
|
|
6
|
+
constructor({ dreamClass, association, }) {
|
|
7
|
+
super();
|
|
8
|
+
this.dreamClass = dreamClass;
|
|
9
|
+
this.association = association;
|
|
10
|
+
}
|
|
11
|
+
get message() {
|
|
12
|
+
return `
|
|
13
|
+
Through associations may not define an array of targets:
|
|
14
|
+
Dream class: ${this.dreamClass.sanitizedName}
|
|
15
|
+
Association: ${this.association.as}
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.default = ArrayTargetsIncompatibleWithThroughAssociation;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class CannotAssociateThroughMultiplePolymorphics extends Error {
|
|
4
|
+
dreamClass;
|
|
5
|
+
association;
|
|
6
|
+
innerJoinStatements;
|
|
7
|
+
leftJoinStatements;
|
|
8
|
+
constructor({ dreamClass, association, innerJoinStatements, leftJoinStatements, }) {
|
|
9
|
+
super();
|
|
10
|
+
this.dreamClass = dreamClass;
|
|
11
|
+
this.association = association;
|
|
12
|
+
this.innerJoinStatements = innerJoinStatements;
|
|
13
|
+
this.leftJoinStatements = leftJoinStatements;
|
|
14
|
+
}
|
|
15
|
+
get message() {
|
|
16
|
+
return `
|
|
17
|
+
Cannot associate through multiple polymorphic associations if one of them is a BelongsTo:
|
|
18
|
+
Dream class: ${this.dreamClass.sanitizedName}
|
|
19
|
+
Association: ${this.association.as}
|
|
20
|
+
Inner Join statements:
|
|
21
|
+
${JSON.stringify(this.innerJoinStatements, null, 2)}
|
|
22
|
+
Left Join statements:
|
|
23
|
+
${JSON.stringify(this.leftJoinStatements, null, 2)}
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.default = CannotAssociateThroughMultiplePolymorphics;
|
|
@@ -16,7 +16,7 @@ class MissingThroughAssociationSource extends Error {
|
|
|
16
16
|
|
|
17
17
|
\`${this.dreamClass.sanitizedName}\` association \`${this.association.through}\` points to \`${this.throughClass.sanitizedName}\`.
|
|
18
18
|
|
|
19
|
-
Dream expects association \`${this.association.source}\` to be
|
|
19
|
+
Dream expects association \`${this.association.source}\` to be defined on \`${this.throughClass.sanitizedName}\`, but \`${this.throughClass.sanitizedName}\` does not define association \`${this.association.source}\`.
|
|
20
20
|
|
|
21
21
|
There are two possible fixes:
|
|
22
22
|
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const kysely_1 = require("kysely");
|
|
4
4
|
const fs = require("node:fs/promises");
|
|
5
5
|
const path = require("node:path");
|
|
6
|
+
const CliFileWriter_js_1 = require("../../cli/CliFileWriter.js");
|
|
6
7
|
const dataTypes_js_1 = require("../../db/dataTypes.js");
|
|
7
8
|
const index_js_1 = require("../../db/index.js");
|
|
8
9
|
const index_js_2 = require("../../dream-app/index.js");
|
|
@@ -51,7 +52,7 @@ export const globalSchema = {
|
|
|
51
52
|
// ${schemaConstContent}
|
|
52
53
|
// `
|
|
53
54
|
const schemaPath = path.join(dreamApp.projectRoot, dreamApp.paths.types, 'dream.ts');
|
|
54
|
-
await
|
|
55
|
+
await CliFileWriter_js_1.CliFileWriter.write(schemaPath, newSchemaFileContents);
|
|
55
56
|
}
|
|
56
57
|
globalModelNames() {
|
|
57
58
|
const dreamApp = index_js_2.default.getOrFail();
|
package/dist/cjs/src/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = void 0;
|
|
3
|
+
exports.relativeDreamPath = exports.dreamPath = exports.pascalize = exports.normalizeUnicode = exports.loadRepl = exports.isEmpty = exports.intersection = exports.hyphenize = exports.groupBy = exports.globalClassNameFromFullyQualifiedModelName = exports.Env = exports.DreamLogos = exports.DateTime = exports.compact = exports.cloneDeepSafe = exports.generateDream = exports.capitalize = exports.camelize = exports.CalendarDate = exports.Benchmark = exports.ValidationError = exports.RecordNotFound = exports.GlobalNameNotSet = exports.CreateOrFindByFailedToCreateAndFind = exports.NonLoadedAssociation = exports.Encrypt = exports.Query = exports.DreamTransaction = exports.openapiShorthandPrimitiveTypes = exports.openapiPrimitiveTypes = exports.DreamConst = exports.Dream = exports.DreamAppAllowedPackageManagersEnumValues = exports.DreamApp = exports.lookupClassByGlobalName = exports.DreamImporter = exports.Decorators = exports.STI = exports.SoftDelete = exports.ReplicaSafe = exports.validateTable = exports.validateColumn = exports.DreamMigrationHelpers = exports.untypedDb = exports.pgErrorType = exports.dreamDbConnections = exports.closeAllDbConnections = exports.DreamCLI = exports.CliFileWriter = exports.DreamBin = void 0;
|
|
4
|
+
exports.ObjectSerializerBuilder = exports.DreamSerializerBuilder = exports.ObjectSerializer = exports.DreamSerializer = exports.serializerNameFromFullyQualifiedModelName = exports.isDreamSerializer = exports.inferSerializersFromDreamClassOrViewModelClass = exports.inferSerializerFromDreamOrViewModel = exports.ops = exports.uniq = exports.uncapitalize = exports.expandStiClasses = exports.standardizeFullyQualifiedModelName = exports.sortObjectByValue = exports.sortObjectByKey = exports.sortBy = exports.sort = exports.snakeify = exports.round = exports.range = exports.Range = exports.sharedPathPrefix = void 0;
|
|
5
5
|
var index_js_1 = require("./bin/index.js");
|
|
6
6
|
Object.defineProperty(exports, "DreamBin", { enumerable: true, get: function () { return index_js_1.default; } });
|
|
7
|
+
var CliFileWriter_js_1 = require("./cli/CliFileWriter.js");
|
|
8
|
+
Object.defineProperty(exports, "CliFileWriter", { enumerable: true, get: function () { return CliFileWriter_js_1.CliFileWriter; } });
|
|
7
9
|
var index_js_2 = require("./cli/index.js");
|
|
8
10
|
Object.defineProperty(exports, "DreamCLI", { enumerable: true, get: function () { return index_js_2.default; } });
|
|
9
11
|
var DreamDbConnection_js_1 = require("./db/DreamDbConnection.js");
|
|
@@ -9,11 +9,13 @@ import EnvInternal from '../../helpers/EnvInternal.js';
|
|
|
9
9
|
import dreamPath from '../../helpers/path/dreamPath.js';
|
|
10
10
|
import snakeify from '../../helpers/snakeify.js';
|
|
11
11
|
import sspawn from '../../helpers/sspawn.js';
|
|
12
|
+
import { CliFileWriter } from '../../cli/CliFileWriter.js';
|
|
12
13
|
export default async function writeSyncFile() {
|
|
13
14
|
const dreamApp = DreamApp.getOrFail();
|
|
14
15
|
const dbConf = dreamApp.dbConnectionConfig('primary');
|
|
15
16
|
const dbSyncFilePath = path.join(dreamPath('types'), 'db.ts');
|
|
16
17
|
const absoluteDbSyncPath = path.join(dreamApp.projectRoot, dbSyncFilePath);
|
|
18
|
+
await CliFileWriter.cache(absoluteDbSyncPath);
|
|
17
19
|
await sspawn(`kysely-codegen --dialect=postgres --url=postgres://${dbConf.user}:${dbConf.password}@${dbConf.host}:${dbConf.port}/${dbConf.name} --out-file=${absoluteDbSyncPath}`, {
|
|
18
20
|
onStdout: message => {
|
|
19
21
|
DreamCLI.logger.logContinueProgress(colorize(`[db]`, { color: 'cyan' }) + ' ' + message, {
|
|
@@ -25,7 +27,7 @@ export default async function writeSyncFile() {
|
|
|
25
27
|
// from the dist folder, whereas dirname here is pointing to true src folder.
|
|
26
28
|
const file = (await fs.readFile(absoluteDbSyncPath)).toString();
|
|
27
29
|
const enhancedSchema = enhanceSchema(file);
|
|
28
|
-
await
|
|
30
|
+
await CliFileWriter.write(absoluteDbSyncPath, enhancedSchema);
|
|
29
31
|
}
|
|
30
32
|
// begin: schema helpers
|
|
31
33
|
function enhanceSchema(file) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import DreamCLI from './index.js';
|
|
3
|
+
export class CliFileWriter {
|
|
4
|
+
static async write(filepath, contents) {
|
|
5
|
+
await cliFileWriter.write(filepath, contents);
|
|
6
|
+
}
|
|
7
|
+
static async revert() {
|
|
8
|
+
await cliFileWriter.revert();
|
|
9
|
+
}
|
|
10
|
+
static async cache(filepath) {
|
|
11
|
+
await cliFileWriter.cache(filepath);
|
|
12
|
+
}
|
|
13
|
+
fileCache = {};
|
|
14
|
+
async write(filepath, contents) {
|
|
15
|
+
// if we have manually backed up this file, or else this file
|
|
16
|
+
// has been written to twice in one CLI session, we want
|
|
17
|
+
// to preserve the original backup, so we do not attempt
|
|
18
|
+
// to cache a second time
|
|
19
|
+
if (!this.fileCache[filepath])
|
|
20
|
+
await this.cache(filepath);
|
|
21
|
+
await fs.writeFile(filepath, contents);
|
|
22
|
+
}
|
|
23
|
+
async revert() {
|
|
24
|
+
const filepaths = Object.keys(this.fileCache);
|
|
25
|
+
for (const filepath of filepaths) {
|
|
26
|
+
DreamCLI.logger.logContinueProgress(`reverting ${filepath}`);
|
|
27
|
+
await fs.writeFile(filepath, this.fileCache[filepath]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async cache(filepath) {
|
|
31
|
+
const originalContents = (await fs.readFile(filepath)).toString();
|
|
32
|
+
this.fileCache[filepath] = originalContents;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const cliFileWriter = new CliFileWriter();
|
|
@@ -8,6 +8,11 @@ export default class DreamCliLogger {
|
|
|
8
8
|
});
|
|
9
9
|
loggable.render();
|
|
10
10
|
}
|
|
11
|
+
async logProgress(text, cb, { logPrefix = '✺ ┌', logPrefixColor, logPrefixBgColor } = {}) {
|
|
12
|
+
this.log(text, { logPrefix, logPrefixColor, logPrefixBgColor });
|
|
13
|
+
await cb();
|
|
14
|
+
this.logEndProgress();
|
|
15
|
+
}
|
|
11
16
|
logStartProgress(text, { logPrefix = '✺ ┌', logPrefixColor, logPrefixBgColor } = {}) {
|
|
12
17
|
this.log(text, { logPrefix, logPrefixColor, logPrefixBgColor });
|
|
13
18
|
}
|
|
@@ -89,12 +89,12 @@ export function applyGetterAndSetter(target, partialAssociation, { foreignKeyBas
|
|
|
89
89
|
export function associationPrimaryKeyAccessors(partialAssociation, dreamClass) {
|
|
90
90
|
return {
|
|
91
91
|
...partialAssociation,
|
|
92
|
-
primaryKey(associationInstance) {
|
|
92
|
+
primaryKey(associationInstance, { associatedClassOverride } = {}) {
|
|
93
93
|
if (this.primaryKeyOverride)
|
|
94
94
|
return this.primaryKeyOverride;
|
|
95
95
|
if (associationInstance)
|
|
96
96
|
return associationInstance.primaryKey;
|
|
97
|
-
const associationClass = this.modelCB();
|
|
97
|
+
const associationClass = associatedClassOverride ?? this.modelCB();
|
|
98
98
|
if (Array.isArray(associationClass)) {
|
|
99
99
|
throw new Error(`
|
|
100
100
|
Cannot lookup primaryKey on polymorphic association:
|