local-kv-cli 1.0.0 → 2.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ ## 2.0.0
4
+
5
+ ### Breaking changes
6
+
7
+ - **New data file format.** Each value now stores its type, created/updated times and history, and values are grouped into namespaces. 1.x files are upgraded automatically on first use, and the old file is kept as `store.json.v1-backup`. 1.x can't read the new format.
8
+ - **Values are typed.** `lkv set n 42` now stores the number `42`, and `true`, `false` and JSON objects/arrays are stored as their type. Values like `007` or `1e5` stay text. Use `--type string` to keep text. Values from 1.x stay text.
9
+ - **Library API.** `Store` values are typed (`Value`) instead of always strings. `set(key, value, force)` is now `set(key, value, { force })`. `getStorePath()` was replaced by `locateStore()` / `globalStorePath()`.
10
+ - **Project stores.** Inside a folder with a `.lkv.json` (created by `lkv init`), `lkv` uses that file instead of the global store. Use `--global` to get the global store.
11
+ - The `LKV_STORE_PATH` environment variable still overrides everything.
12
+
13
+ ### New
14
+
15
+ - `incr` / `decr` counters
16
+ - `history` of previous values (last 20 per key); `list --long` shows type and update time
17
+ - Namespaces: `-n <name>`, `LKV_NAMESPACE`, `lkv namespaces`
18
+ - `lkv init` for per-project stores
19
+ - `search`, `list --filter`
20
+ - `rename`
21
+ - `export` / `import` (handles UTF-16 files from Windows PowerShell's `>`)
22
+ - `env` (sh, PowerShell, cmd) and `run <command>`
23
+ - `get --copy` to copy a value to the clipboard, `get --json`
24
+ - `--version`
25
+
26
+ ## 1.0.0
27
+
28
+ - First release: `set`, `get`, `update`, `delete`, `list`, `clear`, `path`
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # local-kv-cli
2
2
 
3
- A tiny, zero-dependency CLI to store key-value pairs locally on your machine.
3
+ A tiny, zero-dependency CLI to store key-value pairs locally on your machine, with typed values, counters, history, namespaces, per-project stores and environment variable export.
4
4
 
5
5
  ## Install
6
6
 
@@ -8,32 +8,140 @@ A tiny, zero-dependency CLI to store key-value pairs locally on your machine.
8
8
  npm install -g local-kv-cli
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Basics
12
12
 
13
13
  ```bash
14
14
  lkv set api_url https://example.com # create a pair
15
15
  lkv get api_url # print a value
16
16
  lkv update api_url https://new.com # change an existing value
17
- lkv list # show all pairs (add --json for JSON)
18
- lkv delete api_url # remove a pair
19
- lkv clear # remove everything
20
- lkv path # show where data is stored
17
+ lkv rename api_url base_url # rename a key
18
+ lkv delete base_url # remove a pair
19
+ lkv list # show all pairs
20
+ lkv clear # remove everything in the namespace
21
21
  ```
22
22
 
23
23
  `set` won't overwrite an existing key; use `update`, or `set <key> <value> --force`.
24
24
 
25
- Data is stored in `~/.local-kv/store.json`. Set `LKV_STORE_PATH` to use a different file.
25
+ ## Typed values
26
+
27
+ Numbers, `true`/`false` and JSON are stored with their type:
28
+
29
+ ```bash
30
+ lkv set retries 3 # number
31
+ lkv set debug true # boolean
32
+ lkv set config '{"port":8080}' # JSON
33
+ lkv set zip 02134 # stays text (leading zero)
34
+ lkv set -t string code 42 # force a type: string, number, boolean or json
35
+ lkv get config --json # print as JSON
36
+ ```
37
+
38
+ ## Counters
39
+
40
+ ```bash
41
+ lkv incr build_count # 1 (missing keys start at 0)
42
+ lkv incr build_count 10 # 11
43
+ lkv decr build_count # 10
44
+ ```
45
+
46
+ ## History and details
47
+
48
+ Every change keeps the previous value (the last 20 per key).
49
+
50
+ ```bash
51
+ lkv history retries # current value first, then older ones
52
+ lkv list --long # type and last update time for each key
53
+ ```
54
+
55
+ ## Search
56
+
57
+ ```bash
58
+ lkv search example # key or value contains "example"
59
+ lkv list --filter api # key contains "api"
60
+ lkv list --json # everything as JSON
61
+ ```
62
+
63
+ ## Namespaces
64
+
65
+ Keep separate groups of values:
66
+
67
+ ```bash
68
+ lkv -n work set token abc123
69
+ lkv -n work list
70
+ lkv namespaces # list namespaces and how many keys each has
71
+ ```
72
+
73
+ You can also set the `LKV_NAMESPACE` environment variable.
74
+
75
+ ## Per-project stores
76
+
77
+ ```bash
78
+ cd my-project
79
+ lkv init # creates .lkv.json here
80
+ lkv set port 3000
81
+ ```
82
+
83
+ Inside that folder (and its subfolders) `lkv` uses the project's `.lkv.json`. Add `--global` (`-g`) to use your global store instead. Add `.lkv.json` to `.gitignore` if it holds private values.
84
+
85
+ `lkv path` shows which file is in use.
86
+
87
+ ## Environment variables
88
+
89
+ ```bash
90
+ eval "$(lkv env)" # bash / zsh
91
+ lkv env | Invoke-Expression # PowerShell
92
+ lkv env --shell cmd # cmd.exe syntax
93
+ lkv env --upper # API_URL instead of api_url
94
+
95
+ lkv run npm start # run a command with your values as env variables
96
+ ```
97
+
98
+ Keys that aren't valid variable names (like `my-key`) are skipped with a warning.
99
+
100
+ ## Backup and restore
101
+
102
+ ```bash
103
+ lkv export backup.json # current namespace
104
+ lkv export backup.json --all # every namespace
105
+ lkv import backup.json # skips keys that already exist
106
+ lkv import backup.json --force # overwrite them
107
+ ```
108
+
109
+ `import` also accepts a plain `{ "key": "value" }` JSON object.
110
+
111
+ ## Clipboard
112
+
113
+ ```bash
114
+ lkv get api_url --copy
115
+ ```
116
+
117
+ On Linux this needs `wl-clipboard`, `xclip` or `xsel`.
118
+
119
+ ## Where data is stored
120
+
121
+ 1. The file in the `LKV_STORE_PATH` environment variable, if set
122
+ 2. Otherwise a `.lkv.json` in the current folder or a parent folder
123
+ 3. Otherwise `~/.local-kv/store.json`
26
124
 
27
125
  ## Use from code
28
126
 
29
127
  ```ts
30
128
  import { Store } from "local-kv-cli";
31
129
 
32
- const store = new Store();
33
- store.set("visits", "1");
34
- store.get("visits"); // "1"
130
+ const store = new Store(); // same lookup as the CLI
131
+ const work = new Store({ namespace: "work" });
132
+ const custom = new Store({ path: "./data.json" });
133
+
134
+ store.set("visits", 0);
135
+ store.incr("visits"); // 1
136
+ store.get("visits"); // 1
137
+ store.history("visits"); // [{ value: 0, type: "number", updated: "..." }]
138
+ store.entry("visits"); // value, type, created, updated, history
35
139
  ```
36
140
 
141
+ ## Upgrading from 1.x
142
+
143
+ Your data is upgraded automatically the first time 2.x runs, and a copy of the old file is saved next to it as `store.json.v1-backup`. See [CHANGELOG.md](CHANGELOG.md) for breaking changes.
144
+
37
145
  ## License
38
146
 
39
147
  MIT
package/dist/args.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export interface ParsedArgs {
2
+ command?: string;
3
+ args: string[];
4
+ options: Record<string, string | undefined>;
5
+ flags: Set<string>;
6
+ }
7
+ export declare function parseArgs(argv: string[]): ParsedArgs;
package/dist/args.js ADDED
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseArgs = parseArgs;
4
+ /** Flags that take a value, with their short aliases. */
5
+ const VALUE_FLAGS = {
6
+ "--namespace": "namespace",
7
+ "-n": "namespace",
8
+ "--type": "type",
9
+ "-t": "type",
10
+ "--filter": "filter",
11
+ "--shell": "shell",
12
+ };
13
+ /** On/off flags, with their short aliases. */
14
+ const BOOL_FLAGS = {
15
+ "--force": "force",
16
+ "-f": "force",
17
+ "--json": "json",
18
+ "--long": "long",
19
+ "-l": "long",
20
+ "--copy": "copy",
21
+ "-c": "copy",
22
+ "--all": "all",
23
+ "--global": "global",
24
+ "-g": "global",
25
+ "--upper": "upper",
26
+ "--help": "help",
27
+ "-h": "help",
28
+ "--version": "version",
29
+ "-v": "version",
30
+ };
31
+ /** Negative numbers ("-5") are values, not flags. */
32
+ function isFlag(token) {
33
+ return token.startsWith("-") && token !== "-" && !/^-\d/.test(token);
34
+ }
35
+ function parseArgs(argv) {
36
+ const parsed = { args: [], options: {}, flags: new Set() };
37
+ for (let i = 0; i < argv.length; i++) {
38
+ const token = argv[i];
39
+ if (token === "--") {
40
+ parsed.args.push(...argv.slice(i + 1));
41
+ break;
42
+ }
43
+ // Everything after `run`'s first word belongs to the command being run.
44
+ if (parsed.command === "run" && parsed.args.length > 0) {
45
+ parsed.args.push(...argv.slice(i));
46
+ break;
47
+ }
48
+ if (!isFlag(token)) {
49
+ if (parsed.command === undefined)
50
+ parsed.command = token;
51
+ else
52
+ parsed.args.push(token);
53
+ continue;
54
+ }
55
+ const eq = token.indexOf("=");
56
+ const name = eq === -1 ? token : token.slice(0, eq);
57
+ if (name in VALUE_FLAGS) {
58
+ const value = eq === -1 ? argv[++i] : token.slice(eq + 1);
59
+ if (value === undefined)
60
+ throw new Error(`${name} needs a value`);
61
+ parsed.options[VALUE_FLAGS[name]] = value;
62
+ }
63
+ else if (name in BOOL_FLAGS && eq === -1) {
64
+ parsed.flags.add(BOOL_FLAGS[name]);
65
+ }
66
+ else {
67
+ throw new Error(`Unknown option "${token}". Run "lkv help".`);
68
+ }
69
+ }
70
+ return parsed;
71
+ }
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { Store } from "./store";
3
- export declare function run(argv: string[], store?: Store): void;
2
+ /** Runs the CLI and returns the exit code. */
3
+ export declare function main(argv: string[]): number;