@tekcify/auth-backend 1.0.0 → 1.0.3

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.
Files changed (56) hide show
  1. package/README.md +414 -22
  2. package/dist/application-management.d.ts +62 -0
  3. package/dist/application-management.d.ts.map +1 -0
  4. package/dist/application-management.js +133 -0
  5. package/dist/application-management.js.map +1 -0
  6. package/{src/express/index.ts → dist/express/index.d.ts} +1 -0
  7. package/dist/express/index.d.ts.map +1 -0
  8. package/dist/express/index.js +6 -0
  9. package/dist/express/index.js.map +1 -0
  10. package/dist/express/middleware.d.ts +16 -0
  11. package/dist/express/middleware.d.ts.map +1 -0
  12. package/dist/express/middleware.js +39 -0
  13. package/dist/express/middleware.js.map +1 -0
  14. package/{src/index.ts → dist/index.d.ts} +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +24 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/nestjs/decorator.d.ts +2 -0
  19. package/dist/nestjs/decorator.d.ts.map +1 -0
  20. package/dist/nestjs/decorator.js +11 -0
  21. package/dist/nestjs/decorator.js.map +1 -0
  22. package/dist/nestjs/guard.d.ts +13 -0
  23. package/dist/nestjs/guard.d.ts.map +1 -0
  24. package/dist/nestjs/guard.js +56 -0
  25. package/dist/nestjs/guard.js.map +1 -0
  26. package/{src/nestjs/index.ts → dist/nestjs/index.d.ts} +1 -0
  27. package/dist/nestjs/index.d.ts.map +1 -0
  28. package/dist/nestjs/index.js +8 -0
  29. package/dist/nestjs/index.js.map +1 -0
  30. package/dist/types.d.ts +22 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +3 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/user-profile.d.ts +18 -0
  35. package/dist/user-profile.d.ts.map +1 -0
  36. package/dist/user-profile.js +78 -0
  37. package/dist/user-profile.js.map +1 -0
  38. package/dist/userinfo.d.ts +9 -0
  39. package/dist/userinfo.d.ts.map +1 -0
  40. package/dist/userinfo.js +16 -0
  41. package/dist/userinfo.js.map +1 -0
  42. package/dist/verify.d.ts +4 -0
  43. package/dist/verify.d.ts.map +1 -0
  44. package/dist/verify.js +38 -0
  45. package/dist/verify.js.map +1 -0
  46. package/package.json +13 -10
  47. package/src/__tests__/verify.test.ts +0 -80
  48. package/src/express/middleware.ts +0 -61
  49. package/src/nestjs/decorator.ts +0 -12
  50. package/src/nestjs/guard.ts +0 -57
  51. package/src/types.ts +0 -24
  52. package/src/userinfo.ts +0 -26
  53. package/src/verify.ts +0 -36
  54. package/tsconfig.json +0 -11
  55. package/tsconfig.tsbuildinfo +0 -1
  56. package/vitest.config.ts +0 -9
package/README.md CHANGED
@@ -28,9 +28,16 @@ You need the JWT access secret from your Tekcify Auth server. This should match
28
28
 
29
29
  ```env
30
30
  JWT_ACCESS_SECRET=your-jwt-access-secret-here
31
- AUTH_SERVER_URL=http://localhost:7001
32
31
  ```
33
32
 
33
+ **Note:** The auth server URL is centralized in `@tekcify/auth-core-client` package as `AUTH_SERVER_URL` (default: `http://localhost:7001`, override with `AUTH_SERVER_URL` env). Functions that communicate with the auth server use this constant automatically.
34
+
35
+ ## Auth Server Endpoints Used
36
+
37
+ - Base prefix: `/api`
38
+ - User profile: `GET/PUT /api/user/profile`, `POST /api/user/profile/picture`
39
+ - Applications: `GET/POST /api/applications`, `GET /api/applications/public/:clientId`, `PUT/DELETE /api/applications/:clientId`, `POST /api/applications/:clientId/logo`
40
+
34
41
  ## NestJS Integration
35
42
 
36
43
  ### Step 1: Install Dependencies
@@ -255,7 +262,7 @@ import { introspectToken } from '@tekcify/auth-core-client';
255
262
 
256
263
  const token = req.headers.authorization?.replace('Bearer ', '');
257
264
 
258
- const result = await introspectToken(process.env.AUTH_SERVER_URL!, {
265
+ const result = await introspectToken({
259
266
  token: token!,
260
267
  clientId: process.env.CLIENT_ID,
261
268
  clientSecret: process.env.CLIENT_SECRET,
@@ -277,16 +284,159 @@ Fetch user information from the auth server:
277
284
  ```typescript
278
285
  import { fetchUserInfo } from '@tekcify/auth-backend';
279
286
 
280
- const userInfo = await fetchUserInfo(
281
- process.env.AUTH_SERVER_URL!,
282
- accessToken
283
- );
287
+ const userInfo = await fetchUserInfo(accessToken);
284
288
 
285
289
  console.log('Email:', userInfo.email);
286
290
  console.log('Name:', userInfo.name);
287
291
  console.log('Verified:', userInfo.email_verified);
288
292
  ```
289
293
 
294
+ ## User Profile Management
295
+
296
+ Manage user profiles with simple function calls:
297
+
298
+ ### Get User Profile
299
+
300
+ ```typescript
301
+ import { getUserProfile } from '@tekcify/auth-backend';
302
+
303
+ const profile = await getUserProfile(accessToken);
304
+
305
+ console.log('User ID:', profile.userId);
306
+ console.log('Email:', profile.email);
307
+ console.log('Name:', profile.firstName, profile.lastName);
308
+ console.log('Avatar:', profile.avatarUrl);
309
+ ```
310
+
311
+ ### Update User Profile
312
+
313
+ ```typescript
314
+ import { updateUserProfile } from '@tekcify/auth-backend';
315
+
316
+ const updatedProfile = await updateUserProfile(accessToken, {
317
+ firstName: 'John',
318
+ lastName: 'Doe',
319
+ });
320
+
321
+ console.log('Profile updated:', updatedProfile);
322
+ ```
323
+
324
+ ### Upload Profile Picture
325
+
326
+ ```typescript
327
+ import { uploadProfilePicture } from '@tekcify/auth-backend';
328
+
329
+ // Browser (with File object)
330
+ const fileInput = document.querySelector<HTMLInputElement>('#profilePic');
331
+ const file = fileInput?.files?.[0];
332
+
333
+ if (file) {
334
+ const result = await uploadProfilePicture(accessToken, file);
335
+ console.log('New avatar URL:', result.avatarUrl);
336
+ }
337
+
338
+ // Node.js (with Buffer)
339
+ import fs from 'fs';
340
+
341
+ const fileBuffer = fs.readFileSync('./avatar.jpg');
342
+ const result = await uploadProfilePicture(accessToken, fileBuffer, 'avatar.jpg');
343
+ console.log('New avatar URL:', result.avatarUrl);
344
+ ```
345
+
346
+ ## Application Management
347
+
348
+ Manage OAuth applications with simple function calls:
349
+
350
+ ### List Applications
351
+
352
+ ```typescript
353
+ import { listApplications } from '@tekcify/auth-backend';
354
+
355
+ const apps = await listApplications(accessToken);
356
+
357
+ apps.forEach(app => {
358
+ console.log('App:', app.name);
359
+ console.log('Client ID:', app.clientId);
360
+ console.log('Logo:', app.logoUrl);
361
+ });
362
+ ```
363
+
364
+ ### Get Application by Client ID
365
+
366
+ ```typescript
367
+ import { getApplicationByClientId } from '@tekcify/auth-backend';
368
+
369
+ // Public endpoint - no auth required
370
+ const app = await getApplicationByClientId('your-client-id');
371
+
372
+ console.log('App Name:', app.name);
373
+ console.log('Scopes:', app.scopes);
374
+ ```
375
+
376
+ ### Create Application
377
+
378
+ ```typescript
379
+ import { createApplication } from '@tekcify/auth-backend';
380
+
381
+ const newApp = await createApplication(accessToken, {
382
+ name: 'My Cool App',
383
+ description: 'An awesome application',
384
+ redirectUris: ['https://myapp.com/callback'],
385
+ authorizedOrigins: ['https://myapp.com'],
386
+ scopes: ['read:profile', 'write:profile'],
387
+ });
388
+
389
+ console.log('Client ID:', newApp.clientId);
390
+ console.log('Client Secret:', newApp.clientSecret); // Save this securely!
391
+ ```
392
+
393
+ ### Update Application
394
+
395
+ ```typescript
396
+ import { updateApplication } from '@tekcify/auth-backend';
397
+
398
+ await updateApplication(accessToken, 'your-client-id', {
399
+ name: 'Updated App Name',
400
+ description: 'New description',
401
+ });
402
+
403
+ console.log('Application updated');
404
+ ```
405
+
406
+ ### Upload Application Logo
407
+
408
+ ```typescript
409
+ import { uploadApplicationLogo } from '@tekcify/auth-backend';
410
+
411
+ // Browser
412
+ const logoFile = document.querySelector<HTMLInputElement>('#logo')?.files?.[0];
413
+ if (logoFile) {
414
+ const result = await uploadApplicationLogo(accessToken, 'your-client-id', logoFile);
415
+ console.log('New logo URL:', result.logoUrl);
416
+ }
417
+
418
+ // Node.js
419
+ import fs from 'fs';
420
+
421
+ const logoBuffer = fs.readFileSync('./logo.png');
422
+ const result = await uploadApplicationLogo(
423
+ accessToken,
424
+ 'your-client-id',
425
+ logoBuffer,
426
+ 'logo.png'
427
+ );
428
+ console.log('New logo URL:', result.logoUrl);
429
+ ```
430
+
431
+ ### Delete Application
432
+
433
+ ```typescript
434
+ import { deleteApplication } from '@tekcify/auth-backend';
435
+
436
+ await deleteApplication(accessToken, 'your-client-id');
437
+ console.log('Application deleted');
438
+ ```
439
+
290
440
  ## Complete NestJS Example
291
441
 
292
442
  ```typescript
@@ -335,7 +485,7 @@ export class ApiController {
335
485
 
336
486
  ```typescript
337
487
  import express from 'express';
338
- import { createAuthMiddleware } from '@tekcify/auth-backend/express';
488
+ import { createAuthMiddleware, getUserProfile, updateUserProfile } from '@tekcify/auth-backend';
339
489
 
340
490
  const app = express();
341
491
  app.use(express.json());
@@ -354,17 +504,24 @@ app.get('/health', (req, res) => {
354
504
  // Protected routes
355
505
  app.use('/api', authMiddleware);
356
506
 
357
- app.get('/api/profile', (req, res) => {
358
- res.json({
359
- userId: req.user!.userId,
360
- email: req.user!.email,
361
- scopes: req.user!.scopes,
362
- });
507
+ app.get('/api/profile', async (req, res) => {
508
+ try {
509
+ const accessToken = req.headers.authorization?.replace('Bearer ', '');
510
+ const profile = await getUserProfile(accessToken!);
511
+ res.json(profile);
512
+ } catch (error) {
513
+ res.status(500).json({ error: error.message });
514
+ }
363
515
  });
364
516
 
365
- app.get('/api/data', async (req, res) => {
366
- const data = await fetchDataForUser(req.user!.userId);
367
- res.json(data);
517
+ app.put('/api/profile', async (req, res) => {
518
+ try {
519
+ const accessToken = req.headers.authorization?.replace('Bearer ', '');
520
+ const updated = await updateUserProfile(accessToken!, req.body);
521
+ res.json(updated);
522
+ } catch (error) {
523
+ res.status(500).json({ error: error.message });
524
+ }
368
525
  });
369
526
 
370
527
  app.listen(3000, () => {
@@ -372,6 +529,93 @@ app.listen(3000, () => {
372
529
  });
373
530
  ```
374
531
 
532
+ ## Complete Integration Example
533
+
534
+ Here's a complete example showing authentication, profile management, and application management:
535
+
536
+ ```typescript
537
+ import {
538
+ OAuthClient,
539
+ generateCodeVerifier,
540
+ generateCodeChallenge,
541
+ } from '@tekcify/auth-core-client';
542
+
543
+ import {
544
+ getUserProfile,
545
+ updateUserProfile,
546
+ uploadProfilePicture,
547
+ listApplications,
548
+ createApplication,
549
+ uploadApplicationLogo,
550
+ } from '@tekcify/auth-backend';
551
+
552
+ // Step 1: Authenticate user (using OAuth flow)
553
+ const oauthClient = new OAuthClient({
554
+ clientId: 'your-client-id',
555
+ clientSecret: 'your-client-secret',
556
+ redirectUri: 'https://yourapp.com/callback',
557
+ scopes: ['read:profile', 'write:profile'],
558
+ });
559
+
560
+ // Generate PKCE parameters
561
+ const verifier = generateCodeVerifier();
562
+ const challenge = await generateCodeChallenge(verifier, 'S256');
563
+
564
+ // Build auth URL and redirect user
565
+ const authUrl = await oauthClient.buildAuthorizeUrl({
566
+ state: crypto.randomUUID(),
567
+ codeChallenge: challenge,
568
+ codeChallengeMethod: 'S256',
569
+ });
570
+
571
+ // After callback, exchange code for tokens
572
+ const tokens = await oauthClient.exchangeCode(code, verifier);
573
+ const accessToken = tokens.accessToken;
574
+
575
+ // Step 2: Manage user profile
576
+ const profile = await getUserProfile(accessToken);
577
+ console.log('Current profile:', profile);
578
+
579
+ // Update profile
580
+ const updated = await updateUserProfile(accessToken, {
581
+ firstName: 'John',
582
+ lastName: 'Doe',
583
+ });
584
+ console.log('Updated profile:', updated);
585
+
586
+ // Upload profile picture (browser)
587
+ const fileInput = document.querySelector<HTMLInputElement>('#profilePic');
588
+ if (fileInput?.files?.[0]) {
589
+ const result = await uploadProfilePicture(accessToken, fileInput.files[0]);
590
+ console.log('New avatar URL:', result.avatarUrl);
591
+ }
592
+
593
+ // Step 3: Manage applications
594
+ const apps = await listApplications(accessToken);
595
+ console.log('My applications:', apps);
596
+
597
+ // Create new application
598
+ const newApp = await createApplication(accessToken, {
599
+ name: 'My New App',
600
+ description: 'A cool application',
601
+ redirectUris: ['https://myapp.com/callback'],
602
+ scopes: ['read:profile'],
603
+ });
604
+ console.log('Created app:', newApp.clientId);
605
+ console.log('Client secret (save this!):', newApp.clientSecret);
606
+
607
+ // Upload application logo
608
+ const logoInput = document.querySelector<HTMLInputElement>('#logo');
609
+ if (logoInput?.files?.[0]) {
610
+ const logoResult = await uploadApplicationLogo(
611
+ accessToken,
612
+ newApp.clientId,
613
+ logoInput.files[0]
614
+ );
615
+ console.log('Logo uploaded:', logoResult.logoUrl);
616
+ }
617
+ ```
618
+
375
619
  ## API Reference
376
620
 
377
621
  ### NestJS
@@ -412,6 +656,104 @@ createAuthMiddleware({
412
656
  })
413
657
  ```
414
658
 
659
+ ### User Profile Functions
660
+
661
+ #### `getUserProfile(accessToken)`
662
+
663
+ Get the authenticated user's profile.
664
+
665
+ ```typescript
666
+ getUserProfile(accessToken: string): Promise<UserProfile>
667
+ ```
668
+
669
+ #### `updateUserProfile(accessToken, data)`
670
+
671
+ Update the user's profile information.
672
+
673
+ ```typescript
674
+ updateUserProfile(
675
+ accessToken: string,
676
+ data: UpdateProfileDto
677
+ ): Promise<UserProfile>
678
+ ```
679
+
680
+ #### `uploadProfilePicture(accessToken, file, fileName?)`
681
+
682
+ Upload a profile picture. Works with both File (browser) and Buffer (Node.js).
683
+
684
+ ```typescript
685
+ uploadProfilePicture(
686
+ accessToken: string,
687
+ file: File | Buffer,
688
+ fileName?: string
689
+ ): Promise<UploadResponse>
690
+ ```
691
+
692
+ ### Application Management Functions
693
+
694
+ #### `listApplications(accessToken)`
695
+
696
+ Get all applications owned by the authenticated user.
697
+
698
+ ```typescript
699
+ listApplications(accessToken: string): Promise<Application[]>
700
+ ```
701
+
702
+ #### `getApplicationByClientId(clientId)`
703
+
704
+ Get public application information (no auth required).
705
+
706
+ ```typescript
707
+ getApplicationByClientId(clientId: string): Promise<Application>
708
+ ```
709
+
710
+ #### `createApplication(accessToken, data)`
711
+
712
+ Create a new OAuth application.
713
+
714
+ ```typescript
715
+ createApplication(
716
+ accessToken: string,
717
+ data: CreateApplicationDto
718
+ ): Promise<CreateApplicationResponse>
719
+ ```
720
+
721
+ #### `updateApplication(accessToken, clientId, data)`
722
+
723
+ Update an existing application.
724
+
725
+ ```typescript
726
+ updateApplication(
727
+ accessToken: string,
728
+ clientId: string,
729
+ data: UpdateApplicationDto
730
+ ): Promise<{ message: string }>
731
+ ```
732
+
733
+ #### `uploadApplicationLogo(accessToken, clientId, file, fileName?)`
734
+
735
+ Upload an application logo. Works with both File (browser) and Buffer (Node.js).
736
+
737
+ ```typescript
738
+ uploadApplicationLogo(
739
+ accessToken: string,
740
+ clientId: string,
741
+ file: File | Buffer,
742
+ fileName?: string
743
+ ): Promise<LogoUploadResponse>
744
+ ```
745
+
746
+ #### `deleteApplication(accessToken, clientId)`
747
+
748
+ Delete an application.
749
+
750
+ ```typescript
751
+ deleteApplication(
752
+ accessToken: string,
753
+ clientId: string
754
+ ): Promise<{ message: string }>
755
+ ```
756
+
415
757
  ### Utilities
416
758
 
417
759
  #### `verifyAccessToken(token, options)`
@@ -426,15 +768,12 @@ verifyAccessToken(token: string, {
426
768
  }): VerifiedToken
427
769
  ```
428
770
 
429
- #### `fetchUserInfo(authServerUrl, accessToken)`
771
+ #### `fetchUserInfo(accessToken)`
430
772
 
431
- Fetches user information from the auth server.
773
+ Fetches user information from the Tekcify auth server using the centralized `AUTH_SERVER_URL`.
432
774
 
433
775
  ```typescript
434
- fetchUserInfo(
435
- authServerUrl: string,
436
- accessToken: string
437
- ): Promise<UserInfo>
776
+ fetchUserInfo(accessToken: string): Promise<UserInfo>
438
777
  ```
439
778
 
440
779
  ### Types
@@ -450,6 +789,59 @@ interface VerifiedToken {
450
789
  payload: TokenPayload;
451
790
  valid: boolean;
452
791
  }
792
+
793
+ interface UserProfile {
794
+ userId: string;
795
+ email: string;
796
+ firstName: string | null;
797
+ lastName: string | null;
798
+ avatarUrl: string | null;
799
+ }
800
+
801
+ interface UpdateProfileDto {
802
+ firstName?: string;
803
+ lastName?: string;
804
+ }
805
+
806
+ interface UploadResponse {
807
+ avatarUrl: string;
808
+ }
809
+
810
+ interface Application {
811
+ clientId: string;
812
+ name: string;
813
+ description: string | null;
814
+ logoUrl: string | null;
815
+ redirectUris: string[];
816
+ authorizedOrigins: string[] | null;
817
+ scopes: string[];
818
+ createdAt: string;
819
+ updatedAt: string;
820
+ }
821
+
822
+ interface CreateApplicationDto {
823
+ name: string;
824
+ description?: string;
825
+ redirectUris: string[];
826
+ authorizedOrigins?: string[];
827
+ scopes: string[];
828
+ }
829
+
830
+ interface CreateApplicationResponse extends Application {
831
+ clientSecret: string; // Only returned once!
832
+ }
833
+
834
+ interface UpdateApplicationDto {
835
+ name?: string;
836
+ description?: string;
837
+ redirectUris?: string[];
838
+ authorizedOrigins?: string[];
839
+ scopes?: string[];
840
+ }
841
+
842
+ interface LogoUploadResponse {
843
+ logoUrl: string;
844
+ }
453
845
  ```
454
846
 
455
847
  ## Error Handling
@@ -0,0 +1,62 @@
1
+ export interface Application {
2
+ clientId: string;
3
+ name: string;
4
+ description: string | null;
5
+ logoUrl: string | null;
6
+ redirectUris: string[];
7
+ authorizedOrigins: string[] | null;
8
+ scopes: string[];
9
+ createdAt: string;
10
+ updatedAt: string;
11
+ }
12
+ export interface CreateApplicationDto {
13
+ name: string;
14
+ description?: string;
15
+ redirectUris: string[];
16
+ authorizedOrigins?: string[];
17
+ scopes: string[];
18
+ }
19
+ export interface CreateApplicationResponse extends Application {
20
+ clientSecret: string;
21
+ }
22
+ export interface UpdateApplicationDto {
23
+ name?: string;
24
+ description?: string;
25
+ redirectUris?: string[];
26
+ authorizedOrigins?: string[];
27
+ scopes?: string[];
28
+ }
29
+ export interface LogoUploadResponse {
30
+ logoUrl: string;
31
+ }
32
+ export interface ApplicationStats {
33
+ total: number;
34
+ active: number;
35
+ inactive: number;
36
+ }
37
+ export interface PaginationInfo {
38
+ page: number;
39
+ limit: number;
40
+ total: number;
41
+ totalPages: number;
42
+ }
43
+ export interface ListApplicationsResponse {
44
+ success: boolean;
45
+ stats: ApplicationStats;
46
+ data: Application[];
47
+ pagination: PaginationInfo;
48
+ }
49
+ export declare function listApplications(accessToken: string, options?: {
50
+ page?: number;
51
+ limit?: number;
52
+ }): Promise<ListApplicationsResponse>;
53
+ export declare function getApplicationByClientId(clientId: string): Promise<Omit<Application, 'createdAt' | 'updatedAt'>>;
54
+ export declare function createApplication(accessToken: string, data: CreateApplicationDto): Promise<CreateApplicationResponse>;
55
+ export declare function updateApplication(accessToken: string, clientId: string, data: UpdateApplicationDto): Promise<{
56
+ message: string;
57
+ }>;
58
+ export declare function deleteApplication(accessToken: string, clientId: string): Promise<{
59
+ message: string;
60
+ }>;
61
+ export declare function uploadApplicationLogo(accessToken: string, clientId: string, file: Blob | File, fileName?: string): Promise<LogoUploadResponse>;
62
+ //# sourceMappingURL=application-management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-management.d.ts","sourceRoot":"","sources":["../src/application-management.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,yBAA0B,SAAQ,WAAW;IAC5D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,UAAU,EAAE,cAAc,CAAC;CAC5B;AA8FD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,wBAAwB,CAAC,CAWnC;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC,CAMvD;AAED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,yBAAyB,CAAC,CAQpC;AAED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAQ9B;AAED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAO9B;AAED,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAgB7B"}
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listApplications = listApplications;
4
+ exports.getApplicationByClientId = getApplicationByClientId;
5
+ exports.createApplication = createApplication;
6
+ exports.updateApplication = updateApplication;
7
+ exports.deleteApplication = deleteApplication;
8
+ exports.uploadApplicationLogo = uploadApplicationLogo;
9
+ const auth_core_client_1 = require("@tekcify/auth-core-client");
10
+ function buildUrl(path, query) {
11
+ const url = new URL(`${auth_core_client_1.AUTH_SERVER_URL}${path}`);
12
+ Object.entries(query ?? {}).forEach(([key, value]) => {
13
+ if (value !== undefined) {
14
+ url.searchParams.set(key, String(value));
15
+ }
16
+ });
17
+ return url.toString();
18
+ }
19
+ function extractMessage(payload, fallback) {
20
+ if (typeof payload === 'string' && payload.trim()) {
21
+ return payload;
22
+ }
23
+ if (payload &&
24
+ typeof payload === 'object' &&
25
+ 'message' in payload &&
26
+ typeof payload.message === 'string' &&
27
+ payload.message.trim()) {
28
+ return payload.message;
29
+ }
30
+ return fallback;
31
+ }
32
+ async function request(config) {
33
+ const { path, method, defaultError, token, query, body, formData, headers } = config;
34
+ const url = buildUrl(path, query);
35
+ const hasJsonBody = body !== undefined && !formData;
36
+ const mergedHeaders = new Headers();
37
+ if (token) {
38
+ mergedHeaders.set('Authorization', `Bearer ${token}`);
39
+ }
40
+ if (hasJsonBody) {
41
+ mergedHeaders.set('Content-Type', 'application/json');
42
+ }
43
+ if (headers) {
44
+ new Headers(headers).forEach((value, key) => {
45
+ mergedHeaders.set(key, value);
46
+ });
47
+ }
48
+ const init = {
49
+ method,
50
+ headers: mergedHeaders,
51
+ body: formData ?? (hasJsonBody ? JSON.stringify(body) : undefined),
52
+ };
53
+ let response;
54
+ try {
55
+ response = await fetch(url, init);
56
+ }
57
+ catch (error) {
58
+ if (error instanceof Error) {
59
+ throw new Error(`${defaultError}: ${error.message}`);
60
+ }
61
+ throw new Error(defaultError);
62
+ }
63
+ const payload = await response.json().catch(() => null);
64
+ if (!response.ok) {
65
+ const message = extractMessage(payload, `${defaultError}: ${response.statusText} (Status: ${response.status})`);
66
+ throw new Error(message);
67
+ }
68
+ if (payload === null) {
69
+ throw new Error(`${defaultError}: Invalid response`);
70
+ }
71
+ return payload;
72
+ }
73
+ async function listApplications(accessToken, options) {
74
+ const page = options?.page ?? 1;
75
+ const limit = options?.limit ?? 10;
76
+ return request({
77
+ path: '/api/applications',
78
+ method: 'GET',
79
+ defaultError: 'Failed to list applications',
80
+ token: accessToken,
81
+ query: { page, limit },
82
+ });
83
+ }
84
+ async function getApplicationByClientId(clientId) {
85
+ return request({
86
+ path: `/api/applications/public/${clientId}`,
87
+ method: 'GET',
88
+ defaultError: 'Failed to get application',
89
+ });
90
+ }
91
+ async function createApplication(accessToken, data) {
92
+ return request({
93
+ path: '/api/applications',
94
+ method: 'POST',
95
+ defaultError: 'Failed to create application',
96
+ token: accessToken,
97
+ body: data,
98
+ });
99
+ }
100
+ async function updateApplication(accessToken, clientId, data) {
101
+ return request({
102
+ path: `/api/applications/${clientId}`,
103
+ method: 'PUT',
104
+ defaultError: 'Failed to update application',
105
+ token: accessToken,
106
+ body: data,
107
+ });
108
+ }
109
+ async function deleteApplication(accessToken, clientId) {
110
+ return request({
111
+ path: `/api/applications/${clientId}`,
112
+ method: 'DELETE',
113
+ defaultError: 'Failed to delete application',
114
+ token: accessToken,
115
+ });
116
+ }
117
+ async function uploadApplicationLogo(accessToken, clientId, file, fileName) {
118
+ const formData = new FormData();
119
+ if (fileName && !(file instanceof File)) {
120
+ formData.append('file', file, fileName);
121
+ }
122
+ else {
123
+ formData.append('file', file);
124
+ }
125
+ return request({
126
+ path: `/api/applications/${clientId}/logo`,
127
+ method: 'POST',
128
+ defaultError: 'Failed to upload application logo',
129
+ token: accessToken,
130
+ formData,
131
+ });
132
+ }
133
+ //# sourceMappingURL=application-management.js.map