@scell/sdk 1.0.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.
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Auth Resource
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ import type { HttpClient, RequestOptions } from '../client.js';
8
+ import type { MessageResponse, SingleResponse } from '../types/common.js';
9
+ import type {
10
+ AuthResponse,
11
+ ForgotPasswordInput,
12
+ LoginCredentials,
13
+ RegisterInput,
14
+ ResetPasswordInput,
15
+ User,
16
+ } from '../types/auth.js';
17
+
18
+ /**
19
+ * Auth API resource
20
+ *
21
+ * Note: Most auth endpoints are only used during initial setup.
22
+ * After login, use the returned token to create a ScellClient.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // Login and get token
27
+ * const auth = await ScellAuth.login({
28
+ * email: 'user@example.com',
29
+ * password: 'password'
30
+ * });
31
+ *
32
+ * // Create client with token
33
+ * const client = new ScellClient(auth.token);
34
+ *
35
+ * // Get current user
36
+ * const user = await client.auth.me();
37
+ * ```
38
+ */
39
+ export class AuthResource {
40
+ constructor(private readonly http: HttpClient) {}
41
+
42
+ /**
43
+ * Get current authenticated user
44
+ *
45
+ * @param requestOptions - Request options
46
+ * @returns Current user details
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const { data: user } = await client.auth.me();
51
+ * console.log(`Logged in as: ${user.name} (${user.email})`);
52
+ * ```
53
+ */
54
+ async me(requestOptions?: RequestOptions): Promise<SingleResponse<User>> {
55
+ return this.http.get<SingleResponse<User>>(
56
+ '/auth/me',
57
+ undefined,
58
+ requestOptions
59
+ );
60
+ }
61
+
62
+ /**
63
+ * Logout (revoke current token)
64
+ *
65
+ * @param requestOptions - Request options
66
+ * @returns Logout confirmation
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * await client.auth.logout();
71
+ * // Token is now invalid
72
+ * ```
73
+ */
74
+ async logout(requestOptions?: RequestOptions): Promise<MessageResponse> {
75
+ return this.http.post<MessageResponse>(
76
+ '/auth/logout',
77
+ undefined,
78
+ requestOptions
79
+ );
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Static auth methods (don't require authentication)
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * import { ScellAuth } from '@scell/sdk';
89
+ *
90
+ * // Register new user
91
+ * const auth = await ScellAuth.register({
92
+ * name: 'John Doe',
93
+ * email: 'john@example.com',
94
+ * password: 'securepassword123',
95
+ * password_confirmation: 'securepassword123'
96
+ * });
97
+ *
98
+ * // Login existing user
99
+ * const auth = await ScellAuth.login({
100
+ * email: 'john@example.com',
101
+ * password: 'securepassword123'
102
+ * });
103
+ *
104
+ * // Use the token
105
+ * const client = new ScellClient(auth.token);
106
+ * ```
107
+ */
108
+ export const ScellAuth = {
109
+ /**
110
+ * Default base URL for auth requests
111
+ */
112
+ baseUrl: 'https://api.scell.io/api/v1',
113
+
114
+ /**
115
+ * Register a new user
116
+ *
117
+ * @param input - Registration data
118
+ * @param baseUrl - Optional base URL override
119
+ * @returns Auth response with token
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const auth = await ScellAuth.register({
124
+ * name: 'Jane Doe',
125
+ * email: 'jane@example.com',
126
+ * password: 'MySecurePassword123!',
127
+ * password_confirmation: 'MySecurePassword123!'
128
+ * });
129
+ *
130
+ * console.log('Welcome,', auth.user.name);
131
+ * const client = new ScellClient(auth.token);
132
+ * ```
133
+ */
134
+ async register(
135
+ input: RegisterInput,
136
+ baseUrl?: string
137
+ ): Promise<AuthResponse> {
138
+ const url = `${baseUrl ?? this.baseUrl}/auth/register`;
139
+
140
+ const response = await fetch(url, {
141
+ method: 'POST',
142
+ headers: {
143
+ 'Content-Type': 'application/json',
144
+ Accept: 'application/json',
145
+ },
146
+ body: JSON.stringify(input),
147
+ });
148
+
149
+ const body = await response.json();
150
+
151
+ if (!response.ok) {
152
+ const { parseApiError } = await import('../errors.js');
153
+ parseApiError(response.status, body, response.headers);
154
+ }
155
+
156
+ return body as AuthResponse;
157
+ },
158
+
159
+ /**
160
+ * Login an existing user
161
+ *
162
+ * @param credentials - Login credentials
163
+ * @param baseUrl - Optional base URL override
164
+ * @returns Auth response with token
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const auth = await ScellAuth.login({
169
+ * email: 'user@example.com',
170
+ * password: 'password'
171
+ * });
172
+ *
173
+ * // Store the token securely
174
+ * localStorage.setItem('scell_token', auth.token);
175
+ *
176
+ * // Create client
177
+ * const client = new ScellClient(auth.token);
178
+ * ```
179
+ */
180
+ async login(
181
+ credentials: LoginCredentials,
182
+ baseUrl?: string
183
+ ): Promise<AuthResponse> {
184
+ const url = `${baseUrl ?? this.baseUrl}/auth/login`;
185
+
186
+ const response = await fetch(url, {
187
+ method: 'POST',
188
+ headers: {
189
+ 'Content-Type': 'application/json',
190
+ Accept: 'application/json',
191
+ },
192
+ body: JSON.stringify(credentials),
193
+ });
194
+
195
+ const body = await response.json();
196
+
197
+ if (!response.ok) {
198
+ const { parseApiError } = await import('../errors.js');
199
+ parseApiError(response.status, body, response.headers);
200
+ }
201
+
202
+ return body as AuthResponse;
203
+ },
204
+
205
+ /**
206
+ * Request password reset email
207
+ *
208
+ * @param input - Email address
209
+ * @param baseUrl - Optional base URL override
210
+ * @returns Confirmation message
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * await ScellAuth.forgotPassword({
215
+ * email: 'user@example.com'
216
+ * });
217
+ * console.log('Check your email for reset link');
218
+ * ```
219
+ */
220
+ async forgotPassword(
221
+ input: ForgotPasswordInput,
222
+ baseUrl?: string
223
+ ): Promise<MessageResponse> {
224
+ const url = `${baseUrl ?? this.baseUrl}/auth/forgot-password`;
225
+
226
+ const response = await fetch(url, {
227
+ method: 'POST',
228
+ headers: {
229
+ 'Content-Type': 'application/json',
230
+ Accept: 'application/json',
231
+ },
232
+ body: JSON.stringify(input),
233
+ });
234
+
235
+ const body = await response.json();
236
+
237
+ if (!response.ok) {
238
+ const { parseApiError } = await import('../errors.js');
239
+ parseApiError(response.status, body, response.headers);
240
+ }
241
+
242
+ return body as MessageResponse;
243
+ },
244
+
245
+ /**
246
+ * Reset password with token from email
247
+ *
248
+ * @param input - Reset password data
249
+ * @param baseUrl - Optional base URL override
250
+ * @returns Confirmation message
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * await ScellAuth.resetPassword({
255
+ * email: 'user@example.com',
256
+ * token: 'reset-token-from-email',
257
+ * password: 'NewSecurePassword123!',
258
+ * password_confirmation: 'NewSecurePassword123!'
259
+ * });
260
+ * ```
261
+ */
262
+ async resetPassword(
263
+ input: ResetPasswordInput,
264
+ baseUrl?: string
265
+ ): Promise<MessageResponse> {
266
+ const url = `${baseUrl ?? this.baseUrl}/auth/reset-password`;
267
+
268
+ const response = await fetch(url, {
269
+ method: 'POST',
270
+ headers: {
271
+ 'Content-Type': 'application/json',
272
+ Accept: 'application/json',
273
+ },
274
+ body: JSON.stringify(input),
275
+ });
276
+
277
+ const body = await response.json();
278
+
279
+ if (!response.ok) {
280
+ const { parseApiError } = await import('../errors.js');
281
+ parseApiError(response.status, body, response.headers);
282
+ }
283
+
284
+ return body as MessageResponse;
285
+ },
286
+ };
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Balance Resource
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ import type { HttpClient, RequestOptions } from '../client.js';
8
+ import type {
9
+ MessageWithDataResponse,
10
+ PaginatedResponse,
11
+ SingleResponse,
12
+ } from '../types/common.js';
13
+ import type {
14
+ Balance,
15
+ ReloadBalanceInput,
16
+ ReloadBalanceResponse,
17
+ Transaction,
18
+ TransactionListOptions,
19
+ UpdateBalanceSettingsInput,
20
+ } from '../types/balance.js';
21
+
22
+ /**
23
+ * Balance API resource
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Check balance
28
+ * const balance = await client.balance.get();
29
+ * console.log(`Current balance: ${balance.amount} ${balance.currency}`);
30
+ *
31
+ * // Reload balance
32
+ * await client.balance.reload({ amount: 100 });
33
+ *
34
+ * // View transactions
35
+ * const transactions = await client.balance.transactions({
36
+ * type: 'debit',
37
+ * service: 'invoice'
38
+ * });
39
+ * ```
40
+ */
41
+ export class BalanceResource {
42
+ constructor(private readonly http: HttpClient) {}
43
+
44
+ /**
45
+ * Get current balance and settings
46
+ *
47
+ * @param requestOptions - Request options
48
+ * @returns Current balance details
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const { data: balance } = await client.balance.get();
53
+ * console.log(`Balance: ${balance.amount} ${balance.currency}`);
54
+ *
55
+ * if (balance.amount < balance.low_balance_alert_threshold) {
56
+ * console.log('Warning: Low balance!');
57
+ * }
58
+ * ```
59
+ */
60
+ async get(requestOptions?: RequestOptions): Promise<SingleResponse<Balance>> {
61
+ return this.http.get<SingleResponse<Balance>>(
62
+ '/balance',
63
+ undefined,
64
+ requestOptions
65
+ );
66
+ }
67
+
68
+ /**
69
+ * Reload balance
70
+ *
71
+ * Note: This is a simulation endpoint. In production, use Stripe integration.
72
+ *
73
+ * @param input - Reload amount (10-10000 EUR)
74
+ * @param requestOptions - Request options
75
+ * @returns Reload transaction details
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const { transaction } = await client.balance.reload({ amount: 100 });
80
+ * console.log(`New balance: ${transaction.balance_after}`);
81
+ * ```
82
+ */
83
+ async reload(
84
+ input: ReloadBalanceInput,
85
+ requestOptions?: RequestOptions
86
+ ): Promise<ReloadBalanceResponse> {
87
+ return this.http.post<ReloadBalanceResponse>(
88
+ '/balance/reload',
89
+ input,
90
+ requestOptions
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Update balance settings
96
+ *
97
+ * Configure auto-reload and alert thresholds.
98
+ *
99
+ * @param input - Settings to update
100
+ * @param requestOptions - Request options
101
+ * @returns Updated settings
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * await client.balance.updateSettings({
106
+ * auto_reload_enabled: true,
107
+ * auto_reload_threshold: 50,
108
+ * auto_reload_amount: 200,
109
+ * low_balance_alert_threshold: 100,
110
+ * critical_balance_alert_threshold: 25
111
+ * });
112
+ * ```
113
+ */
114
+ async updateSettings(
115
+ input: UpdateBalanceSettingsInput,
116
+ requestOptions?: RequestOptions
117
+ ): Promise<MessageWithDataResponse<Partial<Balance>>> {
118
+ return this.http.put<MessageWithDataResponse<Partial<Balance>>>(
119
+ '/balance/settings',
120
+ input,
121
+ requestOptions
122
+ );
123
+ }
124
+
125
+ /**
126
+ * List balance transactions
127
+ *
128
+ * @param options - Filter and pagination options
129
+ * @param requestOptions - Request options
130
+ * @returns Paginated list of transactions
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * // List all invoice debits
135
+ * const { data, meta } = await client.balance.transactions({
136
+ * type: 'debit',
137
+ * service: 'invoice',
138
+ * from: '2024-01-01',
139
+ * to: '2024-01-31'
140
+ * });
141
+ *
142
+ * data.forEach(tx => {
143
+ * console.log(`${tx.description}: -${tx.amount} EUR`);
144
+ * });
145
+ * ```
146
+ */
147
+ async transactions(
148
+ options: TransactionListOptions = {},
149
+ requestOptions?: RequestOptions
150
+ ): Promise<PaginatedResponse<Transaction>> {
151
+ return this.http.get<PaginatedResponse<Transaction>>(
152
+ '/balance/transactions',
153
+ options as Record<string, string | number | boolean | undefined>,
154
+ requestOptions
155
+ );
156
+ }
157
+ }
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Companies Resource
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ import type { HttpClient, RequestOptions } from '../client.js';
8
+ import type {
9
+ MessageResponse,
10
+ MessageWithDataResponse,
11
+ SingleResponse,
12
+ } from '../types/common.js';
13
+ import type {
14
+ Company,
15
+ CreateCompanyInput,
16
+ KycInitiateResponse,
17
+ KycStatusResponse,
18
+ UpdateCompanyInput,
19
+ } from '../types/companies.js';
20
+
21
+ /**
22
+ * Companies API resource
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // Create a company
27
+ * const company = await client.companies.create({
28
+ * name: 'My Company',
29
+ * siret: '12345678901234',
30
+ * address_line1: '1 Rue de la Paix',
31
+ * postal_code: '75001',
32
+ * city: 'Paris'
33
+ * });
34
+ *
35
+ * // Initiate KYC
36
+ * const kyc = await client.companies.initiateKyc(company.id);
37
+ * console.log('KYC URL:', kyc.redirect_url);
38
+ * ```
39
+ */
40
+ export class CompaniesResource {
41
+ constructor(private readonly http: HttpClient) {}
42
+
43
+ /**
44
+ * List all companies for the authenticated user
45
+ *
46
+ * @param requestOptions - Request options
47
+ * @returns List of companies
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const { data: companies } = await client.companies.list();
52
+ * companies.forEach(c => console.log(c.name, c.status));
53
+ * ```
54
+ */
55
+ async list(
56
+ requestOptions?: RequestOptions
57
+ ): Promise<{ data: Company[] }> {
58
+ return this.http.get<{ data: Company[] }>(
59
+ '/companies',
60
+ undefined,
61
+ requestOptions
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Get a specific company by ID
67
+ *
68
+ * @param id - Company UUID
69
+ * @param requestOptions - Request options
70
+ * @returns Company details
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const { data: company } = await client.companies.get('uuid');
75
+ * console.log(company.name, company.siret);
76
+ * ```
77
+ */
78
+ async get(
79
+ id: string,
80
+ requestOptions?: RequestOptions
81
+ ): Promise<SingleResponse<Company>> {
82
+ return this.http.get<SingleResponse<Company>>(
83
+ `/companies/${id}`,
84
+ undefined,
85
+ requestOptions
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Create a new company
91
+ *
92
+ * @param input - Company creation data
93
+ * @param requestOptions - Request options
94
+ * @returns Created company
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const { data: company } = await client.companies.create({
99
+ * name: 'Acme Corp',
100
+ * siret: '12345678901234',
101
+ * vat_number: 'FR12345678901',
102
+ * legal_form: 'SAS',
103
+ * address_line1: '123 Business Street',
104
+ * postal_code: '75001',
105
+ * city: 'Paris',
106
+ * country: 'FR',
107
+ * email: 'contact@acme.com',
108
+ * phone: '+33 1 23 45 67 89'
109
+ * });
110
+ * ```
111
+ */
112
+ async create(
113
+ input: CreateCompanyInput,
114
+ requestOptions?: RequestOptions
115
+ ): Promise<MessageWithDataResponse<Company>> {
116
+ return this.http.post<MessageWithDataResponse<Company>>(
117
+ '/companies',
118
+ input,
119
+ requestOptions
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Update a company
125
+ *
126
+ * @param id - Company UUID
127
+ * @param input - Fields to update
128
+ * @param requestOptions - Request options
129
+ * @returns Updated company
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const { data: company } = await client.companies.update('uuid', {
134
+ * email: 'new-email@acme.com',
135
+ * phone: '+33 1 98 76 54 32'
136
+ * });
137
+ * ```
138
+ */
139
+ async update(
140
+ id: string,
141
+ input: UpdateCompanyInput,
142
+ requestOptions?: RequestOptions
143
+ ): Promise<MessageWithDataResponse<Company>> {
144
+ return this.http.put<MessageWithDataResponse<Company>>(
145
+ `/companies/${id}`,
146
+ input,
147
+ requestOptions
148
+ );
149
+ }
150
+
151
+ /**
152
+ * Delete a company
153
+ *
154
+ * @param id - Company UUID
155
+ * @param requestOptions - Request options
156
+ * @returns Deletion confirmation
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * await client.companies.delete('company-uuid');
161
+ * ```
162
+ */
163
+ async delete(
164
+ id: string,
165
+ requestOptions?: RequestOptions
166
+ ): Promise<MessageResponse> {
167
+ return this.http.delete<MessageResponse>(
168
+ `/companies/${id}`,
169
+ requestOptions
170
+ );
171
+ }
172
+
173
+ /**
174
+ * Initiate KYC verification for a company
175
+ *
176
+ * @param id - Company UUID
177
+ * @param requestOptions - Request options
178
+ * @returns KYC reference and redirect URL
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const { kyc_reference, redirect_url } = await client.companies.initiateKyc(
183
+ * 'company-uuid'
184
+ * );
185
+ * // Redirect user to redirect_url for KYC verification
186
+ * ```
187
+ */
188
+ async initiateKyc(
189
+ id: string,
190
+ requestOptions?: RequestOptions
191
+ ): Promise<KycInitiateResponse> {
192
+ return this.http.post<KycInitiateResponse>(
193
+ `/companies/${id}/kyc`,
194
+ undefined,
195
+ requestOptions
196
+ );
197
+ }
198
+
199
+ /**
200
+ * Get KYC verification status
201
+ *
202
+ * @param id - Company UUID
203
+ * @param requestOptions - Request options
204
+ * @returns Current KYC status
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const status = await client.companies.kycStatus('company-uuid');
209
+ * if (status.status === 'active') {
210
+ * console.log('KYC completed at:', status.kyc_completed_at);
211
+ * }
212
+ * ```
213
+ */
214
+ async kycStatus(
215
+ id: string,
216
+ requestOptions?: RequestOptions
217
+ ): Promise<KycStatusResponse> {
218
+ return this.http.get<KycStatusResponse>(
219
+ `/companies/${id}/kyc/status`,
220
+ undefined,
221
+ requestOptions
222
+ );
223
+ }
224
+ }