Skip to content

Commit 5aa5778

Browse files
committed
Implement EdgeDB Product Repo
1 parent 23d2333 commit 5aa5778

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed

src/components/product/dto/product.dto.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ declare module '../dto/producible.dto' {
269269
}
270270
}
271271

272+
export const ProductConcretes = {
273+
DirectScriptureProduct,
274+
DerivativeScriptureProduct,
275+
OtherProduct,
276+
};
277+
272278
declare module '~/core/resources/map' {
273279
interface ResourceMap {
274280
Product: typeof Product;
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
import { Injectable, Type } from '@nestjs/common';
2+
import { ModuleRef } from '@nestjs/core';
3+
import { LazyGetter } from 'lazy-get-decorator';
4+
import { ID, PublicOf, Session } from '../../common';
5+
import { grabInstances } from '../../common/instance-maps';
6+
import { e, RepoFor } from '../../core/edgedb';
7+
import {
8+
ProductConcretes as ConcreteTypes,
9+
CreateDerivativeScriptureProduct,
10+
CreateDirectScriptureProduct,
11+
CreateOtherProduct,
12+
Product,
13+
} from './dto';
14+
import { ProductRepository } from './product.repository';
15+
16+
// scriptureReferencesOverride, scriptureReferences
17+
18+
const baseHydrate = e.shape(e.Product, (product) => ({
19+
...product['*'],
20+
__typename: product.__type__.name,
21+
project: {
22+
id: true,
23+
status: true,
24+
type: true,
25+
},
26+
engagement: {
27+
id: true,
28+
status: true,
29+
},
30+
parent: e.tuple({
31+
identity: product.engagement.id,
32+
labels: e.array_agg(e.set(product.engagement.__type__.name.slice(9, null))),
33+
properties: e.tuple({
34+
id: product.engagement.id,
35+
createdAt: product.engagement.createdAt,
36+
}),
37+
}),
38+
pnpIndex: true,
39+
scriptureReferences: product.scripture,
40+
}));
41+
42+
const directScriptureExtraHydrate = {
43+
totalVerses: true,
44+
totalVerseEquivalents: true,
45+
} as const;
46+
47+
const derivativeScriptureExtraHydrate = {
48+
scripture: true,
49+
composite: true,
50+
totalVerses: true,
51+
totalVerseEquivalents: true,
52+
} as const;
53+
54+
const otherExtraHydrate = {
55+
title: true,
56+
description: true,
57+
} as const;
58+
59+
const directScriptureProductHydrate = e.shape(
60+
e.DirectScriptureProduct,
61+
(dsp) => ({
62+
...baseHydrate(dsp),
63+
__typename: dsp.__type__.name,
64+
unspecifiedScripture: {
65+
book: true,
66+
totalVerses: true,
67+
},
68+
//TODO - remove after migration
69+
unspecifiedScripturePortion: {
70+
book: true,
71+
totalVerses: true,
72+
},
73+
...directScriptureExtraHydrate,
74+
}),
75+
);
76+
77+
const derivativeScriptureProductHydrate = e.shape(
78+
e.DerivativeScriptureProduct,
79+
(dsp) => ({
80+
...baseHydrate(dsp),
81+
__typename: dsp.__type__.name,
82+
scriptureReferencesOverride: dsp.scriptureOverride,
83+
produces: {
84+
scriptureReferences: e.tuple([dsp.produces.scripture]),
85+
createdAt: dsp.produces.createdAt,
86+
id: dsp.produces.id,
87+
},
88+
...derivativeScriptureExtraHydrate,
89+
}),
90+
);
91+
92+
const otherProductHydrate = e.shape(e.OtherProduct, (op) => ({
93+
...baseHydrate(op),
94+
__typename: op.__type__.name,
95+
scriptureReferencesOverride: false, //TODO - remove after migration
96+
...otherExtraHydrate,
97+
}));
98+
99+
const hydrate = e.shape(e.Product, (product) => ({
100+
...baseHydrate(product),
101+
...e.is(e.DirectScriptureProduct, directScriptureExtraHydrate),
102+
...e.is(e.DerivativeScriptureProduct, derivativeScriptureExtraHydrate),
103+
...e.is(e.OtherProduct, otherExtraHydrate),
104+
}));
105+
106+
export const ConcreteRepos = {
107+
DirectScriptureProduct: class DirectScriptureProductRepository extends RepoFor(
108+
ConcreteTypes.DirectScriptureProduct,
109+
{
110+
hydrate: directScriptureProductHydrate,
111+
omit: ['create'],
112+
},
113+
) {
114+
async create(input: CreateDirectScriptureProduct) {
115+
const engagement = e.cast(
116+
e.LanguageEngagement,
117+
e.uuid(input.engagementId),
118+
);
119+
return await this.defaults.create({
120+
...input,
121+
projectContext: engagement.projectContext,
122+
});
123+
}
124+
},
125+
126+
DerivativeScriptureProduct: class DerivativeScriptureProductRepository extends RepoFor(
127+
ConcreteTypes.DerivativeScriptureProduct,
128+
{
129+
hydrate: derivativeScriptureProductHydrate,
130+
omit: ['create'],
131+
},
132+
) {
133+
async create(input: CreateDerivativeScriptureProduct) {
134+
const engagement = e.cast(
135+
e.LanguageEngagement,
136+
e.uuid(input.engagementId),
137+
);
138+
return await this.defaults.create({
139+
...input,
140+
projectContext: engagement.projectContext,
141+
});
142+
}
143+
},
144+
145+
OtherProduct: class OtherProductRepository extends RepoFor(
146+
ConcreteTypes.OtherProduct,
147+
{
148+
hydrate: otherProductHydrate,
149+
omit: ['create'],
150+
},
151+
) {
152+
async create(input: CreateOtherProduct) {
153+
const engagement = e.cast(
154+
e.LanguageEngagement,
155+
e.uuid(input.engagementId),
156+
);
157+
return await this.defaults.create({
158+
...input,
159+
projectContext: engagement.projectContext,
160+
});
161+
}
162+
},
163+
} satisfies Record<keyof typeof ConcreteTypes, Type>;
164+
165+
@Injectable()
166+
export class ProductEdgedbRepository
167+
extends RepoFor(Product, {
168+
hydrate,
169+
omit: ['create'],
170+
})
171+
implements PublicOf<ProductRepository>
172+
{
173+
constructor(private readonly moduleRef: ModuleRef) {
174+
super();
175+
}
176+
177+
@LazyGetter() protected get concretes() {
178+
return grabInstances(this.moduleRef, ConcreteRepos);
179+
}
180+
181+
async createDerivative(
182+
input: CreateDerivativeScriptureProduct & {
183+
totalVerses: number;
184+
totalVerseEquivalents: number;
185+
},
186+
_session: Session,
187+
) {
188+
return await this.concretes.DerivativeScriptureProduct.create(input);
189+
}
190+
191+
async createDirect(
192+
input: CreateDirectScriptureProduct & {
193+
totalVerses: number;
194+
totalVerseEquivalents: number;
195+
},
196+
_session: Session,
197+
) {
198+
return await this.concretes.DirectScriptureProduct.create(input);
199+
}
200+
201+
async createOther(input: CreateOtherProduct, _session: Session) {
202+
return await this.concretes.OtherProduct.create(input);
203+
}
204+
205+
async listIdsAndScriptureRefs(engagementId: ID) {
206+
const engagement = e.cast(e.LanguageEngagement, e.uuid(engagementId));
207+
const query = e.select(e.DirectScriptureProduct, (dsp) => ({
208+
id: true,
209+
pnpIndex: true,
210+
scriptureRanges: dsp.scripture,
211+
unspecifiedScripture: dsp.unspecifiedScripture,
212+
filter: e.op(dsp.engagement, '=', engagement),
213+
}));
214+
215+
return await this.db.run(query);
216+
}
217+
}

0 commit comments

Comments
 (0)