[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,190 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { GoogleDriveAdapter } from './GoogleDriveAdapter.ts';
import type { OAuthTokens } from '../../../domain/sync.ts';
type WindowGlobal = typeof globalThis & { window?: unknown };
function setBridge(bridge: Record<string, unknown>): () => void {
const g = globalThis as WindowGlobal;
const original = g.window;
// Loosely typed: the real window.netcatty is a large NetcattyBridge; tests
// only stub the handful of Google methods the adapter actually calls.
g.window = { netcatty: bridge } as unknown as Window & typeof globalThis;
return () => {
g.window = original;
};
}
const expiredTokens = (): OAuthTokens => ({
accessToken: 'old-access',
refreshToken: 'old-refresh',
// Already expired so any operation forces a refresh.
expiresAt: Date.now() - 60_000,
tokenType: 'Bearer',
});
test('refreshing tokens during an operation fires the persistence callback with refreshed tokens', async () => {
const refreshed: OAuthTokens = {
accessToken: 'fresh-access',
refreshToken: 'old-refresh',
expiresAt: Date.now() + 3_600_000,
tokenType: 'Bearer',
};
let refreshCalledWith: string | undefined;
const remoteSyncedFile = { meta: { version: 1 }, payload: 'x' };
const restore = setBridge({
googleRefreshAccessToken: async ({ refreshToken }: { refreshToken: string }) => {
refreshCalledWith = refreshToken;
return refreshed;
},
googleDriveDownloadSyncFile: async ({ accessToken }: { accessToken: string }) => {
// Operation must run with the refreshed access token.
assert.equal(accessToken, 'fresh-access');
return { syncedFile: remoteSyncedFile };
},
});
try {
const adapter = new GoogleDriveAdapter(expiredTokens(), 'file-1');
const persisted: OAuthTokens[] = [];
adapter.setOnTokensRefreshed((tokens) => persisted.push(tokens));
const result = await adapter.download();
assert.deepEqual(result, remoteSyncedFile);
assert.equal(refreshCalledWith, 'old-refresh');
assert.equal(persisted.length, 1);
assert.deepEqual(persisted[0], refreshed);
// Adapter also exposes the refreshed tokens for the caller to persist.
assert.deepEqual(adapter.getTokens(), refreshed);
} finally {
restore();
}
});
test('refresh preserves the prior refresh token when Google omits a new one', async () => {
// Google's refresh response frequently has no refresh_token. The persisted
// tokens must keep the previous refresh token, or the connection becomes
// unrefreshable on the next launch.
const refreshedWithoutRefreshToken: OAuthTokens = {
accessToken: 'fresh-access',
// No refreshToken — mirrors a real Google refresh_token response.
expiresAt: Date.now() + 3_600_000,
tokenType: 'Bearer',
};
const remoteSyncedFile = { meta: { version: 1 }, payload: 'x' };
const restore = setBridge({
googleRefreshAccessToken: async () => refreshedWithoutRefreshToken,
googleDriveDownloadSyncFile: async () => ({ syncedFile: remoteSyncedFile }),
});
try {
const adapter = new GoogleDriveAdapter(expiredTokens(), 'file-1');
const persisted: OAuthTokens[] = [];
adapter.setOnTokensRefreshed((tokens) => persisted.push(tokens));
await adapter.download();
assert.equal(persisted.length, 1);
// The persisted (and in-memory) tokens carry the original refresh token.
assert.equal(persisted[0].refreshToken, 'old-refresh');
assert.equal(persisted[0].accessToken, 'fresh-access');
assert.equal(adapter.getTokens()?.refreshToken, 'old-refresh');
} finally {
restore();
}
});
test('setTokens refreshes an expired token and persists the refreshed tokens', async () => {
const refreshed: OAuthTokens = {
accessToken: 'fresh-access',
refreshToken: 'old-refresh',
expiresAt: Date.now() + 3_600_000,
tokenType: 'Bearer',
};
const restore = setBridge({
googleRefreshAccessToken: async () => refreshed,
googleGetUserInfo: async () => ({
id: 'u1',
email: 'u@example.com',
name: 'User',
picture: '',
}),
});
try {
const adapter = new GoogleDriveAdapter();
const persisted: OAuthTokens[] = [];
adapter.setOnTokensRefreshed((tokens) => persisted.push(tokens));
await adapter.setTokens(expiredTokens());
assert.deepEqual(persisted, [refreshed]);
assert.deepEqual(adapter.getTokens(), refreshed);
assert.equal(adapter.accountInfo?.id, 'u1');
} finally {
restore();
}
});
test('a persistence callback that throws does not abort the operation', async () => {
const refreshed: OAuthTokens = {
accessToken: 'fresh-access',
refreshToken: 'old-refresh',
expiresAt: Date.now() + 3_600_000,
tokenType: 'Bearer',
};
const remoteSyncedFile = { meta: { version: 1 }, payload: 'x' };
const restore = setBridge({
googleRefreshAccessToken: async () => refreshed,
googleDriveDownloadSyncFile: async () => ({ syncedFile: remoteSyncedFile }),
});
try {
const adapter = new GoogleDriveAdapter(expiredTokens(), 'file-1');
adapter.setOnTokensRefreshed(() => {
throw new Error('persist boom');
});
// Refresh succeeds, the throwing callback is swallowed, the op completes.
const result = await adapter.download();
assert.deepEqual(result, remoteSyncedFile);
assert.deepEqual(adapter.getTokens(), refreshed);
} finally {
restore();
}
});
test('signOut clears the refresh persistence callback', async () => {
const refreshed: OAuthTokens = {
accessToken: 'fresh-access',
refreshToken: 'old-refresh',
expiresAt: Date.now() + 3_600_000,
tokenType: 'Bearer',
};
const restore = setBridge({
googleRefreshAccessToken: async () => refreshed,
googleGetUserInfo: async () => ({
id: 'u1',
email: 'u@example.com',
name: 'User',
picture: '',
}),
});
try {
const adapter = new GoogleDriveAdapter(expiredTokens(), 'file-1');
let callbackFired = false;
adapter.setOnTokensRefreshed(() => {
callbackFired = true;
});
adapter.signOut();
// Re-arm tokens and refresh; the callback must not fire after signOut.
await adapter.setTokens(expiredTokens());
assert.equal(callbackFired, false);
} finally {
restore();
}
});