@lokalise/tm-sdk 1.0.0

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.
@@ -0,0 +1,4 @@
1
+ export * from './sdk/TranslationMemoryClient';
2
+ export * from './sdk/errors/TranslationMemoryClientError';
3
+ export * from './sdk/types/requests';
4
+ export * from './sdk/types/models';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './sdk/TranslationMemoryClient';
2
+ export * from './sdk/errors/TranslationMemoryClientError';
3
+ export * from './sdk/types/requests';
4
+ export * from './sdk/types/models';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAA;AAC7C,cAAc,2CAA2C,CAAA;AACzD,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA"}
@@ -0,0 +1,26 @@
1
+ import type { MandatoryPaginationParams } from '@lokalise/api-common';
2
+ import type { ErrorReporter } from '@lokalise/node-core';
3
+ import type { RetryConfig } from 'undici-retry';
4
+ import type { BulkTranslationMemoryMatches, TranslationMemoryMatch, TranslationMemoryRecordsResponse, UpsertRecordDto } from './types/models';
5
+ import type { BulkFindMatchesRequest, FindMatchesRequest } from './types/requests';
6
+ export type TranslationMemoryClientConfig = {
7
+ baseUrl: string;
8
+ jwtToken: string;
9
+ retryConfig?: Partial<RetryConfig>;
10
+ errorReporter?: ErrorReporter;
11
+ };
12
+ export declare class TranslationMemoryClient {
13
+ private readonly maxFindMatchesRequestSize;
14
+ private readonly httpClient;
15
+ private readonly retryConfig;
16
+ private readonly headers;
17
+ private readonly errorReporter?;
18
+ constructor(config: TranslationMemoryClientConfig);
19
+ findMatches(groupId: string, request: FindMatchesRequest): Promise<TranslationMemoryMatch[]>;
20
+ bulkFindMatches(groupId: string, request: BulkFindMatchesRequest): Promise<BulkTranslationMemoryMatches[]>;
21
+ bulkFindMatchesIterative(groupId: string, request: BulkFindMatchesRequest): AsyncGenerator<BulkTranslationMemoryMatches[]>;
22
+ getRecords(groupId: string, pagination?: MandatoryPaginationParams): Promise<TranslationMemoryRecordsResponse>;
23
+ upsertRecords(groupId: string, records: UpsertRecordDto[]): Promise<void>;
24
+ private internalBulkFindMatches;
25
+ private handleError;
26
+ }
@@ -0,0 +1,117 @@
1
+ import { buildClient, chunk, InternalError, isResponseStatusError, sendGet, sendPost, sendPut, } from '@lokalise/node-core';
2
+ import { TranslationMemoryClientError } from './errors/TranslationMemoryClientError';
3
+ import { transformToQueryParam } from './utils';
4
+ export class TranslationMemoryClient {
5
+ maxFindMatchesRequestSize = 20; // TODO: TBD
6
+ httpClient;
7
+ retryConfig;
8
+ headers;
9
+ errorReporter;
10
+ constructor(config) {
11
+ this.httpClient = buildClient(config.baseUrl);
12
+ this.headers = {
13
+ 'Content-Type': 'application/json',
14
+ Authorization: `Bearer ${config.jwtToken}`,
15
+ };
16
+ this.retryConfig = {
17
+ retryOnTimeout: false,
18
+ maxAttempts: 5,
19
+ delayBetweenAttemptsInMsecs: 250,
20
+ statusCodesToRetry: [
21
+ 408,
22
+ 423,
23
+ 429,
24
+ 500,
25
+ 503,
26
+ 504, // Gateway timeout,
27
+ ],
28
+ ...config.retryConfig,
29
+ };
30
+ this.errorReporter = config.errorReporter;
31
+ }
32
+ async findMatches(groupId, request) {
33
+ try {
34
+ const response = await sendGet(this.httpClient, `/v1/groups/${groupId}/actions/find-matches`, {
35
+ headers: this.headers,
36
+ retryConfig: this.retryConfig,
37
+ requestLabel: '(tm-sdk) Find matches',
38
+ query: transformToQueryParam(request),
39
+ });
40
+ return response.result.body.data;
41
+ }
42
+ catch (e) {
43
+ throw this.handleError(e);
44
+ }
45
+ }
46
+ async bulkFindMatches(groupId, request) {
47
+ const response = [];
48
+ for (const filters of chunk(request.filters, this.maxFindMatchesRequestSize)) {
49
+ const partialResponse = await this.internalBulkFindMatches(groupId, { filters });
50
+ response.push(...partialResponse);
51
+ }
52
+ return response;
53
+ }
54
+ async *bulkFindMatchesIterative(groupId, request) {
55
+ for (const filters of chunk(request.filters, this.maxFindMatchesRequestSize)) {
56
+ yield await this.internalBulkFindMatches(groupId, { filters });
57
+ }
58
+ }
59
+ async getRecords(groupId, pagination) {
60
+ try {
61
+ const response = await sendGet(this.httpClient, `/v1/groups/${groupId}/records`, {
62
+ headers: this.headers,
63
+ retryConfig: this.retryConfig,
64
+ requestLabel: '(tm-sdk) Get records',
65
+ query: pagination,
66
+ });
67
+ return {
68
+ records: response.result.body.data,
69
+ meta: response.result.body.meta,
70
+ };
71
+ }
72
+ catch (e) {
73
+ throw this.handleError(e);
74
+ }
75
+ }
76
+ async upsertRecords(groupId, records) {
77
+ try {
78
+ await sendPut(this.httpClient, `/v1/groups/${groupId}/records`, records, {
79
+ headers: this.headers,
80
+ retryConfig: this.retryConfig,
81
+ requestLabel: '(tm-sdk) Create or update records',
82
+ });
83
+ }
84
+ catch (e) {
85
+ throw this.handleError(e);
86
+ }
87
+ }
88
+ async internalBulkFindMatches(groupId, request) {
89
+ try {
90
+ const response = await sendPost(this.httpClient, `/v1/groups/${groupId}/actions/bulk-find-matches`, request, {
91
+ headers: this.headers,
92
+ retryConfig: this.retryConfig,
93
+ requestLabel: '(tm-sdk) Bulk find matches',
94
+ });
95
+ return response.result.body.data;
96
+ }
97
+ catch (e) {
98
+ throw this.handleError(e);
99
+ }
100
+ }
101
+ handleError(e) {
102
+ let error;
103
+ if (e instanceof Error) {
104
+ error = isResponseStatusError(e) ? new TranslationMemoryClientError(e) : e;
105
+ }
106
+ else {
107
+ error = new InternalError({
108
+ message: 'Unknown error',
109
+ errorCode: 'UNKNOWN_ERROR',
110
+ details: { error: JSON.stringify(e) },
111
+ });
112
+ }
113
+ this.errorReporter?.report({ error });
114
+ return error;
115
+ }
116
+ }
117
+ //# sourceMappingURL=TranslationMemoryClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TranslationMemoryClient.js","sourceRoot":"","sources":["../../src/sdk/TranslationMemoryClient.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,KAAK,EACL,aAAa,EACb,qBAAqB,EACrB,OAAO,EACP,QAAQ,EACR,OAAO,GACR,MAAM,qBAAqB,CAAA;AAI5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAA;AAapF,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAS/C,MAAM,OAAO,uBAAuB;IACjB,yBAAyB,GAAG,EAAE,CAAA,CAAC,YAAY;IAE3C,UAAU,CAAQ;IAClB,WAAW,CAAa;IACxB,OAAO,CAAyB;IAChC,aAAa,CAAgB;IAE9C,YAAY,MAAqC;QAC/C,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC7C,IAAI,CAAC,OAAO,GAAG;YACb,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,MAAM,CAAC,QAAQ,EAAE;SAC3C,CAAA;QACD,IAAI,CAAC,WAAW,GAAG;YACjB,cAAc,EAAE,KAAK;YACrB,WAAW,EAAE,CAAC;YACd,2BAA2B,EAAE,GAAG;YAChC,kBAAkB,EAAE;gBAClB,GAAG;gBACH,GAAG;gBACH,GAAG;gBACH,GAAG;gBACH,GAAG;gBACH,GAAG,EAAE,mBAAmB;aACzB;YACD,GAAG,MAAM,CAAC,WAAW;SACtB,CAAA;QACD,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAA;IAC3C,CAAC;IAED,KAAK,CAAC,WAAW,CACf,OAAe,EACf,OAA2B;QAE3B,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAC5B,IAAI,CAAC,UAAU,EACf,cAAc,OAAO,uBAAuB,EAC5C;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,YAAY,EAAE,uBAAuB;gBACrC,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC;aACtC,CACF,CAAA;YAED,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;SACjC;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;SAC1B;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,OAAe,EACf,OAA+B;QAE/B,MAAM,QAAQ,GAAmC,EAAE,CAAA;QACnD,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,yBAAyB,CAAC,EAAE;YAC5E,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;YAChF,QAAQ,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAA;SAClC;QAED,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,CAAC,wBAAwB,CAC7B,OAAe,EACf,OAA+B;QAE/B,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,yBAAyB,CAAC,EAAE;YAC5E,MAAM,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;SAC/D;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CACd,OAAe,EACf,UAAsC;QAEtC,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAC5B,IAAI,CAAC,UAAU,EACf,cAAc,OAAO,UAAU,EAC/B;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,YAAY,EAAE,sBAAsB;gBACpC,KAAK,EAAE,UAAU;aAClB,CACF,CAAA;YAED,OAAO;gBACL,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;gBAClC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;aAChC,CAAA;SACF;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;SAC1B;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,OAA0B;QAC7D,IAAI;YACF,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,OAAO,UAAU,EAAE,OAAO,EAAE;gBACvE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,YAAY,EAAE,mCAAmC;aAClD,CAAC,CAAA;SACH;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;SAC1B;IACH,CAAC;IAEO,KAAK,CAAC,uBAAuB,CACnC,OAAe,EACf,OAA+B;QAE/B,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAC7B,IAAI,CAAC,UAAU,EACf,cAAc,OAAO,4BAA4B,EACjD,OAAO,EACP;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,YAAY,EAAE,4BAA4B;aAC3C,CACF,CAAA;YAED,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;SACjC;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;SAC1B;IACH,CAAC;IAEO,WAAW,CAAC,CAAU;QAC5B,IAAI,KAAwB,CAAA;QAC5B,IAAI,CAAC,YAAY,KAAK,EAAE;YACtB,KAAK,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,4BAA4B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;SAC3E;aAAM;YACL,KAAK,GAAG,IAAI,aAAa,CAAC;gBACxB,OAAO,EAAE,eAAe;gBACxB,SAAS,EAAE,eAAe;gBAC1B,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;aACtC,CAAC,CAAA;SACH;QAED,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QACrC,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ import type { ResponseStatusError } from '@lokalise/node-core';
2
+ import { InternalError } from '@lokalise/node-core';
3
+ export declare class TranslationMemoryClientError extends InternalError {
4
+ constructor(error: ResponseStatusError);
5
+ }
@@ -0,0 +1,14 @@
1
+ import { InternalError } from '@lokalise/node-core';
2
+ export class TranslationMemoryClientError extends InternalError {
3
+ constructor(error) {
4
+ super({
5
+ message: `Translation memory service failed with error: ${error.message}`,
6
+ details: {
7
+ responseBody: JSON.stringify(error.response.body),
8
+ details: error.details,
9
+ },
10
+ errorCode: error.errorCode,
11
+ });
12
+ }
13
+ }
14
+ //# sourceMappingURL=TranslationMemoryClientError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TranslationMemoryClientError.js","sourceRoot":"","sources":["../../../src/sdk/errors/TranslationMemoryClientError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,OAAO,4BAA6B,SAAQ,aAAa;IAC7D,YAAY,KAA0B;QACpC,KAAK,CAAC;YACJ,OAAO,EAAE,iDAAiD,KAAK,CAAC,OAAO,EAAE;YACzE,OAAO,EAAE;gBACP,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACjD,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;YACD,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAA;IACJ,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import type { PaginationMeta } from '@lokalise/api-common';
2
+ import type { BulkTranslationMemoryMatches, TranslationMemoryMatch, TranslationMemoryRecord } from './models';
3
+ export type GetFindMatchesResponse = {
4
+ data: TranslationMemoryMatch[];
5
+ };
6
+ export type PostBulkFindMatchesResponse = {
7
+ data: BulkTranslationMemoryMatches[];
8
+ };
9
+ export type GetRecordsResponse = {
10
+ data: TranslationMemoryRecord[];
11
+ meta: PaginationMeta;
12
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=apiResponses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiResponses.js","sourceRoot":"","sources":["../../../src/sdk/types/apiResponses.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import type { PaginationMeta } from '@lokalise/api-common';
2
+ import type { MayOmit } from '@lokalise/node-core';
3
+ export type TranslationMemoryMatch = {
4
+ targetText: string;
5
+ };
6
+ export type BulkTranslationMemoryMatches = {
7
+ filterId?: string;
8
+ matches: TranslationMemoryMatch[];
9
+ };
10
+ export type TranslationMemoryRecord = {
11
+ id: string;
12
+ groupId: string;
13
+ ownerId: string;
14
+ sourceText: string;
15
+ targetText: string;
16
+ sourceLocale: string;
17
+ targetLocale: string;
18
+ sourcePrevContent?: string;
19
+ sourceNextContent?: string;
20
+ createdAt: Date;
21
+ };
22
+ export type TranslationMemoryRecordsResponse = {
23
+ records: TranslationMemoryRecord[];
24
+ meta: PaginationMeta;
25
+ };
26
+ export type UpsertRecordDto = Omit<MayOmit<TranslationMemoryRecord, 'id'>, 'groupId' | 'createdAt'>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../src/sdk/types/models.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ export type FindMatchesRequest = {
2
+ sourceText: string;
3
+ sourceLocale: string;
4
+ targetLocale: string;
5
+ prevContent?: string;
6
+ nextContent?: string;
7
+ maxMatches?: number;
8
+ };
9
+ export type BulkFindMatchesFilter = FindMatchesRequest & {
10
+ filterId?: string;
11
+ };
12
+ export type BulkFindMatchesRequest = {
13
+ filters: BulkFindMatchesFilter[];
14
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../../../src/sdk/types/requests.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ type TransformObjectKeys<T> = {
2
+ [K in keyof T as K extends string ? TransformKey<K> : never]: T[K] extends object ? TransformObjectKeys<T[K]> : T[K];
3
+ };
4
+ type TransformKey<T extends string> = T extends `${infer F}${infer R}` ? F extends Capitalize<F> ? `-${Lowercase<F>}${TransformKey<R>}` : `${F}${TransformKey<R>}` : Lowercase<T>;
5
+ export declare const transformToQueryParam: <T extends object>(object: T) => TransformObjectKeys<T>;
6
+ export {};
@@ -0,0 +1,12 @@
1
+ // TODO: could this be useful on node-core?
2
+ export const transformToQueryParam = (object) => {
3
+ const transformed = {};
4
+ for (const key in object) {
5
+ const value = object[key];
6
+ const transformedKey = key.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
7
+ transformed[transformedKey] =
8
+ typeof value === 'object' ? transformToQueryParam(value) : value;
9
+ }
10
+ return transformed;
11
+ };
12
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/sdk/utils.ts"],"names":[],"mappings":"AAYA,2CAA2C;AAC3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAmB,MAAS,EAA0B,EAAE;IAC3F,MAAM,WAAW,GAA4B,EAAE,CAAA;IAC/C,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QACzB,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QAEhF,WAAW,CAAC,cAAc,CAAC;YACzB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;KAC7E;IAED,OAAO,WAAqC,CAAA;AAC9C,CAAC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@lokalise/tm-sdk",
3
+ "version": "1.0.0",
4
+ "author": {
5
+ "name": "Lokalise",
6
+ "url": "https://lokalise.com/"
7
+ },
8
+ "files": [
9
+ "dist/**"
10
+ ],
11
+ "license": "Apache-2.0",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git://github.com/lokalise/tm-service.git"
15
+ },
16
+ "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
18
+ "type": "commonjs",
19
+ "scripts": {
20
+ "build": "shx rm -rf ./dist && tsc",
21
+ "build:publish": "shx rm -rf ./dist && tsc -p tsconfig.publish.json",
22
+ "lint": "eslint . --ext .ts && prettier --check \"**/*.{json,md,ts}\" && tsc --noEmit",
23
+ "lint:fix": "eslint . --ext .ts --fix && prettier --write --log-level warn \"**/*.{json,md,ts}\"",
24
+ "test": "vitest",
25
+ "test:coverage": "npm test -- --coverage",
26
+ "test:ci": "npm run test:coverage",
27
+ "version": "auto-changelog -p && git add CHANGELOG.md",
28
+ "prepublishOnly": "npm run build:publish"
29
+ },
30
+ "dependencies": {
31
+ "@lokalise/api-common": "^2.0.0",
32
+ "@lokalise/node-core": "^9.7.0",
33
+ "undici": "^6.4.0",
34
+ "undici-retry": "^5.0.2"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "20.11.5",
38
+ "@typescript-eslint/eslint-plugin": "^6.13.1",
39
+ "@typescript-eslint/parser": "^6.13.1",
40
+ "@vitest/coverage-v8": "^1.2.1",
41
+ "auto-changelog": "^2.4.0",
42
+ "eslint": "^8.56.0",
43
+ "eslint-plugin-import": "^2.29.1",
44
+ "eslint-plugin-vitest": "^0.3.20",
45
+ "mockttp": "^3.10.1",
46
+ "prettier": "^3.2.4",
47
+ "shx": "^0.3.4",
48
+ "typescript": "5.3.3",
49
+ "vitest": "^1.2.1"
50
+ }
51
+ }