test: stub prisma modelType delegate
This commit is contained in:
@@ -111,6 +111,17 @@ type PieceRecord = {
|
|||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ModelTypeRecord = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
category: 'COMPONENT' | 'PIECE';
|
||||||
|
description: Nullable<string>;
|
||||||
|
notes: Nullable<string>;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
};
|
||||||
|
|
||||||
type CustomFieldRecord = {
|
type CustomFieldRecord = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -152,6 +163,7 @@ class InMemoryPrismaService {
|
|||||||
private sites: SiteRecord[] = [];
|
private sites: SiteRecord[] = [];
|
||||||
private typeComposants: TypeComposantRecord[] = [];
|
private typeComposants: TypeComposantRecord[] = [];
|
||||||
private typePieces: TypePieceRecord[] = [];
|
private typePieces: TypePieceRecord[] = [];
|
||||||
|
private modelTypes: ModelTypeRecord[] = [];
|
||||||
private modelTypeCodeCounter = 0;
|
private modelTypeCodeCounter = 0;
|
||||||
private typeMachines: TypeMachineRecord[] = [];
|
private typeMachines: TypeMachineRecord[] = [];
|
||||||
private typeMachineComponentRequirements: TypeMachineComponentRequirementRecord[] =
|
private typeMachineComponentRequirements: TypeMachineComponentRequirementRecord[] =
|
||||||
@@ -178,6 +190,7 @@ class InMemoryPrismaService {
|
|||||||
this.sites = [];
|
this.sites = [];
|
||||||
this.typeComposants = [];
|
this.typeComposants = [];
|
||||||
this.typePieces = [];
|
this.typePieces = [];
|
||||||
|
this.modelTypes = [];
|
||||||
this.modelTypeCodeCounter = 0;
|
this.modelTypeCodeCounter = 0;
|
||||||
this.typeMachines = [];
|
this.typeMachines = [];
|
||||||
this.typeMachineComponentRequirements = [];
|
this.typeMachineComponentRequirements = [];
|
||||||
@@ -190,6 +203,131 @@ class InMemoryPrismaService {
|
|||||||
this.profiles = [];
|
this.profiles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly modelTypeDelegate = {
|
||||||
|
create: async ({ data, include }: any) => {
|
||||||
|
const now = new Date();
|
||||||
|
const category: 'COMPONENT' | 'PIECE' = data.category ?? 'COMPONENT';
|
||||||
|
const record: ModelTypeRecord = {
|
||||||
|
id: generateId('model_type'),
|
||||||
|
name: data.name,
|
||||||
|
code: data.code ?? this.generateModelTypeCode(data.name),
|
||||||
|
category,
|
||||||
|
description: data.description ?? null,
|
||||||
|
notes: data.notes ?? null,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
};
|
||||||
|
this.modelTypes.push(record);
|
||||||
|
|
||||||
|
if (data.customFields?.create) {
|
||||||
|
for (const field of data.customFields.create) {
|
||||||
|
this.createCustomFieldForModel(record.id, 'COMPONENT', field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.pieceCustomFields?.create) {
|
||||||
|
for (const field of data.pieceCustomFields.create) {
|
||||||
|
this.createCustomFieldForModel(record.id, 'PIECE', field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.syncModelType(record);
|
||||||
|
const resolvedInclude = typeof include === 'object' ? include : {};
|
||||||
|
return this.buildModelType(record, resolvedInclude);
|
||||||
|
},
|
||||||
|
|
||||||
|
findMany: async ({ where, include, orderBy }: any = {}) => {
|
||||||
|
let records = [...this.modelTypes];
|
||||||
|
if (where) {
|
||||||
|
records = records.filter((item) =>
|
||||||
|
this.matchesModelTypeWhere(item, where),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (orderBy?.name) {
|
||||||
|
records.sort((a, b) =>
|
||||||
|
orderBy.name === 'desc'
|
||||||
|
? b.name.localeCompare(a.name)
|
||||||
|
: a.name.localeCompare(b.name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const resolvedInclude = typeof include === 'object' ? include : {};
|
||||||
|
return records.map((record) =>
|
||||||
|
this.buildModelType(record, resolvedInclude),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
findFirst: async ({ where, include }: any = {}) => {
|
||||||
|
const record = this.modelTypes.find((item) =>
|
||||||
|
this.matchesModelTypeWhere(item, where),
|
||||||
|
);
|
||||||
|
const resolvedInclude = typeof include === 'object' ? include : {};
|
||||||
|
return record ? this.buildModelType(record, resolvedInclude) : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
findUnique: async ({ where, include }: any) => {
|
||||||
|
const record = this.modelTypes.find((item) => {
|
||||||
|
if (!where) return false;
|
||||||
|
if (where.id) {
|
||||||
|
return item.id === where.id;
|
||||||
|
}
|
||||||
|
if (where.code) {
|
||||||
|
return item.code === where.code;
|
||||||
|
}
|
||||||
|
return this.matchesModelTypeWhere(item, where);
|
||||||
|
});
|
||||||
|
const resolvedInclude = typeof include === 'object' ? include : {};
|
||||||
|
return record ? this.buildModelType(record, resolvedInclude) : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
update: async ({ where, data, include }: any) => {
|
||||||
|
const record = this.modelTypes.find((item) =>
|
||||||
|
this.matchesModelTypeWhere(item, where),
|
||||||
|
);
|
||||||
|
if (!record) {
|
||||||
|
throw new Error('ModelType not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.name !== undefined) {
|
||||||
|
record.name = this.applyUpdateValue(data.name);
|
||||||
|
}
|
||||||
|
if (data.description !== undefined) {
|
||||||
|
record.description = this.applyUpdateValue(data.description);
|
||||||
|
}
|
||||||
|
if (data.notes !== undefined) {
|
||||||
|
record.notes = this.applyUpdateValue(data.notes);
|
||||||
|
}
|
||||||
|
if (data.code !== undefined) {
|
||||||
|
record.code = this.applyUpdateValue(data.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
record.updatedAt = new Date();
|
||||||
|
this.syncModelType(record);
|
||||||
|
const resolvedInclude = typeof include === 'object' ? include : {};
|
||||||
|
return this.buildModelType(record, resolvedInclude);
|
||||||
|
},
|
||||||
|
|
||||||
|
delete: async ({ where }: any) => {
|
||||||
|
const index = this.modelTypes.findIndex((item) =>
|
||||||
|
this.matchesModelTypeWhere(item, where),
|
||||||
|
);
|
||||||
|
if (index === -1) {
|
||||||
|
throw new Error('ModelType not found');
|
||||||
|
}
|
||||||
|
const [record] = this.modelTypes.splice(index, 1);
|
||||||
|
this.removeModelType(record);
|
||||||
|
this.customFields = this.customFields.filter(
|
||||||
|
(field) =>
|
||||||
|
field.typeComposantId !== record.id &&
|
||||||
|
field.typePieceId !== record.id,
|
||||||
|
);
|
||||||
|
return { ...record };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
get modelType() {
|
||||||
|
return this.modelTypeDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
site = {
|
site = {
|
||||||
create: async ({ data }: any) => {
|
create: async ({ data }: any) => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@@ -604,6 +742,26 @@ class InMemoryPrismaService {
|
|||||||
this.customFields.push(record);
|
this.customFields.push(record);
|
||||||
return { ...record };
|
return { ...record };
|
||||||
},
|
},
|
||||||
|
createMany: async ({ data }: any) => {
|
||||||
|
const now = new Date();
|
||||||
|
const records = data.map((item: any) => {
|
||||||
|
const record: CustomFieldRecord = {
|
||||||
|
id: generateId('cf'),
|
||||||
|
name: item.name,
|
||||||
|
type: item.type,
|
||||||
|
required: item.required ?? false,
|
||||||
|
options: item.options ?? [],
|
||||||
|
typeMachineId: item.typeMachineId ?? null,
|
||||||
|
typeComposantId: item.typeComposantId ?? null,
|
||||||
|
typePieceId: item.typePieceId ?? null,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
};
|
||||||
|
this.customFields.push(record);
|
||||||
|
return record;
|
||||||
|
});
|
||||||
|
return { count: records.length };
|
||||||
|
},
|
||||||
findMany: async ({ where }: any) => {
|
findMany: async ({ where }: any) => {
|
||||||
return this.customFields
|
return this.customFields
|
||||||
.filter((field) => {
|
.filter((field) => {
|
||||||
@@ -766,6 +924,183 @@ class InMemoryPrismaService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private matchesModelTypeWhere(record: ModelTypeRecord, where?: any) {
|
||||||
|
if (!where) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (where.AND && Array.isArray(where.AND)) {
|
||||||
|
return where.AND.every((clause: any) =>
|
||||||
|
this.matchesModelTypeWhere(record, clause),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (where.OR && Array.isArray(where.OR)) {
|
||||||
|
return where.OR.some((clause: any) =>
|
||||||
|
this.matchesModelTypeWhere(record, clause),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (where.NOT && Array.isArray(where.NOT)) {
|
||||||
|
return where.NOT.every(
|
||||||
|
(clause: any) => !this.matchesModelTypeWhere(record, clause),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Object.entries(where).every(([key, value]) => {
|
||||||
|
if (value === undefined) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
key === 'id' ||
|
||||||
|
key === 'code' ||
|
||||||
|
key === 'category' ||
|
||||||
|
key === 'name'
|
||||||
|
) {
|
||||||
|
return (record as any)[key] === value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createCustomFieldForModel(
|
||||||
|
modelTypeId: string,
|
||||||
|
category: 'COMPONENT' | 'PIECE',
|
||||||
|
field: any,
|
||||||
|
) {
|
||||||
|
const now = new Date();
|
||||||
|
const record: CustomFieldRecord = {
|
||||||
|
id: generateId('cf'),
|
||||||
|
name: field.name,
|
||||||
|
type: field.type,
|
||||||
|
required: field.required ?? false,
|
||||||
|
options: field.options ?? [],
|
||||||
|
typeMachineId: null,
|
||||||
|
typeComposantId: category === 'COMPONENT' ? modelTypeId : null,
|
||||||
|
typePieceId: category === 'PIECE' ? modelTypeId : null,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
};
|
||||||
|
this.customFields.push(record);
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
private syncModelType(record: ModelTypeRecord) {
|
||||||
|
const base = {
|
||||||
|
id: record.id,
|
||||||
|
name: record.name,
|
||||||
|
description: record.description ?? null,
|
||||||
|
createdAt: record.createdAt,
|
||||||
|
updatedAt: record.updatedAt,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (record.category === 'COMPONENT') {
|
||||||
|
const existing = this.typeComposants.find(
|
||||||
|
(item) => item.id === record.id,
|
||||||
|
);
|
||||||
|
if (existing) {
|
||||||
|
existing.name = base.name;
|
||||||
|
existing.description = base.description;
|
||||||
|
existing.updatedAt = record.updatedAt;
|
||||||
|
} else {
|
||||||
|
this.typeComposants.push({ ...base });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const existing = this.typePieces.find((item) => item.id === record.id);
|
||||||
|
if (existing) {
|
||||||
|
existing.name = base.name;
|
||||||
|
existing.description = base.description;
|
||||||
|
existing.updatedAt = record.updatedAt;
|
||||||
|
} else {
|
||||||
|
this.typePieces.push({ ...base });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeModelType(record: ModelTypeRecord) {
|
||||||
|
if (record.category === 'COMPONENT') {
|
||||||
|
this.typeComposants = this.typeComposants.filter(
|
||||||
|
(item) => item.id !== record.id,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.typePieces = this.typePieces.filter((item) => item.id !== record.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateModelTypeCode(name: string) {
|
||||||
|
const base =
|
||||||
|
(name || 'type')
|
||||||
|
.toLowerCase()
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
|
.replace(/^-+|-+$/g, '') || 'type';
|
||||||
|
let candidate = base;
|
||||||
|
let suffix = 1;
|
||||||
|
while (this.modelTypes.some((item) => item.code === candidate)) {
|
||||||
|
candidate = `${base}-${suffix++}`;
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyUpdateValue<T>(value: any): T {
|
||||||
|
if (value && typeof value === 'object' && 'set' in value) {
|
||||||
|
return value.set as T;
|
||||||
|
}
|
||||||
|
return value as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildModelType(record: ModelTypeRecord, include: any) {
|
||||||
|
const base: any = { ...record };
|
||||||
|
|
||||||
|
const customFieldsInclude = include?.customFields;
|
||||||
|
if (customFieldsInclude) {
|
||||||
|
const select =
|
||||||
|
typeof customFieldsInclude === 'object'
|
||||||
|
? customFieldsInclude.select
|
||||||
|
: undefined;
|
||||||
|
base.customFields = this.customFields
|
||||||
|
.filter((field) => field.typeComposantId === record.id)
|
||||||
|
.map((field) => this.applySelect(field, select));
|
||||||
|
}
|
||||||
|
|
||||||
|
const pieceCustomFieldsInclude = include?.pieceCustomFields;
|
||||||
|
if (pieceCustomFieldsInclude) {
|
||||||
|
const select =
|
||||||
|
typeof pieceCustomFieldsInclude === 'object'
|
||||||
|
? pieceCustomFieldsInclude.select
|
||||||
|
: undefined;
|
||||||
|
base.pieceCustomFields = this.customFields
|
||||||
|
.filter((field) => field.typePieceId === record.id)
|
||||||
|
.map((field) => this.applySelect(field, select));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include?.composants) {
|
||||||
|
base.composants = this.composants
|
||||||
|
.filter((item) => item.typeComposantId === record.id)
|
||||||
|
.map((item) => ({ ...item }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include?.models) {
|
||||||
|
base.models = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include?.pieceModels) {
|
||||||
|
base.pieceModels = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include?.pieceRequirements) {
|
||||||
|
base.pieceRequirements = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include?.pieces) {
|
||||||
|
base.pieces = this.pieces
|
||||||
|
.filter((item) => item.typePieceId === record.id)
|
||||||
|
.map((item) => ({ ...item }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include?.componentRequirements) {
|
||||||
|
base.componentRequirements = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
private buildSite(site: SiteRecord, include: any) {
|
private buildSite(site: SiteRecord, include: any) {
|
||||||
const base: any = { ...site };
|
const base: any = { ...site };
|
||||||
if (include?.machines) {
|
if (include?.machines) {
|
||||||
|
|||||||
Reference in New Issue
Block a user