From 2dd5889395f7748fbb20d956f41d6b3fffcae698 Mon Sep 17 00:00:00 2001 From: alvarosabu Date: Mon, 26 May 2025 15:12:31 +0200 Subject: [PATCH 1/4] fix(creds): get first credential to operate --- src/creds.test.ts | 5 +++-- src/creds.ts | 7 ++++--- src/session.ts | 9 +++++---- src/types/index.ts | 8 ++++++++ 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/creds.test.ts b/src/creds.test.ts index edaad92..6b46fd9 100644 --- a/src/creds.test.ts +++ b/src/creds.test.ts @@ -1,5 +1,6 @@ import { addCredentials, getCredentials, removeCredentials } from './creds'; import { vol } from 'memfs'; +import type { StoryblokCredentials } from './types'; // tell vitest to use fs mock from __mocks__ folder // this can be done in a setup file if fs should always be mocked vi.mock('node:fs'); @@ -23,7 +24,7 @@ describe('creds', async () => { }), }, '/temp'); - const credentials = await getCredentials('/temp/test/credentials.json'); + const credentials = await getCredentials('/temp/test/credentials.json') as StoryblokCredentials; expect(credentials['api.storyblok.com']).toEqual({ login: 'julio.iglesias@storyblok.com', @@ -33,7 +34,7 @@ describe('creds', async () => { }); it('should create a credentials.json file if it does not exist', async () => { const credentials = await getCredentials('/temp/test/nonexistent.json'); - expect(credentials).toEqual({}); + expect(credentials).toEqual(null); }); }); diff --git a/src/creds.ts b/src/creds.ts index bf44f45..8b9322b 100644 --- a/src/creds.ts +++ b/src/creds.ts @@ -5,8 +5,9 @@ import chalk from 'chalk'; import type { RegionCode } from './constants'; import { colorPalette, regionsDomain } from './constants'; import { getStoryblokGlobalPath, readFile, saveToFile } from './utils/filesystem'; +import type { StoryblokCredentials } from './types'; -export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), 'credentials.json')) => { +export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), 'credentials.json')): Promise => { try { await access(filePath); const content = await readFile(filePath); @@ -16,10 +17,10 @@ export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), ' if ((error as NodeJS.ErrnoException).code === 'ENOENT') { // File doesn't exist, create it with empty credentials await saveToFile(filePath, JSON.stringify({}, null, 2), { mode: 0o600 }); - return {}; + return null; } handleFileSystemError('read', error as NodeJS.ErrnoException); - return {}; + return null; } }; diff --git a/src/session.ts b/src/session.ts index d6ea6a3..6e8e88a 100644 --- a/src/session.ts +++ b/src/session.ts @@ -17,7 +17,7 @@ function createSession() { isLoggedIn: false, }; - async function initializeSession(region = 'eu' as RegionCode) { + async function initializeSession() { // First, check for environment variables const envCredentials = getEnvCredentials(); if (envCredentials) { @@ -30,9 +30,10 @@ function createSession() { } // If no environment variables, fall back to .storyblok/credentials.json - const machines = await getCredentials(); - const creds = machines[regionsDomain[region] || 'api.storyblok.com']; - if (creds) { + const credentials = await getCredentials(); + if (credentials) { + // Todo: evaluate this in future when we want to support multiple regions + const creds = Object.values(credentials)[0]; state.isLoggedIn = true; state.login = creds.login; state.password = creds.password; diff --git a/src/types/index.ts b/src/types/index.ts index de58176..970a0e1 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,5 @@ +import type { RegionCode } from '../constants'; + /** * Interface representing the default options for a CLI command. */ @@ -54,3 +56,9 @@ export interface FileReaderResult { data: T[]; error?: Error; } + +export interface StoryblokCredentials { + login: string; + password: string; + region: RegionCode; +} From 992e3a24fa15e498454c39b3c87d48167d786ddd Mon Sep 17 00:00:00 2001 From: alvarosabu Date: Tue, 27 May 2025 12:36:33 +0200 Subject: [PATCH 2/4] fix(creds): update getCredentials to return empty object instead of null - Modified the getCredentials function to return an empty object when the credentials file does not exist, improving type consistency. - Updated related tests to reflect this change, ensuring that the expected output aligns with the new implementation. - Introduced a utility function isEmptyObject to check for empty objects, enhancing code readability and maintainability. --- src/creds.test.ts | 2 +- src/creds.ts | 6 +++--- src/session.ts | 3 ++- src/utils/index.ts | 4 ++++ 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/creds.test.ts b/src/creds.test.ts index 6b46fd9..2514b68 100644 --- a/src/creds.test.ts +++ b/src/creds.test.ts @@ -34,7 +34,7 @@ describe('creds', async () => { }); it('should create a credentials.json file if it does not exist', async () => { const credentials = await getCredentials('/temp/test/nonexistent.json'); - expect(credentials).toEqual(null); + expect(credentials).toEqual({}); }); }); diff --git a/src/creds.ts b/src/creds.ts index 8b9322b..4acee66 100644 --- a/src/creds.ts +++ b/src/creds.ts @@ -7,7 +7,7 @@ import { colorPalette, regionsDomain } from './constants'; import { getStoryblokGlobalPath, readFile, saveToFile } from './utils/filesystem'; import type { StoryblokCredentials } from './types'; -export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), 'credentials.json')): Promise => { +export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), 'credentials.json')): Promise => { try { await access(filePath); const content = await readFile(filePath); @@ -17,10 +17,10 @@ export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), ' if ((error as NodeJS.ErrnoException).code === 'ENOENT') { // File doesn't exist, create it with empty credentials await saveToFile(filePath, JSON.stringify({}, null, 2), { mode: 0o600 }); - return null; + return {}; } handleFileSystemError('read', error as NodeJS.ErrnoException); - return null; + return {}; } }; diff --git a/src/session.ts b/src/session.ts index 6e8e88a..b5804c2 100644 --- a/src/session.ts +++ b/src/session.ts @@ -1,6 +1,7 @@ // session.ts import { type RegionCode, regionsDomain } from './constants'; import { addCredentials, getCredentials } from './creds'; +import { isEmptyObject } from './utils'; interface SessionState { isLoggedIn: boolean; @@ -31,7 +32,7 @@ function createSession() { // If no environment variables, fall back to .storyblok/credentials.json const credentials = await getCredentials(); - if (credentials) { + if (!isEmptyObject(credentials)) { // Todo: evaluate this in future when we want to support multiple regions const creds = Object.values(credentials)[0]; state.isLoggedIn = true; diff --git a/src/utils/index.ts b/src/utils/index.ts index 0dc77d6..654f220 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -14,4 +14,8 @@ export function isRegion(value: RegionCode): value is RegionCode { return Object.values(regions).includes(value); } +export function isEmptyObject(obj: object): boolean { + return Object.keys(obj).length === 0; +} + export const isVitest = process.env.VITEST === 'true'; From d2d099902e2956540bdd1e0b9045b061fbbf7d91 Mon Sep 17 00:00:00 2001 From: alvarosabu Date: Tue, 27 May 2025 12:42:17 +0200 Subject: [PATCH 3/4] fix(creds): update getCredentials to return null for empty credentials - Modified the getCredentials function to return null instead of an empty object when the credentials file is empty or does not exist, improving type consistency. - Updated related tests to reflect this change, ensuring that the expected output aligns with the new implementation. - Adjusted session handling to check for null credentials, enhancing the robustness of the session creation process. --- src/creds.test.ts | 2 +- src/creds.ts | 15 +++++++++++---- src/session.ts | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/creds.test.ts b/src/creds.test.ts index 2514b68..6b46fd9 100644 --- a/src/creds.test.ts +++ b/src/creds.test.ts @@ -34,7 +34,7 @@ describe('creds', async () => { }); it('should create a credentials.json file if it does not exist', async () => { const credentials = await getCredentials('/temp/test/nonexistent.json'); - expect(credentials).toEqual({}); + expect(credentials).toEqual(null); }); }); diff --git a/src/creds.ts b/src/creds.ts index 4acee66..ede3e12 100644 --- a/src/creds.ts +++ b/src/creds.ts @@ -7,20 +7,27 @@ import { colorPalette, regionsDomain } from './constants'; import { getStoryblokGlobalPath, readFile, saveToFile } from './utils/filesystem'; import type { StoryblokCredentials } from './types'; -export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), 'credentials.json')): Promise => { +export const getCredentials = async (filePath = join(getStoryblokGlobalPath(), 'credentials.json')): Promise => { try { await access(filePath); const content = await readFile(filePath); - return JSON.parse(content); + const parsedContent = JSON.parse(content); + + // Return null if the parsed content is an empty object + if (Object.keys(parsedContent).length === 0) { + return null; + } + + return parsedContent; } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') { // File doesn't exist, create it with empty credentials await saveToFile(filePath, JSON.stringify({}, null, 2), { mode: 0o600 }); - return {}; + return null; } handleFileSystemError('read', error as NodeJS.ErrnoException); - return {}; + return null; } }; diff --git a/src/session.ts b/src/session.ts index b5804c2..08aa82a 100644 --- a/src/session.ts +++ b/src/session.ts @@ -32,7 +32,7 @@ function createSession() { // If no environment variables, fall back to .storyblok/credentials.json const credentials = await getCredentials(); - if (!isEmptyObject(credentials)) { + if (credentials) { // Todo: evaluate this in future when we want to support multiple regions const creds = Object.values(credentials)[0]; state.isLoggedIn = true; From d61edd65c18029604025ad1c0bd2ce06b410c086 Mon Sep 17 00:00:00 2001 From: alvarosabu Date: Tue, 27 May 2025 12:43:14 +0200 Subject: [PATCH 4/4] refactor(session): remove unused isEmptyObject import - Removed the unused import of isEmptyObject from utils, streamlining the session.ts file and improving code clarity. - This change does not affect the functionality of the session handling. --- src/session.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/session.ts b/src/session.ts index 08aa82a..6e8e88a 100644 --- a/src/session.ts +++ b/src/session.ts @@ -1,7 +1,6 @@ // session.ts import { type RegionCode, regionsDomain } from './constants'; import { addCredentials, getCredentials } from './creds'; -import { isEmptyObject } from './utils'; interface SessionState { isLoggedIn: boolean;