@rvoh/dream 2.32.0 → 2.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/src/Dream.js +14 -1
- package/dist/cjs/src/cli/index.js +4 -4
- package/dist/cjs/src/db/helpers/syncDbTypesFiles.js +6 -7
- package/dist/cjs/src/decorators/Decorators.js +20 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterCreateCommit.js +4 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterDestroyCommit.js +4 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterSaveCommit.js +4 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterUpdateCommit.js +4 -0
- package/dist/cjs/src/dream/DreamTransaction.js +14 -3
- package/dist/cjs/src/dream/QueryDriver/Base.js +7 -0
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +8 -1
- package/dist/cjs/src/dream/QueryDriver/Postgres.js +7 -1
- package/dist/cjs/src/dream/QueryDriver/helpers/pg/loadPgClient.js +29 -1
- package/dist/cjs/src/dream/internal/runHooksFor.js +16 -5
- package/dist/cjs/src/dream/internal/withConcurrentWriterRetry.js +6 -1
- package/dist/esm/src/Dream.js +14 -1
- package/dist/esm/src/cli/index.js +4 -4
- package/dist/esm/src/db/helpers/syncDbTypesFiles.js +6 -7
- package/dist/esm/src/decorators/Decorators.js +20 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterCreateCommit.js +4 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterDestroyCommit.js +4 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterSaveCommit.js +4 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterUpdateCommit.js +4 -0
- package/dist/esm/src/dream/DreamTransaction.js +14 -3
- package/dist/esm/src/dream/QueryDriver/Base.js +7 -0
- package/dist/esm/src/dream/QueryDriver/Kysely.js +8 -1
- package/dist/esm/src/dream/QueryDriver/Postgres.js +7 -1
- package/dist/esm/src/dream/QueryDriver/helpers/pg/loadPgClient.js +29 -1
- package/dist/esm/src/dream/internal/runHooksFor.js +16 -5
- package/dist/esm/src/dream/internal/withConcurrentWriterRetry.js +6 -1
- package/dist/types/src/Dream.d.ts +14 -1
- package/dist/types/src/cli/index.d.ts +7 -6
- package/dist/types/src/decorators/Decorators.d.ts +24 -4
- package/dist/types/src/decorators/field/lifecycle/AfterCreateCommit.d.ts +6 -2
- package/dist/types/src/decorators/field/lifecycle/AfterDestroyCommit.d.ts +6 -1
- package/dist/types/src/decorators/field/lifecycle/AfterSaveCommit.d.ts +6 -2
- package/dist/types/src/decorators/field/lifecycle/AfterUpdateCommit.d.ts +6 -2
- package/dist/types/src/dream/DreamTransaction.d.ts +8 -1
- package/dist/types/src/dream/QueryDriver/Base.d.ts +3 -0
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +1 -0
- package/dist/types/src/dream/QueryDriver/helpers/pg/loadPgClient.d.ts +5 -0
- package/dist/types/src/dream/internal/runHooksFor.d.ts +5 -0
- package/dist/types/src/dream/internal/withConcurrentWriterRetry.d.ts +2 -1
- package/dist/types/src/dream-app/index.d.ts +11 -1
- package/dist/types/src/types/lifecycle.d.ts +29 -0
- package/dist/types/src/types/types/lifecycle.ts +46 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +47 -45
- package/docs/classes/db.PostgresQueryDriver.html +48 -46
- package/docs/classes/db.QueryDriverBase.html +46 -44
- package/docs/classes/errors.CannotSaveMissingDream.html +5 -5
- package/docs/classes/errors.CheckConstraintViolation.html +5 -5
- package/docs/classes/errors.ColumnOverflow.html +5 -5
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +5 -5
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +5 -5
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +5 -5
- package/docs/classes/errors.DecryptionError.html +4 -4
- package/docs/classes/errors.DecryptionParseError.html +4 -4
- package/docs/classes/errors.DecryptionRotationError.html +5 -5
- package/docs/classes/errors.GlobalNameNotSet.html +5 -5
- package/docs/classes/errors.InvalidCalendarDate.html +5 -5
- package/docs/classes/errors.InvalidClockTime.html +5 -5
- package/docs/classes/errors.InvalidClockTimeTz.html +5 -5
- package/docs/classes/errors.InvalidDateTime.html +5 -5
- package/docs/classes/errors.MissingSerializersDefinition.html +5 -5
- package/docs/classes/errors.NonLoadedAssociation.html +5 -5
- package/docs/classes/errors.NotNullViolation.html +5 -5
- package/docs/classes/errors.RecordNotFound.html +5 -5
- package/docs/classes/errors.SortableScopeDidNotStabilize.html +5 -5
- package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +5 -5
- package/docs/classes/errors.ValidationError.html +5 -5
- package/docs/classes/index.CalendarDate.html +33 -33
- package/docs/classes/index.ClockTime.html +32 -32
- package/docs/classes/index.ClockTimeTz.html +35 -35
- package/docs/classes/index.DateTime.html +86 -86
- package/docs/classes/index.Decorators.html +39 -23
- package/docs/classes/index.Dream.html +135 -125
- package/docs/classes/index.DreamApp.html +10 -10
- package/docs/classes/index.DreamTransaction.html +6 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +65 -65
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +11 -11
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +11 -11
- package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +3 -3
- package/docs/classes/utils.Range.html +2 -2
- package/docs/functions/db.closeAllDbConnections.html +1 -1
- package/docs/functions/db.dreamDbConnections.html +1 -1
- package/docs/functions/db.untypedDb.html +1 -1
- package/docs/functions/db.validateColumn.html +1 -1
- package/docs/functions/db.validateTable.html +1 -1
- package/docs/functions/errors.pgErrorType.html +1 -1
- package/docs/functions/index.DreamSerializer.html +1 -1
- package/docs/functions/index.ObjectSerializer.html +1 -1
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +1 -1
- package/docs/functions/utils.camelize.html +1 -1
- package/docs/functions/utils.capitalize.html +1 -1
- package/docs/functions/utils.cloneDeepSafe.html +1 -1
- package/docs/functions/utils.compact.html +1 -1
- package/docs/functions/utils.groupBy.html +1 -1
- package/docs/functions/utils.hyphenize.html +1 -1
- package/docs/functions/utils.intersection.html +1 -1
- package/docs/functions/utils.isEmpty.html +3 -3
- package/docs/functions/utils.normalizeUnicode.html +1 -1
- package/docs/functions/utils.pascalize.html +1 -1
- package/docs/functions/utils.percent.html +1 -1
- package/docs/functions/utils.range.html +1 -1
- package/docs/functions/utils.round.html +1 -1
- package/docs/functions/utils.sanitizeString.html +1 -1
- package/docs/functions/utils.snakeify.html +1 -1
- package/docs/functions/utils.sort.html +1 -1
- package/docs/functions/utils.sortBy.html +1 -1
- package/docs/functions/utils.sortObjectByKey.html +1 -1
- package/docs/functions/utils.sortObjectByValue.html +1 -1
- package/docs/functions/utils.uncapitalize.html +1 -1
- package/docs/functions/utils.uniq.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +1 -1
- package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
- package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/types.BelongsToStatement.html +2 -2
- package/docs/interfaces/types.DecoratorContext.html +2 -2
- package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.DreamDbConfig.html +13 -5
- package/docs/interfaces/types.DurationObject.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/openapi.OpenapiAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiFormats.html +1 -1
- package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaString.html +1 -1
- package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiTypeField.html +1 -1
- package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/types.CalendarDateDurationUnit.html +1 -1
- package/docs/types/types.CalendarDateObject.html +1 -1
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.ClockTimeObject.html +1 -1
- package/docs/types/types.DbConnectionType.html +1 -1
- package/docs/types/types.DbTypes.html +1 -1
- package/docs/types/types.DreamAssociationMetadata.html +1 -1
- package/docs/types/types.DreamAttributes.html +1 -1
- package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/types.DreamClassColumn.html +1 -1
- package/docs/types/types.DreamColumn.html +1 -1
- package/docs/types/types.DreamColumnNames.html +1 -1
- package/docs/types/types.DreamLogLevel.html +1 -1
- package/docs/types/types.DreamLogger.html +2 -2
- package/docs/types/types.DreamModelSerializerType.html +1 -1
- package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/types.DreamParamSafeAttributes.html +1 -1
- package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
- package/docs/types/types.DreamSerializable.html +1 -1
- package/docs/types/types.DreamSerializableArray.html +1 -1
- package/docs/types/types.DreamSerializerKey.html +1 -1
- package/docs/types/types.DreamSerializers.html +1 -1
- package/docs/types/types.DreamVirtualColumns.html +1 -1
- package/docs/types/types.DurationUnit.html +1 -1
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.PrimaryKeyType.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +2 -2
- package/docs/types/types.ViewModelClass.html +1 -1
- package/docs/types/types.WeekdayName.html +1 -1
- package/docs/types/types.WhereStatementForDream.html +1 -1
- package/docs/types/types.WhereStatementForDreamClass.html +1 -1
- package/docs/variables/index.DreamConst.html +1 -1
- package/docs/variables/index.ops.html +1 -1
- package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/system.primaryKeyTypes.html +1 -1
- package/package.json +5 -2
|
@@ -626,6 +626,13 @@ export default class QueryDriverBase {
|
|
|
626
626
|
static get syncDialect() {
|
|
627
627
|
return 'postgres';
|
|
628
628
|
}
|
|
629
|
+
/** @internal Resolve the credential used by the database type generator. */
|
|
630
|
+
static codegenPassword(password) {
|
|
631
|
+
if (typeof password === 'function') {
|
|
632
|
+
throw new Error('This database adapter does not support a password provider for type generation');
|
|
633
|
+
}
|
|
634
|
+
return Promise.resolve(password);
|
|
635
|
+
}
|
|
629
636
|
/**
|
|
630
637
|
* Returns the sql that would be executed by this Query
|
|
631
638
|
*
|
|
@@ -71,6 +71,7 @@ import softDeleteDream from '../internal/softDeleteDream.js';
|
|
|
71
71
|
import sqlResultToDreamInstance from '../internal/sqlResultToDreamInstance.js';
|
|
72
72
|
import Query from '../Query.js';
|
|
73
73
|
import QueryDriverBase from './Base.js';
|
|
74
|
+
import { PasswordProviderPoolClient } from './helpers/pg/loadPgClient.js';
|
|
74
75
|
import checkForNeedToBeRunMigrations from './helpers/kysely/checkForNeedToBeRunMigrations.js';
|
|
75
76
|
import foreignKeyTypeFromPrimaryKey from './helpers/kysely/foreignKeyTypeFromPrimaryKey.js';
|
|
76
77
|
import runMigration from './helpers/kysely/runMigration.js';
|
|
@@ -103,7 +104,10 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
103
104
|
// Spread pg passthrough first; Dream's resolved fields follow and
|
|
104
105
|
// always win (per-connection database name, TLS directive).
|
|
105
106
|
...(connectionConf.pg ?? {}),
|
|
107
|
+
Client: typeof connectionConf.password === 'function' ? PasswordProviderPoolClient : undefined,
|
|
106
108
|
user: connectionConf.user || '',
|
|
109
|
+
// pg accepts a callback here and resolves it for each new client when
|
|
110
|
+
// the server requests password authentication.
|
|
107
111
|
password: connectionConf.password || '',
|
|
108
112
|
database: DreamApp.getOrFail().dbName(connectionName, dbConnectionType),
|
|
109
113
|
host: connectionConf.host || 'localhost',
|
|
@@ -227,6 +231,9 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
227
231
|
static get syncDialect() {
|
|
228
232
|
return 'postgres';
|
|
229
233
|
}
|
|
234
|
+
static async codegenPassword(password) {
|
|
235
|
+
return typeof password === 'function' ? await password() : password;
|
|
236
|
+
}
|
|
230
237
|
/**
|
|
231
238
|
* @internal
|
|
232
239
|
*
|
|
@@ -344,7 +351,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
344
351
|
dreamTransaction.kyselyTransaction = kyselyTransaction;
|
|
345
352
|
callbackResponse = (await callback(dreamTransaction));
|
|
346
353
|
});
|
|
347
|
-
await dreamTransaction.runAfterCommitHooks(
|
|
354
|
+
await dreamTransaction.runAfterCommitHooks();
|
|
348
355
|
return callbackResponse;
|
|
349
356
|
}
|
|
350
357
|
/**
|
|
@@ -332,7 +332,13 @@ export default class PostgresQueryDriver extends KyselyQueryDriver {
|
|
|
332
332
|
keepAlive: true,
|
|
333
333
|
keepAliveInitialDelayMillis: LOCK_CONNECTION_KEEPALIVE_INITIAL_DELAY_MS,
|
|
334
334
|
});
|
|
335
|
-
|
|
335
|
+
try {
|
|
336
|
+
await client.connect();
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
await client.end().catch(() => undefined);
|
|
340
|
+
throw err;
|
|
341
|
+
}
|
|
336
342
|
return {
|
|
337
343
|
async tryAcquire(namespace, index) {
|
|
338
344
|
const result = await client.query('SELECT pg_try_advisory_lock($1::int4, $2::int4) AS locked', [
|
|
@@ -8,6 +8,28 @@
|
|
|
8
8
|
// @ts-ignore
|
|
9
9
|
import pg from 'pg';
|
|
10
10
|
import DreamApp from '../../../../dream-app/index.js';
|
|
11
|
+
export class PasswordProviderPoolClient extends pg.Client {
|
|
12
|
+
connect(callback) {
|
|
13
|
+
if (callback) {
|
|
14
|
+
super.connect(err => {
|
|
15
|
+
if (err)
|
|
16
|
+
this.destroyConnectionStream();
|
|
17
|
+
callback(err);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return super.connect().catch(err => {
|
|
22
|
+
this.destroyConnectionStream();
|
|
23
|
+
throw err;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
destroyConnectionStream() {
|
|
28
|
+
// pg reports a rejected password provider without closing its socket.
|
|
29
|
+
;
|
|
30
|
+
this.connection?.stream.destroy();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
11
33
|
export default async function loadPgClient({ connectionName, useSystemDb, }) {
|
|
12
34
|
const dreamconf = DreamApp.getOrFail();
|
|
13
35
|
const creds = dreamconf.dbCredentialsFor(connectionName)?.primary;
|
|
@@ -20,6 +42,12 @@ export default async function loadPgClient({ connectionName, useSystemDb, }) {
|
|
|
20
42
|
user: creds.user,
|
|
21
43
|
password: creds.password,
|
|
22
44
|
});
|
|
23
|
-
|
|
45
|
+
try {
|
|
46
|
+
await client.connect();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
await client.end().catch(() => undefined);
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
24
52
|
return client;
|
|
25
53
|
}
|
|
@@ -35,7 +35,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
35
35
|
if (txn)
|
|
36
36
|
txn.addCommitHook(hook, dream);
|
|
37
37
|
else
|
|
38
|
-
await
|
|
38
|
+
await runCommitHook(hook, dream);
|
|
39
39
|
}
|
|
40
40
|
break;
|
|
41
41
|
case 'afterSave':
|
|
@@ -50,7 +50,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
50
50
|
if (txn)
|
|
51
51
|
txn.addCommitHook(hook, dream);
|
|
52
52
|
else
|
|
53
|
-
await
|
|
53
|
+
await runCommitHook(hook, dream);
|
|
54
54
|
}
|
|
55
55
|
break;
|
|
56
56
|
case 'afterUpdate':
|
|
@@ -63,7 +63,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
63
63
|
if (txn)
|
|
64
64
|
txn.addCommitHook(hook, dream);
|
|
65
65
|
else
|
|
66
|
-
await
|
|
66
|
+
await runCommitHook(hook, dream);
|
|
67
67
|
}
|
|
68
68
|
break;
|
|
69
69
|
default:
|
|
@@ -79,7 +79,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
79
79
|
if (txn)
|
|
80
80
|
txn.addCommitHook(hook, dream);
|
|
81
81
|
else
|
|
82
|
-
await
|
|
82
|
+
await runCommitHook(hook, dream);
|
|
83
83
|
break;
|
|
84
84
|
default:
|
|
85
85
|
await runHook(hook, dream, txn);
|
|
@@ -88,6 +88,18 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
export async function runHook(statement, dream, txn) {
|
|
91
|
+
assertHookMethodExists(statement, dream);
|
|
92
|
+
await dream[statement.method](txn);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Commit hooks run after the transaction has committed, so they are called
|
|
96
|
+
* with no argument.
|
|
97
|
+
*/
|
|
98
|
+
export async function runCommitHook(statement, dream) {
|
|
99
|
+
assertHookMethodExists(statement, dream);
|
|
100
|
+
await dream[statement.method]();
|
|
101
|
+
}
|
|
102
|
+
function assertHookMethodExists(statement, dream) {
|
|
91
103
|
if (typeof dream[statement.method] !== 'function') {
|
|
92
104
|
throw new Error(`
|
|
93
105
|
Attempting to run ${statement.method} as part of the ${statement.type}
|
|
@@ -96,7 +108,6 @@ Dream model hook sequence, but we encountered a method that does not exist.
|
|
|
96
108
|
Please make sure "${statement.method}" is defined on ${dream['sanitizedConstructorName']}
|
|
97
109
|
`);
|
|
98
110
|
}
|
|
99
|
-
await dream[statement.method](txn);
|
|
100
111
|
}
|
|
101
112
|
function shouldRunBeforeCreateHook(dream, statement) {
|
|
102
113
|
let shouldRun = false;
|
|
@@ -22,7 +22,8 @@ export const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
22
22
|
* rows mid-statement as well. Either way the database has undone the whole
|
|
23
23
|
* transaction, nothing has committed and no commit hook has run, so running
|
|
24
24
|
* the operation again reads the rows as the other writer left them. The last
|
|
25
|
-
* attempt's error is the adapter's own.
|
|
25
|
+
* attempt's error is the adapter's own. An error raised after COMMIT, such as a
|
|
26
|
+
* commit hook's, is never retried.
|
|
26
27
|
*
|
|
27
28
|
* A unique violation raised by a statement inside the callback is not a
|
|
28
29
|
* collision but a write that violates a constraint outright, and is not
|
|
@@ -46,15 +47,19 @@ export const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
46
47
|
export default async function withConcurrentWriterRetry(dreamClass, callback) {
|
|
47
48
|
const queryDriverClass = DreamApp.getOrFail().dbConnectionQueryDriverClass(dreamClass.prototype.connectionName);
|
|
48
49
|
for (let attempt = 1;; attempt++) {
|
|
50
|
+
let attemptTransaction = null;
|
|
49
51
|
let callbackResolved = false;
|
|
50
52
|
try {
|
|
51
53
|
return await dreamClass.transaction(async (txn) => {
|
|
54
|
+
attemptTransaction = txn;
|
|
52
55
|
const result = await callback(txn);
|
|
53
56
|
callbackResolved = true;
|
|
54
57
|
return result;
|
|
55
58
|
});
|
|
56
59
|
}
|
|
57
60
|
catch (error) {
|
|
61
|
+
if (attemptTransaction?.['committed'])
|
|
62
|
+
throw error;
|
|
58
63
|
const undoneByConcurrentWriter = queryDriverClass.isDeadlock(error) ||
|
|
59
64
|
(callbackResolved && queryDriverClass.isUniqueConstraintViolation(error));
|
|
60
65
|
if (!undoneByConcurrentWriter || attempt === MAX_CONCURRENT_WRITER_ATTEMPTS)
|
|
@@ -2312,6 +2312,10 @@ export default class Dream {
|
|
|
2312
2312
|
* being persisted to the database, with the values
|
|
2313
2313
|
* that were last persisted to the database.
|
|
2314
2314
|
*
|
|
2315
|
+
* On a record that has not been persisted, every
|
|
2316
|
+
* column counts as changed: the object has a key
|
|
2317
|
+
* for every column.
|
|
2318
|
+
*
|
|
2315
2319
|
* ```ts
|
|
2316
2320
|
* const user = User.new({ email: 'original@email', password: 'howyadoin' })
|
|
2317
2321
|
* await user.save()
|
|
@@ -2421,6 +2425,10 @@ export default class Dream {
|
|
|
2421
2425
|
* Returns true if the columnName provided has
|
|
2422
2426
|
* changes that have not yet been persisted.
|
|
2423
2427
|
*
|
|
2428
|
+
* On a record that has not been persisted, every
|
|
2429
|
+
* column counts as changed, so this returns true
|
|
2430
|
+
* for every column, whether or not it was assigned.
|
|
2431
|
+
*
|
|
2424
2432
|
* @param attribute - the column name to check
|
|
2425
2433
|
* @returns A boolean
|
|
2426
2434
|
*/
|
|
@@ -2436,10 +2444,15 @@ export default class Dream {
|
|
|
2436
2444
|
* of columns that have changed since last persist,
|
|
2437
2445
|
* and their current values.
|
|
2438
2446
|
*
|
|
2447
|
+
* On a record that has not been persisted, every
|
|
2448
|
+
* column counts as changed: the object has a key
|
|
2449
|
+
* for every column, including those never assigned,
|
|
2450
|
+
* whose value is `undefined`.
|
|
2451
|
+
*
|
|
2439
2452
|
* ```ts
|
|
2440
2453
|
* const user = User.new({ email: 'hello@world' })
|
|
2441
2454
|
* user.dirtyAttributes()
|
|
2442
|
-
* // { email: 'hello@world' }
|
|
2455
|
+
* // { id: undefined, email: 'hello@world', name: undefined, ...every other column: undefined }
|
|
2443
2456
|
*
|
|
2444
2457
|
* await user.save()
|
|
2445
2458
|
*
|
|
@@ -8,8 +8,9 @@ export type SpawnOptions = Omit<NodeSpawnOptions, 'shell'> & {
|
|
|
8
8
|
* Argv elements passed to the child as separate arguments. Defaults to `[]`.
|
|
9
9
|
* Each entry is passed literally — shell meta-characters (`$`, backticks,
|
|
10
10
|
* `&&`, spaces, etc.) inside any element are not interpreted by a shell.
|
|
11
|
-
* This is the right shape for
|
|
12
|
-
*
|
|
11
|
+
* This is the right shape for paths and other non-secret values. Pass
|
|
12
|
+
* credentials through the child's environment so they do not appear in
|
|
13
|
+
* the process command line or a refused-spawn error.
|
|
13
14
|
*/
|
|
14
15
|
args?: string[];
|
|
15
16
|
};
|
|
@@ -103,10 +104,10 @@ export default class DreamCLI {
|
|
|
103
104
|
* (package.json scripts, CLI argv, scaffold templates) — never from
|
|
104
105
|
* runtime request input or any other untrusted external source.
|
|
105
106
|
*
|
|
106
|
-
* Argv-form
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
107
|
+
* Argv-form passes config values and paths literally to the child,
|
|
108
|
+
* without interpreting shell metacharacters. Credentials belong in
|
|
109
|
+
* the child's environment, since argv is visible in process listings
|
|
110
|
+
* and in the refused-spawn error.
|
|
110
111
|
*
|
|
111
112
|
* ## Layered defense
|
|
112
113
|
*
|
|
@@ -399,9 +399,14 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
399
399
|
* }
|
|
400
400
|
* ```
|
|
401
401
|
*
|
|
402
|
+
* The decorated method is called with no argument, once the
|
|
403
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
404
|
+
* compile error. A subclass override of the method that is not itself
|
|
405
|
+
* decorated is not checked; it is still called with no argument.
|
|
406
|
+
*
|
|
402
407
|
* @returns The AfterCreateCommit decorator
|
|
403
408
|
*/
|
|
404
|
-
AfterCreateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>):
|
|
409
|
+
AfterCreateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
405
410
|
/**
|
|
406
411
|
* AfterSave decorator
|
|
407
412
|
*
|
|
@@ -430,10 +435,15 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
430
435
|
* }
|
|
431
436
|
* ```
|
|
432
437
|
*
|
|
438
|
+
* The decorated method is called with no argument, once the
|
|
439
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
440
|
+
* compile error. A subclass override of the method that is not itself
|
|
441
|
+
* decorated is not checked; it is still called with no argument.
|
|
442
|
+
*
|
|
433
443
|
* @returns The AfterSaveCommit decorator
|
|
434
444
|
*
|
|
435
445
|
*/
|
|
436
|
-
AfterSaveCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>):
|
|
446
|
+
AfterSaveCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
437
447
|
/**
|
|
438
448
|
* AfterUpdate decorator
|
|
439
449
|
*
|
|
@@ -462,10 +472,15 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
462
472
|
* }
|
|
463
473
|
* ```
|
|
464
474
|
*
|
|
475
|
+
* The decorated method is called with no argument, once the
|
|
476
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
477
|
+
* compile error. A subclass override of the method that is not itself
|
|
478
|
+
* decorated is not checked; it is still called with no argument.
|
|
479
|
+
*
|
|
465
480
|
* @returns The AfterUpdateCommit decorator
|
|
466
481
|
*
|
|
467
482
|
*/
|
|
468
|
-
AfterUpdateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>):
|
|
483
|
+
AfterUpdateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
469
484
|
/**
|
|
470
485
|
* AfterDestroy decorator
|
|
471
486
|
*
|
|
@@ -494,8 +509,13 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
494
509
|
* }
|
|
495
510
|
* ```
|
|
496
511
|
*
|
|
512
|
+
* The decorated method is called with no argument, once the
|
|
513
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
514
|
+
* compile error. A subclass override of the method that is not itself
|
|
515
|
+
* decorated is not checked; it is still called with no argument.
|
|
516
|
+
*
|
|
497
517
|
* @returns The AfterDestroyCommit decorator
|
|
498
518
|
*
|
|
499
519
|
*/
|
|
500
|
-
AfterDestroyCommit(this: Decorators<TD>):
|
|
520
|
+
AfterDestroyCommit(this: Decorators<TD>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
501
521
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Dream from '../../../Dream.js';
|
|
2
|
-
import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
2
|
+
import { AfterHookOpts, CommitHookDecorator } from '../../../types/lifecycle.js';
|
|
3
3
|
/**
|
|
4
4
|
* Calls the decorated method whenever a dream has finished
|
|
5
5
|
* being created. If the save takes place within a transaction,
|
|
@@ -8,6 +8,10 @@ import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
|
8
8
|
* a transaction, the method will be run after the save
|
|
9
9
|
* is complete.
|
|
10
10
|
*
|
|
11
|
+
* The method is called with no argument: the transaction has already
|
|
12
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
13
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
14
|
+
*
|
|
11
15
|
* class User extends ApplicationModel {
|
|
12
16
|
* @deco.AfterCreateCommit()
|
|
13
17
|
* public doSomething() {
|
|
@@ -17,5 +21,5 @@ import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
|
17
21
|
*
|
|
18
22
|
* @param opts.ifChanged - Optional. A list of columns which should must change in order for this function to be called.
|
|
19
23
|
*/
|
|
20
|
-
export default function AfterCreateCommit<T extends Dream>(opts?: AfterHookOpts<T>):
|
|
24
|
+
export default function AfterCreateCommit<T extends Dream>(opts?: AfterHookOpts<T>): CommitHookDecorator;
|
|
21
25
|
export declare function afterCreateCommitImplementation<T extends Dream>(target: T, key: string, opts?: AfterHookOpts<T>): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Dream from '../../../Dream.js';
|
|
2
|
+
import { CommitHookDecorator } from '../../../types/lifecycle.js';
|
|
2
3
|
/**
|
|
3
4
|
* Calls the decorated method whenever a dream has finished
|
|
4
5
|
* being destroyed. If the destroy takes place within a transaction,
|
|
@@ -7,6 +8,10 @@ import Dream from '../../../Dream.js';
|
|
|
7
8
|
* a transaction, the method will be run after the save
|
|
8
9
|
* is complete.
|
|
9
10
|
*
|
|
11
|
+
* The method is called with no argument: the transaction has already
|
|
12
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
13
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
14
|
+
*
|
|
10
15
|
* class User extends ApplicationModel {
|
|
11
16
|
* @deco.AfterDestroyCommit()
|
|
12
17
|
* public doSomething() {
|
|
@@ -14,5 +19,5 @@ import Dream from '../../../Dream.js';
|
|
|
14
19
|
* }
|
|
15
20
|
* }
|
|
16
21
|
*/
|
|
17
|
-
export default function AfterDestroyCommit():
|
|
22
|
+
export default function AfterDestroyCommit(): CommitHookDecorator;
|
|
18
23
|
export declare function afterDestroyCommitImplementation<T extends Dream>(target: T, key: string): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Dream from '../../../Dream.js';
|
|
2
|
-
import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
2
|
+
import { AfterHookOpts, CommitHookDecorator } from '../../../types/lifecycle.js';
|
|
3
3
|
/**
|
|
4
4
|
* Calls the decorated method whenever a dream has finished
|
|
5
5
|
* being saved. If the save takes place within a transaction,
|
|
@@ -8,6 +8,10 @@ import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
|
8
8
|
* a transaction, the method will be run after the save
|
|
9
9
|
* is complete.
|
|
10
10
|
*
|
|
11
|
+
* The method is called with no argument: the transaction has already
|
|
12
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
13
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
14
|
+
*
|
|
11
15
|
* class User extends ApplicationModel {
|
|
12
16
|
* @deco.AfterSaveCommit()
|
|
13
17
|
* public doSomething() {
|
|
@@ -17,5 +21,5 @@ import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
|
17
21
|
*
|
|
18
22
|
* @param opts.ifChanged - Optional. A list of columns which should must change in order for this function to be called.
|
|
19
23
|
*/
|
|
20
|
-
export default function AfterSaveCommit<T extends Dream>(opts?: AfterHookOpts<T>):
|
|
24
|
+
export default function AfterSaveCommit<T extends Dream>(opts?: AfterHookOpts<T>): CommitHookDecorator;
|
|
21
25
|
export declare function afterSaveCommitImplementation<T extends Dream>(target: T, key: string, opts?: AfterHookOpts<T>): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Dream from '../../../Dream.js';
|
|
2
|
-
import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
2
|
+
import { AfterHookOpts, CommitHookDecorator } from '../../../types/lifecycle.js';
|
|
3
3
|
/**
|
|
4
4
|
* Calls the decorated method whenever a dream has finished
|
|
5
5
|
* being updated. If the save takes place within a transaction,
|
|
@@ -8,6 +8,10 @@ import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
|
8
8
|
* a transaction, the method will be run after the save
|
|
9
9
|
* is complete.
|
|
10
10
|
*
|
|
11
|
+
* The method is called with no argument: the transaction has already
|
|
12
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
13
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
14
|
+
*
|
|
11
15
|
* class User extends ApplicationModel {
|
|
12
16
|
* @deco.AfterUpdateCommit()
|
|
13
17
|
* public doSomething() {
|
|
@@ -17,5 +21,5 @@ import { AfterHookOpts } from '../../../types/lifecycle.js';
|
|
|
17
21
|
*
|
|
18
22
|
* @param opts.ifChanged - Optional. A list of columns which should must change in order for this function to be called.
|
|
19
23
|
*/
|
|
20
|
-
export default function AfterUpdateCommit<T extends Dream>(opts?: AfterHookOpts<T>):
|
|
24
|
+
export default function AfterUpdateCommit<T extends Dream>(opts?: AfterHookOpts<T>): CommitHookDecorator;
|
|
21
25
|
export declare function afterUpdateCommitImplementation<T extends Dream>(target: T, key: string, opts?: AfterHookOpts<T>): void;
|
|
@@ -8,8 +8,15 @@ export interface TransactionCommitHookStatement {
|
|
|
8
8
|
export default class DreamTransaction<T extends Dream, DB extends T['DB'] = T['DB']> {
|
|
9
9
|
private _kyselyTransaction;
|
|
10
10
|
private commitHooks;
|
|
11
|
+
private committed;
|
|
11
12
|
get kyselyTransaction(): Transaction<DB>;
|
|
12
13
|
set kyselyTransaction(txn: Transaction<DB>);
|
|
13
14
|
addCommitHook(hookStatement: HookStatement, dreamInstance: Dream): void;
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Runs the commit hooks queued during the transaction, in the order they
|
|
17
|
+
* were queued. A query driver calls this once the transaction has
|
|
18
|
+
* committed. Each hook is called with no argument, since the transaction
|
|
19
|
+
* it would otherwise receive can no longer run queries.
|
|
20
|
+
*/
|
|
21
|
+
runAfterCommitHooks(): Promise<void>;
|
|
15
22
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CompiledQuery, DeleteQueryBuilder, SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
|
|
2
|
+
import type { DreamDbConfig } from '../../dream-app/index.js';
|
|
2
3
|
import Dream from '../../Dream.js';
|
|
3
4
|
import { SchemaBuilderAssociationData, SchemaBuilderColumnData } from '../../helpers/cli/ASTBuilder.js';
|
|
4
5
|
import { AssociationStatement } from '../../types/associations/shared.js';
|
|
@@ -480,6 +481,8 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
|
|
|
480
481
|
*/
|
|
481
482
|
static destroyDream(dream: Dream, txn: DreamTransaction<Dream>, reallyDestroy: boolean): Promise<number>;
|
|
482
483
|
static get syncDialect(): string;
|
|
484
|
+
/** @internal Resolve the credential used by the database type generator. */
|
|
485
|
+
static codegenPassword(password: DreamDbConfig['password']): Promise<string>;
|
|
483
486
|
/**
|
|
484
487
|
* Returns the sql that would be executed by this Query
|
|
485
488
|
*
|
|
@@ -44,6 +44,7 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
|
|
|
44
44
|
schemaOnly?: boolean;
|
|
45
45
|
}): Promise<void>;
|
|
46
46
|
static get syncDialect(): string;
|
|
47
|
+
static codegenPassword(password: DreamDbConfig['password']): Promise<string>;
|
|
47
48
|
/**
|
|
48
49
|
* @internal
|
|
49
50
|
*
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import pg from 'pg';
|
|
2
|
+
export declare class PasswordProviderPoolClient extends pg.Client {
|
|
3
|
+
connect(): Promise<void>;
|
|
4
|
+
connect(callback: (err: Error) => void): void;
|
|
5
|
+
private destroyConnectionStream;
|
|
6
|
+
}
|
|
2
7
|
export default function loadPgClient({ connectionName, useSystemDb, }: {
|
|
3
8
|
connectionName: string;
|
|
4
9
|
useSystemDb?: boolean;
|
|
@@ -6,3 +6,8 @@ export default function runHooksFor<T extends Dream>(key: HookType, dream: T, al
|
|
|
6
6
|
now: any;
|
|
7
7
|
}>> | null, txn: DreamTransaction<any> | null): Promise<void>;
|
|
8
8
|
export declare function runHook<T extends Dream>(statement: HookStatement, dream: T, txn: DreamTransaction<any> | null): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Commit hooks run after the transaction has committed, so they are called
|
|
11
|
+
* with no argument.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runCommitHook<T extends Dream>(statement: HookStatement, dream: T): Promise<void>;
|
|
@@ -23,7 +23,8 @@ export declare const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
23
23
|
* rows mid-statement as well. Either way the database has undone the whole
|
|
24
24
|
* transaction, nothing has committed and no commit hook has run, so running
|
|
25
25
|
* the operation again reads the rows as the other writer left them. The last
|
|
26
|
-
* attempt's error is the adapter's own.
|
|
26
|
+
* attempt's error is the adapter's own. An error raised after COMMIT, such as a
|
|
27
|
+
* commit hook's, is never retried.
|
|
27
28
|
*
|
|
28
29
|
* A unique violation raised by a statement inside the callback is not a
|
|
29
30
|
* collision but a write that violates a constraint outright, and is not
|
|
@@ -288,7 +288,17 @@ export interface DreamDbCredentialOptions {
|
|
|
288
288
|
type UnicodeNormalizationForm = 'NFC' | 'NFD' | 'none';
|
|
289
289
|
export interface DreamDbConfig {
|
|
290
290
|
user: string;
|
|
291
|
-
|
|
291
|
+
/**
|
|
292
|
+
* A fixed password, or a provider for Dream's built-in PostgreSQL driver.
|
|
293
|
+
* PostgreSQL calls the provider when the server requests password
|
|
294
|
+
* authentication for a new physical connection. The provider may return a
|
|
295
|
+
* string or a promise of one. Each such connection gets a fresh result;
|
|
296
|
+
* existing pooled connections keep their credential. A rejected provider
|
|
297
|
+
* fails that connection attempt and reaches its caller; Dream does not cache
|
|
298
|
+
* credentials or retry. Custom query drivers receive the configured value
|
|
299
|
+
* and must handle or reject a provider themselves.
|
|
300
|
+
*/
|
|
301
|
+
password: string | (() => string | Promise<string>);
|
|
292
302
|
host: string;
|
|
293
303
|
name: string;
|
|
294
304
|
port: number;
|
|
@@ -2,6 +2,35 @@ import Dream from '../Dream.js';
|
|
|
2
2
|
import { DreamColumnNames } from './dream.js';
|
|
3
3
|
export type HookType = 'beforeCreate' | 'beforeSave' | 'beforeUpdate' | 'beforeDestroy' | 'afterCreate' | 'afterSave' | 'afterUpdate' | 'afterDestroy' | CommitHookType;
|
|
4
4
|
export type CommitHookType = 'afterCreateCommit' | 'afterSaveCommit' | 'afterUpdateCommit' | 'afterDestroyCommit';
|
|
5
|
+
/**
|
|
6
|
+
* The decorator returned by `deco.AfterCreateCommit()`,
|
|
7
|
+
* `deco.AfterSaveCommit()`, `deco.AfterUpdateCommit()` and
|
|
8
|
+
* `deco.AfterDestroyCommit()`.
|
|
9
|
+
*
|
|
10
|
+
* Dream calls every commit hook with no argument: by the time it runs, the
|
|
11
|
+
* transaction has already committed, so there is no transaction to hand it.
|
|
12
|
+
* Decorating an instance method that declares a parameter — required,
|
|
13
|
+
* optional, defaulted or rest — is therefore a compile error.
|
|
14
|
+
*
|
|
15
|
+
* Other placements of the decorator (an arrow-function field, an `accessor`
|
|
16
|
+
* field, a getter, a static method) are not checked.
|
|
17
|
+
*
|
|
18
|
+
* A subclass that overrides a decorated commit hook without decorating the
|
|
19
|
+
* override is not checked either, so `override hook(txn?: ...)` compiles; at
|
|
20
|
+
* runtime the override is still called with no argument.
|
|
21
|
+
*/
|
|
22
|
+
export interface CommitHookDecorator {
|
|
23
|
+
<This, Method extends (...args: any[]) => unknown>(value: This extends abstract new (...args: any[]) => unknown ? Method : CommitHookMethod<Method>, context: ClassMethodDecoratorContext<This, Method>): void;
|
|
24
|
+
(value: any, context: ClassFieldDecoratorContext<any, any> | ClassGetterDecoratorContext<any, any> | ClassSetterDecoratorContext<any, any> | ClassAccessorDecoratorContext<any, any> | ClassDecoratorContext<any>): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A method a commit-hook decorator accepts: one that declares no parameter.
|
|
28
|
+
* Any other method resolves to a message naming the problem, which the
|
|
29
|
+
* decorated method is not assignable to. The parameter tuple is compared
|
|
30
|
+
* whole, so a rest parameter typed as a union such as `[] | [X]` is rejected
|
|
31
|
+
* too.
|
|
32
|
+
*/
|
|
33
|
+
export type CommitHookMethod<Method> = Method extends (...args: infer Params) => unknown ? [Params] extends [[]] ? Method : 'a commit hook is called with no argument: remove its parameters' : never;
|
|
5
34
|
export interface HookStatement {
|
|
6
35
|
type: HookType;
|
|
7
36
|
className: string;
|
|
@@ -18,6 +18,52 @@ export type CommitHookType =
|
|
|
18
18
|
| 'afterUpdateCommit'
|
|
19
19
|
| 'afterDestroyCommit'
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* The decorator returned by `deco.AfterCreateCommit()`,
|
|
23
|
+
* `deco.AfterSaveCommit()`, `deco.AfterUpdateCommit()` and
|
|
24
|
+
* `deco.AfterDestroyCommit()`.
|
|
25
|
+
*
|
|
26
|
+
* Dream calls every commit hook with no argument: by the time it runs, the
|
|
27
|
+
* transaction has already committed, so there is no transaction to hand it.
|
|
28
|
+
* Decorating an instance method that declares a parameter — required,
|
|
29
|
+
* optional, defaulted or rest — is therefore a compile error.
|
|
30
|
+
*
|
|
31
|
+
* Other placements of the decorator (an arrow-function field, an `accessor`
|
|
32
|
+
* field, a getter, a static method) are not checked.
|
|
33
|
+
*
|
|
34
|
+
* A subclass that overrides a decorated commit hook without decorating the
|
|
35
|
+
* override is not checked either, so `override hook(txn?: ...)` compiles; at
|
|
36
|
+
* runtime the override is still called with no argument.
|
|
37
|
+
*/
|
|
38
|
+
export interface CommitHookDecorator {
|
|
39
|
+
<This, Method extends (...args: any[]) => unknown>(
|
|
40
|
+
value: This extends abstract new (...args: any[]) => unknown ? Method : CommitHookMethod<Method>,
|
|
41
|
+
context: ClassMethodDecoratorContext<This, Method>
|
|
42
|
+
): void
|
|
43
|
+
(
|
|
44
|
+
value: any,
|
|
45
|
+
context:
|
|
46
|
+
| ClassFieldDecoratorContext<any, any>
|
|
47
|
+
| ClassGetterDecoratorContext<any, any>
|
|
48
|
+
| ClassSetterDecoratorContext<any, any>
|
|
49
|
+
| ClassAccessorDecoratorContext<any, any>
|
|
50
|
+
| ClassDecoratorContext<any>
|
|
51
|
+
): void
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A method a commit-hook decorator accepts: one that declares no parameter.
|
|
56
|
+
* Any other method resolves to a message naming the problem, which the
|
|
57
|
+
* decorated method is not assignable to. The parameter tuple is compared
|
|
58
|
+
* whole, so a rest parameter typed as a union such as `[] | [X]` is rejected
|
|
59
|
+
* too.
|
|
60
|
+
*/
|
|
61
|
+
export type CommitHookMethod<Method> = Method extends (...args: infer Params) => unknown
|
|
62
|
+
? [Params] extends [[]]
|
|
63
|
+
? Method
|
|
64
|
+
: 'a commit hook is called with no argument: remove its parameters'
|
|
65
|
+
: never
|
|
66
|
+
|
|
21
67
|
export interface HookStatement {
|
|
22
68
|
type: HookType
|
|
23
69
|
className: string
|
package/docs/assets/hierarchy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
window.hierarchyData = "
|
|
1
|
+
window.hierarchyData = "eJyVk8FOAjEQht9lzgUpCwvboxATY0RNjB4Ih7I7uA3dlnS6mA3h3U3lsiK65dR2Mv/8X6fTAzhrPYFY8nQ8YZzzFQOHG425V9YQiANwzsNiZIUg4KVG18yd2qO7lYTAYKtMAYIPpwxqp0FAriUR0k2x7p9l90tfaWCnDBDgqegFee8UYJCXShcODYhlMhitjgySwajl/tAQ6qZVtcP/V/41BDxJpgEhrC2GZ0v+wyHFU1xQdHAE13TY7vusxHw7s4a8k8r4N2W1DE/0nzU6Zx31/5LGMCRZm8HqujJPe3QbbT9jnH8IYvzGk5bfXHp5b3Jb7aRXa43vypchtpaEdwp1EYHQWeOqiUiHnIWmMJ5OUsbT7HtGw+EM+7XZ4en2YfeoqJI+LyN5L4tj2pe1P8vC+kWt9TWjci7p8jwevwDboG8X"
|