From bcdcb7ecba570835ad093ca65711ab4e22eaf906 Mon Sep 17 00:00:00 2001 From: Erik Hughes Date: Tue, 20 May 2025 13:54:48 +0200 Subject: [PATCH 1/4] feat: add client and client version to request headers --- packages/cli/package.json | 2 +- packages/cli/stores/config.ts | 19 +++++++++++++++++++ packages/cli/utils/auth.ts | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) 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..24a7dd2f 100644 --- a/packages/cli/stores/config.ts +++ b/packages/cli/stores/config.ts @@ -59,6 +59,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() { @@ -101,6 +102,20 @@ class ConfigStore { const content = await readFile(this.configPath, "utf-8"); const parsed = parseJSON(content) as unknown as Partial; + if (packageJSONPath) { + try { + const packageJSONContent = await readFile(packageJSONPath, "utf-8"); + const packageJSONParsed = parseJSON( + packageJSONContent, + ) as unknown as { + version: string; + }; + this.clientVersion = packageJSONParsed.version; + } catch { + // Should not be the case, but no package.json found + } + } + // Normalize values if (parsed.baseUrl) parsed.baseUrl = stripTrailingSlash(parsed.baseUrl.trim()); @@ -167,6 +182,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..2aca466f 100644 --- a/packages/cli/utils/auth.ts +++ b/packages/cli/utils/auth.ts @@ -153,6 +153,8 @@ export async function authRequest>( headers: { ...options?.headers, Authorization: `Bearer ${token}`, + "X-Client": "cli", + "X-Client-Version": configStore.getClientVersion() ?? "unknown", }, }); From 6c11538b9187e6152c0f377a034f12b894706862 Mon Sep 17 00:00:00 2001 From: Erik Hughes Date: Wed, 21 May 2025 10:15:33 +0200 Subject: [PATCH 2/4] feat: switched to bucket-sdk-version --- packages/cli/utils/auth.ts | 9 +++++++-- packages/cli/utils/constants.ts | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/cli/utils/auth.ts b/packages/cli/utils/auth.ts index 2aca466f..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,8 +157,9 @@ export async function authRequest>( headers: { ...options?.headers, Authorization: `Bearer ${token}`, - "X-Client": "cli", - "X-Client-Version": configStore.getClientVersion() ?? "unknown", + [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..bc6e8fef 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) => + `node-sdk/${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`; From 75b04a4d2d8dd9645f8f45786a15e2b2e15d56ee Mon Sep 17 00:00:00 2001 From: Erik Hughes Date: Wed, 21 May 2025 10:37:32 +0200 Subject: [PATCH 3/4] fix: name --- packages/cli/utils/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/utils/constants.ts b/packages/cli/utils/constants.ts index bc6e8fef..2260266d 100644 --- a/packages/cli/utils/constants.ts +++ b/packages/cli/utils/constants.ts @@ -3,7 +3,7 @@ import { join } from "node:path"; export const CLIENT_VERSION_HEADER_NAME = "bucket-sdk-version"; export const CLIENT_VERSION_HEADER_VALUE = (version: string) => - `node-sdk/${version}`; + `cli/${version}`; export const CONFIG_FILE_NAME = "bucket.config.json"; export const AUTH_FILE = join(os.homedir(), ".bucket-auth"); From bf346c10cd75d10ffacae783c6b4790d088d1936 Mon Sep 17 00:00:00 2001 From: Erik Hughes Date: Wed, 21 May 2025 11:44:02 +0200 Subject: [PATCH 4/4] refactor(config): streamline module path resolution - Introduced a `moduleRoot` constant to simplify path calculations for the schema and package.json files. - Updated the `createValidator` method to use `moduleRoot` for resolving the schema path and loading the client version from package.json, enhancing code clarity and maintainability. - Removed redundant code related to package.json path handling, improving overall efficiency. --- packages/cli/stores/config.ts | 43 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/cli/stores/config.ts b/packages/cli/stores/config.ts index 24a7dd2f..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[], @@ -70,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(); @@ -90,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; @@ -102,20 +117,6 @@ class ConfigStore { const content = await readFile(this.configPath, "utf-8"); const parsed = parseJSON(content) as unknown as Partial; - if (packageJSONPath) { - try { - const packageJSONContent = await readFile(packageJSONPath, "utf-8"); - const packageJSONParsed = parseJSON( - packageJSONContent, - ) as unknown as { - version: string; - }; - this.clientVersion = packageJSONParsed.version; - } catch { - // Should not be the case, but no package.json found - } - } - // Normalize values if (parsed.baseUrl) parsed.baseUrl = stripTrailingSlash(parsed.baseUrl.trim());