diff --git a/apps/desktop/src/app/DesktopAppIdentity.test.ts b/apps/desktop/src/app/DesktopAppIdentity.test.ts index 8629193b207..3c95b266bc1 100644 --- a/apps/desktop/src/app/DesktopAppIdentity.test.ts +++ b/apps/desktop/src/app/DesktopAppIdentity.test.ts @@ -126,7 +126,7 @@ const withIdentity = ( input.legacyPathProbeError ? Effect.fail(input.legacyPathProbeError) : Effect.succeed( - input.legacyPathExists === true && path.includes("T3 Code (Alpha v2)"), + input.legacyPathExists === true && path.includes("T3 Code (Alpha)"), ), readFileString: () => Effect.succeed(input.packageJson ?? '{"t3codeCommitHash":"abcdef1234567890"}'), @@ -147,14 +147,14 @@ describe("DesktopAppIdentity", () => { const identity = yield* DesktopAppIdentity.DesktopAppIdentity; const userDataPath = yield* identity.resolveUserDataPath; - assert.equal(userDataPath, "/Users/alice/Library/Application Support/T3 Code (Alpha v2)"); + assert.equal(userDataPath, "/Users/alice/Library/Application Support/T3 Code (Alpha)"); }), { legacyPathExists: true }, ), ); it.effect("preserves failures while inspecting the legacy userData path", () => { - const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Alpha v2)"; + const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Alpha)"; const cause = PlatformError.systemError({ _tag: "PermissionDenied", module: "FileSystem", diff --git a/apps/desktop/src/app/DesktopConnectionCatalogStore.test.ts b/apps/desktop/src/app/DesktopConnectionCatalogStore.test.ts index 1ee8817763e..7c7818994f6 100644 --- a/apps/desktop/src/app/DesktopConnectionCatalogStore.test.ts +++ b/apps/desktop/src/app/DesktopConnectionCatalogStore.test.ts @@ -254,7 +254,7 @@ describe("DesktopConnectionCatalogStore", () => { _tag: "PermissionDenied", module: "FileSystem", method: "readFileString", - pathOrDescriptor: `${baseDir}/userdata-v2/connection-catalog.json`, + pathOrDescriptor: `${baseDir}/userdata/connection-catalog.json`, }); const fileSystemLayer = Layer.succeed( FileSystem.FileSystem, @@ -271,11 +271,11 @@ describe("DesktopConnectionCatalogStore", () => { error, DesktopConnectionCatalogStore.DesktopConnectionCatalogStoreReadError, ); - assert.equal(error.catalogPath, `${baseDir}/userdata-v2/connection-catalog.json`); + assert.equal(error.catalogPath, `${baseDir}/userdata/connection-catalog.json`); assert.strictEqual(error.cause, permissionError); assert.equal( error.message, - `Failed to read the desktop connection catalog at ${baseDir}/userdata-v2/connection-catalog.json.`, + `Failed to read the desktop connection catalog at ${baseDir}/userdata/connection-catalog.json.`, ); assert.notEqual(error.message, permissionError.message); }).pipe(Effect.provide(NodeServices.layer), Effect.scoped), @@ -291,7 +291,7 @@ describe("DesktopConnectionCatalogStore", () => { _tag: "PermissionDenied", module: "FileSystem", method: "makeDirectory", - pathOrDescriptor: `${baseDir}/userdata-v2`, + pathOrDescriptor: `${baseDir}/userdata`, }); const fileSystemLayer = Layer.succeed( FileSystem.FileSystem, @@ -309,11 +309,11 @@ describe("DesktopConnectionCatalogStore", () => { DesktopConnectionCatalogStore.DesktopConnectionCatalogStoreWriteError, ); assert.equal(error.operation, "create-directory"); - assert.equal(error.path, `${baseDir}/userdata-v2`); + assert.equal(error.path, `${baseDir}/userdata`); assert.strictEqual(error.cause, permissionError); assert.equal( error.message, - `Desktop connection catalog write failed during create-directory at ${baseDir}/userdata-v2.`, + `Desktop connection catalog write failed during create-directory at ${baseDir}/userdata.`, ); assert.notEqual(error.message, permissionError.message); }).pipe(Effect.provide(NodeServices.layer), Effect.scoped), @@ -398,14 +398,14 @@ describe("DesktopConnectionCatalogStore", () => { DesktopConnectionCatalogStore.DesktopConnectionCatalogStoreProtectionError, ); assert.equal(error.operation, "decrypt-catalog"); - assert.equal(error.catalogPath, `${baseDir}/userdata-v2/connection-catalog.json`); + assert.equal(error.catalogPath, `${baseDir}/userdata/connection-catalog.json`); assert.instanceOf(error.cause, ElectronSafeStorage.ElectronSafeStorageDecryptError); const decryptError = error.cause as ElectronSafeStorage.ElectronSafeStorageDecryptError; assert.instanceOf(decryptError.cause, Error); assert.equal(decryptError.cause.message, "invalid encrypted catalog"); assert.equal( error.message, - `Desktop connection catalog protection failed during decrypt-catalog at ${baseDir}/userdata-v2/connection-catalog.json.`, + `Desktop connection catalog protection failed during decrypt-catalog at ${baseDir}/userdata/connection-catalog.json.`, ); assert.notEqual(error.message, decryptError.message); yield* Ref.set(failDecrypt, false); diff --git a/apps/desktop/src/app/DesktopEnvironment.test.ts b/apps/desktop/src/app/DesktopEnvironment.test.ts index 9a52592995a..05d4c17891c 100644 --- a/apps/desktop/src/app/DesktopEnvironment.test.ts +++ b/apps/desktop/src/app/DesktopEnvironment.test.ts @@ -78,7 +78,7 @@ describe("DesktopEnvironment", () => { }), ); - it.effect("derives production state paths under userdata-v2", () => + it.effect("reuses production state and identity paths from existing installations", () => Effect.gen(function* () { const environment = yield* makeEnvironment( {}, @@ -88,12 +88,18 @@ describe("DesktopEnvironment", () => { ); assert.equal(environment.isDevelopment, false); - assert.equal(environment.stateDir, "/tmp/t3/userdata-v2"); - assert.equal(environment.logDir, "/tmp/t3/userdata-v2/logs"); - assert.equal(environment.browserArtifactsDir, "/tmp/t3/userdata-v2/browser-artifacts"); - assert.equal(environment.serverSettingsPath, "/tmp/t3/userdata-v2/settings.json"); - assert.equal(environment.userDataDirName, "t3code-v2"); - assert.equal(environment.legacyUserDataDirName, "T3 Code (Alpha v2)"); + assert.equal(environment.stateDir, "/tmp/t3/userdata"); + assert.equal(environment.desktopSettingsPath, "/tmp/t3/userdata/desktop-settings.json"); + assert.equal(environment.clientSettingsPath, "/tmp/t3/userdata/client-settings.json"); + assert.equal( + environment.savedEnvironmentRegistryPath, + "/tmp/t3/userdata/saved-environments.json", + ); + assert.equal(environment.logDir, "/tmp/t3/userdata/logs"); + assert.equal(environment.browserArtifactsDir, "/tmp/t3/userdata/browser-artifacts"); + assert.equal(environment.serverSettingsPath, "/tmp/t3/userdata/settings.json"); + assert.equal(environment.userDataDirName, "t3code"); + assert.equal(environment.legacyUserDataDirName, "T3 Code (Alpha)"); }), ); diff --git a/apps/desktop/src/app/DesktopEnvironment.ts b/apps/desktop/src/app/DesktopEnvironment.ts index 823b3a6294f..061a9368c53 100644 --- a/apps/desktop/src/app/DesktopEnvironment.ts +++ b/apps/desktop/src/app/DesktopEnvironment.ts @@ -155,9 +155,9 @@ const make = Effect.fn("desktop.environment.make")(function* ( appVersion: input.appVersion, }); const displayName = branding.displayName; - const stateDir = path.join(baseDir, isDevelopment ? "dev" : "userdata-v2"); - const userDataDirName = isDevelopment ? "t3code-dev" : "t3code-v2"; - const legacyUserDataDirName = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha v2)"; + const stateDir = path.join(baseDir, isDevelopment ? "dev" : "userdata"); + const userDataDirName = isDevelopment ? "t3code-dev" : "t3code"; + const legacyUserDataDirName = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; const resourcesPath = input.resourcesPath; return DesktopEnvironment.of({ diff --git a/apps/desktop/src/backend/DesktopBackendConfiguration.test.ts b/apps/desktop/src/backend/DesktopBackendConfiguration.test.ts index 60df9db7977..24c90943ec3 100644 --- a/apps/desktop/src/backend/DesktopBackendConfiguration.test.ts +++ b/apps/desktop/src/backend/DesktopBackendConfiguration.test.ts @@ -358,7 +358,7 @@ describe("DesktopBackendConfiguration", () => { const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); - const settingsPath = path.join(baseDir, "userdata-v2", "settings.json"); + const settingsPath = path.join(baseDir, "userdata", "settings.json"); const cause = PlatformError.systemError({ _tag: "PermissionDenied", module: "FileSystem", diff --git a/apps/desktop/src/backend/DesktopBackendConfiguration.ts b/apps/desktop/src/backend/DesktopBackendConfiguration.ts index 9dc196ef69d..7ae3ad6c912 100644 --- a/apps/desktop/src/backend/DesktopBackendConfiguration.ts +++ b/apps/desktop/src/backend/DesktopBackendConfiguration.ts @@ -503,7 +503,7 @@ const resolveWslStartConfig = Effect.fn("desktop.backendConfiguration.resolveWsl }; // Forward the dev-server URL as an explicit CLI flag so the WSL backend's - // config resolution lands in dev/ instead of userdata-v2/. Inheriting through + // config resolution lands in dev/ instead of userdata/. Inheriting through // WSLENV is unreliable in practice (URL-shaped values with colons / // slashes get translated unpredictably depending on flags), and the // packaged build leaves devServerUrl as None anyway. diff --git a/apps/desktop/src/settings/DesktopClientSettings.diagnostics.test.ts b/apps/desktop/src/settings/DesktopClientSettings.diagnostics.test.ts index db68a51b2d4..5034df44cf7 100644 --- a/apps/desktop/src/settings/DesktopClientSettings.diagnostics.test.ts +++ b/apps/desktop/src/settings/DesktopClientSettings.diagnostics.test.ts @@ -83,7 +83,7 @@ describe("DesktopClientSettings diagnostics", () => { _tag: "PermissionDenied", module: "FileSystem", method: "readFileString", - pathOrDescriptor: `${baseDir}/userdata-v2/client-settings.json`, + pathOrDescriptor: `${baseDir}/userdata/client-settings.json`, }); return Effect.gen(function* () { diff --git a/apps/desktop/src/settings/DesktopSavedEnvironments.test.ts b/apps/desktop/src/settings/DesktopSavedEnvironments.test.ts index 08cd158739c..ec70308b3d3 100644 --- a/apps/desktop/src/settings/DesktopSavedEnvironments.test.ts +++ b/apps/desktop/src/settings/DesktopSavedEnvironments.test.ts @@ -403,7 +403,7 @@ describe("DesktopSavedEnvironments", () => { const baseDir = yield* baseFileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-saved-environments-test-", }); - const registryPath = `${baseDir}/userdata-v2/saved-environments.json`; + const registryPath = `${baseDir}/userdata/saved-environments.json`; const permissionError = PlatformError.systemError({ _tag: "PermissionDenied", module: "FileSystem", @@ -439,7 +439,7 @@ describe("DesktopSavedEnvironments", () => { _tag: "PermissionDenied", module: "FileSystem", method: "makeDirectory", - pathOrDescriptor: `${baseDir}/userdata-v2`, + pathOrDescriptor: `${baseDir}/userdata`, }); const fileSystemLayer = Layer.succeed( FileSystem.FileSystem, @@ -455,11 +455,11 @@ describe("DesktopSavedEnvironments", () => { const error = yield* savedEnvironments.setRegistry([savedRegistryRecord]).pipe(Effect.flip); assert.instanceOf(error, DesktopSavedEnvironments.DesktopSavedEnvironmentsWriteError); assert.equal(error.operation, "create-directory"); - assert.equal(error.path, `${baseDir}/userdata-v2`); + assert.equal(error.path, `${baseDir}/userdata`); assert.strictEqual(error.cause, permissionError); assert.equal( error.message, - `Desktop saved-environment write failed during create-directory at ${baseDir}/userdata-v2.`, + `Desktop saved-environment write failed during create-directory at ${baseDir}/userdata.`, ); assert.notEqual(error.message, permissionError.message); }).pipe(Effect.provide(NodeServices.layer), Effect.scoped), diff --git a/apps/server/src/cli/config.test.ts b/apps/server/src/cli/config.test.ts index 0ececb07f3b..fd5aa4d674f 100644 --- a/apps/server/src/cli/config.test.ts +++ b/apps/server/src/cli/config.test.ts @@ -56,6 +56,19 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { return fd; }); + it.effect("keeps production state in userdata while isolating development state", () => + Effect.gen(function* () { + const { join } = yield* Path.Path; + const baseDir = join(NodeOS.tmpdir(), "t3-cli-config-state-paths"); + + const productionPaths = yield* deriveServerPaths(baseDir, undefined); + const developmentPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:5173")); + + assert.equal(productionPaths.stateDir, join(baseDir, "userdata")); + assert.equal(developmentPaths.stateDir, join(baseDir, "dev")); + }), + ); + it.effect("falls back to effect/config values when flags are omitted", () => Effect.gen(function* () { const { join } = yield* Path.Path; @@ -328,7 +341,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { tailscaleServeEnabled: false, tailscaleServePort: 443, }); - assert.equal(join(baseDir, "userdata-v2"), resolved.stateDir); + assert.equal(join(baseDir, "userdata"), resolved.stateDir); }), ); @@ -377,6 +390,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { ]) { expect(yield* fs.exists(directory)).toBe(true); } + expect(resolved.stateDir).toBe(path.join(baseDir, "dev")); expect(resolved.cwd).toBe(path.resolve(customCwd)); }), ); diff --git a/apps/server/src/config.ts b/apps/server/src/config.ts index 7d737238137..2608ccc16ae 100644 --- a/apps/server/src/config.ts +++ b/apps/server/src/config.ts @@ -93,7 +93,7 @@ export const deriveServerPaths = Effect.fn(function* ( devUrl: ServerConfig["Service"]["devUrl"], ): Effect.fn.Return { const { join } = yield* Path.Path; - const stateDir = join(baseDir, devUrl !== undefined ? "dev" : "userdata-v2"); + const stateDir = join(baseDir, devUrl !== undefined ? "dev" : "userdata"); const dbPath = join(stateDir, "state.sqlite"); const attachmentsDir = join(stateDir, "attachments"); const logsDir = join(stateDir, "logs"); diff --git a/packages/ssh/src/tunnel.test.ts b/packages/ssh/src/tunnel.test.ts index d32b5fe3e94..7e7a5a54276 100644 --- a/packages/ssh/src/tunnel.test.ts +++ b/packages/ssh/src/tunnel.test.ts @@ -189,7 +189,7 @@ describe("ssh tunnel scripts", () => { assert.include(buildRemoteStopScript(target), 'rm -f "$PID_FILE" "$PORT_FILE" "$MANAGED_FILE"'); assert.include( buildRemoteLaunchScript(), - 'DEFAULT_RUNTIME_FILE="$DEFAULT_SERVER_HOME/userdata-v2/server-runtime.json"', + 'DEFAULT_RUNTIME_FILE="$DEFAULT_SERVER_HOME/userdata/server-runtime.json"', ); assert.include(buildRemoteLaunchScript(), "resolve_default_runtime_port()"); assert.include( diff --git a/packages/ssh/src/tunnel.ts b/packages/ssh/src/tunnel.ts index 25ea25a787b..016d5e9a854 100644 --- a/packages/ssh/src/tunnel.ts +++ b/packages/ssh/src/tunnel.ts @@ -440,7 +440,7 @@ export const REMOTE_LAUNCH_SCRIPT = `set -eu STATE_KEY="$1" STATE_DIR="$HOME/.t3/ssh-launch/$STATE_KEY" DEFAULT_SERVER_HOME="$HOME/.t3" -DEFAULT_RUNTIME_FILE="$DEFAULT_SERVER_HOME/userdata-v2/server-runtime.json" +DEFAULT_RUNTIME_FILE="$DEFAULT_SERVER_HOME/userdata/server-runtime.json" PORT_FILE="$STATE_DIR/port" PID_FILE="$STATE_DIR/pid" MANAGED_FILE="$STATE_DIR/managed"