feat: l'IDE devient la vue par défaut + deep-link worktree unifié
Some checks failed
CI / Build & test (Node 22) (push) Successful in 10m13s
CI / Pack & boot smoke (Node 22) (push) Has been cancelled
CI / No em/en dashes (push) Has been cancelled
CI / Build & test (Node 24) (push) Has been cancelled

Route / redirige vers /ide ; le dashboard passe à /dashboard (nom inchangé). /workspace/:repoId/:wt rend désormais l'IDE (IdeShell) : au montage il décode la clé, active et déplie le worktree ciblé, ouvre ?file= le cas échéant. WorkspaceView et useWorkspaceLayout retirés.

encode/decodeWtKey déplacés dans @arboretum/shared (source unique) avec décodeur TOLÉRANT (base64url OU chemin percent-encodé), corrigeant la divergence historique du deep-link VS Code. config.ts de l'extension aligné sur encodeWtKey. Tests wt-key (shared) + config (vscode) mis à jour. 431 tests.
This commit is contained in:
2026-07-17 17:28:48 +02:00
parent 6741b2d47c
commit d287c3c1d1
10 changed files with 97 additions and 262 deletions

View File

@@ -1,2 +1,3 @@
export * from './protocol.js';
export * from './api.js';
export * from './wt-key.js';

View File

@@ -0,0 +1,33 @@
// Encodage du chemin absolu d'un worktree pour le segment d'URL /workspace/:repoId/:wt.
// Source unique partagée par le front web ET l'extension VS Code (deep-link), pour éviter toute
// divergence d'encodage. base64url (sans +, /, =) donne un segment propre et réversible.
/** Encode un chemin absolu en base64url (sûr en segment d'URL). */
export function encodeWtKey(path: string): string {
const b64 = btoa(unescape(encodeURIComponent(path)));
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
/**
* Décode une clé de worktree vers son chemin absolu. Tolérant à deux formats historiques :
* - base64url (front web, encodeWtKey) ;
* - chemin percent-encodé (ancien deep-link VS Code via encodeURIComponent) : reconnaissable au
* caractère `%` que le base64url ne contient jamais.
* Ne lève pas : renvoie la clé telle quelle en dernier recours.
*/
export function decodeWtKey(key: string): string {
if (key.includes('%')) {
try {
return decodeURIComponent(key);
} catch {
return key;
}
}
const b64 = key.replace(/-/g, '+').replace(/_/g, '/');
const pad = b64.length % 4 === 0 ? '' : '='.repeat(4 - (b64.length % 4));
try {
return decodeURIComponent(escape(atob(b64 + pad)));
} catch {
return key;
}
}

View File

@@ -0,0 +1,24 @@
import { describe, it, expect } from 'vitest';
import { encodeWtKey, decodeWtKey } from '../src/wt-key.js';
describe('wt-key', () => {
it('encode puis decode restitue le chemin (aller-retour)', () => {
for (const p of ['/home/johan/repo', '/a/b c/é', '/tmp/x-y_z', 'C:/Users/x/proj']) {
expect(decodeWtKey(encodeWtKey(p))).toBe(p);
}
});
it('un segment base64url ne contient ni %, ni +, ni /, ni =', () => {
const k = encodeWtKey('/home/johan/mon repo/sous-dossier');
expect(k).not.toMatch(/[%+/=]/);
});
it('décode aussi un chemin percent-encodé (ancien deep-link VS Code)', () => {
const raw = encodeURIComponent('/home/johan/repo');
expect(decodeWtKey(raw)).toBe('/home/johan/repo');
});
it('ne lève pas sur une clé invalide', () => {
expect(() => decodeWtKey('!!!not-valid')).not.toThrow();
});
});