@rvoh/dream 2.3.0-alpha.6 → 2.3.0-alpha.8
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 +2 -40
- package/dist/cjs/src/cli/index.js +4 -0
- package/dist/cjs/src/dream/Query.js +14 -11
- package/dist/cjs/src/dream/QueryDriver/Base.js +0 -14
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +86 -74
- package/dist/cjs/src/dream/QueryDriver/Postgres.js +10 -2
- package/dist/cjs/src/dream/internal/extractAssignableAssociationAttributes.js +9 -0
- package/dist/cjs/src/errors/db/DataIncompatibleWithDatabaseField.js +1 -3
- package/dist/cjs/src/helpers/areEqual.js +5 -0
- package/dist/cjs/src/helpers/cli/ASTBuilder.js +54 -2
- package/dist/cjs/src/helpers/cli/ASTKyselyCodegenEnhancer.js +84 -0
- package/dist/cjs/src/helpers/cli/ASTSchemaBuilder.js +17 -1
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +16 -0
- package/dist/cjs/src/helpers/cloneDeepSafe.js +21 -10
- package/dist/cjs/src/helpers/customPgParsers.js +18 -1
- package/dist/cjs/src/helpers/db/normalizeDataForDb.js +81 -0
- package/dist/cjs/src/helpers/db/types/helpers.js +5 -0
- package/dist/cjs/src/helpers/db/types/isDatetimeOrDatetimeArrayColumn.js +2 -1
- package/dist/cjs/src/helpers/sortBy.js +7 -5
- package/dist/cjs/src/helpers/sqlAttributes.js +4 -53
- package/dist/cjs/src/helpers/stringCasing.js +6 -5
- package/dist/cjs/src/helpers/toSafeObject.js +17 -0
- package/dist/cjs/src/package-exports/errors.js +2 -0
- package/dist/cjs/src/package-exports/index.js +2 -0
- package/dist/cjs/src/serializer/SerializerRenderer.js +11 -11
- package/dist/cjs/src/types/clocktime.js +1 -0
- package/dist/cjs/src/utils/datetime/BaseClockTime.js +363 -0
- package/dist/cjs/src/utils/datetime/CalendarDate.js +110 -119
- package/dist/cjs/src/utils/datetime/ClockTime.js +173 -0
- package/dist/cjs/src/utils/datetime/ClockTimeTz.js +232 -0
- package/dist/cjs/src/utils/datetime/DateTime.js +288 -193
- package/dist/cjs/src/utils/datetime/helpers/isoTimeDecimalString.js +1 -1
- package/dist/esm/src/Dream.js +2 -40
- package/dist/esm/src/cli/index.js +4 -0
- package/dist/esm/src/dream/Query.js +14 -11
- package/dist/esm/src/dream/QueryDriver/Base.js +0 -14
- package/dist/esm/src/dream/QueryDriver/Kysely.js +86 -74
- package/dist/esm/src/dream/QueryDriver/Postgres.js +10 -2
- package/dist/esm/src/dream/internal/extractAssignableAssociationAttributes.js +9 -0
- package/dist/esm/src/errors/db/DataIncompatibleWithDatabaseField.js +1 -3
- package/dist/esm/src/helpers/areEqual.js +5 -0
- package/dist/esm/src/helpers/cli/ASTBuilder.js +54 -2
- package/dist/esm/src/helpers/cli/ASTKyselyCodegenEnhancer.js +84 -0
- package/dist/esm/src/helpers/cli/ASTSchemaBuilder.js +17 -1
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +16 -0
- package/dist/esm/src/helpers/cloneDeepSafe.js +21 -10
- package/dist/esm/src/helpers/customPgParsers.js +18 -1
- package/dist/esm/src/helpers/db/normalizeDataForDb.js +81 -0
- package/dist/esm/src/helpers/db/types/helpers.js +5 -0
- package/dist/esm/src/helpers/db/types/isDatetimeOrDatetimeArrayColumn.js +2 -1
- package/dist/esm/src/helpers/sortBy.js +7 -5
- package/dist/esm/src/helpers/sqlAttributes.js +4 -53
- package/dist/esm/src/helpers/stringCasing.js +6 -5
- package/dist/esm/src/helpers/toSafeObject.js +17 -0
- package/dist/esm/src/package-exports/errors.js +2 -0
- package/dist/esm/src/package-exports/index.js +2 -0
- package/dist/esm/src/serializer/SerializerRenderer.js +11 -11
- package/dist/esm/src/types/clocktime.js +1 -0
- package/dist/esm/src/utils/datetime/BaseClockTime.js +363 -0
- package/dist/esm/src/utils/datetime/CalendarDate.js +110 -119
- package/dist/esm/src/utils/datetime/ClockTime.js +173 -0
- package/dist/esm/src/utils/datetime/ClockTimeTz.js +232 -0
- package/dist/esm/src/utils/datetime/DateTime.js +288 -193
- package/dist/esm/src/utils/datetime/helpers/isoTimeDecimalString.js +1 -1
- package/dist/types/src/Dream.d.ts +29 -33
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +9 -10
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +16 -16
- package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +1 -1
- package/dist/types/src/dream/LoadBuilder.d.ts +1 -1
- package/dist/types/src/dream/Query.d.ts +16 -16
- package/dist/types/src/dream/QueryDriver/Base.d.ts +0 -1
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +1 -0
- package/dist/types/src/dream/internal/associations/associationQuery.d.ts +1 -1
- package/dist/types/src/dream/internal/associations/associationUpdateQuery.d.ts +1 -1
- package/dist/types/src/dream/internal/associations/destroyAssociation.d.ts +1 -1
- package/dist/types/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.d.ts +4 -2
- package/dist/types/src/dream/internal/associations/undestroyAssociation.d.ts +1 -1
- package/dist/types/src/dream/internal/extractAssignableAssociationAttributes.d.ts +3 -0
- package/dist/types/src/dream/internal/similarity/SimilarityBuilder.d.ts +7 -7
- package/dist/types/src/errors/db/DataIncompatibleWithDatabaseField.d.ts +2 -7
- package/dist/types/src/helpers/cli/ASTBuilder.d.ts +31 -0
- package/dist/types/src/helpers/cli/ASTKyselyCodegenEnhancer.d.ts +13 -0
- package/dist/types/src/helpers/customPgParsers.d.ts +5 -0
- package/dist/types/src/helpers/db/normalizeDataForDb.d.ts +6 -0
- package/dist/types/src/helpers/db/types/helpers.d.ts +5 -0
- package/dist/types/src/helpers/sort.d.ts +2 -1
- package/dist/types/src/helpers/sortBy.d.ts +3 -0
- package/dist/types/src/helpers/toSafeObject.d.ts +8 -0
- package/dist/types/src/package-exports/errors.d.ts +2 -0
- package/dist/types/src/package-exports/index.d.ts +2 -0
- package/dist/types/src/package-exports/types.d.ts +2 -1
- package/dist/types/src/types/associations/shared.d.ts +15 -13
- package/dist/types/src/types/associations/shared.ts +81 -41
- package/dist/types/src/types/calendardate.d.ts +22 -1
- package/dist/types/src/types/calendardate.ts +33 -1
- package/dist/types/src/types/clocktime.d.ts +22 -0
- package/dist/types/src/types/clocktime.ts +59 -0
- package/dist/types/src/types/datetime.d.ts +11 -18
- package/dist/types/src/types/datetime.ts +16 -21
- package/dist/types/src/types/dream.d.ts +27 -13
- package/dist/types/src/types/dream.ts +40 -14
- package/dist/types/src/types/variadic.d.ts +10 -9
- package/dist/types/src/types/variadic.ts +30 -5
- package/dist/types/src/utils/datetime/BaseClockTime.d.ts +287 -0
- package/dist/types/src/utils/datetime/CalendarDate.d.ts +65 -47
- package/dist/types/src/utils/datetime/ClockTime.d.ts +138 -0
- package/dist/types/src/utils/datetime/ClockTimeTz.d.ts +194 -0
- package/dist/types/src/utils/datetime/DateTime.d.ts +142 -56
- package/dist/types/src/utils/datetime/helpers/isoTimeDecimalString.d.ts +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +9 -9
- package/docs/classes/db.KyselyQueryDriver.html +33 -34
- package/docs/classes/db.PostgresQueryDriver.html +34 -35
- package/docs/classes/db.QueryDriverBase.html +32 -33
- package/docs/classes/errors.CheckConstraintViolation.html +4 -6
- package/docs/classes/errors.ColumnOverflow.html +4 -6
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +4 -6
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +4 -6
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.InvalidClockTime.html +17 -0
- package/docs/classes/errors.InvalidClockTimeTz.html +17 -0
- 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 +4 -6
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- package/docs/classes/index.CalendarDate.html +80 -92
- package/docs/classes/index.ClockTime.html +232 -0
- package/docs/classes/index.ClockTimeTz.html +253 -0
- package/docs/classes/index.DateTime.html +123 -129
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +127 -127
- package/docs/classes/index.DreamApp.html +5 -5
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +71 -71
- package/docs/classes/system.CliFileWriter.html +2 -2
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +5 -5
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +8 -8
- package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +2 -2
- 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-1.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/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.DurationObject.html +5 -5
- 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/modules/db.html +1 -1
- package/docs/modules/errors.html +3 -1
- package/docs/modules/index.html +3 -1
- package/docs/modules/openapi.html +1 -1
- package/docs/modules/system.html +1 -1
- package/docs/modules/types.html +3 -1
- package/docs/modules/utils.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.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 +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +1 -1
- 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 +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- 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 +2 -0
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.ClockTimeObject.html +2 -0
- 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 +1 -1
- 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 +2 -4
- 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 +1 -1
- 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-1.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/system.primaryKeyTypes.html +1 -1
- package/package.json +2 -2
- package/dist/cjs/src/helpers/db/types/isDateOrDateArrayColumn.js +0 -3
- package/dist/cjs/src/helpers/db/types/isTextOrTextArrayColumn.js +0 -3
- package/dist/esm/src/helpers/db/types/isDateOrDateArrayColumn.js +0 -3
- package/dist/esm/src/helpers/db/types/isTextOrTextArrayColumn.js +0 -3
- package/dist/types/src/helpers/db/types/isDateOrDateArrayColumn.d.ts +0 -2
- package/dist/types/src/helpers/db/types/isTextOrTextArrayColumn.d.ts +0 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Dream from '../Dream.js';
|
|
2
|
+
import { ClockTime, ClockTimeTz } from '../package-exports/index.js';
|
|
2
3
|
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
3
4
|
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
4
5
|
/**
|
|
@@ -34,6 +35,10 @@ function areEqualOrUndefined(a, b) {
|
|
|
34
35
|
return b instanceof DateTime && a.equals(b);
|
|
35
36
|
if (a instanceof CalendarDate)
|
|
36
37
|
return b instanceof CalendarDate && a.equals(b);
|
|
38
|
+
if (a instanceof ClockTime)
|
|
39
|
+
return b instanceof ClockTime && a.equals(b);
|
|
40
|
+
if (a instanceof ClockTimeTz)
|
|
41
|
+
return b instanceof ClockTimeTz && a.equals(b);
|
|
37
42
|
if (Array.isArray(a))
|
|
38
43
|
return Array.isArray(b) && a.length === b.length && !a.find((value, index) => !areEqual(value, b[index]));
|
|
39
44
|
if (a instanceof Dream)
|
|
@@ -229,10 +229,19 @@ export default class ASTBuilder {
|
|
|
229
229
|
dateTimeNamedImports // namedBindings
|
|
230
230
|
);
|
|
231
231
|
const dateTimeImportDeclaration = ts.factory.createImportDeclaration(undefined, dateTimeImportClause, ts.factory.createStringLiteral('../../src/utils/datetime/DateTime.js'));
|
|
232
|
-
|
|
232
|
+
const clockTimeImport = ts.factory.createImportClause(true, f.createIdentifier('ClockTime'), undefined);
|
|
233
|
+
const clockTimeImportDeclaration = ts.factory.createImportDeclaration(undefined, clockTimeImport, ts.factory.createStringLiteral('../../src/utils/datetime/ClockTime.js'));
|
|
234
|
+
const clockTimeTzImport = ts.factory.createImportClause(true, f.createIdentifier('ClockTimeTz'), undefined);
|
|
235
|
+
const clockTimeTzImportDeclaration = ts.factory.createImportDeclaration(undefined, clockTimeTzImport, ts.factory.createStringLiteral('../../src/utils/datetime/ClockTimeTz.js'));
|
|
236
|
+
return [
|
|
237
|
+
calendarImportDeclaration,
|
|
238
|
+
dateTimeImportDeclaration,
|
|
239
|
+
clockTimeImportDeclaration,
|
|
240
|
+
clockTimeTzImportDeclaration,
|
|
241
|
+
];
|
|
233
242
|
}
|
|
234
243
|
else {
|
|
235
|
-
const namedImports = ts.factory.createNamedImports(['CalendarDate', 'DateTime'].map(importName => f.createImportSpecifier(true, undefined, ts.factory.createIdentifier(importName))));
|
|
244
|
+
const namedImports = ts.factory.createNamedImports(['CalendarDate', 'DateTime', 'ClockTime', 'ClockTimeTz'].map(importName => f.createImportSpecifier(true, undefined, ts.factory.createIdentifier(importName))));
|
|
236
245
|
const importClause = ts.factory.createImportClause(false, // isTypeOnly: false for the clause itself if not all imports are type only
|
|
237
246
|
undefined, // name: undefined for default import
|
|
238
247
|
namedImports // namedBindings
|
|
@@ -274,4 +283,47 @@ export default class ASTBuilder {
|
|
|
274
283
|
const serializers = dreamApp.serializers;
|
|
275
284
|
return Object.keys(serializers);
|
|
276
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* @internal
|
|
288
|
+
*
|
|
289
|
+
* checks if a database type is a date type (with optional array suffix)
|
|
290
|
+
*/
|
|
291
|
+
isDateDbType(dbType) {
|
|
292
|
+
return /^date[[\]]*$/.test(dbType);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* @internal
|
|
296
|
+
*
|
|
297
|
+
* checks if a database type is a time without time zone type (with optional array suffix)
|
|
298
|
+
*/
|
|
299
|
+
isTimeWithoutTimeZoneDbType(dbType) {
|
|
300
|
+
return /^time without time zone[[\]]*$/.test(dbType);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* @internal
|
|
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
|
+
}
|
|
277
329
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { CliFileWriter } from '../../cli/CliFileWriter.js';
|
|
3
3
|
import camelize from '../camelize.js';
|
|
4
|
+
import snakeify from '../snakeify.js';
|
|
4
5
|
import ASTConnectionBuilder from './ASTConnectionBuilder.js';
|
|
5
6
|
import autogeneratedFileDisclaimer from './autoGeneratedFileDisclaimer.js';
|
|
6
7
|
const f = ts.factory;
|
|
@@ -25,6 +26,7 @@ export default class ASTKyselyCodegenEnhancer extends ASTConnectionBuilder {
|
|
|
25
26
|
let dbSourceFile = await this.getDbSourceFile();
|
|
26
27
|
dbSourceFile = this.camelizeKeys(dbSourceFile);
|
|
27
28
|
dbSourceFile = this.replaceTimestampExport(dbSourceFile);
|
|
29
|
+
dbSourceFile = await this.replaceTimeFieldsInInterfaces(dbSourceFile);
|
|
28
30
|
dbSourceFile = this.addMissingImports(dbSourceFile);
|
|
29
31
|
dbSourceFile = this.replaceInt8Export(dbSourceFile);
|
|
30
32
|
dbSourceFile = this.sortExportedInterfacesTransformer(dbSourceFile);
|
|
@@ -90,6 +92,88 @@ ${output}`);
|
|
|
90
92
|
const result = ts.transform(dbSourceFile, [transformer]);
|
|
91
93
|
return result.transformed[0];
|
|
92
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* @internal
|
|
97
|
+
*
|
|
98
|
+
* Replaces string types with TimeWithZone or TimeWithoutZone for TIME columns
|
|
99
|
+
* based on the schema metadata from dream.ts
|
|
100
|
+
*/
|
|
101
|
+
async replaceTimeFieldsInInterfaces(dbSourceFile) {
|
|
102
|
+
const schemaData = await this.getSchemaData();
|
|
103
|
+
const transformer = context => {
|
|
104
|
+
return sourceFile => {
|
|
105
|
+
const visitor = (node) => {
|
|
106
|
+
if (ts.isInterfaceDeclaration(node) && node.name.text !== 'DB') {
|
|
107
|
+
const tableName = snakeify(node.name.text);
|
|
108
|
+
const tableSchema = schemaData[tableName];
|
|
109
|
+
if (!tableSchema) {
|
|
110
|
+
return ts.visitEachChild(node, visitor, context);
|
|
111
|
+
}
|
|
112
|
+
const updatedMembers = node.members.map(member => {
|
|
113
|
+
if (ts.isPropertySignature(member) && ts.isIdentifier(member.name)) {
|
|
114
|
+
const columnName = member.name.text;
|
|
115
|
+
const columnSchema = tableSchema.columns[columnName];
|
|
116
|
+
if (!columnSchema)
|
|
117
|
+
return member;
|
|
118
|
+
const dbType = columnSchema.dbType;
|
|
119
|
+
// Check if this is a TIME field that's currently typed as string
|
|
120
|
+
if (this.isTimeDbType(dbType) && member.type) {
|
|
121
|
+
const isTimeTz = this.isTimeWithTimeZoneDbType(dbType);
|
|
122
|
+
const newType = this.replaceStringWithClockTimeType(member.type, sourceFile, isTimeTz);
|
|
123
|
+
if (newType !== member.type) {
|
|
124
|
+
return f.updatePropertySignature(member, member.modifiers, member.name, member.questionToken, newType);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return member;
|
|
129
|
+
});
|
|
130
|
+
return f.updateInterfaceDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, updatedMembers);
|
|
131
|
+
}
|
|
132
|
+
return ts.visitEachChild(node, visitor, context);
|
|
133
|
+
};
|
|
134
|
+
return ts.visitNode(sourceFile, visitor);
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
const result = ts.transform(dbSourceFile, [transformer]);
|
|
138
|
+
return result.transformed[0];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* @internal
|
|
142
|
+
*
|
|
143
|
+
* Helper to replace string type references with ClockTime or ClockTimeTz type references
|
|
144
|
+
*/
|
|
145
|
+
replaceStringWithClockTimeType(typeNode, sourceFile, isTimeTz) {
|
|
146
|
+
const toTimeType = () => f.createTypeReferenceNode(f.createIdentifier(isTimeTz ? 'ClockTimeTz' : 'ClockTime'));
|
|
147
|
+
// Handle union types (e.g., string | null)
|
|
148
|
+
if (ts.isUnionTypeNode(typeNode)) {
|
|
149
|
+
const updatedTypes = typeNode.types.map(t => this.replaceStringWithClockTimeType(t, sourceFile, isTimeTz));
|
|
150
|
+
return f.createUnionTypeNode(updatedTypes);
|
|
151
|
+
}
|
|
152
|
+
// Handle array syntax (e.g., string[])
|
|
153
|
+
if (ts.isArrayTypeNode(typeNode)) {
|
|
154
|
+
const elementType = this.isStringLikeType(typeNode.elementType, sourceFile)
|
|
155
|
+
? toTimeType()
|
|
156
|
+
: this.replaceStringWithClockTimeType(typeNode.elementType, sourceFile, isTimeTz);
|
|
157
|
+
return f.createArrayTypeNode(elementType);
|
|
158
|
+
}
|
|
159
|
+
// Handle generic array syntax (e.g., Array<string>)
|
|
160
|
+
if (ts.isTypeReferenceNode(typeNode) &&
|
|
161
|
+
typeNode.typeName.getText(sourceFile) === 'Array' &&
|
|
162
|
+
typeNode.typeArguments?.length === 1) {
|
|
163
|
+
const arg = typeNode.typeArguments?.[0];
|
|
164
|
+
if (!arg)
|
|
165
|
+
return typeNode;
|
|
166
|
+
const nextArg = this.isStringLikeType(arg, sourceFile)
|
|
167
|
+
? toTimeType()
|
|
168
|
+
: this.replaceStringWithClockTimeType(arg, sourceFile, isTimeTz);
|
|
169
|
+
return f.createTypeReferenceNode(f.createIdentifier('Array'), [nextArg]);
|
|
170
|
+
}
|
|
171
|
+
// Handle direct string type
|
|
172
|
+
if (this.isStringLikeType(typeNode, sourceFile)) {
|
|
173
|
+
return toTimeType();
|
|
174
|
+
}
|
|
175
|
+
return typeNode;
|
|
176
|
+
}
|
|
93
177
|
/**
|
|
94
178
|
* @internal
|
|
95
179
|
*
|
|
@@ -262,7 +262,9 @@ ${output}`;
|
|
|
262
262
|
*/
|
|
263
263
|
coercedType(dbSourceFile, propertySignature, dbType, importedModules) {
|
|
264
264
|
const extractedPropertyTypes = this.extractTypeNodesFromTypeOrUnion(propertySignature);
|
|
265
|
-
const isDate =
|
|
265
|
+
const isDate = this.isDateDbType(dbType);
|
|
266
|
+
const isTime = this.isTimeWithoutTimeZoneDbType(dbType);
|
|
267
|
+
const isTimeTz = this.isTimeWithTimeZoneDbType(dbType);
|
|
266
268
|
const types = compact(extractedPropertyTypes.map(typeNode => {
|
|
267
269
|
const typeText = typeNode.getText(dbSourceFile);
|
|
268
270
|
let defaultReturnNode = /^Generated/.test(typeText) ? this.getFirstGenericType(typeNode) : typeNode;
|
|
@@ -287,6 +289,20 @@ ${output}`;
|
|
|
287
289
|
return isDate
|
|
288
290
|
? f.createArrayTypeNode(f.createTypeReferenceNode('CalendarDate'))
|
|
289
291
|
: f.createArrayTypeNode(f.createTypeReferenceNode('DateTime'));
|
|
292
|
+
case 'string':
|
|
293
|
+
// Kysely-codegen types TIME columns as string, we need to check dbType
|
|
294
|
+
if (isTime)
|
|
295
|
+
return f.createTypeReferenceNode('ClockTime');
|
|
296
|
+
if (isTimeTz)
|
|
297
|
+
return f.createTypeReferenceNode('ClockTimeTz');
|
|
298
|
+
return defaultReturnNode;
|
|
299
|
+
case 'string[]':
|
|
300
|
+
// Kysely-codegen types TIME[] columns as string[], we need to check dbType
|
|
301
|
+
if (isTime)
|
|
302
|
+
return f.createArrayTypeNode(f.createTypeReferenceNode('ClockTime'));
|
|
303
|
+
if (isTimeTz)
|
|
304
|
+
return f.createArrayTypeNode(f.createTypeReferenceNode('ClockTimeTz'));
|
|
305
|
+
return defaultReturnNode;
|
|
290
306
|
case 'Int8':
|
|
291
307
|
return f.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
|
|
292
308
|
case 'Int8[]':
|
|
@@ -97,6 +97,22 @@ export default function generateFactoryContent({ fullyQualifiedModelName, column
|
|
|
97
97
|
dreamImports.push('DateTime');
|
|
98
98
|
attributeDefaults.push(`${attributeVariable}: [DateTime.now()],`);
|
|
99
99
|
break;
|
|
100
|
+
case 'time':
|
|
101
|
+
dreamImports.push('ClockTime');
|
|
102
|
+
attributeDefaults.push(`${attributeVariable}: ClockTime.now(),`);
|
|
103
|
+
break;
|
|
104
|
+
case 'time[]':
|
|
105
|
+
dreamImports.push('ClockTime');
|
|
106
|
+
attributeDefaults.push(`${attributeVariable}: [ClockTime.now()],`);
|
|
107
|
+
break;
|
|
108
|
+
case 'timetz':
|
|
109
|
+
dreamImports.push('ClockTimeTz');
|
|
110
|
+
attributeDefaults.push(`${attributeVariable}: ClockTimeTz.now(),`);
|
|
111
|
+
break;
|
|
112
|
+
case 'timetz[]':
|
|
113
|
+
dreamImports.push('ClockTimeTz');
|
|
114
|
+
attributeDefaults.push(`${attributeVariable}: [ClockTimeTz.now()],`);
|
|
115
|
+
break;
|
|
100
116
|
case 'uuid':
|
|
101
117
|
nodeImports.push('randomUUID');
|
|
102
118
|
attributeDefaults.push(`${attributeVariable}: randomUUID(),`);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Dream from '../Dream.js';
|
|
2
2
|
import OpsStatement from '../ops/ops-statement.js';
|
|
3
|
+
import BaseClockTime from '../utils/datetime/BaseClockTime.js';
|
|
3
4
|
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
4
5
|
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
5
6
|
import isObject from './isObject.js';
|
|
@@ -24,14 +25,13 @@ export default function cloneDeepSafe(original, unsupportedTypeCloneFunction) {
|
|
|
24
25
|
return original;
|
|
25
26
|
if (['number', 'boolean', 'bigint', 'symbol'].includes(typeof original))
|
|
26
27
|
return original;
|
|
27
|
-
if (original instanceof DateTime
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return original;
|
|
33
|
-
if (original instanceof OpsStatement)
|
|
28
|
+
if (original instanceof DateTime ||
|
|
29
|
+
original instanceof CalendarDate ||
|
|
30
|
+
original instanceof BaseClockTime ||
|
|
31
|
+
original instanceof Range ||
|
|
32
|
+
original instanceof OpsStatement) {
|
|
34
33
|
return original;
|
|
34
|
+
}
|
|
35
35
|
if (original instanceof Dream)
|
|
36
36
|
return original['clone']();
|
|
37
37
|
if (original?.isDreamQuery)
|
|
@@ -40,9 +40,20 @@ export default function cloneDeepSafe(original, unsupportedTypeCloneFunction) {
|
|
|
40
40
|
return original;
|
|
41
41
|
if (Array.isArray(original))
|
|
42
42
|
return original.map(value => cloneDeepSafe(value, unsupportedTypeCloneFunction));
|
|
43
|
-
if
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
// complex check here to ensure that if the object to clone was
|
|
44
|
+
// created using Object.create(null), we cannot access the constructor,
|
|
45
|
+
// and instead of to check that the original prototype is null
|
|
46
|
+
const isObjectLike = isObject(original) &&
|
|
47
|
+
(original.constructor?.name === 'Object' || Object.getPrototypeOf(original) === null);
|
|
48
|
+
if (isObjectLike) {
|
|
49
|
+
// if we are provided with an object that has a null prototype, create a new
|
|
50
|
+
// object with a null prototype to append to. Otherwise, create a standard
|
|
51
|
+
// object clone.
|
|
52
|
+
const clone = Object.getPrototypeOf(original) === null ? Object.create(null) : { ...original };
|
|
53
|
+
Object.keys(original).forEach(key => {
|
|
54
|
+
;
|
|
55
|
+
clone[key] = cloneDeepSafe(original[key], unsupportedTypeCloneFunction);
|
|
56
|
+
});
|
|
46
57
|
return clone;
|
|
47
58
|
}
|
|
48
59
|
if (unsupportedTypeCloneFunction)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
2
|
+
import ClockTime from '../utils/datetime/ClockTime.js';
|
|
3
|
+
import ClockTimeTz from '../utils/datetime/ClockTimeTz.js';
|
|
2
4
|
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
3
5
|
export async function findEnumArrayOids(kyselyDb) {
|
|
4
6
|
const result = await kyselyDb.selectFrom('pg_type').select('typarray').where('typtype', '=', 'e').execute();
|
|
@@ -24,7 +26,22 @@ export function parsePostgresDate(dateString) {
|
|
|
24
26
|
return dateString ? CalendarDate.fromSQL(dateString) : dateString;
|
|
25
27
|
}
|
|
26
28
|
export function parsePostgresDatetime(datetimeString) {
|
|
27
|
-
|
|
29
|
+
if (!datetimeString)
|
|
30
|
+
return datetimeString;
|
|
31
|
+
return DateTime.fromSQL(datetimeString, { zone: 'UTC' });
|
|
32
|
+
}
|
|
33
|
+
export function parsePostgresDatetimeTz(datetimeString) {
|
|
34
|
+
return parsePostgresDatetime(datetimeString);
|
|
35
|
+
}
|
|
36
|
+
export function parsePostgresTime(timeString) {
|
|
37
|
+
if (!timeString)
|
|
38
|
+
return timeString;
|
|
39
|
+
return ClockTime.fromSQL(timeString);
|
|
40
|
+
}
|
|
41
|
+
export function parsePostgresTimeTz(timeString) {
|
|
42
|
+
if (!timeString)
|
|
43
|
+
return timeString;
|
|
44
|
+
return ClockTimeTz.fromSQL(timeString, { zone: 'UTC' });
|
|
28
45
|
}
|
|
29
46
|
export function parsePostgresDecimal(numberString) {
|
|
30
47
|
return numberString ? parseFloat(numberString) : numberString;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import DataTypeColumnTypeMismatch from '../../errors/db/DataTypeColumnTypeMismatch.js';
|
|
2
|
+
import BaseClockTime from '../../utils/datetime/BaseClockTime.js';
|
|
3
|
+
import CalendarDate from '../../utils/datetime/CalendarDate.js';
|
|
4
|
+
import ClockTime from '../../utils/datetime/ClockTime.js';
|
|
5
|
+
import ClockTimeTz from '../../utils/datetime/ClockTimeTz.js';
|
|
6
|
+
import { DateTime } from '../../utils/datetime/DateTime.js';
|
|
7
|
+
import normalizeUnicode from '../normalizeUnicode.js';
|
|
8
|
+
import { DATE_OR_DATE_ARRAY_COLUMN_CHECK_REGEXP, DATETIME_OR_DATETIME_ARRAY_COLUMN_CHECK_REGEXP, STRING_OR_STRING_ARRAY_COLUMN_CHECK_REGEXP, TIME_WITH_TIMEZONE_COLUMN_CHECK_REGEXP, TIME_WITHOUT_TIMEZONE_COLUMN_CHECK_REGEXP, } from './types/helpers.js';
|
|
9
|
+
export function normalizeDataForDb({ val, dreamClass, column, }) {
|
|
10
|
+
const columnType = dreamClass['cachedTypeFor'](column);
|
|
11
|
+
if (val instanceof DateTime || DATETIME_OR_DATETIME_ARRAY_COLUMN_CHECK_REGEXP.test(columnType)) {
|
|
12
|
+
return dateTimeOrDateToSql(DateTime, val);
|
|
13
|
+
//
|
|
14
|
+
}
|
|
15
|
+
else if (val instanceof CalendarDate || DATE_OR_DATE_ARRAY_COLUMN_CHECK_REGEXP.test(columnType)) {
|
|
16
|
+
return dateTimeOrDateToSql(CalendarDate, val);
|
|
17
|
+
//
|
|
18
|
+
}
|
|
19
|
+
else if (val instanceof ClockTime || TIME_WITHOUT_TIMEZONE_COLUMN_CHECK_REGEXP.test(columnType)) {
|
|
20
|
+
return clockTimeOrClockTimeTzToSql(ClockTime, val);
|
|
21
|
+
//
|
|
22
|
+
}
|
|
23
|
+
else if (val instanceof ClockTimeTz || TIME_WITH_TIMEZONE_COLUMN_CHECK_REGEXP.test(columnType)) {
|
|
24
|
+
return clockTimeOrClockTimeTzToSql(ClockTimeTz, val);
|
|
25
|
+
//
|
|
26
|
+
}
|
|
27
|
+
else if (typeof val === 'string' || STRING_OR_STRING_ARRAY_COLUMN_CHECK_REGEXP.test(columnType)) {
|
|
28
|
+
return normalizedString(val);
|
|
29
|
+
//
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return val;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function normalizedString(_val) {
|
|
36
|
+
const alreadyAnArray = Array.isArray(_val);
|
|
37
|
+
const normalizedValueArray = (alreadyAnArray ? _val : [_val]).map(val => typeof val === 'string' ? normalizeUnicode(val) : val);
|
|
38
|
+
return alreadyAnArray ? normalizedValueArray : normalizedValueArray[0];
|
|
39
|
+
}
|
|
40
|
+
function dateTimeOrDateToSql(dateClass, _val) {
|
|
41
|
+
const alreadyAnArray = Array.isArray(_val);
|
|
42
|
+
const normalizedValueArray = (alreadyAnArray ? _val : [_val]).map(val => {
|
|
43
|
+
if (val === null || val === undefined)
|
|
44
|
+
return val;
|
|
45
|
+
if (val instanceof DateTime || val instanceof CalendarDate)
|
|
46
|
+
return val.toSQL();
|
|
47
|
+
try {
|
|
48
|
+
if (typeof val !== 'string') {
|
|
49
|
+
throw new DataTypeColumnTypeMismatch(new Error(`database column type error: invalid ${dateClass.name} (received ${typeof val})`));
|
|
50
|
+
}
|
|
51
|
+
return dateClass.fromISO(val, { zone: 'UTC' }).toSQL();
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new DataTypeColumnTypeMismatch(error instanceof Error
|
|
55
|
+
? error
|
|
56
|
+
: new Error(`database column type error: invalid ${dateClass.name} (received ${typeof val}: ${val})`));
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return alreadyAnArray ? normalizedValueArray : normalizedValueArray[0];
|
|
60
|
+
}
|
|
61
|
+
function clockTimeOrClockTimeTzToSql(clockTimeClass, _val) {
|
|
62
|
+
const alreadyAnArray = Array.isArray(_val);
|
|
63
|
+
const normalizedValueArray = (alreadyAnArray ? _val : [_val]).map(val => {
|
|
64
|
+
if (val === null || val === undefined)
|
|
65
|
+
return val;
|
|
66
|
+
if (val instanceof BaseClockTime)
|
|
67
|
+
return val.toSQL();
|
|
68
|
+
try {
|
|
69
|
+
if (typeof val !== 'string') {
|
|
70
|
+
throw new DataTypeColumnTypeMismatch(new Error(`database column type error: invalid ${clockTimeClass.name} (received ${typeof val})`));
|
|
71
|
+
}
|
|
72
|
+
return clockTimeClass.fromISO(val, { zone: 'UTC' }).toSQL();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
throw new DataTypeColumnTypeMismatch(error instanceof Error
|
|
76
|
+
? error
|
|
77
|
+
: new Error(`database column type error: invalid ${clockTimeClass.name} (received ${typeof val}: ${val})`));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return alreadyAnArray ? normalizedValueArray : normalizedValueArray[0];
|
|
81
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export const DATETIME_OR_DATETIME_ARRAY_COLUMN_CHECK_REGEXP = /^timestamp/;
|
|
2
|
+
export const DATE_OR_DATE_ARRAY_COLUMN_CHECK_REGEXP = /^date/;
|
|
3
|
+
export const TIME_WITH_TIMEZONE_COLUMN_CHECK_REGEXP = /^time with time zone/;
|
|
4
|
+
export const TIME_WITHOUT_TIMEZONE_COLUMN_CHECK_REGEXP = /^time without time zone/;
|
|
5
|
+
export const STRING_OR_STRING_ARRAY_COLUMN_CHECK_REGEXP = /^(text|character varying|citext)/;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DATETIME_OR_DATETIME_ARRAY_COLUMN_CHECK_REGEXP } from './helpers.js';
|
|
1
2
|
export default function isDatetimeOrDatetimeArrayColumn(dreamClass, column) {
|
|
2
|
-
return
|
|
3
|
+
return DATETIME_OR_DATETIME_ARRAY_COLUMN_CHECK_REGEXP.test(dreamClass['cachedTypeFor'](column));
|
|
3
4
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ClockTime, ClockTimeTz } from '../package-exports/index.js';
|
|
1
2
|
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
2
3
|
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
3
4
|
/**
|
|
@@ -26,11 +27,12 @@ export default function sortBy(array, valueToCompare) {
|
|
|
26
27
|
return aPrime > bPrime ? 1 : aPrime < bPrime ? -1 : 0;
|
|
27
28
|
if (typeof aPrime === 'string' && typeof bPrime === 'string')
|
|
28
29
|
return aPrime.localeCompare(bPrime);
|
|
29
|
-
if (aPrime instanceof DateTime
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
(
|
|
33
|
-
return
|
|
30
|
+
if (((aPrime instanceof DateTime || aPrime instanceof CalendarDate) &&
|
|
31
|
+
(bPrime instanceof DateTime || bPrime instanceof CalendarDate)) ||
|
|
32
|
+
(aPrime instanceof ClockTime && bPrime instanceof ClockTime) ||
|
|
33
|
+
(aPrime instanceof ClockTimeTz && bPrime instanceof ClockTimeTz)) {
|
|
34
|
+
return aPrime.valueOf().localeCompare(bPrime.valueOf());
|
|
35
|
+
}
|
|
34
36
|
throw new UnsupportedValueFromComparisonFunction(aPrime, bPrime);
|
|
35
37
|
});
|
|
36
38
|
}
|
|
@@ -1,61 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import DataTypeColumnTypeMismatch from '../errors/db/DataTypeColumnTypeMismatch.js';
|
|
3
|
-
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
4
|
-
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
5
|
-
import isDatetimeOrDatetimeArrayColumn from './db/types/isDatetimeOrDatetimeArrayColumn.js';
|
|
6
|
-
import isTextOrTextArrayColumn from './db/types/isTextOrTextArrayColumn.js';
|
|
7
|
-
import normalizeUnicode from './normalizeUnicode.js';
|
|
1
|
+
import { normalizeDataForDb } from './db/normalizeDataForDb.js';
|
|
8
2
|
export default function sqlAttributes(dream) {
|
|
9
3
|
const attributes = dream.dirtyAttributes();
|
|
10
4
|
const dreamClass = dream.constructor;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
let val = attributes[key];
|
|
5
|
+
return Object.keys(attributes).reduce((result, column) => {
|
|
6
|
+
const val = attributes[column];
|
|
14
7
|
if (val === undefined)
|
|
15
8
|
return result;
|
|
16
|
-
|
|
17
|
-
if (isDatetimeOrDatetimeArrayColumn(dreamClass, key))
|
|
18
|
-
val = val.map(aVal => valueToDatetime(dream, aVal));
|
|
19
|
-
else if (isTextOrTextArrayColumn(dreamClass, key))
|
|
20
|
-
val = val.map(normalizeUnicode);
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
if (isDatetimeOrDatetimeArrayColumn(dreamClass, key))
|
|
24
|
-
val = valueToDatetime(dream, val);
|
|
25
|
-
else if (isTextOrTextArrayColumn(dreamClass, key))
|
|
26
|
-
val = normalizeUnicode(val);
|
|
27
|
-
}
|
|
28
|
-
if (val instanceof DateTime || val instanceof CalendarDate) {
|
|
29
|
-
const dateOrDatetime = val instanceof DateTime ? 'datetime' : 'date';
|
|
30
|
-
// Converting toJSDate resulted in the correct timezone, but even with process.env.TZ=UTC,
|
|
31
|
-
// Kysely inserted into the database with the machine timezone, which can shift the date
|
|
32
|
-
// (e.g., toJSDate resulted in a JS Date that formats as "1987-04-07T00:00:00.000Z", but
|
|
33
|
-
// Kysely inserted "1907-04-06" into the database). By converting to an SQL string before
|
|
34
|
-
// handing off to Kysely, we bypass Javascript dates altogether, sending the string into the
|
|
35
|
-
// database for storage as a date or datetime.
|
|
36
|
-
result[key] = queryDriverClass.serializeDbType(dateOrDatetime, val);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
result[key] = val;
|
|
40
|
-
}
|
|
9
|
+
result[column] = normalizeDataForDb({ val, dreamClass, column });
|
|
41
10
|
return result;
|
|
42
11
|
}, {});
|
|
43
12
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Convert datetimes to UTC
|
|
46
|
-
*/
|
|
47
|
-
function valueToDatetime(dream, val) {
|
|
48
|
-
if (typeof val !== 'string')
|
|
49
|
-
return val;
|
|
50
|
-
let datetime;
|
|
51
|
-
try {
|
|
52
|
-
datetime = DateTime.fromISO(val, { zone: 'UTC' });
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
throw new DataTypeColumnTypeMismatch({
|
|
56
|
-
dream,
|
|
57
|
-
error: error instanceof Error ? error : new Error('database column type error'),
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
return datetime.isValid ? datetime : val;
|
|
61
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Dream from '../Dream.js';
|
|
2
|
+
import BaseClockTime from '../utils/datetime/BaseClockTime.js';
|
|
2
3
|
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
3
4
|
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
4
5
|
import isObject from './isObject.js';
|
|
@@ -17,12 +18,12 @@ function recursiveStringCase(target, stringCaser) {
|
|
|
17
18
|
if (Array.isArray(target))
|
|
18
19
|
return target.map(s => recursiveStringCase(s, stringCaser));
|
|
19
20
|
if (isObject(target)) {
|
|
20
|
-
if (target instanceof DateTime
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (target instanceof Dream)
|
|
21
|
+
if (target instanceof DateTime ||
|
|
22
|
+
target instanceof CalendarDate ||
|
|
23
|
+
target instanceof BaseClockTime ||
|
|
24
|
+
target instanceof Dream) {
|
|
25
25
|
return target;
|
|
26
|
+
}
|
|
26
27
|
return Object.keys(target).reduce((stringCasedObject, targetKey) => {
|
|
27
28
|
stringCasedObject[stringCaser(targetKey)] = recursiveStringCase(target[targetKey], stringCaser);
|
|
28
29
|
return stringCasedObject;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*
|
|
4
|
+
* Returns a shallow copy of the object using a prototype-less container
|
|
5
|
+
* (Object.create(null)). Use when assigning untrusted keys so that keys like
|
|
6
|
+
* __proto__ or constructor cannot pollute Object.prototype.
|
|
7
|
+
*/
|
|
8
|
+
export function toSafeObject(obj) {
|
|
9
|
+
if (obj === null || typeof obj !== 'object')
|
|
10
|
+
return obj;
|
|
11
|
+
const safe = Object.create(null);
|
|
12
|
+
for (const key of Object.keys(obj)) {
|
|
13
|
+
;
|
|
14
|
+
safe[key] = obj[key];
|
|
15
|
+
}
|
|
16
|
+
return safe;
|
|
17
|
+
}
|
|
@@ -11,4 +11,6 @@ export { default as RecordNotFound } from '../errors/RecordNotFound.js';
|
|
|
11
11
|
export { default as MissingSerializersDefinition } from '../errors/serializers/MissingSerializersDefinition.js';
|
|
12
12
|
export { default as ValidationError } from '../errors/ValidationError.js';
|
|
13
13
|
export { InvalidCalendarDate } from '../utils/datetime/CalendarDate.js';
|
|
14
|
+
export { InvalidClockTime } from '../utils/datetime/ClockTime.js';
|
|
15
|
+
export { InvalidClockTimeTz } from '../utils/datetime/ClockTimeTz.js';
|
|
14
16
|
export { InvalidDateTime } from '../utils/datetime/DateTime.js';
|
|
@@ -12,4 +12,6 @@ export { default as ops } from '../ops/index.js';
|
|
|
12
12
|
export { default as DreamSerializer } from '../serializer/DreamSerializer.js';
|
|
13
13
|
export { default as ObjectSerializer } from '../serializer/ObjectSerializer.js';
|
|
14
14
|
export { default as CalendarDate } from '../utils/datetime/CalendarDate.js';
|
|
15
|
+
export { default as ClockTime } from '../utils/datetime/ClockTime.js';
|
|
16
|
+
export { default as ClockTimeTz } from '../utils/datetime/ClockTimeTz.js';
|
|
15
17
|
export { DateTime } from '../utils/datetime/DateTime.js';
|
|
@@ -2,6 +2,7 @@ import RendersManyMustReceiveArray from '../errors/serializers/RendersManyMustRe
|
|
|
2
2
|
import compact from '../helpers/compact.js';
|
|
3
3
|
import round from '../helpers/round.js';
|
|
4
4
|
import snakeify from '../helpers/snakeify.js';
|
|
5
|
+
import BaseClockTime from '../utils/datetime/BaseClockTime.js';
|
|
5
6
|
import CalendarDate from '../utils/datetime/CalendarDate.js';
|
|
6
7
|
import { DateTime } from '../utils/datetime/DateTime.js';
|
|
7
8
|
import DreamSerializerBuilder from './builders/DreamSerializerBuilder.js';
|
|
@@ -42,7 +43,7 @@ export default class SerializerRenderer {
|
|
|
42
43
|
const value = data[attribute.name] ?? attribute.options?.default;
|
|
43
44
|
if (value === undefined && attribute.options?.required === false)
|
|
44
45
|
return accumulator;
|
|
45
|
-
accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, attribute.options, this.passthroughData, this.renderOpts);
|
|
46
|
+
accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(data, value, attribute.name, attribute.options, this.passthroughData, this.renderOpts);
|
|
46
47
|
return accumulator;
|
|
47
48
|
}
|
|
48
49
|
/////////////////////
|
|
@@ -57,7 +58,7 @@ export default class SerializerRenderer {
|
|
|
57
58
|
const value = target?.[attribute.name] ?? attribute.options?.default;
|
|
58
59
|
if (value === undefined && attribute.options?.required === false)
|
|
59
60
|
return accumulator;
|
|
60
|
-
accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, attribute.options, this.passthroughData, this.renderOpts);
|
|
61
|
+
accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(target, value, attribute.name, attribute.options, this.passthroughData, this.renderOpts);
|
|
61
62
|
return accumulator;
|
|
62
63
|
}
|
|
63
64
|
//////////////////////////////
|
|
@@ -77,11 +78,11 @@ export default class SerializerRenderer {
|
|
|
77
78
|
if (attribute.options.flatten) {
|
|
78
79
|
return {
|
|
79
80
|
...accumulator,
|
|
80
|
-
...applyRenderingOptionsToAttribute(value, {}, this.passthroughData, this.renderOpts),
|
|
81
|
+
...applyRenderingOptionsToAttribute(null, value, attribute.name, {}, this.passthroughData, this.renderOpts),
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
84
|
else {
|
|
84
|
-
accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(value, {}, this.passthroughData, this.renderOpts);
|
|
85
|
+
accumulator[outputAttributeName] = applyRenderingOptionsToAttribute(null, value, attribute.name, {}, this.passthroughData, this.renderOpts);
|
|
85
86
|
return accumulator;
|
|
86
87
|
}
|
|
87
88
|
}
|
|
@@ -187,18 +188,17 @@ export default class SerializerRenderer {
|
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
|
-
function applyRenderingOptionsToAttribute(value, options, passthroughData, renderOptions) {
|
|
191
|
+
function applyRenderingOptionsToAttribute(data, value, attributeName, options, passthroughData, renderOptions) {
|
|
191
192
|
if (Array.isArray(value))
|
|
192
|
-
return value.map(val => _applyRenderingOptionsToAttribute(val, options, passthroughData, renderOptions));
|
|
193
|
-
return _applyRenderingOptionsToAttribute(value, options, passthroughData, renderOptions);
|
|
193
|
+
return value.map(val => _applyRenderingOptionsToAttribute(data, val, attributeName, options, passthroughData, renderOptions));
|
|
194
|
+
return _applyRenderingOptionsToAttribute(data, value, attributeName, options, passthroughData, renderOptions);
|
|
194
195
|
}
|
|
195
|
-
function _applyRenderingOptionsToAttribute(value, options, passthroughData, renderOptions) {
|
|
196
|
+
function _applyRenderingOptionsToAttribute(data, value, attributeName, options, passthroughData, renderOptions) {
|
|
196
197
|
if (value instanceof DreamSerializerBuilder || value instanceof ObjectSerializerBuilder)
|
|
197
198
|
return value.render(passthroughData, renderOptions);
|
|
198
|
-
if (value instanceof DateTime)
|
|
199
|
-
return value.toISO();
|
|
200
|
-
if (value instanceof CalendarDate)
|
|
199
|
+
if (value instanceof DateTime || value instanceof CalendarDate || value instanceof BaseClockTime) {
|
|
201
200
|
return value.toISO();
|
|
201
|
+
}
|
|
202
202
|
if (typeof value === 'bigint')
|
|
203
203
|
return value.toString();
|
|
204
204
|
const precision = options?.precision;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|