@rvoh/dream 0.45.1 → 0.45.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 +6 -2
- package/dist/cjs/src/cli/index.js +41 -5
- package/dist/cjs/src/helpers/cli/generateDream.js +2 -0
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +6 -2
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +27 -17
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +45 -39
- package/dist/cjs/src/helpers/cli/generateSerializer.js +2 -1
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +20 -8
- package/dist/esm/src/bin/index.js +6 -2
- package/dist/esm/src/cli/index.js +41 -5
- package/dist/esm/src/helpers/cli/generateDream.js +2 -0
- package/dist/esm/src/helpers/cli/generateDreamContent.js +6 -2
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +27 -17
- 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 +20 -8
- 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/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,40 @@ 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 columnsWithTypesDescription = `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}
|
|
25
|
+
${INDENT} - integer
|
|
26
|
+
${INDENT}
|
|
27
|
+
${INDENT} - decimal:
|
|
28
|
+
${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
|
|
29
|
+
${INDENT}
|
|
30
|
+
${INDENT} - enum:
|
|
31
|
+
${INDENT} include the enum name to automatically create the enum:
|
|
32
|
+
${INDENT} type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional
|
|
33
|
+
${INDENT}
|
|
34
|
+
${INDENT} omit the enum values to leverage an existing enum (omits the enum type creation):
|
|
35
|
+
${INDENT} type:enum:room_types or type:enum:room_types:optional
|
|
36
|
+
${INDENT}
|
|
37
|
+
${INDENT} - belongs_to:
|
|
38
|
+
${INDENT} Not only updates the migration but also adds a BelongsTo association to the generated model:
|
|
39
|
+
${INDENT} Place:belongs_to
|
|
40
|
+
${INDENT}
|
|
41
|
+
${INDENT} Include the full Path to the model. E.g., if the Coach model is in src/app/models/Health/Coach:
|
|
42
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
9
43
|
class DreamCLI {
|
|
10
44
|
/**
|
|
11
45
|
* use this method for initializing a standalone dream application. If using Psychic and Dream together,
|
|
@@ -35,7 +69,7 @@ class DreamCLI {
|
|
|
35
69
|
.alias('g:migration')
|
|
36
70
|
.description('create a new migration')
|
|
37
71
|
.argument('<migrationName>', 'end with -to-table-name to prepopulate with an alterTable command')
|
|
38
|
-
.argument('[columnsWithTypes...]',
|
|
72
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
39
73
|
.action(async (migrationName, columnsWithTypes) => {
|
|
40
74
|
await initializeDreamApp();
|
|
41
75
|
await index_js_1.default.generateMigration(migrationName, columnsWithTypes);
|
|
@@ -47,7 +81,7 @@ class DreamCLI {
|
|
|
47
81
|
.alias('generate:dream')
|
|
48
82
|
.alias('g:dream')
|
|
49
83
|
.option('--no-serializer')
|
|
50
|
-
.option('--sti-base-serializer', '
|
|
84
|
+
.option('--sti-base-serializer', 'omits the serializer from the dream model, but does create the serializer so it can be extended by STI children')
|
|
51
85
|
.description('create a new Dream model')
|
|
52
86
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
53
87
|
.argument('[columnsWithTypes...]', 'properties of the model property1:text/string/enum/etc. property2:text/string/enum/etc. ... propertyN:text/string/enum/etc.')
|
|
@@ -62,9 +96,11 @@ class DreamCLI {
|
|
|
62
96
|
.description('create a new Dream model that extends another Dream model, leveraging STI (single table inheritance)')
|
|
63
97
|
.option('--no-serializer')
|
|
64
98
|
.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
|
-
|
|
99
|
+
.argument('<extends>', 'just the word "extends"')
|
|
100
|
+
.argument('<parentModelName>', `fully qualified name of the parent model, e.g.:
|
|
101
|
+
${INDENT} to extend the Room model in src/app/models/Room: Room
|
|
102
|
+
${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
|
|
103
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
68
104
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
69
105
|
await initializeDreamApp();
|
|
70
106
|
if (extendsWord !== 'extends')
|
|
@@ -21,6 +21,7 @@ async function generateDream({ fullyQualifiedModelName, columnsWithTypes, option
|
|
|
21
21
|
columnsWithTypes,
|
|
22
22
|
fullyQualifiedParentName,
|
|
23
23
|
serializer: options.serializer && !options.stiBaseSerializer,
|
|
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
|
|
|
@@ -13,37 +13,47 @@ function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, })
|
|
|
13
13
|
const belongsToNames = [];
|
|
14
14
|
const belongsToTypedNames = [];
|
|
15
15
|
const associationCreationStatements = [];
|
|
16
|
-
const
|
|
17
|
-
let
|
|
16
|
+
const attributeDefaults = [];
|
|
17
|
+
let counterVariableIncremented = false;
|
|
18
18
|
for (const attribute of columnsWithTypes) {
|
|
19
19
|
const [attributeName, attributeType, ...descriptors] = attribute.split(':');
|
|
20
20
|
if (attributeName === undefined)
|
|
21
21
|
continue;
|
|
22
|
-
const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
|
|
23
|
-
const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
|
|
24
|
-
const associationFactoryImportStatement = `import create${associationModelName} from '${(0, relativeDreamPath_js_1.default)('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
|
|
25
|
-
const associationName = (0, camelize_js_1.default)(associationModelName);
|
|
26
22
|
if (attributeName === undefined)
|
|
27
23
|
continue;
|
|
28
|
-
|
|
24
|
+
const attributeVariable = (0, camelize_js_1.default)(attributeName.replace(/\//g, ''));
|
|
25
|
+
if (/(_type|_id)$/.test(attributeName))
|
|
29
26
|
continue;
|
|
30
27
|
if (!attributeType)
|
|
31
|
-
throw new Error(`Must pass a column type for ${
|
|
28
|
+
throw new Error(`Must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
32
29
|
switch (attributeType) {
|
|
33
|
-
case 'belongs_to':
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
case 'belongs_to': {
|
|
31
|
+
const fullyQualifiedAssociatedModelName = (0, standardizeFullyQualifiedModelName_js_1.default)(attributeName);
|
|
32
|
+
const associationModelName = (0, globalClassNameFromFullyQualifiedModelName_js_1.default)(fullyQualifiedAssociatedModelName);
|
|
33
|
+
const associationFactoryImportStatement = `import create${associationModelName} from '${(0, relativeDreamPath_js_1.default)('factories', 'factories', fullyQualifiedModelName, fullyQualifiedAssociatedModelName)}'`;
|
|
34
|
+
belongsToNames.push(attributeVariable);
|
|
35
|
+
belongsToTypedNames.push(`${attributeVariable}: ${associationModelName}`);
|
|
36
36
|
additionalImports.push(associationFactoryImportStatement);
|
|
37
|
-
associationCreationStatements.push(`${
|
|
37
|
+
associationCreationStatements.push(`${attributeVariable}: attrs.${attributeVariable} ? null : await create${associationModelName}(),`);
|
|
38
38
|
break;
|
|
39
|
+
}
|
|
39
40
|
case 'string':
|
|
40
41
|
case 'text':
|
|
41
42
|
case 'citext':
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
attributeDefaults.push(`${attributeVariable}: \`${fullyQualifiedModelName} ${attributeVariable} ${counterVariableIncremented ? '${counter}' : '${++counter}'}\`,`);
|
|
44
|
+
counterVariableIncremented = true;
|
|
44
45
|
break;
|
|
45
46
|
case 'enum':
|
|
46
|
-
|
|
47
|
+
attributeDefaults.push(`${attributeVariable}: '${(descriptors.at(-1) || '<tbd>').split(',')[0]}',`);
|
|
48
|
+
break;
|
|
49
|
+
case 'integer':
|
|
50
|
+
attributeDefaults.push(`${attributeVariable}: 1,`);
|
|
51
|
+
break;
|
|
52
|
+
case 'bigint':
|
|
53
|
+
attributeDefaults.push(`${attributeVariable}: '11111111111111111',`);
|
|
54
|
+
break;
|
|
55
|
+
case 'decimal':
|
|
56
|
+
attributeDefaults.push(`${attributeVariable}: 1.1,`);
|
|
47
57
|
break;
|
|
48
58
|
default:
|
|
49
59
|
// noop
|
|
@@ -54,10 +64,10 @@ function generateFactoryContent({ fullyQualifiedModelName, columnsWithTypes, })
|
|
|
54
64
|
return `\
|
|
55
65
|
import { ${(0, uniq_js_1.default)(dreamImports).join(', ')} } from '@rvoh/dream'
|
|
56
66
|
import ${modelClassName} from '${relativePath}'${additionalImports.length ? '\n' + (0, uniq_js_1.default)(additionalImports).join('\n') : ''}
|
|
57
|
-
${
|
|
67
|
+
${counterVariableIncremented ? '\nlet counter = 0\n' : ''}
|
|
58
68
|
export default async function create${modelClassName}(attrs: UpdateableProperties<${modelClassName}> = {}) {
|
|
59
69
|
return await ${modelClassName}.create({
|
|
60
|
-
${associationCreationStatements.length ? associationCreationStatements.join('\n ') + '\n ' : ''}${
|
|
70
|
+
${associationCreationStatements.length ? associationCreationStatements.join('\n ') + '\n ' : ''}${attributeDefaults.length ? attributeDefaults.join('\n ') + '\n ' : ''}...attrs,
|
|
61
71
|
})
|
|
62
72
|
}
|
|
63
73
|
`;
|
|
@@ -3,17 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.default = generateMigrationContent;
|
|
4
4
|
const pluralize_esm_1 = require("pluralize-esm");
|
|
5
5
|
const InvalidDecimalFieldPassedToGenerator_js_1 = require("../../errors/InvalidDecimalFieldPassedToGenerator.js");
|
|
6
|
+
const compact_js_1 = require("../compact.js");
|
|
6
7
|
const foreignKeyTypeFromPrimaryKey_js_1 = require("../db/foreignKeyTypeFromPrimaryKey.js");
|
|
7
8
|
const snakeify_js_1 = require("../snakeify.js");
|
|
8
9
|
const STI_TYPE_COLUMN_NAME = 'type';
|
|
9
10
|
const COLUMNS_TO_INDEX = [STI_TYPE_COLUMN_NAME];
|
|
10
|
-
const NOT_NULL_COLUMNS = [STI_TYPE_COLUMN_NAME];
|
|
11
11
|
function generateMigrationContent({ table, columnsWithTypes = [], primaryKeyType = 'bigserial', createOrAlter = 'create', } = {}) {
|
|
12
12
|
const altering = createOrAlter === 'alter';
|
|
13
13
|
let requireCitextExtension = false;
|
|
14
14
|
const { columnDefs, columnDrops, indexDefs, indexDrops } = columnsWithTypes.reduce((acc, attribute) => {
|
|
15
15
|
const { columnDefs, columnDrops, indexDefs, indexDrops } = acc;
|
|
16
16
|
const [nonStandardAttributeName, attributeType, ...descriptors] = attribute.split(':');
|
|
17
|
+
const optional = optionalFromDescriptors(descriptors);
|
|
18
|
+
const sqlAttributeType = getAttributeType(attributeType, descriptors);
|
|
17
19
|
let attributeName = (0, snakeify_js_1.default)(nonStandardAttributeName);
|
|
18
20
|
if (attributeName === undefined)
|
|
19
21
|
return acc;
|
|
@@ -21,30 +23,29 @@ function generateMigrationContent({ table, columnsWithTypes = [], primaryKeyType
|
|
|
21
23
|
return acc;
|
|
22
24
|
if (attributeType === 'citext')
|
|
23
25
|
requireCitextExtension = true;
|
|
24
|
-
const coercedAttributeType = getAttributeType(attribute);
|
|
25
26
|
switch (attributeType) {
|
|
26
27
|
case 'belongs_to':
|
|
27
28
|
columnDefs.push(generateBelongsToStr(attributeName, {
|
|
28
29
|
primaryKeyType,
|
|
29
|
-
optional
|
|
30
|
+
optional,
|
|
30
31
|
}));
|
|
31
32
|
attributeName = associationNameToForeignKey(attributeName);
|
|
32
33
|
break;
|
|
33
34
|
case 'enum':
|
|
34
|
-
columnDefs.push(generateEnumStr(
|
|
35
|
+
columnDefs.push(generateEnumStr(attributeName, { descriptors, optional }));
|
|
35
36
|
break;
|
|
36
37
|
case 'decimal':
|
|
37
|
-
columnDefs.push(generateDecimalStr(
|
|
38
|
+
columnDefs.push(generateDecimalStr(attributeName, { descriptors, optional }));
|
|
38
39
|
break;
|
|
39
40
|
case 'boolean':
|
|
40
|
-
columnDefs.push(generateBooleanStr(attributeName));
|
|
41
|
+
columnDefs.push(generateBooleanStr(attributeName, { optional }));
|
|
41
42
|
break;
|
|
42
43
|
case 'encrypted':
|
|
43
|
-
columnDefs.push(generateColumnStr(`encrypted_${attributeName}`, 'text', descriptors));
|
|
44
|
+
columnDefs.push(generateColumnStr(`encrypted_${attributeName}`, 'text', descriptors, { optional }));
|
|
44
45
|
break;
|
|
45
46
|
default:
|
|
46
|
-
if (
|
|
47
|
-
columnDefs.push(generateColumnStr(attributeName,
|
|
47
|
+
if (sqlAttributeType !== undefined) {
|
|
48
|
+
columnDefs.push(generateColumnStr(attributeName, sqlAttributeType, descriptors, { optional }));
|
|
48
49
|
}
|
|
49
50
|
break;
|
|
50
51
|
}
|
|
@@ -109,31 +110,29 @@ export async function down(db: Kysely<any>): Promise<void> {
|
|
|
109
110
|
}\
|
|
110
111
|
`;
|
|
111
112
|
}
|
|
112
|
-
function getAttributeType(
|
|
113
|
-
const [, attributeType, ...descriptors] = attribute.split(':');
|
|
114
|
-
if (attributeType === 'enum') {
|
|
115
|
-
return enumAttributeType(attribute)[0];
|
|
116
|
-
}
|
|
113
|
+
function getAttributeType(attributeType, descriptors) {
|
|
117
114
|
switch (attributeType) {
|
|
118
|
-
case 'datetime':
|
|
119
|
-
return 'timestamp';
|
|
120
115
|
case 'string':
|
|
121
116
|
return `varchar(${descriptors[0] || 255})`;
|
|
117
|
+
case 'enum':
|
|
118
|
+
return enumAttributeType(descriptors);
|
|
119
|
+
case 'datetime':
|
|
120
|
+
return 'timestamp';
|
|
122
121
|
default:
|
|
123
122
|
return attributeType;
|
|
124
123
|
}
|
|
125
124
|
}
|
|
126
|
-
function enumAttributeType(
|
|
127
|
-
const [, , ...descriptors] = attribute.split(':');
|
|
125
|
+
function enumAttributeType(descriptors) {
|
|
128
126
|
return `sql\`${descriptors[0]}_enum\``;
|
|
129
127
|
}
|
|
130
128
|
function generateEnumStatements(columnsWithTypes) {
|
|
131
129
|
const enumStatements = columnsWithTypes.filter(attribute => /:enum:.*:/.test(attribute));
|
|
132
|
-
const finalStatements = enumStatements.map(statement => {
|
|
133
|
-
const enumName = statement.split(':')
|
|
134
|
-
|
|
130
|
+
const finalStatements = (0, compact_js_1.default)(enumStatements.map(statement => {
|
|
131
|
+
const [, , enumName, ...descriptors] = statement.split(':');
|
|
132
|
+
optionalFromDescriptors(descriptors);
|
|
133
|
+
const columnsWithTypesString = descriptors[0];
|
|
135
134
|
if (columnsWithTypesString === undefined)
|
|
136
|
-
return
|
|
135
|
+
return;
|
|
137
136
|
const columnsWithTypes = columnsWithTypesString.split(/,\s{0,}/);
|
|
138
137
|
return ` await db.schema
|
|
139
138
|
.createType('${enumName}_enum')
|
|
@@ -141,40 +140,41 @@ function generateEnumStatements(columnsWithTypes) {
|
|
|
141
140
|
${columnsWithTypes.map(attr => `'${attr}'`).join(',\n ')}
|
|
142
141
|
])
|
|
143
142
|
.execute()`;
|
|
144
|
-
});
|
|
143
|
+
}));
|
|
145
144
|
return finalStatements.length ? finalStatements.join('\n\n') + '\n\n' : '';
|
|
146
145
|
}
|
|
147
146
|
function generateEnumDropStatements(columnsWithTypes) {
|
|
148
147
|
const enumStatements = columnsWithTypes.filter(attribute => /:enum:.*:/.test(attribute));
|
|
149
|
-
const finalStatements = enumStatements.map(statement => {
|
|
150
|
-
const enumName = statement.split(':')
|
|
148
|
+
const finalStatements = (0, compact_js_1.default)(enumStatements.map(statement => {
|
|
149
|
+
const [, , enumName, ...descriptors] = statement.split(':');
|
|
150
|
+
optionalFromDescriptors(descriptors);
|
|
151
|
+
const columnsWithTypesString = descriptors[0];
|
|
152
|
+
if (columnsWithTypesString === undefined)
|
|
153
|
+
return;
|
|
151
154
|
return `await db.schema.dropType('${enumName}_enum').execute()`;
|
|
152
|
-
});
|
|
155
|
+
}));
|
|
153
156
|
return finalStatements.length ? '\n\n ' + finalStatements.join('\n ') : '';
|
|
154
157
|
}
|
|
155
|
-
function generateBooleanStr(attributeName) {
|
|
156
|
-
return `.addColumn('${attributeName}', 'boolean', col => col.notNull().defaultTo(false))`;
|
|
158
|
+
function generateBooleanStr(attributeName, { optional }) {
|
|
159
|
+
return `.addColumn('${attributeName}', 'boolean'${optional ? '' : ', col => col.notNull().defaultTo(false)'})`;
|
|
157
160
|
}
|
|
158
|
-
function generateEnumStr(
|
|
159
|
-
const computedAttributeType = enumAttributeType(
|
|
160
|
-
const attributeName = attribute.split(':')[0];
|
|
161
|
+
function generateEnumStr(attributeName, { descriptors, optional }) {
|
|
162
|
+
const computedAttributeType = enumAttributeType(descriptors);
|
|
161
163
|
if (attributeName === undefined)
|
|
162
164
|
return '';
|
|
163
|
-
|
|
164
|
-
return `.addColumn('${attributeName}', ${computedAttributeType}${notNull ? ', col => col.notNull()' : ''})`;
|
|
165
|
+
return `.addColumn('${attributeName}', ${computedAttributeType}${optional ? '' : ', col => col.notNull()'})`;
|
|
165
166
|
}
|
|
166
|
-
function generateDecimalStr(
|
|
167
|
-
const [, , ...descriptors] = attribute.split(':');
|
|
167
|
+
function generateDecimalStr(attributeName, { descriptors, optional }) {
|
|
168
168
|
const [scale, precision] = descriptors[0]?.split(',') || [null, null];
|
|
169
169
|
if (!scale || !precision)
|
|
170
|
-
throw new InvalidDecimalFieldPassedToGenerator_js_1.default(
|
|
171
|
-
return `.addColumn('${
|
|
170
|
+
throw new InvalidDecimalFieldPassedToGenerator_js_1.default(attributeName);
|
|
171
|
+
return `.addColumn('${attributeName}', 'decimal(${scale}, ${precision})'${optional ? '' : ', col => col.notNull()'})`;
|
|
172
172
|
}
|
|
173
|
-
function generateColumnStr(attributeName, attributeType, descriptors) {
|
|
173
|
+
function generateColumnStr(attributeName, attributeType, descriptors, { optional }) {
|
|
174
174
|
let returnStr = `.addColumn('${attributeName}', ${attributeTypeString(attributeType)}`;
|
|
175
175
|
const providedDefaultArg = descriptors.find(d => /^default\(/.test(d));
|
|
176
176
|
const providedDefault = providedDefaultArg?.replace(/^default\(/, '')?.replace(/\)$/, '');
|
|
177
|
-
const notNull =
|
|
177
|
+
const notNull = !optional;
|
|
178
178
|
const hasExtraValues = providedDefault || notNull;
|
|
179
179
|
if (hasExtraValues)
|
|
180
180
|
returnStr += ', col => col';
|
|
@@ -226,3 +226,9 @@ function generateIdStr({ primaryKeyType }) {
|
|
|
226
226
|
function associationNameToForeignKey(associationName) {
|
|
227
227
|
return (0, snakeify_js_1.default)(associationName.replace(/\//g, '_').replace(/_id$/, '') + '_id');
|
|
228
228
|
}
|
|
229
|
+
function optionalFromDescriptors(descriptors) {
|
|
230
|
+
const optional = descriptors.at(-1) === 'optional';
|
|
231
|
+
if (optional)
|
|
232
|
+
descriptors.pop();
|
|
233
|
+
return optional;
|
|
234
|
+
}
|
|
@@ -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 = [];
|
|
@@ -27,7 +27,7 @@ function generateSerializerContent({ fullyQualifiedModelName, columnsWithTypes =
|
|
|
27
27
|
: `(${modelInstanceName}: ${modelClassName})`;
|
|
28
28
|
const modelSerializerArgs = `${modelInstanceName}`;
|
|
29
29
|
const dreamSerializerArgs = `${stiBaseSerializer ? 'StiChildClass' : modelClassName}, ${modelInstanceName}`;
|
|
30
|
-
const
|
|
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) {
|
|
@@ -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,40 @@ 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 columnsWithTypesDescription = `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}
|
|
23
|
+
${INDENT} - integer
|
|
24
|
+
${INDENT}
|
|
25
|
+
${INDENT} - decimal:
|
|
26
|
+
${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
|
|
27
|
+
${INDENT}
|
|
28
|
+
${INDENT} - enum:
|
|
29
|
+
${INDENT} include the enum name to automatically create the enum:
|
|
30
|
+
${INDENT} type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional
|
|
31
|
+
${INDENT}
|
|
32
|
+
${INDENT} omit the enum values to leverage an existing enum (omits the enum type creation):
|
|
33
|
+
${INDENT} type:enum:room_types or type:enum:room_types:optional
|
|
34
|
+
${INDENT}
|
|
35
|
+
${INDENT} - belongs_to:
|
|
36
|
+
${INDENT} Not only updates the migration but also adds a BelongsTo association to the generated model:
|
|
37
|
+
${INDENT} Place:belongs_to
|
|
38
|
+
${INDENT}
|
|
39
|
+
${INDENT} Include the full Path to the model. E.g., if the Coach model is in src/app/models/Health/Coach:
|
|
40
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
7
41
|
export default class DreamCLI {
|
|
8
42
|
/**
|
|
9
43
|
* use this method for initializing a standalone dream application. If using Psychic and Dream together,
|
|
@@ -33,7 +67,7 @@ export default class DreamCLI {
|
|
|
33
67
|
.alias('g:migration')
|
|
34
68
|
.description('create a new migration')
|
|
35
69
|
.argument('<migrationName>', 'end with -to-table-name to prepopulate with an alterTable command')
|
|
36
|
-
.argument('[columnsWithTypes...]',
|
|
70
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
37
71
|
.action(async (migrationName, columnsWithTypes) => {
|
|
38
72
|
await initializeDreamApp();
|
|
39
73
|
await DreamBin.generateMigration(migrationName, columnsWithTypes);
|
|
@@ -45,7 +79,7 @@ export default class DreamCLI {
|
|
|
45
79
|
.alias('generate:dream')
|
|
46
80
|
.alias('g:dream')
|
|
47
81
|
.option('--no-serializer')
|
|
48
|
-
.option('--sti-base-serializer', '
|
|
82
|
+
.option('--sti-base-serializer', 'omits the serializer from the dream model, but does create the serializer so it can be extended by STI children')
|
|
49
83
|
.description('create a new Dream model')
|
|
50
84
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
51
85
|
.argument('[columnsWithTypes...]', 'properties of the model property1:text/string/enum/etc. property2:text/string/enum/etc. ... propertyN:text/string/enum/etc.')
|
|
@@ -60,9 +94,11 @@ export default class DreamCLI {
|
|
|
60
94
|
.description('create a new Dream model that extends another Dream model, leveraging STI (single table inheritance)')
|
|
61
95
|
.option('--no-serializer')
|
|
62
96
|
.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
|
-
|
|
97
|
+
.argument('<extends>', 'just the word "extends"')
|
|
98
|
+
.argument('<parentModelName>', `fully qualified name of the parent model, e.g.:
|
|
99
|
+
${INDENT} to extend the Room model in src/app/models/Room: Room
|
|
100
|
+
${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
|
|
101
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
66
102
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
67
103
|
await initializeDreamApp();
|
|
68
104
|
if (extendsWord !== 'extends')
|
|
@@ -18,6 +18,7 @@ export default async function generateDream({ fullyQualifiedModelName, columnsWi
|
|
|
18
18
|
columnsWithTypes,
|
|
19
19
|
fullyQualifiedParentName,
|
|
20
20
|
serializer: options.serializer && !options.stiBaseSerializer,
|
|
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) {
|
|
@@ -6,7 +6,7 @@ import relativeDreamPath from '../path/relativeDreamPath.js';
|
|
|
6
6
|
import snakeify from '../snakeify.js';
|
|
7
7
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
8
8
|
import uniq from '../uniq.js';
|
|
9
|
-
export default function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, }) {
|
|
9
|
+
export default function generateDreamContent({ fullyQualifiedModelName, columnsWithTypes, fullyQualifiedParentName, serializer, includeAdminSerializers, }) {
|
|
10
10
|
fullyQualifiedModelName = standardizeFullyQualifiedModelName(fullyQualifiedModelName);
|
|
11
11
|
const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
|
|
12
12
|
let parentModelClassName;
|
|
@@ -89,7 +89,11 @@ ${isSTI
|
|
|
89
89
|
? ` public ${isSTI ? 'override ' : ''}get serializers(): DreamSerializers<${modelClassName}> {
|
|
90
90
|
return {
|
|
91
91
|
default: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName)}',
|
|
92
|
-
summary: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName, 'summary')}'
|
|
92
|
+
summary: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName, 'summary')}',${!includeAdminSerializers
|
|
93
|
+
? ''
|
|
94
|
+
: `
|
|
95
|
+
admin: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName).replace(/Serializer$/, 'AdminSerializer')}',
|
|
96
|
+
adminSummary: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName, 'summary').replace(/SummarySerializer$/, 'AdminSummarySerializer')}',`}
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
|