@progalaxyelabs/ngx-stonescriptphp-client 1.1.2 → 1.3.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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ModuleWithProviders } from '@angular/core';
3
- import { BehaviorSubject } from 'rxjs';
2
+ import { ModuleWithProviders, OnInit, EventEmitter } from '@angular/core';
3
+ import { BehaviorSubject, Observable } from 'rxjs';
4
4
  import * as i1 from '@angular/common';
5
5
 
6
6
  declare class TokenService {
@@ -15,15 +15,33 @@ declare class TokenService {
15
15
  getAccessToken(): string;
16
16
  getRefreshToken(): string;
17
17
  clear(): void;
18
+ /**
19
+ * Check if there is a valid (non-empty) access token
20
+ * @returns True if access token exists and is not empty
21
+ */
22
+ hasValidAccessToken(): boolean;
18
23
  static ɵfac: i0.ɵɵFactoryDeclaration<TokenService, never>;
19
24
  static ɵprov: i0.ɵɵInjectableDeclaration<TokenService>;
20
25
  }
21
26
 
27
+ /**
28
+ * @deprecated Use boolean directly. Kept for backward compatibility.
29
+ */
30
+ declare enum VerifyStatus {
31
+ initialized = "initialized",
32
+ yes = "yes",
33
+ no = "no"
34
+ }
22
35
  declare class SigninStatusService {
23
- status: BehaviorSubject<boolean>;
36
+ status: BehaviorSubject<boolean | VerifyStatus>;
24
37
  constructor();
25
38
  signedOut(): void;
26
39
  signedIn(): void;
40
+ /**
41
+ * Set signin status
42
+ * @param isSignedIn - True if user is signed in, false otherwise
43
+ */
44
+ setSigninStatus(isSignedIn: boolean): void;
27
45
  static ɵfac: i0.ɵɵFactoryDeclaration<SigninStatusService, never>;
28
46
  static ɵprov: i0.ɵɵInjectableDeclaration<SigninStatusService>;
29
47
  }
@@ -81,6 +99,16 @@ interface AuthConfig {
81
99
  }
82
100
  declare class MyEnvironmentModel {
83
101
  production: boolean;
102
+ /**
103
+ * Platform code identifier (e.g., 'progalaxy', 'hr', 'admin')
104
+ * Used for multi-tenant authentication
105
+ */
106
+ platformCode: string;
107
+ /**
108
+ * Accounts platform URL for centralized authentication
109
+ * @example 'https://accounts.progalaxyelabs.com'
110
+ */
111
+ accountsUrl: string;
84
112
  firebase: {
85
113
  projectId: string;
86
114
  appId: string;
@@ -157,12 +185,198 @@ declare class ApiConnectionService {
157
185
  */
158
186
  private refreshAccessTokenBodyMode;
159
187
  buildQueryString(options?: any): string;
188
+ /**
189
+ * Upload a drawing (uses upload server if configured, otherwise API server)
190
+ * @deprecated Platform-specific method - consider moving to platform service
191
+ */
192
+ uploadDrawing<DataType>(formData: FormData): Promise<ApiResponse<DataType>>;
193
+ /**
194
+ * Upload an image (uses upload server if configured, otherwise API server)
195
+ * @deprecated Platform-specific method - consider moving to platform service
196
+ */
197
+ uploadImage<DataType>(formData: FormData): Promise<ApiResponse<DataType>>;
160
198
  static ɵfac: i0.ɵɵFactoryDeclaration<ApiConnectionService, never>;
161
199
  static ɵprov: i0.ɵɵInjectableDeclaration<ApiConnectionService>;
162
200
  }
163
201
 
202
+ type AuthProvider = 'google' | 'linkedin' | 'apple' | 'microsoft' | 'github' | 'emailPassword';
203
+ interface User {
204
+ user_id: number;
205
+ email: string;
206
+ display_name: string;
207
+ photo_url?: string;
208
+ is_email_verified: boolean;
209
+ }
210
+ interface AuthResult {
211
+ success: boolean;
212
+ message?: string;
213
+ user?: User;
214
+ }
164
215
  declare class AuthService {
165
- constructor();
216
+ private tokens;
217
+ private signinStatus;
218
+ private environment;
219
+ private userSubject;
220
+ user$: Observable<User | null>;
221
+ constructor(tokens: TokenService, signinStatus: SigninStatusService, environment: MyEnvironmentModel);
222
+ /**
223
+ * Login with email and password
224
+ */
225
+ loginWithEmail(email: string, password: string): Promise<AuthResult>;
226
+ /**
227
+ * Login with Google OAuth (popup window)
228
+ */
229
+ loginWithGoogle(): Promise<AuthResult>;
230
+ /**
231
+ * Login with GitHub OAuth (popup window)
232
+ */
233
+ loginWithGitHub(): Promise<AuthResult>;
234
+ /**
235
+ * Login with LinkedIn OAuth (popup window)
236
+ */
237
+ loginWithLinkedIn(): Promise<AuthResult>;
238
+ /**
239
+ * Login with Apple OAuth (popup window)
240
+ */
241
+ loginWithApple(): Promise<AuthResult>;
242
+ /**
243
+ * Login with Microsoft OAuth (popup window)
244
+ */
245
+ loginWithMicrosoft(): Promise<AuthResult>;
246
+ /**
247
+ * Generic provider-based login (supports all OAuth providers)
248
+ * @param provider - The provider identifier
249
+ */
250
+ loginWithProvider(provider: AuthProvider): Promise<AuthResult>;
251
+ /**
252
+ * Generic OAuth login handler
253
+ * Opens popup window and listens for postMessage
254
+ */
255
+ private loginWithOAuth;
256
+ /**
257
+ * Register new user
258
+ */
259
+ register(email: string, password: string, displayName: string): Promise<AuthResult>;
260
+ /**
261
+ * Sign out user
262
+ */
263
+ signout(): Promise<void>;
264
+ /**
265
+ * Check for active session (call on app init)
266
+ */
267
+ checkSession(): Promise<boolean>;
268
+ /**
269
+ * Check if user is authenticated
270
+ */
271
+ isAuthenticated(): boolean;
272
+ /**
273
+ * Get current user (synchronous)
274
+ */
275
+ getCurrentUser(): User | null;
276
+ /**
277
+ * Register a new user AND create a new tenant (organization)
278
+ * This is used when a user wants to create their own organization
279
+ */
280
+ registerTenant(data: {
281
+ tenantName: string;
282
+ tenantSlug: string;
283
+ displayName?: string;
284
+ email?: string;
285
+ password?: string;
286
+ provider: AuthProvider;
287
+ }): Promise<{
288
+ success: boolean;
289
+ message?: string;
290
+ tenant?: {
291
+ id: string;
292
+ name: string;
293
+ slug: string;
294
+ };
295
+ user?: {
296
+ id: string;
297
+ email: string;
298
+ name: string;
299
+ };
300
+ access_token?: string;
301
+ }>;
302
+ /**
303
+ * Register tenant with OAuth provider
304
+ * Opens popup window for OAuth flow
305
+ */
306
+ private registerTenantWithOAuth;
307
+ /**
308
+ * Get all tenant memberships for the authenticated user
309
+ */
310
+ getTenantMemberships(): Promise<{
311
+ memberships: Array<{
312
+ tenant_id: string;
313
+ slug: string;
314
+ name: string;
315
+ role: string;
316
+ status: string;
317
+ last_accessed?: string;
318
+ }>;
319
+ }>;
320
+ /**
321
+ * Select a tenant for the current session
322
+ * Updates the JWT token with tenant context
323
+ */
324
+ selectTenant(tenantId: string): Promise<{
325
+ success: boolean;
326
+ message?: string;
327
+ access_token?: string;
328
+ }>;
329
+ /**
330
+ * Check if a tenant slug is available
331
+ */
332
+ checkTenantSlugAvailable(slug: string): Promise<{
333
+ available: boolean;
334
+ suggestion?: string;
335
+ }>;
336
+ /**
337
+ * @deprecated Use getCurrentUser()?.user_id instead
338
+ */
339
+ getUserId(): number;
340
+ /**
341
+ * @deprecated Use getCurrentUser()?.display_name instead
342
+ */
343
+ getUserName(): string;
344
+ /**
345
+ * @deprecated Use getCurrentUser()?.photo_url instead
346
+ */
347
+ getPhotoUrl(): string;
348
+ /**
349
+ * @deprecated Use getCurrentUser()?.display_name instead
350
+ */
351
+ getDisplayName(): string;
352
+ /**
353
+ * @deprecated Use `/profile/${getCurrentUser()?.user_id}` instead
354
+ */
355
+ getProfileUrl(): string;
356
+ /**
357
+ * @deprecated Use isAuthenticated() instead
358
+ */
359
+ signin(): Promise<boolean>;
360
+ /**
361
+ * @deprecated Use loginWithEmail() instead
362
+ */
363
+ verifyCredentials(email: string, password: string): Promise<boolean>;
364
+ /**
365
+ * @deprecated Check user.is_email_verified from getCurrentUser() instead
366
+ */
367
+ isSigninEmailValid(): boolean;
368
+ /**
369
+ * @deprecated No longer needed - dialog is managed by platform
370
+ */
371
+ onDialogClose(): void;
372
+ /**
373
+ * @deprecated No longer needed - dialog is managed by platform
374
+ */
375
+ closeSocialAuthDialog(): void;
376
+ /**
377
+ * @deprecated Check if user exists by calling /api/auth/check-email endpoint
378
+ */
379
+ getUserProfile(email: string): Promise<User | null>;
166
380
  static ɵfac: i0.ɵɵFactoryDeclaration<AuthService, never>;
167
381
  static ɵprov: i0.ɵɵInjectableDeclaration<AuthService>;
168
382
  }
@@ -180,5 +394,243 @@ declare class NgxStoneScriptPhpClientModule {
180
394
  static ɵinj: i0.ɵɵInjectorDeclaration<NgxStoneScriptPhpClientModule>;
181
395
  }
182
396
 
183
- export { ApiConnectionService, ApiResponse, AuthService, CsrfService, DbService, MyEnvironmentModel, NgxStoneScriptPhpClientModule, SigninStatusService, TokenService };
184
- export type { AuthConfig, AuthMode };
397
+ declare class LoginDialogComponent implements OnInit {
398
+ private auth;
399
+ /**
400
+ * REQUIRED: Which authentication providers to show in this dialog
401
+ * @example ['google', 'linkedin', 'emailPassword']
402
+ */
403
+ providers: AuthProvider[];
404
+ email: string;
405
+ password: string;
406
+ error: string;
407
+ loading: boolean;
408
+ oauthProviders: AuthProvider[];
409
+ constructor(auth: AuthService);
410
+ ngOnInit(): void;
411
+ isProviderEnabled(provider: AuthProvider): boolean;
412
+ getProviderLabel(provider: AuthProvider): string;
413
+ getProviderIcon(provider: AuthProvider): string | undefined;
414
+ onEmailLogin(): Promise<void>;
415
+ onOAuthLogin(provider: AuthProvider): Promise<void>;
416
+ onRegisterClick(event: Event): void;
417
+ static ɵfac: i0.ɵɵFactoryDeclaration<LoginDialogComponent, never>;
418
+ static ɵcmp: i0.ɵɵComponentDeclaration<LoginDialogComponent, "lib-login-dialog", never, { "providers": { "alias": "providers"; "required": false; }; }, {}, never, never, true, never>;
419
+ }
420
+
421
+ declare class RegisterComponent {
422
+ private auth;
423
+ displayName: string;
424
+ email: string;
425
+ password: string;
426
+ confirmPassword: string;
427
+ error: string;
428
+ success: string;
429
+ loading: boolean;
430
+ constructor(auth: AuthService);
431
+ onRegister(): Promise<void>;
432
+ onLoginClick(event: Event): void;
433
+ static ɵfac: i0.ɵɵFactoryDeclaration<RegisterComponent, never>;
434
+ static ɵcmp: i0.ɵɵComponentDeclaration<RegisterComponent, "lib-register", never, {}, {}, never, never, true, never>;
435
+ }
436
+
437
+ interface TenantMembership {
438
+ tenant_id: string;
439
+ slug: string;
440
+ name: string;
441
+ role: string;
442
+ status: string;
443
+ last_accessed?: string;
444
+ }
445
+ interface TenantSelectedEvent {
446
+ tenantId: string;
447
+ tenantSlug: string;
448
+ role: string;
449
+ }
450
+ declare class TenantLoginComponent implements OnInit {
451
+ private auth;
452
+ title: string;
453
+ providers: AuthProvider[];
454
+ showTenantSelector: boolean;
455
+ autoSelectSingleTenant: boolean;
456
+ allowTenantCreation: boolean;
457
+ tenantSelectorTitle: string;
458
+ tenantSelectorDescription: string;
459
+ continueButtonText: string;
460
+ registerLinkText: string;
461
+ registerLinkAction: string;
462
+ createTenantLinkText: string;
463
+ createTenantLinkAction: string;
464
+ tenantSelected: EventEmitter<TenantSelectedEvent>;
465
+ createTenant: EventEmitter<void>;
466
+ email: string;
467
+ password: string;
468
+ error: string;
469
+ loading: boolean;
470
+ useOAuth: boolean;
471
+ oauthProviders: AuthProvider[];
472
+ showingTenantSelector: boolean;
473
+ memberships: TenantMembership[];
474
+ selectedTenantId: string | null;
475
+ userName: string;
476
+ constructor(auth: AuthService);
477
+ ngOnInit(): void;
478
+ isProviderEnabled(provider: AuthProvider): boolean;
479
+ getProviderLabel(provider: AuthProvider): string;
480
+ getProviderIcon(provider: AuthProvider): string | undefined;
481
+ toggleAuthMethod(event: Event): void;
482
+ onEmailLogin(): Promise<void>;
483
+ onOAuthLogin(provider: AuthProvider): Promise<void>;
484
+ handlePostAuthFlow(): Promise<void>;
485
+ selectTenantItem(tenantId: string): void;
486
+ onContinueWithTenant(): Promise<void>;
487
+ selectAndContinue(membership: TenantMembership): Promise<void>;
488
+ formatRole(role: string): string;
489
+ formatLastAccessed(dateStr: string): string;
490
+ onCreateTenantClick(event: Event): void;
491
+ static ɵfac: i0.ɵɵFactoryDeclaration<TenantLoginComponent, never>;
492
+ static ɵcmp: i0.ɵɵComponentDeclaration<TenantLoginComponent, "lib-tenant-login", never, { "title": { "alias": "title"; "required": false; }; "providers": { "alias": "providers"; "required": false; }; "showTenantSelector": { "alias": "showTenantSelector"; "required": false; }; "autoSelectSingleTenant": { "alias": "autoSelectSingleTenant"; "required": false; }; "allowTenantCreation": { "alias": "allowTenantCreation"; "required": false; }; "tenantSelectorTitle": { "alias": "tenantSelectorTitle"; "required": false; }; "tenantSelectorDescription": { "alias": "tenantSelectorDescription"; "required": false; }; "continueButtonText": { "alias": "continueButtonText"; "required": false; }; "registerLinkText": { "alias": "registerLinkText"; "required": false; }; "registerLinkAction": { "alias": "registerLinkAction"; "required": false; }; "createTenantLinkText": { "alias": "createTenantLinkText"; "required": false; }; "createTenantLinkAction": { "alias": "createTenantLinkAction"; "required": false; }; }, { "tenantSelected": "tenantSelected"; "createTenant": "createTenant"; }, never, never, true, never>;
493
+ }
494
+
495
+ interface TenantCreatedEvent {
496
+ tenant: {
497
+ id: string;
498
+ name: string;
499
+ slug: string;
500
+ };
501
+ user: {
502
+ id: string;
503
+ email: string;
504
+ name: string;
505
+ };
506
+ }
507
+ declare class TenantRegisterComponent implements OnInit {
508
+ private auth;
509
+ title: string;
510
+ providers: AuthProvider[];
511
+ requireTenantName: boolean;
512
+ tenantSectionTitle: string;
513
+ tenantNameLabel: string;
514
+ tenantNamePlaceholder: string;
515
+ tenantSlugLabel: string;
516
+ tenantSlugPlaceholder: string;
517
+ urlPreviewEnabled: boolean;
518
+ urlPreviewPrefix: string;
519
+ userSectionTitle: string;
520
+ oauthDescription: string;
521
+ ownershipTitle: string;
522
+ ownershipMessage: string;
523
+ submitButtonText: string;
524
+ loginLinkText: string;
525
+ loginLinkAction: string;
526
+ tenantCreated: EventEmitter<TenantCreatedEvent>;
527
+ navigateToLogin: EventEmitter<void>;
528
+ tenantName: string;
529
+ tenantSlug: string;
530
+ displayName: string;
531
+ email: string;
532
+ password: string;
533
+ confirmPassword: string;
534
+ error: string;
535
+ success: string;
536
+ loading: boolean;
537
+ loadingText: string;
538
+ checkingSlug: boolean;
539
+ slugAvailable: boolean;
540
+ slugError: string;
541
+ useEmailPassword: boolean;
542
+ oauthProviders: AuthProvider[];
543
+ constructor(auth: AuthService);
544
+ ngOnInit(): void;
545
+ isProviderEnabled(provider: AuthProvider): boolean;
546
+ getProviderLabel(provider: AuthProvider): string;
547
+ getProviderIcon(provider: AuthProvider): string | undefined;
548
+ onTenantNameChange(): void;
549
+ checkSlugAvailability(): Promise<void>;
550
+ toggleAuthMethod(event: Event): void;
551
+ isFormValid(): boolean;
552
+ onOAuthRegister(provider: AuthProvider): Promise<void>;
553
+ onRegister(): Promise<void>;
554
+ onLoginClick(event: Event): void;
555
+ static ɵfac: i0.ɵɵFactoryDeclaration<TenantRegisterComponent, never>;
556
+ static ɵcmp: i0.ɵɵComponentDeclaration<TenantRegisterComponent, "lib-tenant-register", never, { "title": { "alias": "title"; "required": false; }; "providers": { "alias": "providers"; "required": false; }; "requireTenantName": { "alias": "requireTenantName"; "required": false; }; "tenantSectionTitle": { "alias": "tenantSectionTitle"; "required": false; }; "tenantNameLabel": { "alias": "tenantNameLabel"; "required": false; }; "tenantNamePlaceholder": { "alias": "tenantNamePlaceholder"; "required": false; }; "tenantSlugLabel": { "alias": "tenantSlugLabel"; "required": false; }; "tenantSlugPlaceholder": { "alias": "tenantSlugPlaceholder"; "required": false; }; "urlPreviewEnabled": { "alias": "urlPreviewEnabled"; "required": false; }; "urlPreviewPrefix": { "alias": "urlPreviewPrefix"; "required": false; }; "userSectionTitle": { "alias": "userSectionTitle"; "required": false; }; "oauthDescription": { "alias": "oauthDescription"; "required": false; }; "ownershipTitle": { "alias": "ownershipTitle"; "required": false; }; "ownershipMessage": { "alias": "ownershipMessage"; "required": false; }; "submitButtonText": { "alias": "submitButtonText"; "required": false; }; "loginLinkText": { "alias": "loginLinkText"; "required": false; }; "loginLinkAction": { "alias": "loginLinkAction"; "required": false; }; }, { "tenantCreated": "tenantCreated"; "navigateToLogin": "navigateToLogin"; }, never, never, true, never>;
557
+ }
558
+
559
+ /**
560
+ * Dialog wrapper for TenantLoginComponent
561
+ *
562
+ * Usage with Angular Material Dialog:
563
+ * ```typescript
564
+ * const dialogRef = this.dialog.open(TenantLoginDialogComponent, {
565
+ * width: '450px',
566
+ * data: {
567
+ * providers: ['google'],
568
+ * showTenantSelector: true
569
+ * }
570
+ * });
571
+ *
572
+ * dialogRef.afterClosed().subscribe(result => {
573
+ * if (result && result.tenantId) {
574
+ * console.log('Logged in to tenant:', result.tenantSlug);
575
+ * // Redirect to dashboard
576
+ * }
577
+ * });
578
+ * ```
579
+ *
580
+ * Usage with custom dialog service:
581
+ * ```typescript
582
+ * const dialog = this.dialogService.open(TenantLoginDialogComponent, {
583
+ * providers: ['google', 'emailPassword'],
584
+ * autoSelectSingleTenant: true
585
+ * });
586
+ * ```
587
+ */
588
+ declare class TenantLoginDialogComponent {
589
+ data: any;
590
+ dialogRef: any;
591
+ constructor(injectedData?: any, injectedDialogRef?: any);
592
+ onTenantSelected(event: TenantSelectedEvent): void;
593
+ onCreateTenant(): void;
594
+ static ɵfac: i0.ɵɵFactoryDeclaration<TenantLoginDialogComponent, [{ optional: true; }, { optional: true; }]>;
595
+ static ɵcmp: i0.ɵɵComponentDeclaration<TenantLoginDialogComponent, "lib-tenant-login-dialog", never, {}, {}, never, never, true, never>;
596
+ }
597
+
598
+ /**
599
+ * Dialog wrapper for TenantRegisterComponent
600
+ *
601
+ * Usage with Angular Material Dialog:
602
+ * ```typescript
603
+ * const dialogRef = this.dialog.open(TenantRegisterDialogComponent, {
604
+ * width: '500px',
605
+ * data: {
606
+ * providers: ['google'],
607
+ * tenantNameLabel: 'Store Name'
608
+ * }
609
+ * });
610
+ *
611
+ * dialogRef.afterClosed().subscribe(result => {
612
+ * if (result && result.tenant) {
613
+ * console.log('Tenant created:', result.tenant);
614
+ * }
615
+ * });
616
+ * ```
617
+ *
618
+ * Usage with custom dialog service:
619
+ * ```typescript
620
+ * const dialog = this.dialogService.open(TenantRegisterDialogComponent, {
621
+ * providers: ['google', 'emailPassword']
622
+ * });
623
+ * ```
624
+ */
625
+ declare class TenantRegisterDialogComponent {
626
+ data: any;
627
+ dialogRef: any;
628
+ constructor(injectedData?: any, injectedDialogRef?: any);
629
+ onTenantCreated(event: TenantCreatedEvent): void;
630
+ onNavigateToLogin(): void;
631
+ static ɵfac: i0.ɵɵFactoryDeclaration<TenantRegisterDialogComponent, [{ optional: true; }, { optional: true; }]>;
632
+ static ɵcmp: i0.ɵɵComponentDeclaration<TenantRegisterDialogComponent, "lib-tenant-register-dialog", never, {}, {}, never, never, true, never>;
633
+ }
634
+
635
+ export { ApiConnectionService, ApiResponse, AuthService, CsrfService, DbService, LoginDialogComponent, MyEnvironmentModel, NgxStoneScriptPhpClientModule, RegisterComponent, SigninStatusService, TenantLoginComponent, TenantLoginDialogComponent, TenantRegisterComponent, TenantRegisterDialogComponent, TokenService, VerifyStatus };
636
+ export type { AuthConfig, AuthMode, AuthProvider, AuthResult, TenantCreatedEvent, TenantMembership, TenantSelectedEvent, User };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@progalaxyelabs/ngx-stonescriptphp-client",
3
- "version": "1.1.2",
3
+ "version": "1.3.0",
4
4
  "description": "Angular client library for StoneScriptPHP backend framework",
5
5
  "keywords": [
6
6
  "angular",
@@ -26,7 +26,8 @@
26
26
  "private": false,
27
27
  "peerDependencies": {
28
28
  "@angular/common": "^19.0.0 || ^20.0.0",
29
- "@angular/core": "^19.0.0 || ^20.0.0"
29
+ "@angular/core": "^19.0.0 || ^20.0.0",
30
+ "@angular/forms": "^19.0.0 || ^20.0.0"
30
31
  },
31
32
  "dependencies": {
32
33
  "tslib": "^2.8.0"