@tolgee/cli 1.0.2 → 1.1.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,495 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const xstate_1 = require("xstate");
7
+ const properties_1 = __importDefault(require("./shared/properties"));
8
+ const comments_1 = __importDefault(require("./shared/comments"));
9
+ const VOID_KEY = { keyName: '', line: -1 };
10
+ exports.default = (0, xstate_1.createMachine)({
11
+ predictableActionArguments: true,
12
+ id: 'svelteExtractor',
13
+ type: 'parallel',
14
+ context: {
15
+ children: '',
16
+ line: 0,
17
+ key: VOID_KEY,
18
+ useTranslate: null,
19
+ ignore: null,
20
+ keys: [],
21
+ warnings: [],
22
+ },
23
+ states: {
24
+ comments: {
25
+ invoke: {
26
+ id: 'comments',
27
+ src: () => comments_1.default,
28
+ },
29
+ on: {
30
+ // Service messages
31
+ MAGIC_COMMENT: [
32
+ {
33
+ actions: 'ignoreNextLine',
34
+ cond: (_ctx, evt) => evt.kind === 'ignore',
35
+ },
36
+ {
37
+ actions: 'pushImmediateKey',
38
+ cond: (_ctx, evt) => evt.kind === 'key',
39
+ },
40
+ ],
41
+ WARNING: {
42
+ actions: 'pushWarning',
43
+ },
44
+ // Code messages
45
+ 'comment.line.double-slash.ts': {
46
+ actions: (0, xstate_1.send)((_ctx, evt) => ({
47
+ type: 'COMMENT',
48
+ data: evt.token,
49
+ line: evt.line,
50
+ }), { to: 'comments' }),
51
+ },
52
+ 'comment.block.ts': {
53
+ actions: (0, xstate_1.send)((_ctx, evt) => ({
54
+ type: 'COMMENT',
55
+ data: evt.token,
56
+ line: evt.line,
57
+ }), { to: 'comments' }),
58
+ },
59
+ 'comment.block.svelte': {
60
+ actions: (0, xstate_1.send)((_ctx, evt) => ({
61
+ type: 'COMMENT',
62
+ data: evt.token,
63
+ line: evt.line,
64
+ }), { to: 'comments' }),
65
+ },
66
+ newline: {
67
+ actions: 'warnUnusedIgnore',
68
+ cond: (ctx, evt) => ctx.ignore?.type === 'ignore' && ctx.ignore.line === evt.line,
69
+ },
70
+ },
71
+ },
72
+ useTranslate: {
73
+ initial: 'idle',
74
+ states: {
75
+ idle: {
76
+ on: {
77
+ 'entity.name.function.ts': {
78
+ target: 'func',
79
+ actions: 'storeLine',
80
+ cond: (_ctx, evt) => evt.token === 'useTranslate',
81
+ },
82
+ },
83
+ },
84
+ func: {
85
+ on: {
86
+ '*': 'idle',
87
+ newline: undefined,
88
+ 'meta.block.ts': undefined,
89
+ 'meta.var.expr.ts': undefined,
90
+ 'meta.brace.round.ts': [
91
+ {
92
+ target: 'idle',
93
+ actions: 'consumeIgnoredLine',
94
+ cond: (ctx, evt) => ctx.ignore?.line === ctx.line &&
95
+ ctx.ignore.type === 'ignore' &&
96
+ evt.token === '(',
97
+ },
98
+ {
99
+ target: 'call',
100
+ cond: (_ctx, evt) => evt.token === '(',
101
+ },
102
+ ],
103
+ },
104
+ },
105
+ call: {
106
+ on: {
107
+ 'punctuation.definition.string.begin.ts': 'namespace',
108
+ 'punctuation.definition.string.template.begin.ts': 'namespace',
109
+ 'variable.other.readwrite.ts': {
110
+ target: 'idle',
111
+ actions: ['storeUseTranslate', 'markUseTranslateAsDynamic'],
112
+ },
113
+ 'meta.brace.round.ts': {
114
+ target: 'idle',
115
+ cond: (_ctx, evt) => evt.token === ')',
116
+ actions: 'storeUseTranslate',
117
+ },
118
+ },
119
+ },
120
+ namespace: {
121
+ on: {
122
+ '*': {
123
+ target: 'namespace_end',
124
+ actions: 'storeNamespacedUseTranslate',
125
+ },
126
+ },
127
+ },
128
+ namespace_end: {
129
+ on: {
130
+ 'punctuation.separator.comma.ts': 'idle',
131
+ 'meta.brace.round.ts': 'idle',
132
+ 'punctuation.definition.template-expression.begin.ts': {
133
+ target: 'idle',
134
+ actions: 'markUseTranslateAsDynamic',
135
+ },
136
+ 'keyword.operator.arithmetic.ts': {
137
+ target: 'idle',
138
+ actions: 'markUseTranslateAsDynamic',
139
+ },
140
+ },
141
+ },
142
+ },
143
+ },
144
+ component: {
145
+ initial: 'idle',
146
+ states: {
147
+ idle: {
148
+ on: {
149
+ 'punctuation.definition.tag.begin.svelte': {
150
+ target: 'tag',
151
+ actions: 'storeLine',
152
+ cond: (_ctx, evt) => evt.token === '<',
153
+ },
154
+ },
155
+ },
156
+ tag: {
157
+ on: {
158
+ '*': 'idle',
159
+ newline: undefined,
160
+ 'meta.tag.start.svelte': undefined,
161
+ 'support.class.component.svelte': [
162
+ {
163
+ target: 'idle',
164
+ actions: 'consumeIgnoredLine',
165
+ cond: (ctx, evt) => ctx.ignore?.line === ctx.line && evt.token === 'T',
166
+ },
167
+ {
168
+ target: 'props',
169
+ cond: (_ctx, evt) => evt.token === 'T',
170
+ },
171
+ ],
172
+ },
173
+ },
174
+ props: {
175
+ invoke: {
176
+ id: 'propertiesMachine',
177
+ src: properties_1.default,
178
+ onDone: [
179
+ {
180
+ target: 'idle',
181
+ actions: 'emitWarningFromParameters',
182
+ cond: 'isPropertiesDataDynamic',
183
+ },
184
+ {
185
+ target: 'idle',
186
+ actions: ['consumeParameters', 'pushKey'],
187
+ cond: (ctx, evt) => evt.data.lastEvent.token !== '/>' &&
188
+ ((!ctx.key.keyName && !evt.data.keyName) ||
189
+ (!ctx.key.defaultValue && !evt.data.defaultValue)),
190
+ },
191
+ {
192
+ target: 'idle',
193
+ actions: ['consumeParameters', 'pushKey'],
194
+ },
195
+ ],
196
+ },
197
+ on: {
198
+ '*': {
199
+ actions: (0, xstate_1.forwardTo)('propertiesMachine'),
200
+ },
201
+ },
202
+ },
203
+ },
204
+ },
205
+ t: {
206
+ initial: 'idle',
207
+ states: {
208
+ idle: {
209
+ on: {
210
+ 'punctuation.definition.variable.svelte': {
211
+ target: 'dollar',
212
+ cond: (ctx, evt) => ctx.useTranslate !== null && evt.token === '$',
213
+ },
214
+ },
215
+ },
216
+ dollar: {
217
+ on: {
218
+ '*': 'idle',
219
+ 'entity.name.function.ts': {
220
+ target: 'func',
221
+ actions: 'storeLine',
222
+ cond: (_ctx, evt) => evt.token === 't',
223
+ },
224
+ },
225
+ },
226
+ func: {
227
+ on: {
228
+ '*': 'idle',
229
+ newline: undefined,
230
+ 'source.ts': undefined,
231
+ 'meta.brace.round.ts': [
232
+ {
233
+ target: 'idle',
234
+ actions: 'consumeIgnoredLine',
235
+ cond: (ctx, evt) => ctx.ignore?.line === ctx.line && evt.token === '(',
236
+ },
237
+ {
238
+ target: 'call',
239
+ cond: (_ctx, evt) => evt.token === '(',
240
+ },
241
+ ],
242
+ },
243
+ },
244
+ call: {
245
+ on: {
246
+ 'punctuation.definition.string.begin.ts': 'param_string',
247
+ 'punctuation.definition.string.template.begin.ts': 'param_string',
248
+ 'variable.other.readwrite.ts': [
249
+ {
250
+ target: 'idle',
251
+ actions: 'dynamicOptions',
252
+ cond: (ctx) => !!ctx.key.keyName,
253
+ },
254
+ {
255
+ target: 'idle',
256
+ actions: 'dynamicKeyName',
257
+ },
258
+ ],
259
+ 'punctuation.definition.block.ts': {
260
+ target: 'param_object',
261
+ cond: (_ctx, evt) => evt.token === '{',
262
+ },
263
+ 'meta.brace.round.ts': {
264
+ target: 'idle',
265
+ cond: (_ctx, evt) => evt.token === ')',
266
+ actions: 'pushKey',
267
+ },
268
+ },
269
+ },
270
+ param_string: {
271
+ on: {
272
+ '*': [
273
+ {
274
+ target: 'param_end',
275
+ actions: ['storeKeyName', 'storeKeyCurrentNamespace'],
276
+ cond: (ctx) => !ctx.key.keyName,
277
+ },
278
+ {
279
+ target: 'param_end',
280
+ actions: ['storeKeyDefault', 'storeKeyCurrentNamespace'],
281
+ cond: (ctx) => !!ctx.key.keyName,
282
+ },
283
+ ],
284
+ },
285
+ },
286
+ param_end: {
287
+ on: {
288
+ 'punctuation.separator.comma.ts': 'call',
289
+ 'punctuation.definition.template-expression.begin.ts': [
290
+ {
291
+ target: 'param_end_warn',
292
+ actions: 'dynamicKeyDefault',
293
+ cond: (ctx) => !!ctx.key.defaultValue,
294
+ },
295
+ {
296
+ target: 'idle',
297
+ actions: 'dynamicKeyName',
298
+ },
299
+ ],
300
+ 'keyword.operator.arithmetic.ts': [
301
+ {
302
+ target: 'param_end_warn',
303
+ actions: 'dynamicKeyDefault',
304
+ cond: (ctx) => !!ctx.key.defaultValue,
305
+ },
306
+ {
307
+ target: 'idle',
308
+ actions: 'dynamicKeyName',
309
+ },
310
+ ],
311
+ 'meta.brace.round.ts': {
312
+ target: 'idle',
313
+ cond: (_ctx, evt) => evt.token === ')',
314
+ actions: 'pushKey',
315
+ },
316
+ },
317
+ },
318
+ param_end_warn: {
319
+ on: {
320
+ 'punctuation.separator.comma.ts': 'call',
321
+ 'meta.brace.round.ts': {
322
+ target: 'idle',
323
+ cond: (_ctx, evt) => evt.token === ')',
324
+ actions: 'pushKey',
325
+ },
326
+ },
327
+ },
328
+ param_object: {
329
+ invoke: {
330
+ id: 'propertiesMachine',
331
+ src: properties_1.default,
332
+ data: {
333
+ depth: 1,
334
+ },
335
+ onDone: [
336
+ {
337
+ target: 'idle',
338
+ actions: 'emitWarningFromParameters',
339
+ cond: 'isPropertiesDataDynamic',
340
+ },
341
+ {
342
+ target: 'idle',
343
+ actions: ['consumeParameters', 'pushKey'],
344
+ },
345
+ ],
346
+ },
347
+ on: {
348
+ '*': {
349
+ actions: (0, xstate_1.forwardTo)('propertiesMachine'),
350
+ },
351
+ },
352
+ },
353
+ },
354
+ },
355
+ },
356
+ }, {
357
+ guards: {
358
+ isPropertiesDataDynamic: (_ctx, evt) => evt.data.keyName === false || evt.data.namespace === false,
359
+ },
360
+ actions: {
361
+ storeLine: (0, xstate_1.assign)({
362
+ line: (_ctx, evt) => evt.line,
363
+ }),
364
+ ignoreNextLine: (0, xstate_1.assign)({
365
+ ignore: (_ctx, evt) => ({ type: 'ignore', line: evt.line + 1 }),
366
+ }),
367
+ consumeIgnoredLine: (0, xstate_1.assign)({
368
+ ignore: (_ctx, _evt) => null,
369
+ }),
370
+ warnUnusedIgnore: (0, xstate_1.assign)({
371
+ warnings: (ctx, evt) => [
372
+ ...ctx.warnings,
373
+ { warning: 'W_UNUSED_IGNORE', line: evt.line - 1 },
374
+ ],
375
+ }),
376
+ storeUseTranslate: (0, xstate_1.assign)({
377
+ useTranslate: (_ctx, _evt) => '',
378
+ }),
379
+ storeNamespacedUseTranslate: (0, xstate_1.assign)({
380
+ useTranslate: (_ctx, evt) => evt.token,
381
+ }),
382
+ markUseTranslateAsDynamic: (0, xstate_1.assign)({
383
+ useTranslate: (_ctx, _evt) => false,
384
+ warnings: (ctx, _evt) => [
385
+ ...ctx.warnings,
386
+ { warning: 'W_DYNAMIC_NAMESPACE', line: ctx.line },
387
+ ],
388
+ }),
389
+ consumeParameters: (0, xstate_1.assign)({
390
+ key: (ctx, evt) => ({
391
+ keyName: ctx.key.keyName || evt.data.keyName,
392
+ defaultValue: ctx.key.defaultValue || evt.data.defaultValue || undefined,
393
+ namespace: evt.data.namespace ?? ctx.key.namespace,
394
+ line: ctx.line,
395
+ }),
396
+ warnings: (ctx, evt) => {
397
+ if (evt.data.defaultValue !== false)
398
+ return ctx.warnings;
399
+ return [
400
+ ...ctx.warnings,
401
+ { warning: 'W_DYNAMIC_DEFAULT_VALUE', line: ctx.line },
402
+ ];
403
+ },
404
+ }),
405
+ emitWarningFromParameters: (0, xstate_1.assign)({
406
+ warnings: (ctx, evt) => [
407
+ ...ctx.warnings,
408
+ {
409
+ warning: evt.data.keyName === false
410
+ ? 'W_DYNAMIC_KEY'
411
+ : 'W_DYNAMIC_NAMESPACE',
412
+ line: ctx.line,
413
+ },
414
+ ],
415
+ key: (_ctx, _evt) => VOID_KEY,
416
+ }),
417
+ storeKeyName: (0, xstate_1.assign)({
418
+ key: (ctx, evt) => ({ ...ctx.key, keyName: evt.token }),
419
+ }),
420
+ storeKeyDefault: (0, xstate_1.assign)({
421
+ key: (ctx, evt) => ({ ...ctx.key, defaultValue: evt.token }),
422
+ }),
423
+ storeKeyCurrentNamespace: (0, xstate_1.assign)({
424
+ key: (ctx, _evt) => ({
425
+ ...ctx.key,
426
+ namespace: ctx.useTranslate !== null ? ctx.useTranslate : undefined,
427
+ }),
428
+ }),
429
+ dynamicKeyName: (0, xstate_1.assign)({
430
+ warnings: (ctx, _evt) => [
431
+ ...ctx.warnings,
432
+ { warning: 'W_DYNAMIC_KEY', line: ctx.line },
433
+ ],
434
+ key: (_ctx, _evt) => VOID_KEY,
435
+ }),
436
+ dynamicKeyDefault: (0, xstate_1.assign)({
437
+ key: (ctx, _evt) => ({ ...ctx.key, defaultValue: undefined }),
438
+ warnings: (ctx, _evt) => [
439
+ ...ctx.warnings,
440
+ { warning: 'W_DYNAMIC_DEFAULT_VALUE', line: ctx.line },
441
+ ],
442
+ }),
443
+ dynamicOptions: (0, xstate_1.assign)({
444
+ key: (_ctx, _evt) => VOID_KEY,
445
+ warnings: (ctx, _evt) => [
446
+ ...ctx.warnings,
447
+ { warning: 'W_DYNAMIC_OPTIONS', line: ctx.line },
448
+ ],
449
+ }),
450
+ pushKey: (0, xstate_1.assign)({
451
+ warnings: (ctx, _evt) => {
452
+ if (!ctx.key.keyName || ctx.key.namespace !== false)
453
+ return ctx.warnings;
454
+ return [
455
+ ...ctx.warnings,
456
+ { warning: 'W_UNRESOLVABLE_NAMESPACE', line: ctx.line },
457
+ ];
458
+ },
459
+ keys: (ctx, _evt) => {
460
+ if (!ctx.key.keyName || ctx.key.namespace === false)
461
+ return ctx.keys;
462
+ return [
463
+ ...ctx.keys,
464
+ {
465
+ keyName: ctx.key.keyName.trim(),
466
+ namespace: ctx.key.namespace === ''
467
+ ? undefined
468
+ : ctx.key.namespace?.trim(),
469
+ defaultValue: ctx.key.defaultValue?.trim().replace(/\s+/g, ' '),
470
+ line: ctx.line,
471
+ },
472
+ ];
473
+ },
474
+ key: (_ctx, _evt) => ({ keyName: '', line: 0 }),
475
+ }),
476
+ pushImmediateKey: (0, xstate_1.assign)({
477
+ ignore: (_ctx, evt) => ({ type: 'key', line: evt.line + 1 }),
478
+ keys: (ctx, evt) => [
479
+ ...ctx.keys,
480
+ {
481
+ keyName: evt.keyName,
482
+ namespace: evt.namespace,
483
+ defaultValue: evt.defaultValue,
484
+ line: evt.line,
485
+ },
486
+ ],
487
+ }),
488
+ pushWarning: (0, xstate_1.assign)({
489
+ warnings: (ctx, evt) => [
490
+ ...ctx.warnings,
491
+ { warning: evt.kind, line: evt.line },
492
+ ],
493
+ }),
494
+ },
495
+ });
@@ -8,6 +8,7 @@ const GRAMMAR_PATH = (0, path_1.join)(__dirname, '..', '..', 'textmate');
8
8
  const GrammarFiles = {
9
9
  ["source.ts" /* Grammar.TYPESCRIPT */]: (0, path_1.join)(GRAMMAR_PATH, 'TypeScript.tmLanguage'),
10
10
  ["source.tsx" /* Grammar.TYPESCRIPT_TSX */]: (0, path_1.join)(GRAMMAR_PATH, 'TypeScriptReact.tmLanguage'),
11
+ ["source.svelte" /* Grammar.SVELTE */]: (0, path_1.join)(GRAMMAR_PATH, 'Svelte.tmLanguage'),
11
12
  };
12
13
  let oniguruma;
13
14
  let registry;
@@ -27,7 +28,9 @@ async function loadGrammar(scope) {
27
28
  if (!file)
28
29
  return null;
29
30
  const grammar = await (0, promises_1.readFile)(file, 'utf8');
30
- return (0, vscode_textmate_1.parseRawGrammar)(grammar);
31
+ return grammar.startsWith('{')
32
+ ? JSON.parse(grammar)
33
+ : (0, vscode_textmate_1.parseRawGrammar)(grammar);
31
34
  }
32
35
  function extnameToGrammar(extname) {
33
36
  switch (extname) {
@@ -41,6 +44,8 @@ function extnameToGrammar(extname) {
41
44
  case '.jsx':
42
45
  case '.tsx':
43
46
  return "source.tsx" /* Grammar.TYPESCRIPT_TSX */;
47
+ case '.svelte':
48
+ return "source.svelte" /* Grammar.SVELTE */;
44
49
  }
45
50
  }
46
51
  function tokenize(code, grammar) {
@@ -66,8 +66,6 @@ function dumpWarnings(extractionResult) {
66
66
  return warningCount;
67
67
  }
68
68
  exports.dumpWarnings = dumpWarnings;
69
- // TODO: Revisit this function and turn it into an actual GitHub Action Annotation?
70
- // https://docs.github.com/en/rest/checks/runs?apiVersion=2022-11-28#update-a-check-run
71
69
  function emitGitHubWarning(warning, file, line) {
72
70
  if (!process.env.GITHUB_ACTIONS)
73
71
  return;
@@ -7,8 +7,7 @@ exports.callWorker = void 0;
7
7
  const path_1 = require("path");
8
8
  const worker_threads_1 = require("worker_threads");
9
9
  const promises_1 = require("fs/promises");
10
- // TODO: this solution won't handle new integrations and it will need a slight tweaking before adding new ones
11
- const react_1 = __importDefault(require("./presets/react"));
10
+ const extractor_1 = __importDefault(require("./extractor"));
12
11
  const moduleLoader_1 = require("../utils/moduleLoader");
13
12
  const deferred_1 = require("../utils/deferred");
14
13
  const IS_TS_NODE = (0, path_1.extname)(__filename) === '.ts';
@@ -20,7 +19,7 @@ async function handleJob(args) {
20
19
  loadedExtractor = args.extractor;
21
20
  extractor = args.extractor
22
21
  ? await (0, moduleLoader_1.loadModule)(args.extractor).then((mdl) => mdl.default)
23
- : react_1.default;
22
+ : extractor_1.default;
24
23
  }
25
24
  const file = (0, path_1.resolve)(args.file);
26
25
  const code = await (0, promises_1.readFile)(file, 'utf8');
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ function loadProjectId(cmd) {
56
56
  if (opts.projectId !== -1 && opts.projectId !== projectId) {
57
57
  (0, logger_1.error)('The specified API key cannot be used to perform operations on the specified project.');
58
58
  (0, logger_1.info)(`The API key you specified is tied to project #${projectId}, you tried to perform operations on project #${opts.projectId}.`);
59
- (0, logger_1.info)('Learn more about how API keys in Tolgee work here: https://tolgee.io/docs/platform/api-keys-and-pat-tokens');
59
+ (0, logger_1.info)('Learn more about how API keys in Tolgee work here: https://tolgee.io/platform/account_settings/api_keys_and_pat_tokens');
60
60
  process.exit(1);
61
61
  }
62
62
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadModule = void 0;
4
4
  const path_1 = require("path");
5
5
  let tsService;
6
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
7
  function realImport(file) {
7
8
  return eval('import(file)');
8
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tolgee/cli",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "type": "commonjs",
5
5
  "description": "A tool to interact with the Tolgee Platform through CLI",
6
6
  "bin": {
@@ -10,14 +10,14 @@
10
10
  "build": "rimraf dist dist-types && tsc && cp dist-types/extractor/index.d.ts extractor.d.ts",
11
11
  "test": "npm run test:unit && npm run test:e2e && npm run test:package",
12
12
  "test:unit": "jest -c jest.unit.config.ts",
13
- "pretest:e2e": "npm run tolgee:start",
13
+ "pretest:e2e": "npm run build && npm run tolgee:start",
14
14
  "posttest:e2e": "npm run tolgee:stop",
15
15
  "test:e2e": "jest -c jest.e2e.config.ts --runInBand",
16
16
  "test:e2e-run": "jest -c jest.e2e.config.ts --runInBand",
17
17
  "test:package": "node scripts/validatePackage.mjs",
18
18
  "tolgee:start": "node scripts/startDocker.mjs",
19
19
  "tolgee:stop": "docker stop tolgee_cli_e2e",
20
- "lint": "prettier --check ./src ./test ./scripts jest.config.ts jest.*.config.ts",
20
+ "lint": "eslint --ext .ts --ext .js --ext .mjs ./src ./test ./scripts jest.config.ts jest.*.config.ts",
21
21
  "prettier": "prettier --write ./src ./test ./scripts jest.config.ts jest.*.config.ts",
22
22
  "run-dev": "ts-node ./src/index.ts",
23
23
  "schema": "openapi-typescript http://localhost:22222/v3/api-docs/All%20Internal%20-%20for%20Tolgee%20Web%20application --output src/client/internal/schema.generated.ts",
@@ -47,7 +47,13 @@
47
47
  "@types/jest": "^29.2.5",
48
48
  "@types/node": "^18.11.18",
49
49
  "@types/yauzl": "^2.10.0",
50
+ "@typescript-eslint/eslint-plugin": "^5.59.1",
51
+ "@typescript-eslint/parser": "^5.59.1",
52
+ "eslint": "^8.39.0",
53
+ "eslint-plugin-jest": "^27.2.1",
54
+ "eslint-plugin-prettier": "^4.2.1",
50
55
  "jest": "^29.3.1",
56
+ "js-yaml": "^4.1.0",
51
57
  "openapi-typescript": "^6.1.0",
52
58
  "prettier": "^2.8.3",
53
59
  "rimraf": "^4.0.7",