Skip to content

Commit ebe9b00

Browse files
authored
Querying json data now works in mysql
Added prisma extension to convert "path" from array format (postgresql) to string format (mysql)
1 parent 427c994 commit ebe9b00

File tree

4 files changed

+99
-2
lines changed

4 files changed

+99
-2
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Prisma } from '@prisma/client'
2+
import { Logger } from '@config/logger.config';
3+
4+
const logger = new Logger('PGPATH2MYSQL');
5+
6+
function convertPgPathToMysql (path) {
7+
if (!Array.isArray(path)) return path
8+
let result = '$'
9+
for (const item of path) {
10+
if (/^\d+$/.test(item)) {
11+
result += `[${item}]`
12+
} else {
13+
result += `.${item}`
14+
}
15+
}
16+
return result
17+
}
18+
19+
function processWhere (obj) {
20+
if (obj && typeof obj === 'object') {
21+
for (const key in obj) {
22+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
23+
if (key === 'path') {
24+
obj[key] = convertPgPathToMysql(obj[key]);
25+
} else {
26+
processWhere(obj[key]);
27+
}
28+
}
29+
}
30+
}
31+
}
32+
33+
// https://www.prisma.io/docs/orm/prisma-client/client-extensions/query#modify-all-operations-in-all-models-of-your-schema
34+
// https://www.prisma.io/docs/orm/prisma-client/client-extensions/query#modify-a-specific-operation-in-a-specific-model
35+
36+
const overriddenOperation = async ({ model, operation, args, query }) => {
37+
if (args?.where) {
38+
processWhere(args.where)
39+
}
40+
const result = await query(args)
41+
logger.debug({ model, operation, args: JSON.stringify(args), result })
42+
return result
43+
}
44+
45+
export default Prisma.defineExtension({
46+
name: 'prisma-extension-pgpath-to-mysql',
47+
query: {
48+
$allModels: {
49+
findFirst: overriddenOperation,
50+
findMany: overriddenOperation,
51+
updateMany: overriddenOperation,
52+
count: overriddenOperation,
53+
deleteMany: overriddenOperation,
54+
55+
delete: overriddenOperation,
56+
findUnique: overriddenOperation,
57+
update: overriddenOperation,
58+
upsert: overriddenOperation,
59+
}
60+
}
61+
})

src/api/server.module.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CacheEngine } from '@cache/cacheengine';
2-
import { Chatwoot, configService, ProviderSession } from '@config/env.config';
2+
import { Chatwoot, configService, ProviderSession, Database } from '@config/env.config';
33
import { eventEmitter } from '@config/event.config';
44
import { Logger } from '@config/logger.config';
55

@@ -40,6 +40,9 @@ import { ProxyService } from './services/proxy.service';
4040
import { SettingsService } from './services/settings.service';
4141
import { TemplateService } from './services/template.service';
4242

43+
import pgPathToMysql from './extensions/prismaExtensionPgpathToMysql';
44+
import { extendsWithProxy } from '@utils/extendsWithProxy';
45+
4346
const logger = new Logger('WA MODULE');
4447

4548
let chatwootCache: CacheService = null;
@@ -55,7 +58,12 @@ if (configService.get<ProviderSession>('PROVIDER').ENABLED) {
5558
providerFiles = new ProviderFiles(configService);
5659
}
5760

58-
export const prismaRepository = new PrismaRepository(configService);
61+
const provider = configService.get<Database>('DATABASE').PROVIDER;
62+
let extendablePrismaRepository: PrismaRepository = new PrismaRepository(configService)
63+
if (provider === "mysql") {
64+
extendablePrismaRepository = extendsWithProxy(extendablePrismaRepository, pgPathToMysql);
65+
}
66+
export const prismaRepository = extendablePrismaRepository;
5967

6068
export const waMonitor = new WAMonitoringService(
6169
eventEmitter,

src/utils/extendsWithProxy.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { PrismaClient } from '@prisma/client';
2+
3+
type ExtensionArgs = Parameters<PrismaClient['$extends']>[0];
4+
5+
export function extendsWithProxy<T extends PrismaClient>(
6+
instanciaBase: T,
7+
extensao: ExtensionArgs
8+
): T {
9+
const instanciaEstendida = instanciaBase.$extends(extensao);
10+
11+
const proxy = new Proxy(instanciaBase as unknown as object, {
12+
get(target, prop, receiver) {
13+
if (prop === 'toString') {
14+
return () => '[Proxy toString]';
15+
}
16+
if (prop === Symbol.toStringTag) {
17+
return undefined;
18+
}
19+
return prop in instanciaEstendida ? Reflect.get(instanciaEstendida as any, prop, receiver) : Reflect.get(target, prop, receiver);
20+
},
21+
has(target, prop) {
22+
return prop in target || prop in (instanciaEstendida as any);
23+
},
24+
});
25+
26+
return proxy as unknown as T;
27+
}

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"strictNullChecks": false,
1818
"incremental": true,
1919
"noImplicitAny": false,
20+
"allowJs": true,
2021
"baseUrl": ".",
2122
"paths": {
2223
"@api/*": ["./src/api/*"],

0 commit comments

Comments
 (0)