@slyxup/core 1.0.2 → 1.2.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/types.d.ts +15 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -1
- package/.turbo/turbo-build.log +0 -4
- package/CHANGELOG.md +0 -19
- package/src/client.ts +0 -766
- package/src/errors.ts +0 -41
- package/src/index.ts +0 -3
- package/src/types.ts +0 -151
- package/test/client.test.ts +0 -249
- package/test/errors.test.ts +0 -109
- package/tsconfig.json +0 -1
- package/vitest.config.ts +0 -2
package/src/errors.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// SlyxUp Core SDK — typed errors
|
|
2
|
-
|
|
3
|
-
export class SlyxupError extends Error {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly code: string;
|
|
6
|
-
|
|
7
|
-
constructor(message: string, status: number, code: string) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = 'SlyxupError';
|
|
10
|
-
this.status = status;
|
|
11
|
-
this.code = code;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class UnauthorizedError extends SlyxupError {
|
|
16
|
-
constructor(message = 'Unauthorized') {
|
|
17
|
-
super(message, 401, 'unauthorized');
|
|
18
|
-
this.name = 'UnauthorizedError';
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class ValidationError extends SlyxupError {
|
|
23
|
-
constructor(message = 'Validation failed') {
|
|
24
|
-
super(message, 400, 'validation_error');
|
|
25
|
-
this.name = 'ValidationError';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class NetworkError extends SlyxupError {
|
|
30
|
-
constructor(message = 'Network request failed') {
|
|
31
|
-
super(message, 0, 'network_error');
|
|
32
|
-
this.name = 'NetworkError';
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class RateLimitError extends SlyxupError {
|
|
37
|
-
constructor(message = 'Too many requests') {
|
|
38
|
-
super(message, 429, 'rate_limited');
|
|
39
|
-
this.name = 'RateLimitError';
|
|
40
|
-
}
|
|
41
|
-
}
|
package/src/index.ts
DELETED
package/src/types.ts
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
// SlyxUp Core SDK — shared types
|
|
2
|
-
|
|
3
|
-
export interface SlyxupUser {
|
|
4
|
-
id: string;
|
|
5
|
-
projectId: string | null;
|
|
6
|
-
email: string;
|
|
7
|
-
emailVerified: boolean;
|
|
8
|
-
username: string | null;
|
|
9
|
-
firstName: string | null;
|
|
10
|
-
lastName: string | null;
|
|
11
|
-
avatarUrl: string | null;
|
|
12
|
-
twoFactorEnabled: boolean;
|
|
13
|
-
preferences: Record<string, unknown> | null;
|
|
14
|
-
createdAt: string;
|
|
15
|
-
updatedAt: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface SlyxupSession {
|
|
19
|
-
id: string;
|
|
20
|
-
userId: string;
|
|
21
|
-
expiresAt: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface SignInInput {
|
|
25
|
-
email?: string;
|
|
26
|
-
username?: string;
|
|
27
|
-
password: string;
|
|
28
|
-
projectId?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface SignUpInput extends Omit<SignInInput, 'username'> {
|
|
32
|
-
firstName?: string;
|
|
33
|
-
lastName?: string;
|
|
34
|
-
username?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface UpdateUserInput {
|
|
38
|
-
firstName?: string;
|
|
39
|
-
lastName?: string;
|
|
40
|
-
avatarUrl?: string;
|
|
41
|
-
username?: string | null;
|
|
42
|
-
preferences?: Record<string, unknown>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface SessionResponse {
|
|
46
|
-
ok: true;
|
|
47
|
-
user: Pick<SlyxupUser, 'id' | 'email'>;
|
|
48
|
-
session: Pick<SlyxupSession, 'id' | 'expiresAt'>;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface ChangePasswordInput {
|
|
52
|
-
currentPassword: string;
|
|
53
|
-
newPassword: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface SlyxupSessionInfo {
|
|
57
|
-
id: string;
|
|
58
|
-
ipAddress: string | null;
|
|
59
|
-
userAgent: string | null;
|
|
60
|
-
expiresAt: string;
|
|
61
|
-
createdAt: string;
|
|
62
|
-
/** true when this session belongs to the caller's current cookie */
|
|
63
|
-
isCurrent: boolean;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface SessionsResponse {
|
|
67
|
-
ok: true;
|
|
68
|
-
sessions: SlyxupSessionInfo[];
|
|
69
|
-
total: number;
|
|
70
|
-
limit: number;
|
|
71
|
-
offset: number;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface RevokeSessionsResponse {
|
|
75
|
-
ok: true;
|
|
76
|
-
revoked: number;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface UserResponse {
|
|
80
|
-
ok: true;
|
|
81
|
-
user: SlyxupUser;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface AuthResponse {
|
|
85
|
-
ok: true;
|
|
86
|
-
user: Pick<SlyxupUser, 'id' | 'email'>;
|
|
87
|
-
sessionToken?: string;
|
|
88
|
-
expiresAt?: string;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Returned by signIn when the account has 2FA enabled. */
|
|
92
|
-
export interface TwoFactorRequiredResponse {
|
|
93
|
-
ok: false;
|
|
94
|
-
code: '2FA_REQUIRED';
|
|
95
|
-
challengeToken: string;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Union returned by client.auth.signIn. */
|
|
99
|
-
export type SignInResponse = AuthResponse | TwoFactorRequiredResponse;
|
|
100
|
-
|
|
101
|
-
export interface TOTPSetupResponse {
|
|
102
|
-
ok: true;
|
|
103
|
-
secret: string;
|
|
104
|
-
provisioningUri: string;
|
|
105
|
-
accountName: string;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface EnableTOTPResponse {
|
|
109
|
-
ok: true;
|
|
110
|
-
recoveryCodes: string[];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export interface TwoFactorStatusResponse {
|
|
114
|
-
ok: boolean;
|
|
115
|
-
enabled: boolean;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface ConnectedAccount {
|
|
119
|
-
id: string;
|
|
120
|
-
provider: 'google' | 'github';
|
|
121
|
-
providerAccountId: string;
|
|
122
|
-
createdAt: string;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface ConnectedAccountsResponse {
|
|
126
|
-
ok: true;
|
|
127
|
-
accounts: ConnectedAccount[];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** Input for completing a 2FA sign-in challenge. */
|
|
131
|
-
export interface CompleteSignInInput {
|
|
132
|
-
challengeToken: string;
|
|
133
|
-
code?: string;
|
|
134
|
-
recoveryCode?: string;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export interface ErrorResponse {
|
|
138
|
-
ok: false;
|
|
139
|
-
error: string;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export type Result<T> = T | ErrorResponse;
|
|
143
|
-
|
|
144
|
-
export interface SlyxupClientOptions {
|
|
145
|
-
/** Publishable key — pk_test_xxx / pk_live_xxx */
|
|
146
|
-
publishableKey?: string;
|
|
147
|
-
/** Secret key — sk_test_xxx / sk_live_xxx (server-side admin API) */
|
|
148
|
-
secretKey?: string;
|
|
149
|
-
/** API base URL, default https://auth.slyxup.online */
|
|
150
|
-
apiUrl?: string;
|
|
151
|
-
}
|
package/test/client.test.ts
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { SlyxupClient } from '../src/client.js';
|
|
3
|
-
import { SlyxupError, UnauthorizedError, NetworkError, RateLimitError } from '../src/errors.js';
|
|
4
|
-
|
|
5
|
-
function mockFetch(
|
|
6
|
-
data: unknown,
|
|
7
|
-
init?: { ok?: boolean; status?: number; headers?: Record<string, string> }
|
|
8
|
-
) {
|
|
9
|
-
const fn = vi.fn().mockResolvedValue({
|
|
10
|
-
ok: init?.ok ?? true,
|
|
11
|
-
status: init?.status ?? 200,
|
|
12
|
-
headers: {
|
|
13
|
-
get: (key: string) => {
|
|
14
|
-
const lower = key.toLowerCase();
|
|
15
|
-
for (const [k, v] of Object.entries(init?.headers ?? {})) {
|
|
16
|
-
if (k.toLowerCase() === lower) return v;
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
json: () => Promise.resolve(data),
|
|
22
|
-
});
|
|
23
|
-
global.fetch = fn;
|
|
24
|
-
return fn;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
describe('SlyxupClient', () => {
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
vi.clearAllMocks();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('constructor', () => {
|
|
33
|
-
it('should use default apiUrl', () => {
|
|
34
|
-
mockFetch({ ok: true });
|
|
35
|
-
const client = new SlyxupClient();
|
|
36
|
-
expect(client.apiUrl).toBe('https://auth.slyxup.online');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should strip trailing slash from apiUrl', () => {
|
|
40
|
-
mockFetch({ ok: true });
|
|
41
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost:3000/' });
|
|
42
|
-
expect(client.apiUrl).toBe('http://localhost:3000');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should store publishableKey', () => {
|
|
46
|
-
mockFetch({ ok: true });
|
|
47
|
-
const client = new SlyxupClient({ publishableKey: 'pk_test_123' });
|
|
48
|
-
expect(client.publishableKey).toBe('pk_test_123');
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('auth.signUp', () => {
|
|
53
|
-
it('should POST to /v1/auth/sign-up with JSON body', async () => {
|
|
54
|
-
const fn = mockFetch({ ok: true, user: { id: 'u1', email: 'a@b.com' } });
|
|
55
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
56
|
-
const res = await client.auth.signUp({
|
|
57
|
-
email: 'a@b.com',
|
|
58
|
-
password: '12345678',
|
|
59
|
-
firstName: 'Test',
|
|
60
|
-
});
|
|
61
|
-
expect(fn).toHaveBeenCalledWith(
|
|
62
|
-
'http://localhost/v1/auth/sign-up',
|
|
63
|
-
expect.objectContaining({
|
|
64
|
-
method: 'POST',
|
|
65
|
-
body: JSON.stringify({ email: 'a@b.com', password: '12345678', firstName: 'Test' }),
|
|
66
|
-
})
|
|
67
|
-
);
|
|
68
|
-
expect(res).toEqual({ ok: true, user: { id: 'u1', email: 'a@b.com' } });
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should throw SlyxupError when response has no user', async () => {
|
|
72
|
-
mockFetch({ ok: true, error: 'Invalid email' });
|
|
73
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
74
|
-
await expect(
|
|
75
|
-
client.auth.signUp({ email: 'bad', password: '12345678' })
|
|
76
|
-
).rejects.toThrow(SlyxupError);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('auth.signIn', () => {
|
|
81
|
-
it('should POST to /v1/auth/sign-in', async () => {
|
|
82
|
-
const fn = mockFetch({ ok: true, user: { id: 'u1', email: 'a@b.com' } });
|
|
83
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
84
|
-
const res = await client.auth.signIn({ email: 'a@b.com', password: 'pass' });
|
|
85
|
-
expect(fn).toHaveBeenCalledWith(
|
|
86
|
-
'http://localhost/v1/auth/sign-in',
|
|
87
|
-
expect.objectContaining({ method: 'POST' })
|
|
88
|
-
);
|
|
89
|
-
expect(res).toEqual({ ok: true, user: { id: 'u1', email: 'a@b.com' } });
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('should throw UnauthorizedError on 401', async () => {
|
|
93
|
-
mockFetch({ ok: false, error: 'Bad credentials' }, { ok: false, status: 401 });
|
|
94
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
95
|
-
await expect(
|
|
96
|
-
client.auth.signIn({ email: 'a@b.com', password: 'wrong' })
|
|
97
|
-
).rejects.toThrow(UnauthorizedError);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should throw SlyxupError when response has no user', async () => {
|
|
101
|
-
mockFetch({ ok: true, error: 'No user' });
|
|
102
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
103
|
-
await expect(
|
|
104
|
-
client.auth.signIn({ email: 'a@b.com', password: 'pass' })
|
|
105
|
-
).rejects.toThrow(SlyxupError);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe('auth.signOut', () => {
|
|
110
|
-
it('should POST to /v1/auth/sign-out', async () => {
|
|
111
|
-
const fn = mockFetch({ ok: true });
|
|
112
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
113
|
-
const res = await client.auth.signOut();
|
|
114
|
-
expect(fn).toHaveBeenCalledWith(
|
|
115
|
-
'http://localhost/v1/auth/sign-out',
|
|
116
|
-
expect.objectContaining({ method: 'POST' })
|
|
117
|
-
);
|
|
118
|
-
expect(res).toEqual({ ok: true });
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
describe('sessions.get', () => {
|
|
123
|
-
it('should GET /v1/session', async () => {
|
|
124
|
-
const data = { ok: true, user: { id: 'u1', email: 'a@b.com' }, session: { id: 's1', expiresAt: '2030' } };
|
|
125
|
-
const fn = mockFetch(data);
|
|
126
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
127
|
-
const res = await client.sessions.get();
|
|
128
|
-
expect(fn).toHaveBeenCalledWith('http://localhost/v1/session', expect.anything());
|
|
129
|
-
expect(res).toEqual(data);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('should throw UnauthorizedError when no session in response', async () => {
|
|
133
|
-
mockFetch({ ok: true, error: 'No session' });
|
|
134
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
135
|
-
await expect(client.sessions.get()).rejects.toThrow(UnauthorizedError);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it('should throw NetworkError when fetch rejects', async () => {
|
|
139
|
-
global.fetch = vi.fn().mockRejectedValue(new Error('fetch failed'));
|
|
140
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
141
|
-
await expect(client.sessions.get()).rejects.toThrow(NetworkError);
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
describe('users.me', () => {
|
|
146
|
-
it('should GET /v1/user', async () => {
|
|
147
|
-
const user = { id: 'u1', email: 'a@b.com', firstName: 'Test', lastName: 'User', createdAt: '', updatedAt: '', projectId: null, emailVerified: true, avatarUrl: null, preferences: null };
|
|
148
|
-
const fn = mockFetch({ ok: true, user });
|
|
149
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
150
|
-
const res = await client.users.me();
|
|
151
|
-
expect(fn).toHaveBeenCalledWith('http://localhost/v1/user', expect.anything());
|
|
152
|
-
expect(res.user).toEqual(user);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should throw UnauthorizedError when no user', async () => {
|
|
156
|
-
mockFetch({ ok: true, error: 'Not found' });
|
|
157
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
158
|
-
await expect(client.users.me()).rejects.toThrow(UnauthorizedError);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
describe('users.update', () => {
|
|
163
|
-
it('should PATCH /v1/user with JSON body', async () => {
|
|
164
|
-
const fn = mockFetch({ ok: true, user: { id: 'u1', firstName: 'Jane' } });
|
|
165
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
166
|
-
await client.users.update({ firstName: 'Jane' });
|
|
167
|
-
expect(fn).toHaveBeenCalledWith(
|
|
168
|
-
'http://localhost/v1/user',
|
|
169
|
-
expect.objectContaining({ method: 'PATCH', body: JSON.stringify({ firstName: 'Jane' }) })
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
describe('users.delete', () => {
|
|
175
|
-
it('should DELETE /v1/user', async () => {
|
|
176
|
-
const fn = mockFetch({ ok: true });
|
|
177
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
178
|
-
const res = await client.users.delete();
|
|
179
|
-
expect(fn).toHaveBeenCalledWith('http://localhost/v1/user', expect.objectContaining({ method: 'DELETE' }));
|
|
180
|
-
expect(res).toEqual({ ok: true });
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
describe('cookie jar', () => {
|
|
185
|
-
it('should capture Set-Cookie and forward as Cookie header', async () => {
|
|
186
|
-
const fn = vi.fn()
|
|
187
|
-
.mockResolvedValueOnce({
|
|
188
|
-
ok: true,
|
|
189
|
-
status: 200,
|
|
190
|
-
headers: {
|
|
191
|
-
get: (key: string) => key.toLowerCase() === 'set-cookie' ? 'slyxup_session=abc123; Path=/; HttpOnly' : null,
|
|
192
|
-
},
|
|
193
|
-
json: () => Promise.resolve({ ok: true, user: { id: 'u1', email: 'a@b.com' } }),
|
|
194
|
-
})
|
|
195
|
-
.mockResolvedValueOnce({
|
|
196
|
-
ok: true,
|
|
197
|
-
status: 200,
|
|
198
|
-
headers: { get: () => null },
|
|
199
|
-
json: () => Promise.resolve({ ok: true, user: { id: 'u1', email: 'a@b.com' }, session: { id: 's1', expiresAt: '2030' } }),
|
|
200
|
-
});
|
|
201
|
-
global.fetch = fn;
|
|
202
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
203
|
-
await client.auth.signIn({ email: 'a@b.com', password: 'pass' });
|
|
204
|
-
await client.sessions.get();
|
|
205
|
-
expect(fn).toHaveBeenCalledTimes(2);
|
|
206
|
-
const secondCall = fn.mock.calls[1] as any[];
|
|
207
|
-
expect(secondCall[1].headers).toMatchObject({ Cookie: 'slyxup_session=abc123' });
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
describe('error handling', () => {
|
|
212
|
-
it('should throw RateLimitError on 429', async () => {
|
|
213
|
-
mockFetch({ error: 'rate limited' }, { ok: false, status: 429 });
|
|
214
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
215
|
-
await expect(client.sessions.get()).rejects.toThrow(RateLimitError);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it('should throw NetworkError when fetch rejects', async () => {
|
|
219
|
-
global.fetch = vi.fn().mockRejectedValue(new TypeError('Failed to fetch'));
|
|
220
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
221
|
-
await expect(client.auth.signIn({ email: 'a', password: 'b' })).rejects.toThrow(NetworkError);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should throw SlyxupError on 500 with error message', async () => {
|
|
225
|
-
mockFetch({ error: 'Server error' }, { ok: false, status: 500 });
|
|
226
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
227
|
-
try {
|
|
228
|
-
await client.sessions.get();
|
|
229
|
-
expect.fail('Should have thrown');
|
|
230
|
-
} catch (e) {
|
|
231
|
-
expect(e).toBeInstanceOf(SlyxupError);
|
|
232
|
-
expect((e as SlyxupError).status).toBe(500);
|
|
233
|
-
expect((e as SlyxupError).code).toBe('api_error');
|
|
234
|
-
expect((e as SlyxupError).message).toBe('Server error');
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('should handle invalid JSON gracefully', async () => {
|
|
239
|
-
global.fetch = vi.fn().mockResolvedValue({
|
|
240
|
-
ok: true,
|
|
241
|
-
status: 200,
|
|
242
|
-
headers: { get: () => null },
|
|
243
|
-
json: () => Promise.reject(new Error('not json')),
|
|
244
|
-
});
|
|
245
|
-
const client = new SlyxupClient({ apiUrl: 'http://localhost' });
|
|
246
|
-
await expect(client.sessions.get()).rejects.toThrow(UnauthorizedError);
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
});
|
package/test/errors.test.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
SlyxupError,
|
|
4
|
-
UnauthorizedError,
|
|
5
|
-
ValidationError,
|
|
6
|
-
NetworkError,
|
|
7
|
-
RateLimitError,
|
|
8
|
-
} from '../src/errors.js';
|
|
9
|
-
|
|
10
|
-
describe('SlyxupError', () => {
|
|
11
|
-
it('should set message, status, code, and name', () => {
|
|
12
|
-
const err = new SlyxupError('test', 500, 'test_error');
|
|
13
|
-
expect(err.message).toBe('test');
|
|
14
|
-
expect(err.status).toBe(500);
|
|
15
|
-
expect(err.code).toBe('test_error');
|
|
16
|
-
expect(err.name).toBe('SlyxupError');
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should be instanceof Error', () => {
|
|
20
|
-
const err = new SlyxupError('test', 400, 'err');
|
|
21
|
-
expect(err).toBeInstanceOf(Error);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should be instanceof SlyxupError', () => {
|
|
25
|
-
const err = new SlyxupError('test', 400, 'err');
|
|
26
|
-
expect(err).toBeInstanceOf(SlyxupError);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('UnauthorizedError', () => {
|
|
31
|
-
it('should have default values', () => {
|
|
32
|
-
const err = new UnauthorizedError();
|
|
33
|
-
expect(err.message).toBe('Unauthorized');
|
|
34
|
-
expect(err.status).toBe(401);
|
|
35
|
-
expect(err.code).toBe('unauthorized');
|
|
36
|
-
expect(err.name).toBe('UnauthorizedError');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should accept custom message', () => {
|
|
40
|
-
const err = new UnauthorizedError('Custom');
|
|
41
|
-
expect(err.message).toBe('Custom');
|
|
42
|
-
expect(err.status).toBe(401);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should be instanceof SlyxupError', () => {
|
|
46
|
-
expect(new UnauthorizedError()).toBeInstanceOf(SlyxupError);
|
|
47
|
-
expect(new UnauthorizedError()).toBeInstanceOf(Error);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('ValidationError', () => {
|
|
52
|
-
it('should have default values', () => {
|
|
53
|
-
const err = new ValidationError();
|
|
54
|
-
expect(err.message).toBe('Validation failed');
|
|
55
|
-
expect(err.status).toBe(400);
|
|
56
|
-
expect(err.code).toBe('validation_error');
|
|
57
|
-
expect(err.name).toBe('ValidationError');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should accept custom message', () => {
|
|
61
|
-
const err = new ValidationError('Bad input');
|
|
62
|
-
expect(err.message).toBe('Bad input');
|
|
63
|
-
expect(err.status).toBe(400);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should be instanceof SlyxupError', () => {
|
|
67
|
-
expect(new ValidationError()).toBeInstanceOf(SlyxupError);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('NetworkError', () => {
|
|
72
|
-
it('should have default values', () => {
|
|
73
|
-
const err = new NetworkError();
|
|
74
|
-
expect(err.message).toBe('Network request failed');
|
|
75
|
-
expect(err.status).toBe(0);
|
|
76
|
-
expect(err.code).toBe('network_error');
|
|
77
|
-
expect(err.name).toBe('NetworkError');
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should accept custom message', () => {
|
|
81
|
-
const err = new NetworkError('Timeout');
|
|
82
|
-
expect(err.message).toBe('Timeout');
|
|
83
|
-
expect(err.status).toBe(0);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should be instanceof SlyxupError', () => {
|
|
87
|
-
expect(new NetworkError()).toBeInstanceOf(SlyxupError);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe('RateLimitError', () => {
|
|
92
|
-
it('should have default values', () => {
|
|
93
|
-
const err = new RateLimitError();
|
|
94
|
-
expect(err.message).toBe('Too many requests');
|
|
95
|
-
expect(err.status).toBe(429);
|
|
96
|
-
expect(err.code).toBe('rate_limited');
|
|
97
|
-
expect(err.name).toBe('RateLimitError');
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should accept custom message', () => {
|
|
101
|
-
const err = new RateLimitError('Slow down');
|
|
102
|
-
expect(err.message).toBe('Slow down');
|
|
103
|
-
expect(err.status).toBe(429);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should be instanceof SlyxupError', () => {
|
|
107
|
-
expect(new RateLimitError()).toBeInstanceOf(SlyxupError);
|
|
108
|
-
});
|
|
109
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "dist", "rootDir": "src", "lib": ["ES2022", "DOM", "DOM.Iterable"] }, "include": ["src"] }
|
package/vitest.config.ts
DELETED