@rvoh/dream 2.3.0 → 2.3.2
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/bin/index.js +9 -2
- package/dist/cjs/src/cli/index.js +11 -2
- package/dist/cjs/src/dream/Query.js +9 -1
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +11 -10
- package/dist/cjs/src/dream-app/index.js +2 -0
- package/dist/cjs/src/helpers/cli/generateDream.js +16 -21
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +2 -2
- package/dist/cjs/src/helpers/cli/generateFactory.js +8 -22
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +1 -2
- package/dist/cjs/src/helpers/cli/generateMigration.js +18 -26
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +27 -2
- package/dist/cjs/src/helpers/cli/generateSerializer.js +10 -23
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +5 -7
- package/dist/cjs/src/helpers/cli/generateUnitSpec.js +7 -21
- package/dist/cjs/src/helpers/cli/modelClassNameFrom.js +15 -0
- package/dist/cjs/src/helpers/cli/writeGeneratedFile.js +26 -0
- package/dist/esm/src/bin/index.js +9 -2
- package/dist/esm/src/cli/index.js +11 -2
- package/dist/esm/src/dream/Query.js +9 -1
- package/dist/esm/src/dream/QueryDriver/Kysely.js +11 -10
- package/dist/esm/src/dream-app/index.js +2 -0
- package/dist/esm/src/helpers/cli/generateDream.js +16 -21
- package/dist/esm/src/helpers/cli/generateDreamContent.js +2 -2
- package/dist/esm/src/helpers/cli/generateFactory.js +8 -22
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +1 -2
- package/dist/esm/src/helpers/cli/generateMigration.js +18 -26
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +27 -2
- package/dist/esm/src/helpers/cli/generateSerializer.js +10 -23
- package/dist/esm/src/helpers/cli/generateSerializerContent.js +5 -7
- package/dist/esm/src/helpers/cli/generateUnitSpec.js +7 -21
- package/dist/esm/src/helpers/cli/modelClassNameFrom.js +15 -0
- package/dist/esm/src/helpers/cli/writeGeneratedFile.js +26 -0
- package/dist/types/src/bin/index.d.ts +5 -0
- package/dist/types/src/cli/index.d.ts +11 -0
- package/dist/types/src/dream-app/index.d.ts +2 -0
- package/dist/types/src/helpers/cli/generateDream.d.ts +9 -6
- package/dist/types/src/helpers/cli/generateDreamContent.d.ts +3 -0
- package/dist/types/src/helpers/cli/generateFactory.d.ts +2 -1
- package/dist/types/src/helpers/cli/generateFactoryContent.d.ts +3 -1
- package/dist/types/src/helpers/cli/generateMigration.d.ts +8 -1
- package/dist/types/src/helpers/cli/generateSerializer.d.ts +2 -1
- package/dist/types/src/helpers/cli/generateSerializerContent.d.ts +3 -1
- package/dist/types/src/helpers/cli/modelClassNameFrom.d.ts +9 -0
- package/dist/types/src/helpers/cli/writeGeneratedFile.d.ts +18 -0
- package/dist/types/src/helpers/compact.d.ts +2 -2
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +9 -9
- package/docs/classes/db.KyselyQueryDriver.html +32 -32
- package/docs/classes/db.PostgresQueryDriver.html +33 -33
- package/docs/classes/db.QueryDriverBase.html +31 -31
- 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.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.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 +71 -71
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +116 -116
- package/docs/classes/index.DreamApp.html +10 -5
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +56 -56
- package/docs/classes/system.CliFileWriter.html +2 -2
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +9 -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 +2 -2
- 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 +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/modules/db.html +1 -1
- package/docs/modules/errors.html +1 -1
- package/docs/modules/index.html +1 -1
- package/docs/modules/openapi.html +1 -1
- package/docs/modules/system.html +1 -1
- package/docs/modules/types.html +1 -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 +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 +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 +1 -1
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.PrimaryKeyType.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +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 +4 -2
|
@@ -46,14 +46,21 @@ export default class DreamBin {
|
|
|
46
46
|
await generateDream({
|
|
47
47
|
fullyQualifiedModelName,
|
|
48
48
|
columnsWithTypes,
|
|
49
|
-
options: {
|
|
49
|
+
options: {
|
|
50
|
+
includeAdminSerializers: options.adminSerializers ?? false,
|
|
51
|
+
...options,
|
|
52
|
+
},
|
|
50
53
|
});
|
|
51
54
|
}
|
|
52
55
|
static async generateStiChild(fullyQualifiedModelName, fullyQualifiedParentName, columnsWithTypes, options) {
|
|
53
56
|
await generateDream({
|
|
54
57
|
fullyQualifiedModelName,
|
|
55
58
|
columnsWithTypes,
|
|
56
|
-
options: {
|
|
59
|
+
options: {
|
|
60
|
+
includeAdminSerializers: options.adminSerializers ?? false,
|
|
61
|
+
...options,
|
|
62
|
+
stiBaseSerializer: false,
|
|
63
|
+
},
|
|
57
64
|
fullyQualifiedParentName,
|
|
58
65
|
});
|
|
59
66
|
}
|
|
@@ -6,8 +6,9 @@ import EnvInternal from '../helpers/EnvInternal.js';
|
|
|
6
6
|
import loadRepl from '../helpers/loadRepl.js';
|
|
7
7
|
import sspawn from '../helpers/sspawn.js';
|
|
8
8
|
import DreamCliLogger from './logger/DreamCliLogger.js';
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
export const CLI_INDENT = ' ';
|
|
10
|
+
const INDENT = CLI_INDENT;
|
|
11
|
+
export const baseColumnsWithTypesDescription = `space separated snake-case (except for belongs_to model name) properties like this:
|
|
11
12
|
${INDENT} title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to
|
|
12
13
|
${INDENT}
|
|
13
14
|
${INDENT}all properties default to not nullable; null can be allowed by appending ':optional':
|
|
@@ -99,6 +100,9 @@ export default class DreamCLI {
|
|
|
99
100
|
}
|
|
100
101
|
/**
|
|
101
102
|
* @internal
|
|
103
|
+
*
|
|
104
|
+
* Called by Psychic (and other consumers) to programmatically generate a
|
|
105
|
+
* Dream model with all associated files.
|
|
102
106
|
*/
|
|
103
107
|
static async generateDream(opts) {
|
|
104
108
|
await generateDream(opts);
|
|
@@ -128,6 +132,9 @@ export default class DreamCLI {
|
|
|
128
132
|
.option('--no-serializer')
|
|
129
133
|
.option('--connection-name <connectionName>', 'the db connection you want this attached to (defaults to the default db connection)', 'default')
|
|
130
134
|
.option('--sti-base-serializer')
|
|
135
|
+
.option('--table-name <tableName>', 'explicit table name to use instead of the auto-generated one (useful when model namespaces produce long names)')
|
|
136
|
+
.option('--model-name <modelName>', 'explicit model class name to use instead of the auto-generated one (e.g. --model-name=Kitchen for Room/Kitchen)')
|
|
137
|
+
.option('--admin-serializers', 'generate admin serializer variants (AdminSerializer and AdminSummarySerializer) in addition to the default serializers')
|
|
131
138
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
132
139
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
133
140
|
.action(async (modelName, columnsWithTypes, options) => {
|
|
@@ -141,6 +148,8 @@ export default class DreamCLI {
|
|
|
141
148
|
.description('Generates a Dream model that extends another Dream model, leveraging STI (single table inheritance), with corresponding spec factory, serializer, and migration.')
|
|
142
149
|
.option('--no-serializer')
|
|
143
150
|
.option('--connection-name', 'the db connection you want this model attached to (defaults to the default connection)', 'default')
|
|
151
|
+
.option('--model-name <modelName>', 'explicit model class name to use instead of the auto-generated one (e.g. --model-name=Kitchen for Room/Kitchen)')
|
|
152
|
+
.option('--admin-serializers', 'generate admin serializer variants (AdminSerializer and AdminSummarySerializer) in addition to the default serializers')
|
|
144
153
|
.argument('<childModelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
145
154
|
.argument('<extends>', 'just the word "extends"')
|
|
146
155
|
.argument('<parentModelName>', `fully qualified name of the parent model, e.g.:
|
|
@@ -20,6 +20,8 @@ import ops from '../ops/index.js';
|
|
|
20
20
|
import computedPaginatePage from './internal/computedPaginatePage.js';
|
|
21
21
|
import convertDreamClassAndAssociationNameTupleArrayToPreloadArgs from './internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.js';
|
|
22
22
|
import extractNestedPaths from './internal/extractNestedPaths.js';
|
|
23
|
+
// Cache for extractNestedPaths results, keyed by "${sanitizedName}:${serializerKey}"
|
|
24
|
+
const extractedNestedPathsCache = new Map();
|
|
23
25
|
export default class Query {
|
|
24
26
|
/**
|
|
25
27
|
* @internal
|
|
@@ -524,7 +526,13 @@ export default class Query {
|
|
|
524
526
|
* @returns A Query with all serialization associations preloaded
|
|
525
527
|
*/
|
|
526
528
|
preloadFor(serializerKey, modifierFn) {
|
|
527
|
-
const
|
|
529
|
+
const cacheKey = `${this.dreamClass.sanitizedName}:${serializerKey ?? 'default'}`;
|
|
530
|
+
let preloadArgs = extractedNestedPathsCache.get(cacheKey);
|
|
531
|
+
if (!preloadArgs) {
|
|
532
|
+
// Cache miss - compute and store
|
|
533
|
+
preloadArgs = extractNestedPaths(this.dreamClass['serializationMap'](serializerKey));
|
|
534
|
+
extractedNestedPathsCache.set(cacheKey, preloadArgs);
|
|
535
|
+
}
|
|
528
536
|
let query = this;
|
|
529
537
|
preloadArgs.forEach(dreamClassAndAssociationNameTupleArray => {
|
|
530
538
|
query = query.preload(...convertDreamClassAndAssociationNameTupleArrayToPreloadArgs(dreamClassAndAssociationNameTupleArray, modifierFn));
|
|
@@ -33,7 +33,6 @@ import ColumnOverflow from '../../errors/db/ColumnOverflow.js';
|
|
|
33
33
|
import DataTypeColumnTypeMismatch from '../../errors/db/DataTypeColumnTypeMismatch.js';
|
|
34
34
|
import NotNullViolation from '../../errors/db/NotNullViolation.js';
|
|
35
35
|
import UnexpectedUndefined from '../../errors/UnexpectedUndefined.js';
|
|
36
|
-
import camelize from '../../helpers/camelize.js';
|
|
37
36
|
import ASTGlobalSchemaBuilder from '../../helpers/cli/ASTGlobalSchemaBuilder.js';
|
|
38
37
|
import ASTSchemaBuilder from '../../helpers/cli/ASTSchemaBuilder.js';
|
|
39
38
|
import generateMigration from '../../helpers/cli/generateMigration.js';
|
|
@@ -533,18 +532,20 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
533
532
|
let kyselyQuery = new this.constructor(this.query).buildSelect({
|
|
534
533
|
bypassSelectAll: true,
|
|
535
534
|
});
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
535
|
+
// Use short aliases to avoid PostgreSQL's 63-byte identifier truncation.
|
|
536
|
+
// Previously, the full namespaced field (e.g. "longAlias.columnName") was used as the
|
|
537
|
+
// AS alias, which Kysely's CamelCasePlugin converts to a single snake_case identifier
|
|
538
|
+
// that can exceed 63 bytes. Short aliases like "pluck0" avoid this entirely.
|
|
539
|
+
const shortAliases = [];
|
|
540
|
+
fields.forEach((field, index) => {
|
|
541
|
+
const shortAlias = `pluck${index}`;
|
|
542
|
+
shortAliases.push(shortAlias);
|
|
542
543
|
// namespace the selection so that when plucking the same column name from
|
|
543
|
-
//
|
|
544
|
+
// multiple tables, they don't get saved as the same name (e.g. select results with two `id` columns,
|
|
544
545
|
// which the pg package then returns in an object with a single `id` key)
|
|
545
|
-
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(field)} as ${
|
|
546
|
+
kyselyQuery = kyselyQuery.select(`${this.namespaceColumn(field)} as ${shortAlias}`);
|
|
546
547
|
});
|
|
547
|
-
return (await executeDatabaseQuery(kyselyQuery, 'execute')).map(singleResult =>
|
|
548
|
+
return (await executeDatabaseQuery(kyselyQuery, 'execute')).map(singleResult => shortAliases.map(alias => singleResult[alias]));
|
|
548
549
|
}
|
|
549
550
|
/**
|
|
550
551
|
* Returns a new Kysely SelectQueryBuilder instance to be used
|
|
@@ -7,6 +7,7 @@ import DreamAppInitMissingCallToLoadModels from '../errors/dream-app/DreamAppIni
|
|
|
7
7
|
import DreamAppInitMissingMissingProjectRoot from '../errors/dream-app/DreamAppInitMissingMissingProjectRoot.js';
|
|
8
8
|
import DreamAppInitMissingPackageManager from '../errors/dream-app/DreamAppInitMissingPackageManager.js';
|
|
9
9
|
import autogeneratedFileDisclaimer from '../helpers/cli/autoGeneratedFileDisclaimer.js';
|
|
10
|
+
import modelClassNameFrom from '../helpers/cli/modelClassNameFrom.js';
|
|
10
11
|
import EnvInternal from '../helpers/EnvInternal.js';
|
|
11
12
|
import globalClassNameFromFullyQualifiedModelName from '../helpers/globalClassNameFromFullyQualifiedModelName.js';
|
|
12
13
|
import absoluteDreamPath from '../helpers/path/absoluteDreamPath.js';
|
|
@@ -87,6 +88,7 @@ export default class DreamApp {
|
|
|
87
88
|
static get system() {
|
|
88
89
|
return {
|
|
89
90
|
globalClassNameFromFullyQualifiedModelName,
|
|
91
|
+
modelClassNameFrom,
|
|
90
92
|
absoluteDreamPath,
|
|
91
93
|
dreamPath,
|
|
92
94
|
standardizeFullyQualifiedModelName,
|
|
@@ -1,39 +1,31 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises';
|
|
2
|
-
import DreamCLI from '../../cli/index.js';
|
|
3
|
-
import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
|
|
4
|
-
import dreamPath from '../path/dreamPath.js';
|
|
5
1
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
6
2
|
import generateDreamContent from './generateDreamContent.js';
|
|
7
3
|
import generateFactory from './generateFactory.js';
|
|
8
4
|
import generateMigration from './generateMigration.js';
|
|
9
5
|
import generateSerializer from './generateSerializer.js';
|
|
10
6
|
import generateUnitSpec from './generateUnitSpec.js';
|
|
7
|
+
import modelClassNameFrom from './modelClassNameFrom.js';
|
|
8
|
+
import writeGeneratedFile from './writeGeneratedFile.js';
|
|
11
9
|
export default async function generateDream({ fullyQualifiedModelName, columnsWithTypes, options, fullyQualifiedParentName, }) {
|
|
12
10
|
fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
const modelClassName = modelClassNameFrom(fullyQualifiedModelName, options.modelName);
|
|
12
|
+
await writeGeneratedFile({
|
|
13
|
+
dreamPathKey: 'models',
|
|
14
|
+
fileName: `${fullyQualifiedModelName}.ts`,
|
|
15
|
+
content: generateDreamContent({
|
|
18
16
|
fullyQualifiedModelName,
|
|
19
17
|
columnsWithTypes,
|
|
20
18
|
fullyQualifiedParentName,
|
|
21
19
|
serializer: options.serializer,
|
|
22
20
|
includeAdminSerializers: options.includeAdminSerializers,
|
|
23
21
|
connectionName: options.connectionName,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
${relFilePath}
|
|
30
|
-
|
|
31
|
-
Does this file already exist? Here is the error that was raised:
|
|
32
|
-
${error.message}
|
|
33
|
-
`);
|
|
34
|
-
}
|
|
22
|
+
tableName: options.tableName,
|
|
23
|
+
modelClassName,
|
|
24
|
+
}),
|
|
25
|
+
logLabel: 'dream',
|
|
26
|
+
});
|
|
35
27
|
await generateUnitSpec({ fullyQualifiedModelName });
|
|
36
|
-
await generateFactory({ fullyQualifiedModelName, columnsWithTypes });
|
|
28
|
+
await generateFactory({ fullyQualifiedModelName, columnsWithTypes, modelClassName });
|
|
37
29
|
if (options.serializer)
|
|
38
30
|
await generateSerializer({
|
|
39
31
|
fullyQualifiedModelName,
|
|
@@ -41,6 +33,7 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
|
|
|
41
33
|
fullyQualifiedParentName,
|
|
42
34
|
stiBaseSerializer: options.stiBaseSerializer,
|
|
43
35
|
includeAdminSerializers: options.includeAdminSerializers,
|
|
36
|
+
modelClassName,
|
|
44
37
|
});
|
|
45
38
|
const isSTI = !!fullyQualifiedParentName;
|
|
46
39
|
if (columnsWithTypes.length || !isSTI) {
|
|
@@ -50,6 +43,8 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
|
|
|
50
43
|
columnsWithTypes,
|
|
51
44
|
fullyQualifiedModelName,
|
|
52
45
|
fullyQualifiedParentName,
|
|
46
|
+
tableName: options.tableName,
|
|
47
|
+
modelClassName,
|
|
53
48
|
});
|
|
54
49
|
}
|
|
55
50
|
}
|
|
@@ -31,7 +31,7 @@ ${tableMethod}${serializersMethod}${fieldsSection}
|
|
|
31
31
|
}
|
|
32
32
|
export function createModelConfig(options) {
|
|
33
33
|
const fullyQualifiedModelName = standardizeFullyQualifiedModelName(options.fullyQualifiedModelName);
|
|
34
|
-
const modelClassName =
|
|
34
|
+
const modelClassName = options.modelClassName;
|
|
35
35
|
const isSTI = !!options.fullyQualifiedParentName;
|
|
36
36
|
let parentModelClassName;
|
|
37
37
|
if (isSTI) {
|
|
@@ -40,7 +40,7 @@ export function createModelConfig(options) {
|
|
|
40
40
|
}
|
|
41
41
|
const connectionName = options.connectionName || 'default';
|
|
42
42
|
const applicationModelName = connectionName === 'default' ? 'ApplicationModel' : `${pascalize(connectionName)}ApplicationModel`;
|
|
43
|
-
const tableName = snakeify(pluralize(fullyQualifiedModelName.replace(/\//g, '_')));
|
|
43
|
+
const tableName = options.tableName || snakeify(pluralize(fullyQualifiedModelName.replace(/\//g, '_')));
|
|
44
44
|
return {
|
|
45
45
|
fullyQualifiedModelName,
|
|
46
46
|
modelClassName,
|
|
@@ -1,24 +1,10 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises';
|
|
2
|
-
import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
|
|
3
|
-
import dreamPath from '../path/dreamPath.js';
|
|
4
|
-
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
5
1
|
import generateFactoryContent from './generateFactoryContent.js';
|
|
6
|
-
import
|
|
7
|
-
export default async function generateFactory({ fullyQualifiedModelName, columnsWithTypes, }) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
catch (error) {
|
|
16
|
-
throw new Error(`
|
|
17
|
-
Something happened while trying to create the spec file:
|
|
18
|
-
${relFilePath}
|
|
19
|
-
|
|
20
|
-
Does this file already exist? Here is the error that was raised:
|
|
21
|
-
${error.message}
|
|
22
|
-
`);
|
|
23
|
-
}
|
|
2
|
+
import writeGeneratedFile from './writeGeneratedFile.js';
|
|
3
|
+
export default async function generateFactory({ fullyQualifiedModelName, columnsWithTypes, modelClassName, }) {
|
|
4
|
+
await writeGeneratedFile({
|
|
5
|
+
dreamPathKey: 'factories',
|
|
6
|
+
fileName: `${fullyQualifiedModelName}Factory.ts`,
|
|
7
|
+
content: generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, modelClassName }),
|
|
8
|
+
logLabel: 'factory',
|
|
9
|
+
});
|
|
24
10
|
}
|
|
@@ -4,7 +4,7 @@ import absoluteDreamPath from '../path/absoluteDreamPath.js';
|
|
|
4
4
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
5
5
|
import uniq from '../uniq.js';
|
|
6
6
|
import { optionalFromDescriptors } from './generateMigrationContent.js';
|
|
7
|
-
export default function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, }) {
|
|
7
|
+
export default function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, modelClassName, }) {
|
|
8
8
|
fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
|
|
9
9
|
const dreamTypeImports = ['UpdateableProperties'];
|
|
10
10
|
const dreamImports = [];
|
|
@@ -129,7 +129,6 @@ export default function generateFactoryContent({ fullyQualifiedModelName, column
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
const relativePath = absoluteDreamPath('models', fullyQualifiedModelName);
|
|
132
|
-
const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
|
|
133
132
|
return `\
|
|
134
133
|
${nodeImports.length ? `import { ${uniq(nodeImports).join(', ')} } from 'node:crypto'\n` : ''}${dreamImports.length ? `import { ${uniq(dreamImports).join(', ')} } from '@rvoh/dream'\n` : ''}import { ${uniq(dreamTypeImports).join(', ')} } from '@rvoh/dream/types'
|
|
135
134
|
import ${modelClassName} from '${relativePath}'${additionalImports.length ? '\n' + uniq(additionalImports).join('\n') : ''}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises';
|
|
2
1
|
import * as path from 'node:path';
|
|
3
2
|
import pluralize from 'pluralize-esm';
|
|
4
3
|
import generateMigrationContent from '../cli/generateMigrationContent.js';
|
|
@@ -6,52 +5,45 @@ import primaryKeyType from '../db/primaryKeyType.js';
|
|
|
6
5
|
import hyphenize from '../hyphenize.js';
|
|
7
6
|
import migrationVersion from '../migrationVersion.js';
|
|
8
7
|
import pascalizePath from '../pascalizePath.js';
|
|
9
|
-
import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
|
|
10
8
|
import dreamPath from '../path/dreamPath.js';
|
|
11
9
|
import snakeify from '../snakeify.js';
|
|
12
10
|
import generateStiMigrationContent from './generateStiMigrationContent.js';
|
|
13
|
-
import
|
|
14
|
-
export default async function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, }) {
|
|
15
|
-
const
|
|
16
|
-
?
|
|
17
|
-
:
|
|
11
|
+
import writeGeneratedFile from './writeGeneratedFile.js';
|
|
12
|
+
export default async function generateMigration({ migrationName, columnsWithTypes, connectionName, fullyQualifiedModelName, fullyQualifiedParentName, tableName: explicitTableName, modelClassName, }) {
|
|
13
|
+
const migrationsBasePath = connectionName === 'default'
|
|
14
|
+
? path.join(dreamPath('db'), 'migrations')
|
|
15
|
+
: path.join(dreamPath('db'), 'migrations', connectionName);
|
|
16
|
+
const fileName = `${migrationVersion()}-${hyphenize(migrationName).replace(/\//g, '-')}.ts`;
|
|
18
17
|
const isSTI = !!fullyQualifiedParentName;
|
|
19
|
-
let
|
|
18
|
+
let content = '';
|
|
20
19
|
if (isSTI) {
|
|
21
|
-
|
|
20
|
+
content = generateStiMigrationContent({
|
|
22
21
|
table: snakeify(pluralize(pascalizePath(fullyQualifiedParentName))),
|
|
23
22
|
columnsWithTypes,
|
|
24
23
|
primaryKeyType: primaryKeyType(connectionName),
|
|
25
|
-
stiChildClassName: pascalizePath(fullyQualifiedModelName),
|
|
24
|
+
stiChildClassName: modelClassName || pascalizePath(fullyQualifiedModelName),
|
|
26
25
|
});
|
|
27
26
|
}
|
|
28
27
|
else if (fullyQualifiedModelName) {
|
|
29
|
-
|
|
30
|
-
table: snakeify(pluralize(pascalizePath(fullyQualifiedModelName))),
|
|
28
|
+
content = generateMigrationContent({
|
|
29
|
+
table: explicitTableName || snakeify(pluralize(pascalizePath(fullyQualifiedModelName))),
|
|
31
30
|
columnsWithTypes,
|
|
32
31
|
primaryKeyType: primaryKeyType(connectionName),
|
|
33
32
|
});
|
|
34
33
|
}
|
|
35
34
|
else {
|
|
36
35
|
const tableName = migrationName.match(/-to-(.+)$/)?.[1];
|
|
37
|
-
|
|
36
|
+
content = generateMigrationContent({
|
|
38
37
|
table: tableName ? pluralize(snakeify(tableName)) : '<table-name>',
|
|
39
38
|
columnsWithTypes,
|
|
40
39
|
primaryKeyType: primaryKeyType(connectionName),
|
|
41
40
|
createOrAlter: 'alter',
|
|
42
41
|
});
|
|
43
42
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Something happened while trying to create the migration file:
|
|
51
|
-
${relFilePath}
|
|
52
|
-
|
|
53
|
-
Does this file already exist? Here is the error that was raised:
|
|
54
|
-
${error.message}
|
|
55
|
-
`);
|
|
56
|
-
}
|
|
43
|
+
await writeGeneratedFile({
|
|
44
|
+
basePath: migrationsBasePath,
|
|
45
|
+
fileName,
|
|
46
|
+
content,
|
|
47
|
+
logLabel: 'migration',
|
|
48
|
+
});
|
|
57
49
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import pluralize from 'pluralize-esm';
|
|
2
|
+
import lookupModelByGlobalName from '../../dream-app/helpers/lookupModelByGlobalName.js';
|
|
2
3
|
import Query from '../../dream/Query.js';
|
|
3
4
|
import InvalidDecimalFieldPassedToGenerator from '../../errors/InvalidDecimalFieldPassedToGenerator.js';
|
|
4
5
|
import camelize from '../camelize.js';
|
|
5
6
|
import compact from '../compact.js';
|
|
7
|
+
import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
|
|
6
8
|
import snakeify from '../snakeify.js';
|
|
9
|
+
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
7
10
|
const STI_TYPE_COLUMN_NAME = 'type';
|
|
8
11
|
const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME];
|
|
9
12
|
export default function generateMigrationContent({ connectionName = 'default', table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', stiChildClassName, } = {}) {
|
|
@@ -43,6 +46,7 @@ export default function generateMigrationContent({ connectionName = 'default', t
|
|
|
43
46
|
columnDefs.push(generateBelongsToStr(connectionName, attributeName, {
|
|
44
47
|
primaryKeyType,
|
|
45
48
|
omitInlineNonNull,
|
|
49
|
+
originalAssociationName: nonStandardAttributeName,
|
|
46
50
|
}));
|
|
47
51
|
attributeName = snakeify(nonStandardAttributeName.split('/').pop());
|
|
48
52
|
attributeName = associationNameToForeignKey(attributeName);
|
|
@@ -279,10 +283,10 @@ function attributeTypeString(attributeType) {
|
|
|
279
283
|
}
|
|
280
284
|
}
|
|
281
285
|
}
|
|
282
|
-
function generateBelongsToStr(connectionName, associationName, { primaryKeyType, omitInlineNonNull: optional = false, }) {
|
|
286
|
+
function generateBelongsToStr(connectionName, associationName, { primaryKeyType, omitInlineNonNull: optional = false, originalAssociationName, }) {
|
|
283
287
|
const dbDriverClass = Query.dbDriverClass(connectionName);
|
|
284
288
|
const dataType = dbDriverClass.foreignKeyTypeFromPrimaryKey(primaryKeyType);
|
|
285
|
-
const references =
|
|
289
|
+
const references = lookupReferencesTable(associationName, originalAssociationName);
|
|
286
290
|
return `.addColumn('${associationNameToForeignKey(associationName.split('/').pop())}', '${dataType}', col => col.references('${references}.id').onDelete('restrict')${optional ? '' : '.notNull()'})`;
|
|
287
291
|
}
|
|
288
292
|
function generateIdStr({ primaryKeyType }) {
|
|
@@ -312,6 +316,27 @@ function generateIdStr({ primaryKeyType }) {
|
|
|
312
316
|
return `.addColumn('id', '${primaryKeyType}', col => col.primaryKey())`;
|
|
313
317
|
}
|
|
314
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Determines the referenced table name for a belongs_to association.
|
|
321
|
+
* First tries to look up the actual model to get its table name (handles
|
|
322
|
+
* custom table name overrides). Falls back to deriving the table name
|
|
323
|
+
* from the association string if the model isn't found.
|
|
324
|
+
*/
|
|
325
|
+
function lookupReferencesTable(snakeAssociationName, originalAssociationName) {
|
|
326
|
+
if (originalAssociationName) {
|
|
327
|
+
try {
|
|
328
|
+
const globalName = globalClassNameFromFullyQualifiedModelName(standardizeFullyQualifiedModelName(originalAssociationName));
|
|
329
|
+
const model = lookupModelByGlobalName(globalName);
|
|
330
|
+
if (model?.table) {
|
|
331
|
+
return model.table;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Model not found or DreamApp not initialized — fall through to string derivation
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return pluralize(snakeAssociationName.replace(/\//g, '_').replace(/_id$/, ''));
|
|
339
|
+
}
|
|
315
340
|
function associationNameToForeignKey(associationName) {
|
|
316
341
|
return snakeify(associationName.replace(/\//g, '_').replace(/_id$/, '') + '_id');
|
|
317
342
|
}
|
|
@@ -1,30 +1,17 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises';
|
|
2
|
-
import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
|
|
3
|
-
import dreamPath from '../path/dreamPath.js';
|
|
4
|
-
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
5
1
|
import generateSerializerContent from './generateSerializerContent.js';
|
|
6
|
-
import
|
|
7
|
-
export default async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
await fs.mkdir(absDirPath, { recursive: true });
|
|
13
|
-
await fs.writeFile(absFilePath, generateSerializerContent({
|
|
2
|
+
import writeGeneratedFile from './writeGeneratedFile.js';
|
|
3
|
+
export default async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, modelClassName, }) {
|
|
4
|
+
await writeGeneratedFile({
|
|
5
|
+
dreamPathKey: 'serializers',
|
|
6
|
+
fileName: `${fullyQualifiedModelName}Serializer.ts`,
|
|
7
|
+
content: generateSerializerContent({
|
|
14
8
|
fullyQualifiedModelName,
|
|
15
9
|
columnsWithTypes,
|
|
16
10
|
fullyQualifiedParentName,
|
|
17
11
|
stiBaseSerializer,
|
|
18
12
|
includeAdminSerializers,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Something happened while trying to create the serializer file:
|
|
24
|
-
${relFilePath}
|
|
25
|
-
|
|
26
|
-
Does this file already exist? Here is the error that was raised:
|
|
27
|
-
${error.message}
|
|
28
|
-
`);
|
|
29
|
-
}
|
|
13
|
+
modelClassName,
|
|
14
|
+
}),
|
|
15
|
+
logLabel: 'serializer',
|
|
16
|
+
});
|
|
30
17
|
}
|
|
@@ -4,7 +4,7 @@ import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFu
|
|
|
4
4
|
import absoluteDreamPath from '../path/absoluteDreamPath.js';
|
|
5
5
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
6
6
|
import uniq from '../uniq.js';
|
|
7
|
-
export default function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes = [], fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }) {
|
|
7
|
+
export default function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes = [], fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, modelClassName, }) {
|
|
8
8
|
fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
|
|
9
9
|
const additionalImports = [];
|
|
10
10
|
const dreamImports = [];
|
|
@@ -16,8 +16,7 @@ export default function generateSerializerContent({ fullyQualifiedModelName, col
|
|
|
16
16
|
else {
|
|
17
17
|
dreamImports.push('DreamSerializer');
|
|
18
18
|
}
|
|
19
|
-
const relatedModelImport = importStatementForModel(fullyQualifiedModelName);
|
|
20
|
-
const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
|
|
19
|
+
const relatedModelImport = importStatementForModel(modelClassName, fullyQualifiedModelName);
|
|
21
20
|
const modelInstanceName = camelize(modelClassName);
|
|
22
21
|
const modelSerializerSignature = stiBaseSerializer
|
|
23
22
|
? `<T extends ${modelClassName}>(StiChildClass: typeof ${modelClassName}, ${modelInstanceName}: T)`
|
|
@@ -94,10 +93,9 @@ function importStatementForSerializer(originModelName, destinationModelName) {
|
|
|
94
93
|
const importFrom = absoluteDreamPath('serializers', destinationModelName);
|
|
95
94
|
return `import { ${defaultSerializer}, ${summarySerializer} } from '${importFrom}'\n`;
|
|
96
95
|
}
|
|
97
|
-
function importStatementForModel(
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
return `import ${modelName} from '${importFrom}'\n`;
|
|
96
|
+
function importStatementForModel(modelClassName, fullyQualifiedModelName) {
|
|
97
|
+
const importFrom = absoluteDreamPath('models', fullyQualifiedModelName);
|
|
98
|
+
return `import ${modelClassName} from '${importFrom}'\n`;
|
|
101
99
|
}
|
|
102
100
|
function fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName) {
|
|
103
101
|
return fullyQualifiedModelName.replace(/\//g, '');
|
|
@@ -1,24 +1,10 @@
|
|
|
1
|
-
import * as fs from 'node:fs/promises';
|
|
2
|
-
import DreamCLI from '../../cli/index.js';
|
|
3
|
-
import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
|
|
4
|
-
import dreamPath from '../path/dreamPath.js';
|
|
5
|
-
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
6
1
|
import generateUnitSpecContent from './generateUnitSpecContent.js';
|
|
2
|
+
import writeGeneratedFile from './writeGeneratedFile.js';
|
|
7
3
|
export default async function generateUnitSpec({ fullyQualifiedModelName, }) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
catch (error) {
|
|
16
|
-
throw new Error(`
|
|
17
|
-
Something happened while trying to create the spec file:
|
|
18
|
-
${relFilePath}
|
|
19
|
-
|
|
20
|
-
Does this file already exist? Here is the error that was raised:
|
|
21
|
-
${error.message}
|
|
22
|
-
`);
|
|
23
|
-
}
|
|
4
|
+
await writeGeneratedFile({
|
|
5
|
+
dreamPathKey: 'modelSpecs',
|
|
6
|
+
fileName: `${fullyQualifiedModelName}.spec.ts`,
|
|
7
|
+
content: generateUnitSpecContent({ fullyQualifiedModelName }),
|
|
8
|
+
logLabel: 'spec',
|
|
9
|
+
});
|
|
24
10
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import globalClassNameFromFullyQualifiedModelName from '../globalClassNameFromFullyQualifiedModelName.js';
|
|
2
|
+
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the model class name, either from an explicit override or derived
|
|
5
|
+
* from the fully qualified model name.
|
|
6
|
+
*
|
|
7
|
+
* @param fullyQualifiedModelName - e.g. "Room/Kitchen"
|
|
8
|
+
* @param modelNameOverride - optional explicit class name, e.g. "Kitchen"
|
|
9
|
+
* @returns The model class name, e.g. "RoomKitchen" (derived) or "Kitchen" (override)
|
|
10
|
+
*/
|
|
11
|
+
export default function modelClassNameFrom(fullyQualifiedModelName, modelNameOverride) {
|
|
12
|
+
if (modelNameOverride)
|
|
13
|
+
return modelNameOverride;
|
|
14
|
+
return globalClassNameFromFullyQualifiedModelName(standardizeFullyQualifiedModelName(fullyQualifiedModelName));
|
|
15
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import DreamCLI from '../../cli/index.js';
|
|
3
|
+
import dreamFileAndDirPaths from '../path/dreamFileAndDirPaths.js';
|
|
4
|
+
import dreamPath from '../path/dreamPath.js';
|
|
5
|
+
/**
|
|
6
|
+
* Common file-writing helper used by all Dream generators.
|
|
7
|
+
* Handles directory creation, file writing, logging, and error wrapping.
|
|
8
|
+
*/
|
|
9
|
+
export default async function writeGeneratedFile({ dreamPathKey, basePath, fileName, content, logLabel, }) {
|
|
10
|
+
const resolvedBasePath = basePath ?? dreamPath(dreamPathKey);
|
|
11
|
+
const { relFilePath, absDirPath, absFilePath } = dreamFileAndDirPaths(resolvedBasePath, fileName);
|
|
12
|
+
try {
|
|
13
|
+
DreamCLI.logger.log(`[dream] generating ${logLabel}: ${relFilePath}`);
|
|
14
|
+
await fs.mkdir(absDirPath, { recursive: true });
|
|
15
|
+
await fs.writeFile(absFilePath, content);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
throw new Error(`
|
|
19
|
+
Something happened while trying to create the ${logLabel} file:
|
|
20
|
+
${relFilePath}
|
|
21
|
+
|
|
22
|
+
Does this file already exist? Here is the error that was raised:
|
|
23
|
+
${error.message}
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -46,14 +46,21 @@ export default class DreamBin {
|
|
|
46
46
|
await generateDream({
|
|
47
47
|
fullyQualifiedModelName,
|
|
48
48
|
columnsWithTypes,
|
|
49
|
-
options: {
|
|
49
|
+
options: {
|
|
50
|
+
includeAdminSerializers: options.adminSerializers ?? false,
|
|
51
|
+
...options,
|
|
52
|
+
},
|
|
50
53
|
});
|
|
51
54
|
}
|
|
52
55
|
static async generateStiChild(fullyQualifiedModelName, fullyQualifiedParentName, columnsWithTypes, options) {
|
|
53
56
|
await generateDream({
|
|
54
57
|
fullyQualifiedModelName,
|
|
55
58
|
columnsWithTypes,
|
|
56
|
-
options: {
|
|
59
|
+
options: {
|
|
60
|
+
includeAdminSerializers: options.adminSerializers ?? false,
|
|
61
|
+
...options,
|
|
62
|
+
stiBaseSerializer: false,
|
|
63
|
+
},
|
|
57
64
|
fullyQualifiedParentName,
|
|
58
65
|
});
|
|
59
66
|
}
|