@hiyve/cli 1.0.10 → 1.0.12

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
@@ -1,4 +1,4 @@
1
- # hiyve-cli
1
+ # @hiyve/cli
2
2
 
3
3
  Command-line tool for configuring npm to use the private Hiyve SDK registry.
4
4
 
@@ -6,10 +6,10 @@ Command-line tool for configuring npm to use the private Hiyve SDK registry.
6
6
 
7
7
  ```bash
8
8
  # One command to authenticate and configure npm
9
- npx hiyve-cli login
9
+ npx @hiyve/cli login
10
10
  ```
11
11
 
12
- After login, you can install Hiyve packages normally:
12
+ After login, install Hiyve packages normally:
13
13
 
14
14
  ```bash
15
15
  npm install @hiyve/rtc-client
@@ -18,37 +18,56 @@ npm install @hiyve/react @hiyve/react-ui
18
18
 
19
19
  ## Commands
20
20
 
21
- ### `hiyve login`
21
+ ### `login`
22
22
 
23
23
  Authenticate with Hiyve and configure npm for @hiyve packages.
24
24
 
25
25
  ```bash
26
26
  # Interactive mode (prompts for API key)
27
- npx hiyve-cli login
27
+ npx @hiyve/cli login
28
28
 
29
- # With API key as argument
30
- npx hiyve-cli login --key sk_live_your_secret_key_here
29
+ # Non-interactive (CI/CD)
30
+ npx @hiyve/cli login --key sk_live_your_secret_key_here
31
31
  ```
32
32
 
33
- ### `hiyve logout`
33
+ ### `logout`
34
34
 
35
35
  Remove Hiyve configuration from your ~/.npmrc file.
36
36
 
37
37
  ```bash
38
- npx hiyve-cli logout
38
+ npx @hiyve/cli logout
39
39
  ```
40
40
 
41
- ### `hiyve whoami`
41
+ ### `whoami`
42
42
 
43
43
  Show current authentication status.
44
44
 
45
45
  ```bash
46
- npx hiyve-cli whoami
46
+ npx @hiyve/cli whoami
47
47
  ```
48
48
 
49
+ ### `list`
50
+
51
+ List all available @hiyve packages.
52
+
53
+ ```bash
54
+ npx @hiyve/cli list
55
+ ```
56
+
57
+ ### `init`
58
+
59
+ Scaffold a new Hiyve project from a template.
60
+
61
+ ```bash
62
+ npx @hiyve/cli init my-app
63
+ npx @hiyve/cli init my-app --template ai
64
+ ```
65
+
66
+ Templates: `basic`, `ai`, `full`
67
+
49
68
  ## Getting Your API Key
50
69
 
51
- 1. Log in to the [Hiyve SDK Admin Portal](https://console.hiyve.dev)
70
+ 1. Log in to the [Hiyve Developer Console](https://api.hiyve.dev)
52
71
  2. Navigate to **API Keys** in the sidebar
53
72
  3. Copy your secret key (starts with `sk_test_` or `sk_live_`)
54
73
 
@@ -58,17 +77,30 @@ The `login` command:
58
77
 
59
78
  1. Validates your API key with the Hiyve registry
60
79
  2. Adds two lines to your `~/.npmrc` file:
61
- - `@hiyve:registry=https://api.hiyve.dev/registry/`
62
- - `//:_authToken=your_api_key`
80
+ ```
81
+ @hiyve:registry=https://api.hiyve.dev/registry/
82
+ //api.hiyve.dev/registry/:_authToken=sk_live_...
83
+ ```
63
84
 
64
85
  This tells npm to fetch `@hiyve/*` packages from the private Hiyve registry instead of the public npm registry.
65
86
 
87
+ ## CI/CD Setup
88
+
89
+ For automated deployments, add registry credentials as environment variables in your CI/CD pipeline. Your project `.npmrc` should use variable expansion:
90
+
91
+ ```ini
92
+ @hiyve:registry=https://api.hiyve.dev/registry/
93
+ //api.hiyve.dev/registry/:_authToken=${HIYVE_API_KEY}
94
+ ```
95
+
96
+ Set `HIYVE_API_KEY` in your CI environment (GitHub Actions secrets, AWS SSM, etc.). npm natively expands `${ENV_VAR}` in `.npmrc` files — no custom tooling needed.
97
+
66
98
  ## Troubleshooting
67
99
 
68
100
  ### "Invalid API key" error
69
101
 
70
102
  - Make sure your key starts with `sk_test_` or `sk_live_`
71
- - Verify your account is active in the admin portal
103
+ - Verify your account is active in the developer console
72
104
 
73
105
  ### "Connection failed" error
74
106
 
@@ -80,7 +112,7 @@ This tells npm to fetch `@hiyve/*` packages from the private Hiyve registry inst
80
112
  After login, verify your configuration:
81
113
 
82
114
  ```bash
83
- npx hiyve-cli whoami
115
+ npx @hiyve/cli whoami
84
116
  ```
85
117
 
86
118
  Or check your `~/.npmrc` manually:
@@ -92,8 +124,8 @@ cat ~/.npmrc | grep hiyve
92
124
  ## Security
93
125
 
94
126
  - Your API key is stored in `~/.npmrc` (standard npm token storage)
95
- - The API key is sent only to `api.hiyve.dev`
96
- - Run `hiyve logout` to remove your credentials
127
+ - The key is sent only to the Hiyve registry during npm operations
128
+ - Run `npx @hiyve/cli logout` to remove your credentials
97
129
 
98
130
  ## Support
99
131
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hiyve/cli",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "Hiyve SDK CLI - Configure npm for private @hiyve packages",
5
5
  "type": "module",
6
6
  "bin": {
@@ -217,8 +217,8 @@ export default defineConfig({
217
217
  }
218
218
 
219
219
  function generateEnvExample(template) {
220
- let env = `# Hiyve API Key (from console.hiyve.dev)
221
- HIYVE_API_KEY=sk_live_your_secret_key_here
220
+ let env = `# Hiyve API Key (from api.hiyve.dev)
221
+ HIYVE_API_KEY=pk_live_your_api_key_here
222
222
 
223
223
  # Room configuration
224
224
  HIYVE_SIGNALING_URL=https://signal.hiyve.dev
@@ -28,11 +28,14 @@ export async function login(options) {
28
28
  const response = await prompts({
29
29
  type: 'password',
30
30
  name: 'apiKey',
31
- message: 'Enter your Hiyve API key:',
31
+ message: 'Enter your Hiyve API key (pk_*):',
32
32
  validate: (value) => {
33
33
  if (!value) return 'API key is required';
34
- if (!value.startsWith('sk_') && !value.startsWith('mk_')) {
35
- return 'API key should start with sk_test_, sk_live_, or mk_';
34
+ if (!value.startsWith('pk_')) {
35
+ if (value.startsWith('sk_')) {
36
+ return 'Secret keys (sk_*) are no longer needed for registry login. Use your API key (pk_*) from console.hiyve.dev';
37
+ }
38
+ return 'Expected an API key starting with pk_test_ or pk_live_ (from console.hiyve.dev)';
36
39
  }
37
40
  if (value.length < 35) return 'API key appears to be too short';
38
41
  return true;
@@ -48,17 +51,26 @@ export async function login(options) {
48
51
  apiKey = response.apiKey;
49
52
  }
50
53
 
51
- // Validate API key format (sk_test_*, sk_live_*, or legacy mk_*)
54
+ // Validate API key format
55
+ const isPublicKey = apiKey.match(/^pk_(test|live)_[a-fA-F0-9]+$/);
56
+
57
+ // Accept legacy sk_ and mk_ keys for backward compatibility (existing users)
52
58
  const isSecretKey = apiKey.match(/^sk_(test|live)_[a-fA-F0-9]+$/);
53
59
  const isManagementKey = apiKey.match(/^mk_[a-fA-F0-9]{32}$/);
54
60
 
55
- if (!isSecretKey && !isManagementKey) {
61
+ if (!isPublicKey && !isSecretKey && !isManagementKey) {
56
62
  console.log('');
57
63
  console.log(chalk.red('✗ Invalid API key format'));
58
- console.log(chalk.gray(' Expected: sk_test_* or sk_live_* (from console.hiyve.dev)'));
64
+ console.log(chalk.gray(' Expected: pk_test_* or pk_live_* (from console.hiyve.dev)'));
59
65
  process.exit(1);
60
66
  }
61
67
 
68
+ if (isSecretKey) {
69
+ console.log(chalk.yellow(' Note: Secret keys (sk_*) still work but are no longer required.'));
70
+ console.log(chalk.yellow(' You can use your API key (pk_*) instead for registry access.'));
71
+ console.log('');
72
+ }
73
+
62
74
  // Verify API key with registry
63
75
  const spinner = ora('Verifying API key...').start();
64
76
 
@@ -32,7 +32,8 @@ export async function configureNpmrc(registryUrl, apiKey) {
32
32
  !trimmed.includes('//api.hiyve.dev/') &&
33
33
  !trimmed.includes('//api.muziemedia.com/') &&
34
34
  !trimmed.includes(':_authToken=mk_') &&
35
- !trimmed.includes(':_authToken=sk_')
35
+ !trimmed.includes(':_authToken=sk_') &&
36
+ !trimmed.includes(':_authToken=pk_')
36
37
  );
37
38
  });
38
39
 
@@ -68,7 +69,8 @@ export async function removeNpmrc() {
68
69
  !trimmed.includes('//api.hiyve.dev/') &&
69
70
  !trimmed.includes('//api.muziemedia.com/') &&
70
71
  !trimmed.includes(':_authToken=mk_') &&
71
- !trimmed.includes(':_authToken=sk_')
72
+ !trimmed.includes(':_authToken=sk_') &&
73
+ !trimmed.includes(':_authToken=pk_')
72
74
  );
73
75
  });
74
76
 
@@ -92,18 +94,18 @@ export function getCurrentConfig() {
92
94
  // Find registry line
93
95
  const registryLine = lines.find((line) => line.trim().startsWith('@hiyve:registry'));
94
96
 
95
- // Find token line (sk_* or legacy mk_*)
97
+ // Find token line (pk_*, sk_*, or legacy mk_*)
96
98
  const tokenLine = lines.find((line) => {
97
99
  const trimmed = line.trim();
98
- return trimmed.includes(':_authToken=sk_') || trimmed.includes(':_authToken=mk_');
100
+ return trimmed.includes(':_authToken=pk_') || trimmed.includes(':_authToken=sk_') || trimmed.includes(':_authToken=mk_');
99
101
  });
100
102
 
101
103
  if (!registryLine || !tokenLine) {
102
104
  return null;
103
105
  }
104
106
 
105
- // Extract API key (sk_* or legacy mk_*)
106
- const tokenMatch = tokenLine.match(/:_authToken=((?:sk_|mk_)[a-zA-Z0-9_]+)/);
107
+ // Extract API key (pk_*, sk_*, or legacy mk_*)
108
+ const tokenMatch = tokenLine.match(/:_authToken=((?:pk_|sk_|mk_)[a-zA-Z0-9_]+)/);
107
109
  const apiKey = tokenMatch ? tokenMatch[1] : null;
108
110
 
109
111
  // Mask API key for display
@@ -32,6 +32,19 @@ describe('configureNpmrc', () => {
32
32
  expect(content).toContain(':_authToken=sk_live_abc123def456');
33
33
  });
34
34
 
35
+ it('creates .npmrc with pk_ key', async () => {
36
+ fs.existsSync.mockReturnValue(false);
37
+ fs.writeFileSync.mockImplementation(() => {});
38
+
39
+ await configureNpmrc('https://api.hiyve.dev/registry/', 'pk_live_abc123def456');
40
+
41
+ expect(fs.writeFileSync).toHaveBeenCalledOnce();
42
+ const [writePath, content] = fs.writeFileSync.mock.calls[0];
43
+ expect(writePath).toBe(NPMRC_PATH);
44
+ expect(content).toContain('@hiyve:registry=https://api.hiyve.dev/registry/');
45
+ expect(content).toContain(':_authToken=pk_live_abc123def456');
46
+ });
47
+
35
48
  it('replaces existing @hiyve lines when .npmrc already has them', async () => {
36
49
  const existingContent = [
37
50
  '@hiyve:registry=https://old-registry.example.com/',
@@ -54,6 +67,42 @@ describe('configureNpmrc', () => {
54
67
  expect(content).toContain(':_authToken=sk_live_newkey5678');
55
68
  });
56
69
 
70
+ it('replaces existing sk_ token with pk_ key', async () => {
71
+ const existingContent = [
72
+ '@hiyve:registry=https://api.hiyve.dev/registry/',
73
+ '//api.hiyve.dev/registry/:_authToken=sk_live_oldkey1234',
74
+ 'other-config=value',
75
+ ].join('\n');
76
+
77
+ fs.existsSync.mockReturnValue(true);
78
+ fs.readFileSync.mockReturnValue(existingContent);
79
+ fs.writeFileSync.mockImplementation(() => {});
80
+
81
+ await configureNpmrc('https://api.hiyve.dev/registry/', 'pk_live_newkey5678');
82
+
83
+ const [, content] = fs.writeFileSync.mock.calls[0];
84
+ expect(content).not.toContain('sk_live_oldkey1234');
85
+ expect(content).toContain(':_authToken=pk_live_newkey5678');
86
+ });
87
+
88
+ it('replaces existing pk_ token with new pk_ key', async () => {
89
+ const existingContent = [
90
+ '@hiyve:registry=https://api.hiyve.dev/registry/',
91
+ '//api.hiyve.dev/registry/:_authToken=pk_test_oldkey1234',
92
+ 'other-config=value',
93
+ ].join('\n');
94
+
95
+ fs.existsSync.mockReturnValue(true);
96
+ fs.readFileSync.mockReturnValue(existingContent);
97
+ fs.writeFileSync.mockImplementation(() => {});
98
+
99
+ await configureNpmrc('https://api.hiyve.dev/registry/', 'pk_live_newkey5678');
100
+
101
+ const [, content] = fs.writeFileSync.mock.calls[0];
102
+ expect(content).not.toContain('pk_test_oldkey1234');
103
+ expect(content).toContain(':_authToken=pk_live_newkey5678');
104
+ });
105
+
57
106
  it('replaces legacy mk_ tokens', async () => {
58
107
  const existingContent = [
59
108
  '@hiyve:registry=https://console.hiyve.dev/api/registry/',
@@ -172,6 +221,47 @@ describe('removeNpmrc', () => {
172
221
  expect(content).not.toContain('sk_live_abc123def456');
173
222
  });
174
223
 
224
+ it('removes @hiyve lines with pk_ tokens', async () => {
225
+ const existingContent = [
226
+ 'registry=https://registry.npmjs.org/',
227
+ '@hiyve:registry=https://api.hiyve.dev/registry/',
228
+ '//api.hiyve.dev/registry/:_authToken=pk_live_abc123def456',
229
+ 'other-config=true',
230
+ ].join('\n');
231
+
232
+ fs.existsSync.mockReturnValue(true);
233
+ fs.readFileSync.mockReturnValue(existingContent);
234
+ fs.writeFileSync.mockImplementation(() => {});
235
+
236
+ await removeNpmrc();
237
+
238
+ const [, content] = fs.writeFileSync.mock.calls[0];
239
+ expect(content).not.toContain('@hiyve:registry');
240
+ expect(content).not.toContain('api.hiyve.dev');
241
+ expect(content).not.toContain('pk_live_abc123def456');
242
+ expect(content).toContain('other-config=true');
243
+ });
244
+
245
+ it('removes @hiyve lines with pk_ tokens (old registry)', async () => {
246
+ const existingContent = [
247
+ 'registry=https://registry.npmjs.org/',
248
+ '@hiyve:registry=https://console.hiyve.dev/api/registry/',
249
+ '//console.hiyve.dev/api/registry/:_authToken=pk_test_abc123def456',
250
+ 'other-config=true',
251
+ ].join('\n');
252
+
253
+ fs.existsSync.mockReturnValue(true);
254
+ fs.readFileSync.mockReturnValue(existingContent);
255
+ fs.writeFileSync.mockImplementation(() => {});
256
+
257
+ await removeNpmrc();
258
+
259
+ const [, content] = fs.writeFileSync.mock.calls[0];
260
+ expect(content).not.toContain('@hiyve:registry');
261
+ expect(content).not.toContain('console.hiyve.dev');
262
+ expect(content).not.toContain('pk_test_abc123def456');
263
+ });
264
+
175
265
  it('removes @hiyve lines with legacy mk_ tokens', async () => {
176
266
  const existingContent = [
177
267
  'registry=https://registry.npmjs.org/',
@@ -243,6 +333,40 @@ describe('getCurrentConfig', () => {
243
333
  expect(getCurrentConfig()).toBeNull();
244
334
  });
245
335
 
336
+ it('returns config for pk_ keys (new registry)', () => {
337
+ const content = [
338
+ '@hiyve:registry=https://api.hiyve.dev/registry/',
339
+ '//api.hiyve.dev/registry/:_authToken=pk_live_1a2b3c4d5e6f7890abcd',
340
+ ].join('\n');
341
+
342
+ fs.existsSync.mockReturnValue(true);
343
+ fs.readFileSync.mockReturnValue(content);
344
+
345
+ const result = getCurrentConfig();
346
+ expect(result).toEqual({
347
+ apiKey: 'pk_live_1a2b3c4d5e6f7890abcd',
348
+ maskedApiKey: 'pk_live_...abcd',
349
+ registryUrl: 'https://api.hiyve.dev/registry/',
350
+ });
351
+ });
352
+
353
+ it('returns config for pk_ keys (old registry — backward compat)', () => {
354
+ const content = [
355
+ '@hiyve:registry=https://console.hiyve.dev/api/registry/',
356
+ '//console.hiyve.dev/api/registry/:_authToken=pk_test_1a2b3c4d5e6f7890abcd',
357
+ ].join('\n');
358
+
359
+ fs.existsSync.mockReturnValue(true);
360
+ fs.readFileSync.mockReturnValue(content);
361
+
362
+ const result = getCurrentConfig();
363
+ expect(result).toEqual({
364
+ apiKey: 'pk_test_1a2b3c4d5e6f7890abcd',
365
+ maskedApiKey: 'pk_test_...abcd',
366
+ registryUrl: 'https://console.hiyve.dev/api/registry/',
367
+ });
368
+ });
369
+
246
370
  it('returns config for sk_ keys (new registry)', () => {
247
371
  const content = [
248
372
  '@hiyve:registry=https://api.hiyve.dev/registry/',
@@ -294,7 +418,7 @@ describe('getCurrentConfig', () => {
294
418
  });
295
419
  });
296
420
 
297
- it('maskedApiKey shows first 8 and last 4 chars', () => {
421
+ it('maskedApiKey shows first 8 and last 4 chars for sk_ keys', () => {
298
422
  const apiKey = 'sk_test_aabbccdd11223344eeff';
299
423
  const content = [
300
424
  '@hiyve:registry=https://api.hiyve.dev/registry/',
@@ -309,6 +433,21 @@ describe('getCurrentConfig', () => {
309
433
  expect(result.maskedApiKey).toBe('sk_test_...eeff');
310
434
  });
311
435
 
436
+ it('maskedApiKey shows first 8 and last 4 chars for pk_ keys', () => {
437
+ const apiKey = 'pk_live_aabbccdd11223344eeff';
438
+ const content = [
439
+ '@hiyve:registry=https://api.hiyve.dev/registry/',
440
+ `//api.hiyve.dev/registry/:_authToken=${apiKey}`,
441
+ ].join('\n');
442
+
443
+ fs.existsSync.mockReturnValue(true);
444
+ fs.readFileSync.mockReturnValue(content);
445
+
446
+ const result = getCurrentConfig();
447
+ expect(result.apiKey).toBe(apiKey);
448
+ expect(result.maskedApiKey).toBe('pk_live_...eeff');
449
+ });
450
+
312
451
  it('returns null when only registry line is present but no token', () => {
313
452
  const content = '@hiyve:registry=https://api.hiyve.dev/registry/\n';
314
453