Skip to content

Commit

Permalink
fix(alias): correctly identify upsert varname based on alias in upser…
Browse files Browse the repository at this point in the history
…t derefs
  • Loading branch information
uladkasach committed Jun 15, 2024
1 parent a4d1923 commit e3e6a3c
Show file tree
Hide file tree
Showing 10 changed files with 477 additions and 42 deletions.
6 changes: 6 additions & 0 deletions src/domain/objects/SqlSchemaToDomainObjectRelationship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const schema = Joi.object().keys({
)
.required(),
decorations: Joi.object().keys({
alias: Joi.object().keys({
domainObject: Joi.string().required().allow(null),
}),
unique: Joi.object().keys({
domainObject: Joi.array().items(Joi.string()).required().allow(null),
sqlSchema: Joi.array().items(Joi.string()).required().allow(null),
Expand All @@ -35,6 +38,9 @@ export interface SqlSchemaToDomainObjectRelationship {
domainObject: DomainObjectPropertyMetadata | null; // may be null, if the sql-schema-property is a db-generated property that was not defined by the user in the domain-object
}[];
decorations: {
alias: {
domainObject: string | null;
};
unique: {
sqlSchema: string[] | null;
domainObject: string[] | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
sqlSchema: 'train_engineer',
},
properties: [],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
], // not needed for this one
context: GetTypescriptCodeForPropertyContext.FOR_UPSERT_QUERY,
Expand Down Expand Up @@ -133,7 +136,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
},
},
],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_UPSERT_QUERY,
Expand All @@ -142,6 +148,78 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
'geocodeId: trainLocatedEvent.geocode.id ? trainLocatedEvent.geocode.id : (await geocodeDao.upsert({ geocode: trainLocatedEvent.geocode }, context)).id',
);
});
it('should define the input expression correctly for a solo, aliased, DIRECT_BY_NESTING reference', () => {
const expression =
defineQueryFunctionInputExpressionForDomainObjectProperty({
domainObjectName: 'TrainLocatedEvent',
dobjInputVarName: 'trainLocatedEvent',
sqlSchemaProperty: {
name: 'geocode_id',
isArray: false,
isNullable: false,
isUpdatable: false,
isDatabaseGenerated: false,
reference: {
method: SqlSchemaReferenceMethod.DIRECT_BY_NESTING,
of: {
name: 'Geocode',
extends: DomainObjectVariant.DOMAIN_LITERAL,
},
},
},
domainObjectProperty: {
name: 'geocode',
type: DomainObjectPropertyType.REFERENCE,
of: {
name: 'Geocode',
extends: DomainObjectVariant.DOMAIN_LITERAL,
},
},
allSqlSchemaRelationships: [
new SqlSchemaToDomainObjectRelationship({
name: { domainObject: 'Geocode', sqlSchema: 'geocode' },
properties: [
{
domainObject: {
name: 'latitude',
type: DomainObjectPropertyType.NUMBER,
},
sqlSchema: {
name: 'latitude',
isArray: false,
isNullable: false,
isUpdatable: false,
isDatabaseGenerated: false,
reference: null,
},
},
{
domainObject: {
name: 'longitude',
type: DomainObjectPropertyType.NUMBER,
},
sqlSchema: {
name: 'longitude',
isArray: false,
isNullable: false,
isUpdatable: false,
isDatabaseGenerated: false,
reference: null,
},
},
],
decorations: {
alias: { domainObject: 'geo' },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_UPSERT_QUERY,
});
expect(expression).toEqual(
'geocodeId: trainLocatedEvent.geocode.id ? trainLocatedEvent.geocode.id : (await geocodeDao.upsert({ geo: trainLocatedEvent.geocode }, context)).id',
);
});
it('should define the input expression correctly for a solo, nullable, DIRECT_BY_NESTING reference', () => {
const expression =
defineQueryFunctionInputExpressionForDomainObjectProperty({
Expand Down Expand Up @@ -202,7 +280,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
},
},
],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_UPSERT_QUERY,
Expand Down Expand Up @@ -244,7 +325,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
sqlSchema: 'train_engineer',
},
properties: [],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
], // not needed for this one
context: GetTypescriptCodeForPropertyContext.FOR_FIND_BY_QUERY,
Expand Down Expand Up @@ -314,7 +398,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
},
},
],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_UPSERT_QUERY,
Expand All @@ -323,6 +410,81 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
'geocodeIds: await Promise.all(trainLocatedEvent.geocodes.map(async (geocode) => geocode.id ? geocode.id : (await geocodeDao.upsert({ geocode }, context)).id))',
);
});
it('should define the input expression correctly for an array of, aliased, DIRECT_BY_NESTING reference', () => {
const expression =
defineQueryFunctionInputExpressionForDomainObjectProperty({
domainObjectName: 'TrainLocatedEvent',
dobjInputVarName: 'trainLocatedEvent',
sqlSchemaProperty: {
name: 'geocode_ids',
isArray: true,
isNullable: false,
isUpdatable: false,
isDatabaseGenerated: false,
reference: {
method: SqlSchemaReferenceMethod.DIRECT_BY_NESTING,
of: {
name: 'Geocode',
extends: DomainObjectVariant.DOMAIN_LITERAL,
},
},
},
domainObjectProperty: {
name: 'geocodes',
type: DomainObjectPropertyType.ARRAY,
of: {
type: DomainObjectPropertyType.REFERENCE,
of: {
name: 'Geocode',
extends: DomainObjectVariant.DOMAIN_LITERAL,
},
},
},
allSqlSchemaRelationships: [
new SqlSchemaToDomainObjectRelationship({
name: { domainObject: 'Geocode', sqlSchema: 'geocode' },
properties: [
{
domainObject: {
name: 'latitude',
type: DomainObjectPropertyType.NUMBER,
},
sqlSchema: {
name: 'latitude',
isArray: false,
isNullable: false,
isUpdatable: false,
isDatabaseGenerated: false,
reference: null,
},
},
{
domainObject: {
name: 'longitude',
type: DomainObjectPropertyType.NUMBER,
},
sqlSchema: {
name: 'longitude',
isArray: false,
isNullable: false,
isUpdatable: false,
isDatabaseGenerated: false,
reference: null,
},
},
],
decorations: {
alias: { domainObject: 'geo' },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_UPSERT_QUERY,
});
expect(expression).toEqual(
'geocodeIds: await Promise.all(trainLocatedEvent.geocodes.map(async (geo) => geo.id ? geo.id : (await geocodeDao.upsert({ geo }, context)).id))',
);
});
});
describe('for query', () => {
it('should define the input expression correctly for a standard column-lookup property', () => {
Expand Down Expand Up @@ -377,7 +539,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
sqlSchema: 'train_engineer',
},
properties: [],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
], // not needed for this one
context: GetTypescriptCodeForPropertyContext.FOR_FIND_BY_QUERY,
Expand Down Expand Up @@ -444,7 +609,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
},
},
],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_FIND_BY_QUERY,
Expand Down Expand Up @@ -513,7 +681,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
},
},
],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_FIND_BY_QUERY,
Expand Down Expand Up @@ -555,7 +726,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
sqlSchema: 'train_engineer',
},
properties: [],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
], // not needed for this one
context: GetTypescriptCodeForPropertyContext.FOR_FIND_BY_QUERY,
Expand Down Expand Up @@ -625,7 +799,10 @@ describe('defineQueryFunctionInputExpressionForDomainObjectProperty', () => {
},
},
],
decorations: { unique: { sqlSchema: null, domainObject: null } },
decorations: {
alias: { domainObject: null },
unique: { sqlSchema: null, domainObject: null },
},
}),
],
context: GetTypescriptCodeForPropertyContext.FOR_FIND_BY_QUERY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ export const defineQueryFunctionInputExpressionForDomainObjectProperty = ({
referencedSqlSchemaRelationship.name.sqlSchema;
const referencedDomainObjectName =
referencedSqlSchemaRelationship.name.domainObject;
const referencedDomainObjectAttributeName = camelCase(
referencedSqlSchemaName,
);
const referencedDomainObjectUpsertInputVariableName =
referencedSqlSchemaRelationship.decorations.alias.domainObject
? camelCase(
referencedSqlSchemaRelationship.decorations.alias.domainObject,
)
: referencedDomainObjectAttributeName;

// if its an implicit uuid reference, then all the legwork is done in the sql. simple case here
if (
Expand Down Expand Up @@ -82,9 +91,7 @@ export const defineQueryFunctionInputExpressionForDomainObjectProperty = ({
sqlSchemaProperty.name,
)}: ${nullabilityPrefix}${domainObjectPropertyVariableName}.id ? ${domainObjectPropertyVariableName}.id : (await ${castDomainObjectNameToDaoName(
referencedDomainObjectName,
)}.upsert({ ${camelCase(
referencedSqlSchemaName,
)}: ${domainObjectPropertyVariableName} }, context)).id`;
)}.upsert({ ${referencedDomainObjectUpsertInputVariableName}: ${domainObjectPropertyVariableName} }, context)).id`;

// e.g., `geocodeId: geocode.id`
return `${camelCase(sqlSchemaProperty.name)}: ${nullabilityPrefix}${
Expand All @@ -102,26 +109,16 @@ export const defineQueryFunctionInputExpressionForDomainObjectProperty = ({
sqlSchemaProperty.name,
)}: await Promise.all(${dobjInputVarName}.${
domainObjectProperty.name
}.map(async (${camelCase(referencedSqlSchemaName)}) => ${camelCase(
referencedSqlSchemaName,
)}.id ? ${camelCase(
referencedSqlSchemaName,
)}.id : (await ${castDomainObjectNameToDaoName(
}.map(async (${referencedDomainObjectUpsertInputVariableName}) => ${referencedDomainObjectUpsertInputVariableName}.id ? ${referencedDomainObjectUpsertInputVariableName}.id : (await ${castDomainObjectNameToDaoName(
referencedDomainObjectName,
)}.upsert({ ${camelCase(referencedSqlSchemaName)} }, context)).id))`;
)}.upsert({ ${referencedDomainObjectUpsertInputVariableName} }, context)).id))`;

// e.g., `geocodeIds: geocodes.map(geocode => geocode.id)`
return `${camelCase(sqlSchemaProperty.name)}: await Promise.all(${
domainObjectProperty.name
}.map(async (${camelCase(referencedSqlSchemaName)}) => ${camelCase(
referencedSqlSchemaName,
)}.id ? ${camelCase(
referencedSqlSchemaName,
)}.id : ((await ${castDomainObjectNameToDaoName(
}.map(async (${referencedDomainObjectAttributeName}) => ${referencedDomainObjectAttributeName}.id ? ${referencedDomainObjectAttributeName}.id : ((await ${castDomainObjectNameToDaoName(
referencedDomainObjectName,
)}.findByUnique(${camelCase(
referencedSqlSchemaName,
)}, context))?.id ?? -1) ))`;
)}.findByUnique(${referencedDomainObjectAttributeName}, context))?.id ?? -1) ))`;
}
}

Expand Down
Loading

0 comments on commit e3e6a3c

Please sign in to comment.