mirror of
https://github.com/expo/entity.git
synced 2026-11-14 09:58:09 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa4e2484c9 |
No files matched your search
@@ -79,7 +79,7 @@ export default class EnforcingEntityLoader<
|
|||||||
uniqueFieldName,
|
uniqueFieldName,
|
||||||
fieldValue
|
fieldValue
|
||||||
);
|
);
|
||||||
return entityResult ? entityResult.enforceValue() : null;
|
return entityResult.enforceValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,7 +98,7 @@ export default class EnforcingEntityLoader<
|
|||||||
*/
|
*/
|
||||||
async loadByIDNullableAsync(id: TID): Promise<TEntity | null> {
|
async loadByIDNullableAsync(id: TID): Promise<TEntity | null> {
|
||||||
const entityResult = await this.entityLoader.loadByIDNullableAsync(id);
|
const entityResult = await this.entityLoader.loadByIDNullableAsync(id);
|
||||||
return entityResult ? entityResult.enforceValue() : null;
|
return entityResult.enforceValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export default class EntityAssociationLoader<
|
|||||||
* @param queryContext - query context in which to perform the load
|
* @param queryContext - query context in which to perform the load
|
||||||
*/
|
*/
|
||||||
async loadAssociatedEntityAsync<
|
async loadAssociatedEntityAsync<
|
||||||
|
TIdentifyingField extends keyof Pick<TFields, TSelectedFields>,
|
||||||
TAssociatedFields,
|
TAssociatedFields,
|
||||||
TAssociatedID,
|
TAssociatedID,
|
||||||
TAssociatedEntity extends ReadonlyEntity<
|
TAssociatedEntity extends ReadonlyEntity<
|
||||||
@@ -40,7 +41,7 @@ export default class EntityAssociationLoader<
|
|||||||
>,
|
>,
|
||||||
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
||||||
>(
|
>(
|
||||||
fieldIdentifyingAssociatedEntity: keyof Pick<TFields, TSelectedFields>,
|
fieldIdentifyingAssociatedEntity: TIdentifyingField,
|
||||||
associatedEntityClass: IEntityClass<
|
associatedEntityClass: IEntityClass<
|
||||||
TAssociatedFields,
|
TAssociatedFields,
|
||||||
TAssociatedID,
|
TAssociatedID,
|
||||||
@@ -54,14 +55,20 @@ export default class EntityAssociationLoader<
|
|||||||
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
||||||
.getQueryContextProvider()
|
.getQueryContextProvider()
|
||||||
.getQueryContext()
|
.getQueryContext()
|
||||||
): Promise<Result<TAssociatedEntity>> {
|
): Promise<
|
||||||
|
Result<null extends TFields[TIdentifyingField] ? TAssociatedEntity | null : TAssociatedEntity>
|
||||||
|
> {
|
||||||
const associatedEntityID = this.entity.getField(fieldIdentifyingAssociatedEntity);
|
const associatedEntityID = this.entity.getField(fieldIdentifyingAssociatedEntity);
|
||||||
|
if (!associatedEntityID) {
|
||||||
|
return result(null) as any;
|
||||||
|
}
|
||||||
|
|
||||||
const loader = this.entity
|
const loader = this.entity
|
||||||
.getViewerContext()
|
.getViewerContext()
|
||||||
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
||||||
.getLoaderFactory()
|
.getLoaderFactory()
|
||||||
.forLoad(queryContext);
|
.forLoad(queryContext);
|
||||||
return await loader.loadByIDAsync((associatedEntityID as unknown) as TAssociatedID);
|
return (await loader.loadByIDAsync((associatedEntityID as unknown) as TAssociatedID)) as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,6 +134,7 @@ export default class EntityAssociationLoader<
|
|||||||
* @param queryContext - query context in which to perform the load
|
* @param queryContext - query context in which to perform the load
|
||||||
*/
|
*/
|
||||||
async loadAssociatedEntityByFieldEqualingAsync<
|
async loadAssociatedEntityByFieldEqualingAsync<
|
||||||
|
TIdentifyingField extends keyof Pick<TFields, TSelectedFields>,
|
||||||
TAssociatedFields,
|
TAssociatedFields,
|
||||||
TAssociatedID,
|
TAssociatedID,
|
||||||
TAssociatedEntity extends ReadonlyEntity<
|
TAssociatedEntity extends ReadonlyEntity<
|
||||||
@@ -144,7 +152,7 @@ export default class EntityAssociationLoader<
|
|||||||
>,
|
>,
|
||||||
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
TAssociatedSelectedFields extends keyof TAssociatedFields = keyof TAssociatedFields
|
||||||
>(
|
>(
|
||||||
fieldIdentifyingAssociatedEntity: keyof Pick<TFields, TSelectedFields>,
|
fieldIdentifyingAssociatedEntity: TIdentifyingField,
|
||||||
associatedEntityClass: IEntityClass<
|
associatedEntityClass: IEntityClass<
|
||||||
TAssociatedFields,
|
TAssociatedFields,
|
||||||
TAssociatedID,
|
TAssociatedID,
|
||||||
@@ -159,8 +167,12 @@ export default class EntityAssociationLoader<
|
|||||||
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
||||||
.getQueryContextProvider()
|
.getQueryContextProvider()
|
||||||
.getQueryContext()
|
.getQueryContext()
|
||||||
): Promise<Result<TAssociatedEntity> | null> {
|
): Promise<Result<TAssociatedEntity | null>> {
|
||||||
const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity);
|
const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity);
|
||||||
|
if (!associatedFieldValue) {
|
||||||
|
return result(null);
|
||||||
|
}
|
||||||
|
|
||||||
const loader = this.entity
|
const loader = this.entity
|
||||||
.getViewerContext()
|
.getViewerContext()
|
||||||
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
||||||
@@ -215,6 +227,10 @@ export default class EntityAssociationLoader<
|
|||||||
.getQueryContext()
|
.getQueryContext()
|
||||||
): Promise<readonly Result<TAssociatedEntity>[]> {
|
): Promise<readonly Result<TAssociatedEntity>[]> {
|
||||||
const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity);
|
const associatedFieldValue = this.entity.getField(fieldIdentifyingAssociatedEntity);
|
||||||
|
if (!associatedFieldValue) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const loader = this.entity
|
const loader = this.entity
|
||||||
.getViewerContext()
|
.getViewerContext()
|
||||||
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
.getViewerScopedEntityCompanionForClass(associatedEntityClass)
|
||||||
@@ -258,7 +274,7 @@ export default class EntityAssociationLoader<
|
|||||||
>
|
>
|
||||||
],
|
],
|
||||||
queryContext?: EntityQueryContext
|
queryContext?: EntityQueryContext
|
||||||
): Promise<Result<TEntity2> | null>;
|
): Promise<Result<TEntity2 | null>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
|
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
|
||||||
@@ -313,7 +329,7 @@ export default class EntityAssociationLoader<
|
|||||||
>
|
>
|
||||||
],
|
],
|
||||||
queryContext?: EntityQueryContext
|
queryContext?: EntityQueryContext
|
||||||
): Promise<Result<TEntity3> | null>;
|
): Promise<Result<TEntity3 | null>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
|
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
|
||||||
@@ -389,7 +405,7 @@ export default class EntityAssociationLoader<
|
|||||||
>
|
>
|
||||||
],
|
],
|
||||||
queryContext?: EntityQueryContext
|
queryContext?: EntityQueryContext
|
||||||
): Promise<Result<TEntity4> | null>;
|
): Promise<Result<TEntity4 | null>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
|
* Load an associated entity by folding a sequence of {@link EntityLoadThroughDirective}. At each
|
||||||
@@ -400,12 +416,12 @@ export default class EntityAssociationLoader<
|
|||||||
async loadAssociatedEntityThroughAsync(
|
async loadAssociatedEntityThroughAsync(
|
||||||
loadDirectives: EntityLoadThroughDirective<TViewerContext, any, any, any, any, any, any, any>[],
|
loadDirectives: EntityLoadThroughDirective<TViewerContext, any, any, any, any, any, any, any>[],
|
||||||
queryContext?: EntityQueryContext
|
queryContext?: EntityQueryContext
|
||||||
): Promise<Result<ReadonlyEntity<any, any, any, any>> | null>;
|
): Promise<Result<ReadonlyEntity<any, any, any, any> | null>>;
|
||||||
|
|
||||||
async loadAssociatedEntityThroughAsync(
|
async loadAssociatedEntityThroughAsync(
|
||||||
loadDirectives: EntityLoadThroughDirective<TViewerContext, any, any, any, any, any, any, any>[],
|
loadDirectives: EntityLoadThroughDirective<TViewerContext, any, any, any, any, any, any, any>[],
|
||||||
queryContext?: EntityQueryContext
|
queryContext?: EntityQueryContext
|
||||||
): Promise<Result<ReadonlyEntity<any, any, any, any>> | null> {
|
): Promise<Result<ReadonlyEntity<any, any, any, any> | null>> {
|
||||||
let currentEntity: ReadonlyEntity<any, any, any, any> = this.entity;
|
let currentEntity: ReadonlyEntity<any, any, any, any> = this.entity;
|
||||||
for (const loadDirective of loadDirectives) {
|
for (const loadDirective of loadDirectives) {
|
||||||
const {
|
const {
|
||||||
@@ -413,7 +429,7 @@ export default class EntityAssociationLoader<
|
|||||||
fieldIdentifyingAssociatedEntity,
|
fieldIdentifyingAssociatedEntity,
|
||||||
associatedEntityLookupByField,
|
associatedEntityLookupByField,
|
||||||
} = loadDirective;
|
} = loadDirective;
|
||||||
let associatedEntityResult: Result<ReadonlyEntity<any, any, any, any>> | null;
|
let associatedEntityResult: Result<ReadonlyEntity<any, any, any, any> | null>;
|
||||||
if (associatedEntityLookupByField) {
|
if (associatedEntityLookupByField) {
|
||||||
associatedEntityResult = await currentEntity
|
associatedEntityResult = await currentEntity
|
||||||
.associationLoader()
|
.associationLoader()
|
||||||
@@ -433,13 +449,14 @@ export default class EntityAssociationLoader<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!associatedEntityResult) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!associatedEntityResult.ok) {
|
if (!associatedEntityResult.ok) {
|
||||||
return result(associatedEntityResult.reason);
|
return result(associatedEntityResult.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!associatedEntityResult.value) {
|
||||||
|
return result(null);
|
||||||
|
}
|
||||||
|
|
||||||
currentEntity = associatedEntityResult.value;
|
currentEntity = associatedEntityResult.value;
|
||||||
}
|
}
|
||||||
return result(currentEntity);
|
return result(currentEntity);
|
||||||
|
|||||||
@@ -132,13 +132,13 @@ export default class EntityLoader<
|
|||||||
async loadByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
|
async loadByFieldEqualingAsync<N extends keyof Pick<TFields, TSelectedFields>>(
|
||||||
uniqueFieldName: N,
|
uniqueFieldName: N,
|
||||||
fieldValue: NonNullable<TFields[N]>
|
fieldValue: NonNullable<TFields[N]>
|
||||||
): Promise<Result<TEntity> | null> {
|
): Promise<Result<TEntity | null>> {
|
||||||
const entityResults = await this.loadManyByFieldEqualingAsync(uniqueFieldName, fieldValue);
|
const entityResults = await this.loadManyByFieldEqualingAsync(uniqueFieldName, fieldValue);
|
||||||
invariant(
|
invariant(
|
||||||
entityResults.length <= 1,
|
entityResults.length <= 1,
|
||||||
`loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${uniqueFieldName}=${fieldValue}`
|
`loadByFieldEqualing: Multiple entities of type ${this.entityClass.name} found for ${uniqueFieldName}=${fieldValue}`
|
||||||
);
|
);
|
||||||
return entityResults[0] ?? null;
|
return entityResults[0] ?? result(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,7 +160,7 @@ export default class EntityLoader<
|
|||||||
* @param id - ID of the entity
|
* @param id - ID of the entity
|
||||||
* @returns entity result for matching ID, or null if no entity exists for ID.
|
* @returns entity result for matching ID, or null if no entity exists for ID.
|
||||||
*/
|
*/
|
||||||
async loadByIDNullableAsync(id: TID): Promise<Result<TEntity> | null> {
|
async loadByIDNullableAsync(id: TID): Promise<Result<TEntity | null>> {
|
||||||
return await this.loadByFieldEqualingAsync(this.idField, id as any);
|
return await this.loadByFieldEqualingAsync(this.idField, id as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUn
|
|||||||
|
|
||||||
describe(EntityAssociationLoader, () => {
|
describe(EntityAssociationLoader, () => {
|
||||||
describe('loadAssociatedEntityAsync', () => {
|
describe('loadAssociatedEntityAsync', () => {
|
||||||
it('loads associated entities by ID', async () => {
|
it('loads associated entities by ID and correctly handles a null value', async () => {
|
||||||
const companionProvider = createUnitTestEntityCompanionProvider();
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
||||||
const viewerContext = new TestViewerContext(companionProvider);
|
const viewerContext = new TestViewerContext(companionProvider);
|
||||||
const testOtherEntity = await enforceAsyncResult(
|
const testOtherEntity = await enforceAsyncResult(
|
||||||
@@ -24,6 +24,11 @@ describe(EntityAssociationLoader, () => {
|
|||||||
testEntity.associationLoader().loadAssociatedEntityAsync('stringField', TestEntity)
|
testEntity.associationLoader().loadAssociatedEntityAsync('stringField', TestEntity)
|
||||||
);
|
);
|
||||||
expect(loadedOther.getID()).toEqual(testOtherEntity.getID());
|
expect(loadedOther.getID()).toEqual(testOtherEntity.getID());
|
||||||
|
|
||||||
|
const loadedOther2 = await enforceAsyncResult(
|
||||||
|
testEntity.associationLoader().loadAssociatedEntityAsync('nullableField', TestEntity)
|
||||||
|
);
|
||||||
|
expect(loadedOther2).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -62,7 +67,7 @@ describe(EntityAssociationLoader, () => {
|
|||||||
const loadedOtherResult = await testEntity
|
const loadedOtherResult = await testEntity
|
||||||
.associationLoader()
|
.associationLoader()
|
||||||
.loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
|
.loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
|
||||||
expect(loadedOtherResult?.enforceValue().getID()).toEqual(testOtherEntity.getID());
|
expect(loadedOtherResult.enforceValue()?.getID()).toEqual(testOtherEntity.getID());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns null when loading associated entities by field equaling a non existent association', async () => {
|
it('returns null when loading associated entities by field equaling a non existent association', async () => {
|
||||||
@@ -74,7 +79,19 @@ describe(EntityAssociationLoader, () => {
|
|||||||
const loadedOtherResult = await testEntity
|
const loadedOtherResult = await testEntity
|
||||||
.associationLoader()
|
.associationLoader()
|
||||||
.loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
|
.loadAssociatedEntityByFieldEqualingAsync('stringField', TestEntity, 'customIdField');
|
||||||
expect(loadedOtherResult).toBeNull();
|
expect(loadedOtherResult.enforceValue()).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null when load-by field is null', async () => {
|
||||||
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
||||||
|
const viewerContext = new TestViewerContext(companionProvider);
|
||||||
|
const testEntity = await enforceAsyncResult(
|
||||||
|
TestEntity.creator(viewerContext).setField('stringField', 'blah').createAsync()
|
||||||
|
);
|
||||||
|
const loadedOtherResult = await testEntity
|
||||||
|
.associationLoader()
|
||||||
|
.loadAssociatedEntityByFieldEqualingAsync('nullableField', TestEntity, 'customIdField');
|
||||||
|
expect(loadedOtherResult.enforceValue()).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,6 +119,22 @@ describe(EntityAssociationLoader, () => {
|
|||||||
expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
|
expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
|
||||||
expect(loaded.find((e) => e.getID() === testOtherEntity2.getID())).not.toBeUndefined();
|
expect(loaded.find((e) => e.getID() === testOtherEntity2.getID())).not.toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns empty results when field being queried by is null', async () => {
|
||||||
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
||||||
|
const viewerContext = new TestViewerContext(companionProvider);
|
||||||
|
const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync());
|
||||||
|
const loaded = await enforceResultsAsync(
|
||||||
|
testEntity
|
||||||
|
.associationLoader()
|
||||||
|
.loadManyAssociatedEntitiesByFieldEqualingAsync(
|
||||||
|
'nullableField',
|
||||||
|
TestEntity,
|
||||||
|
'stringField'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
expect(loaded).toHaveLength(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('loadAssociatedEntityThroughAsync', () => {
|
describe('loadAssociatedEntityThroughAsync', () => {
|
||||||
@@ -127,7 +160,7 @@ describe(EntityAssociationLoader, () => {
|
|||||||
fieldIdentifyingAssociatedEntity: 'foreignKey',
|
fieldIdentifyingAssociatedEntity: 'foreignKey',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID());
|
expect(loaded2Result.enforceValue()?.getID()).toEqual(testEntity2.getID());
|
||||||
|
|
||||||
const loaded3Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
const loaded3Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
||||||
{
|
{
|
||||||
@@ -139,7 +172,7 @@ describe(EntityAssociationLoader, () => {
|
|||||||
fieldIdentifyingAssociatedEntity: 'testIndexedField',
|
fieldIdentifyingAssociatedEntity: 'testIndexedField',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(loaded3Result?.enforceValue().getID()).toEqual(testEntity3.getID());
|
expect(loaded3Result.enforceValue()?.getID()).toEqual(testEntity3.getID());
|
||||||
|
|
||||||
const loaded4Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
const loaded4Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
||||||
{
|
{
|
||||||
@@ -155,7 +188,7 @@ describe(EntityAssociationLoader, () => {
|
|||||||
fieldIdentifyingAssociatedEntity: 'foreignKey',
|
fieldIdentifyingAssociatedEntity: 'foreignKey',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(loaded4Result?.enforceValue().getID()).toEqual(testEntity4.getID());
|
expect(loaded4Result.enforceValue()?.getID()).toEqual(testEntity4.getID());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails when chain loading associated entity fails', async () => {
|
it('fails when chain loading associated entity fails', async () => {
|
||||||
@@ -193,7 +226,7 @@ describe(EntityAssociationLoader, () => {
|
|||||||
associatedEntityLookupByField: 'stringField',
|
associatedEntityLookupByField: 'stringField',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(loaded2Result?.enforceValue().getID()).toEqual(testEntity2.getID());
|
expect(loaded2Result.enforceValue()?.getID()).toEqual(testEntity2.getID());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns null when chain loading by field equality returns null', async () => {
|
it('returns null when chain loading by field equality returns null', async () => {
|
||||||
@@ -211,7 +244,24 @@ describe(EntityAssociationLoader, () => {
|
|||||||
associatedEntityLookupByField: 'stringField',
|
associatedEntityLookupByField: 'stringField',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(loaded2Result).toBeNull();
|
expect(loaded2Result.enforceValue()).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null when chain loading by field is null', async () => {
|
||||||
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
||||||
|
const viewerContext = new TestViewerContext(companionProvider);
|
||||||
|
|
||||||
|
const testEntity = await enforceAsyncResult(
|
||||||
|
TestEntity.creator(viewerContext).setField('nullableField', null).createAsync()
|
||||||
|
);
|
||||||
|
|
||||||
|
const loadedResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
||||||
|
{
|
||||||
|
associatedEntityClass: TestEntity,
|
||||||
|
fieldIdentifyingAssociatedEntity: 'nullableField',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(loadedResult.enforceValue()).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -36,6 +36,7 @@ describe(EntityLoader, () => {
|
|||||||
numberField: 5,
|
numberField: 5,
|
||||||
stringField: 'huh',
|
stringField: 'huh',
|
||||||
dateField: dateToInsert,
|
dateField: dateToInsert,
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -43,6 +44,7 @@ describe(EntityLoader, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'huh',
|
stringField: 'huh',
|
||||||
dateField: dateToInsert,
|
dateField: dateToInsert,
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -79,16 +81,16 @@ describe(EntityLoader, () => {
|
|||||||
|
|
||||||
const entityResultNumber3 = await entityLoader.loadByFieldEqualingAsync('numberField', 3);
|
const entityResultNumber3 = await entityLoader.loadByFieldEqualingAsync('numberField', 3);
|
||||||
expect(entityResultNumber3).not.toBeNull();
|
expect(entityResultNumber3).not.toBeNull();
|
||||||
expect(entityResultNumber3!.enforceValue().getID()).toEqual('world');
|
expect(entityResultNumber3.enforceValue()?.getID()).toEqual('world');
|
||||||
|
|
||||||
const entityResultNumber4 = await entityLoader.loadByFieldEqualingAsync('numberField', 4);
|
const entityResultNumber4 = await entityLoader.loadByFieldEqualingAsync('numberField', 4);
|
||||||
expect(entityResultNumber4).toBeNull();
|
expect(entityResultNumber4.enforceValue()).toBeNull();
|
||||||
|
|
||||||
await expect(entityLoader.loadByFieldEqualingAsync('stringField', 'huh')).rejects.toThrowError(
|
await expect(entityLoader.loadByFieldEqualingAsync('stringField', 'huh')).rejects.toThrowError(
|
||||||
'loadByFieldEqualing: Multiple entities of type TestEntity found for stringField=huh'
|
'loadByFieldEqualing: Multiple entities of type TestEntity found for stringField=huh'
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(entityLoader.loadByIDNullableAsync('fake')).resolves.toBeNull();
|
expect((await entityLoader.loadByIDNullableAsync('fake')).enforceValue()).toBeNull();
|
||||||
await expect(entityLoader.loadByIDNullableAsync('hello')).resolves.not.toBeNull();
|
await expect(entityLoader.loadByIDNullableAsync('hello')).resolves.not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -112,6 +114,7 @@ describe(EntityLoader, () => {
|
|||||||
numberField: 4,
|
numberField: 4,
|
||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -119,6 +122,7 @@ describe(EntityLoader, () => {
|
|||||||
numberField: 4,
|
numberField: 4,
|
||||||
testIndexedField: '5',
|
testIndexedField: '5',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'blah',
|
customIdField: 'blah',
|
||||||
@@ -126,6 +130,7 @@ describe(EntityLoader, () => {
|
|||||||
numberField: 4,
|
numberField: 4,
|
||||||
testIndexedField: '6',
|
testIndexedField: '6',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -189,6 +194,7 @@ describe(EntityLoader, () => {
|
|||||||
testIndexedField: '1',
|
testIndexedField: '1',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -310,6 +310,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -317,6 +318,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '5',
|
testIndexedField: '5',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const newEntity = await entityMutatorFactory
|
const newEntity = await entityMutatorFactory
|
||||||
@@ -336,6 +338,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -343,6 +346,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '5',
|
testIndexedField: '5',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -372,6 +376,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -379,6 +384,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '5',
|
testIndexedField: '5',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -409,6 +415,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -416,6 +423,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '5',
|
testIndexedField: '5',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -441,6 +449,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -448,6 +457,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -484,6 +494,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -491,6 +502,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -528,6 +540,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -535,6 +548,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -573,6 +587,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -580,6 +595,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '4',
|
testIndexedField: '4',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -609,6 +625,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -640,6 +657,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -674,6 +692,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -709,6 +728,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -734,6 +754,7 @@ describe(EntityMutatorFactory, () => {
|
|||||||
testIndexedField: '3',
|
testIndexedField: '3',
|
||||||
numberField: 3,
|
numberField: 3,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ describe(ReadonlyEntity, () => {
|
|||||||
stringField: '3',
|
stringField: '3',
|
||||||
numberField: 4,
|
numberField: 4,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
});
|
});
|
||||||
expect(testEntity.getUniqueIdentifier()).not.toEqual(testEntity2.getUniqueIdentifier());
|
expect(testEntity.getUniqueIdentifier()).not.toEqual(testEntity2.getUniqueIdentifier());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -103,6 +103,15 @@ export default class EntityDataManager<TFields> {
|
|||||||
fieldName: N,
|
fieldName: N,
|
||||||
fieldValues: readonly NonNullable<TFields[N]>[]
|
fieldValues: readonly NonNullable<TFields[N]>[]
|
||||||
): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>> {
|
): Promise<ReadonlyMap<NonNullable<TFields[N]>, readonly Readonly<TFields>[]>> {
|
||||||
|
const nullOrUndefinedValueIndex = fieldValues.findIndex(
|
||||||
|
(value) => value === null || value === undefined
|
||||||
|
);
|
||||||
|
if (nullOrUndefinedValueIndex >= 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid load: ${this.entityClassName} (${fieldName} = ${fieldValues[nullOrUndefinedValueIndex]})`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// don't cache when in transaction, as rollbacks complicate things significantly
|
// don't cache when in transaction, as rollbacks complicate things significantly
|
||||||
if (queryContext.isInTransaction()) {
|
if (queryContext.isInTransaction()) {
|
||||||
return await this.databaseAdapter.fetchManyWhereAsync(queryContext, fieldName, fieldValues);
|
return await this.databaseAdapter.fetchManyWhereAsync(queryContext, fieldName, fieldValues);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const getObjects = (): Map<string, TestFields[]> =>
|
|||||||
stringField: 'hello',
|
stringField: 'hello',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: '2',
|
customIdField: '2',
|
||||||
@@ -43,6 +44,7 @@ const getObjects = (): Map<string, TestFields[]> =>
|
|||||||
stringField: 'hello',
|
stringField: 'hello',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: '3',
|
customIdField: '3',
|
||||||
@@ -50,6 +52,7 @@ const getObjects = (): Map<string, TestFields[]> =>
|
|||||||
stringField: 'world',
|
stringField: 'world',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -566,4 +569,34 @@ describe(EntityDataManager, () => {
|
|||||||
verify(metricsAdapterMock.incrementDataManagerCacheLoadCount(anyNumber())).never();
|
verify(metricsAdapterMock.incrementDataManagerCacheLoadCount(anyNumber())).never();
|
||||||
verify(metricsAdapterMock.incrementDataManagerDatabaseLoadCount(anyNumber())).never();
|
verify(metricsAdapterMock.incrementDataManagerDatabaseLoadCount(anyNumber())).never();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('throws when a load by value is null or undefined', async () => {
|
||||||
|
const objects = getObjects();
|
||||||
|
const dataStore = StubDatabaseAdapter.convertFieldObjectsToDataStore(
|
||||||
|
testEntityConfiguration,
|
||||||
|
objects
|
||||||
|
);
|
||||||
|
const databaseAdapter = new StubDatabaseAdapter<TestFields>(testEntityConfiguration, dataStore);
|
||||||
|
const cacheAdapterProvider = new NoCacheStubCacheAdapterProvider();
|
||||||
|
const cacheAdapter = cacheAdapterProvider.getCacheAdapter(testEntityConfiguration);
|
||||||
|
const entityCache = new ReadThroughEntityCache(testEntityConfiguration, cacheAdapter);
|
||||||
|
const entityDataManager = new EntityDataManager(
|
||||||
|
databaseAdapter,
|
||||||
|
entityCache,
|
||||||
|
StubQueryContextProvider,
|
||||||
|
new NoOpEntityMetricsAdapter(),
|
||||||
|
TestEntity.name
|
||||||
|
);
|
||||||
|
const queryContext = StubQueryContextProvider.getQueryContext();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'nullableField', [null as any])
|
||||||
|
).rejects.toThrowError('Invalid load: TestEntity (nullableField = null)');
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
entityDataManager.loadManyByFieldEqualingAsync(queryContext, 'nullableField', [
|
||||||
|
undefined as any,
|
||||||
|
])
|
||||||
|
).rejects.toThrowError('Invalid load: TestEntity (nullableField = undefined)');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -18,6 +18,7 @@ export type TestFields = {
|
|||||||
stringField: string;
|
stringField: string;
|
||||||
numberField: number;
|
numberField: number;
|
||||||
dateField: Date;
|
dateField: Date;
|
||||||
|
nullableField: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
export const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
||||||
@@ -40,6 +41,9 @@ export const testEntityConfiguration = new EntityConfiguration<TestFields>({
|
|||||||
dateField: new DateField({
|
dateField: new DateField({
|
||||||
columnName: 'date_field',
|
columnName: 'date_field',
|
||||||
}),
|
}),
|
||||||
|
nullableField: new StringField({
|
||||||
|
columnName: 'nullable_field',
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES,
|
databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES,
|
||||||
cacheAdapterFlavor: CacheAdapterFlavor.REDIS,
|
cacheAdapterFlavor: CacheAdapterFlavor.REDIS,
|
||||||
@@ -88,6 +92,7 @@ export default class TestEntity extends Entity<TestFields, string, ViewerContext
|
|||||||
stringField: 'hello',
|
stringField: 'hello',
|
||||||
numberField: 1,
|
numberField: 1,
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 5,
|
numberField: 5,
|
||||||
stringField: 'huh',
|
stringField: 'huh',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -42,6 +43,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'wat',
|
stringField: 'wat',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -73,6 +75,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'a',
|
stringField: 'a',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -80,6 +83,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'b',
|
stringField: 'b',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -87,6 +91,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'c',
|
stringField: 'c',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -138,6 +143,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'a',
|
stringField: 'a',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -145,6 +151,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'b',
|
stringField: 'b',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
customIdField: 'world',
|
customIdField: 'world',
|
||||||
@@ -152,6 +159,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'c',
|
stringField: 'c',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -236,6 +244,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'a',
|
stringField: 'a',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -269,6 +278,7 @@ describe(StubDatabaseAdapter, () => {
|
|||||||
numberField: 3,
|
numberField: 3,
|
||||||
stringField: 'a',
|
stringField: 'a',
|
||||||
dateField: new Date(),
|
dateField: new Date(),
|
||||||
|
nullableField: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in new issue
Block a user