Skip to content

Commit

Permalink
fix(dao): handle nullable nested literals; prevent duplicate imports
Browse files Browse the repository at this point in the history
  • Loading branch information
uladkasach committed Jun 9, 2024
1 parent 67f9fc0 commit 31db1c1
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 108 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"prettier": "2.8.1",
"sql-code-generator": "0.9.3",
"sql-schema-control": "1.5.1",
"sql-schema-generator": "0.23.0",
"sql-schema-generator": "0.24.0",
"ts-jest": "29.1.3",
"typescript": "5.4.5",
"uuid": "3.3.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,64 +87,68 @@ export const defineDaoFindByMethodCodeForDomainObject = ({

// define which domain objects are referenced in this method
const referencedDomainObjectNames = [
domainObject.name, // the domain object itself is always referenced
...(findByQueryType === FindByQueryType.UNIQUE
? sqlSchemaRelationship.properties
.map(
({
domainObject: domainObjectProperty,
sqlSchema: sqlSchemaProperty,
}) => {
// if its not explicitly defined property, then not needed in imports
if (!domainObjectProperty) return null;
...new Set([
domainObject.name, // the domain object itself is always referenced
...(findByQueryType === FindByQueryType.UNIQUE
? sqlSchemaRelationship.properties
.map(
({
domainObject: domainObjectProperty,
sqlSchema: sqlSchemaProperty,
}) => {
// if its not explicitly defined property, then not needed in imports
if (!domainObjectProperty) return null;

// if its not part of the unique key, then its not needed in imports
if (
!sqlSchemaRelationship.decorations.unique.sqlSchema?.includes(
sqlSchemaProperty.name,
// if its not part of the unique key, then its not needed in imports
if (
!sqlSchemaRelationship.decorations.unique.sqlSchema?.includes(
sqlSchemaProperty.name,
)
)
)
return null;
return null;

// if its a solo reference to a domain literal, then its needed
if (
isDomainObjectReferenceProperty(domainObjectProperty) &&
domainObjectProperty.of.extends ===
DomainObjectVariant.DOMAIN_LITERAL
)
return domainObjectProperty.of.name;
// if its a solo reference to a domain literal, then its needed
if (
isDomainObjectReferenceProperty(domainObjectProperty) &&
domainObjectProperty.of.extends ===
DomainObjectVariant.DOMAIN_LITERAL
)
return domainObjectProperty.of.name;

// if its a array reference to a domain literal, then its needed
if (
isDomainObjectArrayProperty(domainObjectProperty) &&
isDomainObjectReferenceProperty(domainObjectProperty.of) &&
domainObjectProperty.of.of.extends ===
DomainObjectVariant.DOMAIN_LITERAL
)
return domainObjectProperty.of.of.name;
// if its a array reference to a domain literal, then its needed
if (
isDomainObjectArrayProperty(domainObjectProperty) &&
isDomainObjectReferenceProperty(domainObjectProperty.of) &&
domainObjectProperty.of.of.extends ===
DomainObjectVariant.DOMAIN_LITERAL
)
return domainObjectProperty.of.of.name;

// otherwise, we dont care about it
return null;
},
)
.filter(isPresent)
: []),
// otherwise, we dont care about it
return null;
},
)
.filter(isPresent)
: []),
]),
];

// define the imports
const imports = [
// always present imports
`import { ${
referencedDomainObjectNames.length > 1 ? 'HasId, ' : ''
}HasMetadata } from 'type-fns';`,
'', // split module from relative imports
"import { DatabaseConnection } from '$PATH_TO_DATABASE_CONNECTION';",
"import { log } from '$PATH_TO_LOG_OBJECT';",
`import { ${referencedDomainObjectNames
.sort()
.join(', ')} } from '$PATH_TO_DOMAIN_OBJECT';`,
`import { sqlQueryFind${domainObject.name}By${findByQueryType} } from '$PATH_TO_GENERATED_SQL_QUERY_FUNCTIONS';`,
"import { castFromDatabaseObject } from './castFromDatabaseObject';",
...new Set([
// always present imports
`import { ${
referencedDomainObjectNames.length > 1 ? 'HasId, ' : ''
}HasMetadata } from 'type-fns';`,
'', // split module from relative imports
"import { DatabaseConnection } from '$PATH_TO_DATABASE_CONNECTION';",
"import { log } from '$PATH_TO_LOG_OBJECT';",
`import { ${referencedDomainObjectNames
.sort()
.join(', ')} } from '$PATH_TO_DOMAIN_OBJECT';`,
`import { sqlQueryFind${domainObject.name}By${findByQueryType} } from '$PATH_TO_GENERATED_SQL_QUERY_FUNCTIONS';`,
"import { castFromDatabaseObject } from './castFromDatabaseObject';",
]),
];

// define the where conditions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,30 @@ export const defineDaoUpsertMethodCodeForDomainObject = ({

// define the imports
const imports = [
// always present imports
`import { HasMetadata${
isUniqueOnUuid ? ', HasUuid' : ''
} } from 'type-fns';`,
'', // split module from relative imports
"import { DatabaseConnection } from '$PATH_TO_DATABASE_CONNECTION';",
`import { ${domainObject.name} } from '$PATH_TO_DOMAIN_OBJECT';`,
"import { log } from '$PATH_TO_LOG_OBJECT';",
`import { sqlQueryUpsert${domainObject.name} } from '$PATH_TO_GENERATED_SQL_QUERY_FUNCTIONS';`,
...sqlSchemaRelationship.properties
.filter(
(propertyRelationship) =>
propertyRelationship.sqlSchema.reference?.method ===
SqlSchemaReferenceMethod.DIRECT_BY_NESTING, // this property is nested directly
)
.map((propertyRelationship) => {
const nameOfDaoToImport = castDomainObjectNameToDaoName(
propertyRelationship.sqlSchema.reference!.of.name,
);
return `import { ${nameOfDaoToImport} } from '../${nameOfDaoToImport}';`;
})
.sort(),
...new Set([
// always present imports
`import { HasMetadata${
isUniqueOnUuid ? ', HasUuid' : ''
} } from 'type-fns';`,
'', // split module from relative imports
"import { DatabaseConnection } from '$PATH_TO_DATABASE_CONNECTION';",
`import { ${domainObject.name} } from '$PATH_TO_DOMAIN_OBJECT';`,
"import { log } from '$PATH_TO_LOG_OBJECT';",
`import { sqlQueryUpsert${domainObject.name} } from '$PATH_TO_GENERATED_SQL_QUERY_FUNCTIONS';`,
...sqlSchemaRelationship.properties
.filter(
(propertyRelationship) =>
propertyRelationship.sqlSchema.reference?.method ===
SqlSchemaReferenceMethod.DIRECT_BY_NESTING, // this property is nested directly
)
.map((propertyRelationship) => {
const nameOfDaoToImport = castDomainObjectNameToDaoName(
propertyRelationship.sqlSchema.reference!.of.name,
);
return `import { ${nameOfDaoToImport} } from '../${nameOfDaoToImport}';`;
})
.sort(),
]),
];

// define the query input expressions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,7 @@ describe('defineDaoUtilCastMethodCodeForDomainObject', () => {
);
expect(code).toMatchSnapshot();
});
it.todo(
'should look correct when the same dobj is referenced more than once in a dobj',
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,44 @@ export const defineDaoUtilCastMethodCodeForDomainObject = ({
sqlSchemaRelationship: SqlSchemaToDomainObjectRelationship;
}) => {
// define the referenced domain objects to hydrate
const nestedDomainObjectNames = Object.values(domainObject.properties)
.map((property) => {
if (isDomainObjectReferenceProperty(property)) return property.of.name;
if (
isDomainObjectArrayProperty(property) &&
isDomainObjectReferenceProperty(property.of)
)
return property.of.of.name;
return null;
})
.filter(isPresent)
.sort();
const nestedDomainObjectNames = [
...new Set(
Object.values(domainObject.properties)
.map((property) => {
if (isDomainObjectReferenceProperty(property))
return property.of.name;
if (
isDomainObjectArrayProperty(property) &&
isDomainObjectReferenceProperty(property.of)
)
return property.of.of.name;
return null;
})
.filter(isPresent)
.sort(),
),
];

// define the imports
const imports = [
// always present imports
"import { HasMetadata } from 'type-fns';",
'', // split module from relative imports
`import { ${domainObject.name} } from '$PATH_TO_DOMAIN_OBJECT';`, // import this domain object; note: higher level function will swap out the import path
`import { ${[domainObject.name, ...nestedDomainObjectNames]
.map((domainObjectName) => `SqlQueryFind${domainObjectName}ByIdOutput`)
.sort()
.join(', ')} } from '$PATH_TO_GENERATED_SQL_TYPES';`,
...nestedDomainObjectNames
.map(
(domainObjectName) =>
`import { castFromDatabaseObject as cast${domainObjectName}FromDatabaseObject } from '../${camelCase(
domainObjectName,
)}Dao/castFromDatabaseObject';`,
)
.sort(),
...new Set([
// always present imports
"import { HasMetadata } from 'type-fns';",
'', // split module from relative imports
`import { ${domainObject.name} } from '$PATH_TO_DOMAIN_OBJECT';`, // import this domain object; note: higher level function will swap out the import path
`import { ${[domainObject.name, ...nestedDomainObjectNames]
.map((domainObjectName) => `SqlQueryFind${domainObjectName}ByIdOutput`)
.sort()
.join(', ')} } from '$PATH_TO_GENERATED_SQL_TYPES';`,
...nestedDomainObjectNames
.map(
(domainObjectName) =>
`import { castFromDatabaseObject as cast${domainObjectName}FromDatabaseObject } from '../${camelCase(
domainObjectName,
)}Dao/castFromDatabaseObject';`,
)
.sort(),
]),
];

// define the output type
Expand Down Expand Up @@ -105,9 +112,15 @@ export const defineDaoUtilCastMethodCodeForDomainObject = ({
sqlSchemaProperty.reference.method ===
SqlSchemaReferenceMethod.DIRECT_BY_NESTING
) {
const nullabilityPrefix = sqlSchemaProperty.isNullable
? `dbObject.${snakeCase(
domainObjectProperty.name,
)} === null ? null : `
: '';

// solo reference case
if (!sqlSchemaProperty.isArray)
return `${domainObjectProperty.name}: cast${
return `${domainObjectProperty.name}: ${nullabilityPrefix}cast${
sqlSchemaProperty.reference.of.name
}FromDatabaseObject(dbObject.${snakeCase(
domainObjectProperty.name,
Expand Down
Loading

0 comments on commit 31db1c1

Please sign in to comment.