@rvoh/dream 0.45.1 → 0.45.3
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 +6 -2
- package/dist/cjs/src/cli/index.js +52 -6
- package/dist/cjs/src/helpers/cli/generateDream.js +3 -1
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +6 -2
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +40 -18
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +46 -39
- package/dist/cjs/src/helpers/cli/generateSerializer.js +2 -1
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +22 -10
- package/dist/esm/src/bin/index.js +6 -2
- package/dist/esm/src/cli/index.js +52 -6
- package/dist/esm/src/helpers/cli/generateDream.js +3 -1
- package/dist/esm/src/helpers/cli/generateDreamContent.js +6 -2
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +40 -18
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +45 -39
- package/dist/esm/src/helpers/cli/generateSerializer.js +2 -1
- package/dist/esm/src/helpers/cli/generateSerializerContent.js +22 -10
- package/dist/types/src/helpers/cli/generateDream.d.ts +1 -0
- package/dist/types/src/helpers/cli/generateDreamContent.d.ts +2 -1
- package/dist/types/src/helpers/cli/generateMigrationContent.d.ts +1 -0
- package/dist/types/src/helpers/cli/generateSerializer.d.ts +2 -1
- package/dist/types/src/helpers/cli/generateSerializerContent.d.ts +3 -2
- package/docs/classes/Benchmark.html +2 -2
- package/docs/classes/CalendarDate.html +2 -2
- package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/Decorators.html +19 -19
- package/docs/classes/Dream.html +136 -136
- package/docs/classes/DreamApp.html +4 -4
- package/docs/classes/DreamBin.html +2 -2
- package/docs/classes/DreamCLI.html +4 -4
- package/docs/classes/DreamImporter.html +2 -2
- package/docs/classes/DreamLogos.html +2 -2
- package/docs/classes/DreamMigrationHelpers.html +7 -7
- package/docs/classes/DreamSerializerBuilder.html +8 -8
- package/docs/classes/DreamTransaction.html +2 -2
- package/docs/classes/Encrypt.html +2 -2
- package/docs/classes/Env.html +2 -2
- package/docs/classes/GlobalNameNotSet.html +3 -3
- package/docs/classes/NonLoadedAssociation.html +3 -3
- package/docs/classes/ObjectSerializerBuilder.html +8 -8
- package/docs/classes/Query.html +60 -60
- package/docs/classes/Range.html +2 -2
- package/docs/classes/RecordNotFound.html +3 -3
- package/docs/classes/ValidationError.html +3 -3
- package/docs/functions/DreamSerializer.html +1 -1
- package/docs/functions/ObjectSerializer.html +1 -1
- package/docs/functions/ReplicaSafe.html +1 -1
- package/docs/functions/STI.html +1 -1
- package/docs/functions/SoftDelete.html +1 -1
- package/docs/functions/camelize.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/cloneDeepSafe.html +1 -1
- package/docs/functions/closeAllDbConnections.html +1 -1
- package/docs/functions/compact.html +1 -1
- package/docs/functions/dreamDbConnections.html +1 -1
- package/docs/functions/dreamPath.html +1 -1
- package/docs/functions/expandStiClasses.html +1 -1
- package/docs/functions/generateDream.html +1 -1
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/groupBy.html +1 -1
- package/docs/functions/hyphenize.html +1 -1
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
- package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
- package/docs/functions/intersection.html +1 -1
- package/docs/functions/isDreamSerializer.html +1 -1
- package/docs/functions/isEmpty.html +1 -1
- package/docs/functions/loadRepl.html +1 -1
- package/docs/functions/lookupClassByGlobalName.html +1 -1
- package/docs/functions/normalizeUnicode.html +1 -1
- package/docs/functions/pascalize.html +1 -1
- package/docs/functions/pgErrorType.html +1 -1
- package/docs/functions/range-1.html +1 -1
- package/docs/functions/relativeDreamPath.html +1 -1
- package/docs/functions/round.html +1 -1
- package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/sharedPathPrefix.html +1 -1
- package/docs/functions/snakeify.html +1 -1
- package/docs/functions/sort.html +1 -1
- package/docs/functions/sortBy.html +1 -1
- package/docs/functions/sortObjectByKey.html +1 -1
- package/docs/functions/sortObjectByValue.html +1 -1
- package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
- package/docs/functions/uncapitalize.html +1 -1
- package/docs/functions/uniq.html +1 -1
- package/docs/functions/untypedDb.html +1 -1
- package/docs/functions/validateColumn.html +1 -1
- package/docs/functions/validateTable.html +1 -1
- package/docs/interfaces/BelongsToStatement.html +2 -2
- package/docs/interfaces/DecoratorContext.html +2 -2
- package/docs/interfaces/DreamAppInitOptions.html +2 -2
- package/docs/interfaces/DreamAppOpts.html +2 -2
- package/docs/interfaces/EncryptOptions.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/OpenapiDescription.html +2 -2
- package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/SerializerRendererOpts.html +2 -2
- package/docs/types/Camelized.html +1 -1
- package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/DateTime.html +1 -1
- package/docs/types/DbConnectionType.html +1 -1
- package/docs/types/DbTypes.html +1 -1
- package/docs/types/DreamAssociationMetadata.html +1 -1
- package/docs/types/DreamAttributes.html +1 -1
- package/docs/types/DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/DreamClassColumn.html +1 -1
- package/docs/types/DreamColumn.html +1 -1
- package/docs/types/DreamColumnNames.html +1 -1
- package/docs/types/DreamLogLevel.html +1 -1
- package/docs/types/DreamLogger.html +1 -1
- package/docs/types/DreamModelSerializerType.html +1 -1
- package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/DreamParamSafeAttributes.html +1 -1
- package/docs/types/DreamParamSafeColumnNames.html +1 -1
- package/docs/types/DreamSerializable.html +1 -1
- package/docs/types/DreamSerializableArray.html +1 -1
- package/docs/types/DreamSerializerKey.html +1 -1
- package/docs/types/DreamSerializers.html +1 -1
- package/docs/types/DreamTableSchema.html +1 -1
- package/docs/types/DreamVirtualColumns.html +1 -1
- package/docs/types/EncryptAlgorithm.html +1 -1
- package/docs/types/HasManyStatement.html +1 -1
- package/docs/types/HasOneStatement.html +1 -1
- package/docs/types/Hyphenized.html +1 -1
- package/docs/types/IdType.html +1 -1
- package/docs/types/OpenapiAllTypes.html +1 -1
- package/docs/types/OpenapiFormats.html +1 -1
- package/docs/types/OpenapiNumberFormats.html +1 -1
- package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiSchemaArray.html +1 -1
- package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/OpenapiSchemaBase.html +1 -1
- package/docs/types/OpenapiSchemaBody.html +1 -1
- package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/OpenapiSchemaInteger.html +1 -1
- package/docs/types/OpenapiSchemaNull.html +1 -1
- package/docs/types/OpenapiSchemaNumber.html +1 -1
- package/docs/types/OpenapiSchemaObject.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaString.html +1 -1
- package/docs/types/OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiTypeField.html +1 -1
- package/docs/types/Pascalized.html +1 -1
- package/docs/types/PrimaryKeyType.html +1 -1
- package/docs/types/RoundingPrecision.html +1 -1
- package/docs/types/SerializerCasing.html +1 -1
- package/docs/types/SimpleObjectSerializerType.html +1 -1
- package/docs/types/Snakeified.html +1 -1
- package/docs/types/Timestamp.html +1 -1
- package/docs/types/UpdateableAssociationProperties.html +1 -1
- package/docs/types/UpdateableProperties.html +1 -1
- package/docs/types/ValidationType.html +1 -1
- package/docs/types/ViewModel.html +1 -1
- package/docs/types/ViewModelClass.html +1 -1
- package/docs/types/WhereStatementForDream.html +1 -1
- package/docs/types/WhereStatementForDreamClass.html +1 -1
- package/docs/variables/DateTime-1.html +1 -1
- package/docs/variables/DreamConst.html +1 -1
- package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
- package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/ops.html +1 -1
- package/docs/variables/primaryKeyTypes.html +1 -1
- package/package.json +2 -2
|
@@ -21,13 +21,17 @@ class DreamBin {
|
|
|
21
21
|
await Query_js_1.default.dbDriverClass().rollback(opts);
|
|
22
22
|
}
|
|
23
23
|
static async generateDream(fullyQualifiedModelName, columnsWithTypes, options) {
|
|
24
|
-
await (0, generateDream_js_1.default)({
|
|
24
|
+
await (0, generateDream_js_1.default)({
|
|
25
|
+
fullyQualifiedModelName,
|
|
26
|
+
columnsWithTypes,
|
|
27
|
+
options: { includeAdminSerializers: false, ...options },
|
|
28
|
+
});
|
|
25
29
|
}
|
|
26
30
|
static async generateStiChild(fullyQualifiedModelName, fullyQualifiedParentName, columnsWithTypes, options) {
|
|
27
31
|
await (0, generateDream_js_1.default)({
|
|
28
32
|
fullyQualifiedModelName,
|
|
29
33
|
columnsWithTypes,
|
|
30
|
-
options: { ...options, stiBaseSerializer: false },
|
|
34
|
+
options: { includeAdminSerializers: false, ...options, stiBaseSerializer: false },
|
|
31
35
|
fullyQualifiedParentName,
|
|
32
36
|
});
|
|
33
37
|
}
|
|
@@ -6,6 +6,50 @@ const index_js_2 = require("../dream-app/index.js");
|
|
|
6
6
|
const EnvInternal_js_1 = require("../helpers/EnvInternal.js");
|
|
7
7
|
const sspawn_js_1 = require("../helpers/sspawn.js");
|
|
8
8
|
const DreamCliLogger_js_1 = require("./logger/DreamCliLogger.js");
|
|
9
|
+
const INDENT = ' ';
|
|
10
|
+
const baseColumnsWithTypesDescription = `space separated snake-case (except for belongs_to model name) properties like this:
|
|
11
|
+
${INDENT} title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to
|
|
12
|
+
${INDENT}
|
|
13
|
+
${INDENT}all properties default to not nullable; null can be allowed by appending ':optional':
|
|
14
|
+
${INDENT} subtitle:string:optional
|
|
15
|
+
${INDENT}
|
|
16
|
+
${INDENT}supported types:
|
|
17
|
+
${INDENT} - citext:
|
|
18
|
+
${INDENT} case insensitive text (indexes and queries are automatically case insensitive)
|
|
19
|
+
${INDENT}
|
|
20
|
+
${INDENT} - string:
|
|
21
|
+
${INDENT} varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional
|
|
22
|
+
${INDENT}
|
|
23
|
+
${INDENT} - text
|
|
24
|
+
${INDENT} - date
|
|
25
|
+
${INDENT} - datetime
|
|
26
|
+
${INDENT} - integer
|
|
27
|
+
${INDENT}
|
|
28
|
+
${INDENT} - decimal:
|
|
29
|
+
${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
|
|
30
|
+
${INDENT}
|
|
31
|
+
${INDENT} - enum:
|
|
32
|
+
${INDENT} include the enum name to automatically create the enum:
|
|
33
|
+
${INDENT} type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional
|
|
34
|
+
${INDENT}
|
|
35
|
+
${INDENT} omit the enum values to leverage an existing enum (omits the enum type creation):
|
|
36
|
+
${INDENT} type:enum:room_types or type:enum:room_types:optional`;
|
|
37
|
+
const columnsWithTypesDescription = baseColumnsWithTypesDescription +
|
|
38
|
+
`
|
|
39
|
+
${INDENT}
|
|
40
|
+
${INDENT} - belongs_to:
|
|
41
|
+
${INDENT} not only adds a foreign key to the migration, but also adds a BelongsTo association to the generated model:
|
|
42
|
+
${INDENT}
|
|
43
|
+
${INDENT} include the fully qualified model name, e.g., if the Coach model is in src/app/models/Health/Coach:
|
|
44
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
45
|
+
const columnsWithTypesDescriptionForMigration = baseColumnsWithTypesDescription +
|
|
46
|
+
`
|
|
47
|
+
${INDENT}
|
|
48
|
+
${INDENT} - belongs_to:
|
|
49
|
+
${INDENT} adds a foreign key to migration
|
|
50
|
+
${INDENT}
|
|
51
|
+
${INDENT} include the fully qualified model name, e.g., if the Coach model is in src/app/models/Health/Coach:
|
|
52
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
9
53
|
class DreamCLI {
|
|
10
54
|
/**
|
|
11
55
|
* use this method for initializing a standalone dream application. If using Psychic and Dream together,
|
|
@@ -35,7 +79,7 @@ class DreamCLI {
|
|
|
35
79
|
.alias('g:migration')
|
|
36
80
|
.description('create a new migration')
|
|
37
81
|
.argument('<migrationName>', 'end with -to-table-name to prepopulate with an alterTable command')
|
|
38
|
-
.argument('[columnsWithTypes...]',
|
|
82
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
|
|
39
83
|
.action(async (migrationName, columnsWithTypes) => {
|
|
40
84
|
await initializeDreamApp();
|
|
41
85
|
await index_js_1.default.generateMigration(migrationName, columnsWithTypes);
|
|
@@ -47,10 +91,10 @@ class DreamCLI {
|
|
|
47
91
|
.alias('generate:dream')
|
|
48
92
|
.alias('g:dream')
|
|
49
93
|
.option('--no-serializer')
|
|
50
|
-
.option('--sti-base-serializer'
|
|
94
|
+
.option('--sti-base-serializer')
|
|
51
95
|
.description('create a new Dream model')
|
|
52
96
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
53
|
-
.argument('[columnsWithTypes...]',
|
|
97
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
54
98
|
.action(async (modelName, columnsWithTypes, options) => {
|
|
55
99
|
await initializeDreamApp();
|
|
56
100
|
await index_js_1.default.generateDream(modelName, columnsWithTypes, options);
|
|
@@ -62,9 +106,11 @@ class DreamCLI {
|
|
|
62
106
|
.description('create a new Dream model that extends another Dream model, leveraging STI (single table inheritance)')
|
|
63
107
|
.option('--no-serializer')
|
|
64
108
|
.argument('<childModelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
65
|
-
.argument('<extends>', 'just the word extends')
|
|
66
|
-
.argument('<parentModelName>',
|
|
67
|
-
|
|
109
|
+
.argument('<extends>', 'just the word "extends"')
|
|
110
|
+
.argument('<parentModelName>', `fully qualified name of the parent model, e.g.:
|
|
111
|
+
${INDENT} to extend the Room model in src/app/models/Room: Room
|
|
112
|
+
${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
|
|
113
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
68
114
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
69
115
|
await initializeDreamApp();
|
|
70
116
|
if (extendsWord !== 'extends')
|
|
@@ -20,7 +20,8 @@ async function generateDream({ fullyQualifiedModelName, columnsWithTypes, option
|
|
|
20
20
|
fullyQualifiedModelName,
|
|
21
21
|
columnsWithTypes,
|
|
22
22
|
fullyQualifiedParentName,
|
|
23
|
-
serializer: options.serializer
|
|
23
|
+
serializer: options.serializer,
|
|
24
|
+
includeAdminSerializers: options.includeAdminSerializers,
|
|
24
25
|
}));
|
|
25
26
|
}
|
|
26
27
|
catch (error) {
|
|
@@ -40,6 +41,7 @@ async function generateDream({ fullyQualifiedModelName, columnsWithTypes, option
|
|
|
40
41
|
columnsWithTypes,
|
|
41
42
|
fullyQualifiedParentName,
|
|
42
43
|
stiBaseSerializer: options.stiBaseSerializer,
|
|
44
|
+
includeAdminSerializers: options.includeAdminSerializers,
|
|
43
45
|
});
|
|
44
46
|
const isSTI = !!fullyQualifiedParentName;
|
|
45
47
|
if (columnsWithTypes.length || !isSTI) {
|
|
@@ -9,7 +9,7 @@ const relativeDreamPath_js_1 = require("../path/relativeDreamPath.js");
|
|
|
9
9
|
const snakeify_js_1 = require("../snakeify.js");
|
|
10
10
|
const standardizeFullyQualifiedModelName_js_1 = require("../standardizeFullyQualifiedModelName.js");
|
|
11
11
|
const uniq_js_1 = require("../uniq.js");
|
|
12
|
-
function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, }) {
|
|
12
|
+
function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, includeAdminSerializers, }) {
|
|
13
13
|
fullyQualifiedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
14
14
|
const modelClassName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
15
15
|
let parentModelClassName;
|
|
@@ -92,7 +92,11 @@ ${isSTI
|
|
|
92
92
|
? ` public ${isSTI ? 'override ' : ''}get serializers(): DreamSerializers<${modelClassName}> {
|
|
93
93
|
return {
|
|
94
94
|
default: '${(0, serializerGlobalNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName)}',
|
|
95
|
-
summary: '${(0, serializerGlobalNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName, 'summary')}'
|
|
95
|
+
summary: '${(0, serializerGlobalNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName, 'summary')}',${!includeAdminSerializers
|
|
96
|
+
? ''
|
|
97
|
+
: `
|
|
98
|
+
admin: '${(0, serializerGlobalNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName).replace(/Serializer$/, 'AdminSerializer')}',
|
|
99
|
+
adminSummary: '${(0, serializerGlobalNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName, 'summary').replace(/SummarySerializer$/, 'AdminSummarySerializer')}',`}
|
|
96
100
|
}
|
|
97
101
|
}
|
|
98
102
|
|
|
@@ -6,6 +6,7 @@ const globalClassNameFromFullyQualifiedModelName_js_1 = require("../globalClassN
|
|
|
6
6
|
const relativeDreamPath_js_1 = require("../path/relativeDreamPath.js");
|
|
7
7
|
const standardizeFullyQualifiedModelName_js_1 = require("../standardizeFullyQualifiedModelName.js");
|
|
8
8
|
const uniq_js_1 = require("../uniq.js");
|
|
9
|
+
const generateMigrationContent_js_1 = require("./generateMigrationContent.js");
|
|
9
10
|
function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, }) {
|
|
10
11
|
fullyQualifiedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
11
12
|
const dreamImports = ['UpdateableProperties'];
|
|
@@ -13,37 +14,58 @@ function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, })
|
|
|
13
14
|
const belongsToNames = [];
|
|
14
15
|
const belongsToTypedNames = [];
|
|
15
16
|
const associationCreationStatements = [];
|
|
16
|
-
const
|
|
17
|
-
let
|
|
17
|
+
const attributeDefaults = [];
|
|
18
|
+
let counterVariableIncremented = false;
|
|
18
19
|
for (const attribute of columnsWithTypes) {
|
|
19
20
|
const [attributeName, attributeType, ...descriptors] = attribute.split(':');
|
|
20
21
|
if (attributeName === undefined)
|
|
21
22
|
continue;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
if (attributeName === undefined)
|
|
23
|
+
if (attributeType === undefined)
|
|
24
|
+
continue;
|
|
25
|
+
const optional = (0, generateMigrationContent_js_1.optionalFromDescriptors)(descriptors);
|
|
26
|
+
if (optional)
|
|
27
27
|
continue;
|
|
28
|
-
|
|
28
|
+
const attributeVariable = (0, camelize_js_1.default)(attributeName.replace(/\//g, ''));
|
|
29
|
+
if (/(_type|_id)$/.test(attributeName))
|
|
29
30
|
continue;
|
|
30
31
|
if (!attributeType)
|
|
31
|
-
throw new Error(`Must pass a column type for ${
|
|
32
|
+
throw new Error(`Must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
32
33
|
switch (attributeType) {
|
|
33
|
-
case 'belongs_to':
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
case 'belongs_to': {
|
|
35
|
+
const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
|
|
36
|
+
const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
|
|
37
|
+
const associationFactoryImportStatement = `import create${associationModelName} from '${(0, relativeDreamPath_js_1.default)('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
|
|
38
|
+
belongsToNames.push(attributeVariable);
|
|
39
|
+
belongsToTypedNames.push(`${attributeVariable}: ${associationModelName}`);
|
|
36
40
|
additionalImports.push(associationFactoryImportStatement);
|
|
37
|
-
associationCreationStatements.push(`${
|
|
41
|
+
associationCreationStatements.push(`${attributeVariable}: attrs.${attributeVariable} ? null : await create${associationModelName}(),`);
|
|
38
42
|
break;
|
|
43
|
+
}
|
|
39
44
|
case 'string':
|
|
40
45
|
case 'text':
|
|
41
46
|
case 'citext':
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
attributeDefaults.push(`${attributeVariable}: \`${fullyQualifiedModelName} ${attributeVariable} ${counterVariableIncremented ? '${counter}' : '${++counter}'}\`,`);
|
|
48
|
+
counterVariableIncremented = true;
|
|
44
49
|
break;
|
|
45
50
|
case 'enum':
|
|
46
|
-
|
|
51
|
+
attributeDefaults.push(`${attributeVariable}: '${(descriptors.at(-1) || '<tbd>').split(',')[0]}',`);
|
|
52
|
+
break;
|
|
53
|
+
case 'integer':
|
|
54
|
+
attributeDefaults.push(`${attributeVariable}: 1,`);
|
|
55
|
+
break;
|
|
56
|
+
case 'bigint':
|
|
57
|
+
attributeDefaults.push(`${attributeVariable}: '11111111111111111',`);
|
|
58
|
+
break;
|
|
59
|
+
case 'decimal':
|
|
60
|
+
attributeDefaults.push(`${attributeVariable}: 1.1,`);
|
|
61
|
+
break;
|
|
62
|
+
case 'date':
|
|
63
|
+
dreamImports.push('CalendarDate');
|
|
64
|
+
attributeDefaults.push(`${attributeVariable}: CalendarDate.today(),`);
|
|
65
|
+
break;
|
|
66
|
+
case 'datetime':
|
|
67
|
+
dreamImports.push('DateTime');
|
|
68
|
+
attributeDefaults.push(`${attributeVariable}: DateTime.now(),`);
|
|
47
69
|
break;
|
|
48
70
|
default:
|
|
49
71
|
// noop
|
|
@@ -54,10 +76,10 @@ function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, })
|
|
|
54
76
|
return `\
|
|
55
77
|
import { ${(0, uniq_js_1.default)(dreamImports).join(', ')} } from '@rvoh/dream'
|
|
56
78
|
import ${modelClassName} from '${relativePath}'${additionalImports.length ? '\n' + (0, uniq_js_1.default)(additionalImports).join('\n') : ''}
|
|
57
|
-
${
|
|
79
|
+
${counterVariableIncremented ? '\nlet counter = 0\n' : ''}
|
|
58
80
|
export default async function create${modelClassName}(attrs: UpdateableProperties<${modelClassName}> = {}) {
|
|
59
81
|
return await ${modelClassName}.create({
|
|
60
|
-
${associationCreationStatements.length ? associationCreationStatements.join('\n ') + '\n ' : ''}${
|
|
82
|
+
${associationCreationStatements.length ? associationCreationStatements.join('\n ') + '\n ' : ''}${attributeDefaults.length ? attributeDefaults.join('\n ') + '\n ' : ''}...attrs,
|
|
61
83
|
})
|
|
62
84
|
}
|
|
63
85
|
`;
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = generateMigrationContent;
|
|
4
|
+
exports.optionalFromDescriptors = optionalFromDescriptors;
|
|
4
5
|
const pluralize_esm_1 = require("pluralize-esm");
|
|
5
6
|
const InvalidDecimalFieldPassedToGenerator_js_1 = require("../../errors/InvalidDecimalFieldPassedToGenerator.js");
|
|
7
|
+
const compact_js_1 = require("../compact.js");
|
|
6
8
|
const foreignKeyTypeFromPrimaryKey_js_1 = require("../db/foreignKeyTypeFromPrimaryKey.js");
|
|
7
9
|
const snakeify_js_1 = require("../snakeify.js");
|
|
8
10
|
const STI_TYPE_COLUMN_NAME = 'type';
|
|
9
11
|
const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME];
|
|
10
|
-
const NOT_NULL_COLUMNS = [STI_TYPE_COLUMN_NAME];
|
|
11
12
|
function generateMigrationContent({ table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', } = {}) {
|
|
12
13
|
const altering = createOrAlter === 'alter';
|
|
13
14
|
let requireCitextExtension = false;
|
|
14
15
|
const { columnDefs, columnDrops, indexDefs, indexDrops } = columnsWithTypes.reduce((acc, attribute) => {
|
|
15
16
|
const { columnDefs, columnDrops, indexDefs, indexDrops } = acc;
|
|
16
17
|
const [nonStandardAttributeName, attributeType, ...descriptors] = attribute.split(':');
|
|
18
|
+
const optional = optionalFromDescriptors(descriptors);
|
|
19
|
+
const sqlAttributeType = getAttributeType(attributeType, descriptors);
|
|
17
20
|
let attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName);
|
|
18
21
|
if (attributeName === undefined)
|
|
19
22
|
return acc;
|
|
@@ -21,30 +24,29 @@ function generateMigrationContent({ table, columnsWithTypes = [], primaryKeyType
|
|
|
21
24
|
return acc;
|
|
22
25
|
if (attributeType === 'citext')
|
|
23
26
|
requireCitextExtension = true;
|
|
24
|
-
const coercedAttributeType = getAttributeType(attribute);
|
|
25
27
|
switch (attributeType) {
|
|
26
28
|
case 'belongs_to':
|
|
27
29
|
columnDefs.push(generateBelongsToStr(attributeName, {
|
|
28
30
|
primaryKeyType,
|
|
29
|
-
optional
|
|
31
|
+
optional,
|
|
30
32
|
}));
|
|
31
33
|
attributeName = associationNameToForeignKey(attributeName);
|
|
32
34
|
break;
|
|
33
35
|
case 'enum':
|
|
34
|
-
columnDefs.push(generateEnumStr(
|
|
36
|
+
columnDefs.push(generateEnumStr(attributeName, { descriptors, optional }));
|
|
35
37
|
break;
|
|
36
38
|
case 'decimal':
|
|
37
|
-
columnDefs.push(generateDecimalStr(
|
|
39
|
+
columnDefs.push(generateDecimalStr(attributeName, { descriptors, optional }));
|
|
38
40
|
break;
|
|
39
41
|
case 'boolean':
|
|
40
|
-
columnDefs.push(generateBooleanStr(attributeName));
|
|
42
|
+
columnDefs.push(generateBooleanStr(attributeName, { optional }));
|
|
41
43
|
break;
|
|
42
44
|
case 'encrypted':
|
|
43
|
-
columnDefs.push(generateColumnStr(`encrypted_${attributeName}`, 'text', descriptors));
|
|
45
|
+
columnDefs.push(generateColumnStr(`encrypted_${attributeName}`, 'text', descriptors, { optional }));
|
|
44
46
|
break;
|
|
45
47
|
default:
|
|
46
|
-
if (
|
|
47
|
-
columnDefs.push(generateColumnStr(attributeName,
|
|
48
|
+
if (sqlAttributeType !== undefined) {
|
|
49
|
+
columnDefs.push(generateColumnStr(attributeName, sqlAttributeType, descriptors, { optional }));
|
|
48
50
|
}
|
|
49
51
|
break;
|
|
50
52
|
}
|
|
@@ -109,31 +111,29 @@ export async function down(db: Kysely<any>): Promise<void> {
|
|
|
109
111
|
}\
|
|
110
112
|
`;
|
|
111
113
|
}
|
|
112
|
-
function getAttributeType(
|
|
113
|
-
const [, attributeType, ...descriptors] = attribute.split(':');
|
|
114
|
-
if (attributeType === 'enum') {
|
|
115
|
-
return enumAttributeType(attribute)[0];
|
|
116
|
-
}
|
|
114
|
+
function getAttributeType(attributeType, descriptors) {
|
|
117
115
|
switch (attributeType) {
|
|
118
|
-
case 'datetime':
|
|
119
|
-
return 'timestamp';
|
|
120
116
|
case 'string':
|
|
121
117
|
return `varchar(${descriptors[0] || 255})`;
|
|
118
|
+
case 'enum':
|
|
119
|
+
return enumAttributeType(descriptors);
|
|
120
|
+
case 'datetime':
|
|
121
|
+
return 'timestamp';
|
|
122
122
|
default:
|
|
123
123
|
return attributeType;
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
function enumAttributeType(
|
|
127
|
-
const [, , ...descriptors] = attribute.split(':');
|
|
126
|
+
function enumAttributeType(descriptors) {
|
|
128
127
|
return `sql\`${descriptors[0]}_enum\``;
|
|
129
128
|
}
|
|
130
129
|
function generateEnumStatements(columnsWithTypes) {
|
|
131
130
|
const enumStatements = columnsWithTypes.filter(attribute => /:enum:.*:/.test(attribute));
|
|
132
|
-
const finalStatements = enumStatements.map(statement => {
|
|
133
|
-
const enumName = statement.split(':')
|
|
134
|
-
|
|
131
|
+
const finalStatements = (0, compact_js_1.default)(enumStatements.map(statement => {
|
|
132
|
+
const [, , enumName, ...descriptors] = statement.split(':');
|
|
133
|
+
optionalFromDescriptors(descriptors);
|
|
134
|
+
const columnsWithTypesString = descriptors[0];
|
|
135
135
|
if (columnsWithTypesString === undefined)
|
|
136
|
-
return
|
|
136
|
+
return;
|
|
137
137
|
const columnsWithTypes = columnsWithTypesString.split(/,\s{0,}/);
|
|
138
138
|
return ` await db.schema
|
|
139
139
|
.createType('${enumName}_enum')
|
|
@@ -141,40 +141,41 @@ function generateEnumStatements(columnsWithTypes) {
|
|
|
141
141
|
${columnsWithTypes.map(attr => `'${attr}'`).join(',\n ')}
|
|
142
142
|
])
|
|
143
143
|
.execute()`;
|
|
144
|
-
});
|
|
144
|
+
}));
|
|
145
145
|
return finalStatements.length ? finalStatements.join('\n\n') + '\n\n' : '';
|
|
146
146
|
}
|
|
147
147
|
function generateEnumDropStatements(columnsWithTypes) {
|
|
148
148
|
const enumStatements = columnsWithTypes.filter(attribute => /:enum:.*:/.test(attribute));
|
|
149
|
-
const finalStatements = enumStatements.map(statement => {
|
|
150
|
-
const enumName = statement.split(':')
|
|
149
|
+
const finalStatements = (0, compact_js_1.default)(enumStatements.map(statement => {
|
|
150
|
+
const [, , enumName, ...descriptors] = statement.split(':');
|
|
151
|
+
optionalFromDescriptors(descriptors);
|
|
152
|
+
const columnsWithTypesString = descriptors[0];
|
|
153
|
+
if (columnsWithTypesString === undefined)
|
|
154
|
+
return;
|
|
151
155
|
return `await db.schema.dropType('${enumName}_enum').execute()`;
|
|
152
|
-
});
|
|
156
|
+
}));
|
|
153
157
|
return finalStatements.length ? '\n\n ' + finalStatements.join('\n ') : '';
|
|
154
158
|
}
|
|
155
|
-
function generateBooleanStr(attributeName) {
|
|
156
|
-
return `.addColumn('${attributeName}', 'boolean', col => col.notNull().defaultTo(false))`;
|
|
159
|
+
function generateBooleanStr(attributeName, { optional }) {
|
|
160
|
+
return `.addColumn('${attributeName}', 'boolean'${optional ? '' : ', col => col.notNull().defaultTo(false)'})`;
|
|
157
161
|
}
|
|
158
|
-
function generateEnumStr(
|
|
159
|
-
const computedAttributeType = enumAttributeType(
|
|
160
|
-
const attributeName = attribute.split(':')[0];
|
|
162
|
+
function generateEnumStr(attributeName, { descriptors, optional }) {
|
|
163
|
+
const computedAttributeType = enumAttributeType(descriptors);
|
|
161
164
|
if (attributeName === undefined)
|
|
162
165
|
return '';
|
|
163
|
-
|
|
164
|
-
return `.addColumn('${attributeName}', ${computedAttributeType}${notNull ? ', col => col.notNull()' : ''})`;
|
|
166
|
+
return `.addColumn('${attributeName}', ${computedAttributeType}${optional ? '' : ', col => col.notNull()'})`;
|
|
165
167
|
}
|
|
166
|
-
function generateDecimalStr(
|
|
167
|
-
const [, , ...descriptors] = attribute.split(':');
|
|
168
|
+
function generateDecimalStr(attributeName, { descriptors, optional }) {
|
|
168
169
|
const [scale, precision] = descriptors[0]?.split(',') || [null, null];
|
|
169
170
|
if (!scale || !precision)
|
|
170
|
-
throw new InvalidDecimalFieldPassedToGenerator_js_1.default(
|
|
171
|
-
return `.addColumn('${
|
|
171
|
+
throw new InvalidDecimalFieldPassedToGenerator_js_1.default(attributeName);
|
|
172
|
+
return `.addColumn('${attributeName}', 'decimal(${scale}, ${precision})'${optional ? '' : ', col => col.notNull()'})`;
|
|
172
173
|
}
|
|
173
|
-
function generateColumnStr(attributeName, attributeType, descriptors) {
|
|
174
|
+
function generateColumnStr(attributeName, attributeType, descriptors, { optional }) {
|
|
174
175
|
let returnStr = `.addColumn('${attributeName}', ${attributeTypeString(attributeType)}`;
|
|
175
176
|
const providedDefaultArg = descriptors.find(d => /^default\(/.test(d));
|
|
176
177
|
const providedDefault = providedDefaultArg?.replace(/^default\(/, '')?.replace(/\)$/, '');
|
|
177
|
-
const notNull =
|
|
178
|
+
const notNull = !optional;
|
|
178
179
|
const hasExtraValues = providedDefault || notNull;
|
|
179
180
|
if (hasExtraValues)
|
|
180
181
|
returnStr += ', col => col';
|
|
@@ -226,3 +227,9 @@ function generateIdStr({ primaryKeyType }) {
|
|
|
226
227
|
function associationNameToForeignKey(associationName) {
|
|
227
228
|
return (0, snakeify_js_1.default)(associationName.replace(/\//g, '_').replace(/_id$/, '') + '_id');
|
|
228
229
|
}
|
|
230
|
+
function optionalFromDescriptors(descriptors) {
|
|
231
|
+
const optional = descriptors.at(-1) === 'optional';
|
|
232
|
+
if (optional)
|
|
233
|
+
descriptors.pop();
|
|
234
|
+
return optional;
|
|
235
|
+
}
|
|
@@ -6,7 +6,7 @@ const dreamFileAndDirPaths_js_1 = require("../path/dreamFileAndDirPaths.js");
|
|
|
6
6
|
const dreamPath_js_1 = require("../path/dreamPath.js");
|
|
7
7
|
const standardizeFullyQualifiedModelName_js_1 = require("../standardizeFullyQualifiedModelName.js");
|
|
8
8
|
const generateSerializerContent_js_1 = require("./generateSerializerContent.js");
|
|
9
|
-
async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, }) {
|
|
9
|
+
async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }) {
|
|
10
10
|
fullyQualifiedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
11
11
|
const { relFilePath, absDirPath, absFilePath } = (0, dreamFileAndDirPaths_js_1.default)((0, dreamPath_js_1.default)('serializers'), `${fullyQualifiedModelName}Serializer.ts`);
|
|
12
12
|
try {
|
|
@@ -17,6 +17,7 @@ async function generateSerializer({ fullyQualifiedModelName, columnsWithTypes, f
|
|
|
17
17
|
columnsWithTypes,
|
|
18
18
|
fullyQualifiedParentName,
|
|
19
19
|
stiBaseSerializer,
|
|
20
|
+
includeAdminSerializers,
|
|
20
21
|
}));
|
|
21
22
|
}
|
|
22
23
|
catch (error) {
|
|
@@ -7,7 +7,7 @@ const globalClassNameFromFullyQualifiedModelName_js_1 = require("../globalClassN
|
|
|
7
7
|
const relativeDreamPath_js_1 = require("../path/relativeDreamPath.js");
|
|
8
8
|
const standardizeFullyQualifiedModelName_js_1 = require("../standardizeFullyQualifiedModelName.js");
|
|
9
9
|
const uniq_js_1 = require("../uniq.js");
|
|
10
|
-
function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes = [], fullyQualifiedParentName, stiBaseSerializer
|
|
10
|
+
function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes = [], fullyQualifiedParentName, stiBaseSerializer, includeAdminSerializers, }) {
|
|
11
11
|
fullyQualifiedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(fullyQualifiedModelName);
|
|
12
12
|
const additionalImports = [];
|
|
13
13
|
const dreamImports = [];
|
|
@@ -26,8 +26,8 @@ function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes =
|
|
|
26
26
|
? `<T extends ${modelClassName}>(StiChildClass: typeof ${modelClassName}, ${modelInstanceName}: T)`
|
|
27
27
|
: `(${modelInstanceName}: ${modelClassName})`;
|
|
28
28
|
const modelSerializerArgs = `${modelInstanceName}`;
|
|
29
|
-
const dreamSerializerArgs = `${stiBaseSerializer ?
|
|
30
|
-
const
|
|
29
|
+
const dreamSerializerArgs = `${stiBaseSerializer ? `StiChildClass ?? ${modelClassName}` : modelClassName}, ${modelInstanceName}`;
|
|
30
|
+
const serializerClassName = (0, serializerNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName));
|
|
31
31
|
const summarySerializerClassName = (0, serializerNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedModelName), 'summary');
|
|
32
32
|
const defaultSerializerExtends = isSTI
|
|
33
33
|
? `${(0, serializerNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName))}(${modelClassName}, ${modelSerializerArgs})`
|
|
@@ -35,16 +35,18 @@ function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes =
|
|
|
35
35
|
const summarySerializerExtends = isSTI
|
|
36
36
|
? `${(0, serializerNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelNameToSerializerBaseName(fullyQualifiedParentName), 'summary')}(${modelClassName}, ${modelSerializerArgs})`
|
|
37
37
|
: `DreamSerializer(${dreamSerializerArgs})`;
|
|
38
|
+
// Admin variants
|
|
39
|
+
const adminSerializerClassName = serializerClassName.replace(/Serializer$/, 'AdminSerializer');
|
|
40
|
+
const adminSummarySerializerClassName = summarySerializerClassName.replace(/SummarySerializer$/, 'AdminSummarySerializer');
|
|
41
|
+
// end:Admin variants
|
|
38
42
|
const additionalModelImports = [];
|
|
39
43
|
const dreamImport = dreamImports.length
|
|
40
44
|
? `import { ${(0, uniq_js_1.default)(dreamImports).join(', ')} } from '@rvoh/dream'\n`
|
|
41
45
|
: '';
|
|
42
46
|
const additionalImportsStr = (0, uniq_js_1.default)(additionalImports).join('');
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
export const ${serialzerClassName} = ${modelSerializerSignature} =>
|
|
47
|
+
const summarySerializer = `export const ${summarySerializerClassName} = ${modelSerializerSignature} =>
|
|
48
|
+
${summarySerializerExtends}${isSTI ? '' : `\n .attribute('id')`}`;
|
|
49
|
+
const defaultSerializer = `export const ${serializerClassName} = ${modelSerializerSignature} =>
|
|
48
50
|
${defaultSerializerExtends}${columnsWithTypes
|
|
49
51
|
.map(attr => {
|
|
50
52
|
const [name, type] = attr.split(':');
|
|
@@ -54,7 +56,17 @@ export const ${serialzerClassName} = ${modelSerializerSignature} =>
|
|
|
54
56
|
return '';
|
|
55
57
|
return `\n ${attribute(name, type, attr)}`;
|
|
56
58
|
})
|
|
57
|
-
.join('
|
|
59
|
+
.join('')}`;
|
|
60
|
+
return `${dreamImport}${additionalImportsStr}${relatedModelImport}${additionalModelImports.join('')}
|
|
61
|
+
${summarySerializer}
|
|
62
|
+
|
|
63
|
+
${defaultSerializer}${!includeAdminSerializers
|
|
64
|
+
? ''
|
|
65
|
+
: `
|
|
66
|
+
|
|
67
|
+
${summarySerializer.replace(summarySerializerClassName, adminSummarySerializerClassName)}
|
|
68
|
+
|
|
69
|
+
${defaultSerializer.replace(serializerClassName, adminSerializerClassName).replace(summarySerializerClassName, adminSummarySerializerClassName)}`}
|
|
58
70
|
`;
|
|
59
71
|
}
|
|
60
72
|
function attribute(name, type, attr) {
|
|
@@ -80,7 +92,7 @@ function importStatementForSerializer(originModelName, destinationModelName) {
|
|
|
80
92
|
const defaultSerializer = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)((0, serializerNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelNameToSerializerBaseName(destinationModelName)));
|
|
81
93
|
const summarySerializer = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)((0, serializerNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedModelNameToSerializerBaseName(destinationModelName), 'summary'));
|
|
82
94
|
const importFrom = (0, relativeDreamPath_js_1.default)('serializers', 'serializers', originModelName, destinationModelName);
|
|
83
|
-
return `import ${defaultSerializer},
|
|
95
|
+
return `import { ${defaultSerializer}, ${summarySerializer} } from '${importFrom}'\n`;
|
|
84
96
|
}
|
|
85
97
|
function importStatementForModel(originModelName, destinationModelName = originModelName) {
|
|
86
98
|
const modelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(destinationModelName);
|
|
@@ -19,13 +19,17 @@ export default class DreamBin {
|
|
|
19
19
|
await Query.dbDriverClass().rollback(opts);
|
|
20
20
|
}
|
|
21
21
|
static async generateDream(fullyQualifiedModelName, columnsWithTypes, options) {
|
|
22
|
-
await generateDream({
|
|
22
|
+
await generateDream({
|
|
23
|
+
fullyQualifiedModelName,
|
|
24
|
+
columnsWithTypes,
|
|
25
|
+
options: { includeAdminSerializers: false, ...options },
|
|
26
|
+
});
|
|
23
27
|
}
|
|
24
28
|
static async generateStiChild(fullyQualifiedModelName, fullyQualifiedParentName, columnsWithTypes, options) {
|
|
25
29
|
await generateDream({
|
|
26
30
|
fullyQualifiedModelName,
|
|
27
31
|
columnsWithTypes,
|
|
28
|
-
options: { ...options, stiBaseSerializer: false },
|
|
32
|
+
options: { includeAdminSerializers: false, ...options, stiBaseSerializer: false },
|
|
29
33
|
fullyQualifiedParentName,
|
|
30
34
|
});
|
|
31
35
|
}
|
|
@@ -4,6 +4,50 @@ import DreamApp from '../dream-app/index.js';
|
|
|
4
4
|
import EnvInternal from '../helpers/EnvInternal.js';
|
|
5
5
|
import sspawn from '../helpers/sspawn.js';
|
|
6
6
|
import DreamCliLogger from './logger/DreamCliLogger.js';
|
|
7
|
+
const INDENT = ' ';
|
|
8
|
+
const baseColumnsWithTypesDescription = `space separated snake-case (except for belongs_to model name) properties like this:
|
|
9
|
+
${INDENT} title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to
|
|
10
|
+
${INDENT}
|
|
11
|
+
${INDENT}all properties default to not nullable; null can be allowed by appending ':optional':
|
|
12
|
+
${INDENT} subtitle:string:optional
|
|
13
|
+
${INDENT}
|
|
14
|
+
${INDENT}supported types:
|
|
15
|
+
${INDENT} - citext:
|
|
16
|
+
${INDENT} case insensitive text (indexes and queries are automatically case insensitive)
|
|
17
|
+
${INDENT}
|
|
18
|
+
${INDENT} - string:
|
|
19
|
+
${INDENT} varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional
|
|
20
|
+
${INDENT}
|
|
21
|
+
${INDENT} - text
|
|
22
|
+
${INDENT} - date
|
|
23
|
+
${INDENT} - datetime
|
|
24
|
+
${INDENT} - integer
|
|
25
|
+
${INDENT}
|
|
26
|
+
${INDENT} - decimal:
|
|
27
|
+
${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
|
|
28
|
+
${INDENT}
|
|
29
|
+
${INDENT} - enum:
|
|
30
|
+
${INDENT} include the enum name to automatically create the enum:
|
|
31
|
+
${INDENT} type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional
|
|
32
|
+
${INDENT}
|
|
33
|
+
${INDENT} omit the enum values to leverage an existing enum (omits the enum type creation):
|
|
34
|
+
${INDENT} type:enum:room_types or type:enum:room_types:optional`;
|
|
35
|
+
const columnsWithTypesDescription = baseColumnsWithTypesDescription +
|
|
36
|
+
`
|
|
37
|
+
${INDENT}
|
|
38
|
+
${INDENT} - belongs_to:
|
|
39
|
+
${INDENT} not only adds a foreign key to the migration, but also adds a BelongsTo association to the generated model:
|
|
40
|
+
${INDENT}
|
|
41
|
+
${INDENT} include the fully qualified model name, e.g., if the Coach model is in src/app/models/Health/Coach:
|
|
42
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
43
|
+
const columnsWithTypesDescriptionForMigration = baseColumnsWithTypesDescription +
|
|
44
|
+
`
|
|
45
|
+
${INDENT}
|
|
46
|
+
${INDENT} - belongs_to:
|
|
47
|
+
${INDENT} adds a foreign key to migration
|
|
48
|
+
${INDENT}
|
|
49
|
+
${INDENT} include the fully qualified model name, e.g., if the Coach model is in src/app/models/Health/Coach:
|
|
50
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
7
51
|
export default class DreamCLI {
|
|
8
52
|
/**
|
|
9
53
|
* use this method for initializing a standalone dream application. If using Psychic and Dream together,
|
|
@@ -33,7 +77,7 @@ export default class DreamCLI {
|
|
|
33
77
|
.alias('g:migration')
|
|
34
78
|
.description('create a new migration')
|
|
35
79
|
.argument('<migrationName>', 'end with -to-table-name to prepopulate with an alterTable command')
|
|
36
|
-
.argument('[columnsWithTypes...]',
|
|
80
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescriptionForMigration)
|
|
37
81
|
.action(async (migrationName, columnsWithTypes) => {
|
|
38
82
|
await initializeDreamApp();
|
|
39
83
|
await DreamBin.generateMigration(migrationName, columnsWithTypes);
|
|
@@ -45,10 +89,10 @@ export default class DreamCLI {
|
|
|
45
89
|
.alias('generate:dream')
|
|
46
90
|
.alias('g:dream')
|
|
47
91
|
.option('--no-serializer')
|
|
48
|
-
.option('--sti-base-serializer'
|
|
92
|
+
.option('--sti-base-serializer')
|
|
49
93
|
.description('create a new Dream model')
|
|
50
94
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
51
|
-
.argument('[columnsWithTypes...]',
|
|
95
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
52
96
|
.action(async (modelName, columnsWithTypes, options) => {
|
|
53
97
|
await initializeDreamApp();
|
|
54
98
|
await DreamBin.generateDream(modelName, columnsWithTypes, options);
|
|
@@ -60,9 +104,11 @@ export default class DreamCLI {
|
|
|
60
104
|
.description('create a new Dream model that extends another Dream model, leveraging STI (single table inheritance)')
|
|
61
105
|
.option('--no-serializer')
|
|
62
106
|
.argument('<childModelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
63
|
-
.argument('<extends>', 'just the word extends')
|
|
64
|
-
.argument('<parentModelName>',
|
|
65
|
-
|
|
107
|
+
.argument('<extends>', 'just the word "extends"')
|
|
108
|
+
.argument('<parentModelName>', `fully qualified name of the parent model, e.g.:
|
|
109
|
+
${INDENT} to extend the Room model in src/app/models/Room: Room
|
|
110
|
+
${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
|
|
111
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
66
112
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
67
113
|
await initializeDreamApp();
|
|
68
114
|
if (extendsWord !== 'extends')
|
|
@@ -17,7 +17,8 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
|
|
|
17
17
|
fullyQualifiedModelName,
|
|
18
18
|
columnsWithTypes,
|
|
19
19
|
fullyQualifiedParentName,
|
|
20
|
-
serializer: options.serializer
|
|
20
|
+
serializer: options.serializer,
|
|
21
|
+
includeAdminSerializers: options.includeAdminSerializers,
|
|
21
22
|
}));
|
|
22
23
|
}
|
|
23
24
|
catch (error) {
|
|
@@ -37,6 +38,7 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
|
|
|
37
38
|
columnsWithTypes,
|
|
38
39
|
fullyQualifiedParentName,
|
|
39
40
|
stiBaseSerializer: options.stiBaseSerializer,
|
|
41
|
+
includeAdminSerializers: options.includeAdminSerializers,
|
|
40
42
|
});
|
|
41
43
|
const isSTI = !!fullyQualifiedParentName;
|
|
42
44
|
if (columnsWithTypes.length || !isSTI) {
|