diff --git a/packages/cli/package.json b/packages/cli/package.json index 9e208261..bae2174d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@bucketco/cli", - "version": "1.0.0", + "version": "1.0.1", "packageManager": "yarn@4.1.1", "description": "CLI for Bucket service", "main": "./dist/index.js", diff --git a/packages/cli/stores/config.ts b/packages/cli/stores/config.ts index e1013564..ab04762c 100644 --- a/packages/cli/stores/config.ts +++ b/packages/cli/stores/config.ts @@ -44,6 +44,11 @@ const defaultConfig: Config = { typesOutput: [{ path: DEFAULT_TYPES_OUTPUT, format: "react" }], }; +const moduleRoot = fileURLToPath(import.meta.url).substring( + 0, + fileURLToPath(import.meta.url).lastIndexOf("cli") + 3, +); + // Helper to normalize typesOutput to array format export function normalizeTypesOutput( output?: string | TypesOutput[], @@ -59,6 +64,7 @@ class ConfigStore { protected config: Config = { ...defaultConfig }; protected configPath: string | undefined; protected projectPath: string | undefined; + protected clientVersion: string | undefined; protected validateConfig: ValidateFunction | undefined; async initialize() { @@ -69,11 +75,7 @@ class ConfigStore { protected async createValidator() { try { // Using current config store file, resolve the schema.json path - const filePath = fileURLToPath(import.meta.url); - const schemaPath = join( - filePath.substring(0, filePath.lastIndexOf("cli") + 3), - "schema.json", - ); + const schemaPath = join(moduleRoot, "schema.json"); const content = await readFile(schemaPath, "utf-8"); const parsed = parseJSON(content) as unknown as Config; const ajv = new Ajv(); @@ -89,11 +91,25 @@ class ConfigStore { return; } + // Load the client version from the module's package.json metadata try { - const packageJSONPath = await findUp("package.json"); + const moduleMetadata = await readFile( + join(moduleRoot, "package.json"), + "utf-8", + ); + const moduleMetadataParsed = parseJSON(moduleMetadata) as unknown as { + version: string; + }; + this.clientVersion = moduleMetadataParsed.version; + } catch { + // Should not be the case, but ignore if no package.json is found + } + + try { + const projectMetadataPath = await findUp("package.json"); this.configPath = await findUp(CONFIG_FILE_NAME); this.projectPath = dirname( - this.configPath ?? packageJSONPath ?? process.cwd(), + this.configPath ?? projectMetadataPath ?? process.cwd(), ); if (!this.configPath) return; @@ -167,6 +183,10 @@ class ConfigStore { return this.configPath; } + getClientVersion() { + return this.clientVersion; + } + getProjectPath() { return this.projectPath ?? process.cwd(); } diff --git a/packages/cli/utils/auth.ts b/packages/cli/utils/auth.ts index 052eda79..ca948b5f 100644 --- a/packages/cli/utils/auth.ts +++ b/packages/cli/utils/auth.ts @@ -6,6 +6,10 @@ import open from "open"; import { authStore } from "../stores/auth.js"; import { configStore } from "../stores/config.js"; +import { + CLIENT_VERSION_HEADER_NAME, + CLIENT_VERSION_HEADER_VALUE, +} from "./constants.js"; import { ParamType } from "./types.js"; import { errorUrl, loginUrl, successUrl } from "./urls.js"; @@ -153,6 +157,9 @@ export async function authRequest>( headers: { ...options?.headers, Authorization: `Bearer ${token}`, + [CLIENT_VERSION_HEADER_NAME]: CLIENT_VERSION_HEADER_VALUE( + configStore.getClientVersion() ?? "unknown", + ), }, }); diff --git a/packages/cli/utils/constants.ts b/packages/cli/utils/constants.ts index 79785867..2260266d 100644 --- a/packages/cli/utils/constants.ts +++ b/packages/cli/utils/constants.ts @@ -1,6 +1,10 @@ import os from "node:os"; import { join } from "node:path"; +export const CLIENT_VERSION_HEADER_NAME = "bucket-sdk-version"; +export const CLIENT_VERSION_HEADER_VALUE = (version: string) => + `cli/${version}`; + export const CONFIG_FILE_NAME = "bucket.config.json"; export const AUTH_FILE = join(os.homedir(), ".bucket-auth"); export const SCHEMA_URL = `https://unpkg.com/@bucketco/cli@latest/schema.json`;