• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RauliL / varasto / 26651802556

29 May 2026 05:22PM UTC coverage: 92.759% (-0.7%) from 93.457%
26651802556

push

github

RauliL
Add missing dependency

718 of 747 branches covered (96.12%)

Branch coverage included in aggregate %.

2510 of 2733 relevant lines covered (91.84%)

14.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.79
/packages/cli/src/command.ts
1
import { Storage } from '@varasto/storage';
3✔
2
import JSON5 from 'json5';
×
3
import { colorize } from 'json-colorizer';
×
4

5
import { tokenize } from './tokenizer';
×
6

7
export type CommandDefinition = {
8
  description: string;
9
  args?: string[];
10
  callback: (storage: Storage, args: string[]) => Promise<void>;
11
};
12

13
export class CommandError extends Error {
×
14
  constructor(message: string) {
×
15
    super(message);
×
16
    this.name = 'CommandError';
×
17
  }
×
18
}
×
19

20
const renderValue = (value: string | object): string =>
×
21
  colorize(value, { indent: 2 });
×
22

23
export const renderUsage = (command: CommandDefinition): string =>
×
24
  command.args?.map((arg) => `<${arg}>`).join(' ') ?? '';
×
25

26
const commands: Readonly<Record<string, CommandDefinition>> = {
×
27
  quit: {
×
28
    description: 'Exits the command line interface.',
×
29
    async callback() {
×
30
      process.exit(0);
×
31
    },
×
32
  },
×
33
  help: {
×
34
    description: 'Displays information about an command.',
×
35
    args: ['command'],
×
36
    async callback(storage, [command]) {
×
37
      const definition = commands[command];
×
38

39
      if (definition) {
×
40
        console.log(`${command} ${renderUsage(definition)}`);
×
41
        console.log(definition.description);
×
42
      } else {
×
43
        throw new Error(`Unknown command: ${command}`);
×
44
      }
×
45
    },
×
46
  },
×
47
  list: {
×
48
    description: 'Lists all entries from an namespace.',
×
49
    args: ['namespace'],
×
50
    async callback(storage, [namespace]) {
×
51
      for await (const [key, value] of storage.entries(namespace)) {
×
52
        console.log(renderValue({ [key]: value }));
×
53
      }
×
54
    },
×
55
  },
×
56
  keys: {
×
57
    description: 'Lists keys of all entries from an namespace.',
×
58
    args: ['namespace'],
×
59
    async callback(storage, [namespace]) {
×
60
      for await (const key of storage.keys(namespace)) {
×
61
        console.log(key);
×
62
      }
×
63
    },
×
64
  },
×
65
  get: {
×
66
    description: 'Retrieves an entry from an namespace.',
×
67
    args: ['namespace', 'key'],
×
68
    async callback(storage, [namespace, key]) {
×
69
      const value = await storage.get(namespace, key);
×
70

71
      if (value === undefined) {
×
72
        console.error('Entry does not exist.');
×
73
      } else {
×
74
        console.log(renderValue(value));
×
75
      }
×
76
    },
×
77
  },
×
78
  set: {
×
79
    description: 'Inserts an entry to namespace.',
×
80
    args: ['namespace', 'key', 'value'],
×
81
    async callback(storage, [namespace, key, value]) {
×
82
      await storage.set(namespace, key, JSON5.parse(value));
×
83
    },
×
84
  },
×
85
  update: {
×
86
    description: 'Patches an already existing entry in namespace.',
×
87
    args: ['namespace', 'key', 'value'],
×
88
    async callback(storage, [namespace, key, value]) {
×
89
      if (key === '*') {
×
90
        for await (const key of storage.keys(namespace)) {
×
91
          console.log(
×
92
            renderValue({
×
93
              [key]: await storage.update(namespace, key, JSON5.parse(value)),
×
94
            })
×
95
          );
×
96
        }
×
97
      } else {
×
98
        console.log(
×
99
          renderValue(await storage.update(namespace, key, JSON5.parse(value)))
×
100
        );
×
101
      }
×
102
    },
×
103
  },
×
104
  delete: {
×
105
    description: 'Deletes an entry from namespace.',
×
106
    args: ['namespace', 'key'],
×
107
    async callback(storage, [namespace, key]) {
×
108
      if (key === '*') {
×
109
        for await (const key of storage.keys(namespace)) {
×
110
          await storage.delete(namespace, key);
×
111
        }
×
112
      } else {
×
113
        if (!(await storage.delete(namespace, key))) {
×
114
          console.error('Item does not exist.');
×
115
        }
×
116
      }
×
117
    },
×
118
  },
×
119
};
×
120

121
export const commandNames: Readonly<string[]> = Object.keys(commands).sort();
×
122

123
export const runCommand = async (
×
124
  storage: Storage,
×
125
  input: string
×
126
): Promise<void> => {
×
127
  const args = tokenize(input);
×
128
  let command: CommandDefinition;
×
129

130
  if (args.length === 0) {
×
131
    return;
×
132
  } else if (!(command = commands[args[0]])) {
×
133
    throw new CommandError(`Unknown command: ${args[0]}`);
×
134
  }
×
135

136
  const arity = command.args?.length ?? 0;
×
137

138
  if (args.length - 1 < arity) {
×
139
    throw new CommandError(`Missing arguments for command ${args[0]}`);
×
140
  } else if (args.length - 1 > arity) {
×
141
    throw new CommandError(`Too many arguments for command ${args[0]}`);
×
142
  }
×
143

144
  await command.callback(storage, args.slice(1));
×
145
};
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc