Skip to content

Commit bdb2052

Browse files
fix(chore): cleanup and gitaction
1 parent b16b743 commit bdb2052

File tree

9 files changed

+113
-89
lines changed

9 files changed

+113
-89
lines changed

.github/workflows/checks.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Checks
2+
3+
on:
4+
push:
5+
branches: [dev]
6+
paths:
7+
- "src/**"
8+
pull_request:
9+
branches: [dev]
10+
paths:
11+
- "src/**"
12+
13+
jobs:
14+
check:
15+
runs-on: ubuntu-22.04
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Install Node.js
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: 22.5.1
24+
25+
- name: Install dependencies
26+
run: npm install
27+
28+
- name: Run prettier check on api
29+
run: npm run format-check
30+
working-directory: .
31+
32+
- name: Run lint check on api
33+
run: npm run lint
34+
working-directory: .
35+
36+
# - name: Check Prisma File
37+
# run: npm exec -- prisma validate
38+
# working-directory: .
39+
40+
- name: Run build
41+
run: npm run build
42+
working-directory: .

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"license": "UNLICENSED",
88
"scripts": {
99
"build": "nest build",
10-
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
10+
"format": "prettier --config .prettierrc --write \"src/**/*.ts\" \"test/**/*.ts\"",
11+
"format-check": "prettier --config .prettierrc --check \"src/**/*.ts\" \"test/**/*.ts\" \"envfiles/**/*.js\"",
1112
"start": "nest start",
1213
"start:dev": "nest start --watch",
1314
"start:debug": "nest start --debug --watch",

src/openapi/openapi.service.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import OpenAI from 'openai';
55

66
@Injectable()
77
export class OpenapiService implements OnModuleInit {
8-
constructor(
9-
private readonly configService: ConfigService,
10-
) {}
8+
constructor(private readonly configService: ConfigService) {}
119

1210
async wordEmbedding(word: string) {
1311
const { openIaApiKey } = this.configService.get<AppConfig>(
@@ -31,6 +29,5 @@ export class OpenapiService implements OnModuleInit {
3129
}
3230
}
3331

34-
onModuleInit(): any{
35-
}
32+
onModuleInit(): any {}
3633
}

src/product/product.service.ts

+33-33
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import { Prisma } from '@prisma/client';
22
import { BadRequestException, Injectable } from '@nestjs/common';
3-
import { ConfigService } from '@nestjs/config';
43
import { IProduct, IProductScore } from './types';
5-
import { AppConfig, EnvObjects } from '../config/types';
64
import { PrismaService } from '../prisma/prisma.service';
75
import OpenAI from 'openai';
86
import { OpenapiService } from '../openapi/openapi.service';
97

10-
function jaccardIndex(s1: Set<string>, s2: Set<string>) {
11-
return (s1 as any).intersection(s2).size / (s1 as any).union(s2).size;
12-
}
138
function formatVector(vect: number[]) {
149
return `[${vect.map((nn) => nn.toString(10)).join(',')}]`;
1510
}
@@ -34,8 +29,8 @@ export class ProductService {
3429
throw new BadRequestException(productId, 'Product not found');
3530
}
3631
const scores = await this.prismaService.client.$queryRaw<
37-
(IProductScore & {tagScore: number})[]
38-
>`
32+
(IProductScore & { tagScore: number })[]
33+
>`
3934
SELECT
4035
array_length(allTags.items, 1) AS "unionSize",
4136
interTags.sizee AS "interSize",
@@ -74,19 +69,21 @@ FROM
7469
WHERE
7570
pp2."id" != pp1."id" AND pp1."id" = ${productId};
7671
`;
77-
return scores.map(
78-
({score, tagScore, productId}) => ({
72+
return scores
73+
.map(({ score, tagScore, productId }) => ({
7974
score: TAGS_WEIGH * tagScore + DESCRIPTION_WEIGH * score,
8075
productId,
81-
}),
82-
).sort(({score: score1}, {score: score2}) => score2 - score1);
76+
}))
77+
.sort(({ score: score1 }, { score: score2 }) => score2 - score1);
8378
}
8479

8580
async bulkCreate(items: IProduct[]) {
8681
const wEmbeddingsItems = await Promise.all(
8782
items.map(async (item) => {
8883
try {
89-
const wordEmbedding = await this.openapiService.wordEmbedding(item.description);
84+
const wordEmbedding = await this.openapiService.wordEmbedding(
85+
item.description,
86+
);
9087
return {
9188
...item,
9289
wordEmbedding,
@@ -113,28 +110,31 @@ WHERE
113110
// );
114111
// this.prismaService.client.$executeRaw`INSERT INTO items (id, name, description, tags, wordEmbedding) VALUES ${sqlValues};`;
115112
await this.prismaService.client.$transaction(
116-
([] as Prisma.PrismaPromise<Prisma.BatchPayload | number>[]).concat(...wEmbeddingsItems.map(
117-
// (wEmbeddingsItem) => this.prismaService.client.$executeRaw
118-
// `INSERT INTO "Product" ("id", "name", "description", "tags", "wordEmbedding") VALUES (${wEmbeddingsItem.id},${wEmbeddingsItem.name},${wEmbeddingsItem.description},${wEmbeddingsItem.tags},${formatVector(wEmbeddingsItem.wordEmbedding)});`
119-
// ,
120-
(wEmbeddingsItem) => [
121-
this.prismaService.client.$executeRawUnsafe(
122-
`INSERT INTO "Product" ("id", "name", "description", "tags", "wordEmbedding") VALUES ($1,$2,$3,$4,'${formatVector(wEmbeddingsItem.wordEmbedding)}'::vector);`,
123-
...[
124-
wEmbeddingsItem.id,
125-
wEmbeddingsItem.name,
126-
wEmbeddingsItem.description,
127-
wEmbeddingsItem.tags,
128-
],
129-
),
130-
// ToDo: Store cache of relations between all of them? Symmetric relation
131-
this.prismaService.client.tagOfProduct.createMany({
132-
data: wEmbeddingsItem.tags.map(
133-
(tag) => ({tagValue: tag, productId: wEmbeddingsItem.id}),
113+
([] as Prisma.PrismaPromise<Prisma.BatchPayload | number>[]).concat(
114+
...wEmbeddingsItems.map(
115+
// (wEmbeddingsItem) => this.prismaService.client.$executeRaw
116+
// `INSERT INTO "Product" ("id", "name", "description", "tags", "wordEmbedding") VALUES (${wEmbeddingsItem.id},${wEmbeddingsItem.name},${wEmbeddingsItem.description},${wEmbeddingsItem.tags},${formatVector(wEmbeddingsItem.wordEmbedding)});`
117+
// ,
118+
(wEmbeddingsItem) => [
119+
this.prismaService.client.$executeRawUnsafe(
120+
`INSERT INTO "Product" ("id", "name", "description", "tags", "wordEmbedding") VALUES ($1,$2,$3,$4,'${formatVector(wEmbeddingsItem.wordEmbedding)}'::vector);`,
121+
...[
122+
wEmbeddingsItem.id,
123+
wEmbeddingsItem.name,
124+
wEmbeddingsItem.description,
125+
wEmbeddingsItem.tags,
126+
],
134127
),
135-
}),
136-
],
137-
)),
128+
// ToDo: Store cache of relations between all of them? Symmetric relation
129+
this.prismaService.client.tagOfProduct.createMany({
130+
data: wEmbeddingsItem.tags.map((tag) => ({
131+
tagValue: tag,
132+
productId: wEmbeddingsItem.id,
133+
})),
134+
}),
135+
],
136+
),
137+
),
138138
);
139139
}
140140
}

src/types/builders.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
export type JsonEncodeAble =
32
| { [key: string]: JsonEncodeAble }
43
| JsonEncodeAble[]

test/app.e2e-spec.ts

+22-28
Original file line numberDiff line numberDiff line change
@@ -24,52 +24,46 @@ describe('e2e', () => {
2424
});
2525

2626
it('products', async () => {
27-
const {body: prodSet1} = await request(app.getHttpServer())
27+
await request(app.getHttpServer())
2828
.post('/products')
2929
.send({
3030
products: [
3131
{
32-
id: "i1",
33-
name: "n1",
34-
description: "fooo bar",
35-
tags: [
36-
"t1","t2","t2","t3"
37-
],
32+
id: 'i1',
33+
name: 'n1',
34+
description: 'fooo bar',
35+
tags: ['t1', 't2', 't2', 't3'],
3836
},
3937
],
4038
})
4139
.expect(201);
42-
const {body: prodSet2} = await request(app.getHttpServer())
40+
await request(app.getHttpServer())
4341
.post('/products')
4442
.send({
4543
products: [
4644
{
47-
id: "i2",
48-
name: "n2",
49-
description: "yada blah blah",
50-
tags: [
51-
"t2","t3","t4"
52-
],
45+
id: 'i2',
46+
name: 'n2',
47+
description: 'yada blah blah',
48+
tags: ['t2', 't3', 't4'],
5349
},
5450
{
55-
id: "i3",
56-
name: "n3",
57-
description: "lorem ipsum dolore",
58-
tags: [
59-
"t2","t3"
60-
],
51+
id: 'i3',
52+
name: 'n3',
53+
description: 'lorem ipsum dolore',
54+
tags: ['t2', 't3'],
6155
},
6256
],
6357
})
6458
.expect(201);
6559

66-
const p1Id = 'i1';
67-
const {body: similarities} = await request(app.getHttpServer())
68-
.get(`/products/similar/${p1Id}`)
69-
.expect(200);
70-
expect(similarities.recommendations[0].score).toEqual(0.8333333333333333);
71-
expect(similarities.recommendations[0].productId).toEqual('i3');
72-
expect(similarities.recommendations[1].score).toEqual(0.75);
73-
expect(similarities.recommendations[1].productId).toEqual('i2');
60+
const p1Id = 'i1';
61+
const { body: similarities } = await request(app.getHttpServer())
62+
.get(`/products/similar/${p1Id}`)
63+
.expect(200);
64+
expect(similarities.recommendations[0].score).toEqual(0.8333333333333333);
65+
expect(similarities.recommendations[0].productId).toEqual('i3');
66+
expect(similarities.recommendations[1].score).toEqual(0.75);
67+
expect(similarities.recommendations[1].productId).toEqual('i2');
7468
});
7569
});

test/jest/common-fixture.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
Global,
3-
INestApplication,
4-
Module,
5-
} from '@nestjs/common';
1+
import { Global, INestApplication, Module } from '@nestjs/common';
62
import { Test, TestingModule } from '@nestjs/testing';
73
import { AppModule } from '../../src/app.module';
84
import { setupCors, setupEncoders } from '../../src/bootstrap';

test/jest/env.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import {
2-
IEnvironmentVariables,
3-
} from '../../src/config/types';
1+
import { IEnvironmentVariables } from '../../src/config/types';
42

53
function defined(val: string | undefined): string {
64
if (val === undefined) {

test/jest/setup/reset-db.ts

+10-13
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ const prismaOptions = {
1010
};
1111
const prisma = new PrismaClient(prismaOptions);
1212

13-
const tables = [
14-
'Product',
15-
'TagOfProduct',
16-
];
13+
const tables = ['Product', 'TagOfProduct'];
1714

1815
export default async function resetDb() {
1916
await prisma.$connect();
@@ -31,19 +28,19 @@ export default async function resetDb() {
3128
return;
3229
}
3330
const tableUpperName = `${table
34-
?.at(0)
35-
?.toUpperCase()}${table.slice(1)}`;
31+
?.at(0)
32+
?.toUpperCase()}${table.slice(1)}`;
3633
if (!tableUpperName) {
3734
return;
3835
}
3936
return Promise.all([
40-
prisma.$executeRawUnsafe(
41-
`ALTER SEQUENCE IF EXISTS "${tableUpperName}_id_seq" RESTART WITH 1;`,
42-
),
43-
prisma.$executeRawUnsafe(
44-
`ALTER SEQUENCE IF EXISTS "${table}_id_seq" RESTART WITH 1;`,
45-
),
46-
]);
37+
prisma.$executeRawUnsafe(
38+
`ALTER SEQUENCE IF EXISTS "${tableUpperName}_id_seq" RESTART WITH 1;`,
39+
),
40+
prisma.$executeRawUnsafe(
41+
`ALTER SEQUENCE IF EXISTS "${table}_id_seq" RESTART WITH 1;`,
42+
),
43+
]);
4744
}),
4845
);
4946
} finally {

0 commit comments

Comments
 (0)