@rvoh/dream 2.0.0-alpha.11 → 2.0.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/Dream.js +24 -16
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +167 -74
- package/dist/esm/src/Dream.js +24 -16
- package/dist/esm/src/helpers/cli/generateDreamContent.js +167 -74
- package/dist/types/src/Dream.d.ts +1 -0
- package/dist/types/src/helpers/cli/generateDreamContent.d.ts +31 -2
- package/docs/classes/db.DreamMigrationHelpers.html +9 -9
- package/docs/classes/db.KyselyQueryDriver.html +30 -30
- package/docs/classes/db.PostgresQueryDriver.html +31 -31
- package/docs/classes/db.QueryDriverBase.html +29 -29
- package/docs/classes/errors.CheckConstraintViolation.html +3 -3
- package/docs/classes/errors.ColumnOverflow.html +3 -3
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
- package/docs/classes/errors.NonLoadedAssociation.html +3 -3
- package/docs/classes/errors.NotNullViolation.html +3 -3
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- package/docs/classes/index.CalendarDate.html +2 -2
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +113 -113
- package/docs/classes/index.DreamApp.html +5 -5
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +53 -53
- package/docs/classes/system.CliFileWriter.html +2 -2
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +5 -5
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +8 -8
- package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
- package/docs/classes/utils.Encrypt.html +2 -2
- package/docs/classes/utils.Range.html +2 -2
- package/docs/functions/db.closeAllDbConnections.html +1 -1
- package/docs/functions/db.dreamDbConnections.html +1 -1
- package/docs/functions/db.untypedDb.html +1 -1
- package/docs/functions/db.validateColumn.html +1 -1
- package/docs/functions/db.validateTable.html +1 -1
- package/docs/functions/errors.pgErrorType.html +1 -1
- package/docs/functions/index.DreamSerializer.html +1 -1
- package/docs/functions/index.ObjectSerializer.html +1 -1
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +1 -1
- package/docs/functions/utils.camelize.html +1 -1
- package/docs/functions/utils.capitalize.html +1 -1
- package/docs/functions/utils.cloneDeepSafe.html +1 -1
- package/docs/functions/utils.compact.html +1 -1
- package/docs/functions/utils.groupBy.html +1 -1
- package/docs/functions/utils.hyphenize.html +1 -1
- package/docs/functions/utils.intersection.html +1 -1
- package/docs/functions/utils.isEmpty.html +1 -1
- package/docs/functions/utils.normalizeUnicode.html +1 -1
- package/docs/functions/utils.pascalize.html +1 -1
- package/docs/functions/utils.percent.html +1 -1
- package/docs/functions/utils.range-1.html +1 -1
- package/docs/functions/utils.round.html +1 -1
- package/docs/functions/utils.sanitizeString.html +1 -1
- package/docs/functions/utils.snakeify.html +1 -1
- package/docs/functions/utils.sort.html +1 -1
- package/docs/functions/utils.sortBy.html +1 -1
- package/docs/functions/utils.sortObjectByKey.html +1 -1
- package/docs/functions/utils.sortObjectByValue.html +1 -1
- package/docs/functions/utils.uncapitalize.html +1 -1
- package/docs/functions/utils.uniq.html +1 -1
- package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
- package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/types.BelongsToStatement.html +2 -2
- package/docs/interfaces/types.DecoratorContext.html +2 -2
- package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/modules/db.html +1 -1
- package/docs/modules/errors.html +1 -1
- package/docs/modules/index.html +1 -1
- package/docs/modules/openapi.html +1 -1
- package/docs/modules/system.html +1 -1
- package/docs/modules/types.html +1 -1
- package/docs/modules/utils.html +1 -1
- package/docs/types/index.DateTime.html +1 -1
- package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/openapi.OpenapiAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiFormats.html +1 -1
- package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaString.html +1 -1
- package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiTypeField.html +1 -1
- package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.DbConnectionType.html +1 -1
- package/docs/types/types.DbTypes.html +1 -1
- package/docs/types/types.DreamAssociationMetadata.html +1 -1
- package/docs/types/types.DreamAttributes.html +1 -1
- package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/types.DreamClassColumn.html +1 -1
- package/docs/types/types.DreamColumn.html +1 -1
- package/docs/types/types.DreamColumnNames.html +1 -1
- package/docs/types/types.DreamLogLevel.html +1 -1
- package/docs/types/types.DreamLogger.html +1 -1
- package/docs/types/types.DreamModelSerializerType.html +1 -1
- package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/types.DreamParamSafeAttributes.html +1 -1
- package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
- package/docs/types/types.DreamSerializable.html +1 -1
- package/docs/types/types.DreamSerializableArray.html +1 -1
- package/docs/types/types.DreamSerializerKey.html +1 -1
- package/docs/types/types.DreamSerializers.html +1 -1
- package/docs/types/types.DreamVirtualColumns.html +1 -1
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +1 -1
- package/docs/types/types.ViewModelClass.html +1 -1
- package/docs/types/types.WhereStatementForDream.html +1 -1
- package/docs/types/types.WhereStatementForDreamClass.html +1 -1
- package/docs/variables/index.DateTime-1.html +1 -1
- package/docs/variables/index.DreamConst.html +1 -1
- package/docs/variables/index.ops.html +1 -1
- package/docs/variables/openapi.openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/types.TRIGRAM_OPERATORS.html +1 -1
- package/docs/variables/types.primaryKeyTypes.html +1 -1
- package/package.json +1 -1
package/dist/cjs/src/Dream.js
CHANGED
|
@@ -370,6 +370,12 @@ export default class Dream {
|
|
|
370
370
|
static get isSTIBase() {
|
|
371
371
|
return !!this.extendedBy?.length && !this.isSTIChild;
|
|
372
372
|
}
|
|
373
|
+
static stiSiblings() {
|
|
374
|
+
const stiBase = this.stiBaseClassOrOwnClass;
|
|
375
|
+
if (!stiBase.isSTIBase)
|
|
376
|
+
return [];
|
|
377
|
+
return stiBase.extendedBy;
|
|
378
|
+
}
|
|
373
379
|
/**
|
|
374
380
|
* @internal
|
|
375
381
|
*
|
|
@@ -687,9 +693,9 @@ export default class Dream {
|
|
|
687
693
|
return false;
|
|
688
694
|
if (this.explicitUnsafeParamColumns.includes(column))
|
|
689
695
|
return false;
|
|
690
|
-
if (this.isBelongsToAssociationForeignKey(column))
|
|
696
|
+
if (this.isBelongsToAssociationForeignKey(column, { includeStiSiblings: true }))
|
|
691
697
|
return false;
|
|
692
|
-
if (this.isBelongsToAssociationPolymorphicTypeField(column))
|
|
698
|
+
if (this.isBelongsToAssociationPolymorphicTypeField(column, { includeStiSiblings: true }))
|
|
693
699
|
return false;
|
|
694
700
|
if ((this.isSTIChild || this.isSTIBase) && column === 'type')
|
|
695
701
|
return false;
|
|
@@ -755,13 +761,15 @@ export default class Dream {
|
|
|
755
761
|
*
|
|
756
762
|
* @returns An array containing all of the associations for this dream class
|
|
757
763
|
*/
|
|
758
|
-
static associationMetadataMap() {
|
|
764
|
+
static associationMetadataMap(opts = { includeStiSiblings: false }) {
|
|
759
765
|
const allAssociations = [
|
|
760
766
|
...this.associationMetadataByType.belongsTo,
|
|
761
767
|
...this.associationMetadataByType.hasOne,
|
|
762
768
|
...this.associationMetadataByType.hasMany,
|
|
763
769
|
];
|
|
764
|
-
const map =
|
|
770
|
+
const map = opts.includeStiSiblings
|
|
771
|
+
? this.stiSiblings().reduce((map, sibling) => ({ ...map, ...sibling['associationMetadataMap']() }), {})
|
|
772
|
+
: {};
|
|
765
773
|
for (const association of allAssociations) {
|
|
766
774
|
map[association.as] = association;
|
|
767
775
|
}
|
|
@@ -1837,8 +1845,8 @@ export default class Dream {
|
|
|
1837
1845
|
* @param column - A column on this Dream class
|
|
1838
1846
|
* @returns A boolean
|
|
1839
1847
|
*/
|
|
1840
|
-
static isBelongsToAssociationForeignKey(column) {
|
|
1841
|
-
return this.belongsToAssociationForeignKeys().includes(column);
|
|
1848
|
+
static isBelongsToAssociationForeignKey(column, opts = { includeStiSiblings: false }) {
|
|
1849
|
+
return this.belongsToAssociationForeignKeys(opts).includes(column);
|
|
1842
1850
|
}
|
|
1843
1851
|
/**
|
|
1844
1852
|
* @internal
|
|
@@ -1856,8 +1864,8 @@ export default class Dream {
|
|
|
1856
1864
|
* @param column - a column on this dream class
|
|
1857
1865
|
* @returns A boolean
|
|
1858
1866
|
*/
|
|
1859
|
-
static isBelongsToAssociationPolymorphicTypeField(column) {
|
|
1860
|
-
return this.polymorphicTypeColumns().includes(column);
|
|
1867
|
+
static isBelongsToAssociationPolymorphicTypeField(column, opts = { includeStiSiblings: false }) {
|
|
1868
|
+
return this.polymorphicTypeColumns(opts).includes(column);
|
|
1861
1869
|
}
|
|
1862
1870
|
/**
|
|
1863
1871
|
* @internal
|
|
@@ -1872,9 +1880,9 @@ export default class Dream {
|
|
|
1872
1880
|
*
|
|
1873
1881
|
* @returns An array of column names that are belongs to foreign keys on this dream class
|
|
1874
1882
|
*/
|
|
1875
|
-
static belongsToAssociationForeignKeys() {
|
|
1876
|
-
const associationMap = this.associationMetadataMap();
|
|
1877
|
-
return this.belongsToAssociationNames().map(belongsToKey => associationMap[belongsToKey]?.foreignKey());
|
|
1883
|
+
static belongsToAssociationForeignKeys(opts = { includeStiSiblings: false }) {
|
|
1884
|
+
const associationMap = this.associationMetadataMap(opts);
|
|
1885
|
+
return this.belongsToAssociationNames(opts).map(belongsToKey => associationMap[belongsToKey]?.foreignKey());
|
|
1878
1886
|
}
|
|
1879
1887
|
/**
|
|
1880
1888
|
* @internal
|
|
@@ -1888,9 +1896,9 @@ export default class Dream {
|
|
|
1888
1896
|
*
|
|
1889
1897
|
* @returns An array of column names that are polymorphic type fields on the given dream class
|
|
1890
1898
|
*/
|
|
1891
|
-
static polymorphicTypeColumns() {
|
|
1892
|
-
const associationMap = this.associationMetadataMap();
|
|
1893
|
-
return this.belongsToAssociationNames()
|
|
1899
|
+
static polymorphicTypeColumns(opts = { includeStiSiblings: false }) {
|
|
1900
|
+
const associationMap = this.associationMetadataMap(opts);
|
|
1901
|
+
return this.belongsToAssociationNames(opts)
|
|
1894
1902
|
.filter(key => associationMap[key]?.polymorphic)
|
|
1895
1903
|
.map(belongsToKey => associationMap[belongsToKey]?.foreignKeyTypeField());
|
|
1896
1904
|
}
|
|
@@ -1908,8 +1916,8 @@ export default class Dream {
|
|
|
1908
1916
|
*
|
|
1909
1917
|
* @returns An array of belongs to association names
|
|
1910
1918
|
*/
|
|
1911
|
-
static belongsToAssociationNames() {
|
|
1912
|
-
const associationMap = this.associationMetadataMap();
|
|
1919
|
+
static belongsToAssociationNames(opts = { includeStiSiblings: false }) {
|
|
1920
|
+
const associationMap = this.associationMetadataMap(opts);
|
|
1913
1921
|
return Object.keys(associationMap).filter(key => associationMap[key]?.type === 'BelongsTo');
|
|
1914
1922
|
}
|
|
1915
1923
|
/**
|
|
@@ -7,59 +7,70 @@ import absoluteDreamPath from '../path/absoluteDreamPath.js';
|
|
|
7
7
|
import snakeify from '../snakeify.js';
|
|
8
8
|
import standardizeFullyQualifiedModelName from '../standardizeFullyQualifiedModelName.js';
|
|
9
9
|
import uniq from '../uniq.js';
|
|
10
|
-
export default function generateDreamContent(
|
|
11
|
-
|
|
10
|
+
export default function generateDreamContent(options) {
|
|
11
|
+
const config = createModelConfig(options);
|
|
12
|
+
const baseImports = createImportConfig(config, options);
|
|
13
|
+
const attributesResult = processAttributes(options.columnsWithTypes, config.modelClassName);
|
|
14
|
+
const allImports = {
|
|
15
|
+
...baseImports,
|
|
16
|
+
modelImportStatements: [...baseImports.modelImportStatements, ...attributesResult.imports],
|
|
17
|
+
};
|
|
18
|
+
const importSection = buildImportSection(allImports);
|
|
19
|
+
const classDeclaration = buildClassDeclaration(config);
|
|
20
|
+
const tableMethod = buildTableMethod(config);
|
|
21
|
+
const serializersMethod = buildSerializersMethod(config, options);
|
|
22
|
+
const fieldsSection = buildFieldsSection(config, attributesResult);
|
|
23
|
+
return `${importSection}
|
|
24
|
+
|
|
25
|
+
const deco = new Decorators<typeof ${config.modelClassName}>()
|
|
26
|
+
|
|
27
|
+
${classDeclaration}
|
|
28
|
+
${tableMethod}${serializersMethod}${fieldsSection}
|
|
29
|
+
}
|
|
30
|
+
`.replace(/^\s*$/gm, '');
|
|
31
|
+
}
|
|
32
|
+
export function createModelConfig(options) {
|
|
33
|
+
const fullyQualifiedModelName = standardizeFullyQualifiedModelName(options.fullyQualifiedModelName);
|
|
12
34
|
const modelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedModelName);
|
|
35
|
+
const isSTI = !!options.fullyQualifiedParentName;
|
|
13
36
|
let parentModelClassName;
|
|
37
|
+
if (isSTI) {
|
|
38
|
+
const standardizedParentName = standardizeFullyQualifiedModelName(options.fullyQualifiedParentName);
|
|
39
|
+
parentModelClassName = globalClassNameFromFullyQualifiedModelName(standardizedParentName);
|
|
40
|
+
}
|
|
41
|
+
const connectionName = options.connectionName || 'default';
|
|
42
|
+
const applicationModelName = connectionName === 'default' ? 'ApplicationModel' : `${pascalize(connectionName)}ApplicationModel`;
|
|
43
|
+
const tableName = snakeify(pluralize(fullyQualifiedModelName.replace(/\//g, '_')));
|
|
44
|
+
return {
|
|
45
|
+
fullyQualifiedModelName,
|
|
46
|
+
modelClassName,
|
|
47
|
+
parentModelClassName,
|
|
48
|
+
applicationModelName,
|
|
49
|
+
isSTI,
|
|
50
|
+
tableName,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function createImportConfig(config, options) {
|
|
14
54
|
const dreamTypeImports = ['DreamColumn'];
|
|
15
55
|
const dreamImports = ['Decorators'];
|
|
16
|
-
if (serializer)
|
|
56
|
+
if (options.serializer) {
|
|
17
57
|
dreamTypeImports.push('DreamSerializers');
|
|
18
|
-
|
|
19
|
-
if (isSTI) {
|
|
20
|
-
fullyQualifiedParentName = standardizeFullyQualifiedModelName(fullyQualifiedParentName);
|
|
21
|
-
parentModelClassName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedParentName);
|
|
58
|
+
}
|
|
59
|
+
if (config.isSTI) {
|
|
22
60
|
dreamImports.push('STI');
|
|
23
61
|
}
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (!attributeType)
|
|
37
|
-
throw new Error(`must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
38
|
-
switch (attributeType) {
|
|
39
|
-
case 'belongs_to': {
|
|
40
|
-
modelImportStatements.push(associationImportStatement);
|
|
41
|
-
const associationName = camelize(fullyQualifiedAssociatedModelName.split('/').pop());
|
|
42
|
-
const associationForeignKey = `${associationName}Id`;
|
|
43
|
-
return `
|
|
44
|
-
@deco.BelongsTo('${fullyQualifiedAssociatedModelName}', { on: '${associationForeignKey}'${descriptors.includes('optional') ? ', optional: true' : ''} })
|
|
45
|
-
public ${associationName}: ${associationModelName}${descriptors.includes('optional') ? ' | null' : ''}
|
|
46
|
-
public ${associationForeignKey}: DreamColumn<${modelClassName}, '${associationName}Id'>
|
|
47
|
-
`;
|
|
48
|
-
}
|
|
49
|
-
case 'has_one':
|
|
50
|
-
case 'has_many':
|
|
51
|
-
return '';
|
|
52
|
-
case 'encrypted':
|
|
53
|
-
return `
|
|
54
|
-
@deco.Encrypted()
|
|
55
|
-
public ${camelize(attributeName)}: ${getAttributeType(attribute, modelClassName)}\
|
|
56
|
-
`;
|
|
57
|
-
default:
|
|
58
|
-
return `
|
|
59
|
-
public ${camelize(attributeName)}: ${getAttributeType(attribute, modelClassName)}\
|
|
60
|
-
`;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
62
|
+
const baseModelName = config.isSTI ? options.fullyQualifiedParentName : config.applicationModelName;
|
|
63
|
+
const modelImportStatements = [importStatementForModel(baseModelName)];
|
|
64
|
+
return {
|
|
65
|
+
dreamTypeImports,
|
|
66
|
+
dreamImports,
|
|
67
|
+
modelImportStatements,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function processAttributes(columnsWithTypes, modelClassName) {
|
|
71
|
+
const attributeResults = columnsWithTypes.map(attribute => processAttribute(attribute, modelClassName));
|
|
72
|
+
const allImports = attributeResults.flatMap(result => result.imports);
|
|
73
|
+
const attributeStatements = attributeResults.map(result => result.content);
|
|
63
74
|
const formattedFields = attributeStatements
|
|
64
75
|
.filter(attr => !/^\n@/.test(attr))
|
|
65
76
|
.map(s => s.split('\n').join('\n '))
|
|
@@ -69,42 +80,124 @@ public ${camelize(attributeName)}: ${getAttributeType(attribute, modelClassName)
|
|
|
69
80
|
.map(s => s.split('\n').join('\n '))
|
|
70
81
|
.join('\n ')
|
|
71
82
|
.replace(/\n {2}$/, '');
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
return {
|
|
84
|
+
content: '', // Not used in this context
|
|
85
|
+
imports: allImports,
|
|
86
|
+
formattedFields,
|
|
87
|
+
formattedDecorators,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function processAttribute(attribute, modelClassName) {
|
|
91
|
+
const [attributeName, attributeType, ...descriptors] = attribute.split(':');
|
|
92
|
+
if (attributeName === undefined)
|
|
93
|
+
return { content: '', imports: [] };
|
|
94
|
+
if (!attributeType) {
|
|
95
|
+
throw new Error(`must pass a column type for ${attributeName} (i.e. ${attributeName}:string)`);
|
|
96
|
+
}
|
|
97
|
+
switch (attributeType) {
|
|
98
|
+
case 'belongs_to':
|
|
99
|
+
return createBelongsToAttribute(attributeName, descriptors, modelClassName);
|
|
100
|
+
case 'has_one':
|
|
101
|
+
case 'has_many':
|
|
102
|
+
return { content: '', imports: [] };
|
|
103
|
+
case 'encrypted':
|
|
104
|
+
return createEncryptedAttribute(attributeName, attribute, modelClassName);
|
|
105
|
+
default:
|
|
106
|
+
return createRegularAttribute(attributeName, attribute, modelClassName);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export function createBelongsToAttribute(attributeName, descriptors, modelClassName) {
|
|
110
|
+
const fullyQualifiedAssociatedModelName = standardizeFullyQualifiedModelName(attributeName);
|
|
111
|
+
const associationModelName = globalClassNameFromFullyQualifiedModelName(fullyQualifiedAssociatedModelName);
|
|
112
|
+
const associationImportStatement = importStatementForModel(fullyQualifiedAssociatedModelName);
|
|
113
|
+
const associationName = camelize(fullyQualifiedAssociatedModelName.split('/').pop());
|
|
114
|
+
const associationForeignKey = `${associationName}Id`;
|
|
115
|
+
const isOptional = descriptors.includes('optional');
|
|
116
|
+
const content = `
|
|
117
|
+
@deco.BelongsTo('${fullyQualifiedAssociatedModelName}', { on: '${associationForeignKey}'${isOptional ? ', optional: true' : ''} })
|
|
118
|
+
public ${associationName}: ${associationModelName}${isOptional ? ' | null' : ''}
|
|
119
|
+
public ${associationForeignKey}: DreamColumn<${modelClassName}, '${associationName}Id'>
|
|
75
120
|
`;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
${
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
121
|
+
return {
|
|
122
|
+
content,
|
|
123
|
+
imports: [associationImportStatement],
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function createEncryptedAttribute(attributeName, attribute, modelClassName) {
|
|
127
|
+
const content = `
|
|
128
|
+
@deco.Encrypted()
|
|
129
|
+
public ${camelize(attributeName)}: ${getAttributeType(attribute, modelClassName)}`;
|
|
130
|
+
return {
|
|
131
|
+
content,
|
|
132
|
+
imports: [],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
export function createRegularAttribute(attributeName, attribute, modelClassName) {
|
|
136
|
+
const content = `
|
|
137
|
+
public ${camelize(attributeName)}: ${getAttributeType(attribute, modelClassName)}`;
|
|
138
|
+
return {
|
|
139
|
+
content,
|
|
140
|
+
imports: [],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function buildImportSection(imports) {
|
|
144
|
+
const dreamImportLine = imports.dreamImports.length
|
|
145
|
+
? `import { ${uniq(imports.dreamImports).join(', ')} } from '@rvoh/dream'\n`
|
|
146
|
+
: '';
|
|
147
|
+
const typeImportLine = `import { ${uniq(imports.dreamTypeImports).join(', ')} } from '@rvoh/dream/types'`;
|
|
148
|
+
const modelImports = uniq(imports.modelImportStatements).join('');
|
|
149
|
+
return `${dreamImportLine}${typeImportLine}${modelImports}`;
|
|
150
|
+
}
|
|
151
|
+
function buildClassDeclaration(config) {
|
|
152
|
+
const stiDecorator = config.isSTI ? `@STI(${config.parentModelClassName})\n` : '';
|
|
153
|
+
const extendsClause = config.isSTI ? config.parentModelClassName : config.applicationModelName;
|
|
154
|
+
return `${stiDecorator}export default class ${config.modelClassName} extends ${extendsClause} {`;
|
|
155
|
+
}
|
|
156
|
+
function buildTableMethod(config) {
|
|
157
|
+
if (config.isSTI)
|
|
158
|
+
return '';
|
|
159
|
+
return ` public override get table() {
|
|
160
|
+
return '${config.tableName}' as const
|
|
90
161
|
}
|
|
91
162
|
|
|
92
|
-
|
|
93
|
-
|
|
163
|
+
`;
|
|
164
|
+
}
|
|
165
|
+
function buildSerializersMethod(config, options) {
|
|
166
|
+
if (!options.serializer)
|
|
167
|
+
return '';
|
|
168
|
+
const overrideKeyword = config.isSTI ? 'override ' : '';
|
|
169
|
+
const defaultSerializer = serializerGlobalNameFromFullyQualifiedModelName(config.fullyQualifiedModelName);
|
|
170
|
+
const summarySerializer = serializerGlobalNameFromFullyQualifiedModelName(config.fullyQualifiedModelName, 'summary');
|
|
171
|
+
let adminSerializers = '';
|
|
172
|
+
if (options.includeAdminSerializers) {
|
|
173
|
+
const adminSerializer = defaultSerializer.replace(/Serializer$/, 'AdminSerializer');
|
|
174
|
+
const adminSummarySerializer = summarySerializer.replace(/SummarySerializer$/, 'AdminSummarySerializer');
|
|
175
|
+
adminSerializers = `
|
|
176
|
+
admin: '${adminSerializer}',
|
|
177
|
+
adminSummary: '${adminSummarySerializer}',`;
|
|
178
|
+
}
|
|
179
|
+
return ` public ${overrideKeyword}get serializers(): DreamSerializers<${config.modelClassName}> {
|
|
94
180
|
return {
|
|
95
|
-
default: '${
|
|
96
|
-
summary: '${
|
|
97
|
-
? ''
|
|
98
|
-
: `
|
|
99
|
-
admin: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName).replace(/Serializer$/, 'AdminSerializer')}',
|
|
100
|
-
adminSummary: '${serializerGlobalNameFromFullyQualifiedModelName(fullyQualifiedModelName, 'summary').replace(/SummarySerializer$/, 'AdminSummarySerializer')}',`}
|
|
181
|
+
default: '${defaultSerializer}',
|
|
182
|
+
summary: '${summarySerializer}',${adminSerializers}
|
|
101
183
|
}
|
|
102
184
|
}
|
|
103
185
|
|
|
104
|
-
|
|
105
|
-
: ''}${isSTI ? formattedFields : ` public id: ${idTypescriptType}${formattedFields}${timestamps}`}${formattedDecorators}
|
|
186
|
+
`;
|
|
106
187
|
}
|
|
107
|
-
|
|
188
|
+
function buildFieldsSection(config, attributes) {
|
|
189
|
+
if (config.isSTI) {
|
|
190
|
+
return `${attributes.formattedFields}${attributes.formattedDecorators}`;
|
|
191
|
+
}
|
|
192
|
+
const idField = ` public id: DreamColumn<${config.modelClassName}, 'id'>`;
|
|
193
|
+
let timestamps = `
|
|
194
|
+
public createdAt: DreamColumn<${config.modelClassName}, 'createdAt'>
|
|
195
|
+
public updatedAt: DreamColumn<${config.modelClassName}, 'updatedAt'>
|
|
196
|
+
`;
|
|
197
|
+
if (!attributes.formattedDecorators.length) {
|
|
198
|
+
timestamps = timestamps.replace(/\n$/, '');
|
|
199
|
+
}
|
|
200
|
+
return `${idField}${attributes.formattedFields}${timestamps}${attributes.formattedDecorators}`;
|
|
108
201
|
}
|
|
109
202
|
function getAttributeType(attribute, modelClassName) {
|
|
110
203
|
return `DreamColumn<${modelClassName}, '${camelize(attribute.split(':')[0])}'>`;
|
package/dist/esm/src/Dream.js
CHANGED
|
@@ -370,6 +370,12 @@ export default class Dream {
|
|
|
370
370
|
static get isSTIBase() {
|
|
371
371
|
return !!this.extendedBy?.length && !this.isSTIChild;
|
|
372
372
|
}
|
|
373
|
+
static stiSiblings() {
|
|
374
|
+
const stiBase = this.stiBaseClassOrOwnClass;
|
|
375
|
+
if (!stiBase.isSTIBase)
|
|
376
|
+
return [];
|
|
377
|
+
return stiBase.extendedBy;
|
|
378
|
+
}
|
|
373
379
|
/**
|
|
374
380
|
* @internal
|
|
375
381
|
*
|
|
@@ -687,9 +693,9 @@ export default class Dream {
|
|
|
687
693
|
return false;
|
|
688
694
|
if (this.explicitUnsafeParamColumns.includes(column))
|
|
689
695
|
return false;
|
|
690
|
-
if (this.isBelongsToAssociationForeignKey(column))
|
|
696
|
+
if (this.isBelongsToAssociationForeignKey(column, { includeStiSiblings: true }))
|
|
691
697
|
return false;
|
|
692
|
-
if (this.isBelongsToAssociationPolymorphicTypeField(column))
|
|
698
|
+
if (this.isBelongsToAssociationPolymorphicTypeField(column, { includeStiSiblings: true }))
|
|
693
699
|
return false;
|
|
694
700
|
if ((this.isSTIChild || this.isSTIBase) && column === 'type')
|
|
695
701
|
return false;
|
|
@@ -755,13 +761,15 @@ export default class Dream {
|
|
|
755
761
|
*
|
|
756
762
|
* @returns An array containing all of the associations for this dream class
|
|
757
763
|
*/
|
|
758
|
-
static associationMetadataMap() {
|
|
764
|
+
static associationMetadataMap(opts = { includeStiSiblings: false }) {
|
|
759
765
|
const allAssociations = [
|
|
760
766
|
...this.associationMetadataByType.belongsTo,
|
|
761
767
|
...this.associationMetadataByType.hasOne,
|
|
762
768
|
...this.associationMetadataByType.hasMany,
|
|
763
769
|
];
|
|
764
|
-
const map =
|
|
770
|
+
const map = opts.includeStiSiblings
|
|
771
|
+
? this.stiSiblings().reduce((map, sibling) => ({ ...map, ...sibling['associationMetadataMap']() }), {})
|
|
772
|
+
: {};
|
|
765
773
|
for (const association of allAssociations) {
|
|
766
774
|
map[association.as] = association;
|
|
767
775
|
}
|
|
@@ -1837,8 +1845,8 @@ export default class Dream {
|
|
|
1837
1845
|
* @param column - A column on this Dream class
|
|
1838
1846
|
* @returns A boolean
|
|
1839
1847
|
*/
|
|
1840
|
-
static isBelongsToAssociationForeignKey(column) {
|
|
1841
|
-
return this.belongsToAssociationForeignKeys().includes(column);
|
|
1848
|
+
static isBelongsToAssociationForeignKey(column, opts = { includeStiSiblings: false }) {
|
|
1849
|
+
return this.belongsToAssociationForeignKeys(opts).includes(column);
|
|
1842
1850
|
}
|
|
1843
1851
|
/**
|
|
1844
1852
|
* @internal
|
|
@@ -1856,8 +1864,8 @@ export default class Dream {
|
|
|
1856
1864
|
* @param column - a column on this dream class
|
|
1857
1865
|
* @returns A boolean
|
|
1858
1866
|
*/
|
|
1859
|
-
static isBelongsToAssociationPolymorphicTypeField(column) {
|
|
1860
|
-
return this.polymorphicTypeColumns().includes(column);
|
|
1867
|
+
static isBelongsToAssociationPolymorphicTypeField(column, opts = { includeStiSiblings: false }) {
|
|
1868
|
+
return this.polymorphicTypeColumns(opts).includes(column);
|
|
1861
1869
|
}
|
|
1862
1870
|
/**
|
|
1863
1871
|
* @internal
|
|
@@ -1872,9 +1880,9 @@ export default class Dream {
|
|
|
1872
1880
|
*
|
|
1873
1881
|
* @returns An array of column names that are belongs to foreign keys on this dream class
|
|
1874
1882
|
*/
|
|
1875
|
-
static belongsToAssociationForeignKeys() {
|
|
1876
|
-
const associationMap = this.associationMetadataMap();
|
|
1877
|
-
return this.belongsToAssociationNames().map(belongsToKey => associationMap[belongsToKey]?.foreignKey());
|
|
1883
|
+
static belongsToAssociationForeignKeys(opts = { includeStiSiblings: false }) {
|
|
1884
|
+
const associationMap = this.associationMetadataMap(opts);
|
|
1885
|
+
return this.belongsToAssociationNames(opts).map(belongsToKey => associationMap[belongsToKey]?.foreignKey());
|
|
1878
1886
|
}
|
|
1879
1887
|
/**
|
|
1880
1888
|
* @internal
|
|
@@ -1888,9 +1896,9 @@ export default class Dream {
|
|
|
1888
1896
|
*
|
|
1889
1897
|
* @returns An array of column names that are polymorphic type fields on the given dream class
|
|
1890
1898
|
*/
|
|
1891
|
-
static polymorphicTypeColumns() {
|
|
1892
|
-
const associationMap = this.associationMetadataMap();
|
|
1893
|
-
return this.belongsToAssociationNames()
|
|
1899
|
+
static polymorphicTypeColumns(opts = { includeStiSiblings: false }) {
|
|
1900
|
+
const associationMap = this.associationMetadataMap(opts);
|
|
1901
|
+
return this.belongsToAssociationNames(opts)
|
|
1894
1902
|
.filter(key => associationMap[key]?.polymorphic)
|
|
1895
1903
|
.map(belongsToKey => associationMap[belongsToKey]?.foreignKeyTypeField());
|
|
1896
1904
|
}
|
|
@@ -1908,8 +1916,8 @@ export default class Dream {
|
|
|
1908
1916
|
*
|
|
1909
1917
|
* @returns An array of belongs to association names
|
|
1910
1918
|
*/
|
|
1911
|
-
static belongsToAssociationNames() {
|
|
1912
|
-
const associationMap = this.associationMetadataMap();
|
|
1919
|
+
static belongsToAssociationNames(opts = { includeStiSiblings: false }) {
|
|
1920
|
+
const associationMap = this.associationMetadataMap(opts);
|
|
1913
1921
|
return Object.keys(associationMap).filter(key => associationMap[key]?.type === 'BelongsTo');
|
|
1914
1922
|
}
|
|
1915
1923
|
/**
|