sitevision-cli 1.0.0-beta.16 → 1.0.0-beta.17

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.
@@ -28,6 +28,12 @@ export declare function appStatus(project: ProjectInfo): {
28
28
  signing: boolean;
29
29
  scriptsWarning: string | undefined;
30
30
  };
31
+ /** The name shown for an app in the navigator, and what the filter matches. */
32
+ export declare function appLabel(app: ProjectInfo): string;
33
+ /** Indices into `apps` whose label fuzzy-matches the filter. */
34
+ export declare function navMatches(apps: ProjectInfo[], filter: string): number[];
35
+ /** Next selectable index when moving by `delta`, wrapping at both ends. */
36
+ export declare function navMove(ring: number[], selected: number, delta: number): number;
31
37
  export interface NavigatorProps {
32
38
  apps: ProjectInfo[];
33
39
  groupOf: (app: ProjectInfo) => string;
@@ -38,8 +44,9 @@ export interface NavigatorProps {
38
44
  single: boolean;
39
45
  settingsSelected?: boolean;
40
46
  width: number;
47
+ filter?: string;
41
48
  }
42
- export declare function Navigator({ apps, groupOf, selected, focused, tasks, height, single, settingsSelected, width, }: NavigatorProps): import("react").JSX.Element;
49
+ export declare function Navigator({ apps, groupOf, selected, focused, tasks, height, single, settingsSelected, width, filter, }: NavigatorProps): import("react").JSX.Element;
43
50
  export declare function NavigatorStrip({ apps, selected, focused, }: Pick<NavigatorProps, 'apps' | 'selected' | 'focused'>): import("react").JSX.Element;
44
51
  export declare function elapsed(task: Task): string;
45
52
  export interface Hint {
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from 'ink';
3
3
  import Spinner from 'ink-spinner';
4
4
  import { appTypeOf, getPackageJsonSyncChanges, localizedText, } from '../utils/project-detection.js';
5
+ import { fuzzyMatch } from './actions.js';
5
6
  import { t } from '../utils/i18n.js';
6
7
  export const ACCENT = 'cyan';
7
8
  export const NARROW_BELOW = 100;
@@ -40,7 +41,24 @@ function Dots({ project }) {
40
41
  const dot = (ok, warn = false) => (_jsx(Text, { color: ok ? 'green' : warn ? 'yellow' : 'red', children: "\u25CF" }));
41
42
  return (_jsxs(Text, { children: [dot(s.deps), dot(s.config), dot(s.sync === 0, s.sync > 0), dot(s.signing, !s.signing)] }));
42
43
  }
43
- export function Navigator({ apps, groupOf, selected, focused, tasks, height, single, settingsSelected = false, width, }) {
44
+ /** The name shown for an app in the navigator, and what the filter matches. */
45
+ export function appLabel(app) {
46
+ return localizedText(app.manifest.name) || app.manifest.id;
47
+ }
48
+ /** Indices into `apps` whose label fuzzy-matches the filter. */
49
+ export function navMatches(apps, filter) {
50
+ return apps
51
+ .map((_, index) => index)
52
+ .filter(index => fuzzyMatch(filter, appLabel(apps[index])));
53
+ }
54
+ /** Next selectable index when moving by `delta`, wrapping at both ends. */
55
+ export function navMove(ring, selected, delta) {
56
+ if (ring.length === 0)
57
+ return selected;
58
+ const at = ring.indexOf(selected);
59
+ return ring[at === -1 ? 0 : (at + delta + ring.length) % ring.length];
60
+ }
61
+ export function Navigator({ apps, groupOf, selected, focused, tasks, height, single, settingsSelected = false, width, filter = '', }) {
44
62
  // Row: marker(1) glyph(3) sp name sp version(6) sp dots(4) inside the padding.
45
63
  const nameWidth = width - 2 - 17;
46
64
  const running = tasks.filter(task => task.status === 'running');
@@ -51,16 +69,20 @@ export function Navigator({ apps, groupOf, selected, focused, tasks, height, sin
51
69
  for (const [index, app] of apps.entries()) {
52
70
  const group = groupOf(app);
53
71
  if (!single && group !== lastGroup) {
54
- rows.push(_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: [' ', group] }) }, `g-${group}`));
72
+ rows.push(_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: [' ', group] }) }, `g-${index}-${group}`));
55
73
  rowApp.push(-1);
56
74
  lastGroup = group;
57
75
  }
58
76
  rowApp.push(index);
59
77
  const active = index === selected;
60
78
  const busy = running.some(task => task.appRoot === app.root);
61
- const name = localizedText(app.manifest.name) || app.manifest.id;
79
+ const name = appLabel(app);
62
80
  rows.push(_jsxs(Box, { width: width - 2, height: 1, flexShrink: 0, children: [_jsxs(Text, { backgroundColor: active && focused ? ACCENT : undefined, color: active && focused ? 'black' : undefined, bold: active, wrap: "truncate", children: [active ? '▎' : ' ', _jsx(Text, { dimColor: !active, children: typeGlyph(app.manifest) }), ' ', name.padEnd(nameWidth).slice(0, nameWidth), ' ', _jsx(Text, { dimColor: true, children: app.manifest.version.padStart(6).slice(0, 6) }), ' '] }), busy ? (_jsx(Text, { color: ACCENT, children: _jsx(Spinner, { type: "dots" }) })) : (_jsx(Dots, { project: app }))] }, app.root));
63
81
  }
82
+ if (rows.length === 0) {
83
+ rows.push(_jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: ' ' + t('no matches') }) }, "none"));
84
+ rowApp.push(-1);
85
+ }
64
86
  // Window the list so the selected app stays visible; the lines outside
65
87
  // are summarised as "… n more".
66
88
  const fixed = 1 + 1 + (single ? 0 : 2) + (running.length > 0 ? running.length + 2 : 0);
@@ -79,14 +101,16 @@ export function Navigator({ apps, groupOf, selected, focused, tasks, height, sin
79
101
  if (end < rows.length)
80
102
  shown[shown.length - 1] = more(rows.length - end, '↓');
81
103
  }
82
- return (_jsxs(Box, { flexDirection: "column", width: width, height: height, borderStyle: "single", borderDimColor: true, borderTop: false, borderBottom: false, borderLeft: false, paddingX: 1, overflow: "hidden", children: [_jsx(Text, { bold: true, dimColor: true, children: single
104
+ return (_jsxs(Box, { flexDirection: "column", width: width, height: height, borderStyle: "single", borderDimColor: true, borderTop: false, borderBottom: false, borderLeft: false, paddingX: 1, overflow: "hidden", children: [filter ? (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: ACCENT, children: "\u276F " }), filter, _jsx(Text, { inverse: true, children: " " }), _jsxs(Text, { dimColor: true, children: [' ', apps.length === 1
105
+ ? t('1 match')
106
+ : t('{n} matches', { n: apps.length })] })] })) : (_jsx(Text, { bold: true, dimColor: true, children: single
83
107
  ? t('APP')
84
108
  : apps.length === 1
85
109
  ? t('WORKSPACE 1 app')
86
- : t('WORKSPACE {n} apps', { n: apps.length }) }), shown, _jsx(Text, { dimColor: true, children: ' ' + t('deps·config·sync·signing') }), !single && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { backgroundColor: settingsSelected && focused ? ACCENT : undefined, color: settingsSelected && focused ? 'black' : undefined, bold: settingsSelected, children: [settingsSelected ? '▎' : ' ', "\u2699 ", t('Workspace settings')] }) })), running.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, dimColor: true, children: t('TASKS') }), running.map(task => (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: ACCENT, children: _jsx(Spinner, { type: "dots" }) }), ' ', task.label, " ", task.appName, " ", _jsx(Text, { dimColor: true, children: elapsed(task) })] }, task.id)))] }))] }));
110
+ : t('WORKSPACE {n} apps', { n: apps.length }) })), shown, _jsx(Text, { dimColor: true, children: ' ' + t('deps·config·sync·signing') }), !single && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { backgroundColor: settingsSelected && focused ? ACCENT : undefined, color: settingsSelected && focused ? 'black' : undefined, bold: settingsSelected, children: [settingsSelected ? '▎' : ' ', "\u2699 ", t('Workspace settings')] }) })), running.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, dimColor: true, children: t('TASKS') }), running.map(task => (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: ACCENT, children: _jsx(Spinner, { type: "dots" }) }), ' ', task.label, " ", task.appName, " ", _jsx(Text, { dimColor: true, children: elapsed(task) })] }, task.id)))] }))] }));
87
111
  }
88
112
  export function NavigatorStrip({ apps, selected, focused, }) {
89
- return (_jsx(Box, { paddingX: 1, children: _jsx(Text, { wrap: "truncate", children: apps.map((app, index) => (_jsxs(Text, { backgroundColor: index === selected && focused ? ACCENT : undefined, color: index === selected && focused ? 'black' : undefined, bold: index === selected, children: [' ', typeGlyph(app.manifest), ' ', localizedText(app.manifest.name) || app.manifest.id, ' '] }, app.root))) }) }));
113
+ return (_jsx(Box, { paddingX: 1, children: _jsx(Text, { wrap: "truncate", children: apps.map((app, index) => (_jsxs(Text, { backgroundColor: index === selected && focused ? ACCENT : undefined, color: index === selected && focused ? 'black' : undefined, bold: index === selected, children: [' ', typeGlyph(app.manifest), " ", appLabel(app), ' '] }, app.root))) }) }));
90
114
  }
91
115
  export function elapsed(task) {
92
116
  const ms = (task.endedAt ?? Date.now()) - task.startedAt;
@@ -9,7 +9,7 @@ import { listAddons, listExecutables, } from '../utils/sitevision-api.js';
9
9
  import { useTasks, runningTasks, startActivate, getTasks, } from '../utils/tasks.js';
10
10
  import { PasswordInput } from '../components/PasswordInput.js';
11
11
  import { AuthLoginScreen } from '../components/AuthLoginScreen.js';
12
- import { TopBar, Navigator, NavigatorStrip, BottomBar, navWidth, NARROW_BELOW, ACCENT, } from './Frame.js';
12
+ import { TopBar, Navigator, NavigatorStrip, BottomBar, navMatches, navMove, appLabel, navWidth, NARROW_BELOW, ACCENT, } from './Frame.js';
13
13
  import { TabBar, TABS, Overview, Versions, Log, } from './Tabs.js';
14
14
  import { CommandPalette } from './CommandPalette.js';
15
15
  import { ConfigForm } from './ConfigForm.js';
@@ -43,6 +43,7 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
43
43
  const [tab, setTab] = useState('overview');
44
44
  const [focus, setFocus] = useState(workspaceRoot && !onboard ? 'nav' : 'content');
45
45
  const [overlay, setOverlay] = useState(null);
46
+ const [filter, setFilter] = useState('');
46
47
  const [versions, setVersions] = useState({});
47
48
  const [versionRow, setVersionRow] = useState(0);
48
49
  const [logScroll, setLogScroll] = useState(0);
@@ -78,6 +79,10 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
78
79
  [workspaceRoot, apps, env]);
79
80
  const narrow = columns < NARROW_BELOW;
80
81
  const sidebar = navWidth(columns);
82
+ // The navigator shows the fuzzy matches; `selected` stays an index into
83
+ // `apps` (with `apps.length` meaning the workspace settings row).
84
+ const matches = useMemo(() => navMatches(apps, filter), [apps, filter]);
85
+ const ring = single ? matches : [...matches, apps.length];
81
86
  const running = runningTasks();
82
87
  // Re-render once a second while something runs so elapsed times move.
83
88
  useEffect(() => {
@@ -254,6 +259,10 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
254
259
  ? raw.toUpperCase()
255
260
  : raw;
256
261
  if (key.escape) {
262
+ if (focus === 'nav' && filter) {
263
+ setFilter('');
264
+ return;
265
+ }
257
266
  // Esc backs out of the workspace settings pane, not just its focus.
258
267
  if (settings)
259
268
  setSelected(0);
@@ -265,9 +274,40 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
265
274
  return;
266
275
  }
267
276
  if (key.tab) {
277
+ setFilter('');
268
278
  setFocus(f => f === 'nav' && !single ? 'content' : single ? 'content' : 'nav');
269
279
  return;
270
280
  }
281
+ // Navigator: typing searches, so no action key fires until Enter has
282
+ // moved the focus into the content pane.
283
+ if (focus === 'nav') {
284
+ const move = (delta) => {
285
+ setSelected(navMove(ring, selected, delta));
286
+ };
287
+ const search = (next) => {
288
+ setFilter(next);
289
+ const found = navMatches(apps, next);
290
+ if (found.length > 0 && !found.includes(selected))
291
+ setSelected(found[0]);
292
+ };
293
+ if (key.upArrow)
294
+ move(-1);
295
+ else if (key.downArrow)
296
+ move(1);
297
+ else if (key.return) {
298
+ if (matches.length > 0 || settings) {
299
+ setFilter('');
300
+ setFocus('content');
301
+ }
302
+ }
303
+ else if (key.backspace || key.delete)
304
+ search(filter.slice(0, -1));
305
+ else if (input === 'q' && !filter)
306
+ quit();
307
+ else if (input?.length === 1 && input >= ' ' && !key.ctrl && !key.meta)
308
+ search(filter + input);
309
+ return;
310
+ }
271
311
  if (input === 'a' && tab !== 'versions') {
272
312
  setTab('versions');
273
313
  setFocus('content');
@@ -292,16 +332,7 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
292
332
  quit();
293
333
  return;
294
334
  }
295
- if (focus === 'nav') {
296
- const last = single ? apps.length - 1 : apps.length;
297
- if (key.upArrow)
298
- setSelected(s => (s > 0 ? s - 1 : last));
299
- if (key.downArrow)
300
- setSelected(s => (s < last ? s + 1 : 0));
301
- if (key.return)
302
- setFocus('content');
303
- }
304
- else if (tab === 'versions') {
335
+ if (tab === 'versions') {
305
336
  const count = versions[versionsKey]?.executables?.length ?? 0;
306
337
  if (key.upArrow)
307
338
  setVersionRow(r => Math.max(0, r - 1));
@@ -336,7 +367,7 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
336
367
  const mainHeight = frameRows - 2;
337
368
  const contentHeight = mainHeight - 1 - (narrow ? 1 : 0);
338
369
  const groupOf = (app) => workspaceRoot ? appGroup(workspaceRoot, app.root) : '.';
339
- const appName = localizedText(project.manifest.name) || project.manifest.id;
370
+ const appName = appLabel(project);
340
371
  const tabName = t(TABS.find(entry => entry.id === tab).label).toLowerCase();
341
372
  const contextLabel = settings
342
373
  ? `${t('workspace')} ▸ ${t('settings')}`
@@ -361,61 +392,77 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
361
392
  ['↑↓', 'apps'],
362
393
  ['q', 'quit'],
363
394
  ]);
395
+ const navHints = filter
396
+ ? h([
397
+ ['↑↓', 'move'],
398
+ ['Enter', 'select'],
399
+ ['Esc', 'clear'],
400
+ ['/', 'commands'],
401
+ ])
402
+ : h([
403
+ ['a–z', 'search'],
404
+ ['↑↓', 'move'],
405
+ ['Enter', 'select'],
406
+ ['/', 'commands'],
407
+ ['q', 'quit'],
408
+ ]);
364
409
  const hints = overlay
365
410
  ? h([['Esc', 'cancel']])
366
- : settings
367
- ? settingsHints
368
- : tab === 'versions'
369
- ? h([
370
- ['a', 'activate'],
371
- ['R', 'refresh'],
372
- ['p', 'deploy'],
373
- ['/', 'commands'],
374
- ['q', 'quit'],
375
- ])
376
- : tab === 'log'
411
+ : focus === 'nav' && !settings
412
+ ? navHints
413
+ : settings
414
+ ? settingsHints
415
+ : tab === 'versions'
377
416
  ? h([
378
- ['f', 'follow'],
379
- ['x', 'wrap'],
380
- ['K', 'stop'],
417
+ ['a', 'activate'],
418
+ ['R', 'refresh'],
381
419
  ['p', 'deploy'],
382
420
  ['/', 'commands'],
383
421
  ['q', 'quit'],
384
422
  ])
385
- : tab === 'config'
386
- ? editing
387
- ? h([
388
- ['Enter', 'save'],
389
- ['Esc', 'cancel'],
390
- ])
391
- : formActive
392
- ? h([
393
- ['↑↓', 'field'],
394
- ['Enter', 'edit'],
395
- ['^O', 'pick addon'],
396
- ['y', 'sync'],
397
- ['/', 'commands'],
398
- ['q', 'quit'],
399
- ])
400
- : h([
401
- ['Tab', 'edit'],
402
- ['y', 'sync'],
403
- ['l', 'login'],
404
- ['/', 'commands'],
405
- ['q', 'quit'],
406
- ])
407
- : h([
408
- ['d', 'dev'],
409
- ['w', 'watch'],
410
- ['b', 'build'],
411
- ['s', 'sign'],
423
+ : tab === 'log'
424
+ ? h([
425
+ ['f', 'follow'],
426
+ ['x', 'wrap'],
427
+ ['K', 'stop'],
412
428
  ['p', 'deploy'],
413
- ['a', 'activate'],
414
- ['E', 'env'],
415
- ['i', 'install'],
416
429
  ['/', 'commands'],
417
430
  ['q', 'quit'],
418
- ]);
431
+ ])
432
+ : tab === 'config'
433
+ ? editing
434
+ ? h([
435
+ ['Enter', 'save'],
436
+ ['Esc', 'cancel'],
437
+ ])
438
+ : formActive
439
+ ? h([
440
+ ['↑↓', 'field'],
441
+ ['Enter', 'edit'],
442
+ ['^O', 'pick addon'],
443
+ ['y', 'sync'],
444
+ ['/', 'commands'],
445
+ ['q', 'quit'],
446
+ ])
447
+ : h([
448
+ ['Tab', 'edit'],
449
+ ['y', 'sync'],
450
+ ['l', 'login'],
451
+ ['/', 'commands'],
452
+ ['q', 'quit'],
453
+ ])
454
+ : h([
455
+ ['d', 'dev'],
456
+ ['w', 'watch'],
457
+ ['b', 'build'],
458
+ ['s', 'sign'],
459
+ ['p', 'deploy'],
460
+ ['a', 'activate'],
461
+ ['E', 'env'],
462
+ ['i', 'install'],
463
+ ['/', 'commands'],
464
+ ['q', 'quit'],
465
+ ]);
419
466
  const right = running.length > 0 ? (_jsxs(Text, { children: [_jsx(Text, { color: ACCENT, children: _jsx(Spinner, { type: "dots" }) }), ' ', running[0].label, " ", running[0].appName, running.length > 1 && (_jsxs(Text, { dimColor: true, children: [" \u00B7 ", t('{n} tasks', { n: running.length })] }))] })) : notice ? (_jsx(Text, { color: { info: undefined, ok: 'green', warn: 'yellow', error: 'red' }[notice.level], wrap: "truncate", children: notice.text })) : (_jsx(Text, { dimColor: true, children: t('idle') }));
420
467
  const closeOverlay = () => setOverlay(null);
421
468
  const content = overlay ? (renderOverlay(overlay, {
@@ -448,7 +495,7 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
448
495
  return (_jsxs(Box, { flexDirection: "column", width: columns, height: frameRows, children: [_jsx(TopBar, { context: contextLabel, domain: project.devProperties?.domain, auth: authState(project), environment: {
449
496
  name: env,
450
497
  color: environmentColor(env, rawProject.devProperties),
451
- }, version: version }), _jsxs(Box, { flexGrow: 1, height: mainHeight, borderStyle: "single", borderDimColor: true, borderLeft: false, borderRight: false, borderBottom: false, children: [!narrow && (_jsx(Navigator, { apps: apps, groupOf: groupOf, selected: selected, focused: focus === 'nav', tasks: tasks, height: mainHeight - 1, single: single, settingsSelected: settings, width: sidebar })), _jsxs(Box, { flexDirection: "column", width: narrow ? columns : columns - sidebar, overflow: "hidden", children: [narrow && !single && (_jsx(NavigatorStrip, { apps: apps, selected: selected, focused: focus === 'nav' })), settings ? (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: t('Workspace settings') }), _jsx(Text, { dimColor: true, children: onboard && configIncomplete(workspaceTarget?.base)
498
+ }, version: version }), _jsxs(Box, { flexGrow: 1, height: mainHeight, borderStyle: "single", borderDimColor: true, borderLeft: false, borderRight: false, borderBottom: false, children: [!narrow && (_jsx(Navigator, { apps: matches.map(i => apps[i]), groupOf: groupOf, selected: matches.indexOf(selected), focused: focus === 'nav', tasks: tasks, height: mainHeight - 1, single: single, settingsSelected: settings, width: sidebar, filter: filter })), _jsxs(Box, { flexDirection: "column", width: narrow ? columns : columns - sidebar, overflow: "hidden", children: [narrow && !single && (_jsx(NavigatorStrip, { apps: matches.map(i => apps[i]), selected: matches.indexOf(selected), focused: focus === 'nav' })), settings ? (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: t('Workspace settings') }), _jsx(Text, { dimColor: true, children: onboard && configIncomplete(workspaceTarget?.base)
452
499
  ? t(' · new workspace: fill in once, every app inherits · Esc skips')
453
500
  : t(' · shared .dev_properties.json at the root') })] })) : (_jsx(TabBar, { tab: tab, narrow: narrow, focused: focus === 'content' })), _jsx(Box, { height: contentHeight, overflow: "hidden", alignItems: "flex-start", children: content })] })] }), _jsx(BottomBar, { hints: hints, right: right })] }));
454
501
  }
@@ -203,6 +203,13 @@ const sv = {
203
203
  edit: 'redigera',
204
204
  back: 'tillbaka',
205
205
  quit: 'avsluta',
206
+ search: 'sök',
207
+ move: 'flytta',
208
+ select: 'välj',
209
+ clear: 'rensa',
210
+ 'no matches': 'inga träffar',
211
+ '{n} matches': '{n} träffar',
212
+ '1 match': '1 träff',
206
213
  'edit settings': 'redigera inställningar',
207
214
  apps: 'appar',
208
215
  activate: 'aktivera',
@@ -39,7 +39,10 @@ export function discoverApps(root) {
39
39
  }
40
40
  };
41
41
  walk(root, 1);
42
- return found.toSorted((a, b) => a.root.localeCompare(b.root));
42
+ // Group first, then path: a deeper folder (webapps/nested) must not split
43
+ // its parent's run of apps, or the same group heading renders twice.
44
+ return found.toSorted((a, b) => path.dirname(a.root).localeCompare(path.dirname(b.root)) ||
45
+ a.root.localeCompare(b.root));
43
46
  }
44
47
  /** Group label for an app: its parent folder relative to the workspace root. */
45
48
  export function appGroup(root, appRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sitevision-cli",
3
- "version": "1.0.0-beta.16",
3
+ "version": "1.0.0-beta.17",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "svc": "dist/cli.js"