@bulkgrid/cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/{auth-C7pTl5XB.js → auth-DQ_NoZtw.js} +5 -9
- package/dist/{auth-C7pTl5XB.js.map → auth-DQ_NoZtw.js.map} +1 -1
- package/dist/cli.js +30 -13
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +0 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -71,3 +71,7 @@ bulkgrid sources status <sourceId>
|
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
`analyze` starts deeper analysis and may create a crawl run. `add --input '<json>'` creates/subscribes using explicit source configuration. `recrawl` starts a manual refresh. `collections`, `rules`, and `include` inspect and update collection access. All output JSON; none poll or retry mutations automatically. Use the least API-key scopes needed for the chosen operation. See the source-management skill and CLI documentation for the full workflow and permission mapping.
|
|
74
|
+
|
|
75
|
+
## Change monitors
|
|
76
|
+
|
|
77
|
+
Version 0.5.0 adds monitor creation, settings, history, event comparison, retries, webhook secret rotation, and Slack channel discovery. Use `client.monitors` in the SDKs or `bulkgrid monitors --help` in the CLI. These operations require API keys with `monitors:read` and/or `monitors:write`; OAuth remains search-only. See the [monitor guide](https://bulkgrid.com/docs/monitors) for examples and notification behavior.
|
|
@@ -7,7 +7,7 @@ import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypt
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { chmod, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
9
9
|
import { createServer } from "node:http";
|
|
10
|
-
|
|
10
|
+
// src/init.ts
|
|
11
11
|
const DEFAULT_SERVER_NAME = "bulkgrid";
|
|
12
12
|
const API_KEY_ENV_VAR = "BULKGRID_API_KEY";
|
|
13
13
|
const MCP_URL_ENV_VAR = "BULKGRID_MCP_URL";
|
|
@@ -336,8 +336,7 @@ async function runInitCommand(options) {
|
|
|
336
336
|
else if (agent === "codex") results.push(setupCodex(context));
|
|
337
337
|
return results;
|
|
338
338
|
}
|
|
339
|
-
|
|
340
|
-
//#region src/authStorage.ts
|
|
339
|
+
// src/authStorage.ts
|
|
341
340
|
const credentialsSchema = z.object({
|
|
342
341
|
origin: z.string().url(),
|
|
343
342
|
issuer: z.string().url(),
|
|
@@ -416,8 +415,7 @@ var AuthStorage = class {
|
|
|
416
415
|
}
|
|
417
416
|
}
|
|
418
417
|
};
|
|
419
|
-
|
|
420
|
-
//#region src/oauthCallback.ts
|
|
418
|
+
// src/oauthCallback.ts
|
|
421
419
|
const CLI_CALLBACK_PATH = "/bulkgrid/cli/callback";
|
|
422
420
|
async function listenForOAuthCallback(state, issuer, timeoutMs = 3e5) {
|
|
423
421
|
let resolveCode;
|
|
@@ -495,8 +493,7 @@ async function listenForOAuthCallback(state, issuer, timeoutMs = 3e5) {
|
|
|
495
493
|
}
|
|
496
494
|
};
|
|
497
495
|
}
|
|
498
|
-
|
|
499
|
-
//#region src/auth.ts
|
|
496
|
+
// src/auth.ts
|
|
500
497
|
const DEFAULT_ORIGIN = "https://bulkgrid.com";
|
|
501
498
|
const identityScopes = "openid email profile";
|
|
502
499
|
const metadataSchema = z.object({
|
|
@@ -717,7 +714,6 @@ var CliAuth = class {
|
|
|
717
714
|
});
|
|
718
715
|
}
|
|
719
716
|
};
|
|
720
|
-
//#endregion
|
|
721
717
|
export { resolveOrigin as n, runInitCommand as r, CliAuth as t };
|
|
722
718
|
|
|
723
|
-
//# sourceMappingURL=auth-
|
|
719
|
+
//# sourceMappingURL=auth-DQ_NoZtw.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-C7pTl5XB.js","names":[],"sources":["../src/init.ts","../src/authStorage.ts","../src/oauthCallback.ts","../src/auth.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { checkbox, confirm, input, password, select } from '@inquirer/prompts';\n\nconst DEFAULT_SERVER_NAME = 'bulkgrid';\nconst API_KEY_ENV_VAR = 'BULKGRID_API_KEY';\nconst MCP_URL_ENV_VAR = 'BULKGRID_MCP_URL';\nconst DASHBOARD_API_KEYS_URL = 'https://bulkgrid.com/dashboard/settings/api-keys';\n\ntype AgentName = 'cursor' | 'vscode' | 'claude' | 'codex';\ntype AuthMode = 'browser' | 'manual' | 'skip';\n\nconst AGENT_CHOICES: readonly { label: string; value: AgentName }[] = [\n { label: 'Cursor', value: 'cursor' },\n { label: 'VS Code', value: 'vscode' },\n { label: 'Claude Code', value: 'claude' },\n { label: 'Codex', value: 'codex' },\n];\n\ninterface InitFlags {\n readonly all?: boolean;\n readonly cursor?: boolean;\n readonly vscode?: boolean;\n readonly claude?: boolean;\n readonly codex?: boolean;\n}\n\nexport interface InitCommandOptions extends InitFlags {\n readonly mcpUrl?: string;\n readonly apiKey?: string;\n readonly global?: boolean;\n readonly project?: boolean;\n readonly yes?: boolean;\n readonly writeApiKey?: boolean;\n readonly installGlobal?: boolean;\n readonly auth?: AuthMode;\n}\n\ninterface InitContext {\n readonly agents: readonly AgentName[];\n readonly mcpUrl: string;\n readonly apiKey?: string;\n readonly scope: 'project' | 'global';\n readonly writeApiKey: boolean;\n}\n\ntype McpConfigContext = Pick<InitContext, 'apiKey' | 'mcpUrl' | 'writeApiKey'>;\nexport type JsonObject = { [key: string]: JsonValue };\ntype JsonValue = string | number | boolean | null | JsonObject | JsonValue[];\n\ninterface SetupResult {\n readonly agent: AgentName;\n readonly status: 'configured' | 'skipped';\n readonly message: string;\n}\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseJsonObject(filePath: string): JsonObject {\n if (!existsSync(filePath)) {\n return {};\n }\n\n const parsed: unknown = JSON.parse(readFileSync(filePath, 'utf8'));\n if (!isJsonObject(parsed)) {\n throw new Error(`${filePath} must contain a JSON object`);\n }\n\n return parsed;\n}\n\nfunction writeJsonFile(filePath: string, data: JsonObject): void {\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\\n`);\n}\n\nfunction getObjectProperty(parent: JsonObject, key: string): JsonObject {\n const current = parent[key];\n if (isJsonObject(current)) {\n return current;\n }\n\n const next: JsonObject = {};\n parent[key] = next;\n return next;\n}\n\nfunction buildAuthorizationHeader(context: McpConfigContext, inputExpression: string): string {\n if (context.writeApiKey && context.apiKey) {\n return `Bearer ${context.apiKey}`;\n }\n\n return `Bearer ${inputExpression}`;\n}\n\nfunction buildCursorServer(context: McpConfigContext): JsonObject {\n return {\n url: context.mcpUrl,\n headers: {\n Authorization: buildAuthorizationHeader(context, `\\${env:${API_KEY_ENV_VAR}}`),\n },\n };\n}\n\nexport function mergeCursorConfig(existing: JsonObject, context: McpConfigContext): JsonObject {\n const next = { ...existing };\n const servers = getObjectProperty(next, 'mcpServers');\n servers[DEFAULT_SERVER_NAME] = buildCursorServer(context);\n return next;\n}\n\nfunction buildVsCodeConfig(context: McpConfigContext): JsonObject {\n return {\n inputs: [\n {\n type: 'promptString',\n id: 'bulkgrid-api-key',\n description: 'Bulkgrid API Key',\n password: true,\n },\n ],\n servers: {\n [DEFAULT_SERVER_NAME]: {\n type: 'http',\n url: context.mcpUrl,\n headers: {\n Authorization: buildAuthorizationHeader(context, '${input:bulkgrid-api-key}'),\n },\n },\n },\n };\n}\n\nexport function mergeVsCodeConfig(existing: JsonObject, context: McpConfigContext): JsonObject {\n const next = { ...existing };\n const config = buildVsCodeConfig(context);\n const existingServers = getObjectProperty(next, 'servers');\n const configServers = getObjectProperty(config, 'servers');\n existingServers[DEFAULT_SERVER_NAME] = configServers[DEFAULT_SERVER_NAME] ?? {};\n\n if (!Array.isArray(next.inputs)) {\n next.inputs = config.inputs ?? [];\n return next;\n }\n\n const hasInput = next.inputs.some(item => isJsonObject(item) && item.id === 'bulkgrid-api-key');\n if (!hasInput && Array.isArray(config.inputs)) {\n next.inputs = [...next.inputs, ...config.inputs];\n }\n\n return next;\n}\n\nfunction resolveCursorPath(scope: InitContext['scope']): string {\n if (scope === 'global') {\n return join(homedir(), '.cursor', 'mcp.json');\n }\n\n return join(process.cwd(), '.cursor', 'mcp.json');\n}\n\nfunction resolveVsCodePath(scope: InitContext['scope']): string {\n if (scope === 'global') {\n if (process.platform === 'darwin') {\n return join(homedir(), 'Library', 'Application Support', 'Code', 'User', 'mcp.json');\n }\n if (process.platform === 'win32') {\n return join(homedir(), 'AppData', 'Roaming', 'Code', 'User', 'mcp.json');\n }\n\n return join(homedir(), '.config', 'Code', 'User', 'mcp.json');\n }\n\n return join(process.cwd(), '.vscode', 'mcp.json');\n}\n\nfunction setupCursor(context: InitContext): SetupResult {\n const filePath = resolveCursorPath(context.scope);\n const config = mergeCursorConfig(parseJsonObject(filePath), context);\n writeJsonFile(filePath, config);\n\n return {\n agent: 'cursor',\n status: 'configured',\n message: `Wrote ${filePath}`,\n };\n}\n\nfunction setupVsCode(context: InitContext): SetupResult {\n const filePath = resolveVsCodePath(context.scope);\n const config = mergeVsCodeConfig(parseJsonObject(filePath), context);\n writeJsonFile(filePath, config);\n\n return {\n agent: 'vscode',\n status: 'configured',\n message: `Wrote ${filePath}`,\n };\n}\n\nfunction commandExists(command: string): boolean {\n const result = spawnSync(command, ['--version'], { encoding: 'utf8', stdio: 'ignore' });\n return result.status === 0;\n}\n\nfunction runCommand(command: string, args: readonly string[]): void {\n const result = spawnSync(command, args, { encoding: 'utf8', stdio: 'inherit' });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw new Error(`${command} ${args.join(' ')} failed with exit code ${result.status ?? 'unknown'}`);\n }\n}\n\nfunction printInitBanner(): void {\n console.log('');\n console.log(' ▦ Bulkgrid init');\n console.log('');\n}\n\nasync function promptForConfirmation(message: string, defaultValue: boolean): Promise<boolean> {\n return confirm({\n message,\n default: defaultValue,\n });\n}\n\nasync function promptForSelect<TValue extends string>(\n message: string,\n choices: readonly { label: string; value: TValue }[],\n): Promise<TValue> {\n return select({\n message,\n choices: choices.map(choice => ({\n name: choice.label,\n value: choice.value,\n })),\n });\n}\n\nasync function promptForMultiSelect<TValue extends string>(\n message: string,\n choices: readonly { label: string; value: TValue }[],\n): Promise<readonly TValue[]> {\n return checkbox({\n message,\n choices: choices.map(choice => ({\n name: choice.label,\n value: choice.value,\n checked: true,\n })),\n required: true,\n pageSize: choices.length,\n });\n}\n\nasync function maybeInstallGlobally(options: InitCommandOptions): Promise<void> {\n if (options.installGlobal) {\n runCommand('npm', ['install', '-g', '@bulkgrid/cli']);\n return;\n }\n\n if (options.yes) {\n return;\n }\n\n const shouldInstall = await promptForConfirmation('Install @bulkgrid/cli globally?', false);\n if (shouldInstall) {\n runCommand('npm', ['install', '-g', '@bulkgrid/cli']);\n }\n}\n\nfunction openBrowser(url: string): void {\n let command: string;\n let args: string[];\n\n if (process.platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (process.platform === 'win32') {\n command = 'cmd';\n args = ['/c', 'start', '', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n const result = spawnSync(command, args, { encoding: 'utf8', stdio: 'ignore' });\n if (result.status !== 0) {\n console.log(`Open ${url} to create a Bulkgrid API key.`);\n }\n}\n\nasync function resolveApiKey(options: InitCommandOptions): Promise<string | undefined> {\n const configuredApiKey = options.apiKey ?? process.env[API_KEY_ENV_VAR];\n if (configuredApiKey || options.yes) {\n return configuredApiKey;\n }\n\n const authMode =\n options.auth ??\n (await promptForSelect('Authenticate to Bulkgrid', [\n { label: 'Open the dashboard and paste a new API key', value: 'browser' },\n { label: 'Enter an existing API key', value: 'manual' },\n { label: 'Skip this step', value: 'skip' },\n ]));\n\n if (authMode === 'skip') {\n console.log(`Skipped. Set ${API_KEY_ENV_VAR} later or use client-side prompts.`);\n return undefined;\n }\n\n if (authMode === 'browser') {\n openBrowser(DASHBOARD_API_KEYS_URL);\n console.log('Create an API key with mcp:use and search:query scopes.');\n }\n\n const apiKey = await password({\n message: 'Bulkgrid API key',\n mask: '*',\n validate: value => value.trim().length > 0 || 'Enter a Bulkgrid API key.',\n });\n return apiKey || undefined;\n}\n\nfunction setupCodex(context: InitContext): SetupResult {\n if (!commandExists('codex')) {\n return {\n agent: 'codex',\n status: 'skipped',\n message: 'codex command was not found',\n };\n }\n\n runCommand('codex', ['mcp', 'add', DEFAULT_SERVER_NAME, '--url', context.mcpUrl, '--bearer-token-env-var', API_KEY_ENV_VAR]);\n\n return {\n agent: 'codex',\n status: 'configured',\n message: `Registered ${DEFAULT_SERVER_NAME} with codex mcp add`,\n };\n}\n\nfunction setupClaude(context: InitContext): SetupResult {\n if (!commandExists('claude')) {\n return {\n agent: 'claude',\n status: 'skipped',\n message: 'claude command was not found',\n };\n }\n\n if (!context.apiKey) {\n return {\n agent: 'claude',\n status: 'skipped',\n message: `Set ${API_KEY_ENV_VAR} or pass --api-key to configure Claude Code`,\n };\n }\n\n const args = ['mcp', 'add', '--transport', 'http'];\n if (context.scope === 'global') {\n args.push('--scope', 'user');\n }\n args.push(DEFAULT_SERVER_NAME, context.mcpUrl, '--header', `Authorization: Bearer ${context.apiKey}`);\n runCommand('claude', args);\n\n return {\n agent: 'claude',\n status: 'configured',\n message: `Registered ${DEFAULT_SERVER_NAME} with claude mcp add`,\n };\n}\n\nasync function resolveAgents(options: InitCommandOptions): Promise<readonly AgentName[]> {\n if (options.all || (!options.cursor && !options.vscode && !options.claude && !options.codex)) {\n if (!options.all && !options.yes) {\n const shouldConfigure = await promptForConfirmation('Configure the Bulkgrid MCP server for clients?', true);\n if (!shouldConfigure) {\n return [];\n }\n\n return promptForMultiSelect('Choose MCP clients to configure:', AGENT_CHOICES);\n }\n\n return ['cursor', 'vscode', 'claude', 'codex'];\n }\n\n const agents: AgentName[] = [];\n if (options.cursor) {\n agents.push('cursor');\n }\n if (options.vscode) {\n agents.push('vscode');\n }\n if (options.claude) {\n agents.push('claude');\n }\n if (options.codex) {\n agents.push('codex');\n }\n\n return agents;\n}\n\nasync function promptForValue(message: string): Promise<string> {\n return input({\n message,\n validate: value => value.trim().length > 0 || 'Enter a value.',\n });\n}\n\nasync function buildContext(options: InitCommandOptions): Promise<InitContext> {\n const configuredUrl = options.mcpUrl ?? process.env[MCP_URL_ENV_VAR];\n const mcpUrl = configuredUrl ?? (options.yes ? undefined : await promptForValue('Bulkgrid MCP URL: '));\n if (!mcpUrl) {\n throw new Error(`Missing MCP URL. Pass --mcp-url or set ${MCP_URL_ENV_VAR}.`);\n }\n\n const apiKey = await resolveApiKey(options);\n const agents = await resolveAgents(options);\n\n return {\n agents,\n mcpUrl,\n apiKey,\n scope: options.global ? 'global' : 'project',\n writeApiKey: options.writeApiKey ?? false,\n };\n}\n\nexport async function runInitCommand(options: InitCommandOptions): Promise<readonly SetupResult[]> {\n printInitBanner();\n await maybeInstallGlobally(options);\n\n const context = await buildContext(options);\n const results: SetupResult[] = [];\n\n for (const agent of context.agents) {\n if (agent === 'cursor') {\n results.push(setupCursor(context));\n } else if (agent === 'vscode') {\n results.push(setupVsCode(context));\n } else if (agent === 'claude') {\n results.push(setupClaude(context));\n } else if (agent === 'codex') {\n results.push(setupCodex(context));\n }\n }\n\n return results;\n}\n","import { createHash, randomUUID } from 'node:crypto';\nimport { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { z } from 'zod';\n\nexport const credentialsSchema = z.object({\n origin: z.string().url(),\n issuer: z.string().url(),\n tokenEndpoint: z.string().url(),\n clientId: z.string().min(1),\n accessToken: z.string().min(1),\n refreshToken: z.string().min(1),\n expiresAt: z.number().finite(),\n});\nexport type CliCredentials = z.infer<typeof credentialsSchema>;\n\nfunction hasCode(error: unknown, code: string): boolean {\n return error instanceof Error && 'code' in error && error.code === code;\n}\n\nexport class AuthStorage {\n constructor(private readonly directory = join(homedir(), '.config', 'bulkgrid')) {}\n\n private path(origin: string): string {\n return join(this.directory, `${createHash('sha256').update(origin).digest('hex')}.json`);\n }\n\n async read(origin: string): Promise<CliCredentials | undefined> {\n try {\n const result = credentialsSchema.safeParse(JSON.parse(await readFile(this.path(origin), 'utf8')));\n if (!result.success || result.data.origin !== origin) {\n throw new Error('Invalid saved CLI credentials. Run bulkgrid logout --local to clear them.');\n }\n return result.data;\n } catch (error) {\n if (hasCode(error, 'ENOENT')) {\n return undefined;\n }\n if (error instanceof SyntaxError) {\n throw new Error('Invalid saved CLI credentials. Run bulkgrid logout --local to clear them.');\n }\n throw error;\n }\n }\n\n async save(credentials: CliCredentials): Promise<void> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n await chmod(this.directory, 0o700);\n const target = this.path(credentials.origin);\n const temporary = `${target}.${randomUUID()}.tmp`;\n try {\n await writeFile(temporary, JSON.stringify(credentials), { mode: 0o600, flag: 'wx' });\n await rename(temporary, target);\n } finally {\n await unlink(temporary).catch(error => {\n if (!hasCode(error, 'ENOENT')) {\n throw error;\n }\n });\n }\n }\n\n async clear(origin: string): Promise<void> {\n await unlink(this.path(origin)).catch(error => {\n if (!hasCode(error, 'ENOENT')) {\n throw error;\n }\n });\n }\n\n // Hold one lock across refresh and persistence, including across CLI processes.\n async exclusive<T>(origin: string, operation: () => Promise<T>): Promise<T> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n const lock = `${this.path(origin)}.lock`;\n try {\n await writeFile(lock, String(process.pid), { flag: 'wx', mode: 0o600 });\n } catch (error) {\n if (hasCode(error, 'EEXIST')) {\n throw new Error(`Another CLI authentication operation is running. If it has stopped, remove ${lock} and retry.`);\n }\n throw error;\n }\n try {\n return await operation();\n } finally {\n await unlink(lock);\n }\n }\n}\n","import { createServer } from 'node:http';\nimport { timingSafeEqual } from 'node:crypto';\n\nexport const CLI_CALLBACK_PATH = '/bulkgrid/cli/callback';\n\nexport async function listenForOAuthCallback(state: string, issuer: string, timeoutMs = 300_000) {\n let resolveCode!: (code: string) => void;\n let rejectCode!: (error: Error) => void;\n const code = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n // Discovery can fail before the caller begins waiting for the callback.\n void code.catch(() => undefined);\n let redirectUri = '';\n const server = createServer((request, response) => {\n response.setHeader('Content-Type', 'text/plain; charset=utf-8');\n response.setHeader('Cache-Control', 'no-store');\n response.setHeader('Referrer-Policy', 'no-referrer');\n let url: URL;\n try {\n url = new URL(request.url ?? '/', redirectUri);\n } catch {\n response.writeHead(400).end('Invalid callback URL.');\n return;\n }\n if (request.method !== 'GET' || url.pathname !== CLI_CALLBACK_PATH || request.headers.host !== new URL(redirectUri).host) {\n response.writeHead(404).end('Not found');\n return;\n }\n const receivedState = url.searchParams.get('state') ?? '';\n if (\n Buffer.byteLength(receivedState) !== Buffer.byteLength(state) ||\n !timingSafeEqual(Buffer.from(receivedState), Buffer.from(state))\n ) {\n response.writeHead(400).end('Invalid login state. Return to the original login tab.');\n return;\n }\n if (url.searchParams.has('iss') && url.searchParams.get('iss') !== issuer) {\n response.writeHead(400).end('Invalid authorization server.');\n rejectCode(new Error('OAuth callback issuer did not match.'));\n return;\n }\n if (url.searchParams.has('error')) {\n response.writeHead(400).end('Login was declined. Return to your terminal.');\n rejectCode(new Error('Authorization was declined. Run bulkgrid login to try again.'));\n return;\n }\n const authorizationCode = url.searchParams.get('code');\n if (!authorizationCode) {\n response.writeHead(400).end('Missing authorization code.');\n return;\n }\n response.end('Authorization received. Return to your terminal to check login completed.');\n resolveCode(authorizationCode);\n });\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(0, '127.0.0.1', () => {\n server.removeListener('error', reject);\n resolve();\n });\n });\n const address = server.address();\n if (!address || typeof address === 'string') {\n server.close();\n throw new Error('Unable to start the CLI login callback.');\n }\n redirectUri = `http://127.0.0.1:${address.port}${CLI_CALLBACK_PATH}`;\n const timer = setTimeout(() => rejectCode(new Error('Login timed out. Run bulkgrid login to try again.')), timeoutMs);\n const cancel = () => rejectCode(new Error('Login cancelled.'));\n process.once('SIGINT', cancel);\n process.once('SIGTERM', cancel);\n return {\n redirectUri,\n code,\n close: () => {\n clearTimeout(timer);\n process.removeListener('SIGINT', cancel);\n process.removeListener('SIGTERM', cancel);\n server.closeAllConnections();\n server.close();\n },\n };\n}\n","import { spawn } from 'node:child_process';\nimport { createHash, randomBytes } from 'node:crypto';\nimport { z } from 'zod';\nimport { AuthStorage, type CliCredentials } from './authStorage.js';\nimport { listenForOAuthCallback } from './oauthCallback.js';\n\nconst DEFAULT_ORIGIN = 'https://bulkgrid.com';\nconst identityScopes = 'openid email profile';\nconst metadataSchema = z.object({\n issuer: z.string().url(),\n authorization_endpoint: z.string().url(),\n token_endpoint: z.string().url(),\n registration_endpoint: z.string().url(),\n code_challenge_methods_supported: z.array(z.string()),\n});\nconst tokensSchema = z.object({\n access_token: z.string().min(1),\n refresh_token: z.string().min(1),\n token_type: z.string().refine(value => value.toLowerCase() === 'bearer'),\n expires_in: z.number().positive().finite(),\n});\nconst sessionSchema = z.object({\n userId: z.string(),\n workspaceId: z.string(),\n clientName: z.string().nullable(),\n scopes: z.array(z.string()),\n collectionScope: z.enum(['all', 'selected']),\n});\nexport type CliSession = z.infer<typeof sessionSchema>;\nexport interface LoginOptions {\n readonly url?: string;\n readonly browser?: boolean;\n}\n\nclass HttpError extends Error {\n constructor(readonly status: number) {\n super(`Authentication request failed (HTTP ${status}). Check the server configuration or run bulkgrid login again.`);\n }\n}\n\nfunction secureUrl(value: string): URL {\n const url = new URL(value);\n const local = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);\n if ((url.protocol !== 'https:' && !(url.protocol === 'http:' && local)) || url.username || url.password || url.hash) {\n throw new Error('Authentication URLs must use HTTPS (HTTP is allowed only for local development).');\n }\n return url;\n}\n\nexport function resolveOrigin(value = process.env.BULKGRID_URL ?? DEFAULT_ORIGIN): string {\n const url = secureUrl(value);\n if (url.pathname !== '/' || url.search) {\n throw new Error('Use the Bulkgrid base URL, such as https://bulkgrid.com, without a path or query.');\n }\n return url.origin;\n}\n\nexport function openLoginBrowser(url: string): void {\n // The generated URL is passed as an argument, never interpolated into a shell command.\n const command = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'rundll32' : 'xdg-open';\n const args = process.platform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];\n const child = spawn(command, args, { stdio: 'ignore', detached: true });\n child.on('error', () => console.log('Could not open a browser. Open the login URL above manually.'));\n child.unref();\n}\n\nexport class CliAuth {\n constructor(\n private readonly storage = new AuthStorage(),\n private readonly fetcher: typeof fetch = fetch,\n ) {}\n\n private async request(url: string, init?: RequestInit): Promise<Response> {\n secureUrl(url);\n const response = await this.fetcher(url, { ...init, redirect: 'error', signal: AbortSignal.timeout(15_000) });\n if (!response.ok) {\n throw new HttpError(response.status);\n }\n return response;\n }\n\n private async requestJson(url: string, init?: RequestInit): Promise<unknown> {\n const response = await this.request(url, init);\n try {\n return await response.json();\n } catch {\n throw new Error('The authentication server returned invalid JSON.');\n }\n }\n\n private async discover(origin: string) {\n const resource = `${origin}/api/v1/mcp`;\n const response = await this.requestJson(`${origin}/.well-known/oauth-protected-resource/api/v1/mcp`);\n const protectedResource = z\n .object({ resource: z.literal(resource), authorization_servers: z.array(z.string().url()).length(1) })\n .parse(response);\n const issuer = secureUrl(protectedResource.authorization_servers[0]!);\n if (issuer.search) {\n throw new Error('Invalid authorization server issuer.');\n }\n const discoveryUrl = `${issuer.origin}/.well-known/oauth-authorization-server${issuer.pathname === '/' ? '' : issuer.pathname}`;\n const metadata = metadataSchema.parse(await this.requestJson(discoveryUrl));\n if (\n metadata.issuer !== protectedResource.authorization_servers[0] ||\n !metadata.code_challenge_methods_supported.includes('S256')\n ) {\n throw new Error('Authorization server discovery must match its issuer and support PKCE S256.');\n }\n for (const endpoint of [metadata.authorization_endpoint, metadata.token_endpoint, metadata.registration_endpoint]) {\n if (secureUrl(endpoint).origin !== issuer.origin) {\n throw new Error('OAuth endpoints must belong to the discovered authorization server.');\n }\n }\n return metadata;\n }\n\n async login(options: LoginOptions = {}, openBrowser: (url: string) => void = openLoginBrowser): Promise<CliSession> {\n const origin = resolveOrigin(options.url);\n return this.storage.exclusive(origin, async () => {\n if (await this.storage.read(origin)) {\n throw new Error('A CLI login is already saved for this server. Use bulkgrid status or bulkgrid logout first.');\n }\n const metadata = await this.discover(origin);\n const verifier = randomBytes(32).toString('base64url');\n const state = randomBytes(32).toString('base64url');\n const callback = await listenForOAuthCallback(state, metadata.issuer);\n try {\n const registration = z.object({ client_id: z.string().min(1) }).parse(\n await this.requestJson(metadata.registration_endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n client_name: 'Bulkgrid CLI',\n client_uri: origin,\n redirect_uris: [callback.redirectUri],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n scope: identityScopes,\n }),\n }),\n );\n const authorizationUrl = new URL(metadata.authorization_endpoint);\n authorizationUrl.search = new URLSearchParams({\n response_type: 'code',\n client_id: registration.client_id,\n redirect_uri: callback.redirectUri,\n scope: identityScopes,\n state,\n code_challenge: createHash('sha256').update(verifier).digest('base64url'),\n code_challenge_method: 'S256',\n prompt: 'consent',\n }).toString();\n console.log(`Sign in and approve access:\\n${authorizationUrl.href}`);\n if (options.browser !== false) {\n openBrowser(authorizationUrl.href);\n }\n const code = await callback.code;\n const tokens = await this.exchange(metadata.token_endpoint, {\n grant_type: 'authorization_code',\n client_id: registration.client_id,\n code,\n redirect_uri: callback.redirectUri,\n code_verifier: verifier,\n });\n const credentials: CliCredentials = {\n origin,\n issuer: metadata.issuer,\n tokenEndpoint: metadata.token_endpoint,\n clientId: registration.client_id,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n // Persist before checking the resource so a transient API failure can be retried or logged out.\n await this.storage.save(credentials);\n return await this.session(credentials);\n } finally {\n callback.close();\n }\n });\n }\n\n private async exchange(endpoint: string, body: Record<string, string>) {\n return tokensSchema.parse(\n await this.requestJson(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams(body),\n }),\n );\n }\n\n private async credentials(origin: string): Promise<CliCredentials> {\n const saved = await this.storage.read(origin);\n if (!saved) {\n throw new Error('Not logged in. Run bulkgrid login.');\n }\n if (secureUrl(saved.tokenEndpoint).origin !== secureUrl(saved.issuer).origin) {\n throw new Error('Saved token endpoint does not match the authorization server. Log out locally and sign in again.');\n }\n if (saved.expiresAt > Date.now() + 60_000) {\n return saved;\n }\n const tokens = await this.exchange(saved.tokenEndpoint, {\n grant_type: 'refresh_token',\n client_id: saved.clientId,\n refresh_token: saved.refreshToken,\n });\n const refreshed = {\n ...saved,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n await this.storage.save(refreshed);\n return refreshed;\n }\n\n private async session(credentials: CliCredentials): Promise<CliSession> {\n return sessionSchema.parse(\n await this.requestJson(`${credentials.origin}/api/v1/cli/session`, {\n headers: { Authorization: `Bearer ${credentials.accessToken}` },\n }),\n );\n }\n\n async status(url?: string): Promise<CliSession> {\n const origin = resolveOrigin(url);\n return this.storage.exclusive(origin, async () => this.session(await this.credentials(origin)));\n }\n\n /** For CLI API consumers; tokens are never copied into agent/project configuration. */\n async getAccessToken(url?: string): Promise<string> {\n const origin = resolveOrigin(url);\n return this.storage.exclusive(origin, async () => {\n const credentials = await this.credentials(origin);\n await this.session(credentials);\n return credentials.accessToken;\n });\n }\n\n async logout(options: { url?: string; local?: boolean } = {}): Promise<void> {\n const origin = resolveOrigin(options.url);\n await this.storage.exclusive(origin, async () => {\n if (options.local) {\n await this.storage.clear(origin);\n return;\n }\n if (!(await this.storage.read(origin))) {\n return;\n }\n try {\n const credentials = await this.credentials(origin);\n await this.request(`${origin}/api/v1/cli/session`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${credentials.accessToken}` },\n });\n } catch {\n throw new Error(\n 'Could not revoke the CLI connection. Retry, or revoke it in Connected Apps and use bulkgrid logout --local.',\n );\n }\n await this.storage.clear(origin);\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth-DQ_NoZtw.js","names":[],"sources":["../src/init.ts","../src/authStorage.ts","../src/oauthCallback.ts","../src/auth.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { checkbox, confirm, input, password, select } from '@inquirer/prompts';\n\nconst DEFAULT_SERVER_NAME = 'bulkgrid';\nconst API_KEY_ENV_VAR = 'BULKGRID_API_KEY';\nconst MCP_URL_ENV_VAR = 'BULKGRID_MCP_URL';\nconst DASHBOARD_API_KEYS_URL = 'https://bulkgrid.com/dashboard/settings/api-keys';\n\ntype AgentName = 'cursor' | 'vscode' | 'claude' | 'codex';\ntype AuthMode = 'browser' | 'manual' | 'skip';\n\nconst AGENT_CHOICES: readonly { label: string; value: AgentName }[] = [\n { label: 'Cursor', value: 'cursor' },\n { label: 'VS Code', value: 'vscode' },\n { label: 'Claude Code', value: 'claude' },\n { label: 'Codex', value: 'codex' },\n];\n\ninterface InitFlags {\n readonly all?: boolean;\n readonly cursor?: boolean;\n readonly vscode?: boolean;\n readonly claude?: boolean;\n readonly codex?: boolean;\n}\n\nexport interface InitCommandOptions extends InitFlags {\n readonly mcpUrl?: string;\n readonly apiKey?: string;\n readonly global?: boolean;\n readonly project?: boolean;\n readonly yes?: boolean;\n readonly writeApiKey?: boolean;\n readonly installGlobal?: boolean;\n readonly auth?: AuthMode;\n}\n\ninterface InitContext {\n readonly agents: readonly AgentName[];\n readonly mcpUrl: string;\n readonly apiKey?: string;\n readonly scope: 'project' | 'global';\n readonly writeApiKey: boolean;\n}\n\ntype McpConfigContext = Pick<InitContext, 'apiKey' | 'mcpUrl' | 'writeApiKey'>;\nexport type JsonObject = { [key: string]: JsonValue };\ntype JsonValue = string | number | boolean | null | JsonObject | JsonValue[];\n\ninterface SetupResult {\n readonly agent: AgentName;\n readonly status: 'configured' | 'skipped';\n readonly message: string;\n}\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseJsonObject(filePath: string): JsonObject {\n if (!existsSync(filePath)) {\n return {};\n }\n\n const parsed: unknown = JSON.parse(readFileSync(filePath, 'utf8'));\n if (!isJsonObject(parsed)) {\n throw new Error(`${filePath} must contain a JSON object`);\n }\n\n return parsed;\n}\n\nfunction writeJsonFile(filePath: string, data: JsonObject): void {\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\\n`);\n}\n\nfunction getObjectProperty(parent: JsonObject, key: string): JsonObject {\n const current = parent[key];\n if (isJsonObject(current)) {\n return current;\n }\n\n const next: JsonObject = {};\n parent[key] = next;\n return next;\n}\n\nfunction buildAuthorizationHeader(context: McpConfigContext, inputExpression: string): string {\n if (context.writeApiKey && context.apiKey) {\n return `Bearer ${context.apiKey}`;\n }\n\n return `Bearer ${inputExpression}`;\n}\n\nfunction buildCursorServer(context: McpConfigContext): JsonObject {\n return {\n url: context.mcpUrl,\n headers: {\n Authorization: buildAuthorizationHeader(context, `\\${env:${API_KEY_ENV_VAR}}`),\n },\n };\n}\n\nexport function mergeCursorConfig(existing: JsonObject, context: McpConfigContext): JsonObject {\n const next = { ...existing };\n const servers = getObjectProperty(next, 'mcpServers');\n servers[DEFAULT_SERVER_NAME] = buildCursorServer(context);\n return next;\n}\n\nfunction buildVsCodeConfig(context: McpConfigContext): JsonObject {\n return {\n inputs: [\n {\n type: 'promptString',\n id: 'bulkgrid-api-key',\n description: 'Bulkgrid API Key',\n password: true,\n },\n ],\n servers: {\n [DEFAULT_SERVER_NAME]: {\n type: 'http',\n url: context.mcpUrl,\n headers: {\n Authorization: buildAuthorizationHeader(context, '${input:bulkgrid-api-key}'),\n },\n },\n },\n };\n}\n\nexport function mergeVsCodeConfig(existing: JsonObject, context: McpConfigContext): JsonObject {\n const next = { ...existing };\n const config = buildVsCodeConfig(context);\n const existingServers = getObjectProperty(next, 'servers');\n const configServers = getObjectProperty(config, 'servers');\n existingServers[DEFAULT_SERVER_NAME] = configServers[DEFAULT_SERVER_NAME] ?? {};\n\n if (!Array.isArray(next.inputs)) {\n next.inputs = config.inputs ?? [];\n return next;\n }\n\n const hasInput = next.inputs.some(item => isJsonObject(item) && item.id === 'bulkgrid-api-key');\n if (!hasInput && Array.isArray(config.inputs)) {\n next.inputs = [...next.inputs, ...config.inputs];\n }\n\n return next;\n}\n\nfunction resolveCursorPath(scope: InitContext['scope']): string {\n if (scope === 'global') {\n return join(homedir(), '.cursor', 'mcp.json');\n }\n\n return join(process.cwd(), '.cursor', 'mcp.json');\n}\n\nfunction resolveVsCodePath(scope: InitContext['scope']): string {\n if (scope === 'global') {\n if (process.platform === 'darwin') {\n return join(homedir(), 'Library', 'Application Support', 'Code', 'User', 'mcp.json');\n }\n if (process.platform === 'win32') {\n return join(homedir(), 'AppData', 'Roaming', 'Code', 'User', 'mcp.json');\n }\n\n return join(homedir(), '.config', 'Code', 'User', 'mcp.json');\n }\n\n return join(process.cwd(), '.vscode', 'mcp.json');\n}\n\nfunction setupCursor(context: InitContext): SetupResult {\n const filePath = resolveCursorPath(context.scope);\n const config = mergeCursorConfig(parseJsonObject(filePath), context);\n writeJsonFile(filePath, config);\n\n return {\n agent: 'cursor',\n status: 'configured',\n message: `Wrote ${filePath}`,\n };\n}\n\nfunction setupVsCode(context: InitContext): SetupResult {\n const filePath = resolveVsCodePath(context.scope);\n const config = mergeVsCodeConfig(parseJsonObject(filePath), context);\n writeJsonFile(filePath, config);\n\n return {\n agent: 'vscode',\n status: 'configured',\n message: `Wrote ${filePath}`,\n };\n}\n\nfunction commandExists(command: string): boolean {\n const result = spawnSync(command, ['--version'], { encoding: 'utf8', stdio: 'ignore' });\n return result.status === 0;\n}\n\nfunction runCommand(command: string, args: readonly string[]): void {\n const result = spawnSync(command, args, { encoding: 'utf8', stdio: 'inherit' });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw new Error(`${command} ${args.join(' ')} failed with exit code ${result.status ?? 'unknown'}`);\n }\n}\n\nfunction printInitBanner(): void {\n console.log('');\n console.log(' ▦ Bulkgrid init');\n console.log('');\n}\n\nasync function promptForConfirmation(message: string, defaultValue: boolean): Promise<boolean> {\n return confirm({\n message,\n default: defaultValue,\n });\n}\n\nasync function promptForSelect<TValue extends string>(\n message: string,\n choices: readonly { label: string; value: TValue }[],\n): Promise<TValue> {\n return select({\n message,\n choices: choices.map(choice => ({\n name: choice.label,\n value: choice.value,\n })),\n });\n}\n\nasync function promptForMultiSelect<TValue extends string>(\n message: string,\n choices: readonly { label: string; value: TValue }[],\n): Promise<readonly TValue[]> {\n return checkbox({\n message,\n choices: choices.map(choice => ({\n name: choice.label,\n value: choice.value,\n checked: true,\n })),\n required: true,\n pageSize: choices.length,\n });\n}\n\nasync function maybeInstallGlobally(options: InitCommandOptions): Promise<void> {\n if (options.installGlobal) {\n runCommand('npm', ['install', '-g', '@bulkgrid/cli']);\n return;\n }\n\n if (options.yes) {\n return;\n }\n\n const shouldInstall = await promptForConfirmation('Install @bulkgrid/cli globally?', false);\n if (shouldInstall) {\n runCommand('npm', ['install', '-g', '@bulkgrid/cli']);\n }\n}\n\nfunction openBrowser(url: string): void {\n let command: string;\n let args: string[];\n\n if (process.platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (process.platform === 'win32') {\n command = 'cmd';\n args = ['/c', 'start', '', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n const result = spawnSync(command, args, { encoding: 'utf8', stdio: 'ignore' });\n if (result.status !== 0) {\n console.log(`Open ${url} to create a Bulkgrid API key.`);\n }\n}\n\nasync function resolveApiKey(options: InitCommandOptions): Promise<string | undefined> {\n const configuredApiKey = options.apiKey ?? process.env[API_KEY_ENV_VAR];\n if (configuredApiKey || options.yes) {\n return configuredApiKey;\n }\n\n const authMode =\n options.auth ??\n (await promptForSelect('Authenticate to Bulkgrid', [\n { label: 'Open the dashboard and paste a new API key', value: 'browser' },\n { label: 'Enter an existing API key', value: 'manual' },\n { label: 'Skip this step', value: 'skip' },\n ]));\n\n if (authMode === 'skip') {\n console.log(`Skipped. Set ${API_KEY_ENV_VAR} later or use client-side prompts.`);\n return undefined;\n }\n\n if (authMode === 'browser') {\n openBrowser(DASHBOARD_API_KEYS_URL);\n console.log('Create an API key with mcp:use and search:query scopes.');\n }\n\n const apiKey = await password({\n message: 'Bulkgrid API key',\n mask: '*',\n validate: value => value.trim().length > 0 || 'Enter a Bulkgrid API key.',\n });\n return apiKey || undefined;\n}\n\nfunction setupCodex(context: InitContext): SetupResult {\n if (!commandExists('codex')) {\n return {\n agent: 'codex',\n status: 'skipped',\n message: 'codex command was not found',\n };\n }\n\n runCommand('codex', ['mcp', 'add', DEFAULT_SERVER_NAME, '--url', context.mcpUrl, '--bearer-token-env-var', API_KEY_ENV_VAR]);\n\n return {\n agent: 'codex',\n status: 'configured',\n message: `Registered ${DEFAULT_SERVER_NAME} with codex mcp add`,\n };\n}\n\nfunction setupClaude(context: InitContext): SetupResult {\n if (!commandExists('claude')) {\n return {\n agent: 'claude',\n status: 'skipped',\n message: 'claude command was not found',\n };\n }\n\n if (!context.apiKey) {\n return {\n agent: 'claude',\n status: 'skipped',\n message: `Set ${API_KEY_ENV_VAR} or pass --api-key to configure Claude Code`,\n };\n }\n\n const args = ['mcp', 'add', '--transport', 'http'];\n if (context.scope === 'global') {\n args.push('--scope', 'user');\n }\n args.push(DEFAULT_SERVER_NAME, context.mcpUrl, '--header', `Authorization: Bearer ${context.apiKey}`);\n runCommand('claude', args);\n\n return {\n agent: 'claude',\n status: 'configured',\n message: `Registered ${DEFAULT_SERVER_NAME} with claude mcp add`,\n };\n}\n\nasync function resolveAgents(options: InitCommandOptions): Promise<readonly AgentName[]> {\n if (options.all || (!options.cursor && !options.vscode && !options.claude && !options.codex)) {\n if (!options.all && !options.yes) {\n const shouldConfigure = await promptForConfirmation('Configure the Bulkgrid MCP server for clients?', true);\n if (!shouldConfigure) {\n return [];\n }\n\n return promptForMultiSelect('Choose MCP clients to configure:', AGENT_CHOICES);\n }\n\n return ['cursor', 'vscode', 'claude', 'codex'];\n }\n\n const agents: AgentName[] = [];\n if (options.cursor) {\n agents.push('cursor');\n }\n if (options.vscode) {\n agents.push('vscode');\n }\n if (options.claude) {\n agents.push('claude');\n }\n if (options.codex) {\n agents.push('codex');\n }\n\n return agents;\n}\n\nasync function promptForValue(message: string): Promise<string> {\n return input({\n message,\n validate: value => value.trim().length > 0 || 'Enter a value.',\n });\n}\n\nasync function buildContext(options: InitCommandOptions): Promise<InitContext> {\n const configuredUrl = options.mcpUrl ?? process.env[MCP_URL_ENV_VAR];\n const mcpUrl = configuredUrl ?? (options.yes ? undefined : await promptForValue('Bulkgrid MCP URL: '));\n if (!mcpUrl) {\n throw new Error(`Missing MCP URL. Pass --mcp-url or set ${MCP_URL_ENV_VAR}.`);\n }\n\n const apiKey = await resolveApiKey(options);\n const agents = await resolveAgents(options);\n\n return {\n agents,\n mcpUrl,\n apiKey,\n scope: options.global ? 'global' : 'project',\n writeApiKey: options.writeApiKey ?? false,\n };\n}\n\nexport async function runInitCommand(options: InitCommandOptions): Promise<readonly SetupResult[]> {\n printInitBanner();\n await maybeInstallGlobally(options);\n\n const context = await buildContext(options);\n const results: SetupResult[] = [];\n\n for (const agent of context.agents) {\n if (agent === 'cursor') {\n results.push(setupCursor(context));\n } else if (agent === 'vscode') {\n results.push(setupVsCode(context));\n } else if (agent === 'claude') {\n results.push(setupClaude(context));\n } else if (agent === 'codex') {\n results.push(setupCodex(context));\n }\n }\n\n return results;\n}\n","import { createHash, randomUUID } from 'node:crypto';\nimport { chmod, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { z } from 'zod';\n\nexport const credentialsSchema = z.object({\n origin: z.string().url(),\n issuer: z.string().url(),\n tokenEndpoint: z.string().url(),\n clientId: z.string().min(1),\n accessToken: z.string().min(1),\n refreshToken: z.string().min(1),\n expiresAt: z.number().finite(),\n});\nexport type CliCredentials = z.infer<typeof credentialsSchema>;\n\nfunction hasCode(error: unknown, code: string): boolean {\n return error instanceof Error && 'code' in error && error.code === code;\n}\n\nexport class AuthStorage {\n constructor(private readonly directory = join(homedir(), '.config', 'bulkgrid')) {}\n\n private path(origin: string): string {\n return join(this.directory, `${createHash('sha256').update(origin).digest('hex')}.json`);\n }\n\n async read(origin: string): Promise<CliCredentials | undefined> {\n try {\n const result = credentialsSchema.safeParse(JSON.parse(await readFile(this.path(origin), 'utf8')));\n if (!result.success || result.data.origin !== origin) {\n throw new Error('Invalid saved CLI credentials. Run bulkgrid logout --local to clear them.');\n }\n return result.data;\n } catch (error) {\n if (hasCode(error, 'ENOENT')) {\n return undefined;\n }\n if (error instanceof SyntaxError) {\n throw new Error('Invalid saved CLI credentials. Run bulkgrid logout --local to clear them.');\n }\n throw error;\n }\n }\n\n async save(credentials: CliCredentials): Promise<void> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n await chmod(this.directory, 0o700);\n const target = this.path(credentials.origin);\n const temporary = `${target}.${randomUUID()}.tmp`;\n try {\n await writeFile(temporary, JSON.stringify(credentials), { mode: 0o600, flag: 'wx' });\n await rename(temporary, target);\n } finally {\n await unlink(temporary).catch(error => {\n if (!hasCode(error, 'ENOENT')) {\n throw error;\n }\n });\n }\n }\n\n async clear(origin: string): Promise<void> {\n await unlink(this.path(origin)).catch(error => {\n if (!hasCode(error, 'ENOENT')) {\n throw error;\n }\n });\n }\n\n // Hold one lock across refresh and persistence, including across CLI processes.\n async exclusive<T>(origin: string, operation: () => Promise<T>): Promise<T> {\n await mkdir(this.directory, { recursive: true, mode: 0o700 });\n const lock = `${this.path(origin)}.lock`;\n try {\n await writeFile(lock, String(process.pid), { flag: 'wx', mode: 0o600 });\n } catch (error) {\n if (hasCode(error, 'EEXIST')) {\n throw new Error(`Another CLI authentication operation is running. If it has stopped, remove ${lock} and retry.`);\n }\n throw error;\n }\n try {\n return await operation();\n } finally {\n await unlink(lock);\n }\n }\n}\n","import { createServer } from 'node:http';\nimport { timingSafeEqual } from 'node:crypto';\n\nexport const CLI_CALLBACK_PATH = '/bulkgrid/cli/callback';\n\nexport async function listenForOAuthCallback(state: string, issuer: string, timeoutMs = 300_000) {\n let resolveCode!: (code: string) => void;\n let rejectCode!: (error: Error) => void;\n const code = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n // Discovery can fail before the caller begins waiting for the callback.\n void code.catch(() => undefined);\n let redirectUri = '';\n const server = createServer((request, response) => {\n response.setHeader('Content-Type', 'text/plain; charset=utf-8');\n response.setHeader('Cache-Control', 'no-store');\n response.setHeader('Referrer-Policy', 'no-referrer');\n let url: URL;\n try {\n url = new URL(request.url ?? '/', redirectUri);\n } catch {\n response.writeHead(400).end('Invalid callback URL.');\n return;\n }\n if (request.method !== 'GET' || url.pathname !== CLI_CALLBACK_PATH || request.headers.host !== new URL(redirectUri).host) {\n response.writeHead(404).end('Not found');\n return;\n }\n const receivedState = url.searchParams.get('state') ?? '';\n if (\n Buffer.byteLength(receivedState) !== Buffer.byteLength(state) ||\n !timingSafeEqual(Buffer.from(receivedState), Buffer.from(state))\n ) {\n response.writeHead(400).end('Invalid login state. Return to the original login tab.');\n return;\n }\n if (url.searchParams.has('iss') && url.searchParams.get('iss') !== issuer) {\n response.writeHead(400).end('Invalid authorization server.');\n rejectCode(new Error('OAuth callback issuer did not match.'));\n return;\n }\n if (url.searchParams.has('error')) {\n response.writeHead(400).end('Login was declined. Return to your terminal.');\n rejectCode(new Error('Authorization was declined. Run bulkgrid login to try again.'));\n return;\n }\n const authorizationCode = url.searchParams.get('code');\n if (!authorizationCode) {\n response.writeHead(400).end('Missing authorization code.');\n return;\n }\n response.end('Authorization received. Return to your terminal to check login completed.');\n resolveCode(authorizationCode);\n });\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(0, '127.0.0.1', () => {\n server.removeListener('error', reject);\n resolve();\n });\n });\n const address = server.address();\n if (!address || typeof address === 'string') {\n server.close();\n throw new Error('Unable to start the CLI login callback.');\n }\n redirectUri = `http://127.0.0.1:${address.port}${CLI_CALLBACK_PATH}`;\n const timer = setTimeout(() => rejectCode(new Error('Login timed out. Run bulkgrid login to try again.')), timeoutMs);\n const cancel = () => rejectCode(new Error('Login cancelled.'));\n process.once('SIGINT', cancel);\n process.once('SIGTERM', cancel);\n return {\n redirectUri,\n code,\n close: () => {\n clearTimeout(timer);\n process.removeListener('SIGINT', cancel);\n process.removeListener('SIGTERM', cancel);\n server.closeAllConnections();\n server.close();\n },\n };\n}\n","import { spawn } from 'node:child_process';\nimport { createHash, randomBytes } from 'node:crypto';\nimport { z } from 'zod';\nimport { AuthStorage, type CliCredentials } from './authStorage.js';\nimport { listenForOAuthCallback } from './oauthCallback.js';\n\nconst DEFAULT_ORIGIN = 'https://bulkgrid.com';\nconst identityScopes = 'openid email profile';\nconst metadataSchema = z.object({\n issuer: z.string().url(),\n authorization_endpoint: z.string().url(),\n token_endpoint: z.string().url(),\n registration_endpoint: z.string().url(),\n code_challenge_methods_supported: z.array(z.string()),\n});\nconst tokensSchema = z.object({\n access_token: z.string().min(1),\n refresh_token: z.string().min(1),\n token_type: z.string().refine(value => value.toLowerCase() === 'bearer'),\n expires_in: z.number().positive().finite(),\n});\nconst sessionSchema = z.object({\n userId: z.string(),\n workspaceId: z.string(),\n clientName: z.string().nullable(),\n scopes: z.array(z.string()),\n collectionScope: z.enum(['all', 'selected']),\n});\nexport type CliSession = z.infer<typeof sessionSchema>;\nexport interface LoginOptions {\n readonly url?: string;\n readonly browser?: boolean;\n}\n\nclass HttpError extends Error {\n constructor(readonly status: number) {\n super(`Authentication request failed (HTTP ${status}). Check the server configuration or run bulkgrid login again.`);\n }\n}\n\nfunction secureUrl(value: string): URL {\n const url = new URL(value);\n const local = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);\n if ((url.protocol !== 'https:' && !(url.protocol === 'http:' && local)) || url.username || url.password || url.hash) {\n throw new Error('Authentication URLs must use HTTPS (HTTP is allowed only for local development).');\n }\n return url;\n}\n\nexport function resolveOrigin(value = process.env.BULKGRID_URL ?? DEFAULT_ORIGIN): string {\n const url = secureUrl(value);\n if (url.pathname !== '/' || url.search) {\n throw new Error('Use the Bulkgrid base URL, such as https://bulkgrid.com, without a path or query.');\n }\n return url.origin;\n}\n\nexport function openLoginBrowser(url: string): void {\n // The generated URL is passed as an argument, never interpolated into a shell command.\n const command = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'rundll32' : 'xdg-open';\n const args = process.platform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];\n const child = spawn(command, args, { stdio: 'ignore', detached: true });\n child.on('error', () => console.log('Could not open a browser. Open the login URL above manually.'));\n child.unref();\n}\n\nexport class CliAuth {\n constructor(\n private readonly storage = new AuthStorage(),\n private readonly fetcher: typeof fetch = fetch,\n ) {}\n\n private async request(url: string, init?: RequestInit): Promise<Response> {\n secureUrl(url);\n const response = await this.fetcher(url, { ...init, redirect: 'error', signal: AbortSignal.timeout(15_000) });\n if (!response.ok) {\n throw new HttpError(response.status);\n }\n return response;\n }\n\n private async requestJson(url: string, init?: RequestInit): Promise<unknown> {\n const response = await this.request(url, init);\n try {\n return await response.json();\n } catch {\n throw new Error('The authentication server returned invalid JSON.');\n }\n }\n\n private async discover(origin: string) {\n const resource = `${origin}/api/v1/mcp`;\n const response = await this.requestJson(`${origin}/.well-known/oauth-protected-resource/api/v1/mcp`);\n const protectedResource = z\n .object({ resource: z.literal(resource), authorization_servers: z.array(z.string().url()).length(1) })\n .parse(response);\n const issuer = secureUrl(protectedResource.authorization_servers[0]!);\n if (issuer.search) {\n throw new Error('Invalid authorization server issuer.');\n }\n const discoveryUrl = `${issuer.origin}/.well-known/oauth-authorization-server${issuer.pathname === '/' ? '' : issuer.pathname}`;\n const metadata = metadataSchema.parse(await this.requestJson(discoveryUrl));\n if (\n metadata.issuer !== protectedResource.authorization_servers[0] ||\n !metadata.code_challenge_methods_supported.includes('S256')\n ) {\n throw new Error('Authorization server discovery must match its issuer and support PKCE S256.');\n }\n for (const endpoint of [metadata.authorization_endpoint, metadata.token_endpoint, metadata.registration_endpoint]) {\n if (secureUrl(endpoint).origin !== issuer.origin) {\n throw new Error('OAuth endpoints must belong to the discovered authorization server.');\n }\n }\n return metadata;\n }\n\n async login(options: LoginOptions = {}, openBrowser: (url: string) => void = openLoginBrowser): Promise<CliSession> {\n const origin = resolveOrigin(options.url);\n return this.storage.exclusive(origin, async () => {\n if (await this.storage.read(origin)) {\n throw new Error('A CLI login is already saved for this server. Use bulkgrid status or bulkgrid logout first.');\n }\n const metadata = await this.discover(origin);\n const verifier = randomBytes(32).toString('base64url');\n const state = randomBytes(32).toString('base64url');\n const callback = await listenForOAuthCallback(state, metadata.issuer);\n try {\n const registration = z.object({ client_id: z.string().min(1) }).parse(\n await this.requestJson(metadata.registration_endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n client_name: 'Bulkgrid CLI',\n client_uri: origin,\n redirect_uris: [callback.redirectUri],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n scope: identityScopes,\n }),\n }),\n );\n const authorizationUrl = new URL(metadata.authorization_endpoint);\n authorizationUrl.search = new URLSearchParams({\n response_type: 'code',\n client_id: registration.client_id,\n redirect_uri: callback.redirectUri,\n scope: identityScopes,\n state,\n code_challenge: createHash('sha256').update(verifier).digest('base64url'),\n code_challenge_method: 'S256',\n prompt: 'consent',\n }).toString();\n console.log(`Sign in and approve access:\\n${authorizationUrl.href}`);\n if (options.browser !== false) {\n openBrowser(authorizationUrl.href);\n }\n const code = await callback.code;\n const tokens = await this.exchange(metadata.token_endpoint, {\n grant_type: 'authorization_code',\n client_id: registration.client_id,\n code,\n redirect_uri: callback.redirectUri,\n code_verifier: verifier,\n });\n const credentials: CliCredentials = {\n origin,\n issuer: metadata.issuer,\n tokenEndpoint: metadata.token_endpoint,\n clientId: registration.client_id,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n // Persist before checking the resource so a transient API failure can be retried or logged out.\n await this.storage.save(credentials);\n return await this.session(credentials);\n } finally {\n callback.close();\n }\n });\n }\n\n private async exchange(endpoint: string, body: Record<string, string>) {\n return tokensSchema.parse(\n await this.requestJson(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams(body),\n }),\n );\n }\n\n private async credentials(origin: string): Promise<CliCredentials> {\n const saved = await this.storage.read(origin);\n if (!saved) {\n throw new Error('Not logged in. Run bulkgrid login.');\n }\n if (secureUrl(saved.tokenEndpoint).origin !== secureUrl(saved.issuer).origin) {\n throw new Error('Saved token endpoint does not match the authorization server. Log out locally and sign in again.');\n }\n if (saved.expiresAt > Date.now() + 60_000) {\n return saved;\n }\n const tokens = await this.exchange(saved.tokenEndpoint, {\n grant_type: 'refresh_token',\n client_id: saved.clientId,\n refresh_token: saved.refreshToken,\n });\n const refreshed = {\n ...saved,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: Date.now() + tokens.expires_in * 1000,\n };\n await this.storage.save(refreshed);\n return refreshed;\n }\n\n private async session(credentials: CliCredentials): Promise<CliSession> {\n return sessionSchema.parse(\n await this.requestJson(`${credentials.origin}/api/v1/cli/session`, {\n headers: { Authorization: `Bearer ${credentials.accessToken}` },\n }),\n );\n }\n\n async status(url?: string): Promise<CliSession> {\n const origin = resolveOrigin(url);\n return this.storage.exclusive(origin, async () => this.session(await this.credentials(origin)));\n }\n\n /** For CLI API consumers; tokens are never copied into agent/project configuration. */\n async getAccessToken(url?: string): Promise<string> {\n const origin = resolveOrigin(url);\n return this.storage.exclusive(origin, async () => {\n const credentials = await this.credentials(origin);\n await this.session(credentials);\n return credentials.accessToken;\n });\n }\n\n async logout(options: { url?: string; local?: boolean } = {}): Promise<void> {\n const origin = resolveOrigin(options.url);\n await this.storage.exclusive(origin, async () => {\n if (options.local) {\n await this.storage.clear(origin);\n return;\n }\n if (!(await this.storage.read(origin))) {\n return;\n }\n try {\n const credentials = await this.credentials(origin);\n await this.request(`${origin}/api/v1/cli/session`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${credentials.accessToken}` },\n });\n } catch {\n throw new Error(\n 'Could not revoke the CLI connection. Retry, or revoke it in Connected Apps and use bulkgrid logout --local.',\n );\n }\n await this.storage.clear(origin);\n });\n }\n}\n"],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { r as runInitCommand, t as CliAuth } from "./auth-
|
|
2
|
+
import { r as runInitCommand, t as CliAuth } from "./auth-DQ_NoZtw.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { BulkgridClient, sourceInputSchemas } from "@bulkgrid/sdk";
|
|
4
|
+
import { BulkgridClient, monitorInputSchemas, sourceInputSchemas } from "@bulkgrid/sdk";
|
|
5
5
|
import { Command } from "commander";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
function createSourceClient(options) {
|
|
6
|
+
// src/apiKeyClient.ts
|
|
7
|
+
function createApiKeyClient(options) {
|
|
9
8
|
const apiKey = process.env.BULKGRID_API_KEY;
|
|
10
|
-
if (!apiKey) throw new Error("
|
|
9
|
+
if (!apiKey) throw new Error("Management commands require BULKGRID_API_KEY with explicit operation scopes. CLI OAuth login remains search-only.");
|
|
11
10
|
const baseUrl = new URL(options.url ?? process.env.BULKGRID_URL ?? "https://bulkgrid.com");
|
|
12
11
|
if (baseUrl.username || baseUrl.password || baseUrl.search || baseUrl.hash || baseUrl.pathname !== "/") throw new Error("Use a Bulkgrid origin URL without credentials, a path, query, or fragment.");
|
|
13
12
|
if (baseUrl.protocol !== "https:" && !(baseUrl.protocol === "http:" && [
|
|
@@ -20,7 +19,27 @@ function createSourceClient(options) {
|
|
|
20
19
|
baseUrl: baseUrl.origin
|
|
21
20
|
});
|
|
22
21
|
}
|
|
23
|
-
|
|
22
|
+
// src/monitors.ts
|
|
23
|
+
const uuid$1 = z.uuid();
|
|
24
|
+
const pagination = (options) => ({ offset: z.coerce.number().int().min(0).max(1e5).parse(options.offset ?? 0) });
|
|
25
|
+
function registerMonitorCommands(program, clientFactory = createApiKeyClient) {
|
|
26
|
+
const monitors = program.command("monitors").description("Manage change monitors with a scoped API key; outputs JSON");
|
|
27
|
+
const command = (name, description) => monitors.command(name).description(description).option("--url <url>", "Bulkgrid origin; defaults to BULKGRID_URL or https://bulkgrid.com");
|
|
28
|
+
const print = (result) => console.log(JSON.stringify(result, null, 2));
|
|
29
|
+
command("list", "List up to 50 monitors").option("--offset <offset>", "Pagination offset").action(async (options) => print(await clientFactory(options).monitors.list(pagination(options))));
|
|
30
|
+
command("get <monitorId>", "Read settings and last check status").action(async (id, options) => print(await clientFactory(options).monitors.get(uuid$1.parse(id))));
|
|
31
|
+
command("create", "Create a monitor; Pages targets start recurring crawling. Output includes a sensitive signing secret").requiredOption("--input <json>", "Monitor configuration including target and notification destinations").action(async (options) => print(await clientFactory(options).monitors.create(monitorInputSchemas.create.parse(JSON.parse(options.input ?? "{}")))));
|
|
32
|
+
command("update <monitorId>", "Edit settings, pause or resume with is_active").requiredOption("--input <json>", "Partial monitor configuration").action(async (id, options) => print(await clientFactory(options).monitors.update(uuid$1.parse(id), monitorInputSchemas.update.parse(JSON.parse(options.input ?? "{}")))));
|
|
33
|
+
command("delete <monitorId>", "Delete the monitor and its event history").action(async (id, options) => print(await clientFactory(options).monitors.delete(uuid$1.parse(id))));
|
|
34
|
+
command("events <monitorId>", "List up to 50 events").option("--offset <offset>", "Pagination offset").action(async (id, options) => print(await clientFactory(options).monitors.events(uuid$1.parse(id), pagination(options))));
|
|
35
|
+
command("comparison <monitorId> <eventId>", "Read before and after content for an event").action(async (id, event, options) => print(await clientFactory(options).monitors.comparison(uuid$1.parse(id), uuid$1.parse(event))));
|
|
36
|
+
command("retry <monitorId> <eventId>", "Retry a failed event; may send notifications").action(async (id, event, options) => print(await clientFactory(options).monitors.retry(uuid$1.parse(id), { event_id: uuid$1.parse(event) })));
|
|
37
|
+
command("rotate-secret <monitorId>", "Invalidate the old webhook secret immediately and print the new sensitive secret").action(async (id, options) => print(await clientFactory(options).monitors.rotateSecret(uuid$1.parse(id))));
|
|
38
|
+
command("slack-connections", "List authorized Slack notification channels").action(async (options) => print(await clientFactory(options).monitors.slackConnections()));
|
|
39
|
+
}
|
|
40
|
+
// src/sources.ts
|
|
41
|
+
const uuid = z.uuid();
|
|
42
|
+
function registerSourceCommands(program, clientFactory = createApiKeyClient) {
|
|
24
43
|
const sources = program.command("sources").description("Inspect and manage sources with a scoped API key; outputs JSON");
|
|
25
44
|
const command = (name, description) => sources.command(name).description(description).option("--url <url>", "Bulkgrid origin; defaults to BULKGRID_URL or https://bulkgrid.com");
|
|
26
45
|
const print = (result) => console.log(JSON.stringify(result, null, 2));
|
|
@@ -55,11 +74,9 @@ function registerSourceCommands(program, clientFactory = createSourceClient) {
|
|
|
55
74
|
collectionId: uuid.parse(collectionId)
|
|
56
75
|
})));
|
|
57
76
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/cli.ts
|
|
77
|
+
// package.json
|
|
78
|
+
var version = "0.5.0";
|
|
79
|
+
// src/cli.ts
|
|
63
80
|
const program = new Command();
|
|
64
81
|
program.name("bulkgrid").description("Bulkgrid developer tooling").version(version);
|
|
65
82
|
const auth = new CliAuth();
|
|
@@ -94,11 +111,11 @@ program.command("init").description("Configure the Bulkgrid MCP server").option(
|
|
|
94
111
|
}
|
|
95
112
|
});
|
|
96
113
|
registerSourceCommands(program);
|
|
114
|
+
registerMonitorCommands(program);
|
|
97
115
|
program.parseAsync().catch((error) => {
|
|
98
116
|
console.error(`bulkgrid: ${error instanceof Error ? error.message : "Command failed"}`);
|
|
99
117
|
process.exitCode = 1;
|
|
100
118
|
});
|
|
101
|
-
//#endregion
|
|
102
119
|
export {};
|
|
103
120
|
|
|
104
121
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":["packageMetadata.version"],"sources":["../src/sources.ts","../package.json","../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { BulkgridClient, sourceInputSchemas } from '@bulkgrid/sdk';\nimport { z } from 'zod';\n\ninterface SourceCommandOptions {\n url?: string;\n input?: string;\n}\ntype ClientFactory = (options: SourceCommandOptions) => BulkgridClient;\nconst uuid = z.uuid();\n\nexport function createSourceClient(options: SourceCommandOptions): BulkgridClient {\n const apiKey = process.env.BULKGRID_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'Source commands require BULKGRID_API_KEY with explicit source/collection scopes. CLI OAuth login remains search-only.',\n );\n }\n const baseUrl = new URL(options.url ?? process.env.BULKGRID_URL ?? 'https://bulkgrid.com');\n if (baseUrl.username || baseUrl.password || baseUrl.search || baseUrl.hash || baseUrl.pathname !== '/') {\n throw new Error('Use a Bulkgrid origin URL without credentials, a path, query, or fragment.');\n }\n if (\n baseUrl.protocol !== 'https:' &&\n !(baseUrl.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(baseUrl.hostname))\n ) {\n throw new Error('Remote Bulkgrid deployments require HTTPS.');\n }\n return new BulkgridClient({ apiKey, baseUrl: baseUrl.origin });\n}\n\nexport function registerSourceCommands(program: Command, clientFactory: ClientFactory = createSourceClient): void {\n const sources = program.command('sources').description('Inspect and manage sources with a scoped API key; outputs JSON');\n const command = (name: string, description: string) =>\n sources\n .command(name)\n .description(description)\n .option('--url <url>', 'Bulkgrid origin; defaults to BULKGRID_URL or https://bulkgrid.com');\n const print = (result: unknown) => console.log(JSON.stringify(result, null, 2));\n command('find <query>', 'Find existing sources before adding one').action(\n async (query: string, options: SourceCommandOptions) => print(await clientFactory(options).index.sources.search(query)),\n );\n command('analyze <sourceUrl>', 'Start deeper analysis; may create a crawl run and consume resources').action(\n async (url: string, options: SourceCommandOptions) => print(await clientFactory(options).index.sources.analyze({ url })),\n );\n command('analysis-status <analysisId>', 'Read analysis progress and warnings').action(\n async (analysisId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.getAnalysis(uuid.parse(analysisId))),\n );\n command('add', 'Create or subscribe to a source; may initiate ongoing ingestion')\n .requiredOption('--input <json>', 'Source configuration JSON including explicit visibility, boundaries and refresh interval')\n .action(async (options: SourceCommandOptions) => {\n const input = sourceInputSchemas.create\n .safeExtend({ visibility: z.enum(['public', 'private']) })\n .parse(JSON.parse(options.input ?? '{}'));\n print(await clientFactory(options).index.sources.create(input));\n });\n command('github-connections', 'List workspace GitHub connections and permitted repositories').action(\n async (options: SourceCommandOptions) => print(await clientFactory(options).index.sources.githubConnections()),\n );\n command('subscribe <sourceId>', 'Subscribe to an existing public source without starting ingestion').action(\n async (sourceId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.subscribe(uuid.parse(sourceId))),\n );\n command('add-github', 'Create a GitHub source; private repositories require a workspace connection')\n .requiredOption(\n '--input <json>',\n 'Repository URL, explicit visibility, connection_id for private repositories and indexing settings',\n )\n .action(async (options: SourceCommandOptions) => {\n const input = sourceInputSchemas.createGithub\n .extend({ repositoryUrl: z.url(), visibility: z.enum(['public', 'private']) })\n .parse(JSON.parse(options.input ?? '{}'));\n sourceInputSchemas.createGithub.parse(input);\n print(await clientFactory(options).index.sources.createGithub(input));\n });\n command('analyze-github', 'Analyze documentation paths in a permitted GitHub repository')\n .requiredOption('--input <json>', 'Repository URL and optional connection_id and ref')\n .action(async (options: SourceCommandOptions) => {\n const input = sourceInputSchemas.analyzeGithub.extend({ repositoryUrl: z.url() }).parse(JSON.parse(options.input ?? '{}'));\n sourceInputSchemas.analyzeGithub.parse(input);\n print(await clientFactory(options).index.sources.analyzeGithub(input));\n });\n command('status <sourceId>', 'Read crawl status, errors, size and indexed item counts').action(\n async (sourceId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.status(uuid.parse(sourceId))),\n );\n command('recrawl <sourceId>', 'Start a manual refresh using saved configuration; may consume credits').action(\n async (sourceId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.recrawl(uuid.parse(sourceId))),\n );\n command('collections', 'List collections available for source management').action(async (options: SourceCommandOptions) =>\n print(await clientFactory(options).index.collections.list()),\n );\n command('rules <collectionId>', 'Inspect collection rules before changing membership').action(\n async (collectionId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.collections.rules(uuid.parse(collectionId))),\n );\n command(\n 'include <sourceId> <collectionId>',\n 'Include the entire source in a collection, broadening its retrieval coverage',\n ).action(async (sourceId: string, collectionId: string, options: SourceCommandOptions) =>\n print(\n await clientFactory(options).index.collections.addSource({\n sourceId: uuid.parse(sourceId),\n collectionId: uuid.parse(collectionId),\n }),\n ),\n );\n}\n","","#!/usr/bin/env node\nimport { registerSourceCommands } from './sources.js';\nimport packageMetadata from '../package.json' with { type: 'json' };\nimport { Command } from 'commander';\n\nimport { CliAuth } from './auth.js';\n\nimport { runInitCommand } from './init.js';\n\nconst program = new Command();\n\nprogram.name('bulkgrid').description('Bulkgrid developer tooling').version(packageMetadata.version);\n\nconst auth = new CliAuth();\n\nprogram\n .command('login')\n .description('Sign in to Bulkgrid in your browser')\n .option('--url <url>', 'Bulkgrid base URL; defaults to BULKGRID_URL or https://bulkgrid.com')\n .option('--no-browser', 'print the login URL without opening a browser')\n .action(async options => {\n const session = await auth.login(options);\n console.log(`Logged in to workspace ${session.workspaceId}. Manage access in Settings → Connected Apps.`);\n });\n\nprogram\n .command('status')\n .description('Verify the saved CLI connection and show its access')\n .option('--url <url>', 'Bulkgrid base URL; defaults to BULKGRID_URL or https://bulkgrid.com')\n .action(async options => {\n const session = await auth.status(options.url);\n console.log(`Connected as ${session.userId} to workspace ${session.workspaceId}.`);\n console.log(`Permissions: ${session.scopes.join(', ')}; collections: ${session.collectionScope}.`);\n });\n\nprogram\n .command('logout')\n .description('Revoke this CLI connection and remove its saved tokens')\n .option('--url <url>', 'Bulkgrid base URL; defaults to BULKGRID_URL or https://bulkgrid.com')\n .option('--local', 'only remove local tokens; revoke access separately in Connected Apps')\n .action(async options => {\n await auth.logout(options);\n console.log(options.local ? 'Local credentials removed. Server access was not revoked.' : 'Logged out.');\n });\n\nprogram\n .command('init')\n .description('Configure the Bulkgrid MCP server')\n .option('--all', 'configure all supported agents')\n .option('--cursor', 'configure Cursor')\n .option('--vscode', 'configure VS Code')\n .option('--claude', 'configure Claude Code')\n .option('--codex', 'configure Codex')\n .option('--mcp-url <url>', 'Bulkgrid MCP server URL')\n .option('--api-key <key>', 'Bulkgrid API key; defaults to BULKGRID_API_KEY')\n .option('--global', 'write global user configuration where supported')\n .option('--project', 'write project configuration where supported')\n .option('--yes', 'do not prompt for missing values')\n .option('--write-api-key', 'write the API key into generated JSON config files')\n .option('--install-global', 'install @bulkgrid/cli globally before configuring agents')\n .option('--auth <mode>', 'authentication mode: browser, manual, or skip')\n .action(async options => {\n try {\n const results = await runInitCommand(options);\n if (results.length === 0) {\n console.log('No MCP clients configured.');\n return;\n }\n for (const result of results) {\n const marker = result.status === 'configured' ? 'configured' : 'skipped';\n console.log(`${result.agent}: ${marker} - ${result.message}`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error(`bulkgrid init failed: ${message}`);\n process.exitCode = 1;\n }\n });\n\nregisterSourceCommands(program);\n\nprogram.parseAsync().catch(error => {\n console.error(`bulkgrid: ${error instanceof Error ? error.message : 'Command failed'}`);\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":["uuid","createSourceClient","packageMetadata.version"],"sources":["../src/apiKeyClient.ts","../src/monitors.ts","../src/sources.ts","../package.json","../src/cli.ts"],"sourcesContent":["import { BulkgridClient } from '@bulkgrid/sdk';\n\nexport function createApiKeyClient(options: { url?: string }): BulkgridClient {\n const apiKey = process.env.BULKGRID_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'Management commands require BULKGRID_API_KEY with explicit operation scopes. CLI OAuth login remains search-only.',\n );\n }\n const baseUrl = new URL(options.url ?? process.env.BULKGRID_URL ?? 'https://bulkgrid.com');\n if (baseUrl.username || baseUrl.password || baseUrl.search || baseUrl.hash || baseUrl.pathname !== '/') {\n throw new Error('Use a Bulkgrid origin URL without credentials, a path, query, or fragment.');\n }\n if (\n baseUrl.protocol !== 'https:' &&\n !(baseUrl.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(baseUrl.hostname))\n ) {\n throw new Error('Remote Bulkgrid deployments require HTTPS.');\n }\n return new BulkgridClient({ apiKey, baseUrl: baseUrl.origin });\n}\n","import { Command } from 'commander';\nimport { BulkgridClient, monitorInputSchemas } from '@bulkgrid/sdk';\nimport { z } from 'zod';\nimport { createApiKeyClient } from './apiKeyClient.js';\n\ninterface Options {\n url?: string;\n input?: string;\n offset?: string;\n}\nconst uuid = z.uuid();\nconst pagination = (options: Options) => ({\n offset: z.coerce\n .number()\n .int()\n .min(0)\n .max(100000)\n .parse(options.offset ?? 0),\n});\n\nexport function registerMonitorCommands(\n program: Command,\n clientFactory: (options: Options) => BulkgridClient = createApiKeyClient,\n): void {\n const monitors = program.command('monitors').description('Manage change monitors with a scoped API key; outputs JSON');\n const command = (name: string, description: string) =>\n monitors\n .command(name)\n .description(description)\n .option('--url <url>', 'Bulkgrid origin; defaults to BULKGRID_URL or https://bulkgrid.com');\n const print = (result: unknown) => console.log(JSON.stringify(result, null, 2));\n command('list', 'List up to 50 monitors')\n .option('--offset <offset>', 'Pagination offset')\n .action(async (options: Options) => print(await clientFactory(options).monitors.list(pagination(options))));\n command('get <monitorId>', 'Read settings and last check status').action(async (id: string, options: Options) =>\n print(await clientFactory(options).monitors.get(uuid.parse(id))),\n );\n command('create', 'Create a monitor; Pages targets start recurring crawling. Output includes a sensitive signing secret')\n .requiredOption('--input <json>', 'Monitor configuration including target and notification destinations')\n .action(async (options: Options) =>\n print(await clientFactory(options).monitors.create(monitorInputSchemas.create.parse(JSON.parse(options.input ?? '{}')))),\n );\n command('update <monitorId>', 'Edit settings, pause or resume with is_active')\n .requiredOption('--input <json>', 'Partial monitor configuration')\n .action(async (id: string, options: Options) =>\n print(\n await clientFactory(options).monitors.update(\n uuid.parse(id),\n monitorInputSchemas.update.parse(JSON.parse(options.input ?? '{}')),\n ),\n ),\n );\n command('delete <monitorId>', 'Delete the monitor and its event history').action(async (id: string, options: Options) =>\n print(await clientFactory(options).monitors.delete(uuid.parse(id))),\n );\n command('events <monitorId>', 'List up to 50 events')\n .option('--offset <offset>', 'Pagination offset')\n .action(async (id: string, options: Options) =>\n print(await clientFactory(options).monitors.events(uuid.parse(id), pagination(options))),\n );\n command('comparison <monitorId> <eventId>', 'Read before and after content for an event').action(\n async (id: string, event: string, options: Options) =>\n print(await clientFactory(options).monitors.comparison(uuid.parse(id), uuid.parse(event))),\n );\n command('retry <monitorId> <eventId>', 'Retry a failed event; may send notifications').action(\n async (id: string, event: string, options: Options) =>\n print(await clientFactory(options).monitors.retry(uuid.parse(id), { event_id: uuid.parse(event) })),\n );\n command('rotate-secret <monitorId>', 'Invalidate the old webhook secret immediately and print the new sensitive secret').action(\n async (id: string, options: Options) => print(await clientFactory(options).monitors.rotateSecret(uuid.parse(id))),\n );\n command('slack-connections', 'List authorized Slack notification channels').action(async (options: Options) =>\n print(await clientFactory(options).monitors.slackConnections()),\n );\n}\n","import { createApiKeyClient as createSourceClient } from './apiKeyClient.js';\nexport { createApiKeyClient as createSourceClient } from './apiKeyClient.js';\nimport { Command } from 'commander';\nimport { BulkgridClient, sourceInputSchemas } from '@bulkgrid/sdk';\nimport { z } from 'zod';\n\ninterface SourceCommandOptions {\n url?: string;\n input?: string;\n}\ntype ClientFactory = (options: SourceCommandOptions) => BulkgridClient;\nconst uuid = z.uuid();\n\nexport function registerSourceCommands(program: Command, clientFactory: ClientFactory = createSourceClient): void {\n const sources = program.command('sources').description('Inspect and manage sources with a scoped API key; outputs JSON');\n const command = (name: string, description: string) =>\n sources\n .command(name)\n .description(description)\n .option('--url <url>', 'Bulkgrid origin; defaults to BULKGRID_URL or https://bulkgrid.com');\n const print = (result: unknown) => console.log(JSON.stringify(result, null, 2));\n command('find <query>', 'Find existing sources before adding one').action(\n async (query: string, options: SourceCommandOptions) => print(await clientFactory(options).index.sources.search(query)),\n );\n command('analyze <sourceUrl>', 'Start deeper analysis; may create a crawl run and consume resources').action(\n async (url: string, options: SourceCommandOptions) => print(await clientFactory(options).index.sources.analyze({ url })),\n );\n command('analysis-status <analysisId>', 'Read analysis progress and warnings').action(\n async (analysisId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.getAnalysis(uuid.parse(analysisId))),\n );\n command('add', 'Create or subscribe to a source; may initiate ongoing ingestion')\n .requiredOption('--input <json>', 'Source configuration JSON including explicit visibility, boundaries and refresh interval')\n .action(async (options: SourceCommandOptions) => {\n const input = sourceInputSchemas.create\n .safeExtend({ visibility: z.enum(['public', 'private']) })\n .parse(JSON.parse(options.input ?? '{}'));\n print(await clientFactory(options).index.sources.create(input));\n });\n command('github-connections', 'List workspace GitHub connections and permitted repositories').action(\n async (options: SourceCommandOptions) => print(await clientFactory(options).index.sources.githubConnections()),\n );\n command('subscribe <sourceId>', 'Subscribe to an existing public source without starting ingestion').action(\n async (sourceId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.subscribe(uuid.parse(sourceId))),\n );\n command('add-github', 'Create a GitHub source; private repositories require a workspace connection')\n .requiredOption(\n '--input <json>',\n 'Repository URL, explicit visibility, connection_id for private repositories and indexing settings',\n )\n .action(async (options: SourceCommandOptions) => {\n const input = sourceInputSchemas.createGithub\n .extend({ repositoryUrl: z.url(), visibility: z.enum(['public', 'private']) })\n .parse(JSON.parse(options.input ?? '{}'));\n sourceInputSchemas.createGithub.parse(input);\n print(await clientFactory(options).index.sources.createGithub(input));\n });\n command('analyze-github', 'Analyze documentation paths in a permitted GitHub repository')\n .requiredOption('--input <json>', 'Repository URL and optional connection_id and ref')\n .action(async (options: SourceCommandOptions) => {\n const input = sourceInputSchemas.analyzeGithub.extend({ repositoryUrl: z.url() }).parse(JSON.parse(options.input ?? '{}'));\n sourceInputSchemas.analyzeGithub.parse(input);\n print(await clientFactory(options).index.sources.analyzeGithub(input));\n });\n command('status <sourceId>', 'Read crawl status, errors, size and indexed item counts').action(\n async (sourceId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.status(uuid.parse(sourceId))),\n );\n command('recrawl <sourceId>', 'Start a manual refresh using saved configuration; may consume credits').action(\n async (sourceId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.sources.recrawl(uuid.parse(sourceId))),\n );\n command('collections', 'List collections available for source management').action(async (options: SourceCommandOptions) =>\n print(await clientFactory(options).index.collections.list()),\n );\n command('rules <collectionId>', 'Inspect collection rules before changing membership').action(\n async (collectionId: string, options: SourceCommandOptions) =>\n print(await clientFactory(options).index.collections.rules(uuid.parse(collectionId))),\n );\n command(\n 'include <sourceId> <collectionId>',\n 'Include the entire source in a collection, broadening its retrieval coverage',\n ).action(async (sourceId: string, collectionId: string, options: SourceCommandOptions) =>\n print(\n await clientFactory(options).index.collections.addSource({\n sourceId: uuid.parse(sourceId),\n collectionId: uuid.parse(collectionId),\n }),\n ),\n );\n}\n","","#!/usr/bin/env node\nimport { registerMonitorCommands } from './monitors.js';\nimport { registerSourceCommands } from './sources.js';\nimport packageMetadata from '../package.json' with { type: 'json' };\nimport { Command } from 'commander';\n\nimport { CliAuth } from './auth.js';\n\nimport { runInitCommand } from './init.js';\n\nconst program = new Command();\n\nprogram.name('bulkgrid').description('Bulkgrid developer tooling').version(packageMetadata.version);\n\nconst auth = new CliAuth();\n\nprogram\n .command('login')\n .description('Sign in to Bulkgrid in your browser')\n .option('--url <url>', 'Bulkgrid base URL; defaults to BULKGRID_URL or https://bulkgrid.com')\n .option('--no-browser', 'print the login URL without opening a browser')\n .action(async options => {\n const session = await auth.login(options);\n console.log(`Logged in to workspace ${session.workspaceId}. Manage access in Settings → Connected Apps.`);\n });\n\nprogram\n .command('status')\n .description('Verify the saved CLI connection and show its access')\n .option('--url <url>', 'Bulkgrid base URL; defaults to BULKGRID_URL or https://bulkgrid.com')\n .action(async options => {\n const session = await auth.status(options.url);\n console.log(`Connected as ${session.userId} to workspace ${session.workspaceId}.`);\n console.log(`Permissions: ${session.scopes.join(', ')}; collections: ${session.collectionScope}.`);\n });\n\nprogram\n .command('logout')\n .description('Revoke this CLI connection and remove its saved tokens')\n .option('--url <url>', 'Bulkgrid base URL; defaults to BULKGRID_URL or https://bulkgrid.com')\n .option('--local', 'only remove local tokens; revoke access separately in Connected Apps')\n .action(async options => {\n await auth.logout(options);\n console.log(options.local ? 'Local credentials removed. Server access was not revoked.' : 'Logged out.');\n });\n\nprogram\n .command('init')\n .description('Configure the Bulkgrid MCP server')\n .option('--all', 'configure all supported agents')\n .option('--cursor', 'configure Cursor')\n .option('--vscode', 'configure VS Code')\n .option('--claude', 'configure Claude Code')\n .option('--codex', 'configure Codex')\n .option('--mcp-url <url>', 'Bulkgrid MCP server URL')\n .option('--api-key <key>', 'Bulkgrid API key; defaults to BULKGRID_API_KEY')\n .option('--global', 'write global user configuration where supported')\n .option('--project', 'write project configuration where supported')\n .option('--yes', 'do not prompt for missing values')\n .option('--write-api-key', 'write the API key into generated JSON config files')\n .option('--install-global', 'install @bulkgrid/cli globally before configuring agents')\n .option('--auth <mode>', 'authentication mode: browser, manual, or skip')\n .action(async options => {\n try {\n const results = await runInitCommand(options);\n if (results.length === 0) {\n console.log('No MCP clients configured.');\n return;\n }\n for (const result of results) {\n const marker = result.status === 'configured' ? 'configured' : 'skipped';\n console.log(`${result.agent}: ${marker} - ${result.message}`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error(`bulkgrid init failed: ${message}`);\n process.exitCode = 1;\n }\n });\n\nregisterSourceCommands(program);\nregisterMonitorCommands(program);\n\nprogram.parseAsync().catch(error => {\n console.error(`bulkgrid: ${error instanceof Error ? error.message : 'Command failed'}`);\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
//#region src/init.d.ts
|
|
3
2
|
type AgentName = 'cursor' | 'vscode' | 'claude' | 'codex';
|
|
4
3
|
type AuthMode = 'browser' | 'manual' | 'skip';
|
|
5
4
|
interface InitFlags {
|
|
@@ -25,8 +24,6 @@ interface SetupResult {
|
|
|
25
24
|
readonly message: string;
|
|
26
25
|
}
|
|
27
26
|
declare function runInitCommand(options: InitCommandOptions): Promise<readonly SetupResult[]>;
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/authStorage.d.ts
|
|
30
27
|
declare const credentialsSchema: z.ZodObject<{
|
|
31
28
|
origin: z.ZodString;
|
|
32
29
|
issuer: z.ZodString;
|
|
@@ -46,8 +43,6 @@ declare class AuthStorage {
|
|
|
46
43
|
clear(origin: string): Promise<void>;
|
|
47
44
|
exclusive<T>(origin: string, operation: () => Promise<T>): Promise<T>;
|
|
48
45
|
}
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/auth.d.ts
|
|
51
46
|
declare const sessionSchema: z.ZodObject<{
|
|
52
47
|
userId: z.ZodString;
|
|
53
48
|
workspaceId: z.ZodString;
|
|
@@ -83,6 +78,5 @@ declare class CliAuth {
|
|
|
83
78
|
local?: boolean;
|
|
84
79
|
}): Promise<void>;
|
|
85
80
|
}
|
|
86
|
-
//#endregion
|
|
87
81
|
export { CliAuth, type CliSession, type InitCommandOptions, type LoginOptions, resolveOrigin, runInitCommand };
|
|
88
82
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/init.ts","../src/authStorage.ts","../src/auth.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/init.ts","../src/authStorage.ts","../src/auth.ts"],"mappings":";KAWK;KACA;UASK;WACC;WACA;WACA;WACA;WACA;;UAGM,2BAA2B;WACjC;WACA;WACA;WACA;WACA;WACA;WACA;WACA,OAAO;;UAeR;WACC,OAAO;WACP;WACA;;iBA6XW,eAAe,SAAS,qBAAqB,iBAAiB;cC9avE,mBAAiB,EAAA;;;;;;;;GAQ5B,EAAA,KAAA;KACU,iBAAiB,EAAE,aAAa;cAM/B;mBACkB;EAAA,YAAA;UAErB;EAIF,KAAK,iBAAiB,QAAQ;EAkB9B,KAAK,aAAa,iBAAiB;EAiBnC,MAAM,iBAAiB;EASvB,UAAU,GAAG,gBAAgB,iBAAiB,QAAQ,KAAK,QAAQ;;cCnDrE,eAAa,EAAA;;;;;;;;;GAMjB,EAAA,KAAA;KACU,aAAa,EAAE,aAAa;UACvB;WACN;WACA;;iBAkBK,cAAc;cAiBjB;mBAEQ;mBACA;EADA,YAAA,UAAO,aACP,iBAAgB;UAGrB;UASA;UASA;EA0BR,MAAM,UAAS,cAAmB,eAAc,uBAA0C,QAAQ;UAmE1F;UAUA;UA0BA;EAQR,OAAO,eAAe,QAAQ;;EAM9B,eAAe,eAAe;EAS9B,OAAO;IAAW;IAAc;MAAyB"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { CliAuth, resolveOrigin, runInitCommand };
|
|
1
|
+
export { t as CliAuth, n as resolveOrigin, r as runInitCommand } from "./auth-DQ_NoZtw.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bulkgrid/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/bulkgrid/ai-extraction-platform.git",
|
|
7
|
+
"directory": "packages/cli"
|
|
8
|
+
},
|
|
4
9
|
"type": "module",
|
|
5
10
|
"exports": {
|
|
6
11
|
".": {
|
|
@@ -28,7 +33,7 @@
|
|
|
28
33
|
"@inquirer/prompts": "7.10.1",
|
|
29
34
|
"commander": "14.0.3",
|
|
30
35
|
"zod": "4.4.3",
|
|
31
|
-
"@bulkgrid/sdk": "^0.
|
|
36
|
+
"@bulkgrid/sdk": "^0.5.0"
|
|
32
37
|
},
|
|
33
38
|
"devDependencies": {
|
|
34
39
|
"@repo/eslint-config": "*",
|