@capitalos/angular 0.1.0-rc.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.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # CapitalOS for Angular
2
+
3
+ Angular components and services for integrating with CapitalOS.
4
+
5
+ ## Requirements
6
+
7
+ - Angular 14.0.0 or higher
8
+
9
+ ## Installation
10
+
11
+ ### pnpm
12
+
13
+ ```bash
14
+ pnpm add @capitalos/angular
15
+ ```
16
+
17
+ ### npm
18
+
19
+ ```bash
20
+ npm install @capitalos/angular
21
+ ```
22
+
23
+ ### yarn
24
+
25
+ ```bash
26
+ yarn add @capitalos/angular
27
+ ```
28
+
29
+ ## Documentation
30
+
31
+ Please refer to the [official docs](https://docs.capitalos.com/docs/using-angular-client-library) for more details.
32
+
33
+ ## Usage
34
+
35
+ ### 1) Provide SDK configuration
36
+
37
+ You must provide a `getToken()` function which returns a **one-time token** from your backend (your backend should call CapitalOS "initiate login" for the relevant account/user).
38
+
39
+ #### Standalone apps
40
+
41
+ ```ts
42
+ import { bootstrapApplication } from '@angular/platform-browser'
43
+ import { provideCapitalOs } from '@capitalos/angular'
44
+ import { AppComponent } from './app/app.component'
45
+
46
+ bootstrapApplication(AppComponent, {
47
+ providers: [
48
+ provideCapitalOs({
49
+ getToken: async () => {
50
+ const res = await fetch('/api/capitalos/initiate-login', {
51
+ method: 'POST',
52
+ headers: { 'content-type': 'application/json' },
53
+ body: JSON.stringify({ accountId: 'act_...' }),
54
+ })
55
+ const json = await res.json()
56
+ return json.token
57
+ },
58
+ enableLogging: true,
59
+ }),
60
+ ],
61
+ })
62
+ ```
63
+
64
+ #### NgModule apps
65
+
66
+ ```ts
67
+ import { NgModule } from '@angular/core'
68
+ import { BrowserModule } from '@angular/platform-browser'
69
+ import { CapitalOsModule } from '@capitalos/angular'
70
+
71
+ @NgModule({
72
+ imports: [
73
+ BrowserModule,
74
+ CapitalOsModule.forRoot({
75
+ getToken: async () => {
76
+ const res = await fetch('/api/capitalos/initiate-login', {
77
+ method: 'POST',
78
+ headers: { 'content-type': 'application/json' },
79
+ body: JSON.stringify({ accountId: 'act_...' }),
80
+ })
81
+ const json = await res.json()
82
+ return json.token
83
+ },
84
+ enableLogging: true,
85
+ }),
86
+ ],
87
+ bootstrap: [AppComponent],
88
+ })
89
+ export class AppModule {}
90
+ ```
91
+
92
+ ### 2) Render the Cards app
93
+
94
+ ```ts
95
+ import { Component } from '@angular/core'
96
+ import { CardsAppComponent, CapitalOSError } from '@capitalos/angular'
97
+
98
+ @Component({
99
+ selector: 'app-root',
100
+ standalone: true,
101
+ imports: [CardsAppComponent],
102
+ template: ` <capitalos-cards-app (loaded)="onLoaded()" (error)="onError($event)" /> `,
103
+ })
104
+ export class AppComponent {
105
+ onLoaded(): void {
106
+ // iframe + app content loaded
107
+ }
108
+
109
+ onError(error: CapitalOSError): void {
110
+ // handle auth / connection / iframe errors
111
+ console.error(error)
112
+ }
113
+ }
114
+ ```
115
+
116
+ ## Notes
117
+
118
+ - The SDK automatically performs **token exchange** (one-time token → long-lived JWT) using a hidden iframe.
119
+ - You control loading UI in your app via the component’s `(loaded)` and `(error)` events.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwaXRhbG9zLWFuZ3VsYXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wcm9qZWN0cy9jYXBpdGFsb3MtYW5ndWxhci9zcmMvY2FwaXRhbG9zLWFuZ3VsYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
@@ -0,0 +1,134 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { BehaviorSubject, combineLatest, map } from 'rxjs';
3
+ import { TokenType, TokenParamKey, TokenParamLocation, createLogger } from '@capitalos/core';
4
+ import { TokenExchangeService } from './token-exchange.service';
5
+ import { CAPITALOS_CONFIG } from './provide-capitalos';
6
+ import * as i0 from "@angular/core";
7
+ /**
8
+ * Converts an unknown error to an Error object
9
+ */
10
+ function toError(error) {
11
+ if (error instanceof Error) {
12
+ return error;
13
+ }
14
+ return new Error(String(error));
15
+ }
16
+ /**
17
+ * Service that manages CapitalOS authentication state.
18
+ * This is the Angular equivalent of React's CapitalOsAuthenticationProvider.
19
+ *
20
+ * It handles:
21
+ * - Fetching one-time tokens via the provided getToken callback
22
+ * - Exchanging one-time tokens for long-lived JWTs
23
+ * - Managing token state via observables
24
+ * - Auto-refreshing tokens when they expire
25
+ */
26
+ export class CapitalOsAuthService {
27
+ constructor() {
28
+ this.config = inject(CAPITALOS_CONFIG);
29
+ this.tokenExchangeService = inject(TokenExchangeService);
30
+ // Private BehaviorSubjects for internal state
31
+ this._longLivedToken$ = new BehaviorSubject(undefined);
32
+ this._baseUrl$ = new BehaviorSubject(undefined);
33
+ this._isLoading$ = new BehaviorSubject(false);
34
+ this._error$ = new BehaviorSubject(undefined);
35
+ // Public observable for token data
36
+ this.tokenData$ = combineLatest([this._longLivedToken$, this._baseUrl$]).pipe(map(([token, baseUrl]) => {
37
+ if (!token || !baseUrl) {
38
+ return undefined;
39
+ }
40
+ return {
41
+ token,
42
+ tokenType: TokenType.longLived,
43
+ baseUrl,
44
+ paramKey: TokenParamKey.accessToken,
45
+ paramLocation: TokenParamLocation.hash,
46
+ };
47
+ }));
48
+ // Public observables for UI state
49
+ this.isLoading$ = this._isLoading$.asObservable();
50
+ this.error$ = this._error$.asObservable();
51
+ this.authState$ = combineLatest([this._isLoading$, this._error$, this.tokenData$]).pipe(map(([isLoading, error, tokenData]) => {
52
+ if (isLoading)
53
+ return 'loading';
54
+ if (error)
55
+ return 'error';
56
+ if (tokenData)
57
+ return 'authenticated';
58
+ return 'idle';
59
+ }));
60
+ this.isDestroyed = false;
61
+ this.logger = createLogger(this.config.enableLogging, this.config.logger);
62
+ // Start authentication flow eagerly on construction.
63
+ // This is intentional: auth begins as soon as the app boots so the token
64
+ // is ready when CardsAppComponent renders, reducing perceived load time.
65
+ this.refreshToken();
66
+ }
67
+ ngOnDestroy() {
68
+ this.isDestroyed = true;
69
+ }
70
+ /**
71
+ * Invalidates the current token, triggering a refresh.
72
+ * Called when the iframe signals that the token has expired.
73
+ */
74
+ invalidateToken() {
75
+ this.logger.log('CapitalOsAuthService: Invalidating token');
76
+ this._longLivedToken$.next(undefined);
77
+ this._baseUrl$.next(undefined);
78
+ this._error$.next(undefined);
79
+ this.refreshToken();
80
+ }
81
+ /**
82
+ * Refreshes the token by fetching a new one-time token and exchanging it.
83
+ */
84
+ async refreshToken() {
85
+ if (this.isDestroyed) {
86
+ return;
87
+ }
88
+ // Prevent concurrent refresh calls - if already loading, skip
89
+ if (this._isLoading$.value) {
90
+ this.logger.log('CapitalOsAuthService: Token refresh already in progress, skipping');
91
+ return;
92
+ }
93
+ this.logger.log('CapitalOsAuthService: Starting token refresh');
94
+ this._isLoading$.next(true);
95
+ this._error$.next(undefined);
96
+ try {
97
+ // Get one-time token from platform
98
+ const oneTimeToken = await this.config.getToken();
99
+ this.logger.log('CapitalOsAuthService: Received one-time token');
100
+ if (this.isDestroyed) {
101
+ return;
102
+ }
103
+ // Exchange for long-lived token
104
+ const result = await this.tokenExchangeService.exchange(oneTimeToken, {
105
+ enableLogging: this.config.enableLogging,
106
+ });
107
+ if (this.isDestroyed) {
108
+ return;
109
+ }
110
+ this._longLivedToken$.next(result.longLivedToken);
111
+ this._baseUrl$.next(result.baseUrl);
112
+ this._error$.next(undefined);
113
+ this.logger.log('CapitalOsAuthService: Token exchange complete');
114
+ }
115
+ catch (rawError) {
116
+ if (!this.isDestroyed) {
117
+ const error = toError(rawError);
118
+ this.logger.error(`CapitalOsAuthService: Token refresh failed: ${error.message}`);
119
+ this._error$.next(error);
120
+ }
121
+ }
122
+ finally {
123
+ if (!this.isDestroyed) {
124
+ this._isLoading$.next(false);
125
+ }
126
+ }
127
+ }
128
+ }
129
+ CapitalOsAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
130
+ CapitalOsAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsAuthService });
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsAuthService, decorators: [{
132
+ type: Injectable
133
+ }], ctorParameters: function () { return []; } });
134
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwaXRhbG9zLWF1dGguc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NhcGl0YWxvcy1hbmd1bGFyL3NyYy9saWIvY2FwaXRhbG9zLWF1dGguc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBYSxNQUFNLGVBQWUsQ0FBQTtBQUM3RCxPQUFPLEVBQUUsZUFBZSxFQUFjLGFBQWEsRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUE7QUFDdEUsT0FBTyxFQUFhLFNBQVMsRUFBRSxhQUFhLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDdkcsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDL0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUE7O0FBRXREOztHQUVHO0FBQ0gsU0FBUyxPQUFPLENBQUMsS0FBYztJQUM3QixJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUU7UUFDMUIsT0FBTyxLQUFLLENBQUE7S0FDYjtJQUNELE9BQU8sSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7QUFDakMsQ0FBQztBQU9EOzs7Ozs7Ozs7R0FTRztBQUVILE1BQU0sT0FBTyxvQkFBb0I7SUEwQy9CO1FBekNpQixXQUFNLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUE7UUFDakMseUJBQW9CLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUE7UUFFcEUsOENBQThDO1FBQzdCLHFCQUFnQixHQUFHLElBQUksZUFBZSxDQUFxQixTQUFTLENBQUMsQ0FBQTtRQUNyRSxjQUFTLEdBQUcsSUFBSSxlQUFlLENBQXFCLFNBQVMsQ0FBQyxDQUFBO1FBQzlELGdCQUFXLEdBQUcsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLENB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QUssQ0FBQyxDQUFBO2FBQzdCO1NBQ0Y7SUFDSCxDQUFDOztpSEF0SFUsb0JBQW9CO3FIQUFwQixvQkFBb0I7MkZBQXBCLG9CQUFvQjtrQkFEaEMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIGluamVjdCwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgY29tYmluZUxhdGVzdCwgbWFwIH0gZnJvbSAncnhqcydcbmltcG9ydCB7IFRva2VuRGF0YSwgVG9rZW5UeXBlLCBUb2tlblBhcmFtS2V5LCBUb2tlblBhcmFtTG9jYXRpb24sIGNyZWF0ZUxvZ2dlciB9IGZyb20gJ0BjYXBpdGFsb3MvY29yZSdcbmltcG9ydCB7IFRva2VuRXhjaGFuZ2VTZXJ2aWNlIH0gZnJvbSAnLi90b2tlbi1leGNoYW5nZS5zZXJ2aWNlJ1xuaW1wb3J0IHsgQ0FQSVRBTE9TX0NPTkZJRyB9IGZyb20gJy4vcHJvdmlkZS1jYXBpdGFsb3MnXG5cbi8qKlxuICogQ29udmVydHMgYW4gdW5rbm93biBlcnJvciB0byBhbiBFcnJvciBvYmplY3RcbiAqL1xuZnVuY3Rpb24gdG9FcnJvcihlcnJvcjogdW5rbm93bik6IEVycm9yIHtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3JcbiAgfVxuICByZXR1cm4gbmV3IEVycm9yKFN0cmluZyhlcnJvcikpXG59XG5cbi8qKlxuICogQXV0aGVudGljYXRpb24gc3RhdGUgZW51bVxuICovXG5leHBvcnQgdHlwZSBBdXRoU3RhdGUgPSAnaWRsZScgfCAnbG9hZGluZycgfCAnYXV0aGVudGljYXRlZCcgfCAnZXJyb3InXG5cbi8qKlxuICogU2VydmljZSB0aGF0IG1hbmFnZXMgQ2FwaXRhbE9TIGF1dGhlbnRpY2F0aW9uIHN0YXRlLlxuICogVGhpcyBpcyB0aGUgQW5ndWxhciBlcXVpdmFsZW50IG9mIFJlYWN0J3MgQ2FwaXRhbE9zQXV0aGVudGljYXRpb25Qcm92aWRlci5cbiAqXG4gKiBJdCBoYW5kbGVzOlxuICogLSBGZXRjaGluZyBvbmUtdGltZSB0b2tlbnMgdmlhIHRoZSBwcm92aWRlZCBnZXRUb2tlbiBjYWxsYmFja1xuICogLSBFeGNoYW5naW5nIG9uZS10aW1lIHRva2VucyBmb3IgbG9uZy1saXZlZCBKV1RzXG4gKiAtIE1hbmFnaW5nIHRva2VuIHN0YXRlIHZpYSBvYnNlcnZhYmxlc1xuICogLSBBdXRvLXJlZnJlc2hpbmcgdG9rZW5zIHdoZW4gdGhleSBleHBpcmVcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIENhcGl0YWxPc0F1dGhTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWcgPSBpbmplY3QoQ0FQSVRBTE9TX0NPTkZJRylcbiAgcHJpdmF0ZSByZWFkb25seSB0b2tlbkV4Y2hhbmdlU2VydmljZSA9IGluamVjdChUb2tlbkV4Y2hhbmdlU2VydmljZSlcblxuICAvLyBQcml2YXRlIEJlaGF2aW9yU3ViamVjdHMgZm9yIGludGVybmFsIHN0YXRlXG4gIHByaXZhdGUgcmVhZG9ubHkgX2xvbmdMaXZlZFRva2VuJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Jhc2VVcmwkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZClcbiAgcHJpdmF0ZSByZWFkb25seSBfaXNMb2FkaW5nJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Vycm9yJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8RXJyb3IgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZClcblxuICAvLyBQdWJsaWMgb2JzZXJ2YWJsZSBmb3IgdG9rZW4gZGF0YVxuICByZWFkb25seSB0b2tlbkRhdGEkOiBPYnNlcnZhYmxlPFRva2VuRGF0YSB8IHVuZGVmaW5lZD4gPSBjb21iaW5lTGF0ZXN0KFt0aGlzLl9sb25nTGl2ZWRUb2tlbiQsIHRoaXMuX2Jhc2VVcmwkXSkucGlwZShcbiAgICBtYXAoKFt0b2tlbiwgYmFzZVVybF0pID0+IHtcbiAgICAgIGlmICghdG9rZW4gfHwgIWJhc2VVcmwpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0b2tlbixcbiAgICAgICAgdG9rZW5UeXBlOiBUb2tlblR5cGUubG9uZ0xpdmVkLFxuICAgICAgICBiYXNlVXJsLFxuICAgICAgICBwYXJhbUtleTogVG9rZW5QYXJhbUtleS5hY2Nlc3NUb2tlbixcbiAgICAgICAgcGFyYW1Mb2NhdGlvbjogVG9rZW5QYXJhbUxvY2F0aW9uLmhhc2gsXG4gICAgICB9XG4gICAgfSlcbiAgKVxuXG4gIC8vIFB1YmxpYyBvYnNlcnZhYmxlcyBmb3IgVUkgc3RhdGVcbiAgcmVhZG9ubHkgaXNMb2FkaW5nJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IHRoaXMuX2lzTG9hZGluZyQuYXNPYnNlcnZhYmxlKClcbiAgcmVhZG9ubHkgZXJyb3IkOiBPYnNlcnZhYmxlPEVycm9yIHwgdW5kZWZpbmVkPiA9IHRoaXMuX2Vycm9yJC5hc09ic2VydmFibGUoKVxuICByZWFkb25seSBhdXRoU3RhdGUkOiBPYnNlcnZhYmxlPEF1dGhTdGF0ZT4gPSBjb21iaW5lTGF0ZXN0KFt0aGlzLl9pc0xvYWRpbmckLCB0aGlzLl9lcnJvciQsIHRoaXMudG9rZW5EYXRhJF0pLnBpcGUoXG4gICAgbWFwKChbaXNMb2FkaW5nLCBlcnJvciwgdG9rZW5EYXRhXSkgPT4ge1xuICAgICAgaWYgKGlzTG9hZGluZykgcmV0dXJuICdsb2FkaW5nJ1xuICAgICAgaWYgKGVycm9yKSByZXR1cm4gJ2Vycm9yJ1xuICAgICAgaWYgKHRva2VuRGF0YSkgcmV0dXJuICdhdXRoZW50aWNhdGVkJ1xuICAgICAgcmV0dXJuICdpZGxlJ1xuICAgIH0pXG4gIClcblxuICBwcml2YXRlIGlzRGVzdHJveWVkID0gZmFsc2VcbiAgcHJpdmF0ZSBsb2dnZXI6IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUxvZ2dlcj5cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmxvZ2dlciA9IGNyZWF0ZUxvZ2dlcih0aGlzLmNvbmZpZy5lbmFibGVMb2dnaW5nLCB0aGlzLmNvbmZpZy5sb2dnZXIpXG5cbiAgICAvLyBTdGFydCBhdXRoZW50aWNhdGlvbiBmbG93IGVhZ2VybHkgb24gY29uc3RydWN0aW9uLlxuICAgIC8vIFRoaXMgaXMgaW50ZW50aW9uYWw6IGF1dGggYmVnaW5zIGFzIHNvb24gYXMgdGhlIGFwcCBib290cyBzbyB0aGUgdG9rZW5cbiAgICAvLyBpcyByZWFkeSB3aGVuIENhcmRzQXBwQ29tcG9uZW50IHJlbmRlcnMsIHJlZHVjaW5nIHBlcmNlaXZlZCBsb2FkIHRpbWUuXG4gICAgdGhpcy5yZWZyZXNoVG9rZW4oKVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5pc0Rlc3Ryb3llZCA9IHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZhbGlkYXRlcyB0aGUgY3VycmVudCB0b2tlbiwgdHJpZ2dlcmluZyBhIHJlZnJlc2guXG4gICAqIENhbGxlZCB3aGVuIHRoZSBpZnJhbWUgc2lnbmFscyB0aGF0IHRoZSB0b2tlbiBoYXMgZXhwaXJlZC5cbiAgICovXG4gIGludmFsaWRhdGVUb2tlbigpOiB2b2lkIHtcbiAgICB0aGlzLmxvZ2dlci5sb2coJ0NhcGl0YWxPc0F1dGhTZXJ2aWNlOiBJbnZhbGlkYXRpbmcgdG9rZW4nKVxuICAgIHRoaXMuX2xvbmdMaXZlZFRva2VuJC5uZXh0KHVuZGVmaW5lZClcbiAgICB0aGlzLl9iYXNlVXJsJC5uZXh0KHVuZGVmaW5lZClcbiAgICB0aGlzLl9lcnJvciQubmV4dCh1bmRlZmluZWQpXG4gICAgdGhpcy5yZWZyZXNoVG9rZW4oKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZnJlc2hlcyB0aGUgdG9rZW4gYnkgZmV0Y2hpbmcgYSBuZXcgb25lLXRpbWUgdG9rZW4gYW5kIGV4Y2hhbmdpbmcgaXQuXG4gICAqL1xuICBhc3luYyByZWZyZXNoVG9rZW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIFByZXZlbnQgY29uY3VycmVudCByZWZyZXNoIGNhbGxzIC0gaWYgYWxyZWFkeSBsb2FkaW5nLCBza2lwXG4gICAgaWYgKHRoaXMuX2lzTG9hZGluZyQudmFsdWUpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmxvZygnQ2FwaXRhbE9zQXV0aFNlcnZpY2U6IFRva2VuIHJlZnJlc2ggYWxyZWFkeSBpbiBwcm9ncmVzcywgc2tpcHBpbmcnKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5sb2dnZXIubG9nKCdDYXBpdGFsT3NBdXRoU2VydmljZTogU3RhcnRpbmcgdG9rZW4gcmVmcmVzaCcpXG4gICAgdGhpcy5faXNMb2FkaW5nJC5uZXh0KHRydWUpXG4gICAgdGhpcy5fZXJyb3IkLm5leHQodW5kZWZpbmVkKVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIEdldCBvbmUtdGltZSB0b2tlbiBmcm9tIHBsYXRmb3JtXG4gICAgICBjb25zdCBvbmVUaW1lVG9rZW4gPSBhd2FpdCB0aGlzLmNvbmZpZy5nZXRUb2tlbigpXG4gICAgICB0aGlzLmxvZ2dlci5sb2coJ0NhcGl0YWxPc0F1dGhTZXJ2aWNlOiBSZWNlaXZlZCBvbmUtdGltZSB0b2tlbicpXG5cbiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICAvLyBFeGNoYW5nZSBmb3IgbG9uZy1saXZlZCB0b2tlblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy50b2tlbkV4Y2hhbmdlU2VydmljZS5leGNoYW5nZShvbmVUaW1lVG9rZW4sIHtcbiAgICAgICAgZW5hYmxlTG9nZ2luZzogdGhpcy5jb25maWcuZW5hYmxlTG9nZ2luZyxcbiAgICAgIH0pXG5cbiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICB0aGlzLl9sb25nTGl2ZWRUb2tlbiQubmV4dChyZXN1bHQubG9uZ0xpdmVkVG9rZW4pXG4gICAgICB0aGlzLl9iYXNlVXJsJC5uZXh0KHJlc3VsdC5iYXNlVXJsKVxuICAgICAgdGhpcy5fZXJyb3IkLm5leHQodW5kZWZpbmVkKVxuICAgICAgdGhpcy5sb2dnZXIubG9nKCdDYXBpdGFsT3NBdXRoU2VydmljZTogVG9rZW4gZXhjaGFuZ2UgY29tcGxldGUnKVxuICAgIH0gY2F0Y2ggKHJhd0Vycm9yKSB7XG4gICAgICBpZiAoIXRoaXMuaXNEZXN0cm95ZWQpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSB0b0Vycm9yKHJhd0Vycm9yKVxuICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihgQ2FwaXRhbE9zQXV0aFNlcnZpY2U6IFRva2VuIHJlZnJlc2ggZmFpbGVkOiAke2Vycm9yLm1lc3NhZ2V9YClcbiAgICAgICAgdGhpcy5fZXJyb3IkLm5leHQoZXJyb3IpXG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmICghdGhpcy5pc0Rlc3Ryb3llZCkge1xuICAgICAgICB0aGlzLl9pc0xvYWRpbmckLm5leHQoZmFsc2UpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,48 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CardsAppComponent } from './cards-app.component';
3
+ import { CAPITALOS_CONFIG } from './provide-capitalos';
4
+ import { CapitalOsAuthService } from './capitalos-auth.service';
5
+ import { TokenExchangeService } from './token-exchange.service';
6
+ import * as i0 from "@angular/core";
7
+ /**
8
+ * NgModule for CapitalOS SDK.
9
+ *
10
+ * Use this module for NgModule-based Angular applications.
11
+ * For standalone applications, use provideCapitalOs() instead.
12
+ *
13
+ * Usage:
14
+ * ```typescript
15
+ * @NgModule({
16
+ * imports: [
17
+ * CapitalOsModule.forRoot({
18
+ * getToken: async () => {
19
+ * const response = await fetch('/api/capitalos/token');
20
+ * const data = await response.json();
21
+ * return data.token;
22
+ * },
23
+ * enableLogging: true,
24
+ * }),
25
+ * ],
26
+ * })
27
+ * export class AppModule {}
28
+ * ```
29
+ */
30
+ export class CapitalOsModule {
31
+ static forRoot(config) {
32
+ return {
33
+ ngModule: CapitalOsModule,
34
+ providers: [{ provide: CAPITALOS_CONFIG, useValue: config }, TokenExchangeService, CapitalOsAuthService],
35
+ };
36
+ }
37
+ }
38
+ CapitalOsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
39
+ CapitalOsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsModule, imports: [CardsAppComponent], exports: [CardsAppComponent] });
40
+ CapitalOsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsModule, imports: [CardsAppComponent] });
41
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CapitalOsModule, decorators: [{
42
+ type: NgModule,
43
+ args: [{
44
+ imports: [CardsAppComponent],
45
+ exports: [CardsAppComponent],
46
+ }]
47
+ }] });
48
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwaXRhbG9zLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NhcGl0YWxvcy1hbmd1bGFyL3NyYy9saWIvY2FwaXRhbG9zLm1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXVCLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUM3RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUN6RCxPQUFPLEVBQW1CLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDdkUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDL0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7O0FBRS9EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBS0gsTUFBTSxPQUFPLGVBQWU7SUFDMUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUF1QjtRQUNwQyxPQUFPO1lBQ0wsUUFBUSxFQUFFLGVBQWU7WUFDekIsU0FBUyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixDQUFDO1NBQ3pHLENBQUE7SUFDSCxDQUFDOzs0R0FOVSxlQUFlOzZHQUFmLGVBQWUsWUFIaEIsaUJBQWlCLGFBQ2pCLGlCQUFpQjs2R0FFaEIsZUFBZSxZQUhoQixpQkFBaUI7MkZBR2hCLGVBQWU7a0JBSjNCLFFBQVE7bUJBQUM7b0JBQ1IsT0FBTyxFQUFFLENBQUMsaUJBQWlCLENBQUM7b0JBQzVCLE9BQU8sRUFBRSxDQUFDLGlCQUFpQixDQUFDO2lCQUM3QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IENhcmRzQXBwQ29tcG9uZW50IH0gZnJvbSAnLi9jYXJkcy1hcHAuY29tcG9uZW50J1xuaW1wb3J0IHsgQ2FwaXRhbE9zQ29uZmlnLCBDQVBJVEFMT1NfQ09ORklHIH0gZnJvbSAnLi9wcm92aWRlLWNhcGl0YWxvcydcbmltcG9ydCB7IENhcGl0YWxPc0F1dGhTZXJ2aWNlIH0gZnJvbSAnLi9jYXBpdGFsb3MtYXV0aC5zZXJ2aWNlJ1xuaW1wb3J0IHsgVG9rZW5FeGNoYW5nZVNlcnZpY2UgfSBmcm9tICcuL3Rva2VuLWV4Y2hhbmdlLnNlcnZpY2UnXG5cbi8qKlxuICogTmdNb2R1bGUgZm9yIENhcGl0YWxPUyBTREsuXG4gKlxuICogVXNlIHRoaXMgbW9kdWxlIGZvciBOZ01vZHVsZS1iYXNlZCBBbmd1bGFyIGFwcGxpY2F0aW9ucy5cbiAqIEZvciBzdGFuZGFsb25lIGFwcGxpY2F0aW9ucywgdXNlIHByb3ZpZGVDYXBpdGFsT3MoKSBpbnN0ZWFkLlxuICpcbiAqIFVzYWdlOlxuICogYGBgdHlwZXNjcmlwdFxuICogQE5nTW9kdWxlKHtcbiAqICAgaW1wb3J0czogW1xuICogICAgIENhcGl0YWxPc01vZHVsZS5mb3JSb290KHtcbiAqICAgICAgIGdldFRva2VuOiBhc3luYyAoKSA9PiB7XG4gKiAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvY2FwaXRhbG9zL3Rva2VuJyk7XG4gKiAgICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gKiAgICAgICAgIHJldHVybiBkYXRhLnRva2VuO1xuICogICAgICAgfSxcbiAqICAgICAgIGVuYWJsZUxvZ2dpbmc6IHRydWUsXG4gKiAgICAgfSksXG4gKiAgIF0sXG4gKiB9KVxuICogZXhwb3J0IGNsYXNzIEFwcE1vZHVsZSB7fVxuICogYGBgXG4gKi9cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtDYXJkc0FwcENvbXBvbmVudF0sXG4gIGV4cG9ydHM6IFtDYXJkc0FwcENvbXBvbmVudF0sXG59KVxuZXhwb3J0IGNsYXNzIENhcGl0YWxPc01vZHVsZSB7XG4gIHN0YXRpYyBmb3JSb290KGNvbmZpZzogQ2FwaXRhbE9zQ29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVyczxDYXBpdGFsT3NNb2R1bGU+IHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IENhcGl0YWxPc01vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogQ0FQSVRBTE9TX0NPTkZJRywgdXNlVmFsdWU6IGNvbmZpZyB9LCBUb2tlbkV4Y2hhbmdlU2VydmljZSwgQ2FwaXRhbE9zQXV0aFNlcnZpY2VdLFxuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,93 @@
1
+ import { Component, inject, Input, Output, EventEmitter, ViewChild, } from '@angular/core';
2
+ import { IframeManager, CapitalOSError } from '@capitalos/core';
3
+ import { CapitalOsAuthService } from './capitalos-auth.service';
4
+ import { CAPITALOS_CONFIG } from './provide-capitalos';
5
+ import * as i0 from "@angular/core";
6
+ // TODO: Automate version injection at build time
7
+ const SDK_VERSION = '0.1.0-rc.1';
8
+ /**
9
+ * CardsApp component that renders the CapitalOS cards interface in an iframe.
10
+ *
11
+ * The component emits events for loading state - consumers should handle their own loading UI:
12
+ *
13
+ * ```html
14
+ * <div *ngIf="!cardsLoaded">
15
+ * <my-loading-spinner></my-loading-spinner>
16
+ * </div>
17
+ * <capitalos-cards-app
18
+ * (loaded)="cardsLoaded = true"
19
+ * (error)="onCardsError($event)"
20
+ * ></capitalos-cards-app>
21
+ * ```
22
+ */
23
+ export class CardsAppComponent {
24
+ constructor() {
25
+ // Injected services
26
+ this.authService = inject(CapitalOsAuthService);
27
+ this.config = inject(CAPITALOS_CONFIG);
28
+ this.heightOffsetPx = 12;
29
+ // Outputs
30
+ this.loaded = new EventEmitter();
31
+ this.error = new EventEmitter();
32
+ }
33
+ ngAfterViewInit() {
34
+ // Subscribe to tokenData$ and initialize iframe when ready
35
+ this.tokenDataSubscription = this.authService.tokenData$.subscribe((tokenData) => {
36
+ if (tokenData && this.iframeContainer) {
37
+ this.initializeIframe(tokenData, this.iframeContainer.nativeElement);
38
+ }
39
+ });
40
+ }
41
+ ngOnDestroy() {
42
+ this.tokenDataSubscription?.unsubscribe();
43
+ this.iframeManager?.destroy();
44
+ }
45
+ initializeIframe(tokenData, container) {
46
+ // Destroy previous iframe if exists
47
+ this.iframeManager?.destroy();
48
+ const resolvedEnableLogging = this.enableLogging ?? this.config.enableLogging ?? false;
49
+ const resolvedTheme = this.theme ?? this.config.theme;
50
+ this.iframeManager = new IframeManager({
51
+ container,
52
+ tokenData,
53
+ renderingContext: { entryPoint: 'cardsApp' },
54
+ theme: resolvedTheme,
55
+ enableLogging: resolvedEnableLogging,
56
+ logger: this.config.logger,
57
+ sdkVersion: SDK_VERSION,
58
+ heightOffsetPx: this.heightOffsetPx,
59
+ callbacks: {
60
+ onLoad: () => {
61
+ this.loaded.emit();
62
+ },
63
+ onError: (rawError) => {
64
+ const capitalOsError = new CapitalOSError(rawError);
65
+ this.error.emit(capitalOsError);
66
+ },
67
+ onTokenExpired: () => {
68
+ this.authService.invalidateToken();
69
+ },
70
+ },
71
+ });
72
+ }
73
+ }
74
+ CardsAppComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CardsAppComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
75
+ CardsAppComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: CardsAppComponent, isStandalone: true, selector: "capitalos-cards-app", inputs: { theme: "theme", heightOffsetPx: "heightOffsetPx", enableLogging: "enableLogging" }, outputs: { loaded: "loaded", error: "error" }, viewQueries: [{ propertyName: "iframeContainer", first: true, predicate: ["iframeContainer"], descendants: true }], ngImport: i0, template: `<div #iframeContainer class="capitalos-iframe-container"></div>`, isInline: true, styles: [":host{display:block;width:100%}.capitalos-iframe-container{width:100%}\n"] });
76
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CardsAppComponent, decorators: [{
77
+ type: Component,
78
+ args: [{ selector: 'capitalos-cards-app', standalone: true, template: `<div #iframeContainer class="capitalos-iframe-container"></div>`, styles: [":host{display:block;width:100%}.capitalos-iframe-container{width:100%}\n"] }]
79
+ }], propDecorators: { theme: [{
80
+ type: Input
81
+ }], heightOffsetPx: [{
82
+ type: Input
83
+ }], enableLogging: [{
84
+ type: Input
85
+ }], loaded: [{
86
+ type: Output
87
+ }], error: [{
88
+ type: Output
89
+ }], iframeContainer: [{
90
+ type: ViewChild,
91
+ args: ['iframeContainer']
92
+ }] } });
93
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FyZHMtYXBwLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NhcGl0YWxvcy1hbmd1bGFyL3NyYy9saWIvY2FyZHMtYXBwLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixTQUFTLEdBSVYsTUFBTSxlQUFlLENBQUE7QUFFdEIsT0FBTyxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQWdELE1BQU0saUJBQWlCLENBQUE7QUFDN0csT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDL0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUE7O0FBRXRELGlEQUFpRDtBQUNqRCxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUE7QUFFaEM7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFrQkgsTUFBTSxPQUFPLGlCQUFpQjtJQWpCOUI7UUFrQkUsb0JBQW9CO1FBQ0gsZ0JBQVcsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtRQUMxQyxXQUFNLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUE7UUFJekMsbUJBQWMsR0FBRyxFQUFFLENBQUE7UUFHNUIsVUFBVTtRQUNBLFdBQU0sR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFBO1FBQ2pDLFVBQUssR0FBRyxJQUFJLFlBQVksRUFBa0IsQ0FBQTtLQXFEckQ7SUE1Q0MsZUFBZTtRQUNiLDJEQUEyRDtRQUMzRCxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDL0UsSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRTtnQkFDckMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFBO2FBQ3JFO1FBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxxQkFBcUIsRUFBRSxXQUFXLEVBQUUsQ0FBQTtRQUN6QyxJQUFJLENBQUMsYUFBYSxFQUFFLE9BQU8sRUFBRSxDQUFBO0lBQy9CLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxTQUFvQixFQUFFLFNBQXNCO1FBQ25FLG9DQUFvQztRQUNwQyxJQUFJLENBQUMsYUFBYSxFQUFFLE9BQU8sRUFBRSxDQUFBO1FBRTdCLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUE7UUFDdEYsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQTtRQUVyRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDO1lBQ3JDLFNBQVM7WUFDVCxTQUFTO1lBQ1QsZ0JBQWdCLEVBQUUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFO1lBQzVDLEtBQUssRUFBRSxhQUFhO1lBQ3BCLGFBQWEsRUFBRSxxQkFBcUI7WUFDcEMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtZQUMxQixVQUFVLEVBQUUsV0FBVztZQUN2QixjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWM7WUFDbkMsU0FBUyxFQUFFO2dCQUNULE1BQU0sRUFBRSxHQUFHLEVBQUU7b0JBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtnQkFDcEIsQ0FBQztnQkFDRCxPQUFPLEVBQUUsQ0FBQyxRQUF5QixFQUFFLEVBQUU7b0JBQ3JDLE1BQU0sY0FBYyxHQUFHLElBQUksY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFBO29CQUNuRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQTtnQkFDakMsQ0FBQztnQkFDRCxjQUFjLEVBQUUsR0FBRyxFQUFFO29CQUNuQixJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsRUFBRSxDQUFBO2dCQUNwQyxDQUFDO2FBQ0Y7U0FDRixDQUFDLENBQUE7SUFDSixDQUFDOzs4R0FoRVUsaUJBQWlCO2tHQUFqQixpQkFBaUIsZ1ZBZGxCLGlFQUFpRTsyRkFjaEUsaUJBQWlCO2tCQWpCN0IsU0FBUzsrQkFDRSxxQkFBcUIsY0FDbkIsSUFBSSxZQUNOLGlFQUFpRTs4QkFvQmxFLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBR0ksTUFBTTtzQkFBZixNQUFNO2dCQUNHLEtBQUs7c0JBQWQsTUFBTTtnQkFHdUIsZUFBZTtzQkFBNUMsU0FBUzt1QkFBQyxpQkFBaUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBWaWV3Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIEFmdGVyVmlld0luaXQsXG4gIE9uRGVzdHJveSxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBJZnJhbWVNYW5hZ2VyLCBDYXBpdGFsT1NFcnJvciwgVG9rZW5EYXRhLCBSYXdFcnJvckRldGFpbHMsIFRoZW1lQ29sb3JTY2hlbWUgfSBmcm9tICdAY2FwaXRhbG9zL2NvcmUnXG5pbXBvcnQgeyBDYXBpdGFsT3NBdXRoU2VydmljZSB9IGZyb20gJy4vY2FwaXRhbG9zLWF1dGguc2VydmljZSdcbmltcG9ydCB7IENBUElUQUxPU19DT05GSUcgfSBmcm9tICcuL3Byb3ZpZGUtY2FwaXRhbG9zJ1xuXG4vLyBUT0RPOiBBdXRvbWF0ZSB2ZXJzaW9uIGluamVjdGlvbiBhdCBidWlsZCB0aW1lXG5jb25zdCBTREtfVkVSU0lPTiA9ICcwLjEuMC1yYy4xJ1xuXG4vKipcbiAqIENhcmRzQXBwIGNvbXBvbmVudCB0aGF0IHJlbmRlcnMgdGhlIENhcGl0YWxPUyBjYXJkcyBpbnRlcmZhY2UgaW4gYW4gaWZyYW1lLlxuICpcbiAqIFRoZSBjb21wb25lbnQgZW1pdHMgZXZlbnRzIGZvciBsb2FkaW5nIHN0YXRlIC0gY29uc3VtZXJzIHNob3VsZCBoYW5kbGUgdGhlaXIgb3duIGxvYWRpbmcgVUk6XG4gKlxuICogYGBgaHRtbFxuICogPGRpdiAqbmdJZj1cIiFjYXJkc0xvYWRlZFwiPlxuICogICA8bXktbG9hZGluZy1zcGlubmVyPjwvbXktbG9hZGluZy1zcGlubmVyPlxuICogPC9kaXY+XG4gKiA8Y2FwaXRhbG9zLWNhcmRzLWFwcFxuICogICAobG9hZGVkKT1cImNhcmRzTG9hZGVkID0gdHJ1ZVwiXG4gKiAgIChlcnJvcik9XCJvbkNhcmRzRXJyb3IoJGV2ZW50KVwiXG4gKiA+PC9jYXBpdGFsb3MtY2FyZHMtYXBwPlxuICogYGBgXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NhcGl0YWxvcy1jYXJkcy1hcHAnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZTogYDxkaXYgI2lmcmFtZUNvbnRhaW5lciBjbGFzcz1cImNhcGl0YWxvcy1pZnJhbWUtY29udGFpbmVyXCI+PC9kaXY+YCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgOmhvc3Qge1xuICAgICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICB9XG5cbiAgICAgIC5jYXBpdGFsb3MtaWZyYW1lLWNvbnRhaW5lciB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIENhcmRzQXBwQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgLy8gSW5qZWN0ZWQgc2VydmljZXNcbiAgcHJpdmF0ZSByZWFkb25seSBhdXRoU2VydmljZSA9IGluamVjdChDYXBpdGFsT3NBdXRoU2VydmljZSlcbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWcgPSBpbmplY3QoQ0FQSVRBTE9TX0NPTkZJRylcblxuICAvLyBJbnB1dHNcbiAgQElucHV0KCkgdGhlbWU/OiBUaGVtZUNvbG9yU2NoZW1lXG4gIEBJbnB1dCgpIGhlaWdodE9mZnNldFB4ID0gMTJcbiAgQElucHV0KCkgZW5hYmxlTG9nZ2luZz86IGJvb2xlYW5cblxuICAvLyBPdXRwdXRzXG4gIEBPdXRwdXQoKSBsb2FkZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KClcbiAgQE91dHB1dCgpIGVycm9yID0gbmV3IEV2ZW50RW1pdHRlcjxDYXBpdGFsT1NFcnJvcj4oKVxuXG4gIC8vIFZpZXcgY2hpbGRyZW5cbiAgQFZpZXdDaGlsZCgnaWZyYW1lQ29udGFpbmVyJykgaWZyYW1lQ29udGFpbmVyPzogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD5cblxuICAvLyBJbnRlcm5hbCBzdGF0ZVxuICBwcml2YXRlIGlmcmFtZU1hbmFnZXI/OiBJZnJhbWVNYW5hZ2VyXG4gIHByaXZhdGUgdG9rZW5EYXRhU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uXG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIC8vIFN1YnNjcmliZSB0byB0b2tlbkRhdGEkIGFuZCBpbml0aWFsaXplIGlmcmFtZSB3aGVuIHJlYWR5XG4gICAgdGhpcy50b2tlbkRhdGFTdWJzY3JpcHRpb24gPSB0aGlzLmF1dGhTZXJ2aWNlLnRva2VuRGF0YSQuc3Vic2NyaWJlKCh0b2tlbkRhdGEpID0+IHtcbiAgICAgIGlmICh0b2tlbkRhdGEgJiYgdGhpcy5pZnJhbWVDb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplSWZyYW1lKHRva2VuRGF0YSwgdGhpcy5pZnJhbWVDb250YWluZXIubmF0aXZlRWxlbWVudClcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbkRhdGFTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKClcbiAgICB0aGlzLmlmcmFtZU1hbmFnZXI/LmRlc3Ryb3koKVxuICB9XG5cbiAgcHJpdmF0ZSBpbml0aWFsaXplSWZyYW1lKHRva2VuRGF0YTogVG9rZW5EYXRhLCBjb250YWluZXI6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgLy8gRGVzdHJveSBwcmV2aW91cyBpZnJhbWUgaWYgZXhpc3RzXG4gICAgdGhpcy5pZnJhbWVNYW5hZ2VyPy5kZXN0cm95KClcblxuICAgIGNvbnN0IHJlc29sdmVkRW5hYmxlTG9nZ2luZyA9IHRoaXMuZW5hYmxlTG9nZ2luZyA/PyB0aGlzLmNvbmZpZy5lbmFibGVMb2dnaW5nID8/IGZhbHNlXG4gICAgY29uc3QgcmVzb2x2ZWRUaGVtZSA9IHRoaXMudGhlbWUgPz8gdGhpcy5jb25maWcudGhlbWVcblxuICAgIHRoaXMuaWZyYW1lTWFuYWdlciA9IG5ldyBJZnJhbWVNYW5hZ2VyKHtcbiAgICAgIGNvbnRhaW5lcixcbiAgICAgIHRva2VuRGF0YSxcbiAgICAgIHJlbmRlcmluZ0NvbnRleHQ6IHsgZW50cnlQb2ludDogJ2NhcmRzQXBwJyB9LFxuICAgICAgdGhlbWU6IHJlc29sdmVkVGhlbWUsXG4gICAgICBlbmFibGVMb2dnaW5nOiByZXNvbHZlZEVuYWJsZUxvZ2dpbmcsXG4gICAgICBsb2dnZXI6IHRoaXMuY29uZmlnLmxvZ2dlcixcbiAgICAgIHNka1ZlcnNpb246IFNES19WRVJTSU9OLFxuICAgICAgaGVpZ2h0T2Zmc2V0UHg6IHRoaXMuaGVpZ2h0T2Zmc2V0UHgsXG4gICAgICBjYWxsYmFja3M6IHtcbiAgICAgICAgb25Mb2FkOiAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2FkZWQuZW1pdCgpXG4gICAgICAgIH0sXG4gICAgICAgIG9uRXJyb3I6IChyYXdFcnJvcjogUmF3RXJyb3JEZXRhaWxzKSA9PiB7XG4gICAgICAgICAgY29uc3QgY2FwaXRhbE9zRXJyb3IgPSBuZXcgQ2FwaXRhbE9TRXJyb3IocmF3RXJyb3IpXG4gICAgICAgICAgdGhpcy5lcnJvci5lbWl0KGNhcGl0YWxPc0Vycm9yKVxuICAgICAgICB9LFxuICAgICAgICBvblRva2VuRXhwaXJlZDogKCkgPT4ge1xuICAgICAgICAgIHRoaXMuYXV0aFNlcnZpY2UuaW52YWxpZGF0ZVRva2VuKClcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSlcbiAgfVxufVxuIl19
@@ -0,0 +1,39 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import { CapitalOsAuthService } from './capitalos-auth.service';
3
+ import { TokenExchangeService } from './token-exchange.service';
4
+ /**
5
+ * Injection token for CapitalOS configuration
6
+ */
7
+ export const CAPITALOS_CONFIG = new InjectionToken('CAPITALOS_CONFIG');
8
+ /**
9
+ * Provides the CapitalOS SDK with the specified configuration.
10
+ *
11
+ * Usage in app.config.ts (standalone):
12
+ * ```typescript
13
+ * bootstrapApplication(AppComponent, {
14
+ * providers: [
15
+ * provideCapitalOs({
16
+ * getToken: async () => {
17
+ * const response = await fetch('/api/capitalos/token');
18
+ * const data = await response.json();
19
+ * return data.token;
20
+ * },
21
+ * enableLogging: true,
22
+ * }),
23
+ * ],
24
+ * });
25
+ * ```
26
+ *
27
+ * For NgModule-based apps, use CapitalOsModule.forRoot() instead.
28
+ */
29
+ export function provideCapitalOs(config) {
30
+ return [
31
+ {
32
+ provide: CAPITALOS_CONFIG,
33
+ useValue: config,
34
+ },
35
+ TokenExchangeService,
36
+ CapitalOsAuthService,
37
+ ];
38
+ }
39
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZS1jYXBpdGFsb3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jYXBpdGFsb3MtYW5ndWxhci9zcmMvbGliL3Byb3ZpZGUtY2FwaXRhbG9zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxjQUFjLEVBQVksTUFBTSxlQUFlLENBQUE7QUFFeEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDL0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUE0Qi9EOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxjQUFjLENBQWtCLGtCQUFrQixDQUFDLENBQUE7QUFFdkY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLE1BQXVCO0lBQ3RELE9BQU87UUFDTDtZQUNFLE9BQU8sRUFBRSxnQkFBZ0I7WUFDekIsUUFBUSxFQUFFLE1BQU07U0FDakI7UUFDRCxvQkFBb0I7UUFDcEIsb0JBQW9CO0tBQ3JCLENBQUE7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4sIFByb3ZpZGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IExvZ2dlciwgVGhlbWVDb2xvclNjaGVtZSB9IGZyb20gJ0BjYXBpdGFsb3MvY29yZSdcbmltcG9ydCB7IENhcGl0YWxPc0F1dGhTZXJ2aWNlIH0gZnJvbSAnLi9jYXBpdGFsb3MtYXV0aC5zZXJ2aWNlJ1xuaW1wb3J0IHsgVG9rZW5FeGNoYW5nZVNlcnZpY2UgfSBmcm9tICcuL3Rva2VuLWV4Y2hhbmdlLnNlcnZpY2UnXG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgQ2FwaXRhbE9TIFNES1xuICovXG5leHBvcnQgaW50ZXJmYWNlIENhcGl0YWxPc0NvbmZpZyB7XG4gIC8qKlxuICAgKiBGdW5jdGlvbiB0aGF0IHJldHVybnMgYSBwcm9taXNlIHJlc29sdmluZyB0byBhIG9uZS10aW1lIHRva2VuLlxuICAgKiBUaGlzIGlzIHR5cGljYWxseSBhIGNhbGwgdG8geW91ciBiYWNrZW5kIHRoYXQgaW5pdGlhdGVzIGEgQ2FwaXRhbE9TIGxvZ2luLlxuICAgKi9cbiAgZ2V0VG9rZW46ICgpID0+IFByb21pc2U8c3RyaW5nPlxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGVuYWJsZSBsb2dnaW5nIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG4gICAqL1xuICBlbmFibGVMb2dnaW5nPzogYm9vbGVhblxuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBjdXN0b20gbG9nZ2VyIGZvciBjYXB0dXJpbmcgU0RLIGxvZ3MuXG4gICAqL1xuICBsb2dnZXI/OiBMb2dnZXJcblxuICAvKipcbiAgICogVGhlbWUgY29sb3Igc2NoZW1lIGZvciB0aGUgU0RLIGNvbXBvbmVudHMuXG4gICAqL1xuICB0aGVtZT86IFRoZW1lQ29sb3JTY2hlbWVcbn1cblxuLyoqXG4gKiBJbmplY3Rpb24gdG9rZW4gZm9yIENhcGl0YWxPUyBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBDQVBJVEFMT1NfQ09ORklHID0gbmV3IEluamVjdGlvblRva2VuPENhcGl0YWxPc0NvbmZpZz4oJ0NBUElUQUxPU19DT05GSUcnKVxuXG4vKipcbiAqIFByb3ZpZGVzIHRoZSBDYXBpdGFsT1MgU0RLIHdpdGggdGhlIHNwZWNpZmllZCBjb25maWd1cmF0aW9uLlxuICpcbiAqIFVzYWdlIGluIGFwcC5jb25maWcudHMgKHN0YW5kYWxvbmUpOlxuICogYGBgdHlwZXNjcmlwdFxuICogYm9vdHN0cmFwQXBwbGljYXRpb24oQXBwQ29tcG9uZW50LCB7XG4gKiAgIHByb3ZpZGVyczogW1xuICogICAgIHByb3ZpZGVDYXBpdGFsT3Moe1xuICogICAgICAgZ2V0VG9rZW46IGFzeW5jICgpID0+IHtcbiAqICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnL2FwaS9jYXBpdGFsb3MvdG9rZW4nKTtcbiAqICAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAqICAgICAgICAgcmV0dXJuIGRhdGEudG9rZW47XG4gKiAgICAgICB9LFxuICogICAgICAgZW5hYmxlTG9nZ2luZzogdHJ1ZSxcbiAqICAgICB9KSxcbiAqICAgXSxcbiAqIH0pO1xuICogYGBgXG4gKlxuICogRm9yIE5nTW9kdWxlLWJhc2VkIGFwcHMsIHVzZSBDYXBpdGFsT3NNb2R1bGUuZm9yUm9vdCgpIGluc3RlYWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlQ2FwaXRhbE9zKGNvbmZpZzogQ2FwaXRhbE9zQ29uZmlnKTogUHJvdmlkZXJbXSB7XG4gIHJldHVybiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogQ0FQSVRBTE9TX0NPTkZJRyxcbiAgICAgIHVzZVZhbHVlOiBjb25maWcsXG4gICAgfSxcbiAgICBUb2tlbkV4Y2hhbmdlU2VydmljZSxcbiAgICBDYXBpdGFsT3NBdXRoU2VydmljZSxcbiAgXVxufVxuIl19
@@ -0,0 +1,54 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { exchangeOneTimeToken } from '@capitalos/core';
3
+ import { CAPITALOS_CONFIG } from './provide-capitalos';
4
+ import * as i0 from "@angular/core";
5
+ const TOKEN_EXCHANGE_TIMEOUT_MS = 10000;
6
+ /**
7
+ * Service responsible for exchanging one-time tokens for long-lived JWTs.
8
+ * Creates a hidden iframe to perform the token exchange securely.
9
+ */
10
+ export class TokenExchangeService {
11
+ constructor() {
12
+ this.config = inject(CAPITALOS_CONFIG);
13
+ this.isDestroyed = false;
14
+ this.activeAbortController = null;
15
+ }
16
+ ngOnDestroy() {
17
+ this.isDestroyed = true;
18
+ this.activeAbortController?.abort();
19
+ this.activeAbortController = null;
20
+ }
21
+ /**
22
+ * Exchanges a one-time token for a long-lived JWT.
23
+ * Delegates to @capitalos/core (browser-only) which handles iframe + Penpal lifecycle.
24
+ */
25
+ async exchange(oneTimeToken, options = {}) {
26
+ if (this.isDestroyed) {
27
+ throw new Error('TokenExchangeService was destroyed');
28
+ }
29
+ // Abort any in-flight exchange when a new one begins.
30
+ this.activeAbortController?.abort();
31
+ const abortController = new AbortController();
32
+ this.activeAbortController = abortController;
33
+ try {
34
+ return await exchangeOneTimeToken({
35
+ oneTimeToken,
36
+ enableLogging: options.enableLogging,
37
+ logger: this.config.logger,
38
+ timeoutMs: TOKEN_EXCHANGE_TIMEOUT_MS,
39
+ signal: abortController.signal,
40
+ });
41
+ }
42
+ finally {
43
+ if (this.activeAbortController === abortController) {
44
+ this.activeAbortController = null;
45
+ }
46
+ }
47
+ }
48
+ }
49
+ TokenExchangeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TokenExchangeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
50
+ TokenExchangeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TokenExchangeService });
51
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TokenExchangeService, decorators: [{
52
+ type: Injectable
53
+ }] });
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tZXhjaGFuZ2Uuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NhcGl0YWxvcy1hbmd1bGFyL3NyYy9saWIvdG9rZW4tZXhjaGFuZ2Uuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBYSxNQUFNLGVBQWUsQ0FBQTtBQUM3RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTs7QUFFdEQsTUFBTSx5QkFBeUIsR0FBRyxLQUFNLENBQUE7QUFPeEM7OztHQUdHO0FBRUgsTUFBTSxPQUFPLG9CQUFvQjtJQURqQztRQUVtQixXQUFNLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUE7UUFDMUMsZ0JBQVcsR0FBRyxLQUFLLENBQUE7UUFDbkIsMEJBQXFCLEdBQTJCLElBQUksQ0FBQTtLQXFDN0Q7SUFuQ0MsV0FBVztRQUNULElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxLQUFLLEVBQUUsQ0FBQTtRQUNuQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFBO0lBQ25DLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQW9CLEVBQUUsVUFBdUMsRUFBRTtRQUM1RSxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFBO1NBQ3REO1FBRUQsc0RBQXNEO1FBQ3RELElBQUksQ0FBQyxxQkFBcUIsRUFBRSxLQUFLLEVBQUUsQ0FBQTtRQUVuQyxNQUFNLGVBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFBO1FBQzdDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxlQUFlLENBQUE7UUFFNUMsSUFBSTtZQUNGLE9BQU8sTUFBTSxvQkFBb0IsQ0FBQztnQkFDaEMsWUFBWTtnQkFDWixhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWE7Z0JBQ3BDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU07Z0JBQzFCLFNBQVMsRUFBRSx5QkFBeUI7Z0JBQ3BDLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTTthQUMvQixDQUFDLENBQUE7U0FDSDtnQkFBUztZQUNSLElBQUksSUFBSSxDQUFDLHFCQUFxQixLQUFLLGVBQWUsRUFBRTtnQkFDbEQsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQTthQUNsQztTQUNGO0lBQ0gsQ0FBQzs7aUhBdkNVLG9CQUFvQjtxSEFBcEIsb0JBQW9COzJGQUFwQixvQkFBb0I7a0JBRGhDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgeyBleGNoYW5nZU9uZVRpbWVUb2tlbiB9IGZyb20gJ0BjYXBpdGFsb3MvY29yZSdcbmltcG9ydCB7IENBUElUQUxPU19DT05GSUcgfSBmcm9tICcuL3Byb3ZpZGUtY2FwaXRhbG9zJ1xuXG5jb25zdCBUT0tFTl9FWENIQU5HRV9USU1FT1VUX01TID0gMTBfMDAwXG5cbmV4cG9ydCBpbnRlcmZhY2UgVG9rZW5FeGNoYW5nZVJlc3VsdCB7XG4gIGxvbmdMaXZlZFRva2VuOiBzdHJpbmdcbiAgYmFzZVVybDogc3RyaW5nXG59XG5cbi8qKlxuICogU2VydmljZSByZXNwb25zaWJsZSBmb3IgZXhjaGFuZ2luZyBvbmUtdGltZSB0b2tlbnMgZm9yIGxvbmctbGl2ZWQgSldUcy5cbiAqIENyZWF0ZXMgYSBoaWRkZW4gaWZyYW1lIHRvIHBlcmZvcm0gdGhlIHRva2VuIGV4Y2hhbmdlIHNlY3VyZWx5LlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVG9rZW5FeGNoYW5nZVNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZyA9IGluamVjdChDQVBJVEFMT1NfQ09ORklHKVxuICBwcml2YXRlIGlzRGVzdHJveWVkID0gZmFsc2VcbiAgcHJpdmF0ZSBhY3RpdmVBYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlciB8IG51bGwgPSBudWxsXG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5pc0Rlc3Ryb3llZCA9IHRydWVcbiAgICB0aGlzLmFjdGl2ZUFib3J0Q29udHJvbGxlcj8uYWJvcnQoKVxuICAgIHRoaXMuYWN0aXZlQWJvcnRDb250cm9sbGVyID0gbnVsbFxuICB9XG5cbiAgLyoqXG4gICAqIEV4Y2hhbmdlcyBhIG9uZS10aW1lIHRva2VuIGZvciBhIGxvbmctbGl2ZWQgSldULlxuICAgKiBEZWxlZ2F0ZXMgdG8gQGNhcGl0YWxvcy9jb3JlIChicm93c2VyLW9ubHkpIHdoaWNoIGhhbmRsZXMgaWZyYW1lICsgUGVucGFsIGxpZmVjeWNsZS5cbiAgICovXG4gIGFzeW5jIGV4Y2hhbmdlKG9uZVRpbWVUb2tlbjogc3RyaW5nLCBvcHRpb25zOiB7IGVuYWJsZUxvZ2dpbmc/OiBib29sZWFuIH0gPSB7fSk6IFByb21pc2U8VG9rZW5FeGNoYW5nZVJlc3VsdD4ge1xuICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Rva2VuRXhjaGFuZ2VTZXJ2aWNlIHdhcyBkZXN0cm95ZWQnKVxuICAgIH1cblxuICAgIC8vIEFib3J0IGFueSBpbi1mbGlnaHQgZXhjaGFuZ2Ugd2hlbiBhIG5ldyBvbmUgYmVnaW5zLlxuICAgIHRoaXMuYWN0aXZlQWJvcnRDb250cm9sbGVyPy5hYm9ydCgpXG5cbiAgICBjb25zdCBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcbiAgICB0aGlzLmFjdGl2ZUFib3J0Q29udHJvbGxlciA9IGFib3J0Q29udHJvbGxlclxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBleGNoYW5nZU9uZVRpbWVUb2tlbih7XG4gICAgICAgIG9uZVRpbWVUb2tlbixcbiAgICAgICAgZW5hYmxlTG9nZ2luZzogb3B0aW9ucy5lbmFibGVMb2dnaW5nLFxuICAgICAgICBsb2dnZXI6IHRoaXMuY29uZmlnLmxvZ2dlcixcbiAgICAgICAgdGltZW91dE1zOiBUT0tFTl9FWENIQU5HRV9USU1FT1VUX01TLFxuICAgICAgICBzaWduYWw6IGFib3J0Q29udHJvbGxlci5zaWduYWwsXG4gICAgICB9KVxuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAodGhpcy5hY3RpdmVBYm9ydENvbnRyb2xsZXIgPT09IGFib3J0Q29udHJvbGxlcikge1xuICAgICAgICB0aGlzLmFjdGl2ZUFib3J0Q29udHJvbGxlciA9IG51bGxcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,13 @@
1
+ /*
2
+ * Public API Surface of @capitalos/angular
3
+ */
4
+ // Components
5
+ export { CardsAppComponent } from './lib/cards-app.component';
6
+ // Services
7
+ export { CapitalOsAuthService } from './lib/capitalos-auth.service';
8
+ // Provider (standalone)
9
+ export { provideCapitalOs, CAPITALOS_CONFIG } from './lib/provide-capitalos';
10
+ // Module (NgModule-based apps)
11
+ export { CapitalOsModule } from './lib/capitalos.module';
12
+ export { CapitalOSError, ErrorCode } from '@capitalos/core';
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2NhcGl0YWxvcy1hbmd1bGFyL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsYUFBYTtBQUNiLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDJCQUEyQixDQUFBO0FBRTdELFdBQVc7QUFDWCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQTtBQUduRSx3QkFBd0I7QUFDeEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFHNUUsK0JBQStCO0FBQy9CLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUt4RCxPQUFPLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiBAY2FwaXRhbG9zL2FuZ3VsYXJcbiAqL1xuXG4vLyBDb21wb25lbnRzXG5leHBvcnQgeyBDYXJkc0FwcENvbXBvbmVudCB9IGZyb20gJy4vbGliL2NhcmRzLWFwcC5jb21wb25lbnQnXG5cbi8vIFNlcnZpY2VzXG5leHBvcnQgeyBDYXBpdGFsT3NBdXRoU2VydmljZSB9IGZyb20gJy4vbGliL2NhcGl0YWxvcy1hdXRoLnNlcnZpY2UnXG5leHBvcnQgdHlwZSB7IEF1dGhTdGF0ZSB9IGZyb20gJy4vbGliL2NhcGl0YWxvcy1hdXRoLnNlcnZpY2UnXG5cbi8vIFByb3ZpZGVyIChzdGFuZGFsb25lKVxuZXhwb3J0IHsgcHJvdmlkZUNhcGl0YWxPcywgQ0FQSVRBTE9TX0NPTkZJRyB9IGZyb20gJy4vbGliL3Byb3ZpZGUtY2FwaXRhbG9zJ1xuZXhwb3J0IHR5cGUgeyBDYXBpdGFsT3NDb25maWcgfSBmcm9tICcuL2xpYi9wcm92aWRlLWNhcGl0YWxvcydcblxuLy8gTW9kdWxlIChOZ01vZHVsZS1iYXNlZCBhcHBzKVxuZXhwb3J0IHsgQ2FwaXRhbE9zTW9kdWxlIH0gZnJvbSAnLi9saWIvY2FwaXRhbG9zLm1vZHVsZSdcblxuLy8gUmUtZXhwb3J0IGNvbW1vbmx5IHVzZWQgdHlwZXMgZnJvbSBjb3JlXG5leHBvcnQgdHlwZSB7IFRoZW1lQ29sb3JTY2hlbWUsIExvZ2dlciwgVG9rZW5EYXRhLCBSYXdFcnJvckRldGFpbHMgfSBmcm9tICdAY2FwaXRhbG9zL2NvcmUnXG5cbmV4cG9ydCB7IENhcGl0YWxPU0Vycm9yLCBFcnJvckNvZGUgfSBmcm9tICdAY2FwaXRhbG9zL2NvcmUnXG4iXX0=