@infinite-room-labs/claudesync-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/__tests__/env.test.d.ts +2 -0
- package/dist/auth/__tests__/env.test.d.ts.map +1 -0
- package/dist/auth/__tests__/env.test.js +42 -0
- package/dist/auth/__tests__/env.test.js.map +1 -0
- package/dist/auth/__tests__/firefox.test.d.ts +2 -0
- package/dist/auth/__tests__/firefox.test.d.ts.map +1 -0
- package/dist/auth/__tests__/firefox.test.js +291 -0
- package/dist/auth/__tests__/firefox.test.js.map +1 -0
- package/dist/auth/env.d.ts +10 -0
- package/dist/auth/env.d.ts.map +1 -0
- package/dist/auth/env.js +46 -0
- package/dist/auth/env.js.map +1 -0
- package/dist/auth/errors.d.ts +4 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +7 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth/firefox.d.ts +12 -0
- package/dist/auth/firefox.d.ts.map +1 -0
- package/dist/auth/firefox.js +190 -0
- package/dist/auth/firefox.js.map +1 -0
- package/dist/auth/types.d.ts +10 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/client/__tests__/client.test.d.ts +2 -0
- package/dist/client/__tests__/client.test.d.ts.map +1 -0
- package/dist/client/__tests__/client.test.js +50 -0
- package/dist/client/__tests__/client.test.js.map +1 -0
- package/dist/client/__tests__/endpoints.test.d.ts +2 -0
- package/dist/client/__tests__/endpoints.test.d.ts.map +1 -0
- package/dist/client/__tests__/endpoints.test.js +26 -0
- package/dist/client/__tests__/endpoints.test.js.map +1 -0
- package/dist/client/client.d.ts +54 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +144 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/endpoints.d.ts +18 -0
- package/dist/client/endpoints.d.ts.map +1 -0
- package/dist/client/endpoints.js +25 -0
- package/dist/client/endpoints.js.map +1 -0
- package/dist/client/errors.d.ts +11 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +22 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/export/__tests__/bundle-builder.test.d.ts +2 -0
- package/dist/export/__tests__/bundle-builder.test.d.ts.map +1 -0
- package/dist/export/__tests__/bundle-builder.test.js +272 -0
- package/dist/export/__tests__/bundle-builder.test.js.map +1 -0
- package/dist/export/__tests__/conversation-formatter.test.d.ts +2 -0
- package/dist/export/__tests__/conversation-formatter.test.d.ts.map +1 -0
- package/dist/export/__tests__/conversation-formatter.test.js +99 -0
- package/dist/export/__tests__/conversation-formatter.test.js.map +1 -0
- package/dist/export/bundle-builder.d.ts +24 -0
- package/dist/export/bundle-builder.d.ts.map +1 -0
- package/dist/export/bundle-builder.js +94 -0
- package/dist/export/bundle-builder.js.map +1 -0
- package/dist/export/conversation-formatter.d.ts +23 -0
- package/dist/export/conversation-formatter.d.ts.map +1 -0
- package/dist/export/conversation-formatter.js +40 -0
- package/dist/export/conversation-formatter.js.map +1 -0
- package/dist/export/git-exporter.d.ts +12 -0
- package/dist/export/git-exporter.d.ts.map +1 -0
- package/dist/export/git-exporter.js +68 -0
- package/dist/export/git-exporter.js.map +1 -0
- package/dist/export/types.d.ts +27 -0
- package/dist/export/types.d.ts.map +1 -0
- package/dist/export/types.js +2 -0
- package/dist/export/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/models/__tests__/schemas.test.d.ts +2 -0
- package/dist/models/__tests__/schemas.test.d.ts.map +1 -0
- package/dist/models/__tests__/schemas.test.js +189 -0
- package/dist/models/__tests__/schemas.test.js.map +1 -0
- package/dist/models/schemas.d.ts +805 -0
- package/dist/models/schemas.d.ts.map +1 -0
- package/dist/models/schemas.js +119 -0
- package/dist/models/schemas.js.map +1 -0
- package/dist/models/types.d.ts +15 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +2 -0
- package/dist/models/types.js.map +1 -0
- package/dist/tree/__tests__/message-tree.test.d.ts +2 -0
- package/dist/tree/__tests__/message-tree.test.d.ts.map +1 -0
- package/dist/tree/__tests__/message-tree.test.js +176 -0
- package/dist/tree/__tests__/message-tree.test.js.map +1 -0
- package/dist/tree/message-tree.d.ts +35 -0
- package/dist/tree/message-tree.d.ts.map +1 -0
- package/dist/tree/message-tree.js +70 -0
- package/dist/tree/message-tree.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.test.d.ts","sourceRoot":"","sources":["../../../src/auth/__tests__/env.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { EnvAuth } from "../env.js";
|
|
3
|
+
import { AuthError } from "../errors.js";
|
|
4
|
+
describe("EnvAuth", () => {
|
|
5
|
+
const originalEnv = { ...process.env };
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
process.env = { ...originalEnv };
|
|
8
|
+
});
|
|
9
|
+
it("throws AuthError when CLAUDE_AI_COOKIE is not set", () => {
|
|
10
|
+
delete process.env.CLAUDE_AI_COOKIE;
|
|
11
|
+
expect(() => new EnvAuth()).toThrow(AuthError);
|
|
12
|
+
});
|
|
13
|
+
it("returns headers with cookie and default user-agent", async () => {
|
|
14
|
+
process.env.CLAUDE_AI_COOKIE = "sessionKey=abc123";
|
|
15
|
+
const auth = new EnvAuth();
|
|
16
|
+
const headers = await auth.getHeaders();
|
|
17
|
+
expect(headers["Cookie"]).toBe("sessionKey=abc123");
|
|
18
|
+
expect(headers["User-Agent"]).toBeDefined();
|
|
19
|
+
expect(headers["User-Agent"].length).toBeGreaterThan(0);
|
|
20
|
+
});
|
|
21
|
+
it("uses custom user-agent from env when set", async () => {
|
|
22
|
+
process.env.CLAUDE_AI_COOKIE = "sessionKey=abc123";
|
|
23
|
+
process.env.CLAUDE_AI_USER_AGENT =
|
|
24
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/130.0";
|
|
25
|
+
const auth = new EnvAuth();
|
|
26
|
+
const headers = await auth.getHeaders();
|
|
27
|
+
expect(headers["User-Agent"]).toBe("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/130.0");
|
|
28
|
+
});
|
|
29
|
+
it("clears CLAUDE_AI_COOKIE from process.env after reading", () => {
|
|
30
|
+
process.env.CLAUDE_AI_COOKIE = "sessionKey=abc123";
|
|
31
|
+
new EnvAuth();
|
|
32
|
+
expect(process.env.CLAUDE_AI_COOKIE).toBeUndefined();
|
|
33
|
+
});
|
|
34
|
+
it("fetches organization ID from API", async () => {
|
|
35
|
+
process.env.CLAUDE_AI_COOKIE = "sessionKey=abc123";
|
|
36
|
+
const auth = new EnvAuth();
|
|
37
|
+
// getOrganizationId makes a real API call -- tested in integration tests
|
|
38
|
+
// Here we just verify the method exists and is async
|
|
39
|
+
expect(auth.getOrganizationId).toBeDefined();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=env.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.test.js","sourceRoot":"","sources":["../../../src/auth/__tests__/env.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,MAAM,WAAW,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACpC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,mBAAmB,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,mBAAmB,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,oBAAoB;YAC9B,iEAAiE,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAChC,iEAAiE,CAClE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,mBAAmB,CAAC;QACnD,IAAI,OAAO,EAAE,CAAC;QACd,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,aAAa,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,mBAAmB,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,yEAAyE;QACzE,qDAAqD;QACrD,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firefox.test.d.ts","sourceRoot":"","sources":["../../../src/auth/__tests__/firefox.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
2
|
+
import { AuthError } from "../errors.js";
|
|
3
|
+
// Mock node:fs before importing the module under test
|
|
4
|
+
vi.mock("node:fs", () => ({
|
|
5
|
+
existsSync: vi.fn(),
|
|
6
|
+
readFileSync: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
// Mock better-sqlite3
|
|
9
|
+
const mockGet = vi.fn();
|
|
10
|
+
const mockPrepare = vi.fn(() => ({ get: mockGet }));
|
|
11
|
+
const mockClose = vi.fn();
|
|
12
|
+
vi.mock("better-sqlite3", () => {
|
|
13
|
+
return {
|
|
14
|
+
default: vi.fn(() => ({
|
|
15
|
+
prepare: mockPrepare,
|
|
16
|
+
close: mockClose,
|
|
17
|
+
})),
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
// Import after mocks are set up
|
|
21
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
22
|
+
import Database from "better-sqlite3";
|
|
23
|
+
import { FirefoxProfileAuth } from "../firefox.js";
|
|
24
|
+
const mockedExistsSync = vi.mocked(existsSync);
|
|
25
|
+
const mockedReadFileSync = vi.mocked(readFileSync);
|
|
26
|
+
const MockedDatabase = vi.mocked(Database);
|
|
27
|
+
const PROFILES_INI = `[General]
|
|
28
|
+
StartWithLastProfile=1
|
|
29
|
+
|
|
30
|
+
[Profile0]
|
|
31
|
+
Name=default-release
|
|
32
|
+
IsRelative=1
|
|
33
|
+
Path=abcd1234.default-release
|
|
34
|
+
Default=1
|
|
35
|
+
`;
|
|
36
|
+
const PROFILES_INI_NO_DEFAULT = `[General]
|
|
37
|
+
StartWithLastProfile=1
|
|
38
|
+
|
|
39
|
+
[Profile0]
|
|
40
|
+
Name=default
|
|
41
|
+
IsRelative=1
|
|
42
|
+
Path=wxyz5678.default
|
|
43
|
+
`;
|
|
44
|
+
const PROFILES_INI_ABSOLUTE = `[General]
|
|
45
|
+
StartWithLastProfile=1
|
|
46
|
+
|
|
47
|
+
[Profile0]
|
|
48
|
+
Name=custom
|
|
49
|
+
IsRelative=0
|
|
50
|
+
Path=/opt/firefox-profiles/custom
|
|
51
|
+
Default=1
|
|
52
|
+
`;
|
|
53
|
+
describe("FirefoxProfileAuth", () => {
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
vi.clearAllMocks();
|
|
56
|
+
});
|
|
57
|
+
describe("profile path discovery", () => {
|
|
58
|
+
it("throws AuthError when no Firefox installation is found", () => {
|
|
59
|
+
mockedExistsSync.mockReturnValue(false);
|
|
60
|
+
expect(() => new FirefoxProfileAuth()).toThrow(AuthError);
|
|
61
|
+
expect(() => new FirefoxProfileAuth()).toThrow(/Could not find a Firefox installation/);
|
|
62
|
+
});
|
|
63
|
+
it("uses explicitly provided profilePath without discovery", () => {
|
|
64
|
+
// The profilePath itself must exist (cookies.sqlite check)
|
|
65
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
66
|
+
const path = String(p);
|
|
67
|
+
return path.endsWith("cookies.sqlite");
|
|
68
|
+
});
|
|
69
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
70
|
+
const auth = new FirefoxProfileAuth({
|
|
71
|
+
profilePath: "/custom/firefox/profile",
|
|
72
|
+
});
|
|
73
|
+
expect(auth).toBeDefined();
|
|
74
|
+
// Should NOT have tried to read profiles.ini
|
|
75
|
+
expect(mockedReadFileSync).not.toHaveBeenCalled();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe("profiles.ini parsing", () => {
|
|
79
|
+
it("resolves the default profile from profiles.ini", () => {
|
|
80
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
81
|
+
const path = String(p);
|
|
82
|
+
// Firefox root exists
|
|
83
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
84
|
+
return true;
|
|
85
|
+
// profiles.ini exists
|
|
86
|
+
if (path.endsWith("profiles.ini"))
|
|
87
|
+
return true;
|
|
88
|
+
// cookies.sqlite exists
|
|
89
|
+
if (path.endsWith("cookies.sqlite"))
|
|
90
|
+
return true;
|
|
91
|
+
return false;
|
|
92
|
+
});
|
|
93
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
94
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
95
|
+
const auth = new FirefoxProfileAuth();
|
|
96
|
+
expect(auth).toBeDefined();
|
|
97
|
+
// Verify profiles.ini was read
|
|
98
|
+
expect(mockedReadFileSync).toHaveBeenCalledWith(expect.stringContaining("profiles.ini"), "utf-8");
|
|
99
|
+
});
|
|
100
|
+
it("falls back to first profile when no Default=1 is set", () => {
|
|
101
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
102
|
+
const path = String(p);
|
|
103
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
104
|
+
return true;
|
|
105
|
+
if (path.endsWith("profiles.ini"))
|
|
106
|
+
return true;
|
|
107
|
+
if (path.endsWith("cookies.sqlite"))
|
|
108
|
+
return true;
|
|
109
|
+
return false;
|
|
110
|
+
});
|
|
111
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI_NO_DEFAULT);
|
|
112
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
113
|
+
// Should not throw -- falls back to Profile0
|
|
114
|
+
const auth = new FirefoxProfileAuth();
|
|
115
|
+
expect(auth).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
it("handles absolute paths in profiles.ini", () => {
|
|
118
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
119
|
+
const path = String(p);
|
|
120
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
121
|
+
return true;
|
|
122
|
+
if (path.endsWith("profiles.ini"))
|
|
123
|
+
return true;
|
|
124
|
+
if (path.endsWith("cookies.sqlite"))
|
|
125
|
+
return true;
|
|
126
|
+
return false;
|
|
127
|
+
});
|
|
128
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI_ABSOLUTE);
|
|
129
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
130
|
+
const auth = new FirefoxProfileAuth();
|
|
131
|
+
expect(auth).toBeDefined();
|
|
132
|
+
// Database should have been opened with the absolute path
|
|
133
|
+
expect(MockedDatabase).toHaveBeenCalledWith(expect.stringContaining("/opt/firefox-profiles/custom/cookies.sqlite"), expect.any(Object));
|
|
134
|
+
});
|
|
135
|
+
it("throws AuthError when profiles.ini is missing", () => {
|
|
136
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
137
|
+
const path = String(p);
|
|
138
|
+
// Firefox root exists but profiles.ini does not
|
|
139
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
140
|
+
return true;
|
|
141
|
+
return false;
|
|
142
|
+
});
|
|
143
|
+
expect(() => new FirefoxProfileAuth()).toThrow(AuthError);
|
|
144
|
+
expect(() => new FirefoxProfileAuth()).toThrow(/profiles\.ini not found/);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
describe("cookie reading", () => {
|
|
148
|
+
it("throws AuthError when cookies.sqlite is missing", () => {
|
|
149
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
150
|
+
const path = String(p);
|
|
151
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
152
|
+
return true;
|
|
153
|
+
if (path.endsWith("profiles.ini"))
|
|
154
|
+
return true;
|
|
155
|
+
// cookies.sqlite does NOT exist
|
|
156
|
+
if (path.endsWith("cookies.sqlite"))
|
|
157
|
+
return false;
|
|
158
|
+
return false;
|
|
159
|
+
});
|
|
160
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
161
|
+
expect(() => new FirefoxProfileAuth()).toThrow(AuthError);
|
|
162
|
+
expect(() => new FirefoxProfileAuth()).toThrow(/cookies\.sqlite not found/);
|
|
163
|
+
});
|
|
164
|
+
it("throws AuthError when sessionKey cookie is not found", () => {
|
|
165
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
166
|
+
const path = String(p);
|
|
167
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
168
|
+
return true;
|
|
169
|
+
if (path.endsWith("profiles.ini"))
|
|
170
|
+
return true;
|
|
171
|
+
if (path.endsWith("cookies.sqlite"))
|
|
172
|
+
return true;
|
|
173
|
+
return false;
|
|
174
|
+
});
|
|
175
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
176
|
+
mockGet.mockReturnValue(undefined); // No cookie found
|
|
177
|
+
expect(() => new FirefoxProfileAuth()).toThrow(AuthError);
|
|
178
|
+
expect(() => new FirefoxProfileAuth()).toThrow(/No sessionKey cookie found/);
|
|
179
|
+
});
|
|
180
|
+
it("queries only sessionKey cookie for claude.ai", () => {
|
|
181
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
182
|
+
const path = String(p);
|
|
183
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
184
|
+
return true;
|
|
185
|
+
if (path.endsWith("profiles.ini"))
|
|
186
|
+
return true;
|
|
187
|
+
if (path.endsWith("cookies.sqlite"))
|
|
188
|
+
return true;
|
|
189
|
+
return false;
|
|
190
|
+
});
|
|
191
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
192
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
193
|
+
new FirefoxProfileAuth();
|
|
194
|
+
expect(mockPrepare).toHaveBeenCalledWith("SELECT value FROM moz_cookies WHERE host LIKE '%claude.ai%' AND name = 'sessionKey'");
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
describe("database handling", () => {
|
|
198
|
+
it("opens the database with immutable=1 URI flag and readonly mode", () => {
|
|
199
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
200
|
+
const path = String(p);
|
|
201
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
202
|
+
return true;
|
|
203
|
+
if (path.endsWith("profiles.ini"))
|
|
204
|
+
return true;
|
|
205
|
+
if (path.endsWith("cookies.sqlite"))
|
|
206
|
+
return true;
|
|
207
|
+
return false;
|
|
208
|
+
});
|
|
209
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
210
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
211
|
+
new FirefoxProfileAuth();
|
|
212
|
+
expect(MockedDatabase).toHaveBeenCalledWith(expect.stringMatching(/^file:.*cookies\.sqlite\?immutable=1$/), { readonly: true, fileMustExist: true });
|
|
213
|
+
});
|
|
214
|
+
it("closes the database connection after reading", () => {
|
|
215
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
216
|
+
const path = String(p);
|
|
217
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
218
|
+
return true;
|
|
219
|
+
if (path.endsWith("profiles.ini"))
|
|
220
|
+
return true;
|
|
221
|
+
if (path.endsWith("cookies.sqlite"))
|
|
222
|
+
return true;
|
|
223
|
+
return false;
|
|
224
|
+
});
|
|
225
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
226
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
227
|
+
new FirefoxProfileAuth();
|
|
228
|
+
expect(mockClose).toHaveBeenCalledOnce();
|
|
229
|
+
});
|
|
230
|
+
it("closes the database even when the cookie is not found", () => {
|
|
231
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
232
|
+
const path = String(p);
|
|
233
|
+
if (path.endsWith("/firefox") || path.endsWith("/.mozilla/firefox"))
|
|
234
|
+
return true;
|
|
235
|
+
if (path.endsWith("profiles.ini"))
|
|
236
|
+
return true;
|
|
237
|
+
if (path.endsWith("cookies.sqlite"))
|
|
238
|
+
return true;
|
|
239
|
+
return false;
|
|
240
|
+
});
|
|
241
|
+
mockedReadFileSync.mockReturnValue(PROFILES_INI);
|
|
242
|
+
mockGet.mockReturnValue(undefined);
|
|
243
|
+
try {
|
|
244
|
+
new FirefoxProfileAuth();
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// expected
|
|
248
|
+
}
|
|
249
|
+
expect(mockClose).toHaveBeenCalledOnce();
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
describe("getHeaders()", () => {
|
|
253
|
+
it("returns headers with sessionKey cookie and Chrome User-Agent", async () => {
|
|
254
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
255
|
+
const path = String(p);
|
|
256
|
+
if (path.endsWith("cookies.sqlite"))
|
|
257
|
+
return true;
|
|
258
|
+
return false;
|
|
259
|
+
});
|
|
260
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
261
|
+
const auth = new FirefoxProfileAuth({
|
|
262
|
+
profilePath: "/mock/profile",
|
|
263
|
+
});
|
|
264
|
+
const headers = await auth.getHeaders();
|
|
265
|
+
expect(headers["Cookie"]).toBe("sessionKey=sk-test-session-key");
|
|
266
|
+
expect(headers["User-Agent"]).toContain("Chrome/");
|
|
267
|
+
expect(headers["Accept"]).toBe("application/json");
|
|
268
|
+
expect(headers["Content-Type"]).toBe("application/json");
|
|
269
|
+
});
|
|
270
|
+
it("caches the session key and does not re-read the database", async () => {
|
|
271
|
+
mockedExistsSync.mockImplementation((p) => {
|
|
272
|
+
const path = String(p);
|
|
273
|
+
if (path.endsWith("cookies.sqlite"))
|
|
274
|
+
return true;
|
|
275
|
+
return false;
|
|
276
|
+
});
|
|
277
|
+
mockGet.mockReturnValue({ value: "sk-test-session-key" });
|
|
278
|
+
const auth = new FirefoxProfileAuth({
|
|
279
|
+
profilePath: "/mock/profile",
|
|
280
|
+
});
|
|
281
|
+
// Database was opened once during construction
|
|
282
|
+
expect(MockedDatabase).toHaveBeenCalledOnce();
|
|
283
|
+
// Multiple getHeaders calls should NOT re-open the database
|
|
284
|
+
await auth.getHeaders();
|
|
285
|
+
await auth.getHeaders();
|
|
286
|
+
await auth.getHeaders();
|
|
287
|
+
expect(MockedDatabase).toHaveBeenCalledOnce();
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
//# sourceMappingURL=firefox.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firefox.test.js","sourceRoot":"","sources":["../../../src/auth/__tests__/firefox.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuthProvider } from "./types.js";
|
|
2
|
+
export declare class EnvAuth implements AuthProvider {
|
|
3
|
+
private readonly cookie;
|
|
4
|
+
private readonly userAgent;
|
|
5
|
+
private cachedOrgId;
|
|
6
|
+
constructor();
|
|
7
|
+
getHeaders(): Promise<Record<string, string>>;
|
|
8
|
+
getOrganizationId(): Promise<string>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,qBAAa,OAAQ,YAAW,YAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,WAAW,CAAuB;;IAkBpC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAS7C,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;CAwB3C"}
|
package/dist/auth/env.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AuthError } from "./errors.js";
|
|
2
|
+
const DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36";
|
|
3
|
+
export class EnvAuth {
|
|
4
|
+
cookie;
|
|
5
|
+
userAgent;
|
|
6
|
+
cachedOrgId = null;
|
|
7
|
+
constructor() {
|
|
8
|
+
const cookie = process.env.CLAUDE_AI_COOKIE;
|
|
9
|
+
if (!cookie) {
|
|
10
|
+
throw new AuthError("CLAUDE_AI_COOKIE environment variable is required. " +
|
|
11
|
+
"Get it from browser DevTools: Application > Cookies > claude.ai > sessionKey");
|
|
12
|
+
}
|
|
13
|
+
this.cookie = cookie;
|
|
14
|
+
this.userAgent = process.env.CLAUDE_AI_USER_AGENT ?? DEFAULT_USER_AGENT;
|
|
15
|
+
// Security: clear the cookie from process.env to minimize exposure
|
|
16
|
+
// via /proc/<pid>/environ and docker inspect
|
|
17
|
+
delete process.env.CLAUDE_AI_COOKIE;
|
|
18
|
+
}
|
|
19
|
+
async getHeaders() {
|
|
20
|
+
return {
|
|
21
|
+
Cookie: this.cookie,
|
|
22
|
+
"User-Agent": this.userAgent,
|
|
23
|
+
Accept: "application/json",
|
|
24
|
+
"Content-Type": "application/json",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async getOrganizationId() {
|
|
28
|
+
if (this.cachedOrgId) {
|
|
29
|
+
return this.cachedOrgId;
|
|
30
|
+
}
|
|
31
|
+
const headers = await this.getHeaders();
|
|
32
|
+
const response = await fetch("https://claude.ai/api/organizations", {
|
|
33
|
+
headers,
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
throw new AuthError(`Failed to fetch organizations: ${response.status} ${response.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
const orgs = await response.json();
|
|
39
|
+
if (!Array.isArray(orgs) || orgs.length === 0 || !orgs[0].uuid) {
|
|
40
|
+
throw new AuthError("No organizations found for this session");
|
|
41
|
+
}
|
|
42
|
+
this.cachedOrgId = orgs[0].uuid;
|
|
43
|
+
return this.cachedOrgId;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,kBAAkB,GACtB,uGAAuG,CAAC;AAE1G,MAAM,OAAO,OAAO;IACD,MAAM,CAAS;IACf,SAAS,CAAS;IAC3B,WAAW,GAAkB,IAAI,CAAC;IAE1C;QACE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,SAAS,CACjB,qDAAqD;gBACnD,8EAA8E,CACjF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,kBAAkB,CAAC;QAExE,mEAAmE;QACnE,6CAA6C;QAC7C,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,IAAI,CAAC,SAAS;YAC5B,MAAM,EAAE,kBAAkB;YAC1B,cAAc,EAAE,kBAAkB;SACnC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YAClE,OAAO;SACR,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,SAAS,CACjB,kCAAkC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/D,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAc,CAAC;QAC1C,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AuthProvider } from "./types.js";
|
|
2
|
+
export declare class FirefoxProfileAuth implements AuthProvider {
|
|
3
|
+
private readonly sessionKey;
|
|
4
|
+
private readonly userAgent;
|
|
5
|
+
private cachedOrgId;
|
|
6
|
+
constructor(options?: {
|
|
7
|
+
profilePath?: string;
|
|
8
|
+
});
|
|
9
|
+
getHeaders(): Promise<Record<string, string>>;
|
|
10
|
+
getOrganizationId(): Promise<string>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=firefox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firefox.d.ts","sourceRoot":"","sources":["../../src/auth/firefox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA8L/C,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,WAAW,CAAuB;gBAE9B,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAMxC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAS7C,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;CAwB3C"}
|