@tolgee/cli 1.1.2 → 1.3.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.
@@ -10,7 +10,7 @@ async function loginHandler(key) {
10
10
  keyInfo = await RestClient.getApiKeyInformation(opts.apiUrl, key);
11
11
  }
12
12
  catch (e) {
13
- if (e instanceof HttpError && e.response.status === 403) {
13
+ if (e instanceof HttpError && e.response.status === 401) {
14
14
  error("Couldn't log in: the API key you provided is invalid.");
15
15
  process.exit(1);
16
16
  }
@@ -1,21 +1,33 @@
1
1
  import { Command, Option } from 'commander';
2
2
  import { unzipBuffer } from '../utils/zip.js';
3
3
  import { overwriteDir } from '../utils/overwriteDir.js';
4
- import { loading, success } from '../utils/logger.js';
4
+ import { error, loading, success } from '../utils/logger.js';
5
+ import { HttpError } from '../client/errors.js';
5
6
  async function fetchZipBlob(opts) {
6
7
  return opts.client.export.export({
7
8
  format: opts.format,
8
9
  languages: opts.languages,
9
10
  filterState: opts.states,
10
11
  structureDelimiter: opts.delimiter,
12
+ filterNamespace: opts.namespaces,
11
13
  });
12
14
  }
13
15
  async function pullHandler(path) {
14
16
  const opts = this.optsWithGlobals();
15
17
  await overwriteDir(path, opts.overwrite);
16
- const zipBlob = await loading('Fetching strings from Tolgee...', fetchZipBlob(opts));
17
- await loading('Extracting strings...', unzipBuffer(zipBlob, path));
18
- success('Done!');
18
+ try {
19
+ const zipBlob = await loading('Fetching strings from Tolgee...', fetchZipBlob(opts));
20
+ await loading('Extracting strings...', unzipBuffer(zipBlob, path));
21
+ success('Done!');
22
+ }
23
+ catch (e) {
24
+ if (e instanceof HttpError && e.response.status === 400) {
25
+ const res = await e.response.json();
26
+ error(`Please check if your parameters, including namespaces, are configured correctly. Tolgee responded with: ${res.code}`);
27
+ return;
28
+ }
29
+ throw e;
30
+ }
19
31
  }
20
32
  export default new Command()
21
33
  .name('pull')
@@ -32,5 +44,6 @@ export default new Command()
32
44
  .addOption(new Option('-d, --delimiter', 'Structure delimiter to use. By default, Tolgee interprets `.` as a nested structure. You can change the delimiter, or disable structure formatting by not specifying any value to the option')
33
45
  .default('.')
34
46
  .argParser((v) => v || ''))
47
+ .addOption(new Option('-n, --namespaces <namespaces...>', 'List of namespaces to pull. Defaults to all namespaces'))
35
48
  .option('-o, --overwrite', 'Whether to automatically overwrite existing files. BE CAREFUL, THIS WILL WIPE *ALL* THE CONTENTS OF THE TARGET FOLDER. If unspecified, the user will be prompted interactively, or the command will fail when in non-interactive')
36
49
  .action(pullHandler);
@@ -49,7 +49,7 @@ function parseConfig(rc) {
49
49
  if (typeof rc.delimiter !== 'string' && rc.delimiter !== null) {
50
50
  throw new Error('Invalid config: delimiter is not a string');
51
51
  }
52
- cfg.delimiter = rc.delimiter || void 0;
52
+ cfg.delimiter = rc.delimiter || '';
53
53
  }
54
54
  return cfg;
55
55
  }
package/dist/constants.js CHANGED
@@ -8,4 +8,4 @@ export const USER_AGENT = `Tolgee-CLI/${VERSION} (+https://github.com/tolgee/tol
8
8
  export const DEFAULT_API_URL = new URL('https://app.tolgee.io');
9
9
  export const API_KEY_PAT_PREFIX = 'tgpat_';
10
10
  export const API_KEY_PAK_PREFIX = 'tgpak_';
11
- export const SDKS = ['react'];
11
+ export const SDKS = ['react', 'vue', 'svelte'];
@@ -1,8 +1,10 @@
1
1
  import { extname } from 'path';
2
2
  import { interpret } from 'xstate';
3
3
  import reactExtractorMachine from './machines/react.js';
4
+ import vueExtractorMachine from './machines/vue/extract.js';
4
5
  import svelteExtractorMachine from './machines/svelte.js';
5
6
  import commentsExtractorMachine from './machines/comments.js';
7
+ import vueSfcProcessor from './processors/vueSfc.js';
6
8
  import tokenizer from './tokenizer.js';
7
9
  const REACT_EXTS = [
8
10
  '.js',
@@ -14,6 +16,7 @@ const REACT_EXTS = [
14
16
  '.jsx',
15
17
  '.tsx',
16
18
  ];
19
+ const VUE_EXTS = REACT_EXTS;
17
20
  const ALL_EXTS = [
18
21
  '.js',
19
22
  '.mjs',
@@ -25,11 +28,13 @@ const ALL_EXTS = [
25
28
  '.tsx',
26
29
  '.svelte',
27
30
  ];
28
- function pickMachine(code, fileName) {
29
- const ext = extname(fileName);
31
+ function pickMachine(code, ext) {
30
32
  if (REACT_EXTS.includes(ext) && code.includes('@tolgee/react')) {
31
33
  return reactExtractorMachine;
32
34
  }
35
+ if (VUE_EXTS.includes(ext) && code.includes('@tolgee/vue')) {
36
+ return vueExtractorMachine;
37
+ }
33
38
  if (ext === '.svelte' && code.includes('@tolgee/svelte')) {
34
39
  return svelteExtractorMachine;
35
40
  }
@@ -40,7 +45,15 @@ function pickMachine(code, fileName) {
40
45
  return null;
41
46
  }
42
47
  export default async function extractor(code, fileName) {
43
- const machineSpec = pickMachine(code, fileName);
48
+ const ext = extname(fileName);
49
+ if (ext === '.vue' &&
50
+ (code.includes('$t') ||
51
+ code.includes('@tolgee/vue') ||
52
+ code.includes('@tolgee-key') ||
53
+ code.includes('@tolgee-ignore'))) {
54
+ return vueSfcProcessor(code, fileName);
55
+ }
56
+ const machineSpec = pickMachine(code, ext);
44
57
  if (!machineSpec) {
45
58
  return { warnings: [], keys: [] };
46
59
  }
@@ -1,4 +1,5 @@
1
1
  import { createMachine, assign, send, forwardTo } from 'xstate';
2
+ import translateCallMachine from './shared/translateCall.js';
2
3
  import propertiesMachine from './shared/properties.js';
3
4
  import commentsService from './shared/comments.js';
4
5
  const VOID_KEY = { keyName: '', line: -1 };
@@ -456,111 +457,38 @@ export default createMachine({
456
457
  },
457
458
  },
458
459
  call: {
459
- on: {
460
- 'punctuation.definition.string.begin.ts': 'param_string',
461
- 'punctuation.definition.string.template.begin.ts': 'param_string',
462
- 'variable.other.readwrite.ts': [
463
- {
464
- target: 'idle',
465
- actions: 'dynamicOptions',
466
- cond: (ctx) => !!ctx.key.keyName,
467
- },
460
+ invoke: {
461
+ id: 'tCall',
462
+ src: translateCallMachine,
463
+ onDone: [
468
464
  {
469
465
  target: 'idle',
470
466
  actions: 'dynamicKeyName',
471
- },
472
- ],
473
- 'punctuation.definition.block.ts': {
474
- target: 'param_object',
475
- cond: (_ctx, evt) => evt.token === '{',
476
- },
477
- 'meta.brace.round.ts': {
478
- target: 'idle',
479
- cond: (_ctx, evt) => evt.token === ')',
480
- actions: 'pushKey',
481
- },
482
- },
483
- },
484
- param_string: {
485
- on: {
486
- '*': [
487
- {
488
- target: 'param_end',
489
- actions: ['storeKeyName', 'storeKeyCurrentNamespace'],
490
- cond: (ctx) => !ctx.key.keyName,
491
- },
492
- {
493
- target: 'param_end',
494
- actions: ['storeKeyDefault', 'storeKeyCurrentNamespace'],
495
- cond: (ctx) => !!ctx.key.keyName,
496
- },
497
- ],
498
- },
499
- },
500
- param_end: {
501
- on: {
502
- 'punctuation.separator.comma.ts': 'call',
503
- 'punctuation.definition.template-expression.begin.ts': [
504
- {
505
- target: 'param_end_warn',
506
- actions: 'dynamicKeyDefault',
507
- cond: (ctx) => !!ctx.key.defaultValue,
467
+ cond: (_, evt) => evt.data.keyName === false,
508
468
  },
509
469
  {
510
470
  target: 'idle',
511
- actions: 'dynamicKeyName',
512
- },
513
- ],
514
- 'keyword.operator.arithmetic.ts': [
515
- {
516
- target: 'param_end_warn',
517
- actions: 'dynamicKeyDefault',
518
- cond: (ctx) => !!ctx.key.defaultValue,
471
+ actions: 'dynamicNamespace',
472
+ cond: (_, evt) => evt.data.namespace === false,
519
473
  },
520
474
  {
521
475
  target: 'idle',
522
- actions: 'dynamicKeyName',
476
+ actions: 'dynamicOptions',
477
+ cond: (_, evt) => evt.data.dynamicOptions,
523
478
  },
524
- ],
525
- 'meta.brace.round.ts': {
526
- target: 'idle',
527
- cond: (_ctx, evt) => evt.token === ')',
528
- actions: 'pushKey',
529
- },
530
- },
531
- },
532
- param_end_warn: {
533
- on: {
534
- 'punctuation.separator.comma.ts': 'call',
535
- 'meta.brace.round.ts': {
536
- target: 'idle',
537
- cond: (_ctx, evt) => evt.token === ')',
538
- actions: 'pushKey',
539
- },
540
- },
541
- },
542
- param_object: {
543
- invoke: {
544
- id: 'propertiesMachine',
545
- src: propertiesMachine,
546
- data: {
547
- depth: 1,
548
- },
549
- onDone: [
550
479
  {
551
480
  target: 'idle',
552
- actions: 'emitWarningFromParameters',
553
- cond: 'isPropertiesDataDynamic',
481
+ cond: (_, evt) => !evt.data.keyName,
554
482
  },
555
483
  {
556
484
  target: 'idle',
557
- actions: ['consumeParameters', 'pushKey'],
485
+ actions: 'consumeTranslateCall',
558
486
  },
559
487
  ],
560
488
  },
561
489
  on: {
562
490
  '*': {
563
- actions: forwardTo('propertiesMachine'),
491
+ actions: forwardTo('tCall'),
564
492
  },
565
493
  },
566
494
  },
@@ -613,6 +541,43 @@ export default createMachine({
613
541
  { warning: 'W_DYNAMIC_NAMESPACE', line: ctx.line },
614
542
  ],
615
543
  }),
544
+ consumeTranslateCall: assign({
545
+ warnings: (ctx, evt) => {
546
+ const utNamespace = ctx.hooks.length
547
+ ? ctx.hooks[ctx.hooks.length - 1].namespace
548
+ : undefined;
549
+ if (!evt.data.namespace && utNamespace === false) {
550
+ return [
551
+ ...ctx.warnings,
552
+ { warning: 'W_UNRESOLVABLE_NAMESPACE', line: ctx.line },
553
+ ];
554
+ }
555
+ if (evt.data.defaultValue === false) {
556
+ return [
557
+ ...ctx.warnings,
558
+ { warning: 'W_DYNAMIC_DEFAULT_VALUE', line: ctx.line },
559
+ ];
560
+ }
561
+ return ctx.warnings;
562
+ },
563
+ keys: (ctx, evt) => {
564
+ const utNamespace = ctx.hooks.length
565
+ ? ctx.hooks[ctx.hooks.length - 1].namespace
566
+ : undefined;
567
+ const ns = evt.data.namespace === null ? utNamespace : evt.data.namespace;
568
+ if (!evt.data.keyName || ns === false)
569
+ return ctx.keys;
570
+ return [
571
+ ...ctx.keys,
572
+ {
573
+ keyName: evt.data.keyName,
574
+ namespace: ns || undefined,
575
+ defaultValue: evt.data.defaultValue || undefined,
576
+ line: ctx.line,
577
+ },
578
+ ];
579
+ },
580
+ }),
616
581
  consumeParameters: assign({
617
582
  key: (ctx, evt) => ({
618
583
  // We don't want the key and default value to be overridable
@@ -643,7 +608,7 @@ export default createMachine({
643
608
  line: ctx.line,
644
609
  },
645
610
  ],
646
- key: (_ctx, _evt) => VOID_KEY,
611
+ key: VOID_KEY,
647
612
  }),
648
613
  appendChildren: assign({
649
614
  children: (ctx, evt) => (ctx.children ?? '') + evt.token,
@@ -662,20 +627,19 @@ export default createMachine({
662
627
  storeKeyDefault: assign({
663
628
  key: (ctx, evt) => ({ ...ctx.key, defaultValue: evt.token }),
664
629
  }),
665
- storeKeyCurrentNamespace: assign({
666
- key: (ctx, _evt) => ({
667
- ...ctx.key,
668
- namespace: ctx.hooks.length
669
- ? ctx.hooks[ctx.hooks.length - 1].namespace
670
- : undefined,
671
- }),
672
- }),
673
630
  dynamicKeyName: assign({
674
631
  warnings: (ctx, _evt) => [
675
632
  ...ctx.warnings,
676
633
  { warning: 'W_DYNAMIC_KEY', line: ctx.line },
677
634
  ],
678
- key: (_ctx, _evt) => VOID_KEY,
635
+ key: VOID_KEY,
636
+ }),
637
+ dynamicNamespace: assign({
638
+ warnings: (ctx, _evt) => [
639
+ ...ctx.warnings,
640
+ { warning: 'W_DYNAMIC_NAMESPACE', line: ctx.line },
641
+ ],
642
+ key: VOID_KEY,
679
643
  }),
680
644
  dynamicKeyDefault: assign({
681
645
  key: (ctx, _evt) => ({ ...ctx.key, defaultValue: undefined }),
@@ -685,7 +649,7 @@ export default createMachine({
685
649
  ],
686
650
  }),
687
651
  dynamicOptions: assign({
688
- key: (ctx, _evt) => VOID_KEY,
652
+ key: VOID_KEY,
689
653
  warnings: (ctx, _evt) => [
690
654
  ...ctx.warnings,
691
655
  { warning: 'W_DYNAMIC_OPTIONS', line: ctx.line },
@@ -704,14 +668,6 @@ export default createMachine({
704
668
  ],
705
669
  }),
706
670
  pushKey: assign({
707
- warnings: (ctx, _evt) => {
708
- if (!ctx.key.keyName || ctx.key.namespace !== false)
709
- return ctx.warnings;
710
- return [
711
- ...ctx.warnings,
712
- { warning: 'W_UNRESOLVABLE_NAMESPACE', line: ctx.line },
713
- ];
714
- },
715
671
  keys: (ctx, _evt) => {
716
672
  if (!ctx.key.keyName || ctx.key.namespace === false)
717
673
  return ctx.keys;
@@ -8,6 +8,7 @@ export default createMachine({
8
8
  property: null,
9
9
  depth: 0,
10
10
  static: false,
11
+ nextDynamic: false,
11
12
  keyName: null,
12
13
  defaultValue: null,
13
14
  namespace: null,
@@ -47,6 +48,37 @@ export default createMachine({
47
48
  'punctuation.separator.key-value.svelte': {
48
49
  target: 'value',
49
50
  },
51
+ // Vue
52
+ 'punctuation.attribute-shorthand.event.html.vue': [
53
+ {
54
+ cond: (_, evt) => evt.token === '@',
55
+ actions: ['markPropertyAsDynamic', 'markNextPropertyAsDynamic'],
56
+ },
57
+ ],
58
+ 'entity.other.attribute-name.html.vue': [
59
+ {
60
+ cond: (ctx) => ctx.nextDynamic,
61
+ actions: 'markImmediatePropertyAsDynamic',
62
+ },
63
+ {
64
+ actions: [
65
+ 'markPropertyAsDynamic',
66
+ 'unmarkAsStatic',
67
+ 'storePropertyType',
68
+ ],
69
+ },
70
+ ],
71
+ 'punctuation.separator.key-value.html.vue': {
72
+ target: 'value',
73
+ },
74
+ 'entity.other.attribute-name.html': [
75
+ {
76
+ actions: ['markPropertyAsDynamic', 'storePropertyType'],
77
+ },
78
+ ],
79
+ 'punctuation.separator.key-value.html': {
80
+ target: 'value',
81
+ },
50
82
  },
51
83
  },
52
84
  complex_key: {
@@ -76,6 +108,7 @@ export default createMachine({
76
108
  'punctuation.definition.string.template.begin.ts': 'value_string',
77
109
  'punctuation.definition.string.begin.svelte': 'value_string',
78
110
  'punctuation.definition.string.template.begin.svelte': 'value_string',
111
+ 'punctuation.definition.string.begin.html': 'value_string',
79
112
  // Variable
80
113
  'variable.other.readwrite.ts': {
81
114
  target: 'idle',
@@ -98,6 +131,15 @@ export default createMachine({
98
131
  'unmarkAsStatic',
99
132
  ],
100
133
  },
134
+ // Vue
135
+ 'string.unquoted.html': {
136
+ target: 'idle',
137
+ actions: [
138
+ 'storePropertyValue',
139
+ 'clearPropertyType',
140
+ 'unmarkAsStatic',
141
+ ],
142
+ },
101
143
  // Value end
102
144
  'punctuation.separator.comma.ts': {
103
145
  target: 'idle',
@@ -137,6 +179,10 @@ export default createMachine({
137
179
  target: 'idle',
138
180
  actions: ['storeEmptyPropertyValue', 'clearPropertyType'],
139
181
  },
182
+ 'punctuation.definition.string.end.html': {
183
+ target: 'idle',
184
+ actions: ['storeEmptyPropertyValue', 'clearPropertyType'],
185
+ },
140
186
  '*': [
141
187
  {
142
188
  target: 'idle',
@@ -186,6 +232,15 @@ export default createMachine({
186
232
  target: 'idle',
187
233
  actions: 'clearPropertyType',
188
234
  },
235
+ // Vue
236
+ 'punctuation.definition.string.end.html.vue': {
237
+ target: 'idle',
238
+ actions: 'clearPropertyType',
239
+ },
240
+ 'punctuation.definition.string.end.html': {
241
+ target: 'idle',
242
+ actions: 'clearPropertyType',
243
+ },
189
244
  },
190
245
  },
191
246
  end: {
@@ -221,15 +276,27 @@ export default createMachine({
221
276
  target: 'end',
222
277
  actions: 'markPropertyAsDynamic',
223
278
  },
279
+ 'punctuation.definition.tag.end.html.vue': {
280
+ target: 'end',
281
+ actions: 'markPropertyAsDynamic',
282
+ },
283
+ 'punctuation.definition.tag.end.html': {
284
+ target: 'end',
285
+ actions: 'markPropertyAsDynamic',
286
+ },
224
287
  },
225
288
  }, {
226
289
  guards: {
227
290
  isOpenCurly: (_ctx, evt) => evt.token === '{' &&
228
291
  !evt.scopes.includes('meta.embedded.expression.tsx') &&
229
- !evt.scopes.includes('meta.embedded.expression.svelte'),
292
+ !evt.scopes.includes('meta.embedded.expression.svelte') &&
293
+ (!evt.scopes.includes('source.ts.embedded.html.vue') ||
294
+ evt.scopes.includes('expression.embedded.vue')),
230
295
  isCloseCurly: (_ctx, evt) => evt.token === '}' &&
231
296
  !evt.scopes.includes('meta.embedded.expression.tsx') &&
232
- !evt.scopes.includes('meta.embedded.expression.svelte'),
297
+ !evt.scopes.includes('meta.embedded.expression.svelte') &&
298
+ (!evt.scopes.includes('source.ts.embedded.html.vue') ||
299
+ evt.scopes.includes('expression.embedded.vue')),
233
300
  isFinalCloseCurly: (ctx, evt) => evt.token === '}' && ctx.depth === 1,
234
301
  isOpenSquare: (_ctx, evt) => evt.token === '[',
235
302
  isCloseSquare: (_ctx, evt) => evt.token === ']',
@@ -256,7 +323,11 @@ export default createMachine({
256
323
  defaultValue: (ctx) => ctx.property === 'defaultValue' ? '' : ctx.defaultValue,
257
324
  namespace: (ctx) => (ctx.property === 'ns' ? '' : ctx.namespace),
258
325
  }),
326
+ markNextPropertyAsDynamic: assign({
327
+ nextDynamic: true,
328
+ }),
259
329
  markPropertyAsDynamic: assign({
330
+ nextDynamic: false,
260
331
  keyName: (ctx, _evt) => ctx.property === 'key' || ctx.property === 'keyName'
261
332
  ? false
262
333
  : ctx.keyName,
@@ -264,6 +335,7 @@ export default createMachine({
264
335
  namespace: (ctx, _evt) => ctx.property === 'ns' ? false : ctx.namespace,
265
336
  }),
266
337
  markImmediatePropertyAsDynamic: assign({
338
+ nextDynamic: false,
267
339
  keyName: (ctx, evt) => evt.token === 'key' || evt.token === 'keyName' ? false : ctx.keyName,
268
340
  defaultValue: (ctx, evt) => evt.token === 'defaultValue' ? false : ctx.defaultValue,
269
341
  namespace: (ctx, evt) => (evt.token === 'ns' ? false : ctx.namespace),
@@ -275,10 +347,10 @@ export default createMachine({
275
347
  depth: (ctx, _evt) => ctx.depth - 1,
276
348
  }),
277
349
  markAsStatic: assign({
278
- static: (_ctx, _evt) => true,
350
+ static: true,
279
351
  }),
280
352
  unmarkAsStatic: assign({
281
- static: (_ctx, _evt) => false,
353
+ static: false,
282
354
  }),
283
355
  },
284
356
  });
@@ -0,0 +1,141 @@
1
+ // This machine is responsible for extracting data from
2
+ // calls to `t`. It is shared across multiple machines since
3
+ // all t functions share the same signature.
4
+ import { createMachine, assign, forwardTo } from 'xstate';
5
+ import propertiesMachine from './properties.js';
6
+ export default createMachine({
7
+ predictableActionArguments: true,
8
+ id: 'tCall',
9
+ initial: 'idle',
10
+ context: {
11
+ keyName: null,
12
+ defaultValue: null,
13
+ namespace: null,
14
+ dynamicOptions: false,
15
+ },
16
+ states: {
17
+ idle: {
18
+ on: {
19
+ 'punctuation.definition.string.begin.ts': 'string',
20
+ 'punctuation.definition.string.template.begin.ts': 'string',
21
+ 'variable.other.readwrite.ts': [
22
+ {
23
+ target: 'done',
24
+ actions: 'dynamicOptions',
25
+ cond: (ctx) => !!ctx.keyName,
26
+ },
27
+ {
28
+ target: 'done',
29
+ actions: 'dynamicKeyName',
30
+ },
31
+ ],
32
+ 'punctuation.definition.block.ts': {
33
+ target: 'object',
34
+ cond: (_ctx, evt) => evt.token === '{',
35
+ },
36
+ 'meta.brace.round.ts': {
37
+ target: 'done',
38
+ cond: (_ctx, evt) => evt.token === ')',
39
+ },
40
+ },
41
+ },
42
+ string: {
43
+ on: {
44
+ '*': [
45
+ {
46
+ target: 'string_end',
47
+ actions: 'storeKeyName',
48
+ cond: (ctx) => !ctx.keyName,
49
+ },
50
+ {
51
+ target: 'string_end',
52
+ actions: 'storeDefaultValue',
53
+ cond: (ctx) => !!ctx.keyName,
54
+ },
55
+ ],
56
+ },
57
+ },
58
+ string_end: {
59
+ on: {
60
+ 'punctuation.separator.comma.ts': 'idle',
61
+ 'punctuation.definition.template-expression.begin.ts': [
62
+ {
63
+ target: 'string_end_warn',
64
+ actions: 'dynamicDefaultValue',
65
+ cond: (ctx) => !!ctx.defaultValue,
66
+ },
67
+ {
68
+ target: 'done',
69
+ actions: 'dynamicKeyName',
70
+ },
71
+ ],
72
+ 'keyword.operator.arithmetic.ts': [
73
+ {
74
+ target: 'string_end_warn',
75
+ actions: 'dynamicDefaultValue',
76
+ cond: (ctx) => !!ctx.defaultValue,
77
+ },
78
+ {
79
+ target: 'done',
80
+ actions: 'dynamicKeyName',
81
+ },
82
+ ],
83
+ 'meta.brace.round.ts': {
84
+ target: 'done',
85
+ cond: (_ctx, evt) => evt.token === ')',
86
+ },
87
+ },
88
+ },
89
+ string_end_warn: {
90
+ on: {
91
+ 'punctuation.separator.comma.ts': 'idle',
92
+ 'meta.brace.round.ts': {
93
+ target: 'done',
94
+ cond: (_ctx, evt) => evt.token === ')',
95
+ },
96
+ },
97
+ },
98
+ object: {
99
+ invoke: {
100
+ id: 'propertiesMachine',
101
+ src: propertiesMachine,
102
+ data: {
103
+ depth: 1,
104
+ },
105
+ onDone: {
106
+ target: 'done',
107
+ actions: 'consumeParameters',
108
+ },
109
+ },
110
+ on: {
111
+ '*': {
112
+ actions: forwardTo('propertiesMachine'),
113
+ },
114
+ },
115
+ },
116
+ done: { type: 'final', data: (ctx) => ctx },
117
+ },
118
+ }, {
119
+ actions: {
120
+ storeKeyName: assign({
121
+ keyName: (_, evt) => evt.token,
122
+ }),
123
+ storeDefaultValue: assign({
124
+ defaultValue: (_, evt) => evt.token,
125
+ }),
126
+ consumeParameters: assign({
127
+ keyName: (ctx, evt) => ctx.keyName === null ? evt.data.keyName : ctx.keyName,
128
+ namespace: (ctx, evt) => ctx.namespace === null ? evt.data.namespace : ctx.namespace,
129
+ defaultValue: (ctx, evt) => ctx.defaultValue === null ? evt.data.defaultValue : ctx.defaultValue,
130
+ }),
131
+ dynamicKeyName: assign({
132
+ keyName: () => false,
133
+ }),
134
+ dynamicDefaultValue: assign({
135
+ defaultValue: () => false,
136
+ }),
137
+ dynamicOptions: assign({
138
+ dynamicOptions: () => true,
139
+ }),
140
+ },
141
+ });