@lifestreamdynamics/vault-cli 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  A powerful command-line interface for Lifestream Vault - the multi-user Markdown document storage service with WebDAV sync, search, and collaboration features.
4
4
 
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
- [![npm version](https://img.shields.io/npm/v/@lifestream-vault/cli.svg)](https://www.npmjs.com/package/@lifestream-vault/cli)
6
+ [![npm version](https://img.shields.io/npm/v/@lifestreamdynamics/vault-cli.svg)](https://www.npmjs.com/package/@lifestreamdynamics/vault-cli)
7
7
 
8
8
  ## 📖 Table of Contents
9
9
 
@@ -49,14 +49,14 @@ A powerful command-line interface for Lifestream Vault - the multi-user Markdown
49
49
  - **🛡️ Admin Tools** - User management, system stats, and audit logs (admin only)
50
50
  - **⚙️ Flexible Configuration** - Multiple profiles, environment variable support, and configurable sync behavior
51
51
  - **🌐 Offline Support** - Work offline and sync when reconnected
52
- - **📦 TypeScript SDK** - Built on `@lifestream-vault/sdk` with full type safety
52
+ - **📦 TypeScript SDK** - Built on `@lifestreamdynamics/vault-sdk` with full type safety
53
53
 
54
54
  ## 📦 Installation
55
55
 
56
56
  ### Global Installation (Recommended)
57
57
 
58
58
  ```bash
59
- npm install -g @lifestream-vault/cli
59
+ npm install -g @lifestreamdynamics/vault-cli
60
60
  ```
61
61
 
62
62
  After installation, the `lsvault` command will be available globally:
@@ -68,7 +68,7 @@ lsvault --help
68
68
  ### Local Installation (Project-Specific)
69
69
 
70
70
  ```bash
71
- npm install @lifestream-vault/cli
71
+ npm install @lifestreamdynamics/vault-cli
72
72
 
73
73
  # Run with npx
74
74
  npx lsvault --help
@@ -98,7 +98,7 @@ lsvault auth login --api-key lsv_k_your_api_key_here
98
98
  lsvault auth login --email user@example.com
99
99
 
100
100
  # Set a custom API URL (optional)
101
- lsvault auth login --api-key lsv_k_your_key --api-url https://vault.example.com
101
+ lsvault auth login --api-key lsv_k_your_key --api-url https://vault.lifestreamdynamics.com
102
102
  ```
103
103
 
104
104
  ### 2. List Your Vaults
@@ -474,12 +474,14 @@ The CLI stores configuration in `~/.lsvault/config.json`:
474
474
 
475
475
  ```json
476
476
  {
477
- "apiUrl": "http://localhost:4660"
477
+ "apiUrl": "https://vault.lifestreamdynamics.com"
478
478
  }
479
479
  ```
480
480
 
481
481
  **Note:** Credentials are stored securely in the system keychain (or encrypted file fallback), not in the plaintext config file.
482
482
 
483
+ > **Self-hosting?** Replace `https://vault.lifestreamdynamics.com` with your server's URL, or set the `LSVAULT_API_URL` environment variable.
484
+
483
485
  ### Configuration Profiles
484
486
 
485
487
  Manage multiple configurations with profiles:
@@ -489,13 +491,13 @@ Manage multiple configurations with profiles:
489
491
  lsvault config profiles
490
492
 
491
493
  # Create a profile
492
- lsvault config create-profile production --api-url https://vault.example.com
494
+ lsvault config create-profile production --api-url https://vault.lifestreamdynamics.com
493
495
 
494
496
  # Switch profiles
495
497
  lsvault config use production
496
498
 
497
499
  # Set config values
498
- lsvault config set apiUrl https://vault.example.com
500
+ lsvault config set apiUrl https://vault.lifestreamdynamics.com
499
501
 
500
502
  # Get config values
501
503
  lsvault config get apiUrl
@@ -522,14 +524,14 @@ Sync configurations are stored per vault in `~/.lsvault/sync/`:
522
524
 
523
525
  | Variable | Description | Default |
524
526
  |----------|-------------|---------|
525
- | `LSVAULT_API_URL` | API server base URL | `http://localhost:4660` |
527
+ | `LSVAULT_API_URL` | API server base URL | `https://vault.lifestreamdynamics.com` |
526
528
  | `LSVAULT_API_KEY` | API key for authentication | - |
527
529
  | `LSVAULT_CONFIG_DIR` | Configuration directory | `~/.lsvault` |
528
530
  | `LSVAULT_PROFILE` | Active configuration profile | `default` |
529
531
 
530
532
  **Example:**
531
533
  ```bash
532
- export LSVAULT_API_URL=https://vault.example.com
534
+ export LSVAULT_API_URL=https://vault.lifestreamdynamics.com
533
535
  export LSVAULT_API_KEY=lsv_k_your_key_here
534
536
  lsvault vaults list
535
537
  ```
@@ -718,7 +720,7 @@ lsvault auth migrate
718
720
  1. Verify API URL is correct: `lsvault config get apiUrl`
719
721
  2. Test connectivity: `curl <API_URL>/api/v1/health`
720
722
  3. Check firewall/proxy settings
721
- 4. Use custom API URL: `lsvault auth login --api-url https://vault.example.com`
723
+ 4. Use custom API URL: `lsvault auth login --api-url https://vault.lifestreamdynamics.com`
722
724
 
723
725
  ### Output Format Issues
724
726
 
@@ -733,9 +735,9 @@ lsvault docs get vault_abc123 /path.md --quiet > output.md
733
735
 
734
736
  ## 🔗 Related Packages
735
737
 
736
- - **[@lifestream-vault/sdk](https://npmjs.com/package/@lifestream-vault/sdk)** - TypeScript SDK for Lifestream Vault API
737
- - **[@lifestream-vault/api](https://github.com/lifestreamdynamics/lifestream-vault)** - Backend API server
738
- - **[@lifestream-vault/web](https://github.com/lifestreamdynamics/lifestream-vault)** - Web frontend
738
+ - **[@lifestreamdynamics/vault-sdk](https://npmjs.com/package/@lifestreamdynamics/vault-sdk)** - TypeScript SDK for Lifestream Vault API
739
+ - **[@lifestreamdynamics/vault-api](https://github.com/lifestreamdynamics/lifestream-vault)** - Backend API server
740
+ - **[@lifestreamdynamics/vault-web](https://github.com/lifestreamdynamics/lifestream-vault)** - Web frontend
739
741
 
740
742
  ## 📄 Documentation
741
743
 
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  import { formatBytes, formatUptime } from '../utils/format.js';
@@ -12,7 +12,7 @@ export function registerAdminCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching system stats...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const data = await client.admin.getStats();
17
17
  out.stopSpinner();
18
18
  out.record({
@@ -41,7 +41,7 @@ export function registerAdminCommands(program) {
41
41
  const out = createOutput(flags);
42
42
  out.startSpinner('Fetching timeseries data...');
43
43
  try {
44
- const client = getClient();
44
+ const client = await getClientAsync();
45
45
  const data = await client.admin.getTimeseries(String(_opts.metric), String(_opts.period));
46
46
  out.stopSpinner();
47
47
  if (flags.output === 'text') {
@@ -79,7 +79,7 @@ export function registerAdminCommands(program) {
79
79
  const out = createOutput(flags);
80
80
  out.startSpinner('Fetching users...');
81
81
  try {
82
- const client = getClient();
82
+ const client = await getClientAsync();
83
83
  const result = await client.admin.listUsers({
84
84
  page: _opts.page,
85
85
  limit: _opts.limit,
@@ -125,7 +125,7 @@ export function registerAdminCommands(program) {
125
125
  const out = createOutput(flags);
126
126
  out.startSpinner('Fetching user...');
127
127
  try {
128
- const client = getClient();
128
+ const client = await getClientAsync();
129
129
  const user = await client.admin.getUser(userId);
130
130
  out.stopSpinner();
131
131
  out.record({
@@ -169,7 +169,7 @@ export function registerAdminCommands(program) {
169
169
  }
170
170
  out.startSpinner('Updating user...');
171
171
  try {
172
- const client = getClient();
172
+ const client = await getClientAsync();
173
173
  const updated = await client.admin.updateUser(userId, params);
174
174
  out.success(`User updated: ${chalk.cyan(updated.email)} -- ${chalk.magenta(updated.role)} -- ${updated.isActive ? chalk.green('active') : chalk.red('inactive')}`, {
175
175
  email: updated.email,
@@ -190,7 +190,7 @@ export function registerAdminCommands(program) {
190
190
  const out = createOutput(flags);
191
191
  out.startSpinner('Fetching activity...');
192
192
  try {
193
- const client = getClient();
193
+ const client = await getClientAsync();
194
194
  const activity = await client.admin.getActivity(_opts.limit);
195
195
  out.stopSpinner();
196
196
  out.list(activity.map(a => ({
@@ -224,7 +224,7 @@ export function registerAdminCommands(program) {
224
224
  const out = createOutput(flags);
225
225
  out.startSpinner('Fetching subscription summary...');
226
226
  try {
227
- const client = getClient();
227
+ const client = await getClientAsync();
228
228
  const summary = await client.admin.getSubscriptionSummary();
229
229
  out.stopSpinner();
230
230
  out.record({
@@ -246,7 +246,7 @@ export function registerAdminCommands(program) {
246
246
  const out = createOutput(flags);
247
247
  out.startSpinner('Checking system health...');
248
248
  try {
249
- const client = getClient();
249
+ const client = await getClientAsync();
250
250
  const health = await client.admin.getHealth();
251
251
  out.stopSpinner();
252
252
  out.record({
@@ -2,7 +2,7 @@ import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
  import { LifestreamVaultClient } from '@lifestreamdynamics/vault-sdk';
4
4
  import { loadConfigAsync, getCredentialManager } from '../config.js';
5
- import { getClient } from '../client.js';
5
+ import { getClientAsync } from '../client.js';
6
6
  import { migrateCredentials, hasPlaintextCredentials, checkAndPromptMigration } from '../lib/migration.js';
7
7
  export function registerAuthCommands(program) {
8
8
  const auth = program.command('auth').description('Authentication and credential management');
@@ -11,7 +11,7 @@ export function registerAuthCommands(program) {
11
11
  .option('--api-key <key>', 'API key (lsv_k_... prefix)')
12
12
  .option('--email <email>', 'Email address for password login')
13
13
  .option('--password <password>', 'Password (prompts interactively if omitted)')
14
- .option('--api-url <url>', 'API server URL (default: http://localhost:4660)')
14
+ .option('--api-url <url>', 'API server URL (default: https://vault.lifestreamdynamics.com)')
15
15
  .addHelpText('after', `
16
16
  EXAMPLES
17
17
  lsvault auth login --api-key lsv_k_abc123
@@ -179,7 +179,7 @@ EXAMPLES
179
179
  if (config.apiKey || config.accessToken) {
180
180
  const spinner = ora('Fetching user info...').start();
181
181
  try {
182
- const client = getClient();
182
+ const client = await getClientAsync();
183
183
  const user = await client.user.me();
184
184
  spinner.stop();
185
185
  console.log(`User: ${chalk.cyan(user.email)}`);
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerConnectorCommands(program) {
@@ -12,7 +12,7 @@ export function registerConnectorCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching connectors...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const connectorList = await client.connectors.list(_opts.vault);
17
17
  out.stopSpinner();
18
18
  out.list(connectorList.map(c => ({
@@ -48,7 +48,7 @@ export function registerConnectorCommands(program) {
48
48
  const out = createOutput(flags);
49
49
  out.startSpinner('Fetching connector...');
50
50
  try {
51
- const client = getClient();
51
+ const client = await getClientAsync();
52
52
  const c = await client.connectors.get(connectorId);
53
53
  out.stopSpinner();
54
54
  out.record({
@@ -81,7 +81,7 @@ export function registerConnectorCommands(program) {
81
81
  const out = createOutput(flags);
82
82
  out.startSpinner('Creating connector...');
83
83
  try {
84
- const client = getClient();
84
+ const client = await getClientAsync();
85
85
  const connector = await client.connectors.create({
86
86
  provider: provider,
87
87
  name,
@@ -109,7 +109,7 @@ export function registerConnectorCommands(program) {
109
109
  const out = createOutput(flags);
110
110
  out.startSpinner('Updating connector...');
111
111
  try {
112
- const client = getClient();
112
+ const client = await getClientAsync();
113
113
  const params = {};
114
114
  if (_opts.name)
115
115
  params.name = _opts.name;
@@ -133,7 +133,7 @@ export function registerConnectorCommands(program) {
133
133
  const out = createOutput(flags);
134
134
  out.startSpinner('Deleting connector...');
135
135
  try {
136
- const client = getClient();
136
+ const client = await getClientAsync();
137
137
  await client.connectors.delete(connectorId);
138
138
  out.success('Connector deleted.', { id: connectorId, deleted: true });
139
139
  }
@@ -149,7 +149,7 @@ export function registerConnectorCommands(program) {
149
149
  const out = createOutput(flags);
150
150
  out.startSpinner('Testing connection...');
151
151
  try {
152
- const client = getClient();
152
+ const client = await getClientAsync();
153
153
  const result = await client.connectors.test(connectorId);
154
154
  if (result.success) {
155
155
  out.success('Connection test passed.', { success: true });
@@ -174,7 +174,7 @@ export function registerConnectorCommands(program) {
174
174
  const out = createOutput(flags);
175
175
  out.startSpinner('Triggering sync...');
176
176
  try {
177
- const client = getClient();
177
+ const client = await getClientAsync();
178
178
  const result = await client.connectors.sync(connectorId);
179
179
  out.success(result.message, { message: result.message });
180
180
  }
@@ -190,7 +190,7 @@ export function registerConnectorCommands(program) {
190
190
  const out = createOutput(flags);
191
191
  out.startSpinner('Fetching sync logs...');
192
192
  try {
193
- const client = getClient();
193
+ const client = await getClientAsync();
194
194
  const logs = await client.connectors.logs(connectorId);
195
195
  out.stopSpinner();
196
196
  out.list(logs.map(log => ({
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  import { createCredentialManager } from '../lib/credential-manager.js';
@@ -18,7 +18,7 @@ EXAMPLES
18
18
  const out = createOutput(flags);
19
19
  out.startSpinner('Fetching documents...');
20
20
  try {
21
- const client = getClient();
21
+ const client = await getClientAsync();
22
22
  const documents = await client.documents.list(vaultId, _opts.dir);
23
23
  out.stopSpinner();
24
24
  out.list(documents.map(doc => ({
@@ -62,7 +62,7 @@ EXAMPLES
62
62
  const flags = resolveFlags(_opts);
63
63
  const out = createOutput(flags);
64
64
  try {
65
- const client = getClient();
65
+ const client = await getClientAsync();
66
66
  const result = await client.documents.get(vaultId, docPath);
67
67
  // Auto-decrypt if the document is encrypted
68
68
  if (result.document.encrypted && !_opts.meta) {
@@ -119,7 +119,7 @@ EXAMPLES
119
119
  process.stdin.on('end', () => resolve(data));
120
120
  });
121
121
  out.startSpinner('Uploading document...');
122
- const client = getClient();
122
+ const client = await getClientAsync();
123
123
  // Check if vault is encrypted and auto-encrypt
124
124
  const vault = await client.vaults.get(vaultId);
125
125
  let doc;
@@ -157,7 +157,7 @@ EXAMPLES
157
157
  const out = createOutput(flags);
158
158
  out.startSpinner('Deleting document...');
159
159
  try {
160
- const client = getClient();
160
+ const client = await getClientAsync();
161
161
  await client.documents.delete(vaultId, docPath);
162
162
  out.success(`Deleted: ${chalk.cyan(docPath)}`, { path: docPath, deleted: true });
163
163
  }
@@ -180,7 +180,7 @@ EXAMPLES
180
180
  const out = createOutput(flags);
181
181
  out.startSpinner('Moving document...');
182
182
  try {
183
- const client = getClient();
183
+ const client = await getClientAsync();
184
184
  const result = await client.documents.move(vaultId, source, dest, _opts.overwrite);
185
185
  out.success(`Moved: ${chalk.cyan(result.source)} -> ${chalk.cyan(result.destination)}`, {
186
186
  source: result.source,
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerHookCommands(program) {
@@ -12,7 +12,7 @@ export function registerHookCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching hooks...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const hookList = await client.hooks.list(vaultId);
17
17
  out.stopSpinner();
18
18
  out.list(hookList.map(hook => ({
@@ -76,7 +76,7 @@ export function registerHookCommands(program) {
76
76
  }
77
77
  out.startSpinner('Creating hook...');
78
78
  try {
79
- const client = getClient();
79
+ const client = await getClientAsync();
80
80
  const params = {
81
81
  name,
82
82
  triggerEvent: String(_opts.trigger),
@@ -106,7 +106,7 @@ export function registerHookCommands(program) {
106
106
  const out = createOutput(flags);
107
107
  out.startSpinner('Deleting hook...');
108
108
  try {
109
- const client = getClient();
109
+ const client = await getClientAsync();
110
110
  await client.hooks.delete(vaultId, hookId);
111
111
  out.success('Hook deleted successfully', { id: hookId, deleted: true });
112
112
  }
@@ -123,7 +123,7 @@ export function registerHookCommands(program) {
123
123
  const out = createOutput(flags);
124
124
  out.startSpinner('Fetching executions...');
125
125
  try {
126
- const client = getClient();
126
+ const client = await getClientAsync();
127
127
  const executions = await client.hooks.listExecutions(vaultId, hookId);
128
128
  out.stopSpinner();
129
129
  out.list(executions.map(exec => ({
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerKeyCommands(program) {
@@ -11,7 +11,7 @@ export function registerKeyCommands(program) {
11
11
  const out = createOutput(flags);
12
12
  out.startSpinner('Fetching API keys...');
13
13
  try {
14
- const client = getClient();
14
+ const client = await getClientAsync();
15
15
  const apiKeys = await client.apiKeys.list();
16
16
  out.stopSpinner();
17
17
  out.list(apiKeys.map(key => ({
@@ -54,7 +54,7 @@ export function registerKeyCommands(program) {
54
54
  const out = createOutput(flags);
55
55
  out.startSpinner('Fetching API key...');
56
56
  try {
57
- const client = getClient();
57
+ const client = await getClientAsync();
58
58
  const key = await client.apiKeys.get(keyId);
59
59
  out.stopSpinner();
60
60
  out.record({
@@ -89,7 +89,7 @@ EXAMPLES
89
89
  const out = createOutput(flags);
90
90
  out.startSpinner('Creating API key...');
91
91
  try {
92
- const client = getClient();
92
+ const client = await getClientAsync();
93
93
  const params = {
94
94
  name,
95
95
  scopes: String(_opts.scopes || 'read,write').split(',').map((s) => s.trim()),
@@ -131,7 +131,7 @@ EXAMPLES
131
131
  }
132
132
  out.startSpinner('Updating API key...');
133
133
  try {
134
- const client = getClient();
134
+ const client = await getClientAsync();
135
135
  const params = {};
136
136
  if (_opts.name)
137
137
  params.name = String(_opts.name);
@@ -154,7 +154,7 @@ EXAMPLES
154
154
  const out = createOutput(flags);
155
155
  out.startSpinner('Revoking API key...');
156
156
  try {
157
- const client = getClient();
157
+ const client = await getClientAsync();
158
158
  await client.apiKeys.delete(keyId);
159
159
  out.success('API key revoked successfully', { id: keyId, revoked: true });
160
160
  }
@@ -1,4 +1,4 @@
1
- import { getClient } from '../client.js';
1
+ import { getClientAsync } from '../client.js';
2
2
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
3
3
  import { createOutput, handleError } from '../utils/output.js';
4
4
  import chalk from 'chalk';
@@ -12,7 +12,7 @@ export function registerPublishCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching published documents...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const docs = await client.publish.listMine(vaultId);
17
17
  out.stopSpinner();
18
18
  out.list(docs.map(doc => ({
@@ -60,7 +60,7 @@ export function registerPublishCommands(program) {
60
60
  const out = createOutput(flags);
61
61
  out.startSpinner('Publishing document...');
62
62
  try {
63
- const client = getClient();
63
+ const client = await getClientAsync();
64
64
  const params = {
65
65
  slug: String(_opts.slug),
66
66
  };
@@ -96,7 +96,7 @@ export function registerPublishCommands(program) {
96
96
  const out = createOutput(flags);
97
97
  out.startSpinner('Updating published document...');
98
98
  try {
99
- const client = getClient();
99
+ const client = await getClientAsync();
100
100
  const params = {
101
101
  slug: String(_opts.slug),
102
102
  };
@@ -127,7 +127,7 @@ export function registerPublishCommands(program) {
127
127
  const out = createOutput(flags);
128
128
  out.startSpinner('Unpublishing document...');
129
129
  try {
130
- const client = getClient();
130
+ const client = await getClientAsync();
131
131
  await client.publish.delete(vaultId, docPath);
132
132
  out.success('Document unpublished successfully', { path: docPath, unpublished: true });
133
133
  }
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerSearchCommands(program) {
@@ -19,7 +19,7 @@ EXAMPLES
19
19
  const out = createOutput(flags);
20
20
  out.startSpinner('Searching...');
21
21
  try {
22
- const client = getClient();
22
+ const client = await getClientAsync();
23
23
  const response = await client.search.search({
24
24
  q: query,
25
25
  vault: _opts.vault,
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerShareCommands(program) {
@@ -13,7 +13,7 @@ export function registerShareCommands(program) {
13
13
  const out = createOutput(flags);
14
14
  out.startSpinner('Fetching share links...');
15
15
  try {
16
- const client = getClient();
16
+ const client = await getClientAsync();
17
17
  const links = await client.shares.list(vaultId, docPath);
18
18
  out.stopSpinner();
19
19
  out.list(links.map(link => ({
@@ -63,7 +63,7 @@ export function registerShareCommands(program) {
63
63
  const out = createOutput(flags);
64
64
  out.startSpinner('Creating share link...');
65
65
  try {
66
- const client = getClient();
66
+ const client = await getClientAsync();
67
67
  const params = {};
68
68
  if (_opts.permission)
69
69
  params.permission = String(_opts.permission);
@@ -110,7 +110,7 @@ export function registerShareCommands(program) {
110
110
  const out = createOutput(flags);
111
111
  out.startSpinner('Revoking share link...');
112
112
  try {
113
- const client = getClient();
113
+ const client = await getClientAsync();
114
114
  await client.shares.revoke(vaultId, shareId);
115
115
  out.success('Share link revoked successfully', { id: shareId, revoked: true });
116
116
  }
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  import { formatBytes } from '../utils/format.js';
@@ -12,7 +12,7 @@ export function registerSubscriptionCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching subscription...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const data = await client.subscription.get();
17
17
  out.stopSpinner();
18
18
  if (flags.output === 'json') {
@@ -49,7 +49,7 @@ export function registerSubscriptionCommands(program) {
49
49
  const out = createOutput(flags);
50
50
  out.startSpinner('Fetching plans...');
51
51
  try {
52
- const client = getClient();
52
+ const client = await getClientAsync();
53
53
  const plans = await client.subscription.listPlans();
54
54
  out.stopSpinner();
55
55
  out.list(plans.map(p => ({ name: p.name, tier: p.tier, ...p.limits })), {
@@ -85,7 +85,7 @@ EXAMPLES
85
85
  const out = createOutput(flags);
86
86
  out.startSpinner('Creating checkout session...');
87
87
  try {
88
- const client = getClient();
88
+ const client = await getClientAsync();
89
89
  const session = await client.subscription.createCheckoutSession(tier, String(_opts.returnUrl));
90
90
  out.success('Checkout session created', { url: session.url });
91
91
  if (flags.output === 'text') {
@@ -104,7 +104,7 @@ EXAMPLES
104
104
  const out = createOutput(flags);
105
105
  out.startSpinner('Cancelling subscription...');
106
106
  try {
107
- const client = getClient();
107
+ const client = await getClientAsync();
108
108
  await client.subscription.cancel(_opts.reason);
109
109
  out.success('Subscription cancelled', { cancelled: true });
110
110
  }
@@ -120,7 +120,7 @@ EXAMPLES
120
120
  const out = createOutput(flags);
121
121
  out.startSpinner('Creating portal session...');
122
122
  try {
123
- const client = getClient();
123
+ const client = await getClientAsync();
124
124
  const portal = await client.subscription.createPortalSession(String(_opts.returnUrl));
125
125
  out.success('Portal session created', { url: portal.url });
126
126
  if (flags.output === 'text') {
@@ -138,7 +138,7 @@ EXAMPLES
138
138
  const out = createOutput(flags);
139
139
  out.startSpinner('Fetching invoices...');
140
140
  try {
141
- const client = getClient();
141
+ const client = await getClientAsync();
142
142
  const invoices = await client.subscription.listInvoices();
143
143
  out.stopSpinner();
144
144
  out.list(invoices.map(inv => ({
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import chalk from 'chalk';
4
- import { getClient } from '../client.js';
4
+ import { getClientAsync } from '../client.js';
5
5
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
6
6
  import { createOutput, handleError } from '../utils/output.js';
7
7
  import { formatUptime } from '../utils/format.js';
@@ -30,7 +30,7 @@ export function registerSyncCommands(program) {
30
30
  const out = createOutput(flags);
31
31
  out.startSpinner('Initializing sync...');
32
32
  try {
33
- const client = getClient();
33
+ const client = await getClientAsync();
34
34
  const vault = await client.vaults.get(vaultId);
35
35
  const absPath = path.resolve(localPath);
36
36
  const mode = _opts.mode ?? 'sync';
@@ -144,7 +144,7 @@ export function registerSyncCommands(program) {
144
144
  process.exitCode = 1;
145
145
  return;
146
146
  }
147
- const client = getClient();
147
+ const client = await getClientAsync();
148
148
  const ignorePatterns = resolveIgnorePatterns(config.ignore, config.localPath);
149
149
  const lastState = loadSyncState(config.id);
150
150
  out.startSpinner('Scanning local files...');
@@ -220,7 +220,7 @@ export function registerSyncCommands(program) {
220
220
  process.exitCode = 1;
221
221
  return;
222
222
  }
223
- const client = getClient();
223
+ const client = await getClientAsync();
224
224
  const ignorePatterns = resolveIgnorePatterns(config.ignore, config.localPath);
225
225
  const lastState = loadSyncState(config.id);
226
226
  out.startSpinner('Scanning local files...');
@@ -296,7 +296,7 @@ export function registerSyncCommands(program) {
296
296
  process.exitCode = 1;
297
297
  return;
298
298
  }
299
- const client = getClient();
299
+ const client = await getClientAsync();
300
300
  const ignorePatterns = resolveIgnorePatterns(config.ignore, config.localPath);
301
301
  const lastState = loadSyncState(config.id);
302
302
  out.startSpinner('Scanning...');
@@ -373,7 +373,7 @@ export function registerSyncCommands(program) {
373
373
  process.exitCode = 1;
374
374
  return;
375
375
  }
376
- const client = getClient();
376
+ const client = await getClientAsync();
377
377
  const ignorePatterns = resolveIgnorePatterns(config.ignore, config.localPath);
378
378
  const pollInterval = parseInt(String(_opts.pollInterval ?? '30000'), 10);
379
379
  out.status(`Watching sync ${chalk.cyan(syncId.slice(0, 8))}...`);
@@ -447,7 +447,7 @@ export function registerSyncCommands(program) {
447
447
  process.exitCode = 1;
448
448
  return;
449
449
  }
450
- const client = getClient();
450
+ const client = await getClientAsync();
451
451
  const localFile = path.join(config.localPath, docPath);
452
452
  const state = loadSyncState(config.id);
453
453
  if (useVersion === 'local') {
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerTeamCommands(program) {
@@ -12,7 +12,7 @@ export function registerTeamCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching teams...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const teamList = await client.teams.list();
17
17
  out.stopSpinner();
18
18
  out.list(teamList.map(t => ({ name: t.name, id: t.id, description: t.description || 'No description' })), {
@@ -37,7 +37,7 @@ export function registerTeamCommands(program) {
37
37
  const out = createOutput(flags);
38
38
  out.startSpinner('Fetching team...');
39
39
  try {
40
- const client = getClient();
40
+ const client = await getClientAsync();
41
41
  const team = await client.teams.get(teamId);
42
42
  out.stopSpinner();
43
43
  out.record({
@@ -66,7 +66,7 @@ EXAMPLES
66
66
  const out = createOutput(flags);
67
67
  out.startSpinner('Creating team...');
68
68
  try {
69
- const client = getClient();
69
+ const client = await getClientAsync();
70
70
  const team = await client.teams.create({ name, description: _opts.description });
71
71
  out.success(`Team created: ${chalk.cyan(team.name)} (${team.id})`, { id: team.id, name: team.name });
72
72
  }
@@ -84,7 +84,7 @@ EXAMPLES
84
84
  const out = createOutput(flags);
85
85
  out.startSpinner('Updating team...');
86
86
  try {
87
- const client = getClient();
87
+ const client = await getClientAsync();
88
88
  const team = await client.teams.update(teamId, {
89
89
  name: _opts.name,
90
90
  description: _opts.description,
@@ -103,7 +103,7 @@ EXAMPLES
103
103
  const out = createOutput(flags);
104
104
  out.startSpinner('Deleting team...');
105
105
  try {
106
- const client = getClient();
106
+ const client = await getClientAsync();
107
107
  await client.teams.delete(teamId);
108
108
  out.success('Team deleted.', { id: teamId, deleted: true });
109
109
  }
@@ -121,7 +121,7 @@ EXAMPLES
121
121
  const out = createOutput(flags);
122
122
  out.startSpinner('Fetching members...');
123
123
  try {
124
- const client = getClient();
124
+ const client = await getClientAsync();
125
125
  const memberList = await client.teams.listMembers(teamId);
126
126
  out.stopSpinner();
127
127
  out.list(memberList.map(m => ({
@@ -154,7 +154,7 @@ EXAMPLES
154
154
  const role = String(_opts.role);
155
155
  out.startSpinner('Updating member role...');
156
156
  try {
157
- const client = getClient();
157
+ const client = await getClientAsync();
158
158
  const member = await client.teams.updateMemberRole(teamId, userId, role);
159
159
  out.success(`Role updated to ${chalk.magenta(member.role)} for ${member.user.email}`, {
160
160
  userId,
@@ -175,7 +175,7 @@ EXAMPLES
175
175
  const out = createOutput(flags);
176
176
  out.startSpinner('Removing member...');
177
177
  try {
178
- const client = getClient();
178
+ const client = await getClientAsync();
179
179
  await client.teams.removeMember(teamId, userId);
180
180
  out.success('Member removed.', { teamId, userId, removed: true });
181
181
  }
@@ -191,7 +191,7 @@ EXAMPLES
191
191
  const out = createOutput(flags);
192
192
  out.startSpinner('Leaving team...');
193
193
  try {
194
- const client = getClient();
194
+ const client = await getClientAsync();
195
195
  await client.teams.leave(teamId);
196
196
  out.success('Left the team.', { teamId, left: true });
197
197
  }
@@ -209,7 +209,7 @@ EXAMPLES
209
209
  const out = createOutput(flags);
210
210
  out.startSpinner('Fetching invitations...');
211
211
  try {
212
- const client = getClient();
212
+ const client = await getClientAsync();
213
213
  const invitationList = await client.teams.listInvitations(teamId);
214
214
  out.stopSpinner();
215
215
  out.list(invitationList.map(inv => ({
@@ -242,7 +242,7 @@ EXAMPLES
242
242
  const role = String(_opts.role);
243
243
  out.startSpinner('Sending invitation...');
244
244
  try {
245
- const client = getClient();
245
+ const client = await getClientAsync();
246
246
  const invitation = await client.teams.inviteMember(teamId, email, role);
247
247
  out.success(`Invited ${chalk.cyan(invitation.email)} as ${chalk.magenta(invitation.role)}`, {
248
248
  id: invitation.id,
@@ -263,7 +263,7 @@ EXAMPLES
263
263
  const out = createOutput(flags);
264
264
  out.startSpinner('Revoking invitation...');
265
265
  try {
266
- const client = getClient();
266
+ const client = await getClientAsync();
267
267
  await client.teams.revokeInvitation(teamId, invitationId);
268
268
  out.success('Invitation revoked.', { id: invitationId, revoked: true });
269
269
  }
@@ -281,7 +281,7 @@ EXAMPLES
281
281
  const out = createOutput(flags);
282
282
  out.startSpinner('Fetching team vaults...');
283
283
  try {
284
- const client = getClient();
284
+ const client = await getClientAsync();
285
285
  const vaultList = await client.teams.listVaults(teamId);
286
286
  out.stopSpinner();
287
287
  out.list(vaultList.map(v => ({ name: String(v.name), slug: String(v.slug), description: String(v.description) || 'No description' })), {
@@ -308,7 +308,7 @@ EXAMPLES
308
308
  const out = createOutput(flags);
309
309
  out.startSpinner('Creating team vault...');
310
310
  try {
311
- const client = getClient();
311
+ const client = await getClientAsync();
312
312
  const vault = await client.teams.createVault(teamId, { name, description: _opts.description });
313
313
  out.success(`Team vault created: ${chalk.cyan(String(vault.name))}`, {
314
314
  name: String(vault.name),
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  import { formatBytes } from '../utils/format.js';
@@ -12,7 +12,7 @@ export function registerUserCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching storage usage...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const storage = await client.user.getStorage();
17
17
  out.stopSpinner();
18
18
  if (flags.output === 'json') {
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  import { generateVaultKey } from '@lifestreamdynamics/vault-sdk';
@@ -13,7 +13,7 @@ export function registerVaultCommands(program) {
13
13
  const out = createOutput(flags);
14
14
  out.startSpinner('Fetching vaults...');
15
15
  try {
16
- const client = getClient();
16
+ const client = await getClientAsync();
17
17
  const vaultList = await client.vaults.list();
18
18
  out.stopSpinner();
19
19
  out.list(vaultList.map(v => ({ name: v.name, slug: v.slug, encrypted: v.encryptionEnabled ? 'yes' : 'no', description: v.description || 'No description', id: v.id })), {
@@ -43,7 +43,7 @@ export function registerVaultCommands(program) {
43
43
  const out = createOutput(flags);
44
44
  out.startSpinner('Fetching vault...');
45
45
  try {
46
- const client = getClient();
46
+ const client = await getClientAsync();
47
47
  const vault = await client.vaults.get(vaultId);
48
48
  out.stopSpinner();
49
49
  out.record({
@@ -75,7 +75,7 @@ EXAMPLES
75
75
  const out = createOutput(flags);
76
76
  out.startSpinner('Creating vault...');
77
77
  try {
78
- const client = getClient();
78
+ const client = await getClientAsync();
79
79
  const isEncrypted = _opts.encrypted === true;
80
80
  const vault = await client.vaults.create({
81
81
  name,
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerVersionCommands(program) {
@@ -16,7 +16,7 @@ EXAMPLES
16
16
  const out = createOutput(flags);
17
17
  out.startSpinner('Fetching versions...');
18
18
  try {
19
- const client = getClient();
19
+ const client = await getClientAsync();
20
20
  const versionList = await client.documents.listVersions(vaultId, docPath);
21
21
  out.stopSpinner();
22
22
  out.list(versionList.map(v => ({
@@ -65,7 +65,7 @@ EXAMPLES
65
65
  return;
66
66
  }
67
67
  try {
68
- const client = getClient();
68
+ const client = await getClientAsync();
69
69
  const version = await client.documents.getVersion(vaultId, docPath, versionNum);
70
70
  if (version.content === null) {
71
71
  out.error('Version content is no longer available (expired or pruned)');
@@ -99,7 +99,7 @@ EXAMPLES
99
99
  }
100
100
  out.startSpinner('Computing diff...');
101
101
  try {
102
- const client = getClient();
102
+ const client = await getClientAsync();
103
103
  const diff = await client.documents.diffVersions(vaultId, docPath, from, to);
104
104
  out.stopSpinner();
105
105
  if (flags.output === 'json') {
@@ -143,7 +143,7 @@ EXAMPLES
143
143
  }
144
144
  out.startSpinner(`Restoring to version ${versionNum}...`);
145
145
  try {
146
- const client = getClient();
146
+ const client = await getClientAsync();
147
147
  const doc = await client.documents.restoreVersion(vaultId, docPath, versionNum);
148
148
  out.success(`Restored ${chalk.cyan(docPath)} to version ${versionNum}`, {
149
149
  path: doc.path,
@@ -173,7 +173,7 @@ EXAMPLES
173
173
  }
174
174
  out.startSpinner(`Pinning version ${versionNum}...`);
175
175
  try {
176
- const client = getClient();
176
+ const client = await getClientAsync();
177
177
  await client.documents.pinVersion(vaultId, docPath, versionNum);
178
178
  out.success(`Pinned version ${versionNum} of ${chalk.cyan(docPath)}`, {
179
179
  path: docPath,
@@ -204,7 +204,7 @@ EXAMPLES
204
204
  }
205
205
  out.startSpinner(`Unpinning version ${versionNum}...`);
206
206
  try {
207
- const client = getClient();
207
+ const client = await getClientAsync();
208
208
  await client.documents.unpinVersion(vaultId, docPath, versionNum);
209
209
  out.success(`Unpinned version ${versionNum} of ${chalk.cyan(docPath)}`, {
210
210
  path: docPath,
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getClient } from '../client.js';
2
+ import { getClientAsync } from '../client.js';
3
3
  import { addGlobalFlags, resolveFlags } from '../utils/flags.js';
4
4
  import { createOutput, handleError } from '../utils/output.js';
5
5
  export function registerWebhookCommands(program) {
@@ -12,7 +12,7 @@ export function registerWebhookCommands(program) {
12
12
  const out = createOutput(flags);
13
13
  out.startSpinner('Fetching webhooks...');
14
14
  try {
15
- const client = getClient();
15
+ const client = await getClientAsync();
16
16
  const webhookList = await client.webhooks.list(vaultId);
17
17
  out.stopSpinner();
18
18
  out.list(webhookList.map(wh => ({
@@ -50,7 +50,7 @@ export function registerWebhookCommands(program) {
50
50
  const out = createOutput(flags);
51
51
  out.startSpinner('Creating webhook...');
52
52
  try {
53
- const client = getClient();
53
+ const client = await getClientAsync();
54
54
  const params = {
55
55
  url,
56
56
  events: String(_opts.events || 'create,update,delete').split(',').map((e) => e.trim()),
@@ -95,7 +95,7 @@ export function registerWebhookCommands(program) {
95
95
  }
96
96
  out.startSpinner('Updating webhook...');
97
97
  try {
98
- const client = getClient();
98
+ const client = await getClientAsync();
99
99
  const params = {};
100
100
  if (_opts.url)
101
101
  params.url = String(_opts.url);
@@ -125,7 +125,7 @@ export function registerWebhookCommands(program) {
125
125
  const out = createOutput(flags);
126
126
  out.startSpinner('Deleting webhook...');
127
127
  try {
128
- const client = getClient();
128
+ const client = await getClientAsync();
129
129
  await client.webhooks.delete(vaultId, webhookId);
130
130
  out.success('Webhook deleted successfully', { id: webhookId, deleted: true });
131
131
  }
@@ -142,7 +142,7 @@ export function registerWebhookCommands(program) {
142
142
  const out = createOutput(flags);
143
143
  out.startSpinner('Fetching deliveries...');
144
144
  try {
145
- const client = getClient();
145
+ const client = await getClientAsync();
146
146
  const deliveries = await client.webhooks.listDeliveries(vaultId, webhookId);
147
147
  out.stopSpinner();
148
148
  out.list(deliveries.map(d => ({
package/dist/config.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type CredentialManager } from './lib/credential-manager.js';
2
+ export declare const DEFAULT_API_URL = "https://vault.lifestreamdynamics.com";
2
3
  export interface CliConfig {
3
4
  apiUrl: string;
4
5
  apiKey?: string;
package/dist/config.js CHANGED
@@ -4,6 +4,7 @@ import os from 'node:os';
4
4
  import { createCredentialManager } from './lib/credential-manager.js';
5
5
  const CONFIG_DIR = path.join(os.homedir(), '.lsvault');
6
6
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
7
+ export const DEFAULT_API_URL = 'https://vault.lifestreamdynamics.com';
7
8
  // Singleton credential manager
8
9
  let _credentialManager;
9
10
  export function getCredentialManager() {
@@ -25,7 +26,7 @@ export function setCredentialManager(cm) {
25
26
  */
26
27
  export function loadConfig() {
27
28
  const config = {
28
- apiUrl: process.env.LSVAULT_API_URL || 'http://localhost:4660',
29
+ apiUrl: process.env.LSVAULT_API_URL || DEFAULT_API_URL,
29
30
  };
30
31
  if (process.env.LSVAULT_API_KEY) {
31
32
  config.apiKey = process.env.LSVAULT_API_KEY;
@@ -48,7 +49,7 @@ export async function loadConfigAsync() {
48
49
  const cm = getCredentialManager();
49
50
  const secureCreds = await cm.getCredentials();
50
51
  const config = {
51
- apiUrl: secureCreds.apiUrl || process.env.LSVAULT_API_URL || 'http://localhost:4660',
52
+ apiUrl: secureCreds.apiUrl || process.env.LSVAULT_API_URL || DEFAULT_API_URL,
52
53
  };
53
54
  // Load JWT tokens if available
54
55
  if (secureCreds.accessToken) {
@@ -1,6 +1,8 @@
1
1
  const SERVICE_NAME = 'lifestream-vault-cli';
2
2
  const ACCOUNT_API_KEY = 'api-key';
3
3
  const ACCOUNT_API_URL = 'api-url';
4
+ const ACCOUNT_ACCESS_TOKEN = 'access-token';
5
+ const ACCOUNT_REFRESH_TOKEN = 'refresh-token';
4
6
  /**
5
7
  * Dynamically loads keytar. Returns null if unavailable (not installed or
6
8
  * native module fails to load, e.g. missing libsecret on Linux).
@@ -48,6 +50,12 @@ export function createKeychainBackend() {
48
50
  const apiUrl = await kt.getPassword(SERVICE_NAME, ACCOUNT_API_URL);
49
51
  if (apiUrl)
50
52
  result.apiUrl = apiUrl;
53
+ const accessToken = await kt.getPassword(SERVICE_NAME, ACCOUNT_ACCESS_TOKEN);
54
+ if (accessToken)
55
+ result.accessToken = accessToken;
56
+ const refreshToken = await kt.getPassword(SERVICE_NAME, ACCOUNT_REFRESH_TOKEN);
57
+ if (refreshToken)
58
+ result.refreshToken = refreshToken;
51
59
  }
52
60
  catch {
53
61
  // Keychain access failed silently
@@ -64,6 +72,12 @@ export function createKeychainBackend() {
64
72
  if (config.apiUrl) {
65
73
  await kt.setPassword(SERVICE_NAME, ACCOUNT_API_URL, config.apiUrl);
66
74
  }
75
+ if (config.accessToken) {
76
+ await kt.setPassword(SERVICE_NAME, ACCOUNT_ACCESS_TOKEN, config.accessToken);
77
+ }
78
+ if (config.refreshToken) {
79
+ await kt.setPassword(SERVICE_NAME, ACCOUNT_REFRESH_TOKEN, config.refreshToken);
80
+ }
67
81
  },
68
82
  async clearCredentials() {
69
83
  const kt = await getKeytar();
@@ -77,6 +91,14 @@ export function createKeychainBackend() {
77
91
  await kt.deletePassword(SERVICE_NAME, ACCOUNT_API_URL);
78
92
  }
79
93
  catch { /* ignore */ }
94
+ try {
95
+ await kt.deletePassword(SERVICE_NAME, ACCOUNT_ACCESS_TOKEN);
96
+ }
97
+ catch { /* ignore */ }
98
+ try {
99
+ await kt.deletePassword(SERVICE_NAME, ACCOUNT_REFRESH_TOKEN);
100
+ }
101
+ catch { /* ignore */ }
80
102
  },
81
103
  };
82
104
  }
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "@lifestreamdynamics/vault-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Command-line interface for Lifestream Vault",
5
+ "engines": {
6
+ "node": ">=20"
7
+ },
5
8
  "type": "module",
6
9
  "bin": {
7
10
  "lsvault": "./dist/index.js"
@@ -53,10 +56,10 @@
53
56
  },
54
57
  "devDependencies": {
55
58
  "@types/node": "^22.0.0",
56
- "@vitest/coverage-v8": "^2.0.0",
57
- "@vitest/ui": "^2.0.0",
59
+ "@vitest/coverage-v8": "^4.0.18",
60
+ "@vitest/ui": "^4.0.18",
58
61
  "tsx": "^4.19.0",
59
62
  "typescript": "^5.7.0",
60
- "vitest": "^2.0.0"
63
+ "vitest": "^4.0.18"
61
64
  }
62
65
  }