@lokalise/prisma-utils 5.0.2 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +129 -12
  2. package/dist/errors/cockroachdbError.d.ts +1 -1
  3. package/dist/errors/prismaError.d.ts +1 -1
  4. package/dist/factory/extendPrismaClientWithMetrics.d.ts +3 -0
  5. package/dist/factory/extendPrismaClientWithMetrics.js +90 -0
  6. package/dist/factory/extendPrismaClientWithMetrics.js.map +1 -0
  7. package/dist/factory/index.d.ts +1 -0
  8. package/dist/factory/index.js +2 -0
  9. package/dist/factory/index.js.map +1 -0
  10. package/dist/factory/prismaClientFactory.d.ts +20 -0
  11. package/dist/factory/prismaClientFactory.js +26 -0
  12. package/dist/factory/prismaClientFactory.js.map +1 -0
  13. package/dist/index.d.ts +2 -3
  14. package/dist/index.js +2 -3
  15. package/dist/index.js.map +1 -1
  16. package/dist/transaction/index.d.ts +2 -0
  17. package/dist/transaction/index.js +2 -0
  18. package/dist/transaction/index.js.map +1 -0
  19. package/dist/transaction/prismaTransaction.d.ts +17 -0
  20. package/dist/{prismaTransaction.js → transaction/prismaTransaction.js} +5 -6
  21. package/dist/transaction/prismaTransaction.js.map +1 -0
  22. package/dist/transaction/types.d.ts +15 -0
  23. package/dist/transaction/types.js +2 -0
  24. package/dist/transaction/types.js.map +1 -0
  25. package/dist/types.d.ts +2 -39
  26. package/dist/types.js +2 -1
  27. package/dist/types.js.map +1 -1
  28. package/package.json +13 -18
  29. package/dist/isolation_level/isolationLevel.d.ts +0 -3
  30. package/dist/isolation_level/isolationLevel.js +0 -2
  31. package/dist/isolation_level/isolationLevel.js.map +0 -1
  32. package/dist/plugins/CollectionScheduler.d.ts +0 -12
  33. package/dist/plugins/CollectionScheduler.js +0 -20
  34. package/dist/plugins/CollectionScheduler.js.map +0 -1
  35. package/dist/plugins/MetricsCollector.d.ts +0 -36
  36. package/dist/plugins/MetricsCollector.js +0 -188
  37. package/dist/plugins/MetricsCollector.js.map +0 -1
  38. package/dist/plugins/prismaMetricsPlugin.d.ts +0 -21
  39. package/dist/plugins/prismaMetricsPlugin.js +0 -49
  40. package/dist/plugins/prismaMetricsPlugin.js.map +0 -1
  41. package/dist/prismaClientFactory.d.ts +0 -5
  42. package/dist/prismaClientFactory.js +0 -11
  43. package/dist/prismaClientFactory.js.map +0 -1
  44. package/dist/prismaTransaction.d.ts +0 -17
  45. package/dist/prismaTransaction.js.map +0 -1
package/README.md CHANGED
@@ -2,26 +2,143 @@
2
2
 
3
3
  This package provides reusable helpers for Prisma query builder.
4
4
 
5
- # Usage
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @lokalise/prisma-utils
9
+ ```
10
+
11
+ ## Features
12
+
13
+ ### Prisma Client Factory
14
+
15
+ Factory function to create a Prisma client instance with default configuration and optional Prometheus metrics integration.
16
+
17
+ **Without metrics:**
18
+
19
+ ```typescript
20
+ import { prismaClientFactory } from '@lokalise/prisma-utils'
21
+ import { PrismaClient } from '@prisma/client'
22
+
23
+ const prisma = prismaClientFactory(PrismaClient, {
24
+ // Your Prisma client options
25
+ })
26
+ ```
27
+
28
+ **With Prometheus metrics:**
29
+
30
+ ```typescript
31
+ import { prismaClientFactory } from '@lokalise/prisma-utils'
32
+ import { PrismaClient } from '@prisma/client'
33
+ import * as promClient from 'prom-client'
34
+
35
+ const prisma = prismaClientFactory(
36
+ PrismaClient,
37
+ {
38
+ // Your Prisma client options
39
+ },
40
+ { promClient }
41
+ )
42
+ ```
43
+
44
+ The factory automatically:
45
+ - Sets default transaction isolation level to `ReadCommitted`
46
+ - Extends the client with Prometheus metrics when `promClient` is provided
47
+
48
+ #### Prisma Metrics Collection
49
+
50
+ When you provide `promClient` to the factory, the following metrics are automatically collected:
51
+
52
+ - **`prisma_queries_total`**: Total number of Prisma queries executed
53
+ - Labels: `model`, `operation`, `status` (success/error)
54
+ - **`prisma_query_duration_seconds`**: Duration of Prisma queries in seconds
55
+ - Labels: `model`, `operation`
56
+ - Buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5]
57
+ - **`prisma_errors_total`**: Total number of Prisma query errors
58
+ - Labels: `model`, `operation`, `error_code`
59
+
60
+ These metrics are automatically exposed through the Prometheus registry and can be scraped by your monitoring system.
61
+
62
+ ### Prisma Transactions
63
+
64
+ Helper for executing Prisma transactions with intelligent automatic retry mechanism, optimized for distributed databases like CockroachDB.
65
+
66
+ #### Basic Usage
67
+
68
+ **With multiple operations:**
6
69
 
7
70
  ```typescript
8
71
  import { prismaTransaction } from '@lokalise/prisma-utils'
72
+ import type { Either } from '@lokalise/node-core'
9
73
 
10
- const result: Either<unknown, [Item, Segment]> = await prismaTransaction(prisma, [
11
- prisma.item.create({ data: TEST_ITEM_1 }),
12
- prisma.segment.create({ data: TEST_SEGMENT_1 }),
13
- ])
74
+ const result: Either<unknown, [Item, Segment]> = await prismaTransaction(
75
+ prisma,
76
+ { dbDriver: 'CockroachDb' },
77
+ [
78
+ prisma.item.create({ data: { value: 'item-1' } }),
79
+ prisma.segment.create({ data: { name: 'segment-1' } }),
80
+ ]
81
+ )
14
82
  ```
15
83
 
16
- This implementation will retry the transaction on P2034 error, which satisfies Prisma recommendations for distributed databases such as CockroachDB.
84
+ **With transaction callback:**
85
+
86
+ ```typescript
87
+ const result: Either<unknown, User> = await prismaTransaction(
88
+ prisma,
89
+ { dbDriver: 'CockroachDb' },
90
+ async (tx) => {
91
+ const user = await tx.user.create({ data: { name: 'John' } })
92
+ await tx.profile.create({ data: { userId: user.id, bio: 'Developer' } })
93
+ return user
94
+ }
95
+ )
96
+ ```
17
97
 
18
- ### Prisma metrics plugin
98
+ #### Automatic Retry Mechanism
19
99
 
20
- Plugin to collect and send metrics to prometheus. Prisma metrics will be added to our app metrics.
100
+ The transaction helper automatically retries on the following error conditions:
21
101
 
22
- Add the plugin to your Fastify instance by registering it with the following options:
102
+ **Prisma Error Codes:**
103
+ - **P2034**: Write conflict / Serialization failure (common in distributed databases)
104
+ - **P2028**: Transaction API error
105
+ - **P1017**: Server closed the connection
106
+
107
+ **CockroachDB-specific:**
108
+ - Automatically detects and retries CockroachDB retry transaction errors.
109
+
110
+ #### Retry Strategy
111
+
112
+ 1. **Exponential Backoff**: Delay between retries increases exponentially
113
+ - Formula: `2^(retry-1) × baseRetryDelayMs`
114
+ - Example: 100ms → 200ms → 400ms → 800ms...
115
+
116
+ 2. **Smart Timeout Adjustment**: If transaction times out (P2028 with "transaction is closed"), the timeout is
117
+ automatically doubled on retry (up to `maxTimeout`)
118
+
119
+ 3. **Configurable Options**:
120
+
121
+ ```typescript
122
+ const result = await prismaTransaction(
123
+ prisma,
124
+ {
125
+ dbDriver: 'CockroachDb', // Enable CockroachDB-specific retries
126
+ retriesAllowed: 2, // Default: 2 (total 3 attempts)
127
+ baseRetryDelayMs: 100, // Default: 100ms
128
+ maxRetryDelayMs: 30000, // Default: 30s (max delay between retries)
129
+ timeout: 5000, // Default: 5s (transaction timeout)
130
+ maxTimeout: 30000, // Default: 30s (max transaction timeout)
131
+ },
132
+ [
133
+ // Your transaction operations
134
+ ]
135
+ )
136
+ ```
23
137
 
24
- - `isEnabled`;
25
- - `collectionOptions` (by default we collect metrics `every 5 seconds`) to override default collector behaviour
138
+ #### Why This Matters
26
139
 
27
- Once the plugin has been added to your Fastify instance and loaded, we will start collection prisma metrics.
140
+ Distributed databases like CockroachDB use optimistic concurrency control, which can result in serialization errors
141
+ when multiple transactions compete for the same resources. This helper abstracts away the complexity of handling these
142
+ errors, providing a robust and efficient way to ensure your transactions succeed even under high contention.
143
+ By automatically retrying failed transactions with an intelligent backoff strategy, you can significantly improve the
144
+ reliability and performance of your application when using distributed databases.
@@ -1,4 +1,4 @@
1
- import type { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
1
+ import type { PrismaClientKnownRequestError } from '@prisma/client/runtime/client';
2
2
  /**
3
3
  * Check if the error is a CockroachDB transaction retry error
4
4
  *
@@ -1,4 +1,4 @@
1
- import type { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
1
+ import type { PrismaClientKnownRequestError } from '@prisma/client/runtime/client';
2
2
  /**
3
3
  * What is checked?
4
4
  * 1. error is defined and not null
@@ -0,0 +1,3 @@
1
+ import type { PrismaClient } from 'db-client/client.ts';
2
+ import type Prometheus from 'prom-client';
3
+ export declare const extendPrismaClientWithMetrics: <Client extends PrismaClient>(prisma: Client, promClient: typeof Prometheus) => Client;
@@ -0,0 +1,90 @@
1
+ export const extendPrismaClientWithMetrics = (prisma, promClient) => createExtendedClient(prisma, registerMetricsIfNeeded(promClient));
2
+ const METRICS_PREFIX = 'prisma';
3
+ const createExtendedClient = (prisma, metrics) => {
4
+ return prisma.$extends({
5
+ name: 'metrics-collector',
6
+ query: {
7
+ $allModels: {
8
+ async $allOperations({ model, operation, args, query }) {
9
+ const startTime = Date.now();
10
+ const resolvedModel = model ?? 'unknown';
11
+ let result = { result: undefined };
12
+ try {
13
+ const response = await query(args);
14
+ result = { result: response };
15
+ }
16
+ catch (error) {
17
+ result = { error };
18
+ }
19
+ finally {
20
+ const duration = (Date.now() - startTime) / 1000;
21
+ // Always record metrics (success or error)
22
+ metrics.queriesTotal.inc({
23
+ model: resolvedModel,
24
+ operation,
25
+ status: result.error ? 'error' : 'success',
26
+ });
27
+ metrics.queryDuration.observe({ model: resolvedModel, operation }, duration);
28
+ if (result.error) {
29
+ const errorCode = result.error?.code || 'unknown';
30
+ metrics.errorsTotal.inc({
31
+ model: resolvedModel,
32
+ operation,
33
+ error_code: errorCode,
34
+ });
35
+ }
36
+ }
37
+ if (result.error)
38
+ throw result.error;
39
+ return result.result;
40
+ },
41
+ },
42
+ },
43
+ });
44
+ };
45
+ /**
46
+ * Register Prometheus metrics if they don't already exist
47
+ */
48
+ const registerMetricsIfNeeded = (promClient) => {
49
+ const existingMetrics = getExistingMetrics(promClient);
50
+ if (existingMetrics)
51
+ return existingMetrics;
52
+ const queriesTotal = new promClient.Counter({
53
+ name: `${METRICS_PREFIX}_queries_total`,
54
+ help: 'Total number of Prisma queries executed',
55
+ labelNames: ['model', 'operation', 'status'],
56
+ registers: [promClient.register],
57
+ });
58
+ const queryDuration = new promClient.Histogram({
59
+ name: `${METRICS_PREFIX}_query_duration_seconds`,
60
+ help: 'Duration of Prisma queries in seconds',
61
+ labelNames: ['model', 'operation'],
62
+ buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5],
63
+ registers: [promClient.register],
64
+ });
65
+ const errorsTotal = new promClient.Counter({
66
+ name: `${METRICS_PREFIX}_errors_total`,
67
+ help: 'Total number of Prisma query errors',
68
+ labelNames: ['model', 'operation', 'error_code'],
69
+ registers: [promClient.register],
70
+ });
71
+ return { queriesTotal, queryDuration, errorsTotal };
72
+ };
73
+ /**
74
+ * Check if metrics already exist in the registry
75
+ */
76
+ const getExistingMetrics = (promClient) => {
77
+ try {
78
+ const queriesTotal = promClient.register.getSingleMetric(`${METRICS_PREFIX}_queries_total`);
79
+ const queryDuration = promClient.register.getSingleMetric(`${METRICS_PREFIX}_query_duration_seconds`);
80
+ const errorsTotal = promClient.register.getSingleMetric(`${METRICS_PREFIX}_errors_total`);
81
+ if (queriesTotal && queryDuration && errorsTotal) {
82
+ return { queriesTotal, queryDuration, errorsTotal };
83
+ }
84
+ }
85
+ catch {
86
+ // If any error occurs (e.g. metrics not found), return null to create new metrics
87
+ }
88
+ return null;
89
+ };
90
+ //# sourceMappingURL=extendPrismaClientWithMetrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extendPrismaClientWithMetrics.js","sourceRoot":"","sources":["../../src/factory/extendPrismaClientWithMetrics.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,MAAc,EACd,UAA6B,EACrB,EAAE,CAAC,oBAAoB,CAAC,MAAM,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAW,CAAA;AAQxF,MAAM,cAAc,GAAG,QAAQ,CAAA;AAE/B,MAAM,oBAAoB,GAAG,CAAC,MAAoB,EAAE,OAAqB,EAAE,EAAE;IAC3E,OAAO,MAAM,CAAC,QAAQ,CAAC;QACrB,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE;YACL,UAAU,EAAE;gBACV,KAAK,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE;oBACpD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;oBAC5B,MAAM,aAAa,GAAG,KAAK,IAAI,SAAS,CAAA;oBACxC,IAAI,MAAM,GAA6B,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;oBAE5D,IAAI,CAAC;wBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAA;wBAClC,MAAM,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;oBAC/B,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,MAAM,GAAG,EAAE,KAAK,EAAE,CAAA;oBACpB,CAAC;4BAAS,CAAC;wBACT,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAA;wBAEhD,2CAA2C;wBAC3C,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC;4BACvB,KAAK,EAAE,aAAa;4BACpB,SAAS;4BACT,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;yBAC3C,CAAC,CAAA;wBAEF,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAA;wBAE5E,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;4BACjB,MAAM,SAAS,GAAI,MAAM,CAAC,KAAmC,EAAE,IAAI,IAAI,SAAS,CAAA;4BAChF,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC;gCACtB,KAAK,EAAE,aAAa;gCACpB,SAAS;gCACT,UAAU,EAAE,SAAS;6BACtB,CAAC,CAAA;wBACJ,CAAC;oBACH,CAAC;oBAED,IAAI,MAAM,CAAC,KAAK;wBAAE,MAAM,MAAM,CAAC,KAAK,CAAA;oBACpC,OAAO,MAAM,CAAC,MAAM,CAAA;gBACtB,CAAC;aACF;SACF;KACF,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,uBAAuB,GAAG,CAAC,UAA6B,EAAgB,EAAE;IAC9E,MAAM,eAAe,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAA;IACtD,IAAI,eAAe;QAAE,OAAO,eAAe,CAAA;IAE3C,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC;QAC1C,IAAI,EAAE,GAAG,cAAc,gBAAgB;QACvC,IAAI,EAAE,yCAAyC;QAC/C,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC;QAC5C,SAAS,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;KACjC,CAAC,CAAA;IAEF,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC;QAC7C,IAAI,EAAE,GAAG,cAAc,yBAAyB;QAChD,IAAI,EAAE,uCAAuC;QAC7C,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;QAClC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,SAAS,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;KACjC,CAAC,CAAA;IAEF,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC;QACzC,IAAI,EAAE,GAAG,cAAc,eAAe;QACtC,IAAI,EAAE,qCAAqC;QAC3C,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,CAAC;QAChD,SAAS,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;KACjC,CAAC,CAAA;IAEF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AACrD,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,kBAAkB,GAAG,CAAC,UAA6B,EAAuB,EAAE;IAChF,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,cAAc,gBAAgB,CAAC,CAAA;QAC3F,MAAM,aAAa,GAAG,UAAU,CAAC,QAAQ,CAAC,eAAe,CACvD,GAAG,cAAc,yBAAyB,CAC3C,CAAA;QACD,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,cAAc,eAAe,CAAC,CAAA;QAEzF,IAAI,YAAY,IAAI,aAAa,IAAI,WAAW,EAAE,CAAC;YACjD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAkB,CAAA;QACrE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kFAAkF;IACpF,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ export { prismaClientFactory } from './prismaClientFactory.ts';
@@ -0,0 +1,2 @@
1
+ export { prismaClientFactory } from "./prismaClientFactory.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,20 @@
1
+ import type * as RuntimePrisma from '@prisma/client/runtime/client';
2
+ import type { PrismaClient } from 'db-client/client.ts';
3
+ import type { PrismaClientConstructor } from 'db-client/internal/class.ts';
4
+ import type Prometheus from 'prom-client';
5
+ export type prismaClientFactoryOptions = {
6
+ promClient?: typeof Prometheus;
7
+ };
8
+ /**
9
+ * Factory function to create a Prisma client instance with default configuration
10
+ * and optional Prometheus metrics integration.
11
+ *
12
+ * @template Client - The Prisma client type to instantiate
13
+ * @param builder - The Prisma client constructor
14
+ * @param options - Prisma client initialization options
15
+ * @param factoryOptions - Optional factory configuration
16
+ * @param factoryOptions.promClient - Prometheus client instance to enable metrics collection
17
+ * @returns A configured Prisma client instance, optionally extended with metrics
18
+ *
19
+ */
20
+ export declare const prismaClientFactory: <Client extends PrismaClient>(builder: PrismaClientConstructor, options: RuntimePrisma.PrismaClientOptions, factoryOptions?: prismaClientFactoryOptions) => Client;
@@ -0,0 +1,26 @@
1
+ import { extendPrismaClientWithMetrics } from "./extendPrismaClientWithMetrics.js";
2
+ /**
3
+ * Factory function to create a Prisma client instance with default configuration
4
+ * and optional Prometheus metrics integration.
5
+ *
6
+ * @template Client - The Prisma client type to instantiate
7
+ * @param builder - The Prisma client constructor
8
+ * @param options - Prisma client initialization options
9
+ * @param factoryOptions - Optional factory configuration
10
+ * @param factoryOptions.promClient - Prometheus client instance to enable metrics collection
11
+ * @returns A configured Prisma client instance, optionally extended with metrics
12
+ *
13
+ */
14
+ export const prismaClientFactory = (builder, options, factoryOptions) => {
15
+ options.transactionOptions = {
16
+ isolationLevel: 'ReadCommitted',
17
+ ...options.transactionOptions,
18
+ };
19
+ // @ts-expect-error
20
+ let prismaClient = new builder(options);
21
+ if (factoryOptions?.promClient) {
22
+ prismaClient = extendPrismaClientWithMetrics(prismaClient, factoryOptions.promClient);
23
+ }
24
+ return prismaClient;
25
+ };
26
+ //# sourceMappingURL=prismaClientFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prismaClientFactory.js","sourceRoot":"","sources":["../../src/factory/prismaClientFactory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAA;AAMlF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,OAAgC,EAChC,OAA0C,EAC1C,cAA2C,EACnC,EAAE;IACV,OAAO,CAAC,kBAAkB,GAAG;QAC3B,cAAc,EAAE,eAAe;QAC/B,GAAG,OAAO,CAAC,kBAAkB;KAC9B,CAAA;IAED,mBAAmB;IACnB,IAAI,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACvC,IAAI,cAAc,EAAE,UAAU,EAAE,CAAC;QAC/B,YAAY,GAAG,6BAA6B,CAAC,YAAY,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACvF,CAAC;IAED,OAAO,YAAsB,CAAA;AAC/B,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from './errors/index.ts';
2
- export { type PrismaMetricsPluginOptions, prismaMetricsPlugin, } from './plugins/prismaMetricsPlugin.ts';
3
- export { prismaClientFactory } from './prismaClientFactory.ts';
4
- export { prismaTransaction } from './prismaTransaction.ts';
2
+ export * from './factory/index.ts';
3
+ export * from './transaction/index.ts';
5
4
  export type * from './types.ts';
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from "./errors/index.js";
2
- export { prismaMetricsPlugin, } from "./plugins/prismaMetricsPlugin.js";
3
- export { prismaClientFactory } from "./prismaClientFactory.js";
4
- export { prismaTransaction } from "./prismaTransaction.js";
2
+ export * from "./factory/index.js";
3
+ export * from "./transaction/index.js";
5
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAEL,mBAAmB,GACpB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,wBAAwB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { prismaTransaction } from './prismaTransaction.ts';
2
+ export type * from './types.ts';
@@ -0,0 +1,2 @@
1
+ export { prismaTransaction } from "./prismaTransaction.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transaction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,17 @@
1
+ import type { Either } from '@lokalise/node-core';
2
+ import type * as RuntimePrisma from '@prisma/client/runtime/client';
3
+ import type { PrismaClient } from 'db-client/client.ts';
4
+ import type { PrismaTransactionFn, PrismaTransactionOptions } from './types.ts';
5
+ /**
6
+ * Perform a Prisma DB transaction with automatic retries if needed.
7
+ *
8
+ * @template T | T extends Prisma.PrismaPromise<unknown>[]
9
+ * @param {PrismaClient} prisma
10
+ * @param {PrismaTransactionFn<T> | RuntimePrisma.PrismaPromise<unknown>[]} arg operation to perform into the transaction
11
+ * @param {PrismaTransactionOptions} options transaction configuration
12
+ * @return {Promise<PrismaTransactionReturnType<T>>}
13
+ */
14
+ export declare const prismaTransaction: {
15
+ <T, P extends PrismaClient>(prisma: P, options: PrismaTransactionOptions, fn: PrismaTransactionFn<T, P>): Promise<Either<unknown, T>>;
16
+ <T extends RuntimePrisma.PrismaPromise<unknown>[], P extends PrismaClient>(prisma: P, options: PrismaTransactionOptions, args: [...T]): Promise<Either<unknown, RuntimePrisma.Types.Utils.UnwrapTuple<T>>>;
17
+ };
@@ -1,10 +1,9 @@
1
1
  import { setTimeout } from 'node:timers/promises';
2
2
  import { deepClone } from '@lokalise/node-core';
3
- import { isCockroachDBRetryTransaction } from "./errors/cockroachdbError.js";
4
- import { isPrismaClientKnownRequestError, isPrismaTransactionClosedError, PRISMA_SERIALIZATION_ERROR, PRISMA_SERVER_CLOSED_CONNECTION_ERROR, PRISMA_TRANSACTION_ERROR, } from "./errors/prismaError.js";
3
+ import { isCockroachDBRetryTransaction } from "../errors/cockroachdbError.js";
4
+ import { isPrismaClientKnownRequestError, isPrismaTransactionClosedError, PRISMA_SERIALIZATION_ERROR, PRISMA_SERVER_CLOSED_CONNECTION_ERROR, PRISMA_TRANSACTION_ERROR, } from "../errors/index.js";
5
5
  const DEFAULT_OPTIONS = {
6
6
  retriesAllowed: 2, // first try + 2 retries = 3 tries
7
- dbDriver: 'CockroachDb',
8
7
  baseRetryDelayMs: 100,
9
8
  maxRetryDelayMs: 30000, // 30s
10
9
  timeout: 5000, // 5s
@@ -15,11 +14,11 @@ const DEFAULT_OPTIONS = {
15
14
  *
16
15
  * @template T | T extends Prisma.PrismaPromise<unknown>[]
17
16
  * @param {PrismaClient} prisma
18
- * @param {PrismaTransactionFn<T> | Prisma.PrismaPromise<unknown>[]} arg operation to perform into the transaction
19
- * @param {PrismaTransactionOptions | PrismaTransactionBasicOptions} options transaction configuration
17
+ * @param {PrismaTransactionFn<T> | RuntimePrisma.PrismaPromise<unknown>[]} arg operation to perform into the transaction
18
+ * @param {PrismaTransactionOptions} options transaction configuration
20
19
  * @return {Promise<PrismaTransactionReturnType<T>>}
21
20
  */
22
- export const prismaTransaction = (async (prisma, arg, options) => {
21
+ export const prismaTransaction = (async (prisma, options, arg) => {
23
22
  let optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };
24
23
  let result;
25
24
  let retries = 0;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prismaTransaction.js","sourceRoot":"","sources":["../../src/transaction/prismaTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAG/C,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAA;AAC7E,OAAO,EACL,+BAA+B,EAC/B,8BAA8B,EAC9B,0BAA0B,EAC1B,qCAAqC,EACrC,wBAAwB,GACzB,MAAM,oBAAoB,CAAA;AAQ3B,MAAM,eAAe,GAAG;IACtB,cAAc,EAAE,CAAC,EAAE,kCAAkC;IACrD,gBAAgB,EAAE,GAAG;IACrB,eAAe,EAAE,KAAK,EAAE,MAAM;IAC9B,OAAO,EAAE,IAAI,EAAE,KAAK;IACpB,UAAU,EAAE,KAAK,EAAE,MAAM;CACkB,CAAA;AAE7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAK,EACrC,MAAS,EACT,OAAiC,EACjC,GAAuE,EAC9B,EAAE;IAC3C,IAAI,mBAAmB,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAA;IAC5D,IAAI,MAAkD,CAAA;IAEtD,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,GAAG,CAAC;QACF,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,MAAM,UAAU,CACd,mBAAmB,CACjB,OAAO,EACP,mBAAmB,CAAC,gBAAgB,EACpC,mBAAmB,CAAC,eAAe,CACpC,CACF,CAAA;QACH,CAAC;QAED,MAAM,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,mBAAmB,CAAC,CAAA;QACtE,IAAI,MAAM,CAAC,MAAM;YAAE,MAAK;QAExB,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;QACzE,IAAI,CAAC,YAAY;YAAE,MAAK;QAExB,IAAI,YAAY,KAAK,kBAAkB,EAAE,CAAC;YACxC,mBAAmB,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAA;YACpD,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CACpC,mBAAmB,CAAC,OAAO,GAAG,CAAC,EAC/B,mBAAmB,CAAC,UAAU,CAC/B,CAAA;QACH,CAAC;QAED,OAAO,EAAE,CAAA;IACX,CAAC,QAAQ,OAAO,IAAI,mBAAmB,CAAC,cAAc,EAAC;IAEvD,OAAO,MAAM,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,yBAAyB,CAAC,EAAE,CAAA;AAClE,CAAC,CAWA,CAAA;AAED,MAAM,qBAAqB,GAAG,KAAK,EACjC,MAAS,EACT,GAAuE,EACvE,OAAkC,EACO,EAAE;IAC3C,IAAI,CAAC;QACH,OAAO;YACL,mBAAmB;YACnB,MAAM,EAAE,MAAM,MAAM,CAAC,YAAY,CAAI,GAAG,EAAE,OAAO,CAAC;SACnD,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,CAAA;IAClB,CAAC;AACH,CAAC,CAAA;AAED,MAAM,mBAAmB,GAAG,CAC1B,OAAe,EACf,gBAAwB,EACxB,UAAkB,EACV,EAAE;IACV,wDAAwD;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,gBAAgB,CAAA;IAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;AACvC,CAAC,CAAA;AAED,MAAM,kBAAkB,GAAG;IACzB,0BAA0B;IAC1B,qCAAqC;IACrC,wBAAwB;CACzB,CAAA;AAGD,MAAM,cAAc,GAAG,CACrB,MAAsC,EACtC,QAAkB,EACI,EAAE;IACxB,IAAI,+BAA+B,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;QAC1B,wEAAwE;QACxE,8GAA8G;QAC9G,IAAI,8BAA8B,CAAC,KAAK,CAAC;YAAE,OAAO,kBAAkB,CAAA;QACpE,2DAA2D;QAC3D,IAAI,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QACxD,8DAA8D;QAC9D,IAAI,QAAQ,KAAK,aAAa,IAAI,6BAA6B,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;IACrF,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type { Either } from '@lokalise/node-core';
2
+ import type * as RuntimePrisma from '@prisma/client/runtime/client';
3
+ import type { DbDriver } from '../types.ts';
4
+ type InternalTransactionOptions = RuntimePrisma.PrismaClientOptions['transactionOptions'];
5
+ export type PrismaTransactionOptions = {
6
+ dbDriver: DbDriver;
7
+ retriesAllowed?: number;
8
+ baseRetryDelayMs?: number;
9
+ maxRetryDelayMs?: number;
10
+ maxTimeout?: number;
11
+ } & InternalTransactionOptions;
12
+ export type PrismaTransactionClient<P> = Omit<P, RuntimePrisma.ITXClientDenyList>;
13
+ export type PrismaTransactionFn<T, P> = (prisma: PrismaTransactionClient<P>) => Promise<T>;
14
+ export type PrismaTransactionReturnType<T> = Either<unknown, T | RuntimePrisma.Types.Utils.UnwrapTuple<RuntimePrisma.PrismaPromise<unknown>[]>>;
15
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transaction/types.ts"],"names":[],"mappings":""}
package/dist/types.d.ts CHANGED
@@ -1,44 +1,7 @@
1
- import type { Either } from '@lokalise/node-core';
2
- import type { Prisma } from '@prisma/client';
3
- import type * as runtime from '@prisma/client/runtime/library';
4
- import type { CockroachDbIsolationLevel } from './isolation_level/isolationLevel.ts';
5
1
  type ObjectValues<T> = T[keyof T];
6
2
  export declare const DbDriverEnum: {
7
- readonly COCKROACHDB: "CockroachDb";
3
+ readonly COCKROACH_DB: "CockroachDb";
4
+ readonly POSTGRES: "Postgres";
8
5
  };
9
6
  export type DbDriver = ObjectValues<typeof DbDriverEnum>;
10
- export type PrismaTransactionOptions = {
11
- dbDriver?: DbDriver;
12
- retriesAllowed?: number;
13
- baseRetryDelayMs?: number;
14
- maxRetryDelayMs?: number;
15
- maxTimeout?: number;
16
- maxWait?: number;
17
- timeout?: number;
18
- isolationLevel?: CockroachDbIsolationLevel;
19
- };
20
- export type PrismaTransactionBasicOptions = Omit<PrismaTransactionOptions, 'maxWait' | 'timeout' | 'maxTimeout'>;
21
- export type PrismaTransactionClient<P> = Omit<P, runtime.ITXClientDenyList>;
22
- export type PrismaTransactionFn<T, P> = (prisma: PrismaTransactionClient<P>) => Promise<T>;
23
- export type PrismaTransactionReturnType<T> = Either<unknown, T | runtime.Types.Utils.UnwrapTuple<Prisma.PrismaPromise<unknown>[]>>;
24
- /**
25
- * If we try to use `Omit<Prisma.PrismaClientOptions['transactionOptions'], 'isolationLevel'>` to override isolationLevel
26
- * we start to get lint errors about maxWait and timeout not being part of the transactionOptions type.
27
- *
28
- * for that reason, and as this is a temporal solution in the meantime Prisma includes ReadCommitted as a valid isolation
29
- * level for CockroachDB, we are using this type to override the transactionOptions which is basically a copy of
30
- * Prisma.PrismaClientOptions['transactionOptions']
31
- */
32
- type PrismaClientTransactionOptions = {
33
- isolationLevel?: CockroachDbIsolationLevel;
34
- maxWait?: number;
35
- timeout?: number;
36
- };
37
- /**
38
- * this is a temporal solution in the meantime Prisma includes ReadCommitted as a valid isolation level for CockroachDB
39
- */
40
- export type PrismaClientFactoryOptions = Omit<Prisma.PrismaClientOptions, 'transactionOptions'> & {
41
- dbDriver?: DbDriver;
42
- transactionOptions?: PrismaClientTransactionOptions;
43
- };
44
7
  export {};
package/dist/types.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export const DbDriverEnum = {
2
- COCKROACHDB: 'CockroachDb',
2
+ COCKROACH_DB: 'CockroachDb',
3
+ POSTGRES: 'Postgres',
3
4
  };
4
5
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW,EAAE,aAAa;CAClB,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,YAAY,EAAE,aAAa;IAC3B,QAAQ,EAAE,UAAU;CACZ,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokalise/prisma-utils",
3
- "version": "5.0.2",
3
+ "version": "6.0.1",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "files": [
@@ -23,39 +23,34 @@
23
23
  "clean": "rimraf dist",
24
24
  "lint": "biome check . && tsc",
25
25
  "lint:fix": "biome check --write",
26
- "docker:start:ci": "docker compose up -d cockroachdb",
27
- "db:migration:dev": "prisma migrate dev",
26
+ "db:migration:dev": "prisma migrate dev --config=./prisma/prisma.config",
28
27
  "db:update-client": "prisma generate",
29
- "db:wait": "while ! echo \"SELECT 1;\" | prisma db execute --stdin --schema prisma/schema.prisma; do sleep 1; done",
30
28
  "test": "vitest run",
31
- "test:migrate": "cross-env NODE_ENV=test prisma migrate reset --force",
32
- "pretest:ci": "npm run docker:start:ci && npm run db:wait && npm run test:migrate",
29
+ "test:migrate": "cross-env NODE_ENV=test prisma migrate reset --config=./prisma/prisma.config --force",
30
+ "pretest:ci": "docker compose up -d --wait && npm run test:migrate",
33
31
  "test:ci": "npm run test",
34
- "test:ci:teardown": "docker compose down",
32
+ "posttest:ci": "docker compose down",
35
33
  "prepublishOnly": "npm run build",
36
34
  "package-version": "echo $npm_package_version",
37
35
  "postversion": "biome check --write package.json"
38
36
  },
39
- "dependencies": {
40
- "@lokalise/node-core": "^14.4.2"
41
- },
42
37
  "peerDependencies": {
43
- "@prisma/client": ">=5.0.0 <7.0.0",
44
- "prisma": ">=5.0.0 <7.0.0"
38
+ "@lokalise/node-core": ">=14.7.4",
39
+ "@prisma/client": "^7.0.0",
40
+ "prisma": "^7.0.0",
41
+ "prom-client": ">=15.0.0"
45
42
  },
46
43
  "devDependencies": {
47
44
  "@biomejs/biome": "^2.3.7",
48
- "@lokalise/backend-http-client": "^9.0.0",
49
45
  "@lokalise/biome-config": "^3.1.0",
50
- "@lokalise/fastify-extras": "30.6.0",
51
46
  "@lokalise/tsconfig": "^3.1.0",
52
- "@prisma/client": "~6.19.0",
47
+ "@prisma/adapter-pg": "^7.4.0",
48
+ "@prisma/client": "^7.4.0",
53
49
  "@vitest/coverage-v8": "^4.0.15",
54
50
  "cross-env": "^10.0.0",
55
- "prisma": "~6.19.0",
51
+ "prisma": "^7.4.0",
56
52
  "rimraf": "^6.0.1",
57
53
  "typescript": "5.9.3",
58
- "vitest": "^4.0.15",
59
- "zod": "^4.3.6"
54
+ "vitest": "^4.0.15"
60
55
  }
61
56
  }
@@ -1,3 +0,0 @@
1
- type IsolationLevel = 'Serializable' | 'ReadCommitted' | 'ReadUncommitted' | 'RepeatableRead' | 'Snapshot';
2
- export type CockroachDbIsolationLevel = Extract<IsolationLevel, 'ReadCommitted' | 'Serializable'>;
3
- export {};
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=isolationLevel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"isolationLevel.js","sourceRoot":"","sources":["../../src/isolation_level/isolationLevel.ts"],"names":[],"mappings":""}
@@ -1,12 +0,0 @@
1
- export type CollectionScheduler = {
2
- start: () => void;
3
- stop: () => void;
4
- };
5
- export declare class PromiseBasedCollectionScheduler implements CollectionScheduler {
6
- private active;
7
- private readonly collectionIntervalInMs;
8
- private readonly collect;
9
- constructor(collectionIntervalInMs: number, collect: () => Promise<void>);
10
- start(): Promise<void>;
11
- stop(): void;
12
- }
@@ -1,20 +0,0 @@
1
- import { setTimeout } from 'node:timers/promises';
2
- export class PromiseBasedCollectionScheduler {
3
- active = true;
4
- collectionIntervalInMs;
5
- collect;
6
- constructor(collectionIntervalInMs, collect) {
7
- this.collectionIntervalInMs = collectionIntervalInMs;
8
- this.collect = collect;
9
- }
10
- async start() {
11
- while (this.active) {
12
- await setTimeout(this.collectionIntervalInMs);
13
- await this.collect();
14
- }
15
- }
16
- stop() {
17
- this.active = false;
18
- }
19
- }
20
- //# sourceMappingURL=CollectionScheduler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CollectionScheduler.js","sourceRoot":"","sources":["../../src/plugins/CollectionScheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAOjD,MAAM,OAAO,+BAA+B;IAClC,MAAM,GAAG,IAAI,CAAA;IACJ,sBAAsB,CAAQ;IAC9B,OAAO,CAAqB;IAE7C,YAAY,sBAA8B,EAAE,OAA4B;QACtE,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAA;QACpD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,UAAU,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;YAC7C,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;QACtB,CAAC;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACrB,CAAC;CACF"}
@@ -1,36 +0,0 @@
1
- import type { PrismaClient } from '@prisma/client';
2
- import type { FastifyBaseLogger } from 'fastify';
3
- import * as prometheus from 'prom-client';
4
- export type PrometheusMetricsDefinitions = {
5
- counters: Record<string, prometheus.Counter<'prisma' | 'connection-pool'>>;
6
- gauges: Record<string, prometheus.Gauge<'prisma' | 'connection-pool'>>;
7
- histograms: Record<string, prometheus.Histogram<'prisma' | 'connection-pool'>>;
8
- keys: string[];
9
- };
10
- export type MetricCollectorOptions = {
11
- metricsPrefix: string;
12
- };
13
- export declare class MetricsCollector {
14
- private readonly prisma;
15
- private readonly options;
16
- private readonly registry;
17
- private readonly logger;
18
- private metrics;
19
- constructor(prisma: PrismaClient, options: MetricCollectorOptions, registry: prometheus.Registry, logger: FastifyBaseLogger);
20
- /**
21
- * Updates metrics for prisma.
22
- * If metric was not registered before it will be registered here.
23
- */
24
- collect(prefix: string): Promise<void>;
25
- private registerNewMetrics;
26
- /**
27
- * Stops the metrics collection and cleans up resources
28
- */
29
- dispose(): Promise<void>;
30
- private registerMetrics;
31
- /**
32
- * If metrics are already registered, we just return them to avoid triggering a Prometheus error.
33
- */
34
- private getRegisteredMetrics;
35
- private getJsonMetrics;
36
- }
@@ -1,188 +0,0 @@
1
- import * as prometheus from 'prom-client';
2
- function registerMetrics(_prefix, jsonMetrics) {
3
- const metrics = {
4
- counters: {},
5
- gauges: {},
6
- histograms: {},
7
- keys: [],
8
- };
9
- for (const metric of jsonMetrics.counters) {
10
- metrics.counters[metric.key] = new prometheus.Counter({
11
- name: metric.key,
12
- help: metric.description,
13
- labelNames: ['prisma', 'connection_pool'],
14
- });
15
- metrics.keys.push(metric.key);
16
- }
17
- for (const metric of jsonMetrics.gauges) {
18
- metrics.gauges[metric.key] = new prometheus.Gauge({
19
- name: metric.key,
20
- help: metric.description,
21
- labelNames: ['prisma', 'connection_pool'],
22
- });
23
- metrics.keys.push(metric.key);
24
- }
25
- for (const metric of jsonMetrics.histograms) {
26
- metrics.histograms[metric.key] = new prometheus.Histogram({
27
- name: metric.key,
28
- help: metric.description,
29
- buckets: metric.value.buckets.filter((bucket) => bucket[1] === 0).map((bucket) => bucket[0]),
30
- labelNames: ['prisma', 'connection_pool'],
31
- });
32
- metrics.keys.push(metric.key);
33
- }
34
- return metrics;
35
- }
36
- function getMetricKeys(_prefix, jsonMetrics) {
37
- const metricKeys = [];
38
- metricKeys.push(...jsonMetrics.counters.map((metric) => metric.key));
39
- metricKeys.push(...jsonMetrics.gauges.map((metric) => metric.key));
40
- metricKeys.push(...jsonMetrics.histograms.map((metric) => metric.key));
41
- return metricKeys;
42
- }
43
- export class MetricsCollector {
44
- prisma;
45
- options;
46
- registry;
47
- logger;
48
- metrics;
49
- constructor(prisma, options, registry, logger) {
50
- this.prisma = prisma;
51
- this.options = options;
52
- this.registry = registry;
53
- this.logger = logger;
54
- this.metrics = {
55
- counters: {},
56
- gauges: {},
57
- histograms: {},
58
- keys: [],
59
- };
60
- this.registerMetrics(this.registry, this.options).then((result) => {
61
- this.metrics = result;
62
- this.logger.debug({}, `Prisma metrics registered ${result.keys}`);
63
- });
64
- }
65
- /**
66
- * Updates metrics for prisma.
67
- * If metric was not registered before it will be registered here.
68
- */
69
- async collect(prefix) {
70
- try {
71
- const nonRegisteredMetrics = {
72
- counters: [],
73
- gauges: [],
74
- histograms: [],
75
- };
76
- const jsonMetrics = await this.getJsonMetrics();
77
- for (const counterMetric of jsonMetrics.counters) {
78
- const existingMetric = this.metrics.counters[counterMetric.key];
79
- /* c8 ignore start */
80
- if (!existingMetric) {
81
- nonRegisteredMetrics.counters.push(counterMetric);
82
- continue;
83
- }
84
- /* c8 ignore stop */
85
- // we need to reset counter since prisma returns already the accumulated counter value
86
- existingMetric.reset();
87
- existingMetric.inc(counterMetric.value);
88
- }
89
- for (const gaugeMetric of jsonMetrics.gauges) {
90
- const existingMetric = this.metrics.gauges[gaugeMetric.key];
91
- /* c8 ignore start */
92
- if (!existingMetric) {
93
- nonRegisteredMetrics.gauges.push(gaugeMetric);
94
- continue;
95
- }
96
- /* c8 ignore stop */
97
- existingMetric.set(gaugeMetric.value);
98
- }
99
- for (const histogramMetric of jsonMetrics.histograms) {
100
- const existingMetric = this.metrics.histograms[histogramMetric.key];
101
- /* c8 ignore start */
102
- if (!existingMetric) {
103
- nonRegisteredMetrics.histograms.push(histogramMetric);
104
- continue;
105
- }
106
- /* c8 ignore stop */
107
- existingMetric.observe(histogramMetric.value.count);
108
- }
109
- this.registerNewMetrics(prefix, nonRegisteredMetrics);
110
- }
111
- catch (err) {
112
- /* c8 ignore start */
113
- this.logger.error(err);
114
- }
115
- /* c8 ignore stop */
116
- }
117
- registerNewMetrics(prefix, nonRegisteredMetrics) {
118
- if (!nonRegisteredMetrics.counters.length &&
119
- !nonRegisteredMetrics.gauges.length &&
120
- !nonRegisteredMetrics.histograms.length) {
121
- return;
122
- }
123
- /* c8 ignore start */
124
- const newMetrics = registerMetrics(prefix, nonRegisteredMetrics);
125
- for (const [key, value] of Object.entries(newMetrics.counters)) {
126
- this.metrics.counters[key] = value;
127
- }
128
- for (const [key, value] of Object.entries(newMetrics.gauges)) {
129
- this.metrics.gauges[key] = value;
130
- }
131
- for (const [key, value] of Object.entries(newMetrics.histograms)) {
132
- this.metrics.histograms[key] = value;
133
- }
134
- this.logger.debug({}, `Prisma metrics registered ${newMetrics.keys}`);
135
- /* c8 ignore stop */
136
- }
137
- /**
138
- * Stops the metrics collection and cleans up resources
139
- */
140
- async dispose() { }
141
- async registerMetrics(registry, { metricsPrefix }) {
142
- const jsonMetrics = await this.getJsonMetrics();
143
- const metricNames = getMetricKeys(metricsPrefix, jsonMetrics);
144
- const existingMetrics = this.getRegisteredMetrics(registry, metricNames);
145
- if (existingMetrics) {
146
- /* c8 ignore start */
147
- return existingMetrics;
148
- }
149
- /* c8 ignore stop */
150
- return registerMetrics(metricsPrefix, jsonMetrics);
151
- }
152
- /**
153
- * If metrics are already registered, we just return them to avoid triggering a Prometheus error.
154
- */
155
- getRegisteredMetrics(registry, metricNames) {
156
- if (!metricNames.length)
157
- return;
158
- /* c8 ignore start */
159
- const retrievedMetrics = registry.getMetricsAsArray();
160
- if (!retrievedMetrics.length)
161
- return;
162
- const returnValue = {
163
- counters: {},
164
- histograms: {},
165
- gauges: {},
166
- };
167
- for (const metric of retrievedMetrics) {
168
- if (!metricNames.includes(metric.name)) {
169
- continue;
170
- }
171
- if (metric.type.toString() === 'counter') {
172
- returnValue.counters[metric.name] = metric;
173
- }
174
- if (metric.type.toString() === 'gauge') {
175
- returnValue.gauges[metric.name] = metric;
176
- }
177
- if (metric.type.toString() === 'histogram') {
178
- returnValue.histograms[metric.name] = metric;
179
- }
180
- }
181
- return returnValue;
182
- /* c8 ignore stop */
183
- }
184
- getJsonMetrics() {
185
- return this.prisma.$metrics.json();
186
- }
187
- }
188
- //# sourceMappingURL=MetricsCollector.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MetricsCollector.js","sourceRoot":"","sources":["../../src/plugins/MetricsCollector.ts"],"names":[],"mappings":"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"}
@@ -1,21 +0,0 @@
1
- import type { FastifyPluginCallback } from 'fastify';
2
- import 'fastify-metrics';
3
- import type { PrismaClient } from '@prisma/client';
4
- import type { MetricCollectorOptions } from './MetricsCollector.ts';
5
- declare module 'fastify' {
6
- interface FastifyInstance {
7
- prismaMetrics: {
8
- collect: () => Promise<void>;
9
- };
10
- }
11
- }
12
- export type PrismaMetricsPluginOptions = {
13
- prisma: PrismaClient;
14
- collectionOptions?: {
15
- type: 'interval';
16
- intervalInMs: number;
17
- } | {
18
- type: 'manual';
19
- };
20
- } & Partial<MetricCollectorOptions>;
21
- export declare const prismaMetricsPlugin: FastifyPluginCallback<PrismaMetricsPluginOptions>;
@@ -1,49 +0,0 @@
1
- import 'fastify-metrics';
2
- import fp from 'fastify-plugin';
3
- import { PromiseBasedCollectionScheduler } from "./CollectionScheduler.js";
4
- import { MetricsCollector } from "./MetricsCollector.js";
5
- function plugin(fastify, pluginOptions, next) {
6
- if (!fastify.metrics) {
7
- return next(new Error('No Prometheus Client found, Prisma metrics plugin requires `fastify-metrics` plugin to be registered'));
8
- }
9
- const options = {
10
- collectionOptions: {
11
- type: 'interval',
12
- intervalInMs: 5000,
13
- },
14
- ...pluginOptions,
15
- metricsPrefix: 'prisma',
16
- };
17
- try {
18
- const collector = new MetricsCollector(options.prisma, options, fastify.metrics.client.register, fastify.log);
19
- const collectFn = async () => await collector.collect(options.metricsPrefix);
20
- let scheduler;
21
- if (options.collectionOptions.type === 'interval') {
22
- scheduler = new PromiseBasedCollectionScheduler(options.collectionOptions.intervalInMs, collectFn);
23
- // Void is set so the scheduler can run indefinitely
24
- void scheduler.start();
25
- }
26
- fastify.addHook('onClose', async () => {
27
- if (scheduler) {
28
- scheduler.stop();
29
- }
30
- await collector.dispose();
31
- });
32
- fastify.decorate('prismaMetrics', {
33
- collect: collectFn,
34
- });
35
- next();
36
- /* c8 ignore start */
37
- }
38
- catch (err) {
39
- return next(err instanceof Error
40
- ? err
41
- : new Error('Unknown error in prisma-metrics-plugin', { cause: err }));
42
- }
43
- /* c8 ignore stop */
44
- }
45
- export const prismaMetricsPlugin = fp(plugin, {
46
- fastify: '5.x',
47
- name: 'prisma-metrics-plugin',
48
- });
49
- //# sourceMappingURL=prismaMetricsPlugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prismaMetricsPlugin.js","sourceRoot":"","sources":["../../src/plugins/prismaMetricsPlugin.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,CAAA;AAExB,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE/B,OAAO,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAA;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAuBxD,SAAS,MAAM,CACb,OAAwB,EACxB,aAAyC,EACzC,IAA2B;IAE3B,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,IAAI,CACT,IAAI,KAAK,CACP,sGAAsG,CACvG,CACF,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG;QACd,iBAAiB,EAAE;YACjB,IAAI,EAAE,UAAU;YAChB,YAAY,EAAE,IAAI;SACnB;QACD,GAAG,aAAa;QAChB,aAAa,EAAE,QAAQ;KACa,CAAA;IAEtC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,gBAAgB,CACpC,OAAO,CAAC,MAAM,EACd,OAAO,EACP,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAC/B,OAAO,CAAC,GAAG,CACZ,CAAA;QACD,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;QAC5E,IAAI,SAA8B,CAAA;QAElC,IAAI,OAAO,CAAC,iBAAiB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAClD,SAAS,GAAG,IAAI,+BAA+B,CAC7C,OAAO,CAAC,iBAAiB,CAAC,YAAY,EACtC,SAAS,CACV,CAAA;YAED,oDAAoD;YACpD,KAAK,SAAS,CAAC,KAAK,EAAE,CAAA;QACxB,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;YACpC,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,IAAI,EAAE,CAAA;YAClB,CAAC;YACD,MAAM,SAAS,CAAC,OAAO,EAAE,CAAA;QAC3B,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE;YAChC,OAAO,EAAE,SAAS;SACnB,CAAC,CAAA;QAEF,IAAI,EAAE,CAAA;QACN,qBAAqB;IACvB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,OAAO,IAAI,CACT,GAAG,YAAY,KAAK;YAClB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,IAAI,KAAK,CAAC,wCAAwC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CACxE,CAAA;IACH,CAAC;IACD,oBAAoB;AACtB,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAC9B,EAAE,CAA6B,MAAM,EAAE;IACrC,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,uBAAuB;CAC9B,CAAC,CAAA"}
@@ -1,5 +0,0 @@
1
- import type { Prisma, PrismaClient } from '@prisma/client';
2
- import type { PrismaClientFactoryOptions } from './types.ts';
3
- type PrismaClientConstructor<P extends PrismaClient> = new (options: Prisma.PrismaClientOptions) => P;
4
- export declare const prismaClientFactory: <P extends PrismaClient>(PrismaClient: PrismaClientConstructor<P>, options?: PrismaClientFactoryOptions) => P;
5
- export {};
@@ -1,11 +0,0 @@
1
- const defaultOptions = {
2
- transactionOptions: { isolationLevel: 'ReadCommitted' },
3
- };
4
- export const prismaClientFactory = (PrismaClient, options = {}) => {
5
- options.transactionOptions = {
6
- ...defaultOptions.transactionOptions,
7
- ...options.transactionOptions,
8
- };
9
- return new PrismaClient(options);
10
- };
11
- //# sourceMappingURL=prismaClientFactory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prismaClientFactory.js","sourceRoot":"","sources":["../src/prismaClientFactory.ts"],"names":[],"mappings":"AAGA,MAAM,cAAc,GAA+B;IACjD,kBAAkB,EAAE,EAAE,cAAc,EAAE,eAAe,EAAE;CACxD,CAAA;AAMD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,YAAwC,EACxC,UAAsC,EAAE,EACrC,EAAE;IACL,OAAO,CAAC,kBAAkB,GAAG;QAC3B,GAAG,cAAc,CAAC,kBAAkB;QACpC,GAAG,OAAO,CAAC,kBAAkB;KAC9B,CAAA;IAED,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,CAAA;AAClC,CAAC,CAAA"}
@@ -1,17 +0,0 @@
1
- import type { Either } from '@lokalise/node-core';
2
- import type { Prisma, PrismaClient } from '@prisma/client';
3
- import type * as runtime from '@prisma/client/runtime/library';
4
- import type { PrismaTransactionBasicOptions, PrismaTransactionFn, PrismaTransactionOptions } from './types.ts';
5
- /**
6
- * Perform a Prisma DB transaction with automatic retries if needed.
7
- *
8
- * @template T | T extends Prisma.PrismaPromise<unknown>[]
9
- * @param {PrismaClient} prisma
10
- * @param {PrismaTransactionFn<T> | Prisma.PrismaPromise<unknown>[]} arg operation to perform into the transaction
11
- * @param {PrismaTransactionOptions | PrismaTransactionBasicOptions} options transaction configuration
12
- * @return {Promise<PrismaTransactionReturnType<T>>}
13
- */
14
- export declare const prismaTransaction: {
15
- <T, P extends PrismaClient>(prisma: P, fn: PrismaTransactionFn<T, P>, options?: PrismaTransactionOptions): Promise<Either<unknown, T>>;
16
- <T extends Prisma.PrismaPromise<unknown>[], P extends PrismaClient>(prisma: P, args: [...T], options?: PrismaTransactionBasicOptions): Promise<Either<unknown, runtime.Types.Utils.UnwrapTuple<T>>>;
17
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"prismaTransaction.js","sourceRoot":"","sources":["../src/prismaTransaction.ts"],"names":[],"mappings":"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"}