@axium/client 0.1.0 → 0.1.1

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.
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { RequestMethod } from '@axium/core/requests';
2
+ import type { Endpoint, RequestBody, Result, APIParameters } from '@axium/core/api';
3
+ export declare let token: string | null;
4
+ export declare function setToken(value: string | null): void;
5
+ export declare let prefix: string;
6
+ export declare function setPrefix(value: string): void;
7
+ export declare function fetchAPI<const M extends RequestMethod, const E extends Endpoint>(method: M, endpoint: E, data?: RequestBody<M, E>, ...params: APIParameters<E>): Promise<Result<M, E>>;
@@ -0,0 +1,40 @@
1
+ export let token = null;
2
+ export function setToken(value) {
3
+ token = value;
4
+ }
5
+ export let prefix = '/api/';
6
+ export function setPrefix(value) {
7
+ prefix = value;
8
+ }
9
+ export async function fetchAPI(method, endpoint, data, ...params) {
10
+ const options = {
11
+ method,
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ Accept: 'application/json',
15
+ },
16
+ };
17
+ if (method !== 'GET' && method !== 'HEAD')
18
+ options.body = JSON.stringify(data);
19
+ if (token)
20
+ options.headers.Authorization = 'Bearer ' + token;
21
+ const parts = [];
22
+ for (const part of endpoint.split('/')) {
23
+ if (!part.startsWith(':')) {
24
+ parts.push(part);
25
+ continue;
26
+ }
27
+ const value = params.shift();
28
+ if (!value)
29
+ throw new Error(`Missing parameter "${part.slice(1)}"`);
30
+ parts.push(value);
31
+ }
32
+ const response = await fetch(prefix + parts.join('/'), options);
33
+ if (!response.headers.get('Content-Type')?.includes('application/json')) {
34
+ throw new Error(`Unexpected response type: ${response.headers.get('Content-Type')}`);
35
+ }
36
+ const json = await response.json().catch(() => ({ message: 'Unknown server error (invalid JSON response)' }));
37
+ if (!response.ok)
38
+ throw new Error(json.message);
39
+ return json;
40
+ }
package/dist/user.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ import z from 'zod/v4';
2
+ import { type PasskeyChangeable } from '@axium/core';
3
+ export declare function login(userId: string): Promise<import("@axium/core").NewSessionResponse>;
4
+ /**
5
+ * Create an elevated session for the user to perform sensitive actions.
6
+ */
7
+ export declare function elevate(userId: string): Promise<void>;
8
+ export declare function loginByEmail(email: string): Promise<import("@axium/core").NewSessionResponse>;
9
+ export declare function getCurrentSession(): Promise<import("@axium/core").Session & {
10
+ user: import("@axium/core").User;
11
+ }>;
12
+ export declare function getSessions(userId: string): Promise<import("@axium/core").Session[]>;
13
+ export declare function logout(userId: string, ...sessionId: string[]): Promise<import("@axium/core").Session[]>;
14
+ export declare function logoutAll(userId: string): Promise<import("@axium/core").Session[]>;
15
+ export declare function logoutCurrentSession(): Promise<import("@axium/core").Session>;
16
+ export declare function register(_data: Record<string, FormDataEntryValue>): Promise<void>;
17
+ export declare function userInfo(userId: string): Promise<import("@axium/core").UserPublic & Partial<import("@axium/core").User>>;
18
+ export declare function updateUser(userId: string, data: Record<string, FormDataEntryValue>): Promise<import("@axium/core").User>;
19
+ export declare function fullUserInfo(userId: string): Promise<import("@axium/core").User & {
20
+ sessions: import("@axium/core").Session[];
21
+ }>;
22
+ export declare function deleteUser(userId: string): Promise<import("@axium/core").User>;
23
+ export declare function emailVerificationEnabled(userId: string): Promise<boolean>;
24
+ export declare function sendVerificationEmail(userId: string): Promise<import("@axium/core").Verification>;
25
+ export declare function verifyEmail(userId: string, token: string): Promise<{}>;
26
+ export declare function getPasskeys(userId: string): Promise<import("@axium/core").Passkey[]>;
27
+ /**
28
+ * Create a new passkey for an existing user.
29
+ */
30
+ export declare function createPasskey(userId: string): Promise<import("@axium/core").Passkey>;
31
+ export declare function updatePasskey(passkeyId: string, data: z.input<typeof PasskeyChangeable>): Promise<import("@axium/core").Passkey>;
32
+ export declare function deletePasskey(passkeyId: string): Promise<import("@axium/core").Passkey>;
package/dist/user.js ADDED
@@ -0,0 +1,145 @@
1
+ import { startAuthentication, startRegistration } from '@simplewebauthn/browser';
2
+ import z from 'zod/v4';
3
+ import { fetchAPI } from './requests.js';
4
+ import { UserChangeable } from '@axium/core';
5
+ export async function login(userId) {
6
+ const options = await fetchAPI('OPTIONS', 'users/:id/auth', { type: 'login' }, userId);
7
+ const response = await startAuthentication({ optionsJSON: options });
8
+ return await fetchAPI('POST', 'users/:id/auth', response, userId);
9
+ }
10
+ /**
11
+ * Create an elevated session for the user to perform sensitive actions.
12
+ */
13
+ export async function elevate(userId) {
14
+ const options = await fetchAPI('OPTIONS', 'users/:id/auth', { type: 'action' }, userId);
15
+ const response = await startAuthentication({ optionsJSON: options });
16
+ await fetchAPI('POST', 'users/:id/auth', response, userId);
17
+ }
18
+ export async function loginByEmail(email) {
19
+ const { id: userId } = await fetchAPI('POST', 'user_id', {
20
+ using: 'email',
21
+ value: email,
22
+ });
23
+ return await login(userId);
24
+ }
25
+ export async function getCurrentSession() {
26
+ const result = await fetchAPI('GET', 'session');
27
+ result.created = new Date(result.created);
28
+ result.expires = new Date(result.expires);
29
+ return result;
30
+ }
31
+ export async function getSessions(userId) {
32
+ _checkId(userId);
33
+ const result = await fetchAPI('GET', 'users/:id/sessions', {}, userId);
34
+ for (const session of result) {
35
+ session.created = new Date(session.created);
36
+ session.expires = new Date(session.expires);
37
+ }
38
+ return result;
39
+ }
40
+ export async function logout(userId, ...sessionId) {
41
+ _checkId(userId);
42
+ const result = await fetchAPI('DELETE', 'users/:id/sessions', { id: sessionId }, userId);
43
+ for (const session of result) {
44
+ session.created = new Date(session.created);
45
+ session.expires = new Date(session.expires);
46
+ }
47
+ return result;
48
+ }
49
+ export async function logoutAll(userId) {
50
+ _checkId(userId);
51
+ await elevate(userId);
52
+ const result = await fetchAPI('DELETE', 'users/:id/sessions', { confirm_all: true }, userId);
53
+ for (const session of result) {
54
+ session.created = new Date(session.created);
55
+ session.expires = new Date(session.expires);
56
+ }
57
+ return result;
58
+ }
59
+ export async function logoutCurrentSession() {
60
+ return await fetchAPI('DELETE', 'session');
61
+ }
62
+ export async function register(_data) {
63
+ const data = z.object({ name: z.string(), email: z.email() }).parse(_data);
64
+ const { options, userId } = await fetchAPI('OPTIONS', 'register', data);
65
+ const response = await startRegistration({ optionsJSON: options });
66
+ await fetchAPI('POST', 'register', {
67
+ userId,
68
+ name: data.name,
69
+ email: data.email,
70
+ response,
71
+ });
72
+ }
73
+ function _checkId(userId) {
74
+ try {
75
+ z.uuid().parse(userId);
76
+ }
77
+ catch (e) {
78
+ throw z.prettifyError(e);
79
+ }
80
+ }
81
+ export async function userInfo(userId) {
82
+ _checkId(userId);
83
+ return await fetchAPI('GET', 'users/:id', {}, userId);
84
+ }
85
+ export async function updateUser(userId, data) {
86
+ _checkId(userId);
87
+ const body = await UserChangeable.parseAsync(data).catch(e => {
88
+ throw z.prettifyError(e);
89
+ });
90
+ const result = await fetchAPI('PATCH', 'users/:id', body, userId);
91
+ if (result.emailVerified)
92
+ result.emailVerified = new Date(result.emailVerified);
93
+ return result;
94
+ }
95
+ export async function fullUserInfo(userId) {
96
+ _checkId(userId);
97
+ const result = await fetchAPI('GET', 'users/:id/full', {}, userId);
98
+ result.emailVerified = new Date(result.emailVerified);
99
+ return result;
100
+ }
101
+ export async function deleteUser(userId) {
102
+ _checkId(userId);
103
+ const options = await fetchAPI('OPTIONS', 'users/:id/auth', { type: 'action' }, userId);
104
+ const response = await startAuthentication({ optionsJSON: options });
105
+ await fetchAPI('POST', 'users/:id/auth', response, userId);
106
+ const result = await fetchAPI('DELETE', 'users/:id', response, userId);
107
+ result.emailVerified = new Date(result.emailVerified);
108
+ return result;
109
+ }
110
+ export async function emailVerificationEnabled(userId) {
111
+ _checkId(userId);
112
+ const { enabled } = await fetchAPI('OPTIONS', 'users/:id/verify_email', {}, userId);
113
+ return enabled;
114
+ }
115
+ export async function sendVerificationEmail(userId) {
116
+ _checkId(userId);
117
+ return await fetchAPI('GET', 'users/:id/verify_email', {}, userId);
118
+ }
119
+ export async function verifyEmail(userId, token) {
120
+ _checkId(userId);
121
+ return await fetchAPI('POST', 'users/:id/verify_email', { token }, userId);
122
+ }
123
+ export async function getPasskeys(userId) {
124
+ _checkId(userId);
125
+ const result = await fetchAPI('GET', 'users/:id/passkeys', {}, userId);
126
+ for (const passkey of result) {
127
+ passkey.createdAt = new Date(passkey.createdAt);
128
+ }
129
+ return result;
130
+ }
131
+ /**
132
+ * Create a new passkey for an existing user.
133
+ */
134
+ export async function createPasskey(userId) {
135
+ _checkId(userId);
136
+ const options = await fetchAPI('OPTIONS', 'users/:id/passkeys', {}, userId);
137
+ const response = await startRegistration({ optionsJSON: options });
138
+ return await fetchAPI('PUT', 'users/:id/passkeys', response, userId);
139
+ }
140
+ export async function updatePasskey(passkeyId, data) {
141
+ return await fetchAPI('PATCH', 'passkeys/:id', data, passkeyId);
142
+ }
143
+ export async function deletePasskey(passkeyId) {
144
+ return await fetchAPI('DELETE', 'passkeys/:id', {}, passkeyId);
145
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/client",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "author": "James Prevett <jp@jamespre.dev>",
5
5
  "funding": {
6
6
  "type": "individual",