From 9b407567b5351603f5d0faa4f22958965b072a49 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 10 Jun 2026 09:16:04 -0400 Subject: [PATCH] refactor(paths): consolidate ~/.socket dir constants, add _state, drop dead helpers --- src/constants/socket.ts | 26 ++- src/env/socket.ts | 10 ++ src/paths/dirnames.ts | 3 + src/paths/socket.ts | 259 +++++++++++----------------- test/unit/constants/socket.test.mts | 63 +++---- test/unit/paths.test.mts | 107 +++++------- test/unit/paths/socket.test.mts | 62 +++---- 7 files changed, 228 insertions(+), 302 deletions(-) diff --git a/src/constants/socket.ts b/src/constants/socket.ts index 31f3d1176..441a30e10 100644 --- a/src/constants/socket.ts +++ b/src/constants/socket.ts @@ -34,13 +34,25 @@ export const SOCKET_REGISTRY_REPO_NAME = 'socket-registry' export const SOCKET_REGISTRY_PACKAGE_NAME = '@socketsecurity/registry' export const SOCKET_REGISTRY_NPM_ORG = 'socketregistry' -// Socket.dev application names. -export const SOCKET_CLI_APP_NAME = 'socket' -export const SOCKET_DLX_APP_NAME = 'dlx' -export const SOCKET_FIREWALL_APP_NAME = 'sfw' -export const SOCKET_REGISTRY_APP_NAME = 'registry' -export const SOCKET_WHEELHOUSE_APP_NAME = 'wheelhouse' -export const SOCKET_APP_PREFIX = '_' +// The `_` prefix that marks a Socket-managed subdir of ~/.socket/. Applies to +// BOTH app dirs (_socket, _registry) and infra/storage dirs (_cacache, _dlx, +// _state) — so it is a DIR prefix, not an "app" prefix. +export const SOCKET_DIR_PREFIX = '_' + +// Full names of the Socket-managed infra/storage DIRS under ~/.socket/ (the `_` +// prefix included — these are dirs, not apps, and the bare form is never used +// on its own). `_cacache` content-addressable cache; `_dlx` name+version binary +// store (node, jre, python, sfw, …); `_state` version-LESS persistent app state +// (= pnpm `state-dir` / XDG_STATE_HOME); `_wheelhouse` cross-fleet shared bin. +export const SOCKET_DIR = { + __proto__: null, + cacache: `${SOCKET_DIR_PREFIX}cacache`, + dlx: `${SOCKET_DIR_PREFIX}dlx`, + state: `${SOCKET_DIR_PREFIX}state`, + wheelhouse: `${SOCKET_DIR_PREFIX}wheelhouse`, +} as unknown as Readonly< + Record<'cacache' | 'dlx' | 'state' | 'wheelhouse', string> +> // Socket.dev lib. export const SOCKET_LIB_NAME = '@socketsecurity/lib' diff --git a/src/env/socket.ts b/src/env/socket.ts index ff51071dc..af4df1031 100644 --- a/src/env/socket.ts +++ b/src/env/socket.ts @@ -413,6 +413,16 @@ export function getSocketRepositoryName(): string | undefined { ) } +/** + * SOCKET_STATE_DIR environment variable getter. Overrides the default Socket + * state directory (~/.socket/_state) location. + * + * @returns The state directory path, or `undefined` if not set + */ +export function getSocketStateDirEnv(): string | undefined { + return getEnvValue('SOCKET_STATE_DIR') +} + /** * SOCKET_VIEW_ALL_RISKS environment variable getter. Whether to view all Socket * Security risks. diff --git a/src/paths/dirnames.ts b/src/paths/dirnames.ts index 064ee55a6..cbd76121c 100644 --- a/src/paths/dirnames.ts +++ b/src/paths/dirnames.ts @@ -9,6 +9,9 @@ export const DOT_GITHUB = '.github' export const DOT_SOCKET_DIR = '.socket' export const CACHE_DIR = 'cache' export const CACHE_TTL_DIR = 'ttl' +// Runtime subdir of an app's state dir (~/.socket/_state//run/) — home for +// a daemon's Unix socket + concurrency.lock + .pid. +export const RUN_DIR = 'run' // Path patterns. export const NODE_MODULES_GLOB_RECURSIVE = '**/node_modules' diff --git a/src/paths/socket.ts b/src/paths/socket.ts index 3c596341b..a3191c0d8 100644 --- a/src/paths/socket.ts +++ b/src/paths/socket.ts @@ -1,31 +1,26 @@ /** - * @file Path utilities for Socket ecosystem directories. Provides - * platform-aware path resolution for Socket tools' shared directory - * structure. Directory Structure: ~/.socket/ ├── _cacache/ # - * Content-addressable cache for npm packages ├── _dlx/ # DLX installations - * (content-addressed by hash) │ ├── / # npm package installs - * (dlx-package) │ └── / # binary downloads (dlx-binary) ├── _socket/ # - * Socket CLI app directory ├── _registry/ # Socket Registry app directory └── - * _sfw/ # Socket Firewall app directory. + * @file Path utilities for Socket ecosystem directories. Platform-aware + * resolution for the shared ~/.socket/ layout. The `_`-prefixed entries are + * Socket-managed DIRS (not apps): `_cacache` content-addressable cache; + * `_dlx//` name+version binary store (node, jre, python, sfw, …); + * `_state//` version-LESS persistent app state (daemon socket + lock + + * OAuth refresh; mirrors pnpm `state-dir` / XDG_STATE_HOME), with + * `_state//run/` for a daemon's socket/lock/pid; `_wheelhouse` + * cross-fleet shared bin. Generic per-app dirs (`getSocketAppDir('')`) + * nest under the same `_`-prefix. */ -import { CACHE_GITHUB_DIR } from '../constants/github' -import { - SOCKET_APP_PREFIX, - SOCKET_CLI_APP_NAME, - SOCKET_DLX_APP_NAME, - SOCKET_REGISTRY_APP_NAME, - SOCKET_WHEELHOUSE_APP_NAME, -} from '../constants/socket' +import { SOCKET_DIR, SOCKET_DIR_PREFIX } from '../constants/socket' import { getHome } from '../env/home' import { getSocketCacacheDirEnv, getSocketDlxDirEnv, getSocketHome, + getSocketStateDirEnv, } from '../env/socket' import { getUserprofile } from '../env/windows' -import { CACHE_DIR, CACHE_TTL_DIR, DOT_SOCKET_DIR } from './dirnames' +import { CACHE_DIR, CACHE_TTL_DIR, DOT_SOCKET_DIR, RUN_DIR } from './dirnames' import { normalizePath } from './normalize' import { getPathValue } from './rewire' @@ -78,40 +73,60 @@ export function getSocketAppCacheTtlDir(appName: string): string { return normalizePath(path.join(getSocketAppCacheDir(appName), CACHE_TTL_DIR)) } /** - * Get a Socket app directory (~/.socket/_). + * Get a Socket app directory (~/.socket/_). The `_` prefix is applied + * here; pass the bare app name (e.g. 'socket', 'registry'). */ /** - * Get a Socket app directory (~/.socket/_). + * Get a Socket app directory (~/.socket/_). The `_` prefix is applied + * here; pass the bare app name (e.g. 'socket', 'registry'). */ export function getSocketAppDir(appName: string): string { const path = getNodePath() return normalizePath( - path.join(getSocketUserDir(), `${SOCKET_APP_PREFIX}${appName}`), + path.join(getSocketUserDir(), `${SOCKET_DIR_PREFIX}${appName}`), ) } /** - * Get the Socket cacache directory (~/.socket/_cacache). Can be overridden with - * SOCKET_CACACHE_DIR environment variable or via setPath() for testing. Result - * is cached via getPathValue for performance. - * - * Priority order: - * - * 1. Test override via setPath('socket-cacache-dir', ...) - * 2. SOCKET_CACACHE_DIR - Full override of cacache directory - * 3. Default: $SOCKET_HOME/_cacache or $HOME/.socket/_cacache + * Get the Socket cacache directory (~/.socket/_cacache). Override precedence: + * setPath('socket-cacache-dir', …) → SOCKET_CACACHE_DIR env → + * $SOCKET_HOME/_cacache → $HOME/.socket/_cacache. */ /** - * Get the Socket cacache directory (~/.socket/_cacache). Can be overridden with - * SOCKET_CACACHE_DIR environment variable or via setPath() for testing. Result - * is cached via getPathValue for performance. - * - * Priority order: - * - * 1. Test override via setPath('socket-cacache-dir', ...) - * 2. SOCKET_CACACHE_DIR - Full override of cacache directory - * 3. Default: $SOCKET_HOME/_cacache or $HOME/.socket/_cacache + * Get an app's runtime directory (~/.socket/_state//run/) — the home for a + * daemon's Unix socket + `concurrency.lock` + `.pid`. Version-less so + * the socket path is stable across binary upgrades. + */ +export function getSocketAppRuntimeDir(appName: string): string { + const path = getNodePath() + return normalizePath(path.join(getSocketAppStateDir(appName), RUN_DIR)) +} +/** + * Get the Socket user directory (~/.socket). Override precedence: + * setPath('socket-user-dir', …) → SOCKET_HOME env → $HOME/.socket → + * /tmp/.socket (Unix) or %TEMP%.socket (Windows). + */ + +/** + * Get an app's persistent state directory (~/.socket/_state//). The + * `` is a real app (proteus, acorn) nesting its version-less state inside + * the `_state` infra dir. + */ +export function getSocketAppStateDir(appName: string): string { + const path = getNodePath() + return normalizePath(path.join(getSocketStateDir(), appName)) +} +/** + * Get an app's runtime directory (~/.socket/_state//run/) — the home for a + * daemon's Unix socket + `concurrency.lock` + `.pid`. Version-less so + * the socket path is stable across binary upgrades. + */ + +/** + * Get the Socket cacache directory (~/.socket/_cacache). Override precedence: + * setPath('socket-cacache-dir', …) → SOCKET_CACACHE_DIR env → + * $SOCKET_HOME/_cacache → $HOME/.socket/_cacache. */ export function getSocketCacacheDir(): string { return getPathValue('socket-cacache-dir', () => { @@ -119,47 +134,19 @@ export function getSocketCacacheDir(): string { return normalizePath(getSocketCacacheDirEnv() as string) } const path = getNodePath() - return normalizePath( - path.join(getSocketUserDir(), `${SOCKET_APP_PREFIX}cacache`), - ) + return normalizePath(path.join(getSocketUserDir(), SOCKET_DIR.cacache)) }) } /** - * Get the Socket CLI directory (~/.socket/_socket). - */ - -/** - * Get the Socket CLI directory (~/.socket/_socket). - */ -export function getSocketCliDir(): string { - return getSocketAppDir(SOCKET_CLI_APP_NAME) -} -/** - * Get the Socket DLX directory (~/.socket/_dlx). Can be overridden with - * SOCKET_DLX_DIR environment variable or via setPath() for testing. Result is - * cached via getPathValue for performance. - * - * Priority order: - * - * 1. Test override via setPath('socket-dlx-dir', ...) - * 2. SOCKET_DLX_DIR - Full override of DLX cache directory - * 3. SOCKET_HOME/_dlx - Base directory override (inherits from getSocketUserDir) - * 4. Default: $HOME/.socket/_dlx - * 5. Fallback: /tmp/.socket/_dlx (Unix) or %TEMP%.socket_dlx (Windows) + * Get the Socket DLX directory (~/.socket/_dlx) — the name+version binary store + * (node, jre, python, sfw, …). Override precedence: setPath('socket-dlx-dir', + * …) → SOCKET_DLX_DIR env → $SOCKET_HOME/_dlx → $HOME/.socket/_dlx. */ /** - * Get the Socket DLX directory (~/.socket/_dlx). Can be overridden with - * SOCKET_DLX_DIR environment variable or via setPath() for testing. Result is - * cached via getPathValue for performance. - * - * Priority order: - * - * 1. Test override via setPath('socket-dlx-dir', ...) - * 2. SOCKET_DLX_DIR - Full override of DLX cache directory - * 3. SOCKET_HOME/_dlx - Base directory override (inherits from getSocketUserDir) - * 4. Default: $HOME/.socket/_dlx - * 5. Fallback: /tmp/.socket/_dlx (Unix) or %TEMP%.socket_dlx (Windows) + * Get the Socket DLX directory (~/.socket/_dlx) — the name+version binary store + * (node, jre, python, sfw, …). Override precedence: setPath('socket-dlx-dir', + * …) → SOCKET_DLX_DIR env → $SOCKET_HOME/_dlx → $HOME/.socket/_dlx. */ export function getSocketDlxDir(): string { return getPathValue('socket-dlx-dir', () => { @@ -167,12 +154,7 @@ export function getSocketDlxDir(): string { return normalizePath(getSocketDlxDirEnv() as string) } const path = getNodePath() - return normalizePath( - path.join( - getSocketUserDir(), - `${SOCKET_APP_PREFIX}${SOCKET_DLX_APP_NAME}`, - ), - ) + return normalizePath(path.join(getSocketUserDir(), SOCKET_DIR.dlx)) }) } /** @@ -188,60 +170,39 @@ export function getSocketHomePath(): string { return getSocketUserDir() } /** - * Get the Socket Registry directory (~/.socket/_registry). + * Get the Socket state directory (~/.socket/_state) — version-LESS persistent + * app state (the home for daemon sockets, locks, OAuth refresh, durable caches + * that survive version bumps; mirrors pnpm `state-dir` / XDG_STATE_HOME). + * Override precedence: setPath('socket-state-dir', …) → SOCKET_STATE_DIR env → + * $SOCKET_HOME/_state → $HOME/.socket/_state. */ /** - * Get the Socket Registry directory (~/.socket/_registry). - */ -export function getSocketRegistryDir(): string { - return getSocketAppDir(SOCKET_REGISTRY_APP_NAME) -} -/** - * Get the Socket Registry GitHub cache directory - * (~/.socket/_registry/cache/ttl/github). + * Get the Socket state directory (~/.socket/_state) — version-LESS persistent + * app state (the home for daemon sockets, locks, OAuth refresh, durable caches + * that survive version bumps; mirrors pnpm `state-dir` / XDG_STATE_HOME). + * Override precedence: setPath('socket-state-dir', …) → SOCKET_STATE_DIR env → + * $SOCKET_HOME/_state → $HOME/.socket/_state. */ - -/** - * Get the Socket Registry GitHub cache directory - * (~/.socket/_registry/cache/ttl/github). - */ -export function getSocketRegistryGithubCacheDir(): string { - const path = getNodePath() - return normalizePath( - path.join( - getSocketAppCacheTtlDir(SOCKET_REGISTRY_APP_NAME), - CACHE_GITHUB_DIR, - ), - ) +export function getSocketStateDir(): string { + return getPathValue('socket-state-dir', () => { + if (getSocketStateDirEnv()) { + return normalizePath(getSocketStateDirEnv() as string) + } + const path = getNodePath() + return normalizePath(path.join(getSocketUserDir(), SOCKET_DIR.state)) + }) } /** - * Get the Socket Wheelhouse directory (~/.socket/_wheelhouse). Shared - * cross-fleet location for binaries that every fleet member can reach without - * each one re-downloading and re-extracting per-repo. Tool installers (janus, - * sfw, etc.) drop their resolved executables under - * `////`; consumers add the - * appropriate `bin/` to PATH or invoke the binary by absolute path. - * - * Priority order: - * - * 1. Test override via setPath('socket-wheelhouse-dir', ...) - * 2. SOCKET_HOME/_wheelhouse - Base directory override (inherits from - * getSocketUserDir) - * 3. Default: $HOME/.socket/_wheelhouse + * Get an app's persistent state directory (~/.socket/_state//). The + * `` is a real app (proteus, acorn) nesting its version-less state inside + * the `_state` infra dir. */ /** - * Get the Socket user directory (~/.socket). Can be overridden with SOCKET_HOME - * environment variable or via setPath() for testing. Result is cached via - * getPathValue for performance. - * - * Priority order: - * - * 1. Test override via setPath('socket-user-dir', ...) - * 2. SOCKET_HOME - Base directory override - * 3. Default: $HOME/.socket - * 4. Fallback: /tmp/.socket (Unix) or %TEMP%.socket (Windows) + * Get the Socket user directory (~/.socket). Override precedence: + * setPath('socket-user-dir', …) → SOCKET_HOME env → $HOME/.socket → + * /tmp/.socket (Unix) or %TEMP%.socket (Windows). */ export function getSocketUserDir(): string { return getPathValue('socket-user-dir', () => { @@ -254,12 +215,14 @@ export function getSocketUserDir(): string { }) } /** - * Get the user's home directory. Uses environment variables directly to support - * test mocking. Falls back to temporary directory if home is not available. - * - * Priority order: 1. HOME environment variable (Unix) 2. USERPROFILE - * environment variable (Windows) 3. getNodeOs().homedir() 4. Fallback: - * getNodeOs().tmpdir() (rarely used, for restricted environments) + * Get the Socket Wheelhouse directory (~/.socket/_wheelhouse). Shared + * cross-fleet location for binaries that every fleet member can reach without + * each one re-downloading and re-extracting per-repo. Tool installers (janus, + * sfw, etc.) drop their resolved executables under + * `////`; consumers add the + * appropriate `bin/` to PATH or invoke the binary by absolute path. Override + * precedence: setPath('socket-wheelhouse-dir', …) → $SOCKET_HOME/_wheelhouse → + * $HOME/.socket/_wheelhouse. */ /** @@ -268,46 +231,30 @@ export function getSocketUserDir(): string { * each one re-downloading and re-extracting per-repo. Tool installers (janus, * sfw, etc.) drop their resolved executables under * `////`; consumers add the - * appropriate `bin/` to PATH or invoke the binary by absolute path. - * - * Priority order: - * - * 1. Test override via setPath('socket-wheelhouse-dir', ...) - * 2. SOCKET_HOME/_wheelhouse - Base directory override (inherits from - * getSocketUserDir) - * 3. Default: $HOME/.socket/_wheelhouse + * appropriate `bin/` to PATH or invoke the binary by absolute path. Override + * precedence: setPath('socket-wheelhouse-dir', …) → $SOCKET_HOME/_wheelhouse → + * $HOME/.socket/_wheelhouse. */ export function getSocketWheelhouseDir(): string { return getPathValue('socket-wheelhouse-dir', () => { const path = getNodePath() - return normalizePath( - path.join( - getSocketUserDir(), - `${SOCKET_APP_PREFIX}${SOCKET_WHEELHOUSE_APP_NAME}`, - ), - ) + return normalizePath(path.join(getSocketUserDir(), SOCKET_DIR.wheelhouse)) }) } /** - * Get the Socket user directory (~/.socket). Can be overridden with SOCKET_HOME - * environment variable or via setPath() for testing. Result is cached via - * getPathValue for performance. - * - * Priority order: + * Get the user's home directory. Uses environment variables directly to support + * test mocking. Falls back to temporary directory if home is not available. * - * 1. Test override via setPath('socket-user-dir', ...) - * 2. SOCKET_HOME - Base directory override - * 3. Default: $HOME/.socket - * 4. Fallback: /tmp/.socket (Unix) or %TEMP%.socket (Windows) + * Priority order: 1. HOME (Unix) 2. USERPROFILE (Windows) 3. + * getNodeOs().homedir() 4. Fallback: getNodeOs().tmpdir() (restricted envs). */ /** * Get the user's home directory. Uses environment variables directly to support * test mocking. Falls back to temporary directory if home is not available. * - * Priority order: 1. HOME environment variable (Unix) 2. USERPROFILE - * environment variable (Windows) 3. getNodeOs().homedir() 4. Fallback: - * getNodeOs().tmpdir() (rarely used, for restricted environments) + * Priority order: 1. HOME (Unix) 2. USERPROFILE (Windows) 3. + * getNodeOs().homedir() 4. Fallback: getNodeOs().tmpdir() (restricted envs). */ export function getUserHomeDir(): string { // Try HOME first (Unix) diff --git a/test/unit/constants/socket.test.mts b/test/unit/constants/socket.test.mts index f129585e3..f6e9a671c 100644 --- a/test/unit/constants/socket.test.mts +++ b/test/unit/constants/socket.test.mts @@ -12,12 +12,8 @@ import { CACHE_SOCKET_API_DIR as canonicalCacheSocketApiDir, REGISTRY as canonicalRegistry, - SOCKET_CLI_APP_NAME as canonicalSocketCliAppName, - SOCKET_DLX_APP_NAME as canonicalSocketDlxAppName, - SOCKET_FIREWALL_APP_NAME as canonicalSocketFirewallAppName, SOCKET_IPC_HANDSHAKE as canonicalSocketIpcHandshake, SOCKET_PUBLIC_API_KEY as canonicalSocketPublicApiKey, - SOCKET_REGISTRY_APP_NAME as canonicalSocketRegistryAppName, } from '@socketsecurity/lib-stable/constants/socket' import { describe, expect, it } from 'vitest' @@ -27,20 +23,17 @@ import { REGISTRY_SCOPE_DELIMITER, SOCKET_API_BASE_URL, SOCKET_API_TOKENS_URL, - SOCKET_APP_PREFIX, - SOCKET_CLI_APP_NAME, SOCKET_CONTACT_URL, SOCKET_DASHBOARD_URL, - SOCKET_DLX_APP_NAME, + SOCKET_DIR, + SOCKET_DIR_PREFIX, SOCKET_DOCS_URL, - SOCKET_FIREWALL_APP_NAME, SOCKET_GITHUB_ORG, SOCKET_IPC_HANDSHAKE, SOCKET_OVERRIDE_SCOPE, SOCKET_PRICING_URL, SOCKET_PUBLIC_API_KEY, SOCKET_PUBLIC_API_TOKEN, - SOCKET_REGISTRY_APP_NAME, SOCKET_REGISTRY_NPM_ORG, SOCKET_REGISTRY_PACKAGE_NAME, SOCKET_REGISTRY_REPO_NAME, @@ -255,47 +248,32 @@ describe('constants/socket', () => { }) }) - describe('Socket.dev application names', () => { - it('should export SOCKET_CLI_APP_NAME', () => { - expect(SOCKET_CLI_APP_NAME).toBe('socket') + describe('Socket.dev managed directory names', () => { + it('should export SOCKET_DIR_PREFIX', () => { + expect(SOCKET_DIR_PREFIX).toBe('_') }) - it('should export SOCKET_DLX_APP_NAME', () => { - expect(SOCKET_DLX_APP_NAME).toBe('dlx') + it('should map each infra dir to its full _-prefixed name', () => { + expect(SOCKET_DIR.cacache).toBe('_cacache') + expect(SOCKET_DIR.dlx).toBe('_dlx') + expect(SOCKET_DIR.state).toBe('_state') + expect(SOCKET_DIR.wheelhouse).toBe('_wheelhouse') }) - it('should export SOCKET_FIREWALL_APP_NAME', () => { - expect(SOCKET_FIREWALL_APP_NAME).toBe('sfw') - }) - - it('should export SOCKET_REGISTRY_APP_NAME', () => { - expect(SOCKET_REGISTRY_APP_NAME).toBe('registry') - }) - - it('should export SOCKET_APP_PREFIX', () => { - expect(SOCKET_APP_PREFIX).toBe('_') + it('should prefix every dir with SOCKET_DIR_PREFIX', () => { + for (const dir of Object.values(SOCKET_DIR)) { + expect(dir.startsWith(SOCKET_DIR_PREFIX)).toBe(true) + } }) - it('should all be lowercase', () => { - expect(SOCKET_CLI_APP_NAME).toBe(canonicalSocketCliAppName.toLowerCase()) - expect(SOCKET_DLX_APP_NAME).toBe(canonicalSocketDlxAppName.toLowerCase()) - expect(SOCKET_FIREWALL_APP_NAME).toBe( - canonicalSocketFirewallAppName.toLowerCase(), - ) - expect(SOCKET_REGISTRY_APP_NAME).toBe( - canonicalSocketRegistryAppName.toLowerCase(), - ) + it('should have unique dir names', () => { + const dirs = Object.values(SOCKET_DIR) + const unique = [...new Set(dirs)] + expect(unique.length).toBe(dirs.length) }) - it('should have unique app names', () => { - const apps = [ - SOCKET_CLI_APP_NAME, - SOCKET_DLX_APP_NAME, - SOCKET_FIREWALL_APP_NAME, - SOCKET_REGISTRY_APP_NAME, - ] - const uniqueApps = [...new Set(apps)] - expect(uniqueApps.length).toBe(apps.length) + it('should be a null-prototype map', () => { + expect(Object.getPrototypeOf(SOCKET_DIR)).toBe(null) }) }) @@ -349,7 +327,6 @@ describe('constants/socket', () => { expect(SOCKET_REGISTRY_SCOPE).toContain('registry') expect(SOCKET_REGISTRY_REPO_NAME).toContain('registry') expect(SOCKET_REGISTRY_PACKAGE_NAME).toContain('registry') - expect(SOCKET_REGISTRY_APP_NAME).toContain('registry') }) it('should have socket in API and scope names', () => { diff --git a/test/unit/paths.test.mts b/test/unit/paths.test.mts index 0a01c2662..b3cd4c5bf 100644 --- a/test/unit/paths.test.mts +++ b/test/unit/paths.test.mts @@ -7,13 +7,12 @@ * - getSocketAppCacheDir() - app-level cache storage * - getSocketAppCacheTtlDir() - TTL-based cache directory * - getSocketCacacheDir() - cacache (content-addressable cache) directory - * - getSocketCliDir() - CLI-specific directory - * - getSocketDlxDir() - dlx (download and execute) directory - * - getSocketRegistryDir() - registry data storage - * - getSocketRegistryGithubCacheDir() - GitHub API response cache Tests - * validate path existence, normalization, cross-platform consistency, and - * aliasing. These paths are critical for Socket tool state management and - * caching strategies. + * - getSocketDlxDir() - dlx (name+version binary store) directory + * - getSocketStateDir() - _state (version-less persistent app state) directory + * - getSocketAppStateDir() / getSocketAppRuntimeDir() - per-app state + run/ + * dir (daemon socket + lock) Tests validate path existence, normalization, + * cross-platform consistency, and aliasing. These paths are critical for + * Socket tool state management and caching strategies. */ import process from 'node:process' @@ -21,12 +20,12 @@ import { getSocketAppCacheDir, getSocketAppCacheTtlDir, getSocketAppDir, + getSocketAppRuntimeDir, + getSocketAppStateDir, getSocketCacacheDir, - getSocketCliDir, getSocketDlxDir, getSocketHomePath, - getSocketRegistryDir, - getSocketRegistryGithubCacheDir, + getSocketStateDir, getSocketUserDir, } from '../../src/paths/socket' import { describe, expect, it } from 'vitest' @@ -222,77 +221,51 @@ describe('paths', () => { }) }) - describe('getSocketCliDir', () => { - it('should return Socket CLI directory', () => { - const result = getSocketCliDir() - expect(result).toContain('.socket/_socket') - }) - - it('should be an app directory', () => { - const cliDir = getSocketCliDir() - const appDir = getSocketAppDir('socket') - expect(cliDir).toBe(appDir) + describe('getSocketStateDir', () => { + it('should return the _state infra directory', () => { + const result = getSocketStateDir() + expect(result).toContain('.socket/_state') }) it('should return normalized path', () => { - const result = getSocketCliDir() + const result = getSocketStateDir() expect(result).not.toContain('\\') }) it('should be under Socket user directory', () => { const userDir = getSocketUserDir() - const cliDir = getSocketCliDir() - expect(cliDir).toContain(userDir) + const stateDir = getSocketStateDir() + expect(stateDir).toContain(userDir) }) }) - describe('getSocketRegistryDir', () => { - it('should return Socket Registry directory', () => { - const result = getSocketRegistryDir() - expect(result).toContain('.socket/_registry') - }) - - it('should be an app directory', () => { - const registryDir = getSocketRegistryDir() - const appDir = getSocketAppDir('registry') - expect(registryDir).toBe(appDir) - }) - - it('should return normalized path', () => { - const result = getSocketRegistryDir() - expect(result).not.toContain('\\') + describe('getSocketAppStateDir', () => { + it('should nest the app inside _state', () => { + const result = getSocketAppStateDir('proteus') + expect(result).toContain('.socket/_state/proteus') }) - it('should be under Socket user directory', () => { - const userDir = getSocketUserDir() - const registryDir = getSocketRegistryDir() - expect(registryDir).toContain(userDir) + it('should nest under the _state dir', () => { + const result = getSocketAppStateDir('proteus') + expect(result).toMatch(/\/_state\/proteus$/) }) }) - describe('getSocketRegistryGithubCacheDir', () => { - it('should return Socket Registry GitHub cache directory', () => { - const result = getSocketRegistryGithubCacheDir() - expect(result).toContain('.socket/_registry/cache/ttl/github') + describe('getSocketAppRuntimeDir', () => { + it('should return the app run/ dir under _state', () => { + const result = getSocketAppRuntimeDir('proteus') + expect(result).toContain('.socket/_state/proteus/run') }) - it('should be under Registry TTL cache directory', () => { - const ttlDir = getSocketAppCacheTtlDir('registry') - const githubDir = getSocketRegistryGithubCacheDir() - expect(githubDir).toContain(ttlDir) - expect(githubDir).toMatch(/github$/) + it('should end with the app state dir + /run', () => { + const runDir = getSocketAppRuntimeDir('proteus') + expect(runDir).toMatch(/\/_state\/proteus\/run$/) }) it('should return normalized path', () => { - const result = getSocketRegistryGithubCacheDir() + const result = getSocketAppRuntimeDir('proteus') expect(result).not.toContain('\\') }) - - it('should be under Socket user directory', () => { - const userDir = getSocketUserDir() - const githubDir = getSocketRegistryGithubCacheDir() - expect(githubDir).toContain(userDir) - }) }) describe('path hierarchy', () => { @@ -320,11 +293,11 @@ describe('paths', () => { getSocketAppDir('test'), getSocketCacacheDir(), getSocketDlxDir(), - getSocketCliDir(), - getSocketRegistryDir(), + getSocketStateDir(), + getSocketAppStateDir('test'), getSocketAppCacheDir('test'), getSocketAppCacheTtlDir('test'), - getSocketRegistryGithubCacheDir(), + getSocketAppRuntimeDir('test'), ] // All paths should be non-empty strings @@ -452,16 +425,16 @@ describe('paths', () => { }) describe('specific app directories', () => { - it('should generate correct CLI directory', () => { - const cliDir = getSocketCliDir() + it('should generate correct app directory from a bare name', () => { + const cliDir = getSocketAppDir('socket') expect(cliDir).toContain('_socket') expect(cliDir).toMatch(/\/_socket$/) }) - it('should generate correct Registry directory', () => { - const registryDir = getSocketRegistryDir() - expect(registryDir).toContain('_registry') - expect(registryDir).toMatch(/\/_registry$/) + it('should generate correct state directory', () => { + const stateDir = getSocketStateDir() + expect(stateDir).toContain('_state') + expect(stateDir).toMatch(/\/_state$/) }) it('should generate correct DLX directory', () => { diff --git a/test/unit/paths/socket.test.mts b/test/unit/paths/socket.test.mts index c7bb7dd15..4ae1a8777 100644 --- a/test/unit/paths/socket.test.mts +++ b/test/unit/paths/socket.test.mts @@ -19,12 +19,12 @@ import { getSocketAppCacheDir, getSocketAppCacheTtlDir, getSocketAppDir, + getSocketAppRuntimeDir, + getSocketAppStateDir, getSocketCacacheDir, - getSocketCliDir, getSocketDlxDir, getSocketHomePath, - getSocketRegistryDir, - getSocketRegistryGithubCacheDir, + getSocketStateDir, getSocketUserDir, getSocketWheelhouseDir, getUserHomeDir, @@ -266,42 +266,46 @@ describe('paths/socket', () => { }) }) - describe('getSocketCliDir', () => { - it('should return Socket CLI directory', () => { - const result = getSocketCliDir() - expect(result).toContain('.socket/_socket') + describe('getSocketStateDir', () => { + it('should return the _state infra directory', () => { + const result = getSocketStateDir() + expect(result).toContain('.socket/_state') }) - it('should use standard app dir function', () => { - const result = getSocketCliDir() - const expected = getSocketAppDir('socket') - expect(result).toBe(expected) + it('should honor the SOCKET_STATE_DIR env override', () => { + setEnv('SOCKET_STATE_DIR', '/tmp/custom-state') + const result = getSocketStateDir() + expect(result).toBe('/tmp/custom-state') + }) + + it('should honor the setPath test override', () => { + setPath('socket-state-dir', '/tmp/rewired-state') + const result = getSocketStateDir() + expect(result).toBe('/tmp/rewired-state') }) }) - describe('getSocketRegistryDir', () => { - it('should return Socket Registry directory', () => { - const result = getSocketRegistryDir() - expect(result).toContain('.socket/_registry') + describe('getSocketAppStateDir', () => { + it('should nest the app inside _state', () => { + const result = getSocketAppStateDir('proteus') + expect(result).toContain('.socket/_state/proteus') }) - it('should use standard app dir function', () => { - const result = getSocketRegistryDir() - const expected = getSocketAppDir('registry') - expect(result).toBe(expected) + it('should nest under the _state dir', () => { + const result = getSocketAppStateDir('proteus') + expect(result).toMatch(/\/_state\/proteus$/) }) }) - describe('getSocketRegistryGithubCacheDir', () => { - it('should return GitHub cache directory', () => { - const result = getSocketRegistryGithubCacheDir() - expect(result).toContain('.socket/_registry/cache/ttl/github') + describe('getSocketAppRuntimeDir', () => { + it('should return the app run/ dir under _state', () => { + const result = getSocketAppRuntimeDir('proteus') + expect(result).toContain('.socket/_state/proteus/run') }) - it('should build on registry cache dir', () => { - const ttlDir = getSocketAppCacheTtlDir('registry') - const githubDir = getSocketRegistryGithubCacheDir() - expect(githubDir).toContain(ttlDir) + it('should end with the app state dir + /run', () => { + const runDir = getSocketAppRuntimeDir('proteus') + expect(runDir).toMatch(/\/_state\/proteus\/run$/) }) }) @@ -323,8 +327,8 @@ describe('paths/socket', () => { getSocketAppDir('test'), getSocketCacacheDir(), getSocketDlxDir(), - getSocketCliDir(), - getSocketRegistryDir(), + getSocketStateDir(), + getSocketAppRuntimeDir('test'), ] for (let i = 0, { length } = paths; i < length; i += 1) {