@slyxup/core 0.1.0 → 0.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/CHANGELOG.md +13 -0
- package/README.md +81 -0
- package/dist/client.d.ts +34 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +124 -1
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +18 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +19 -2
- package/src/client.ts +171 -1
- package/src/errors.ts +41 -0
- package/src/index.ts +3 -1
- package/src/types.ts +68 -0
- package/tsconfig.json +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @slyxup/core
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`7cf24ff`](https://github.com/slyxup/stack/commit/7cf24ffe37fe6f2bca41fdc0281618c2db02b3ae) - Full V1 SDKs: SlyxupClient with cookie jar, React provider + hooks, Next.js server helpers/middleware, themed UI components, slyxup CLI
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [`44da26b`](https://github.com/slyxup/stack/commit/44da26bd8f952b6fce4b67f75ddb0ef041a984ac) - ci: verify all packages CI/CD — little change in every package + auth/stack/billing
|
|
12
|
+
|
|
13
|
+
- [`fe4f8bb`](https://github.com/slyxup/stack/commit/fe4f8bb4ab412a58303f59921548d3625b0675c9) - ci: second verify all — 14:55
|
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @slyxup/core
|
|
2
|
+
|
|
3
|
+
Core HTTP client for the SlyxUp Auth platform. Zero framework dependencies — works in browsers, Node.js, and edge runtimes.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @slyxup/core
|
|
9
|
+
# pnpm add @slyxup/core
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Quick start
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { SlyxupClient } from '@slyxup/core';
|
|
16
|
+
|
|
17
|
+
const client = new SlyxupClient({
|
|
18
|
+
publishableKey: 'pk_test_xxx', // from `slyxup keys create`
|
|
19
|
+
apiUrl: 'https://auth.slyxup.online', // default; override for self-host/local
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// ── Auth ──
|
|
23
|
+
await client.auth.signUp({ email: 'ada@example.com', password: 'password123', firstName: 'Ada' });
|
|
24
|
+
await client.auth.signIn({ email: 'ada@example.com', password: 'password123' });
|
|
25
|
+
await client.auth.signOut();
|
|
26
|
+
|
|
27
|
+
// ── Sessions ──
|
|
28
|
+
const { session, user } = await client.sessions.get();
|
|
29
|
+
// session.expiresAt — ISO date; throws UnauthorizedError (401) when signed out
|
|
30
|
+
|
|
31
|
+
// ── Users ──
|
|
32
|
+
const me = await client.users.me(); // full profile
|
|
33
|
+
await client.users.update({ firstName: 'Ada', lastName: 'Lovelace' });
|
|
34
|
+
await client.users.delete(); // GDPR delete
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The client keeps an internal cookie jar, so sign-in state persists across calls in **Node/SSR too** (browsers manage cookies natively).
|
|
38
|
+
|
|
39
|
+
## Error handling
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { SlyxupError, UnauthorizedError, RateLimitError, NetworkError, ValidationError } from '@slyxup/core';
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
await client.auth.signIn({ email, password });
|
|
46
|
+
} catch (e) {
|
|
47
|
+
if (e instanceof UnauthorizedError) showInvalidCredentials();
|
|
48
|
+
else if (e instanceof RateLimitError) backOff();
|
|
49
|
+
else if (e instanceof SlyxupError) console.error(e.status, e.code, e.message);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
| Error | Status | Meaning |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `ValidationError` | 400 | Bad input |
|
|
56
|
+
| `UnauthorizedError` | 401 | No/expired session |
|
|
57
|
+
| `RateLimitError` | 429 | Too many requests |
|
|
58
|
+
| `NetworkError` | 0 | Fetch failed |
|
|
59
|
+
| `SlyxupError` | * | Base class (`e.status`, `e.code`) |
|
|
60
|
+
|
|
61
|
+
## API surface
|
|
62
|
+
|
|
63
|
+
| Namespace | Method | Endpoint |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `auth.signUp(input)` | POST | `/v1/auth/sign-up` |
|
|
66
|
+
| `auth.signIn(input)` | POST | `/v1/auth/sign-in` |
|
|
67
|
+
| `auth.signOut()` | POST | `/v1/auth/sign-out` |
|
|
68
|
+
| `sessions.get()` | GET | `/v1/session` |
|
|
69
|
+
| `users.me()` | GET | `/v1/user` |
|
|
70
|
+
| `users.update(patch)` | PATCH | `/v1/user` |
|
|
71
|
+
| `users.delete()` | DELETE | `/v1/user` |
|
|
72
|
+
|
|
73
|
+
## Framework wrappers
|
|
74
|
+
|
|
75
|
+
- React hooks/components: [`@slyxup/react`](../react)
|
|
76
|
+
- Next.js server helpers + middleware: [`@slyxup/nextjs`](../nextjs)
|
|
77
|
+
- Prebuilt UI cards: [`@slyxup/ui`](../ui)
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT © [SlyxUp](https://github.com/slyxup/stack)
|
package/dist/client.d.ts
CHANGED
|
@@ -1,2 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AuthResponse, SessionResponse, SignInInput, SignUpInput, SlyxupClientOptions, UpdateUserInput, UserResponse } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* SlyxUp Core Client.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* const client = new SlyxupClient({ publishableKey: 'pk_test_xxx' });
|
|
7
|
+
* await client.auth.signIn({ email: 'a@b.com', password: '12345678' });
|
|
8
|
+
* const session = await client.sessions.get();
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare class SlyxupClient {
|
|
12
|
+
readonly publishableKey?: string;
|
|
13
|
+
readonly apiUrl: string;
|
|
14
|
+
readonly auth: {
|
|
15
|
+
signUp: (input: SignUpInput) => Promise<AuthResponse>;
|
|
16
|
+
signIn: (input: SignInInput) => Promise<AuthResponse>;
|
|
17
|
+
signOut: () => Promise<{
|
|
18
|
+
ok: true;
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
21
|
+
readonly sessions: {
|
|
22
|
+
get: () => Promise<SessionResponse>;
|
|
23
|
+
};
|
|
24
|
+
readonly users: {
|
|
25
|
+
me: () => Promise<UserResponse>;
|
|
26
|
+
update: (input: UpdateUserInput) => Promise<UserResponse>;
|
|
27
|
+
delete: () => Promise<{
|
|
28
|
+
ok: true;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
constructor(options?: SlyxupClientOptions);
|
|
32
|
+
}
|
|
33
|
+
export * from './types.js';
|
|
34
|
+
export * from './errors.js';
|
|
2
35
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EAGZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,YAAY,EACb,MAAM,YAAY,CAAC;AAkBpB;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,IAAI,EAAE;QACb,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACtD,OAAO,EAAE,MAAM,OAAO,CAAC;YAAE,EAAE,EAAE,IAAI,CAAA;SAAE,CAAC,CAAC;KACtC,CAAC;IAEF,QAAQ,CAAC,QAAQ,EAAE;QACjB,GAAG,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;KACrC,CAAC;IAEF,QAAQ,CAAC,KAAK,EAAE;QACd,EAAE,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;QAChC,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,EAAE,MAAM,OAAO,CAAC;YAAE,EAAE,EAAE,IAAI,CAAA;SAAE,CAAC,CAAC;KACrC,CAAC;gBAEU,OAAO,GAAE,mBAAwB;CAuG9C;AAGD,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,125 @@
|
|
|
1
|
-
|
|
1
|
+
import { NetworkError, RateLimitError, SlyxupError, UnauthorizedError, } from './errors.js';
|
|
2
|
+
const DEFAULT_API_URL = 'https://auth.slyxup.online';
|
|
3
|
+
/** Minimal cookie jar so the SDK works in Node/SSR (browsers manage cookies natively). */
|
|
4
|
+
function createCookieJar() {
|
|
5
|
+
let jar;
|
|
6
|
+
return {
|
|
7
|
+
capture(res) {
|
|
8
|
+
const setCookie = res.headers.get('set-cookie');
|
|
9
|
+
if (setCookie)
|
|
10
|
+
jar = setCookie.split(';')[0]?.trim();
|
|
11
|
+
},
|
|
12
|
+
header() {
|
|
13
|
+
return jar ? { Cookie: jar } : {};
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* SlyxUp Core Client.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const client = new SlyxupClient({ publishableKey: 'pk_test_xxx' });
|
|
22
|
+
* await client.auth.signIn({ email: 'a@b.com', password: '12345678' });
|
|
23
|
+
* const session = await client.sessions.get();
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class SlyxupClient {
|
|
27
|
+
publishableKey;
|
|
28
|
+
apiUrl;
|
|
29
|
+
auth;
|
|
30
|
+
sessions;
|
|
31
|
+
users;
|
|
32
|
+
constructor(options = {}) {
|
|
33
|
+
const jar = createCookieJar();
|
|
34
|
+
this.publishableKey = options.publishableKey;
|
|
35
|
+
this.apiUrl = (options.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, '');
|
|
36
|
+
const request = async (path, init = {}) => {
|
|
37
|
+
let res;
|
|
38
|
+
try {
|
|
39
|
+
res = await fetch(`${this.apiUrl}${path}`, {
|
|
40
|
+
...init,
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
...jar.header(),
|
|
44
|
+
...init.headers,
|
|
45
|
+
},
|
|
46
|
+
credentials: 'include',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
throw new NetworkError();
|
|
51
|
+
}
|
|
52
|
+
jar.capture(res);
|
|
53
|
+
const data = (await res
|
|
54
|
+
.json()
|
|
55
|
+
.catch(() => ({ ok: false, error: 'Invalid response' })));
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
if (res.status === 401)
|
|
58
|
+
throw new UnauthorizedError('error' in data ? String(data.error) : undefined);
|
|
59
|
+
if (res.status === 429)
|
|
60
|
+
throw new RateLimitError();
|
|
61
|
+
throw new SlyxupError('error' in data
|
|
62
|
+
? String(data.error)
|
|
63
|
+
: `Request failed (${res.status})`, res.status, 'api_error');
|
|
64
|
+
}
|
|
65
|
+
return data;
|
|
66
|
+
};
|
|
67
|
+
const post = (path, body) => request(path, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
70
|
+
});
|
|
71
|
+
this.auth = {
|
|
72
|
+
signUp: async (input) => {
|
|
73
|
+
const res = await post('/v1/auth/sign-up', input);
|
|
74
|
+
if (!('user' in res))
|
|
75
|
+
throw new SlyxupError(res.error, 400, 'api_error');
|
|
76
|
+
return res;
|
|
77
|
+
},
|
|
78
|
+
signIn: async (input) => {
|
|
79
|
+
const res = await post('/v1/auth/sign-in', input);
|
|
80
|
+
if (!('user' in res))
|
|
81
|
+
throw new SlyxupError(res.error, 401, 'api_error');
|
|
82
|
+
return res;
|
|
83
|
+
},
|
|
84
|
+
signOut: async () => {
|
|
85
|
+
const res = await post('/v1/auth/sign-out');
|
|
86
|
+
return res;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
this.sessions = {
|
|
90
|
+
get: async () => {
|
|
91
|
+
const res = await request('/v1/session');
|
|
92
|
+
if (!('session' in res))
|
|
93
|
+
throw new UnauthorizedError(res.error);
|
|
94
|
+
return res;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
this.users = {
|
|
98
|
+
me: async () => {
|
|
99
|
+
const res = await request('/v1/user');
|
|
100
|
+
if (!('user' in res))
|
|
101
|
+
throw new UnauthorizedError(res.error);
|
|
102
|
+
return res;
|
|
103
|
+
},
|
|
104
|
+
update: async (input) => {
|
|
105
|
+
const res = await request('/v1/user', {
|
|
106
|
+
method: 'PATCH',
|
|
107
|
+
body: JSON.stringify(input),
|
|
108
|
+
});
|
|
109
|
+
if (!('user' in res))
|
|
110
|
+
throw new SlyxupError(res.error, 400, 'api_error');
|
|
111
|
+
return res;
|
|
112
|
+
},
|
|
113
|
+
delete: async () => {
|
|
114
|
+
const res = await request('/v1/user', {
|
|
115
|
+
method: 'DELETE',
|
|
116
|
+
});
|
|
117
|
+
return res;
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Re-exports so consumers can import from '@slyxup/core'
|
|
123
|
+
export * from './types.js';
|
|
124
|
+
export * from './errors.js';
|
|
2
125
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class SlyxupError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly code: string;
|
|
4
|
+
constructor(message: string, status: number, code: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class UnauthorizedError extends SlyxupError {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class ValidationError extends SlyxupError {
|
|
10
|
+
constructor(message?: string);
|
|
11
|
+
}
|
|
12
|
+
export declare class NetworkError extends SlyxupError {
|
|
13
|
+
constructor(message?: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class RateLimitError extends SlyxupError {
|
|
16
|
+
constructor(message?: string);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAM1D;AAED,qBAAa,iBAAkB,SAAQ,WAAW;gBACpC,OAAO,SAAiB;CAIrC;AAED,qBAAa,eAAgB,SAAQ,WAAW;gBAClC,OAAO,SAAsB;CAI1C;AAED,qBAAa,YAAa,SAAQ,WAAW;gBAC/B,OAAO,SAA2B;CAI/C;AAED,qBAAa,cAAe,SAAQ,WAAW;gBACjC,OAAO,SAAsB;CAI1C"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SlyxUp Core SDK — typed errors
|
|
2
|
+
export class SlyxupError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
constructor(message, status, code) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'SlyxupError';
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class UnauthorizedError extends SlyxupError {
|
|
13
|
+
constructor(message = 'Unauthorized') {
|
|
14
|
+
super(message, 401, 'unauthorized');
|
|
15
|
+
this.name = 'UnauthorizedError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class ValidationError extends SlyxupError {
|
|
19
|
+
constructor(message = 'Validation failed') {
|
|
20
|
+
super(message, 400, 'validation_error');
|
|
21
|
+
this.name = 'ValidationError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class NetworkError extends SlyxupError {
|
|
25
|
+
constructor(message = 'Network request failed') {
|
|
26
|
+
super(message, 0, 'network_error');
|
|
27
|
+
this.name = 'NetworkError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class RateLimitError extends SlyxupError {
|
|
31
|
+
constructor(message = 'Too many requests') {
|
|
32
|
+
super(message, 429, 'rate_limited');
|
|
33
|
+
this.name = 'RateLimitError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,MAAM,CAAS;IACf,IAAI,CAAS;IAEtB,YAAY,OAAe,EAAE,MAAc,EAAE,IAAY;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD,YAAY,OAAO,GAAG,cAAc;QAClC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,YAAY,OAAO,GAAG,mBAAmB;QACvC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,WAAW;IAC3C,YAAY,OAAO,GAAG,wBAAwB;QAC5C,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,WAAW;IAC7C,YAAY,OAAO,GAAG,mBAAmB;QACvC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface SlyxupUser {
|
|
2
|
+
id: string;
|
|
3
|
+
projectId: string | null;
|
|
4
|
+
email: string;
|
|
5
|
+
emailVerified: boolean;
|
|
6
|
+
firstName: string | null;
|
|
7
|
+
lastName: string | null;
|
|
8
|
+
avatarUrl: string | null;
|
|
9
|
+
preferences: Record<string, unknown> | null;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
updatedAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SlyxupSession {
|
|
14
|
+
id: string;
|
|
15
|
+
userId: string;
|
|
16
|
+
expiresAt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SignInInput {
|
|
19
|
+
email: string;
|
|
20
|
+
password: string;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface SignUpInput extends SignInInput {
|
|
24
|
+
firstName?: string;
|
|
25
|
+
lastName?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface UpdateUserInput {
|
|
28
|
+
firstName?: string;
|
|
29
|
+
lastName?: string;
|
|
30
|
+
avatarUrl?: string;
|
|
31
|
+
preferences?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export interface SessionResponse {
|
|
34
|
+
ok: true;
|
|
35
|
+
user: Pick<SlyxupUser, 'id' | 'email'>;
|
|
36
|
+
session: Pick<SlyxupSession, 'id' | 'expiresAt'>;
|
|
37
|
+
}
|
|
38
|
+
export interface UserResponse {
|
|
39
|
+
ok: true;
|
|
40
|
+
user: SlyxupUser;
|
|
41
|
+
}
|
|
42
|
+
export interface AuthResponse {
|
|
43
|
+
ok: true;
|
|
44
|
+
user: Pick<SlyxupUser, 'id' | 'email'>;
|
|
45
|
+
}
|
|
46
|
+
export interface ErrorResponse {
|
|
47
|
+
ok: false;
|
|
48
|
+
error: string;
|
|
49
|
+
}
|
|
50
|
+
export type Result<T> = T | ErrorResponse;
|
|
51
|
+
export interface SlyxupClientOptions {
|
|
52
|
+
/** Publishable key — pk_test_xxx / pk_live_xxx */
|
|
53
|
+
publishableKey?: string;
|
|
54
|
+
/** API base URL, default https://auth.slyxup.online */
|
|
55
|
+
apiUrl?: string;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;IACvC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,iCAAiC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slyxup/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "@slyxup/core — SlyxUp SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"scripts": {
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc -p tsconfig.json",
|
|
10
|
+
"typecheck": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/slyxup/stack.git",
|
|
15
|
+
"directory": "packages/core"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/slyxup/stack/tree/main/packages/core#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/slyxup/stack/issues"
|
|
20
|
+
},
|
|
21
|
+
"author": "SlyxUp <hello@slyxup.online>",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
}
|
|
9
26
|
}
|
package/src/client.ts
CHANGED
|
@@ -1 +1,171 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
|
+
NetworkError,
|
|
3
|
+
RateLimitError,
|
|
4
|
+
SlyxupError,
|
|
5
|
+
UnauthorizedError,
|
|
6
|
+
} from './errors.js';
|
|
7
|
+
import type {
|
|
8
|
+
AuthResponse,
|
|
9
|
+
ErrorResponse,
|
|
10
|
+
Result,
|
|
11
|
+
SessionResponse,
|
|
12
|
+
SignInInput,
|
|
13
|
+
SignUpInput,
|
|
14
|
+
SlyxupClientOptions,
|
|
15
|
+
UpdateUserInput,
|
|
16
|
+
UserResponse,
|
|
17
|
+
} from './types.js';
|
|
18
|
+
|
|
19
|
+
const DEFAULT_API_URL = 'https://auth.slyxup.online';
|
|
20
|
+
|
|
21
|
+
/** Minimal cookie jar so the SDK works in Node/SSR (browsers manage cookies natively). */
|
|
22
|
+
function createCookieJar() {
|
|
23
|
+
let jar: string | undefined;
|
|
24
|
+
return {
|
|
25
|
+
capture(res: Response) {
|
|
26
|
+
const setCookie = res.headers.get('set-cookie');
|
|
27
|
+
if (setCookie) jar = setCookie.split(';')[0]?.trim();
|
|
28
|
+
},
|
|
29
|
+
header(): Record<string, string> {
|
|
30
|
+
return jar ? { Cookie: jar } : {};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* SlyxUp Core Client.
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const client = new SlyxupClient({ publishableKey: 'pk_test_xxx' });
|
|
40
|
+
* await client.auth.signIn({ email: 'a@b.com', password: '12345678' });
|
|
41
|
+
* const session = await client.sessions.get();
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class SlyxupClient {
|
|
45
|
+
readonly publishableKey?: string;
|
|
46
|
+
readonly apiUrl: string;
|
|
47
|
+
|
|
48
|
+
readonly auth: {
|
|
49
|
+
signUp: (input: SignUpInput) => Promise<AuthResponse>;
|
|
50
|
+
signIn: (input: SignInInput) => Promise<AuthResponse>;
|
|
51
|
+
signOut: () => Promise<{ ok: true }>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
readonly sessions: {
|
|
55
|
+
get: () => Promise<SessionResponse>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
readonly users: {
|
|
59
|
+
me: () => Promise<UserResponse>;
|
|
60
|
+
update: (input: UpdateUserInput) => Promise<UserResponse>;
|
|
61
|
+
delete: () => Promise<{ ok: true }>;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
constructor(options: SlyxupClientOptions = {}) {
|
|
65
|
+
const jar = createCookieJar();
|
|
66
|
+
this.publishableKey = options.publishableKey;
|
|
67
|
+
this.apiUrl = (options.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, '');
|
|
68
|
+
|
|
69
|
+
const request = async <T>(
|
|
70
|
+
path: string,
|
|
71
|
+
init: RequestInit & { body?: string } = {}
|
|
72
|
+
): Promise<Result<T>> => {
|
|
73
|
+
let res: Response;
|
|
74
|
+
try {
|
|
75
|
+
res = await fetch(`${this.apiUrl}${path}`, {
|
|
76
|
+
...init,
|
|
77
|
+
headers: {
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
...jar.header(),
|
|
80
|
+
...init.headers,
|
|
81
|
+
},
|
|
82
|
+
credentials: 'include',
|
|
83
|
+
});
|
|
84
|
+
} catch {
|
|
85
|
+
throw new NetworkError();
|
|
86
|
+
}
|
|
87
|
+
jar.capture(res);
|
|
88
|
+
|
|
89
|
+
const data = (await res
|
|
90
|
+
.json()
|
|
91
|
+
.catch(() => ({ ok: false, error: 'Invalid response' }))) as object;
|
|
92
|
+
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
if (res.status === 401)
|
|
95
|
+
throw new UnauthorizedError(
|
|
96
|
+
'error' in data ? String(data.error) : undefined
|
|
97
|
+
);
|
|
98
|
+
if (res.status === 429) throw new RateLimitError();
|
|
99
|
+
throw new SlyxupError(
|
|
100
|
+
'error' in data
|
|
101
|
+
? String(data.error)
|
|
102
|
+
: `Request failed (${res.status})`,
|
|
103
|
+
res.status,
|
|
104
|
+
'api_error'
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return data as Result<T>;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const post = <T>(path: string, body?: unknown) =>
|
|
112
|
+
request<T>(path, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
this.auth = {
|
|
118
|
+
signUp: async (input) => {
|
|
119
|
+
const res = await post<AuthResponse>('/v1/auth/sign-up', input);
|
|
120
|
+
if (!('user' in res))
|
|
121
|
+
throw new SlyxupError(res.error, 400, 'api_error');
|
|
122
|
+
return res;
|
|
123
|
+
},
|
|
124
|
+
signIn: async (input) => {
|
|
125
|
+
const res = await post<AuthResponse>('/v1/auth/sign-in', input);
|
|
126
|
+
if (!('user' in res))
|
|
127
|
+
throw new SlyxupError(res.error, 401, 'api_error');
|
|
128
|
+
return res;
|
|
129
|
+
},
|
|
130
|
+
signOut: async () => {
|
|
131
|
+
const res = await post<{ ok: true }>('/v1/auth/sign-out');
|
|
132
|
+
return res as { ok: true };
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
this.sessions = {
|
|
137
|
+
get: async () => {
|
|
138
|
+
const res = await request<SessionResponse>('/v1/session');
|
|
139
|
+
if (!('session' in res)) throw new UnauthorizedError(res.error);
|
|
140
|
+
return res;
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
this.users = {
|
|
145
|
+
me: async () => {
|
|
146
|
+
const res = await request<UserResponse>('/v1/user');
|
|
147
|
+
if (!('user' in res)) throw new UnauthorizedError(res.error);
|
|
148
|
+
return res;
|
|
149
|
+
},
|
|
150
|
+
update: async (input) => {
|
|
151
|
+
const res = await request<UserResponse>('/v1/user', {
|
|
152
|
+
method: 'PATCH',
|
|
153
|
+
body: JSON.stringify(input),
|
|
154
|
+
});
|
|
155
|
+
if (!('user' in res))
|
|
156
|
+
throw new SlyxupError(res.error, 400, 'api_error');
|
|
157
|
+
return res;
|
|
158
|
+
},
|
|
159
|
+
delete: async () => {
|
|
160
|
+
const res = await request<{ ok: true }>('/v1/user', {
|
|
161
|
+
method: 'DELETE',
|
|
162
|
+
});
|
|
163
|
+
return res as { ok: true };
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Re-exports so consumers can import from '@slyxup/core'
|
|
170
|
+
export * from './types.js';
|
|
171
|
+
export * from './errors.js';
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
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
CHANGED
package/src/types.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
firstName: string | null;
|
|
9
|
+
lastName: string | null;
|
|
10
|
+
avatarUrl: string | null;
|
|
11
|
+
preferences: Record<string, unknown> | null;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SlyxupSession {
|
|
17
|
+
id: string;
|
|
18
|
+
userId: string;
|
|
19
|
+
expiresAt: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface SignInInput {
|
|
23
|
+
email: string;
|
|
24
|
+
password: string;
|
|
25
|
+
projectId?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SignUpInput extends SignInInput {
|
|
29
|
+
firstName?: string;
|
|
30
|
+
lastName?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface UpdateUserInput {
|
|
34
|
+
firstName?: string;
|
|
35
|
+
lastName?: string;
|
|
36
|
+
avatarUrl?: string;
|
|
37
|
+
preferences?: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SessionResponse {
|
|
41
|
+
ok: true;
|
|
42
|
+
user: Pick<SlyxupUser, 'id' | 'email'>;
|
|
43
|
+
session: Pick<SlyxupSession, 'id' | 'expiresAt'>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface UserResponse {
|
|
47
|
+
ok: true;
|
|
48
|
+
user: SlyxupUser;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AuthResponse {
|
|
52
|
+
ok: true;
|
|
53
|
+
user: Pick<SlyxupUser, 'id' | 'email'>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ErrorResponse {
|
|
57
|
+
ok: false;
|
|
58
|
+
error: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type Result<T> = T | ErrorResponse;
|
|
62
|
+
|
|
63
|
+
export interface SlyxupClientOptions {
|
|
64
|
+
/** Publishable key — pk_test_xxx / pk_live_xxx */
|
|
65
|
+
publishableKey?: string;
|
|
66
|
+
/** API base URL, default https://auth.slyxup.online */
|
|
67
|
+
apiUrl?: string;
|
|
68
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "dist", "rootDir": "src" }, "include": ["src"] }
|
|
1
|
+
{ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "dist", "rootDir": "src", "lib": ["ES2022", "DOM", "DOM.Iterable"] }, "include": ["src"] }
|