neutrinos-cli 1.0.2 → 2.0.0-beta.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.
Files changed (56) hide show
  1. package/README.md +77 -111
  2. package/{bin → dist/src/bin}/cli.js +117 -125
  3. package/{cli-auth → dist/src/cli-auth}/auth.js +3 -24
  4. package/{cli-auth → dist/src/cli-auth}/server.js +6 -15
  5. package/{cli-auth → dist/src/cli-auth}/services/auth-utils.js +5 -24
  6. package/{commands → dist/src/commands}/attribute.js +36 -43
  7. package/{commands → dist/src/commands}/build.js +10 -25
  8. package/dist/src/commands/completion.js +298 -0
  9. package/dist/src/commands/deprecate.js +62 -0
  10. package/{commands → dist/src/commands}/dev.js +1 -12
  11. package/dist/src/commands/generate.js +10 -0
  12. package/{commands → dist/src/commands}/new-workspace.js +24 -50
  13. package/{commands → dist/src/commands}/publish.js +53 -200
  14. package/dist/src/commands/select-packages.js +22 -0
  15. package/{commands → dist/src/commands}/serve.js +7 -8
  16. package/dist/src/types/alpha-package.js +1 -0
  17. package/dist/src/types/marketplace.js +1 -0
  18. package/dist/src/types/session.js +1 -0
  19. package/dist/src/types/workspace.js +1 -0
  20. package/{utils → dist/src/utils}/attribute-utils.js +67 -44
  21. package/{utils → dist/src/utils}/check-valid-ws.js +1 -2
  22. package/{utils → dist/src/utils}/copy-utils.js +16 -28
  23. package/{utils → dist/src/utils}/create-client.js +3 -7
  24. package/{utils → dist/src/utils}/file-utils.js +10 -14
  25. package/{utils → dist/src/utils}/generate-component.js +10 -22
  26. package/{utils → dist/src/utils}/generate-module.js +4 -7
  27. package/dist/src/utils/get-package-info.js +60 -0
  28. package/dist/src/utils/get-packages.js +11 -0
  29. package/{utils → dist/src/utils}/inquirer-utils.js +8 -36
  30. package/dist/src/utils/logger.js +11 -0
  31. package/dist/src/utils/marketplace-api-utils.js +16 -0
  32. package/dist/src/utils/path-utils.js +28 -0
  33. package/dist/src/utils/prettify.js +15 -0
  34. package/{utils/user-seesion-utils.js → dist/src/utils/user-session-utils.js} +6 -9
  35. package/package.json +23 -21
  36. package/templates/module/.module.js.hbs +2 -2
  37. package/cli-auth/publish.js +0 -7
  38. package/commands/alpha-publish.js +0 -239
  39. package/commands/deprecate.js +0 -88
  40. package/commands/generate.js +0 -19
  41. package/commands/select-packages.mjs +0 -36
  42. package/templates/project/Dockerfile +0 -15
  43. package/templates/project/helmchart/.helmignore +0 -23
  44. package/templates/project/helmchart/Chart.yaml +0 -24
  45. package/templates/project/helmchart/templates/NOTES.txt +0 -22
  46. package/templates/project/helmchart/templates/_helpers.tpl +0 -62
  47. package/templates/project/helmchart/templates/deployment.yaml +0 -69
  48. package/templates/project/helmchart/templates/ingress.yaml +0 -62
  49. package/templates/project/helmchart/templates/service.yaml +0 -14
  50. package/templates/project/helmchart/values.yaml +0 -74
  51. package/utils/get-package-info.js +0 -53
  52. package/utils/get-packages.js +0 -15
  53. package/utils/logger.js +0 -35
  54. package/utils/marketplace-api-utils.js +0 -34
  55. package/utils/path-utils.js +0 -40
  56. package/utils/prettify.js +0 -36
package/README.md CHANGED
@@ -1,173 +1,139 @@
1
1
  # neutrinos CLI
2
2
 
3
- neutrinos CLI is a command-line interface for managing, developing and publishing the packages.
3
+ A command-line interface for managing, developing, and publishing alpha plugin packages.
4
4
 
5
- ### Installation
5
+ **Requires Node.js 22+**
6
6
 
7
- To install neutrinos CLI, use the following command:
7
+ ## Installation
8
8
 
9
9
  ```sh
10
+ # Stable
10
11
  npm i -g neutrinos-cli
12
+
13
+ # Beta
14
+ npm i -g neutrinos-cli@beta
11
15
  ```
12
16
 
13
- ### Usage
17
+ ## Quick Start
14
18
 
15
19
  ```sh
16
- neutrinos command [options]
20
+ neutrinos new my-workspace
21
+ cd my-workspace
22
+ neutrinos generate component my-button
23
+ neutrinos build plugins
24
+ neutrinos start
17
25
  ```
18
26
 
19
- ### Commands
20
-
21
- - `new <name>` Create a new project
22
- - `generate` | `g` Generate a new plugin. Run "help generate" for more information.
23
- - `auth` Perform authentication tasks like login, logout, or status
24
- - `publish [options] [packageName]` Bundle and publish the plugin
25
- - `build <type> [pluginName]` Build the plugin
26
- - `start [options]` Start the live server for the plugin
27
- - `serve` Start the express server that serves the plugins
28
-
29
- ### Options
30
-
31
- - `-v, --version` Output the version number
32
- - `-h, --help` Display help for command
33
-
34
- ---
35
-
36
27
  ## Commands
37
28
 
38
- ---
39
-
40
- ### `new <name>`
29
+ ```
30
+ neutrinos <command> [options]
31
+ ```
41
32
 
42
- ##### Description
33
+ | Command | Description |
34
+ |---------|-------------|
35
+ | `new <name>` | Create a new plugin workspace |
36
+ | `generate\|g` | Generate a component, module, or attribute |
37
+ | `build <type> [name]` | Build plugins (`plugins` or `docker`) |
38
+ | `start` | Start the Vite dev server |
39
+ | `serve` | Start the Express plugins server |
40
+ | `publish [name]` | Bundle and publish a package |
41
+ | `deprecate [name]` | Deprecate a published package |
42
+ | `auth` | Login or check auth state |
43
+ | `completion <shell>` | Output shell completion script (`bash` or `zsh`) |
43
44
 
44
- - Create a new project with the given name. The project will be created in the current directory.
45
+ ### `new <name>`
45
46
 
46
- ##### Usage
47
+ Create a new workspace with scaffold files, plugin.json, git init, and npm install.
47
48
 
48
49
  ```sh
49
- neutrinos new <name>
50
+ neutrinos new my-workspace
50
51
  ```
51
52
 
52
- ##### Arguments
53
-
54
- - `<name>` project or workspace name
55
-
56
- ---
57
-
58
53
  ### `generate` | `g`
59
54
 
60
- ##### Description
61
-
62
- - Generate a new component or module
63
-
64
- ##### Usage
65
-
66
55
  ```sh
67
- neutrinos generate [command] [argument] || neutrinos g [command] [argument]
56
+ neutrinos generate component <name> [-d <description>]
57
+ neutrinos generate module <name> [-d <description>]
58
+ neutrinos generate attribute [componentName] [options]
68
59
  ```
69
60
 
70
- ##### commands
71
-
72
- - `component <name>` | `c <name>` Component is a package enabling drag and drop functionality within the canvas
73
- - `module <name>` | `m <name>` Module is a globally accessible package, available throughout the entire project on `alpha.plugins` | `ap`.
74
- - `attribute [command] [options]` | `a [command] [options]` Generate an Attribute for a component, Read the `ATTRIBUTE.md` file in projetc/workspcae directory for more help
75
-
76
- ##### Arguments
77
-
78
- - `<name>` component or module name
79
-
80
- ---
61
+ Aliases: `g`, `c`, `m`, `a`
81
62
 
82
- ## `Build <type> [pluginName]`
63
+ Attribute options: `-t` type, `-u` ui-type, `-l` label, `-e` event, `-c` category, `-p` placeholder, `-d` defaultValue, `-o` options, `-f` fieldMappings, `-n` validation. See `ATTRIBUTE.md` in your workspace for details.
83
64
 
84
- #### Description
85
-
86
- - Build the plugins
87
-
88
- #### Usage
65
+ ### `build <type> [pluginName]`
89
66
 
90
67
  ```sh
91
- neutrinos build <type> [pluginName]
68
+ neutrinos build plugins [name] [--module] [--all]
69
+ neutrinos build docker [name]
92
70
  ```
93
71
 
94
- #### Arguments
95
-
96
- - `<type>` The type of build, it can be one of `plugin` or `docker`
97
- - `pluginName` package Name of the component/module to build, it is an optional argument and if not pluginName it will build every package in the current workspace
98
-
99
- ---
100
-
101
- ## `start [options]`
72
+ - `plugins` — Runs tsc + Vite build, copies output to plugins-server
73
+ - `docker` — Builds plugins then runs `docker build`
74
+ - `--module` Skip tsc (for JS-only modules)
75
+ - `--all` Build all packages in the workspace
102
76
 
103
- #### Description
104
-
105
- - Start the live server for the workspace
106
-
107
- #### Usage
77
+ ### `start`
108
78
 
109
79
  ```sh
110
- neutrinos start [options]
80
+ neutrinos start [-p <port>]
111
81
  ```
112
82
 
113
- #### Options
114
-
115
- - `-p, --port <port>` Port to start the server on, default is 6969
83
+ Starts a Vite dev server. Default port: 6969.
116
84
 
117
- ---
85
+ ### `serve`
118
86
 
119
- ## `serve`
120
-
121
- #### Description
87
+ ```sh
88
+ neutrinos serve [-p <port>]
89
+ ```
122
90
 
123
- - Start the express server that serves the plugins
91
+ Starts the Express server that serves built plugins. Default port: 3000.
124
92
 
125
- #### Usage
93
+ ### `publish [packageName]`
126
94
 
127
95
  ```sh
128
- neutrinos serve
96
+ neutrinos publish [name] [-t <patch|minor|major>] [-d <displayName>] [-i <iconPath>] [-m <images...>] [--accept-defaults] [--all]
129
97
  ```
130
98
 
131
- ---
99
+ Authenticates, builds, zips, and uploads the package to the marketplace. Prompts for missing metadata unless `--accept-defaults` is passed.
132
100
 
133
- ### `auth [command]`
101
+ ### `deprecate [packageName]`
134
102
 
135
- #### Description
103
+ ```sh
104
+ neutrinos deprecate [name] [-y] [--all]
105
+ ```
136
106
 
137
- - Perform authentication tasks like login or status
107
+ Marks a published package as deprecated. Prompts for confirmation unless `-y` is passed.
138
108
 
139
- #### Usage
109
+ ### `auth`
140
110
 
141
111
  ```sh
142
- neutrinos auth [command]
112
+ neutrinos auth login # Opens browser for OIDC login
113
+ neutrinos auth state # Shows current auth state
143
114
  ```
144
115
 
145
- #### Commands:
116
+ ### `completion`
146
117
 
147
- - `login` Authenticate with the server
148
- - `state` Get the current state of auth
149
-
150
- ---
118
+ ```sh
119
+ # Bash
120
+ neutrinos completion bash >> ~/.bashrc
151
121
 
152
- ## `publish [PackageName] [options]`
122
+ # Zsh
123
+ neutrinos completion zsh >> ~/.zshrc
124
+ ```
153
125
 
154
- #### Description
126
+ ## Global Options
155
127
 
156
- - Publish a package to the server
128
+ - `-v, --version` Show version
129
+ - `-h, --help` — Show help
157
130
 
158
- #### Usage
131
+ ## Development
159
132
 
160
133
  ```sh
161
- neutrinos publish [PackageName] [Options]
134
+ pnpm install
135
+ pnpm build # tsc
136
+ pnpm test # vitest
137
+ pnpm publish:beta # build + test + npm publish --tag beta
138
+ pnpm publish:latest # build + test + npm publish --tag latest
162
139
  ```
163
-
164
- #### Arguments
165
-
166
- - `PackageName` The name of the component/module to publish, if not cli will show the list of packages inside the current workspace/project
167
-
168
- #### Options
169
-
170
- - `-t, --version-type <versionType>` Version type for verion up, it can be one of `patch`, `minor`, `major`
171
- - `-d, --display-name <displayName>` Display Name for the package
172
- - `-i, --icon <iconPath>` Path to the icon
173
- - `-m, --images <imagePaths...>` path to the image
@@ -1,20 +1,23 @@
1
1
  #! /usr/bin/env node
2
- //@ts-check
3
- const __dirname = fileURLToPath(new URL('.', import.meta.url));
2
+ const [major] = process.versions.node.split('.').map(Number);
3
+ if (major < 22) {
4
+ console.error('neutrinos requires Node.js 22+. Current: ' + process.version);
5
+ process.exit(1);
6
+ }
4
7
  import dotenv from 'dotenv';
8
+ import { PACKAGE_ROOT } from '../utils/path-utils.js';
5
9
  dotenv.config({
6
- path: join(__dirname, '../.env'),
10
+ path: join(PACKAGE_ROOT, '.env'),
7
11
  });
8
- ////////////////////////////////////
9
12
  import { greenBright } from 'colorette';
10
- import { Command, InvalidArgumentError } from 'commander';
13
+ import { Argument, Command, Option } from 'commander';
11
14
  import EventEmitter from 'node:events';
12
15
  import { cwd, env, exit } from 'node:process';
16
+ import { readFileSync, realpathSync } from 'node:fs';
13
17
  import { fileURLToPath } from 'node:url';
14
18
  import open from 'open';
15
- import { join } from 'path';
19
+ import { join, resolve } from 'node:path';
16
20
  import { init } from '../cli-auth/server.js';
17
- import { publish as alphaPublish } from '../commands/alpha-publish.js';
18
21
  import { addAttribute } from '../commands/attribute.js';
19
22
  import { build } from '../commands/build.js';
20
23
  import { deprecate } from '../commands/deprecate.js';
@@ -23,25 +26,25 @@ import { generate } from '../commands/generate.js';
23
26
  import { createWorkspace } from '../commands/new-workspace.js';
24
27
  import { publish } from '../commands/publish.js';
25
28
  import { startPluginsServer } from '../commands/serve.js';
29
+ import { completion } from '../commands/completion.js';
30
+ import { getPackages } from '../utils/get-packages.js';
26
31
  import { validateWorkspace } from '../utils/check-valid-ws.js';
27
32
  import { done, failed, inprogress, log } from '../utils/logger.js';
28
33
  import { authConfigJson } from '../utils/path-utils.js';
34
+ const { version: CLI_VERSION } = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf-8'));
29
35
  export const createProgram = () => {
30
36
  const program = new Command();
31
-
32
- program.version('1.0.0', '-v, --version', 'Output the version number');
33
-
37
+ program.version(CLI_VERSION, '-v, --version', 'Output the version number');
34
38
  program
35
39
  .command('new <name>')
36
40
  .description('Create a new project')
37
41
  .action((name) => {
38
- createWorkspace(join(cwd(), name), name);
39
- });
42
+ createWorkspace(join(cwd(), name), name);
43
+ });
40
44
  const generateCmd = program
41
45
  .command('generate')
42
46
  .alias('g')
43
47
  .description('Generate a new plugin. Run "help generate" for more information.');
44
-
45
48
  generateCmd
46
49
  .command('component')
47
50
  .alias('c')
@@ -49,12 +52,12 @@ export const createProgram = () => {
49
52
  .option('-d,--description <description>', 'Description of the package')
50
53
  .description('Generate a new component plugin')
51
54
  .action(async (name, options) => {
52
- await generate.component({
53
- name,
54
- dir: cwd(),
55
- description: options.description,
56
- });
55
+ await generate.component({
56
+ name,
57
+ dir: cwd(),
58
+ description: options.description,
57
59
  });
60
+ });
58
61
  generateCmd
59
62
  .command('module')
60
63
  .alias('m')
@@ -62,21 +65,18 @@ export const createProgram = () => {
62
65
  .option('-d,--description <description>', 'Description of the package')
63
66
  .description('Generate a new module plugin')
64
67
  .action(async (name, options) => {
65
- await generate.module({
66
- name,
67
- dir: cwd(),
68
- description: options.description,
69
- });
68
+ await generate.module({
69
+ name,
70
+ dir: cwd(),
71
+ description: options.description,
70
72
  });
73
+ });
71
74
  generateCmd
72
75
  .command('attribute')
73
76
  .alias('a')
74
77
  .argument('[componentName]', 'Component name')
75
78
  .option('-t , --type <attributeType>', 'Type of attribute can be property, event, validation')
76
- .option(
77
- '-u , --ui-type <uiType>',
78
- 'Ui-type of attribute can be ===> input, toggle, dropdown, multi-select, typed-input, range, color-picker, data-source, data-set, table-actions, data-mapping',
79
- )
79
+ .option('-u , --ui-type <uiType>', 'Ui-type of attribute can be ===> input, toggle, dropdown, multi-select, typed-input, range, color-picker, data-source, data-set, table-actions, data-mapping')
80
80
  .option('-l , --label <label>', 'Label for an attribute')
81
81
  .option('-e , --event <event>', 'Event name for an attribute if -t/--type is event')
82
82
  .option('-c , --category <category>', 'Category for an attribute')
@@ -87,86 +87,63 @@ export const createProgram = () => {
87
87
  .option('-n , --validation <validation>', 'Validation for an attribute')
88
88
  .description('Generate an Attribute for component')
89
89
  .action(async (componentName, options) => {
90
- return await addAttribute(componentName, cwd(), options);
91
- });
92
-
90
+ return await addAttribute(componentName, cwd(), options);
91
+ });
93
92
  const authCommand = program.command('auth').description('perform: login, logout, or status');
94
93
  authCommand
95
94
  .command('login')
96
95
  .description('authenticate with the server')
97
- .action((action) => {
98
- return new Promise(async (resolve, reject) => {
99
- inprogress(`logging in...`);
100
- const cliServer = await init({
101
- tokenSetPath: authConfigJson(),
102
- });
103
- if (!cliServer) {
104
- failed('Issuer not found');
105
- return;
106
- }
107
- const eventEmitter = new EventEmitter();
108
- eventEmitter.on('cli-auth:login', () => {
109
- done('login successful');
110
- resolve();
111
- process.exit(0);
112
- });
113
- eventEmitter.on('cli-auth:login-failed', () => {
114
- failed('login failed');
115
- reject();
116
- process.exit(1);
117
- });
118
- process.on('SIGINT', () => {
119
- failed('exitting unexpectedly');
120
- cliServer.stop();
121
- exit(0);
122
- });
123
- process.on('SIGTERM', () => {
124
- failed('exitting unexpectedly');
125
- cliServer.stop();
126
- exit(0);
127
- });
128
- await cliServer.start(eventEmitter);
129
- const url = `http://localhost:${env.PORT}/login`;
130
- inprogress(`open to login ${greenBright(url)}`);
131
- await open(url);
96
+ .action(() => {
97
+ return new Promise(async (resolve, reject) => {
98
+ inprogress('logging in...');
99
+ const cliServer = await init({
100
+ tokenSetPath: authConfigJson(),
101
+ });
102
+ if (!cliServer) {
103
+ failed('Issuer not found');
104
+ return;
105
+ }
106
+ const eventEmitter = new EventEmitter();
107
+ eventEmitter.on('cli-auth:login', () => {
108
+ done('login successful');
109
+ resolve();
110
+ process.exit(0);
111
+ });
112
+ eventEmitter.on('cli-auth:login-failed', () => {
113
+ failed('login failed');
114
+ reject();
115
+ process.exit(1);
116
+ });
117
+ process.on('SIGINT', () => {
118
+ failed('exiting unexpectedly');
119
+ void cliServer.stop();
120
+ exit(0);
121
+ });
122
+ process.on('SIGTERM', () => {
123
+ failed('exiting unexpectedly');
124
+ void cliServer.stop();
125
+ exit(0);
132
126
  });
127
+ await cliServer.start(eventEmitter);
128
+ const url = `http://localhost:${env.PORT}/login`;
129
+ inprogress(`open to login ${greenBright(url)}`);
130
+ await open(url);
133
131
  });
132
+ });
134
133
  authCommand
135
134
  .command('state')
136
135
  .description('get the current state of auth')
137
136
  .action(() => {
138
- console.log('state');
139
- });
140
-
137
+ console.log('state');
138
+ });
141
139
  program
142
140
  .command('publish')
143
141
  .argument('[packageName]', 'Component name')
144
- .option(
145
- '-t, --version-type <versionType>',
146
- 'Version type for verion up can be one of "patch", "minor", "major"',
147
- )
148
- .option('-d, --display-name <displayName>', 'Display Name for the package')
149
- .option('-i, --icon <iconPath>', 'Icon path')
150
- .option('-m, --images <imagePaths...>', 'Image paths')
151
- .description('Bundle and publish the plugin')
152
- .action(async (packageName, options) => {
153
- if (
154
- options.versionType &&
155
- !['patch', 'minor', 'major'].includes((options.versionType || '').toLowerCase())
156
- ) {
157
- failed('Invalid version type should be one of "patch", "minor", "major"');
158
- exit(0);
159
- }
160
- return await publish(packageName, cwd(), options);
161
- });
162
-
163
- program
164
- .command('alpha:publish')
165
- .argument('[packageName]', 'Component name')
166
- .option(
167
- '-t, --version-type <versionType>',
168
- 'Version type for version up can be one of "patch", "minor", "major"',
169
- )
142
+ .addOption(new Option('-t, --version-type <versionType>', 'Version type for version up').choices([
143
+ 'patch',
144
+ 'minor',
145
+ 'major',
146
+ ]))
170
147
  .option('-d, --display-name <displayName>', 'Display Name for the package')
171
148
  .option('-i, --icon <iconPath>', 'Icon path')
172
149
  .option('-m, --images <imagePaths...>', 'Image paths')
@@ -174,56 +151,65 @@ export const createProgram = () => {
174
151
  .option('--all', 'Select all the packages')
175
152
  .description('Bundle and publish the plugin')
176
153
  .action(async (packageName, options) => {
177
- if (
178
- options.versionType &&
179
- !['patch', 'minor', 'major'].includes((options.versionType || '').toLowerCase())
180
- ) {
181
- failed('Invalid version type should be one of "patch", "minor", "major"');
182
- exit(0);
183
- }
184
- return await alphaPublish(packageName, cwd(), options);
185
- });
186
-
154
+ return await publish(packageName, cwd(), options);
155
+ });
187
156
  program
188
157
  .command('deprecate')
189
158
  .option('-y, --yes', 'Confirmation to deprecate a package')
190
159
  .option('--all', 'Select all the packages')
191
160
  .argument('[packageName]', 'Package name')
192
161
  .action(async (packageName, options) => {
193
- return await deprecate(packageName, cwd(), options);
194
- });
195
-
162
+ return await deprecate(packageName, cwd(), options);
163
+ });
196
164
  program
197
165
  .command('build')
198
- .argument('<type>', 'Type of build: "plugins" or "docker"', (value, prevValue) => {
199
- if (value !== 'plugins' && value !== 'docker') {
200
- throw new InvalidArgumentError('"build" can be "plugins" or "docker"');
201
- }
202
- return value;
203
- })
166
+ .addArgument(new Argument('<type>', 'Type of build').choices(['plugins', 'docker']))
204
167
  .argument('[pluginName]', 'Name of the plugin')
205
168
  .option('--module', 'Build the plugin as a module')
206
169
  .option('--all', 'Build all the plugin of the workspace')
207
170
  .description('Build the plugin')
208
171
  .action((type, pluginName, options) => {
209
- build[type](cwd(), pluginName, options || {});
210
- });
172
+ build[type](cwd(), pluginName ?? '', options ?? {});
173
+ });
211
174
  program
212
175
  .command('start')
213
176
  .option('-p, --port <port>', 'Port number for serving the plugin')
214
177
  .description('start the live server for the plugin')
215
178
  .action((options) => {
216
- servePlugin(cwd(), options.port || 6969);
217
- });
179
+ servePlugin(cwd(), Number(options.port) || 6969);
180
+ });
218
181
  program
219
182
  .command('serve')
183
+ .option('-p, --port <port>', 'Port number for serving the plugins', '3000')
220
184
  .description('Start the express server that serves the plugins')
185
+ .action((options) => {
186
+ startPluginsServer(cwd(), Number(options.port));
187
+ });
188
+ program
189
+ .command('completion')
190
+ .description('Output shell completion script')
191
+ .addArgument(new Argument('<shell>', 'Shell type').choices(['bash', 'zsh']))
192
+ .action((shell) => {
193
+ completion(program, shell);
194
+ });
195
+ program
196
+ .command('__list-packages', { hidden: true })
197
+ .description('List workspace package names (used by shell completion)')
221
198
  .action(() => {
222
- startPluginsServer(cwd());
223
- });
224
- program.hook('preAction', async (thisCmd, actionCmd) => {
199
+ try {
200
+ const packages = getPackages(cwd());
201
+ for (const p of packages) {
202
+ const pkgJson = JSON.parse(readFileSync(join(p, 'package.json'), 'utf-8'));
203
+ process.stdout.write(pkgJson.name + '\n');
204
+ }
205
+ }
206
+ catch {
207
+ // Silently fail — completion should never error
208
+ }
209
+ });
210
+ program.hook('preAction', async (_thisCmd, actionCmd) => {
225
211
  const cmd = actionCmd.name();
226
- if (cmd === 'new' || cmd === 'login') {
212
+ if (cmd === 'new' || cmd === 'login' || cmd === 'completion' || cmd === '__list-packages') {
227
213
  return;
228
214
  }
229
215
  if (!validateWorkspace(cwd())) {
@@ -231,9 +217,15 @@ export const createProgram = () => {
231
217
  exit(1);
232
218
  }
233
219
  });
234
-
235
220
  return program;
236
221
  };
237
-
238
- const program = createProgram();
239
- program.parse(process.argv);
222
+ // Only parse when run directly (not when imported for testing/introspection)
223
+ const self = realpathSync(fileURLToPath(import.meta.url));
224
+ const entry = process.argv[1] ? realpathSync(resolve(process.argv[1])) : '';
225
+ if (self === entry) {
226
+ const program = createProgram();
227
+ program.parseAsync(process.argv).catch((err) => {
228
+ failed(err.message || 'An unexpected error occurred');
229
+ exit(1);
230
+ });
231
+ }
@@ -1,46 +1,25 @@
1
- import EventEmitter from 'node:events';
2
1
  import { existsSync } from 'node:fs';
3
2
  import { mkdir, writeFile } from 'node:fs/promises';
4
3
  import { sep } from 'node:path';
5
4
  import { authUtils } from './services/auth-utils.js';
6
-
7
- /**
8
- * @param {import('openid-client').Client} client
9
- * @param {string} tokenSetPath
10
- */
11
5
  export const auth = (client, tokenSetPath) => {
12
6
  const authStateNonce = {
13
7
  state: '',
14
8
  nonce: '',
15
9
  };
16
- /**
17
- *
18
- * @param {import('fastify').FastifyRequest} req
19
- * @param {import('fastify').FastifyReply} reply
20
- */
21
10
  return {
22
- /**
23
- * @param {import('fastify').FastifyInstance} server
24
- * @param {EventEmitter} eventEmitter
25
- */
26
11
  mount: (server, eventEmitter) => {
27
- server.get('/login', async (request, reply) => {
12
+ server.get('/login', async (_request, reply) => {
28
13
  const redirectUrl = await authUtils.login(client, authStateNonce);
29
14
  reply.redirect(redirectUrl);
30
15
  });
31
16
  server.get('/login-callback', async (request, reply) => {
32
- const { tokenSet } = await authUtils.loginCallback(
33
- client.callbackParams(request),
34
- client,
35
- authStateNonce,
36
- );
17
+ const { tokenSet } = await authUtils.loginCallback(client.callbackParams(request.raw), client, authStateNonce);
37
18
  const dirPath = tokenSetPath.substring(0, tokenSetPath.lastIndexOf(sep));
38
19
  if (!existsSync(dirPath)) {
39
20
  await mkdir(dirPath, { recursive: true });
40
21
  }
41
- await writeFile(tokenSetPath, JSON.stringify(tokenSet, null, 2), {
42
- encoding: 'utf-8',
43
- });
22
+ await writeFile(tokenSetPath, JSON.stringify(tokenSet, null, 2), { encoding: 'utf-8' });
44
23
  if (tokenSet) {
45
24
  reply.send('Login successful');
46
25
  eventEmitter.emit('cli-auth:login');