@rvoh/dream 2.36.0 → 2.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/Dream.js +3 -1
- package/dist/cjs/src/db/dataTypes.js +0 -8
- package/dist/cjs/src/decorators/field/Encrypted.js +8 -3
- package/dist/cjs/src/dream/QueryDriver/Base.js +17 -24
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +22 -23
- package/dist/cjs/src/dream/QueryDriver/Postgres.js +113 -31
- package/dist/cjs/src/encrypt/InternalEncrypt.js +28 -0
- package/dist/cjs/src/helpers/cli/ASTBuilder.js +11 -202
- package/dist/cjs/src/helpers/cli/ASTConnectionBuilder.js +97 -75
- package/dist/cjs/src/helpers/cli/ASTDbTypesBuilder.js +132 -0
- package/dist/cjs/src/helpers/cli/ASTSchemaBuilder.js +37 -81
- package/dist/cjs/src/helpers/cli/dbTypesNaming.js +90 -0
- package/dist/cjs/src/helpers/cli/tableMatchesPattern.js +21 -0
- package/dist/esm/src/Dream.js +3 -1
- package/dist/esm/src/db/dataTypes.js +0 -8
- package/dist/esm/src/decorators/field/Encrypted.js +8 -3
- package/dist/esm/src/dream/QueryDriver/Base.js +17 -24
- package/dist/esm/src/dream/QueryDriver/Kysely.js +22 -23
- package/dist/esm/src/dream/QueryDriver/Postgres.js +113 -31
- package/dist/esm/src/encrypt/InternalEncrypt.js +28 -0
- package/dist/esm/src/helpers/cli/ASTBuilder.js +11 -202
- package/dist/esm/src/helpers/cli/ASTConnectionBuilder.js +97 -75
- package/dist/esm/src/helpers/cli/ASTDbTypesBuilder.js +132 -0
- package/dist/esm/src/helpers/cli/ASTSchemaBuilder.js +37 -81
- package/dist/esm/src/helpers/cli/dbTypesNaming.js +90 -0
- package/dist/esm/src/helpers/cli/tableMatchesPattern.js +21 -0
- package/dist/types/src/Dream.d.ts +3 -1
- package/dist/types/src/db/dataTypes.d.ts +0 -2
- package/dist/types/src/dream/QueryDriver/Base.d.ts +16 -18
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +0 -9
- package/dist/types/src/dream/QueryDriver/Postgres.d.ts +9 -9
- package/dist/types/src/dream-app/index.d.ts +12 -12
- package/dist/types/src/encrypt/InternalEncrypt.d.ts +9 -0
- package/dist/types/src/helpers/cli/ASTBuilder.d.ts +11 -101
- package/dist/types/src/helpers/cli/ASTConnectionBuilder.d.ts +40 -37
- package/dist/types/src/helpers/cli/ASTDbTypesBuilder.d.ts +26 -0
- package/dist/types/src/helpers/cli/ASTSchemaBuilder.d.ts +5 -15
- package/dist/types/src/helpers/cli/dbTypesNaming.d.ts +37 -0
- package/dist/types/src/helpers/cli/tableMatchesPattern.d.ts +15 -0
- package/dist/types/src/package-exports/types.d.ts +1 -1
- package/dist/types/src/types/db.d.ts +71 -0
- package/dist/types/src/types/types/db.ts +91 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +55 -54
- package/docs/classes/db.PostgresQueryDriver.html +56 -56
- package/docs/classes/db.QueryDriverBase.html +60 -59
- package/docs/classes/errors.CannotSaveMissingDream.html +2 -2
- package/docs/classes/errors.CheckConstraintViolation.html +3 -3
- package/docs/classes/errors.ColumnOverflow.html +3 -3
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
- package/docs/classes/errors.DecryptionError.html +2 -2
- package/docs/classes/errors.DecryptionParseError.html +2 -2
- package/docs/classes/errors.DecryptionRotationError.html +3 -3
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.InvalidClockTime.html +2 -2
- package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
- package/docs/classes/errors.InvalidDateTime.html +2 -2
- package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
- package/docs/classes/errors.NonLoadedAssociation.html +3 -3
- package/docs/classes/errors.NotNullViolation.html +3 -3
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.SortableScopeDidNotStabilize.html +3 -3
- package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- 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 +19 -19
- package/docs/classes/index.Dream.html +125 -125
- package/docs/classes/index.DreamApp.html +11 -11
- package/docs/classes/index.DreamTransaction.html +3 -3
- package/docs/classes/index.Env.html +5 -5
- package/docs/classes/index.Query.html +65 -65
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +3 -3
- package/docs/classes/system.DreamCLI.html +7 -7
- 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 +4 -4
- 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 +1 -1
- 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/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.DecryptCallbacks.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 +6 -6
- package/docs/interfaces/types.DurationObject.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.EncryptionLegacyKeyUsedEvent.html +4 -4
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.IntrospectedColumn.html +17 -0
- package/docs/interfaces/types.IntrospectedDatabase.html +7 -0
- package/docs/interfaces/types.IntrospectedEnum.html +5 -0
- package/docs/interfaces/types.IntrospectedTable.html +11 -0
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/modules/types.html +1 -1
- 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.OpenapiSchemaCombinatorFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
- 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.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.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 +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- 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.IntrospectedValueType.html +5 -0
- 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 +6 -3
- package/dist/cjs/src/db/helpers/syncDbTypesFiles.js +0 -41
- package/dist/cjs/src/helpers/cli/ASTKyselyCodegenEnhancer.js +0 -380
- package/dist/esm/src/db/helpers/syncDbTypesFiles.js +0 -41
- package/dist/esm/src/helpers/cli/ASTKyselyCodegenEnhancer.js +0 -380
- package/dist/types/src/db/helpers/syncDbTypesFiles.d.ts +0 -1
- package/dist/types/src/helpers/cli/ASTKyselyCodegenEnhancer.d.ts +0 -94
|
@@ -96,9 +96,14 @@ export default function Encrypted(columnOrOptions) {
|
|
|
96
96
|
*/
|
|
97
97
|
if (this.columnSetterGuardActivated)
|
|
98
98
|
return;
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
|
|
99
|
+
// On a persisted record, the ciphertext as loaded or last saved is
|
|
100
|
+
// kept when the current key opens it to the assigned value, so
|
|
101
|
+
// assigning a property the plaintext it already holds leaves the
|
|
102
|
+
// record clean; any other value is encrypted fresh. Either way the
|
|
103
|
+
// value is ciphertext Dream produced, so it bypasses setAttribute's
|
|
104
|
+
// check that a backing column receives only decryptable ciphertext
|
|
105
|
+
const dream = this;
|
|
106
|
+
this.setAttributeUnchecked(encryptedKey, InternalEncrypt.reuseOrEncryptColumn(val, dream.isPersisted ? dream['frozenAttributes'][encryptedKey] : undefined));
|
|
102
107
|
},
|
|
103
108
|
configurable: false,
|
|
104
109
|
});
|
|
@@ -91,14 +91,12 @@ export default class QueryDriverBase {
|
|
|
91
91
|
* comlpex to override. You will need to do the following
|
|
92
92
|
* when overriding this method:
|
|
93
93
|
*
|
|
94
|
-
* 1.
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* to achieve.
|
|
94
|
+
* 1. generate a types/db.ts file in the same shape as the existing one.
|
|
95
|
+
* KyselyQueryDriver does this with the ASTDbTypesBuilder, which writes
|
|
96
|
+
* it from {@link introspectDatabase}.
|
|
98
97
|
* 2. generate a types/dream.ts file in the same shape as the existing
|
|
99
|
-
* one.
|
|
100
|
-
*
|
|
101
|
-
* database engine.
|
|
98
|
+
* one. KyselyQueryDriver does this with the ASTSchemaBuilder, which
|
|
99
|
+
* also reads the connection through {@link introspectDatabase}.
|
|
102
100
|
*/
|
|
103
101
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
104
102
|
static async sync(connectionName, _,
|
|
@@ -292,15 +290,20 @@ export default class QueryDriverBase {
|
|
|
292
290
|
keys) {
|
|
293
291
|
throw new Error('override acquireAdvisoryTransactionLocks in child class');
|
|
294
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Reads the tables, columns and enums of the connection's database, from
|
|
295
|
+
* which `sync` writes the connection's `types/db.ts` and `types/dream.ts`.
|
|
296
|
+
* It returns every table the connection can read, sorted by schema and
|
|
297
|
+
* name; `sync` applies `tableIncludePattern` and `tableExcludePattern`
|
|
298
|
+
* itself.
|
|
299
|
+
*
|
|
300
|
+
* @param connectionName - the connection to read
|
|
301
|
+
*/
|
|
295
302
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
296
|
-
static async
|
|
297
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
298
|
-
connectionName,
|
|
303
|
+
static async introspectDatabase(
|
|
299
304
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
allTableAssociationData) {
|
|
303
|
-
throw new Error('implement getColumnData in child class');
|
|
305
|
+
connectionName) {
|
|
306
|
+
throw new Error('implement introspectDatabase in child class');
|
|
304
307
|
}
|
|
305
308
|
/**
|
|
306
309
|
* @internal
|
|
@@ -695,16 +698,6 @@ export default class QueryDriverBase {
|
|
|
695
698
|
reallyDestroy) {
|
|
696
699
|
throw new Error('implement destroyDream in child class');
|
|
697
700
|
}
|
|
698
|
-
static get syncDialect() {
|
|
699
|
-
return 'postgres';
|
|
700
|
-
}
|
|
701
|
-
/** @internal Resolve the credential used by the database type generator. */
|
|
702
|
-
static codegenPassword(password) {
|
|
703
|
-
if (typeof password === 'function') {
|
|
704
|
-
throw new Error('This database adapter does not support a password provider for type generation');
|
|
705
|
-
}
|
|
706
|
-
return Promise.resolve(password);
|
|
707
|
-
}
|
|
708
701
|
/**
|
|
709
702
|
* Returns the sql that would be executed by this Query
|
|
710
703
|
*
|
|
@@ -12,7 +12,6 @@ import pluralize from 'pluralize-esm';
|
|
|
12
12
|
import { CliFileWriter } from '../../cli/CliFileWriter.js';
|
|
13
13
|
import DreamCLI from '../../cli/index.js';
|
|
14
14
|
import { CHECK_VIOLATION, COLUMN_OVERFLOW, INVALID_INPUT_SYNTAX, NOT_NULL_VIOLATION, pgErrorType, } from '../../db/errors.js';
|
|
15
|
-
import syncDbTypesFiles from '../../db/helpers/syncDbTypesFiles.js';
|
|
16
15
|
import { default as _db } from '../../db/index.js';
|
|
17
16
|
import validateColumn from '../../db/validators/validateColumn.js';
|
|
18
17
|
import associationToGetterSetterProp from '../../decorators/field/association/associationToGetterSetterProp.js';
|
|
@@ -39,8 +38,6 @@ import ColumnOverflow from '../../errors/db/ColumnOverflow.js';
|
|
|
39
38
|
import DataTypeColumnTypeMismatch from '../../errors/db/DataTypeColumnTypeMismatch.js';
|
|
40
39
|
import NotNullViolation from '../../errors/db/NotNullViolation.js';
|
|
41
40
|
import UnexpectedUndefined from '../../errors/UnexpectedUndefined.js';
|
|
42
|
-
import ASTGlobalSchemaBuilder from '../../helpers/cli/ASTGlobalSchemaBuilder.js';
|
|
43
|
-
import ASTSchemaBuilder from '../../helpers/cli/ASTSchemaBuilder.js';
|
|
44
41
|
import generateMigration from '../../helpers/cli/generateMigration.js';
|
|
45
42
|
import compact from '../../helpers/compact.js';
|
|
46
43
|
import { normalizeDataForDb } from '../../helpers/db/normalizeDataForDb.js';
|
|
@@ -51,7 +48,6 @@ import isEmpty from '../../helpers/isEmpty.js';
|
|
|
51
48
|
import maybeNamespacedColumnNameToColumnName from '../../helpers/maybeNamespacedColumnNameToColumnName.js';
|
|
52
49
|
import namespaceColumn from '../../helpers/namespaceColumn.js';
|
|
53
50
|
import objectPathsToArrays from '../../helpers/objectPathsToArrays.js';
|
|
54
|
-
import pascalize from '../../helpers/pascalize.js';
|
|
55
51
|
import protectAgainstPollutingAssignment from '../../helpers/protectAgainstPollutingAssignment.js';
|
|
56
52
|
import { Range } from '../../helpers/range.js';
|
|
57
53
|
import snakeify from '../../helpers/snakeify.js';
|
|
@@ -200,13 +196,16 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
200
196
|
* */
|
|
201
197
|
static async sync(connectionName, onSync, options = {}) {
|
|
202
198
|
try {
|
|
203
|
-
|
|
199
|
+
const { ASTDbTypesBuilder, ASTSchemaBuilder, ASTGlobalSchemaBuilder } = await loadTypeFileBuilders();
|
|
200
|
+
// the schema builder takes the db types builder's reading of the
|
|
201
|
+
// connection, so that a sync reads each connection once for both files
|
|
202
|
+
const dbTypesBuilder = options?.schemaOnly ? undefined : new ASTDbTypesBuilder(connectionName);
|
|
203
|
+
if (dbTypesBuilder) {
|
|
204
204
|
await DreamCLI.logger.logProgress(`introspecting db for connection: ${connectionName}...`, async () => {
|
|
205
|
-
|
|
206
|
-
await syncDbTypesFiles(connectionName);
|
|
205
|
+
await dbTypesBuilder.build();
|
|
207
206
|
});
|
|
208
207
|
}
|
|
209
|
-
const newSchemaBuilder = new ASTSchemaBuilder(connectionName);
|
|
208
|
+
const newSchemaBuilder = new ASTSchemaBuilder(connectionName, { introspectionFrom: dbTypesBuilder });
|
|
210
209
|
await DreamCLI.logger.logProgress(`building dream schema for connection ${connectionName}...`, async () => {
|
|
211
210
|
await newSchemaBuilder.build();
|
|
212
211
|
});
|
|
@@ -243,12 +242,6 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
243
242
|
throw error;
|
|
244
243
|
}
|
|
245
244
|
}
|
|
246
|
-
static get syncDialect() {
|
|
247
|
-
return 'postgres';
|
|
248
|
-
}
|
|
249
|
-
static async codegenPassword(password) {
|
|
250
|
-
return typeof password === 'function' ? await password() : password;
|
|
251
|
-
}
|
|
252
245
|
/**
|
|
253
246
|
* @internal
|
|
254
247
|
*
|
|
@@ -369,15 +362,6 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
369
362
|
await dreamTransaction.runAfterCommitHooks();
|
|
370
363
|
return callbackResponse;
|
|
371
364
|
}
|
|
372
|
-
/**
|
|
373
|
-
* @internal
|
|
374
|
-
*
|
|
375
|
-
* this is used by getColumnData to serialize enums
|
|
376
|
-
*/
|
|
377
|
-
static enumType(row) {
|
|
378
|
-
const enumName = pascalize(row.udtName.replace(/\[\]$/, ''));
|
|
379
|
-
return enumName;
|
|
380
|
-
}
|
|
381
365
|
/**
|
|
382
366
|
* @internal
|
|
383
367
|
*
|
|
@@ -2828,3 +2812,18 @@ function shouldSoftDelete(dream, reallyDestroy) {
|
|
|
2828
2812
|
const dreamClass = dream.constructor;
|
|
2829
2813
|
return dreamClass['softDelete'] && !reallyDestroy;
|
|
2830
2814
|
}
|
|
2815
|
+
/**
|
|
2816
|
+
* The type file builders import `typescript`, a devDependency that a
|
|
2817
|
+
* production install does not have, and this driver is reached from the
|
|
2818
|
+
* package's main entry, so they are loaded only when `sync` runs: in
|
|
2819
|
+
* development, and never in production, where migrations run with
|
|
2820
|
+
* `--skip-sync`.
|
|
2821
|
+
*/
|
|
2822
|
+
async function loadTypeFileBuilders() {
|
|
2823
|
+
const [{ default: ASTDbTypesBuilder }, { default: ASTSchemaBuilder }, { default: ASTGlobalSchemaBuilder }] = await Promise.all([
|
|
2824
|
+
import('../../helpers/cli/ASTDbTypesBuilder.js'),
|
|
2825
|
+
import('../../helpers/cli/ASTSchemaBuilder.js'),
|
|
2826
|
+
import('../../helpers/cli/ASTGlobalSchemaBuilder.js'),
|
|
2827
|
+
]);
|
|
2828
|
+
return { ASTDbTypesBuilder, ASTSchemaBuilder, ASTGlobalSchemaBuilder };
|
|
2829
|
+
}
|
|
@@ -9,11 +9,9 @@
|
|
|
9
9
|
import pg from 'pg';
|
|
10
10
|
import { sql } from 'kysely';
|
|
11
11
|
import DreamCLI from '../../cli/index.js';
|
|
12
|
-
import { isPrimitiveDataType } from '../../db/dataTypes.js';
|
|
13
12
|
import { DEADLOCK_DETECTED, LOCK_NOT_AVAILABLE, pgErrorType, UNIQUE_VIOLATION } from '../../db/errors.js';
|
|
14
13
|
import DreamApp from '../../dream-app/index.js';
|
|
15
14
|
import SortableScopeLockWaitTimedOut from '../../errors/SortableScopeLockWaitTimedOut.js';
|
|
16
|
-
import camelize from '../../helpers/camelize.js';
|
|
17
15
|
import { findCitextArrayOid, findCorrespondingArrayOid, findEnumArrayOids, parsePostgresBigint, parsePostgresDate, parsePostgresDatetime, parsePostgresDatetimeTz, parsePostgresDecimal, parsePostgresTime, parsePostgresTimeTz, } from '../../helpers/customPgParsers.js';
|
|
18
16
|
import { testDatabasePoolSize } from '../../db/testDatabasePool.js';
|
|
19
17
|
import EnvInternal from '../../helpers/EnvInternal.js';
|
|
@@ -139,38 +137,96 @@ export default class PostgresQueryDriver extends KyselyQueryDriver {
|
|
|
139
137
|
}
|
|
140
138
|
}
|
|
141
139
|
/**
|
|
142
|
-
*
|
|
140
|
+
* Reads the tables, views, materialized views, and partitioned and foreign
|
|
141
|
+
* tables of every schema the connection's user can use, except Postgres's
|
|
142
|
+
* own schemas, tables that inherit from another (partitions included) and
|
|
143
|
+
* Kysely's migration tables. A domain column reads as the type at the
|
|
144
|
+
* bottom of its domains. An enum outside the `public` schema is named
|
|
145
|
+
* `<schema>.<name>`.
|
|
143
146
|
*
|
|
144
|
-
*
|
|
145
|
-
* within the types/dream.ts file.
|
|
147
|
+
* @param connectionName - the connection to read
|
|
146
148
|
*/
|
|
147
|
-
static async
|
|
149
|
+
static async introspectDatabase(connectionName) {
|
|
148
150
|
const db = this.dbFor(connectionName, 'primary');
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
151
|
+
const columnRows = (await sql `
|
|
152
|
+
WITH RECURSIVE domain_base(oid, base, domainnotnull) AS (
|
|
153
|
+
SELECT dom.oid, dom.typbasetype, dom.typnotnull
|
|
154
|
+
FROM pg_catalog.pg_type AS dom
|
|
155
|
+
JOIN pg_catalog.pg_type AS typ ON typ.oid = dom.typbasetype
|
|
156
|
+
WHERE typ.typtype <> 'd'
|
|
157
|
+
UNION ALL
|
|
158
|
+
SELECT dom.oid, parent.base, parent.domainnotnull OR dom.typnotnull
|
|
159
|
+
FROM domain_base AS parent
|
|
160
|
+
JOIN pg_catalog.pg_type AS dom ON dom.typbasetype = parent.oid
|
|
161
|
+
)
|
|
162
|
+
SELECT
|
|
163
|
+
ns.nspname AS schemaname,
|
|
164
|
+
cls.relname AS tablename,
|
|
165
|
+
att.attname AS columnname,
|
|
166
|
+
format_type(val.oid, NULL) || CASE WHEN base.typcategory = 'A' THEN '[]' ELSE '' END AS dbtype,
|
|
167
|
+
base.typcategory = 'A' AS isarray,
|
|
168
|
+
format_type(val.oid, NULL) AS valuedbtype,
|
|
169
|
+
CASE WHEN val.typtype = 'e' THEN
|
|
170
|
+
CASE WHEN valns.nspname = 'public' THEN val.typname ELSE valns.nspname || '.' || val.typname END
|
|
171
|
+
END AS enumname,
|
|
172
|
+
NOT (att.attnotnull OR coalesce(columndomain.domainnotnull, false)) AS nullable,
|
|
173
|
+
(att.atthasdef OR att.attidentity <> '') AS hasdefault
|
|
174
|
+
FROM pg_catalog.pg_class AS cls
|
|
175
|
+
JOIN pg_catalog.pg_namespace AS ns ON ns.oid = cls.relnamespace
|
|
176
|
+
JOIN pg_catalog.pg_attribute AS att ON att.attrelid = cls.oid
|
|
177
|
+
LEFT JOIN domain_base AS columndomain ON columndomain.oid = att.atttypid
|
|
178
|
+
JOIN pg_catalog.pg_type AS base ON base.oid = coalesce(columndomain.base, att.atttypid)
|
|
179
|
+
LEFT JOIN domain_base AS elemdomain ON elemdomain.oid = base.typelem
|
|
180
|
+
JOIN pg_catalog.pg_type AS val
|
|
181
|
+
ON val.oid = CASE WHEN base.typcategory = 'A' THEN coalesce(elemdomain.base, base.typelem) ELSE base.oid END
|
|
182
|
+
JOIN pg_catalog.pg_namespace AS valns ON valns.oid = val.typnamespace
|
|
183
|
+
WHERE cls.relkind IN ('r', 'p', 'v', 'm', 'f')
|
|
184
|
+
AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_inherits AS inh WHERE inh.inhrelid = cls.oid)
|
|
185
|
+
AND ns.nspname !~ '^pg_'
|
|
186
|
+
AND ns.nspname <> 'information_schema'
|
|
187
|
+
AND has_schema_privilege(ns.oid, 'USAGE')
|
|
188
|
+
AND cls.relname NOT IN ('kysely_migration', 'kysely_migration_lock')
|
|
189
|
+
AND att.attnum > 0
|
|
190
|
+
AND NOT att.attisdropped
|
|
191
|
+
ORDER BY ns.nspname, cls.relname, att.attnum
|
|
192
|
+
`.execute(db)).rows;
|
|
193
|
+
const enumRows = (await sql `
|
|
194
|
+
SELECT
|
|
195
|
+
CASE WHEN ns.nspname = 'public' THEN typ.typname ELSE ns.nspname || '.' || typ.typname END AS enumname,
|
|
196
|
+
enm.enumlabel AS label
|
|
197
|
+
FROM pg_catalog.pg_enum AS enm
|
|
198
|
+
JOIN pg_catalog.pg_type AS typ ON typ.oid = enm.enumtypid
|
|
199
|
+
JOIN pg_catalog.pg_namespace AS ns ON ns.oid = typ.typnamespace
|
|
200
|
+
`.execute(db)).rows;
|
|
201
|
+
const tables = [];
|
|
202
|
+
for (const row of columnRows) {
|
|
203
|
+
let table = tables.at(-1);
|
|
204
|
+
if (table?.schema !== row.schemaname || table.name !== row.tablename) {
|
|
205
|
+
table = {
|
|
206
|
+
schema: row.schemaname,
|
|
207
|
+
name: row.tablename,
|
|
208
|
+
inDefaultSchema: row.schemaname === 'public',
|
|
209
|
+
columns: [],
|
|
210
|
+
};
|
|
211
|
+
tables.push(table);
|
|
212
|
+
}
|
|
213
|
+
table.columns.push({
|
|
214
|
+
name: row.columnname,
|
|
215
|
+
dbType: row.dbtype,
|
|
216
|
+
valueType: row.enumname ? 'enum' : (POSTGRES_VALUE_TYPES[row.valuedbtype] ?? 'string'),
|
|
217
|
+
enumName: row.enumname,
|
|
218
|
+
isArray: row.isarray,
|
|
219
|
+
allowNull: row.nullable,
|
|
220
|
+
hasDefault: row.hasdefault,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
const enumValues = {};
|
|
224
|
+
for (const row of enumRows)
|
|
225
|
+
(enumValues[row.enumname] ||= []).push(row.label);
|
|
226
|
+
return {
|
|
227
|
+
tables,
|
|
228
|
+
enums: Object.keys(enumValues).map(name => ({ name, values: enumValues[name] })),
|
|
229
|
+
};
|
|
174
230
|
}
|
|
175
231
|
static async duplicateDatabase(connectionName) {
|
|
176
232
|
const dreamApp = DreamApp.getOrFail();
|
|
@@ -353,3 +409,29 @@ export default class PostgresQueryDriver extends KyselyQueryDriver {
|
|
|
353
409
|
};
|
|
354
410
|
}
|
|
355
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* The `types/db.ts` type of one value of each Postgres type Dream reads as
|
|
414
|
+
* something other than a string, keyed by the type's name as `format_type`
|
|
415
|
+
* gives it. Every other type, enums aside, reads as a string.
|
|
416
|
+
*/
|
|
417
|
+
const POSTGRES_VALUE_TYPES = {
|
|
418
|
+
smallint: 'number',
|
|
419
|
+
integer: 'number',
|
|
420
|
+
real: 'number',
|
|
421
|
+
'double precision': 'number',
|
|
422
|
+
oid: 'number',
|
|
423
|
+
bigint: 'Int8',
|
|
424
|
+
numeric: 'Numeric',
|
|
425
|
+
boolean: 'boolean',
|
|
426
|
+
date: 'Timestamp',
|
|
427
|
+
'timestamp without time zone': 'Timestamp',
|
|
428
|
+
'timestamp with time zone': 'Timestamp',
|
|
429
|
+
'time without time zone': 'ClockTime',
|
|
430
|
+
'time with time zone': 'ClockTimeTz',
|
|
431
|
+
json: 'Json',
|
|
432
|
+
jsonb: 'Json',
|
|
433
|
+
bytea: 'Buffer',
|
|
434
|
+
interval: 'Interval',
|
|
435
|
+
point: 'Point',
|
|
436
|
+
circle: 'Circle',
|
|
437
|
+
};
|
|
@@ -14,6 +14,34 @@ export default class InternalEncrypt {
|
|
|
14
14
|
return null;
|
|
15
15
|
return this.doEncryption(data, encryptOpts.current);
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns `existingCiphertext` when the current column key opens it to a
|
|
19
|
+
* value whose JSON serialization equals `data`'s, the plaintext
|
|
20
|
+
* `encryptColumn(data)` would encrypt, and otherwise `encryptColumn(data)`.
|
|
21
|
+
* A value only the legacy key opens, ciphertext no key opens, and a
|
|
22
|
+
* missing `existingCiphertext` all get fresh ciphertext. It never calls
|
|
23
|
+
* `onLegacyKeyUsed`.
|
|
24
|
+
*/
|
|
25
|
+
static reuseOrEncryptColumn(data, existingCiphertext) {
|
|
26
|
+
if (data === null || data === undefined || typeof existingCiphertext !== 'string')
|
|
27
|
+
return this.encryptColumn(data);
|
|
28
|
+
const dreamApp = DreamApp.getOrFail();
|
|
29
|
+
const encryptOpts = dreamApp.encryption?.columns;
|
|
30
|
+
if (!encryptOpts)
|
|
31
|
+
throw new MissingColumnEncryptionOpts();
|
|
32
|
+
let existingPlaintext;
|
|
33
|
+
try {
|
|
34
|
+
existingPlaintext = Encrypt.decrypt(existingCiphertext, encryptOpts.current);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err instanceof DecryptionError || err instanceof DecryptionParseError)
|
|
38
|
+
return this.encryptColumn(data);
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
return JSON.stringify(existingPlaintext) === JSON.stringify(data)
|
|
42
|
+
? existingCiphertext
|
|
43
|
+
: this.encryptColumn(data);
|
|
44
|
+
}
|
|
17
45
|
/**
|
|
18
46
|
* Decrypts `data` with the column keys, current then legacy.
|
|
19
47
|
* `onLegacyKeyUsed` is passed to `Encrypt.decrypt`, so it is called only
|
|
@@ -7,7 +7,7 @@ const f = ts.factory;
|
|
|
7
7
|
* @internal
|
|
8
8
|
*
|
|
9
9
|
* This is a base class, which is inherited by the ASTSchemaBuilder,
|
|
10
|
-
* the
|
|
10
|
+
* the ASTDbTypesBuilder, and the ASTGlobalSchemaBuilder,
|
|
11
11
|
* each of which is responsible for building up the output of the various
|
|
12
12
|
* type files consumed by dream internally.
|
|
13
13
|
*
|
|
@@ -23,131 +23,6 @@ export default class ASTBuilder {
|
|
|
23
23
|
newLine() {
|
|
24
24
|
return f.createIdentifier('\n');
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
* @internal
|
|
28
|
-
*
|
|
29
|
-
* given an interface declaration, it will extrace the relevant property statement
|
|
30
|
-
* by the given property name.
|
|
31
|
-
*/
|
|
32
|
-
getPropertyFromInterface(interfaceNode, propertyName) {
|
|
33
|
-
for (const member of interfaceNode.members) {
|
|
34
|
-
if (ts.isPropertySignature(member)) {
|
|
35
|
-
if (ts.isIdentifier(member.name) && member.name.text === propertyName) {
|
|
36
|
-
return member;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* @internal
|
|
44
|
-
*
|
|
45
|
-
* returns an array of string type literals which were extracted from
|
|
46
|
-
* either a type or type union, depending on what is provided
|
|
47
|
-
* for the typeAlias. this allows you to safely and easily collect
|
|
48
|
-
* an array of types given an alias
|
|
49
|
-
*/
|
|
50
|
-
extractStringLiteralTypeNodesFromTypeOrUnion(typeAlias) {
|
|
51
|
-
const literals = [];
|
|
52
|
-
if (ts.isUnionTypeNode(typeAlias.type)) {
|
|
53
|
-
typeAlias.type.types.forEach(typeNode => {
|
|
54
|
-
if (ts.isLiteralTypeNode(typeNode) && ts.isStringLiteral(typeNode.literal)) {
|
|
55
|
-
literals.push(typeNode);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
else if (ts.isLiteralTypeNode(typeAlias.type) && ts.isStringLiteral(typeAlias.type.literal)) {
|
|
60
|
-
literals.push(typeAlias.type);
|
|
61
|
-
}
|
|
62
|
-
return literals;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* @internal
|
|
66
|
-
*
|
|
67
|
-
* returns an array of type literals which were extracted from
|
|
68
|
-
* either a type or type union, depending on what is provided
|
|
69
|
-
* for the typeAlias. this allows you to safely and easily collect
|
|
70
|
-
* an array of types given an alias
|
|
71
|
-
*/
|
|
72
|
-
extractTypeNodesFromTypeOrUnion(typeAlias) {
|
|
73
|
-
const literals = [];
|
|
74
|
-
if (typeAlias.type && ts.isUnionTypeNode(typeAlias.type)) {
|
|
75
|
-
typeAlias.type.types.forEach(typeNode => {
|
|
76
|
-
literals.push(typeNode);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
else if (typeAlias.type) {
|
|
80
|
-
literals.push(typeAlias.type);
|
|
81
|
-
}
|
|
82
|
-
return literals;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* @internal
|
|
86
|
-
*
|
|
87
|
-
* returns the provided node iff
|
|
88
|
-
* a.) the node is an exported type alias
|
|
89
|
-
* b.) the exported name matches the provided name (or else there was no name provided)
|
|
90
|
-
*
|
|
91
|
-
* otherwise, returns null
|
|
92
|
-
*/
|
|
93
|
-
exportedTypeAliasOrNull(node, exportName) {
|
|
94
|
-
if (ts.isTypeAliasDeclaration(node) &&
|
|
95
|
-
node?.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) &&
|
|
96
|
-
(!exportName ? true : node.name.text === exportName))
|
|
97
|
-
return node;
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* @internal
|
|
102
|
-
*
|
|
103
|
-
* returns the provided node iff
|
|
104
|
-
* a.) the node is an exported interface
|
|
105
|
-
* b.) the exported name matches the provided name (or else there was no name provided)
|
|
106
|
-
*
|
|
107
|
-
* otherwise, returns null
|
|
108
|
-
*/
|
|
109
|
-
exportedInterfaceOrNull(node, exportName) {
|
|
110
|
-
if (ts.isInterfaceDeclaration(node) &&
|
|
111
|
-
node?.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) &&
|
|
112
|
-
(!exportName ? true : node.name.text === exportName))
|
|
113
|
-
return node;
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* @internal
|
|
118
|
-
*
|
|
119
|
-
* extracts the exportName from the provided dbSourceFile
|
|
120
|
-
*/
|
|
121
|
-
findDbExport(dbSourceFile, exportName) {
|
|
122
|
-
let foundNode;
|
|
123
|
-
ts.forEachChild(dbSourceFile, node => {
|
|
124
|
-
const hasModifiers = ts.isFunctionDeclaration(node) ||
|
|
125
|
-
ts.isClassDeclaration(node) ||
|
|
126
|
-
ts.isInterfaceDeclaration(node) ||
|
|
127
|
-
ts.isVariableStatement(node) ||
|
|
128
|
-
ts.isTypeAliasDeclaration(node);
|
|
129
|
-
if (hasModifiers) {
|
|
130
|
-
const isExported = node.modifiers?.some(modifier => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
131
|
-
if (isExported && ts.isVariableStatement(node)) {
|
|
132
|
-
const declarations = node.declarationList.declarations;
|
|
133
|
-
const name = declarations?.[0]?.name;
|
|
134
|
-
if (declarations.length > 0 && ts.isIdentifier(name) && name?.text === exportName) {
|
|
135
|
-
foundNode = node;
|
|
136
|
-
return true; // Stop traversal
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const declarationWithName = node;
|
|
140
|
-
if (isExported &&
|
|
141
|
-
declarationWithName.name &&
|
|
142
|
-
ts.isIdentifier(declarationWithName.name) &&
|
|
143
|
-
declarationWithName.name.text === exportName) {
|
|
144
|
-
foundNode = node;
|
|
145
|
-
return true; // Stop traversal
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
return foundNode;
|
|
150
|
-
}
|
|
151
26
|
/**
|
|
152
27
|
* @internal
|
|
153
28
|
*
|
|
@@ -189,25 +64,6 @@ export default class ASTBuilder {
|
|
|
189
64
|
return output;
|
|
190
65
|
}
|
|
191
66
|
}
|
|
192
|
-
/**
|
|
193
|
-
* @internal
|
|
194
|
-
*
|
|
195
|
-
* given a type node, it will send back the first found generic
|
|
196
|
-
* provided to that type.
|
|
197
|
-
*/
|
|
198
|
-
getFirstGenericType(node) {
|
|
199
|
-
if (ts.isTypeReferenceNode(node)) {
|
|
200
|
-
if (node.typeArguments && node.typeArguments.length > 0) {
|
|
201
|
-
return node.typeArguments[0];
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else if (ts.isCallExpression(node)) {
|
|
205
|
-
if (node.typeArguments && node.typeArguments.length > 0) {
|
|
206
|
-
return node.typeArguments[0];
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
67
|
/**
|
|
212
68
|
* @internal
|
|
213
69
|
*
|
|
@@ -251,28 +107,6 @@ export default class ASTBuilder {
|
|
|
251
107
|
return [importDeclaration];
|
|
252
108
|
}
|
|
253
109
|
}
|
|
254
|
-
/**
|
|
255
|
-
* @internal
|
|
256
|
-
*
|
|
257
|
-
* for a given table name (i.e. balloon_lines), it will return the exported
|
|
258
|
-
* `BalloonLines` interface within the dbSourceFile
|
|
259
|
-
*/
|
|
260
|
-
getTableInterfaceDeclaration(dbSourceFile, tableName) {
|
|
261
|
-
const DB = this.findDbExport(dbSourceFile, 'DB');
|
|
262
|
-
let targetProperty = null;
|
|
263
|
-
for (const member of DB.members) {
|
|
264
|
-
if (ts.isPropertySignature(member) && member.name.getText(dbSourceFile) === tableName) {
|
|
265
|
-
targetProperty = member;
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
const tableInterfaceName = (targetProperty?.type)
|
|
270
|
-
.typeName?.escapedText;
|
|
271
|
-
if (!tableInterfaceName)
|
|
272
|
-
throw new Error(`failed to find table interface for table: ${tableName}`);
|
|
273
|
-
const tableInterface = this.findDbExport(dbSourceFile, tableInterfaceName);
|
|
274
|
-
return tableInterface;
|
|
275
|
-
}
|
|
276
110
|
/**
|
|
277
111
|
* @internal
|
|
278
112
|
*
|
|
@@ -291,39 +125,14 @@ export default class ASTBuilder {
|
|
|
291
125
|
isDateDbType(dbType) {
|
|
292
126
|
return /^date[[\]]*$/.test(dbType);
|
|
293
127
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
*
|
|
305
|
-
* checks if a database type is a time with time zone type (with optional array suffix)
|
|
306
|
-
*/
|
|
307
|
-
isTimeWithTimeZoneDbType(dbType) {
|
|
308
|
-
return /^time with time zone[[\]]*$/.test(dbType);
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* @internal
|
|
312
|
-
*
|
|
313
|
-
* checks if a database type is any time type (with or without time zone, with optional array suffix)
|
|
314
|
-
*/
|
|
315
|
-
isTimeDbType(dbType) {
|
|
316
|
-
return /^time (without|with) time zone(\[\])?$/.test(dbType);
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* @internal
|
|
320
|
-
*
|
|
321
|
-
* checks if a TypeScript type node represents a string-like type
|
|
322
|
-
* (string keyword, string type reference, or string literal)
|
|
323
|
-
*/
|
|
324
|
-
isStringLikeType(node, sourceFile) {
|
|
325
|
-
return (node.kind === ts.SyntaxKind.StringKeyword ||
|
|
326
|
-
(ts.isTypeReferenceNode(node) && node.typeName.getText(sourceFile) === 'string') ||
|
|
327
|
-
(ts.isLiteralTypeNode(node) && ts.isStringLiteral(node.literal)));
|
|
328
|
-
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* @internal
|
|
131
|
+
*
|
|
132
|
+
* A property name for an object literal, interface or class: the name itself
|
|
133
|
+
* when it is an identifier, and a string literal otherwise, such as a table
|
|
134
|
+
* outside the default schema (`inventory.parts`).
|
|
135
|
+
*/
|
|
136
|
+
export function propertyName(name) {
|
|
137
|
+
return /^[A-Za-z_$][\w$]*$/.test(name) ? f.createIdentifier(name) : f.createStringLiteral(name);
|
|
329
138
|
}
|