@vendian/cli 0.0.1 → 0.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vendian/cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Public Vendian CLI bootstrapper and launcher",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -10,17 +10,24 @@
10
10
  },
11
11
  "type": "module",
12
12
  "bin": {
13
- "vendian": "bin/vendian.js"
13
+ "vendian": "bin/vendian.cjs"
14
14
  },
15
15
  "files": [
16
16
  "bin/",
17
- "src/",
17
+ "cli-wrapper.cjs",
18
+ "LICENSE",
18
19
  "README.md"
19
20
  ],
20
21
  "scripts": {
22
+ "build": "node scripts/build-package.mjs",
23
+ "prepack": "npm run build",
24
+ "prepublishOnly": "npm test",
21
25
  "test": "node --test"
22
26
  },
23
27
  "engines": {
24
28
  "node": ">=18.18.0"
29
+ },
30
+ "devDependencies": {
31
+ "esbuild": "^0.28.0"
25
32
  }
26
33
  }
package/bin/vendian.js DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
- import { main } from '../src/main.js';
3
-
4
- main(process.argv.slice(2)).catch((error) => {
5
- const message = error && typeof error.message === 'string' ? error.message : String(error);
6
- console.error(`[vendian] ${message}`);
7
- process.exitCode = 1;
8
- });
package/src/auth.js DELETED
@@ -1,239 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import http from 'node:http';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import { spawnSync } from 'node:child_process';
6
- import { BACKEND_TARGETS } from './constants.js';
7
-
8
- const DEFAULT_OAUTH_REDIRECT_PORT = 8765;
9
-
10
- export function resolveApiUrl({ backend, apiUrl, env = process.env } = {}) {
11
- if (apiUrl) {
12
- return apiUrl.replace(/\/$/, '');
13
- }
14
- if (env.VENDIAN_API_URL) {
15
- return env.VENDIAN_API_URL.replace(/\/$/, '');
16
- }
17
- const target = backend || 'prod';
18
- const resolved = BACKEND_TARGETS[target];
19
- if (!resolved) {
20
- throw new Error(`Unknown Vendian backend '${target}'. Use local, dev, staging, prod, or --api-url.`);
21
- }
22
- return resolved;
23
- }
24
-
25
- export async function loginWithVendianOAuth({ backend, apiUrl, noBrowser = false, env = process.env } = {}) {
26
- const resolvedApiUrl = resolveApiUrl({ backend, apiUrl, env });
27
- const callback = await createCallbackServer(env);
28
- try {
29
- const config = await getOAuthConfig(resolvedApiUrl, callback.redirectUri);
30
- const codeVerifier = crypto.randomBytes(48).toString('base64url');
31
- const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64url');
32
- const state = crypto.randomBytes(18).toString('base64url');
33
- const authorizationUrl = authorizationUrlFor(config, { state, codeChallenge });
34
-
35
- if (noBrowser) {
36
- console.error(`Open this URL to authenticate the CLI: ${authorizationUrl}`);
37
- } else {
38
- openBrowser(authorizationUrl);
39
- }
40
-
41
- const callbackResult = await callback.wait();
42
- if (callbackResult.state !== state) {
43
- throw new Error('OAuth state mismatch');
44
- }
45
- const clerkToken = await exchangeCodeForClerkToken(config, callbackResult.code, codeVerifier, callback.redirectUri);
46
- const exchange = await postJson(`${resolvedApiUrl}/api/v1/cli/auth/oauth/exchange`, {
47
- clerkToken
48
- });
49
- return { apiUrl: resolvedApiUrl, ...exchange };
50
- } finally {
51
- await callback.close();
52
- }
53
- }
54
-
55
- async function getOAuthConfig(apiUrl, redirectUri) {
56
- const url = new URL(`${apiUrl}/api/v1/cli/auth/oauth/config`);
57
- url.searchParams.set('redirectUri', redirectUri);
58
- return getJson(url);
59
- }
60
-
61
- function authorizationUrlFor(config, { state, codeChallenge }) {
62
- const url = new URL(String(config.authorizationUrl));
63
- url.searchParams.set('response_type', 'code');
64
- url.searchParams.set('client_id', String(config.clientId));
65
- url.searchParams.set('redirect_uri', String(config.redirectUri));
66
- url.searchParams.set('scope', String(config.scopes || 'email profile'));
67
- url.searchParams.set('state', state);
68
- url.searchParams.set('code_challenge', codeChallenge);
69
- url.searchParams.set('code_challenge_method', 'S256');
70
- return url.toString();
71
- }
72
-
73
- async function exchangeCodeForClerkToken(config, code, codeVerifier, redirectUri) {
74
- const body = new URLSearchParams({
75
- grant_type: 'authorization_code',
76
- client_id: String(config.clientId),
77
- code,
78
- redirect_uri: redirectUri,
79
- code_verifier: codeVerifier
80
- });
81
- const payload = await postForm(String(config.tokenUrl), body);
82
- const token = payload.access_token || payload.id_token;
83
- if (!token) {
84
- throw new Error('OAuth token exchange did not return a Clerk token');
85
- }
86
- return String(token);
87
- }
88
-
89
- async function getJson(url) {
90
- const response = await fetch(url, { headers: { Accept: 'application/json' } });
91
- return decodeResponse(response);
92
- }
93
-
94
- async function postJson(url, body) {
95
- const response = await fetch(url, {
96
- method: 'POST',
97
- headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
98
- body: JSON.stringify(body)
99
- });
100
- return decodeResponse(response);
101
- }
102
-
103
- async function postForm(url, body) {
104
- const response = await fetch(url, {
105
- method: 'POST',
106
- headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
107
- body
108
- });
109
- return decodeResponse(response);
110
- }
111
-
112
- async function decodeResponse(response) {
113
- const text = await response.text();
114
- let payload = {};
115
- if (text) {
116
- try {
117
- payload = JSON.parse(text);
118
- } catch {
119
- payload = { error: text };
120
- }
121
- }
122
- if (!response.ok) {
123
- throw new Error(payload.message || payload.error || `HTTP ${response.status}`);
124
- }
125
- return payload;
126
- }
127
-
128
- async function createCallbackServer(env) {
129
- const port = Number(env.VENDIAN_CLI_OAUTH_REDIRECT_PORT || DEFAULT_OAUTH_REDIRECT_PORT);
130
- let server;
131
- let settled = false;
132
- let timeout;
133
- const waitPromise = new Promise((resolve, reject) => {
134
- timeout = setTimeout(() => {
135
- settled = true;
136
- reject(new Error('OAuth login timed out before callback completed'));
137
- }, 300_000);
138
- server = http.createServer((req, res) => {
139
- const url = new URL(req.url || '/', `http://${req.headers.host || '127.0.0.1'}`);
140
- const code = url.searchParams.get('code');
141
- const state = url.searchParams.get('state');
142
- const error = url.searchParams.get('error');
143
- const body = code
144
- ? 'Vendian CLI authentication complete. You can close this window.'
145
- : 'Vendian CLI authentication failed. Return to the terminal.';
146
- res.writeHead(code ? 200 : 400, {
147
- 'Content-Type': 'text/plain; charset=utf-8',
148
- 'Content-Length': Buffer.byteLength(body)
149
- });
150
- res.end(body);
151
- clearTimeout(timeout);
152
- if (settled) {
153
- return;
154
- }
155
- settled = true;
156
- if (error) {
157
- reject(new Error(`OAuth login failed: ${error}`));
158
- return;
159
- }
160
- if (!code) {
161
- reject(new Error('OAuth callback did not include an authorization code'));
162
- return;
163
- }
164
- resolve({ code, state });
165
- });
166
- server.on('error', reject);
167
- server.listen(port, '127.0.0.1');
168
- });
169
- await new Promise((resolve, reject) => {
170
- server.once('listening', resolve);
171
- server.once('error', reject);
172
- });
173
-
174
- return {
175
- redirectUri: `http://127.0.0.1:${server.address().port}/callback`,
176
- wait: () => waitPromise,
177
- close: () => new Promise((resolve) => server.close(resolve))
178
- };
179
- }
180
-
181
- function openBrowser(url) {
182
- const platform = process.platform;
183
- if (platform === 'win32') {
184
- spawnSync(...buildWindowsOpenCommand(url), { stdio: 'ignore', shell: false });
185
- return;
186
- }
187
- if (platform === 'darwin') {
188
- spawnSync('open', [url], { stdio: 'ignore', shell: false });
189
- return;
190
- }
191
- spawnSync('xdg-open', [url], { stdio: 'ignore', shell: false });
192
- }
193
-
194
- export function buildWindowsOpenCommand(url) {
195
- return ['rundll32.exe', ['url.dll,FileProtocolHandler', String(url)]];
196
- }
197
-
198
- export function cloudConfigPath(env = process.env, platform = process.platform) {
199
- if (env.VENDIAN_CLOUD_CONFIG) {
200
- return path.resolve(env.VENDIAN_CLOUD_CONFIG);
201
- }
202
- if (platform === 'win32') {
203
- const root = env.APPDATA || path.join(process.env.USERPROFILE || '', 'AppData', 'Roaming');
204
- return path.win32.join(root, 'Vendian', 'cloud-auth.json');
205
- }
206
- const root = env.XDG_CONFIG_HOME || path.join(process.env.HOME || '', '.config');
207
- return path.posix.join(root, 'vendian', 'cloud-auth.json');
208
- }
209
-
210
- export function saveCloudToken(token, { env = process.env, platform = process.platform } = {}) {
211
- const file = cloudConfigPath(env, platform);
212
- let raw = { version: 2, profiles: {}, active_api_url: token.apiUrl };
213
- try {
214
- const existing = JSON.parse(fs.readFileSync(file, 'utf8'));
215
- if (existing && typeof existing === 'object' && existing.profiles && typeof existing.profiles === 'object') {
216
- raw.profiles = existing.profiles;
217
- }
218
- } catch {
219
- // Missing or invalid config is replaced.
220
- }
221
- raw.active_api_url = token.apiUrl;
222
- raw.profiles[token.apiUrl] = {
223
- api_url: token.apiUrl,
224
- access_token: token.accessToken,
225
- user_id: token.userId,
226
- email: token.email,
227
- expires_at: token.expiresAt,
228
- scopes: token.scopes,
229
- tooling_eligible: token.toolingEligible
230
- };
231
- fs.mkdirSync(path.dirname(file), { recursive: true });
232
- fs.writeFileSync(file, `${JSON.stringify(raw, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
233
- try {
234
- fs.chmodSync(file, 0o600);
235
- } catch {
236
- // Best effort on Windows filesystems.
237
- }
238
- return file;
239
- }
package/src/config.js DELETED
@@ -1,40 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { CONFIG_VERSION } from './constants.js';
4
- import { configPath } from './paths.js';
5
-
6
- export function loadConfig(env = process.env, platform = process.platform) {
7
- const file = configPath(env, platform);
8
- try {
9
- const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
10
- return typeof parsed === 'object' && parsed !== null ? parsed : {};
11
- } catch (error) {
12
- if (error && error.code === 'ENOENT') {
13
- return {};
14
- }
15
- return {};
16
- }
17
- }
18
-
19
- export function saveConfig(config, env = process.env, platform = process.platform) {
20
- const file = configPath(env, platform);
21
- fs.mkdirSync(path.dirname(file), { recursive: true });
22
- const next = { version: CONFIG_VERSION, ...config };
23
- fs.writeFileSync(file, `${JSON.stringify(next, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
24
- try {
25
- fs.chmodSync(file, 0o600);
26
- } catch {
27
- // Best effort on Windows filesystems.
28
- }
29
- return file;
30
- }
31
-
32
- export function redact(value) {
33
- if (!value || typeof value !== 'string') {
34
- return value;
35
- }
36
- if (value.length <= 8) {
37
- return '********';
38
- }
39
- return `${value.slice(0, 4)}...${value.slice(-4)}`;
40
- }
package/src/constants.js DELETED
@@ -1,15 +0,0 @@
1
- export const DEFAULT_GITLAB_HOST = 'gitlab.com';
2
- export const DEFAULT_SDK_PUBLIC_PROJECT_ID = '77150592';
3
- export const DEFAULT_SDK_RUNTIME_PROJECT_ID = '79410876';
4
- export const PUBLIC_PACKAGE = 'vendian-agents[full]';
5
- export const RUNTIME_PACKAGE = 'vendian-agents-runtime';
6
- export const CONFIG_VERSION = 1;
7
-
8
- export const BACKEND_TARGETS = {
9
- local: 'http://localhost:3000',
10
- localhost: 'http://localhost:3000',
11
- dev: 'https://api.dev.vendian.ai',
12
- staging: 'https://api.staging.vendian.ai',
13
- prod: 'https://api.vendian.ai',
14
- production: 'https://api.vendian.ai'
15
- };
package/src/doctor.js DELETED
@@ -1,23 +0,0 @@
1
- import fs from 'node:fs';
2
- import { loadConfig, redact } from './config.js';
3
- import { registryConfig } from './install.js';
4
- import { managedVenvPath, venvPython, venvVendian } from './paths.js';
5
- import { findPython, hasUv, pythonVersion, verifyVendianImports } from './python.js';
6
-
7
- export function doctor({ env = process.env, platform = process.platform } = {}) {
8
- const config = loadConfig(env, platform);
9
- const venvPath = managedVenvPath(env, platform);
10
- const pythonPath = venvPython(venvPath, platform);
11
- const vendianPath = venvVendian(venvPath, platform);
12
- const registry = registryConfig(config, env, platform);
13
-
14
- console.log('Vendian doctor');
15
- console.log(`Home: ${venvPath}`);
16
- console.log(`System Python 3.11+: ${findPython(platform) ? 'yes' : 'no'}`);
17
- console.log(`uv: ${hasUv() ? 'yes' : 'no, will use pip fallback'}`);
18
- console.log(`Managed Python: ${fs.existsSync(pythonPath) ? pythonVersion(pythonPath) || 'present' : 'missing'}`);
19
- console.log(`Vendian executable: ${fs.existsSync(vendianPath) ? vendianPath : 'missing'}`);
20
- console.log(`Vendian imports: ${fs.existsSync(pythonPath) && verifyVendianImports(pythonPath) ? 'ok' : 'missing'}`);
21
- console.log(`GitLab host: ${registry.gitlabHost}`);
22
- console.log(`Package token: ${registry.token ? `${redact(registry.token)} (${registry.tokenSource})` : 'missing'}`);
23
- }
package/src/forward.js DELETED
@@ -1,47 +0,0 @@
1
- import fs from 'node:fs';
2
- import { loadConfig, saveConfig } from './config.js';
3
- import { installVendianPackages, registryConfig } from './install.js';
4
- import { managedVenvPath, venvPython, venvVendian } from './paths.js';
5
- import { spawnForward } from './process.js';
6
-
7
- const AUTO_UPDATE_INTERVAL_MS = 24 * 60 * 60 * 1000;
8
-
9
- export async function forwardToPythonVendian(args, { env = process.env, platform = process.platform } = {}) {
10
- const venvPath = managedVenvPath(env, platform);
11
- const vendianPath = venvVendian(venvPath, platform);
12
- if (!fs.existsSync(vendianPath)) {
13
- throw new Error('Vendian is not set up yet. Run `vendian login` first.');
14
- }
15
- maybeAutoUpdateManagedEnv({ env, platform, venvPath });
16
- const code = await spawnForward(vendianPath, args, { env });
17
- process.exitCode = code;
18
- }
19
-
20
- export function maybeAutoUpdateManagedEnv({ env = process.env, platform = process.platform, venvPath = managedVenvPath(env, platform) } = {}) {
21
- if (env.VENDIAN_SKIP_AUTO_UPDATE === '1') {
22
- return false;
23
- }
24
- const config = loadConfig(env, platform);
25
- const lastUpdate = Date.parse(config.lastManagedUpdateAt || '');
26
- if (Number.isFinite(lastUpdate) && Date.now() - lastUpdate < AUTO_UPDATE_INTERVAL_MS) {
27
- return false;
28
- }
29
- const registry = registryConfig(config, env);
30
- if (!registry.token) {
31
- return false;
32
- }
33
- const pythonPath = venvPython(venvPath, platform);
34
- if (!fs.existsSync(pythonPath)) {
35
- return false;
36
- }
37
- try {
38
- console.error('[vendian] Checking managed CLI/runtime updates...');
39
- installVendianPackages({ pythonPath, venvPath, config, env });
40
- saveConfig({ ...config, lastManagedUpdateAt: new Date().toISOString() }, env, platform);
41
- return true;
42
- } catch (error) {
43
- const message = error && typeof error.message === 'string' ? error.message : String(error);
44
- console.error(`[vendian] Update check failed; continuing with installed CLI. ${message}`);
45
- return false;
46
- }
47
- }
package/src/install.js DELETED
@@ -1,105 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import {
4
- DEFAULT_GITLAB_HOST,
5
- DEFAULT_SDK_PUBLIC_PROJECT_ID,
6
- DEFAULT_SDK_RUNTIME_PROJECT_ID,
7
- PUBLIC_PACKAGE,
8
- RUNTIME_PACKAGE
9
- } from './constants.js';
10
- import { runInherit } from './process.js';
11
- import { hasUv } from './python.js';
12
- import { loadPackageTokenSecret } from './secret-store.js';
13
-
14
- export function registryConfig(config = {}, env = process.env, platform = process.platform) {
15
- const gitlabHost = env.GITLAB_HOST || config.gitlabHost || DEFAULT_GITLAB_HOST;
16
- const username = env.GITLAB_USERNAME || config.gitlabUsername || '__token__';
17
- const sdkProjectId = env.SDK_PUBLIC_PROJECT_ID || config.sdkPublicProjectId || DEFAULT_SDK_PUBLIC_PROJECT_ID;
18
- const runtimeProjectId = env.SDK_RUNTIME_PROJECT_ID || config.sdkRuntimeProjectId || DEFAULT_SDK_RUNTIME_PROJECT_ID;
19
- const secretToken = loadPackageTokenSecret(config, platform);
20
- const token = env.GITLAB_TOKEN || config.gitlabToken || secretToken || '';
21
- const tokenSource = env.GITLAB_TOKEN ? 'env' : config.gitlabToken ? 'config' : secretToken ? 'secret-store' : 'missing';
22
- const vendianAgentsVersion = env.VENDIAN_AGENTS_VERSION || config.vendianAgentsVersion || '';
23
- const vendianRuntimeVersion = env.VENDIAN_AGENTS_RUNTIME_VERSION || config.vendianAgentsRuntimeVersion || '';
24
-
25
- return {
26
- gitlabHost,
27
- username,
28
- sdkProjectId,
29
- runtimeProjectId,
30
- token,
31
- tokenSource,
32
- vendianAgentsVersion,
33
- vendianRuntimeVersion
34
- };
35
- }
36
-
37
- export function buildIndexUrls(registry) {
38
- if (!registry.token) {
39
- return null;
40
- }
41
- const username = encodeURIComponent(registry.username || '__token__');
42
- const token = encodeURIComponent(registry.token);
43
- const sdkIndexUrl = `https://${username}:${token}@${registry.gitlabHost}/api/v4/projects/${registry.sdkProjectId}/packages/pypi/simple`;
44
- const runtimeIndexUrl = `https://${username}:${token}@${registry.gitlabHost}/api/v4/projects/${registry.runtimeProjectId}/packages/pypi/simple`;
45
- return { sdkIndexUrl, runtimeIndexUrl };
46
- }
47
-
48
- export function packageSpecs(registry) {
49
- const publicSpec = registry.vendianAgentsVersion
50
- ? `${PUBLIC_PACKAGE}==${registry.vendianAgentsVersion}`
51
- : PUBLIC_PACKAGE;
52
- const runtimeSpec = registry.vendianRuntimeVersion
53
- ? `${RUNTIME_PACKAGE}==${registry.vendianRuntimeVersion}`
54
- : RUNTIME_PACKAGE;
55
- return [publicSpec, runtimeSpec];
56
- }
57
-
58
- export function installVendianPackages({ pythonPath, venvPath, config, env = process.env, platform = process.platform }) {
59
- const registry = registryConfig(config, env, platform);
60
- const indexes = buildIndexUrls(registry);
61
- if (!indexes) {
62
- throw new Error('A GitLab package token is required until backend-issued package tokens are available. Run `vendian setup` or set GITLAB_TOKEN.');
63
- }
64
-
65
- const specs = packageSpecs(registry);
66
- const installArgs = [
67
- 'install',
68
- '--upgrade',
69
- ...specs,
70
- '--index-url',
71
- indexes.sdkIndexUrl,
72
- '--extra-index-url',
73
- indexes.runtimeIndexUrl,
74
- '--extra-index-url',
75
- 'https://pypi.org/simple'
76
- ];
77
-
78
- let status;
79
- if (hasUv()) {
80
- status = runInherit('uv', ['pip', ...installArgs, '--python', pythonPath]);
81
- } else {
82
- status = runInherit(pythonPath, ['-m', 'pip', ...installArgs]);
83
- }
84
- if (status !== 0) {
85
- throw new Error('Could not install Vendian SDK/runtime packages. Check token access and package versions.');
86
- }
87
-
88
- writeInstallMarker(venvPath, {
89
- gitlabHost: registry.gitlabHost,
90
- gitlabUsername: registry.username,
91
- sdkProjectId: registry.sdkProjectId,
92
- runtimeProjectId: registry.runtimeProjectId,
93
- vendianAgentsVersion: registry.vendianAgentsVersion || 'latest',
94
- vendianAgentsRuntimeVersion: registry.vendianRuntimeVersion || 'latest'
95
- });
96
- }
97
-
98
- export function writeInstallMarker(venvPath, marker) {
99
- fs.mkdirSync(venvPath, { recursive: true });
100
- fs.writeFileSync(
101
- path.join(venvPath, '.vendian-bootstrap.json'),
102
- `${JSON.stringify({ version: 1, ...marker }, null, 2)}\n`,
103
- 'utf8'
104
- );
105
- }
package/src/main.js DELETED
@@ -1,80 +0,0 @@
1
- import { doctor } from './doctor.js';
2
- import { forwardToPythonVendian } from './forward.js';
3
- import { setup } from './setup.js';
4
-
5
- function printHelp() {
6
- console.log(`Vendian CLI bootstrapper
7
-
8
- Usage:
9
- vendian login Sign in and install the private Vendian CLI/runtime
10
- vendian setup Alias for vendian login
11
- vendian doctor Check local bootstrap health
12
- vendian update Update the managed Vendian CLI/runtime
13
- vendian <command> Forward to the managed Python Vendian CLI
14
-
15
- Examples:
16
- vendian login
17
- vendian login --backend prod
18
- vendian cloud local serve --agents-dir ./agents
19
-
20
- Environment:
21
- VENDIAN_CLI_HOME Override managed CLI home
22
- VENDIAN_API_URL Override Vendian backend API URL
23
- GITLAB_TOKEN Local-dev package registry token fallback
24
- GITLAB_USERNAME Local-dev package registry username fallback
25
- GITLAB_HOST Defaults to gitlab.com
26
- SDK_PUBLIC_PROJECT_ID Defaults to Vendian SDK project
27
- SDK_RUNTIME_PROJECT_ID Defaults to Vendian runtime project
28
- `);
29
- }
30
-
31
- export async function main(argv) {
32
- const [command, ...rest] = argv;
33
- if (!command || command === '--help' || command === '-h') {
34
- printHelp();
35
- return;
36
- }
37
- if (command === '--version' || command === 'version') {
38
- console.log('0.1.0');
39
- return;
40
- }
41
- if (isBootstrapCommand(command)) {
42
- await setup(parseSetupOptions(rest));
43
- return;
44
- }
45
- if (command === 'doctor') {
46
- doctor();
47
- return;
48
- }
49
- if (command === 'update') {
50
- await setup({ nonInteractive: true });
51
- return;
52
- }
53
- await forwardToPythonVendian(argv);
54
- }
55
-
56
- export function isBootstrapCommand(command) {
57
- return command === 'login' || command === 'setup';
58
- }
59
-
60
- function parseSetupOptions(args) {
61
- const options = {
62
- nonInteractive: args.includes('--yes') || args.includes('--non-interactive'),
63
- noBrowser: args.includes('--no-browser')
64
- };
65
- for (let index = 0; index < args.length; index += 1) {
66
- const arg = args[index];
67
- if (arg === '--backend' || arg === '-b') {
68
- options.backend = args[index + 1];
69
- index += 1;
70
- } else if (arg.startsWith('--backend=')) {
71
- options.backend = arg.slice('--backend='.length);
72
- } else if (arg === '--api-url') {
73
- options.apiUrl = args[index + 1];
74
- index += 1;
75
- } else if (arg.startsWith('--api-url=')) {
76
- options.apiUrl = arg.slice('--api-url='.length);
77
- }
78
- }
79
- return options;
80
- }
package/src/paths.js DELETED
@@ -1,43 +0,0 @@
1
- import os from 'node:os';
2
- import path from 'node:path';
3
-
4
- function pathApi(platform) {
5
- return platform === 'win32' ? path.win32 : path.posix;
6
- }
7
-
8
- export function vendianHome(env = process.env, platform = process.platform) {
9
- if (env.VENDIAN_CLI_HOME) {
10
- return pathApi(platform).resolve(env.VENDIAN_CLI_HOME);
11
- }
12
- if (platform === 'win32') {
13
- const root = env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
14
- return path.win32.join(root, 'Vendian', 'cli');
15
- }
16
- return path.posix.join(os.homedir(), '.vendian', 'cli');
17
- }
18
-
19
- export function configPath(env = process.env, platform = process.platform) {
20
- if (env.VENDIAN_CLI_CONFIG) {
21
- return pathApi(platform).resolve(env.VENDIAN_CLI_CONFIG);
22
- }
23
- return pathApi(platform).join(vendianHome(env, platform), 'config.json');
24
- }
25
-
26
- export function managedVenvPath(env = process.env, platform = process.platform) {
27
- if (env.VENDIAN_CLI_VENV) {
28
- return pathApi(platform).resolve(env.VENDIAN_CLI_VENV);
29
- }
30
- return pathApi(platform).join(vendianHome(env, platform), '.venv');
31
- }
32
-
33
- export function venvPython(venvPath, platform = process.platform) {
34
- return platform === 'win32'
35
- ? path.win32.join(venvPath, 'Scripts', 'python.exe')
36
- : path.posix.join(venvPath, 'bin', 'python');
37
- }
38
-
39
- export function venvVendian(venvPath, platform = process.platform) {
40
- return platform === 'win32'
41
- ? path.win32.join(venvPath, 'Scripts', 'vendian.exe')
42
- : path.posix.join(venvPath, 'bin', 'vendian');
43
- }