jamdesk 1.0.14 → 1.0.16

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.
@@ -10,7 +10,18 @@ vi.mock('../../lib/config.js', () => ({
10
10
  // Mock global fetch
11
11
  const mockFetch = vi.fn();
12
12
  vi.stubGlobal('fetch', mockFetch);
13
- import { isLoggedIn, getValidToken, storeAuth, clearAuth, apiCall, FIREBASE_API_KEY, FUNCTIONS_BASE_URL, _resetTokenCache, } from '../../lib/auth.js';
13
+ import { isLoggedIn, getValidToken, storeAuth, clearAuth, apiCall, FUNCTIONS_BASE_URL, _resetTokenCache, } from '../../lib/auth.js';
14
+ const TEST_API_KEY = 'test-firebase-api-key';
15
+ function authConfig(overrides = {}) {
16
+ return {
17
+ refreshToken: 'tok',
18
+ email: 'a@b.com',
19
+ uid: '1',
20
+ expiresAt: 0,
21
+ firebaseApiKey: TEST_API_KEY,
22
+ ...overrides,
23
+ };
24
+ }
14
25
  describe('auth', () => {
15
26
  beforeEach(() => {
16
27
  vi.clearAllMocks();
@@ -19,13 +30,13 @@ describe('auth', () => {
19
30
  });
20
31
  describe('isLoggedIn', () => {
21
32
  it('returns true when auth config has refreshToken', () => {
22
- expect(isLoggedIn({ auth: { refreshToken: 'tok', email: 'a@b.com', uid: '1', expiresAt: 0 } })).toBe(true);
33
+ expect(isLoggedIn({ auth: authConfig() })).toBe(true);
23
34
  });
24
35
  it('returns false when auth config is missing', () => {
25
36
  expect(isLoggedIn({})).toBe(false);
26
37
  });
27
38
  it('returns false when refreshToken is empty', () => {
28
- expect(isLoggedIn({ auth: { refreshToken: '', email: '', uid: '', expiresAt: 0 } })).toBe(false);
39
+ expect(isLoggedIn({ auth: authConfig({ refreshToken: '' }) })).toBe(false);
29
40
  });
30
41
  });
31
42
  describe('getValidToken', () => {
@@ -33,9 +44,21 @@ describe('auth', () => {
33
44
  mockLoadConfig.mockResolvedValue({});
34
45
  await expect(getValidToken()).rejects.toThrow('Not logged in');
35
46
  });
47
+ it('throws when firebaseApiKey is missing', async () => {
48
+ mockLoadConfig.mockResolvedValue({
49
+ auth: authConfig({ firebaseApiKey: undefined }),
50
+ });
51
+ await expect(getValidToken()).rejects.toThrow('Run `jamdesk login` to re-authenticate');
52
+ });
53
+ it('throws when firebaseApiKey is empty string', async () => {
54
+ mockLoadConfig.mockResolvedValue({
55
+ auth: authConfig({ firebaseApiKey: '' }),
56
+ });
57
+ await expect(getValidToken()).rejects.toThrow('Run `jamdesk login` to re-authenticate');
58
+ });
36
59
  it('refreshes token via Firebase REST API', async () => {
37
60
  mockLoadConfig.mockResolvedValue({
38
- auth: { refreshToken: 'old-refresh', email: 'a@b.com', uid: '1', expiresAt: 0 },
61
+ auth: authConfig({ refreshToken: 'old-refresh' }),
39
62
  });
40
63
  mockFetch.mockResolvedValue({
41
64
  ok: true,
@@ -47,8 +70,8 @@ describe('auth', () => {
47
70
  });
48
71
  const token = await getValidToken();
49
72
  expect(token).toBe('new-id-token');
50
- // Verify fetch was called with correct URL and body
51
- expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('securetoken.googleapis.com/v1/token'), expect.objectContaining({
73
+ // Verify fetch was called with API key from config
74
+ expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining(`key=${TEST_API_KEY}`), expect.objectContaining({
52
75
  method: 'POST',
53
76
  body: expect.stringContaining('refresh_token=old-refresh'),
54
77
  }));
@@ -59,9 +82,26 @@ describe('auth', () => {
59
82
  }),
60
83
  }));
61
84
  });
85
+ it('preserves firebaseApiKey after token refresh', async () => {
86
+ mockLoadConfig.mockResolvedValue({
87
+ auth: authConfig({ refreshToken: 'old-refresh' }),
88
+ });
89
+ mockFetch.mockResolvedValue({
90
+ ok: true,
91
+ json: () => Promise.resolve({
92
+ id_token: 'new-id-token',
93
+ refresh_token: 'new-refresh-token',
94
+ expires_in: '3600',
95
+ }),
96
+ });
97
+ await getValidToken();
98
+ // Verify saved config still has firebaseApiKey
99
+ const savedConfig = mockSaveConfig.mock.calls[0][0];
100
+ expect(savedConfig.auth.firebaseApiKey).toBe(TEST_API_KEY);
101
+ });
62
102
  it('throws on refresh failure', async () => {
63
103
  mockLoadConfig.mockResolvedValue({
64
- auth: { refreshToken: 'bad-token', email: 'a@b.com', uid: '1', expiresAt: 0 },
104
+ auth: authConfig({ refreshToken: 'bad-token' }),
65
105
  });
66
106
  mockFetch.mockResolvedValue({
67
107
  ok: false,
@@ -74,7 +114,7 @@ describe('auth', () => {
74
114
  });
75
115
  it('clears auth on permanent token errors', async () => {
76
116
  mockLoadConfig.mockResolvedValue({
77
- auth: { refreshToken: 'expired', email: 'a@b.com', uid: '1', expiresAt: 0 },
117
+ auth: authConfig({ refreshToken: 'expired' }),
78
118
  });
79
119
  mockFetch.mockResolvedValue({
80
120
  ok: false,
@@ -91,7 +131,7 @@ describe('auth', () => {
91
131
  describe('storeAuth', () => {
92
132
  it('saves auth config', async () => {
93
133
  mockLoadConfig.mockResolvedValue({ verbose: true });
94
- const auth = { refreshToken: 'tok', email: 'a@b.com', uid: '1', expiresAt: 100 };
134
+ const auth = authConfig({ expiresAt: 100 });
95
135
  await storeAuth(auth);
96
136
  expect(mockSaveConfig).toHaveBeenCalledWith({
97
137
  verbose: true,
@@ -103,7 +143,7 @@ describe('auth', () => {
103
143
  it('removes auth from config', async () => {
104
144
  mockLoadConfig.mockResolvedValue({
105
145
  verbose: true,
106
- auth: { refreshToken: 'tok', email: 'a@b.com', uid: '1', expiresAt: 100 },
146
+ auth: authConfig({ expiresAt: 100 }),
107
147
  });
108
148
  await clearAuth();
109
149
  expect(mockSaveConfig).toHaveBeenCalledWith({ verbose: true });
@@ -111,10 +151,7 @@ describe('auth', () => {
111
151
  });
112
152
  describe('apiCall', () => {
113
153
  it('makes authenticated GET request', async () => {
114
- // Mock getValidToken's flow
115
- mockLoadConfig.mockResolvedValue({
116
- auth: { refreshToken: 'tok', email: 'a@b.com', uid: '1', expiresAt: 0 },
117
- });
154
+ mockLoadConfig.mockResolvedValue({ auth: authConfig() });
118
155
  // First fetch: token refresh
119
156
  mockFetch.mockResolvedValueOnce({
120
157
  ok: true,
@@ -138,9 +175,7 @@ describe('auth', () => {
138
175
  expect(apiCallArgs[1].headers.Authorization).toBe('Bearer test-id-token');
139
176
  });
140
177
  it('makes authenticated POST request with body', async () => {
141
- mockLoadConfig.mockResolvedValue({
142
- auth: { refreshToken: 'tok', email: 'a@b.com', uid: '1', expiresAt: 0 },
143
- });
178
+ mockLoadConfig.mockResolvedValue({ auth: authConfig() });
144
179
  mockFetch
145
180
  .mockResolvedValueOnce({
146
181
  ok: true,
@@ -157,10 +192,6 @@ describe('auth', () => {
157
192
  });
158
193
  });
159
194
  describe('constants', () => {
160
- it('exports Firebase API key', () => {
161
- expect(FIREBASE_API_KEY).toBeTruthy();
162
- expect(FIREBASE_API_KEY).toMatch(/^AIza/);
163
- });
164
195
  it('exports functions base URL', () => {
165
196
  expect(FUNCTIONS_BASE_URL).toContain('cloudfunctions.net');
166
197
  });
@@ -1 +1 @@
1
- {"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/auth.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/auth.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE9D,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3D,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;IACvB,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;CACxB,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACpC,UAAU,EAAE,cAAc;IAC1B,UAAU,EAAE,cAAc;CAC3B,CAAC,CAAC,CAAC;AAEJ,oBAAoB;AACpB,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAC1B,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAElC,OAAO,EACL,UAAU,EACV,aAAa,EACb,SAAS,EACT,SAAS,EACT,OAAO,EACP,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAE7C,SAAS,UAAU,CAAC,SAAS,GAAG,EAAE;IAChC,OAAO;QACL,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,GAAG;QACR,SAAS,EAAE,CAAC;QACZ,cAAc,EAAE,YAAY;QAC5B,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,cAAc,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC5C,gBAAgB,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;YACzC,cAAc,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;YACrC,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,IAAI,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;aAChD,CAAC,CAAC;YACH,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,IAAI,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;aACzC,CAAC,CAAC;YACH,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,IAAI,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;aAClD,CAAC,CAAC;YAEH,SAAS,CAAC,iBAAiB,CAAC;gBAC1B,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC1B,QAAQ,EAAE,cAAc;oBACxB,aAAa,EAAE,mBAAmB;oBAClC,UAAU,EAAE,MAAM;iBACnB,CAAC;aACH,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,MAAM,aAAa,EAAE,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAEnC,mDAAmD;YACnD,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CACpC,MAAM,CAAC,gBAAgB,CAAC,OAAO,YAAY,EAAE,CAAC,EAC9C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,CAAC;aAC3D,CAAC,CACH,CAAC;YAEF,iDAAiD;YACjD,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CACzC,MAAM,CAAC,gBAAgB,CAAC;gBACtB,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC5B,YAAY,EAAE,mBAAmB;iBAClC,CAAC;aACH,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,IAAI,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;aAClD,CAAC,CAAC;YAEH,SAAS,CAAC,iBAAiB,CAAC;gBAC1B,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC1B,QAAQ,EAAE,cAAc;oBACxB,aAAa,EAAE,mBAAmB;oBAClC,UAAU,EAAE,MAAM;iBACnB,CAAC;aACH,CAAC,CAAC;YAEH,MAAM,aAAa,EAAE,CAAC;YAEtB,+CAA+C;YAC/C,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;YACzC,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,IAAI,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;aAChD,CAAC,CAAC;YAEH,SAAS,CAAC,iBAAiB,CAAC;gBAC1B,EAAE,EAAE,KAAK;gBACT,UAAU,EAAE,aAAa;gBACzB,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC1B,KAAK,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE;iBAC5C,CAAC;aACH,CAAC,CAAC;YAEH,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,IAAI,EAAE,UAAU,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;aAC9C,CAAC,CAAC;YAEH,SAAS,CAAC,iBAAiB,CAAC;gBAC1B,EAAE,EAAE,KAAK;gBACT,UAAU,EAAE,aAAa;gBACzB,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC1B,KAAK,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE;iBACpC,CAAC;aACH,CAAC,CAAC;YAEH,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAEhD,2BAA2B;YAC3B,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CACzC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CACzD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;YACjC,cAAc,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAEpD,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5C,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;YAEtB,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC;gBAC1C,OAAO,EAAE,IAAI;gBACb,IAAI;aACL,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,cAAc,CAAC,iBAAiB,CAAC;gBAC/B,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;aACrC,CAAC,CAAC;YAEH,MAAM,SAAS,EAAE,CAAC;YAElB,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,cAAc,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;YAEzD,6BAA6B;YAC7B,SAAS,CAAC,qBAAqB,CAAC;gBAC9B,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;oBAC1B,QAAQ,EAAE,eAAe;oBACzB,aAAa,EAAE,aAAa;oBAC5B,UAAU,EAAE,MAAM;iBACnB,CAAC;aACH,CAAC,CAAC;YAEH,yBAAyB;YACzB,SAAS,CAAC,qBAAqB,CAAC;gBAC9B,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;aAC9C,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;YACnD,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE/B,oCAAoC;YACpC,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,kBAAkB,mBAAmB,CAAC,CAAC;YACtE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,cAAc,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;YAEzD,SAAS;iBACN,qBAAqB,CAAC;gBACrB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;aACzF,CAAC;iBACD,qBAAqB,CAAC;gBACrB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;aAC/C,CAAC,CAAC;YAEL,MAAM,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;YAE/D,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,CAAC,kBAAkB,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -18,6 +18,26 @@ const { mockOutput } = vi.hoisted(() => ({
18
18
  vi.mock('../../lib/output.js', () => ({ output: mockOutput }));
19
19
  vi.mock('open', () => ({ default: vi.fn() }));
20
20
  import { login } from '../../commands/login.js';
21
+ function sendOptions(port) {
22
+ return new Promise((resolve, reject) => {
23
+ const req = http.request({
24
+ hostname: '127.0.0.1',
25
+ port,
26
+ path: '/callback',
27
+ method: 'OPTIONS',
28
+ headers: {
29
+ Origin: 'https://dashboard.jamdesk.com',
30
+ 'Access-Control-Request-Method': 'POST',
31
+ 'Access-Control-Request-Private-Network': 'true',
32
+ },
33
+ }, (res) => {
34
+ res.resume();
35
+ res.on('end', () => resolve({ statusCode: res.statusCode || 0, headers: res.headers }));
36
+ });
37
+ req.on('error', reject);
38
+ req.end();
39
+ });
40
+ }
21
41
  function sendCallback(port, body) {
22
42
  return new Promise((resolve, reject) => {
23
43
  const data = JSON.stringify(body);
@@ -26,7 +46,11 @@ function sendCallback(port, body) {
26
46
  port,
27
47
  path: '/callback',
28
48
  method: 'POST',
29
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
49
+ headers: {
50
+ 'Content-Type': 'application/json',
51
+ 'Content-Length': Buffer.byteLength(data),
52
+ Origin: 'https://dashboard.jamdesk.com',
53
+ },
30
54
  }, (res) => {
31
55
  res.resume();
32
56
  res.on('end', () => resolve({ statusCode: res.statusCode || 0 }));
@@ -36,22 +60,32 @@ function sendCallback(port, body) {
36
60
  req.end();
37
61
  });
38
62
  }
63
+ /** Start login, extract port and state from the logged URL. */
64
+ async function startLoginAndGetParams() {
65
+ vi.spyOn(console, 'log').mockImplementation(() => { });
66
+ const loginPromise = login();
67
+ await new Promise((r) => setTimeout(r, 200));
68
+ const consoleSpy = vi.mocked(console.log);
69
+ const urlLog = consoleSpy.mock.calls.find((c) => typeof c[0] === 'string' && c[0].includes('cli-auth'));
70
+ expect(urlLog).toBeTruthy();
71
+ const url = new URL(urlLog[0].trim());
72
+ const port = parseInt(url.searchParams.get('port'), 10);
73
+ const state = url.searchParams.get('state');
74
+ return { loginPromise, port, state };
75
+ }
76
+ /** Send a valid callback to shut down the login server. */
77
+ function shutdownServer(port, state) {
78
+ return sendCallback(port, {
79
+ token: 't', refreshToken: 't', email: 'e@e.com', uid: 'u', state, firebaseApiKey: 'k',
80
+ });
81
+ }
39
82
  describe('login', () => {
40
- let consoleSpy;
41
83
  beforeEach(() => {
42
84
  vi.clearAllMocks();
43
85
  mockStoreAuth.mockResolvedValue(undefined);
44
- consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
45
86
  });
46
- it('stores auth on valid callback with correct state', async () => {
47
- const loginPromise = login();
48
- await new Promise((r) => setTimeout(r, 200));
49
- // Extract port and state from logged URL
50
- const urlLog = consoleSpy.mock.calls.find((c) => typeof c[0] === 'string' && c[0].includes('cli-auth'));
51
- expect(urlLog).toBeTruthy();
52
- const url = new URL(urlLog[0].trim());
53
- const port = parseInt(url.searchParams.get('port'), 10);
54
- const state = url.searchParams.get('state');
87
+ it('stores auth with firebaseApiKey on valid callback', async () => {
88
+ const { loginPromise, port, state } = await startLoginAndGetParams();
55
89
  expect(port).toBeGreaterThanOrEqual(1024);
56
90
  expect(state).toHaveLength(64); // 32 bytes hex
57
91
  const response = await sendCallback(port, {
@@ -60,6 +94,7 @@ describe('login', () => {
60
94
  email: 'user@test.com',
61
95
  uid: 'uid-123',
62
96
  state,
97
+ firebaseApiKey: 'AIzaTest123',
63
98
  });
64
99
  expect(response.statusCode).toBe(200);
65
100
  await loginPromise;
@@ -67,33 +102,66 @@ describe('login', () => {
67
102
  refreshToken: 'test-refresh',
68
103
  email: 'user@test.com',
69
104
  uid: 'uid-123',
105
+ firebaseApiKey: 'AIzaTest123',
70
106
  }));
71
107
  expect(mockOutput.success).toHaveBeenCalledWith('Logged in as user@test.com');
72
108
  }, 10000);
73
109
  it('rejects callback with wrong state', async () => {
74
- const loginPromise = login();
75
- await new Promise((r) => setTimeout(r, 200));
76
- const urlLog = consoleSpy.mock.calls.find((c) => typeof c[0] === 'string' && c[0].includes('cli-auth'));
77
- const url = new URL(urlLog[0].trim());
78
- const port = parseInt(url.searchParams.get('port'), 10);
110
+ const { loginPromise, port, state } = await startLoginAndGetParams();
79
111
  const response = await sendCallback(port, {
80
112
  token: 'test',
81
113
  refreshToken: 'test',
82
114
  email: 'test@test.com',
83
115
  uid: 'uid',
84
116
  state: 'wrong-state-value',
117
+ firebaseApiKey: 'key',
85
118
  });
86
119
  expect(response.statusCode).toBe(403);
87
120
  expect(mockStoreAuth).not.toHaveBeenCalled();
88
- // Send valid state to clean up
89
- const state = url.searchParams.get('state');
90
- await sendCallback(port, {
91
- token: 'test',
92
- refreshToken: 'test',
93
- email: 'test@test.com',
94
- uid: 'uid',
121
+ await shutdownServer(port, state);
122
+ await loginPromise;
123
+ }, 10000);
124
+ it('responds to CORS preflight with PNA header', async () => {
125
+ const { loginPromise, port, state } = await startLoginAndGetParams();
126
+ const res = await sendOptions(port);
127
+ expect(res.statusCode).toBe(204);
128
+ expect(res.headers['access-control-allow-private-network']).toBe('true');
129
+ expect(res.headers['access-control-allow-origin']).toBe('https://dashboard.jamdesk.com');
130
+ await shutdownServer(port, state);
131
+ await loginPromise;
132
+ }, 10000);
133
+ it('rejects POST without Origin header', async () => {
134
+ const { loginPromise, port, state } = await startLoginAndGetParams();
135
+ // POST without Origin (non-browser client) should be rejected
136
+ const res = await new Promise((resolve, reject) => {
137
+ const data = JSON.stringify({
138
+ refreshToken: 't', email: 'e@e.com', uid: 'u', state, firebaseApiKey: 'k',
139
+ });
140
+ const req = http.request({
141
+ hostname: '127.0.0.1', port, path: '/callback', method: 'POST',
142
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
143
+ }, (r) => { r.resume(); r.on('end', () => resolve({ statusCode: r.statusCode || 0 })); });
144
+ req.on('error', reject);
145
+ req.write(data);
146
+ req.end();
147
+ });
148
+ expect(res.statusCode).toBe(403);
149
+ await shutdownServer(port, state);
150
+ await loginPromise;
151
+ }, 10000);
152
+ it('rejects callback missing firebaseApiKey', async () => {
153
+ const { loginPromise, port, state } = await startLoginAndGetParams();
154
+ const response = await sendCallback(port, {
155
+ token: 'test-id-token',
156
+ refreshToken: 'test-refresh',
157
+ email: 'user@test.com',
158
+ uid: 'uid-123',
95
159
  state,
160
+ // no firebaseApiKey
96
161
  });
162
+ expect(response.statusCode).toBe(400);
163
+ expect(mockStoreAuth).not.toHaveBeenCalled();
164
+ await shutdownServer(port, state);
97
165
  await loginPromise;
98
166
  }, 10000);
99
167
  });
@@ -1 +1 @@
1
- {"version":3,"file":"login.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/login.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/login.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1C,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;CACvB,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IAClC,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACvC,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE;QACb,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QAChB,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;QACd,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE;QACb,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE;KACd;CACF,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAC/D,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEhD,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB;YACE,QAAQ,EAAE,WAAW;YACrB,IAAI;YACJ,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE;gBACP,MAAM,EAAE,+BAA+B;gBACvC,+BAA+B,EAAE,MAAM;gBACvC,wCAAwC,EAAE,MAAM;aACjD;SACF,EACD,CAAC,GAAG,EAAE,EAAE;YACN,GAAG,CAAC,MAAM,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1F,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,IAA4B;IAC9D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB;YACE,QAAQ,EAAE,WAAW;YACrB,IAAI;YACJ,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;gBACzC,MAAM,EAAE,+BAA+B;aACxC;SACF,EACD,CAAC,GAAG,EAAE,EAAE;YACN,GAAG,CAAC,MAAM,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+DAA+D;AAC/D,KAAK,UAAU,sBAAsB;IACnC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;IAC7B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAE7C,MAAM,UAAU,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CACvC,CAAC,CAAY,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CACxE,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;IAE5B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAE,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;IAE7C,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC;AAED,2DAA2D;AAC3D,SAAS,cAAc,CAAC,IAAY,EAAE,KAAa;IACjD,OAAO,YAAY,CAAC,IAAI,EAAE;QACxB,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG;KACtF,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,aAAa,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAErE,MAAM,CAAC,IAAI,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe;QAE/C,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE;YACxC,KAAK,EAAE,eAAe;YACtB,YAAY,EAAE,cAAc;YAC5B,KAAK,EAAE,eAAe;YACtB,GAAG,EAAE,SAAS;YACd,KAAK;YACL,cAAc,EAAE,aAAa;SAC9B,CAAC,CAAC;QAEH,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,YAAY,CAAC;QAEnB,MAAM,CAAC,aAAa,CAAC,CAAC,oBAAoB,CACxC,MAAM,CAAC,gBAAgB,CAAC;YACtB,YAAY,EAAE,cAAc;YAC5B,KAAK,EAAE,eAAe;YACtB,GAAG,EAAE,SAAS;YACd,cAAc,EAAE,aAAa;SAC9B,CAAC,CACH,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,4BAA4B,CAAC,CAAC;IAChF,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAErE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE;YACxC,KAAK,EAAE,MAAM;YACb,YAAY,EAAE,MAAM;YACpB,KAAK,EAAE,eAAe;YACtB,GAAG,EAAE,KAAK;YACV,KAAK,EAAE,mBAAmB;YAC1B,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC;QAEH,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAE7C,MAAM,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,MAAM,YAAY,CAAC;IACrB,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAErE,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAEzF,MAAM,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,MAAM,YAAY,CAAC;IACrB,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAErE,8DAA8D;QAC9D,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC1B,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG;aAC1E,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB;gBACE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM;gBAC9D,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;aAC3F,EACD,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CACtF,CAAC;YACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACxB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChB,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,MAAM,YAAY,CAAC;IACrB,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAErE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE;YACxC,KAAK,EAAE,eAAe;YACtB,YAAY,EAAE,cAAc;YAC5B,KAAK,EAAE,eAAe;YACtB,GAAG,EAAE,SAAS;YACd,KAAK;YACL,oBAAoB;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAE7C,MAAM,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,MAAM,YAAY,CAAC;IACrB,CAAC,EAAE,KAAK,CAAC,CAAC;AACZ,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAyI3C"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAiJ3C"}
@@ -26,8 +26,15 @@ export async function login() {
26
26
  }
27
27
  }, TIMEOUT_MS);
28
28
  const server = http.createServer(async (req, res) => {
29
- // Validate Origin header (defense-in-depth alongside state parameter)
29
+ // Validate Origin header (defense-in-depth alongside state parameter).
30
+ // OPTIONS preflight may omit Origin in non-browser clients, so only
31
+ // require it on POST where browsers always send it cross-origin.
30
32
  const origin = req.headers.origin;
33
+ if (req.method === 'POST' && origin !== ALLOWED_ORIGIN) {
34
+ res.writeHead(403);
35
+ res.end();
36
+ return;
37
+ }
31
38
  if (origin && origin !== ALLOWED_ORIGIN) {
32
39
  res.writeHead(403);
33
40
  res.end();
@@ -37,6 +44,7 @@ export async function login() {
37
44
  res.setHeader('Access-Control-Allow-Origin', ALLOWED_ORIGIN);
38
45
  res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
39
46
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
47
+ res.setHeader('Access-Control-Allow-Private-Network', 'true');
40
48
  if (req.method === 'OPTIONS') {
41
49
  res.writeHead(204);
42
50
  res.end();
@@ -62,24 +70,24 @@ export async function login() {
62
70
  }
63
71
  try {
64
72
  const body = JSON.parse(Buffer.concat(chunks).toString());
65
- const { refreshToken, email, uid, state: receivedState } = body;
73
+ const { refreshToken, email, uid, state: receivedState, firebaseApiKey } = body;
66
74
  // Verify state matches (anti-CSRF)
67
75
  if (receivedState !== state) {
68
76
  res.writeHead(403, { 'Content-Type': 'application/json' });
69
77
  res.end(JSON.stringify({ error: 'Invalid state parameter' }));
70
78
  return;
71
79
  }
72
- if (!refreshToken || !email || !uid) {
80
+ if (!refreshToken || !email || !uid || !firebaseApiKey) {
73
81
  res.writeHead(400, { 'Content-Type': 'application/json' });
74
82
  res.end(JSON.stringify({ error: 'Missing required fields' }));
75
83
  return;
76
84
  }
77
- // Store auth
78
85
  await storeAuth({
79
86
  refreshToken,
80
87
  email,
81
88
  uid,
82
89
  expiresAt: Date.now() + 3600 * 1000, // 1 hour
90
+ firebaseApiKey,
83
91
  });
84
92
  res.writeHead(200, { 'Content-Type': 'application/json' });
85
93
  res.end(JSON.stringify({ success: true }));
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,6 @@
5
5
  * Tokens are refreshed automatically via the Firebase REST API.
6
6
  */
7
7
  import { type AuthConfig } from './config.js';
8
- declare const FIREBASE_API_KEY = "AIzaSyC415KAqbWNXXyr80nuNIDf6hM1Sv3rOMU";
9
8
  declare const FUNCTIONS_BASE_URL = "https://us-central1-jamdesk-prod.cloudfunctions.net";
10
9
  export declare function isLoggedIn(config: {
11
10
  auth?: AuthConfig;
@@ -28,7 +27,7 @@ export declare function apiCall(endpoint: string, options?: {
28
27
  body?: Record<string, unknown>;
29
28
  baseUrl?: string;
30
29
  }): Promise<Response>;
31
- export { FIREBASE_API_KEY, FUNCTIONS_BASE_URL };
30
+ export { FUNCTIONS_BASE_URL };
32
31
  /** Reset in-memory token cache (testing only). */
33
32
  export declare function _resetTokenCache(): void;
34
33
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAGtE,QAAA,MAAM,gBAAgB,4CAA4C,CAAC;AACnE,QAAA,MAAM,kBAAkB,wDAAwD,CAAC;AAQjF,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAsDrD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/D;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAK/C;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GACL,OAAO,CAAC,QAAQ,CAAC,CAmBnB;AAED,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;AAEhD,kDAAkD;AAClD,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtE,QAAA,MAAM,kBAAkB,wDAAwD,CAAC;AAQjF,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CA0DrD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/D;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAK/C;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GACL,OAAO,CAAC,QAAQ,CAAC,CAmBnB;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,kDAAkD;AAClD,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
package/dist/lib/auth.js CHANGED
@@ -5,8 +5,6 @@
5
5
  * Tokens are refreshed automatically via the Firebase REST API.
6
6
  */
7
7
  import { loadConfig, saveConfig } from './config.js';
8
- // Public Firebase config — same values as the dashboard
9
- const FIREBASE_API_KEY = 'AIzaSyC415KAqbWNXXyr80nuNIDf6hM1Sv3rOMU';
10
8
  const FUNCTIONS_BASE_URL = 'https://us-central1-jamdesk-prod.cloudfunctions.net';
11
9
  // Token refresh buffer: refresh 5 minutes before expiry
12
10
  const REFRESH_BUFFER_MS = 5 * 60 * 1000;
@@ -29,8 +27,11 @@ export async function getValidToken() {
29
27
  if (!config.auth?.refreshToken) {
30
28
  throw new Error('Not logged in. Run `jamdesk login` first.');
31
29
  }
30
+ if (!config.auth.firebaseApiKey) {
31
+ throw new Error('CLI config updated. Run `jamdesk login` to re-authenticate (one-time setup).');
32
+ }
32
33
  // Refresh the token
33
- const response = await fetch(`https://securetoken.googleapis.com/v1/token?key=${FIREBASE_API_KEY}`, {
34
+ const response = await fetch(`https://securetoken.googleapis.com/v1/token?key=${config.auth.firebaseApiKey}`, {
34
35
  method: 'POST',
35
36
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
36
37
  body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(config.auth.refreshToken)}`,
@@ -97,7 +98,7 @@ export async function apiCall(endpoint, options = {}) {
97
98
  throw new Error(`API request failed: ${message}`);
98
99
  }
99
100
  }
100
- export { FIREBASE_API_KEY, FUNCTIONS_BASE_URL };
101
+ export { FUNCTIONS_BASE_URL };
101
102
  /** Reset in-memory token cache (testing only). */
102
103
  export function _resetTokenCache() {
103
104
  cachedIdToken = null;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ export interface AuthConfig {
3
3
  email: string;
4
4
  uid: string;
5
5
  expiresAt: number;
6
+ firebaseApiKey?: string;
6
7
  }
7
8
  export interface JamdeskConfig {
8
9
  defaultPort?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,eAAO,MAAM,WAAW,QAAqC,CAAC;AAE9D,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAWzD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,eAAO,MAAM,WAAW,QAAqC,CAAC;AAE9D,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAWzD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAgB1B,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAqB;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,yEAAyE;IACzE,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAiB1B,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAqB;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,yEAAyE;IACzE,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
5
5
  "keywords": [
6
6
  "jamdesk",
@@ -3,6 +3,31 @@ import { NextRequest } from 'next/server';
3
3
 
4
4
  export const runtime = 'edge';
5
5
 
6
+ const ACCENT_COLOR = '#8B5CF6';
7
+ const MAX_DESCRIPTION_LENGTH = 120;
8
+ const LONG_TITLE_THRESHOLD = 40;
9
+ const FONT_STACK =
10
+ 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
11
+ const ACCENT_GRADIENT = `linear-gradient(90deg, ${ACCENT_COLOR} 0%, #C4B5FD 50%, #A78BFA 100%)`;
12
+
13
+ function getThemeColors(isDark: boolean) {
14
+ return {
15
+ text: isDark ? '#ffffff' : '#1a1a2e',
16
+ muted: isDark ? '#a0a0b0' : '#666680',
17
+ background: isDark
18
+ ? 'linear-gradient(135deg, #1a1a3e 0%, #0f0f23 100%)'
19
+ : 'linear-gradient(135deg, #f8f8fc 0%, #ffffff 100%)',
20
+ badgeBackground: isDark
21
+ ? 'rgba(139, 92, 246, 0.15)'
22
+ : 'rgba(139, 92, 246, 0.1)',
23
+ };
24
+ }
25
+
26
+ function truncateText(text: string, maxLength: number): string {
27
+ if (text.length <= maxLength) return text;
28
+ return text.substring(0, maxLength) + '...';
29
+ }
30
+
6
31
  /**
7
32
  * OG Image Generator
8
33
  *
@@ -26,18 +51,27 @@ export async function GET(request: NextRequest) {
26
51
  const description = searchParams.get('description') || '';
27
52
  const section = searchParams.get('section') || '';
28
53
  const siteName = searchParams.get('siteName') || 'Documentation';
29
- const logo = searchParams.get('logo') || '';
30
- const theme = searchParams.get('theme') || 'dark';
54
+ const logoUrl = searchParams.get('logo') || '';
55
+ const isDark = (searchParams.get('theme') || 'dark') === 'dark';
31
56
 
32
- const isDark = theme === 'dark';
57
+ // Fetch logo and convert to base64 data URI for Satori compatibility
58
+ // (Satori doesn't support webp and can fail on remote URLs)
59
+ let logo = '';
60
+ if (logoUrl) {
61
+ try {
62
+ const res = await fetch(logoUrl);
63
+ if (res.ok) {
64
+ const contentType = res.headers.get('content-type') || 'image/png';
65
+ const buf = await res.arrayBuffer();
66
+ logo = `data:${contentType};base64,${Buffer.from(buf).toString('base64')}`;
67
+ }
68
+ } catch {
69
+ // Skip logo on fetch failure
70
+ }
71
+ }
33
72
 
34
- // Colors based on theme
35
- const bgColor = isDark ? '#0f0f23' : '#ffffff';
36
- const textColor = isDark ? '#ffffff' : '#1a1a2e';
37
- const mutedColor = isDark ? '#a0a0b0' : '#666680';
38
- const accentColor = '#8B5CF6'; // Jamdesk purple
39
- const gradientStart = isDark ? '#1a1a3e' : '#f8f8fc';
40
- const gradientEnd = isDark ? '#0f0f23' : '#ffffff';
73
+ const colors = getThemeColors(isDark);
74
+ const titleFontSize = title.length > LONG_TITLE_THRESHOLD ? '52px' : '64px';
41
75
 
42
76
  return new ImageResponse(
43
77
  (
@@ -48,15 +82,16 @@ export async function GET(request: NextRequest) {
48
82
  display: 'flex',
49
83
  flexDirection: 'column',
50
84
  padding: '60px',
51
- background: `linear-gradient(135deg, ${gradientStart} 0%, ${gradientEnd} 100%)`,
52
- fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
85
+ background: colors.background,
86
+ fontFamily: FONT_STACK,
53
87
  }}
54
88
  >
55
- {/* Top bar with logo and site name */}
89
+ {/* Logo and site name */}
56
90
  <div
57
91
  style={{
58
92
  display: 'flex',
59
- alignItems: 'center',
93
+ flexDirection: 'column',
94
+ alignItems: 'flex-start',
60
95
  marginBottom: '40px',
61
96
  }}
62
97
  >
@@ -64,10 +99,10 @@ export async function GET(request: NextRequest) {
64
99
  <img
65
100
  src={logo}
66
101
  alt=""
67
- width={40}
68
- height={40}
102
+ width={48}
103
+ height={48}
69
104
  style={{
70
- marginRight: '16px',
105
+ marginBottom: '16px',
71
106
  borderRadius: '8px',
72
107
  }}
73
108
  />
@@ -76,7 +111,7 @@ export async function GET(request: NextRequest) {
76
111
  style={{
77
112
  fontSize: '24px',
78
113
  fontWeight: 600,
79
- color: mutedColor,
114
+ color: colors.muted,
80
115
  textTransform: 'uppercase',
81
116
  letterSpacing: '0.05em',
82
117
  }}
@@ -97,9 +132,9 @@ export async function GET(request: NextRequest) {
97
132
  style={{
98
133
  fontSize: '18px',
99
134
  fontWeight: 500,
100
- color: accentColor,
135
+ color: ACCENT_COLOR,
101
136
  padding: '8px 16px',
102
- background: isDark ? 'rgba(139, 92, 246, 0.15)' : 'rgba(139, 92, 246, 0.1)',
137
+ background: colors.badgeBackground,
103
138
  borderRadius: '20px',
104
139
  }}
105
140
  >
@@ -108,7 +143,7 @@ export async function GET(request: NextRequest) {
108
143
  </div>
109
144
  )}
110
145
 
111
- {/* Main title */}
146
+ {/* Title and description */}
112
147
  <div
113
148
  style={{
114
149
  display: 'flex',
@@ -119,9 +154,9 @@ export async function GET(request: NextRequest) {
119
154
  >
120
155
  <h1
121
156
  style={{
122
- fontSize: title.length > 40 ? '52px' : '64px',
157
+ fontSize: titleFontSize,
123
158
  fontWeight: 700,
124
- color: textColor,
159
+ color: colors.text,
125
160
  lineHeight: 1.2,
126
161
  margin: 0,
127
162
  maxWidth: '900px',
@@ -134,15 +169,13 @@ export async function GET(request: NextRequest) {
134
169
  <p
135
170
  style={{
136
171
  fontSize: '28px',
137
- color: mutedColor,
172
+ color: colors.muted,
138
173
  marginTop: '24px',
139
174
  lineHeight: 1.4,
140
175
  maxWidth: '800px',
141
176
  }}
142
177
  >
143
- {description.length > 120
144
- ? description.substring(0, 120) + '...'
145
- : description}
178
+ {truncateText(description, MAX_DESCRIPTION_LENGTH)}
146
179
  </p>
147
180
  )}
148
181
  </div>
@@ -152,7 +185,7 @@ export async function GET(request: NextRequest) {
152
185
  style={{
153
186
  display: 'flex',
154
187
  height: '6px',
155
- background: `linear-gradient(90deg, ${accentColor} 0%, #C4B5FD 50%, #A78BFA 100%)`,
188
+ background: ACCENT_GRADIENT,
156
189
  borderRadius: '3px',
157
190
  marginTop: '40px',
158
191
  }}
@@ -162,6 +195,9 @@ export async function GET(request: NextRequest) {
162
195
  {
163
196
  width: 1200,
164
197
  height: 630,
198
+ headers: {
199
+ 'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=604800',
200
+ },
165
201
  }
166
202
  );
167
203
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import type { Metadata } from 'next';
11
- import type { DocsConfig, Logo, LogoConfig, LanguageConfig, LanguageCode } from './docs-types';
11
+ import type { DocsConfig, Logo, LogoConfig, Favicon, FaviconConfig, LanguageConfig, LanguageCode } from './docs-types';
12
12
  import { transformLanguagePath, extractLanguageFromPath, isValidLanguageCode } from './language-utils';
13
13
 
14
14
  /**
@@ -23,6 +23,7 @@ function buildOgImageUrl(
23
23
  description?: string;
24
24
  section?: string;
25
25
  logo?: Logo;
26
+ favicon?: Favicon;
26
27
  theme?: 'light' | 'dark';
27
28
  }
28
29
  ): string {
@@ -40,16 +41,31 @@ function buildOgImageUrl(
40
41
  params.set('theme', options.theme);
41
42
  }
42
43
 
43
- // Get root URL (strip /docs path if present, since API endpoints are at domain root)
44
+ // For hostAtDocs sites (baseUrl ends with /docs), use the parent domain with
45
+ // /_jd/og path instead of cross-domain /api/og. LinkedIn's crawler fails to
46
+ // fetch OG images from different domains. The /_jd/og path is proxied through
47
+ // the customer's CF Worker/proxy to the ISR app's /api/og via Next.js rewrite.
48
+ const isHostAtDocs = baseUrl.endsWith('/docs');
44
49
  const rootUrl = baseUrl.replace(/\/docs$/, '');
45
50
 
46
51
  // Handle logo - prefer dark variant for OG images (dark background)
47
- if (options?.logo) {
48
- let logoPath: string;
49
- if (typeof options.logo === 'string') {
50
- logoPath = options.logo;
51
- } else {
52
- logoPath = (options.logo as LogoConfig).dark || (options.logo as LogoConfig).light;
52
+ // Satori (@vercel/og) can't render webp, so fall back to favicon if logo is webp
53
+ if (options?.logo || options?.favicon) {
54
+ let logoPath = '';
55
+ if (options?.logo) {
56
+ if (typeof options.logo === 'string') {
57
+ logoPath = options.logo;
58
+ } else {
59
+ logoPath = (options.logo as LogoConfig).dark || (options.logo as LogoConfig).light;
60
+ }
61
+ }
62
+ // Fall back to favicon when logo is webp (Satori can't decode webp)
63
+ if ((!logoPath || logoPath.endsWith('.webp')) && options?.favicon) {
64
+ if (typeof options.favicon === 'string') {
65
+ logoPath = options.favicon;
66
+ } else {
67
+ logoPath = (options.favicon as FaviconConfig).dark || (options.favicon as FaviconConfig).light;
68
+ }
53
69
  }
54
70
  // Make logo URL absolute (use root URL since assets are at domain root)
55
71
  if (logoPath && !logoPath.startsWith('http')) {
@@ -60,7 +76,10 @@ function buildOgImageUrl(
60
76
  }
61
77
  }
62
78
 
63
- return `${rootUrl}/api/og?${params.toString()}`;
79
+ // hostAtDocs: use /_jd/og (proxied to ISR app's /api/og) for same-domain OG images
80
+ // non-hostAtDocs: use /api/og directly (already same-domain)
81
+ const ogPath = isHostAtDocs ? '/_jd/og' : '/api/og';
82
+ return `${rootUrl}${ogPath}?${params.toString()}`;
64
83
  }
65
84
 
66
85
  export interface PageFrontmatter {
@@ -137,7 +156,7 @@ export function buildSeoMetadata(
137
156
  frontmatter: PageFrontmatter,
138
157
  pagePath: string,
139
158
  baseUrl: string,
140
- languages?: LanguageConfig[]
159
+ languages?: LanguageConfig[],
141
160
  ): Partial<Metadata> {
142
161
  const globalMeta = config.seo?.metatags || {};
143
162
  const pageMeta = (frontmatter.seo as Record<string, string>) || {};
@@ -210,6 +229,7 @@ export function buildSeoMetadata(
210
229
  description: frontmatter.description,
211
230
  section: frontmatter.section,
212
231
  logo: config.logo,
232
+ favicon: config.favicon,
213
233
  theme: 'dark', // Dark theme looks better for OG images
214
234
  }
215
235
  );
@@ -220,13 +240,19 @@ export function buildSeoMetadata(
220
240
  url: metatags['og:url'] || pageUrl,
221
241
  siteName: metatags['og:site_name'] || config.name,
222
242
  type: (metatags['og:type'] as 'website' | 'article') || 'website',
223
- images: [ogImageUrl],
243
+ images: [{
244
+ url: ogImageUrl,
245
+ width: 1200,
246
+ height: 630,
247
+ type: 'image/png',
248
+ }],
224
249
  };
225
250
  }
226
251
 
227
252
  // 9. Twitter Cards
228
253
  // Auto-generate Twitter card with OG image
229
- const twitterImageUrl = metatags['twitter:image'] || (metadata.openGraph as { images?: string[] })?.images?.[0];
254
+ const ogImages = (metadata.openGraph as { images?: Array<{ url: string }> })?.images;
255
+ const twitterImageUrl = metatags['twitter:image'] || ogImages?.[0]?.url;
230
256
  metadata.twitter = {
231
257
  card: (metatags['twitter:card'] as 'summary' | 'summary_large_image') || 'summary_large_image',
232
258
  site: metatags['twitter:site'],