@cranberry-money/shared-services 4.0.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/dist/api/functional-client.d.ts +0 -66
- package/dist/api/functional-client.d.ts.map +0 -1
- package/dist/api/functional-client.js +0 -165
- package/dist/auth/functional/auth-operations.d.ts +0 -116
- package/dist/auth/functional/auth-operations.d.ts.map +0 -1
- package/dist/auth/functional/auth-operations.js +0 -246
- package/dist/auth/functional/auth-state.d.ts +0 -38
- package/dist/auth/functional/auth-state.d.ts.map +0 -1
- package/dist/auth/functional/auth-state.js +0 -87
- package/dist/auth/functional/token-storage.d.ts +0 -44
- package/dist/auth/functional/token-storage.d.ts.map +0 -1
- package/dist/auth/functional/token-storage.js +0 -178
- package/dist/auth/react/AuthProvider.d.ts +0 -92
- package/dist/auth/react/AuthProvider.d.ts.map +0 -1
- package/dist/auth/react/AuthProvider.js +0 -207
- package/dist/integration/blueberry-integration.d.ts +0 -21
- package/dist/integration/blueberry-integration.d.ts.map +0 -1
- package/dist/integration/blueberry-integration.js +0 -109
- package/dist/integration/index.d.ts +0 -8
- package/dist/integration/index.d.ts.map +0 -1
- package/dist/integration/index.js +0 -18
- package/dist/services/accounts.d.ts +0 -220
- package/dist/services/accounts.d.ts.map +0 -1
- package/dist/services/accounts.js +0 -175
- package/dist/services/banks.d.ts +0 -123
- package/dist/services/banks.d.ts.map +0 -1
- package/dist/services/banks.js +0 -151
- package/dist/services/cash-accounts.d.ts +0 -112
- package/dist/services/cash-accounts.d.ts.map +0 -1
- package/dist/services/cash-accounts.js +0 -222
- package/dist/services/documents.d.ts +0 -143
- package/dist/services/documents.d.ts.map +0 -1
- package/dist/services/documents.js +0 -253
- package/dist/services/factories/account-factory.d.ts +0 -16
- package/dist/services/factories/account-factory.d.ts.map +0 -1
- package/dist/services/factories/account-factory.js +0 -79
- package/dist/services/factories/auth-factory.d.ts +0 -23
- package/dist/services/factories/auth-factory.d.ts.map +0 -1
- package/dist/services/factories/auth-factory.js +0 -75
- package/dist/services/factories/bank-factory.d.ts +0 -16
- package/dist/services/factories/bank-factory.d.ts.map +0 -1
- package/dist/services/factories/bank-factory.js +0 -72
- package/dist/services/factories/cash-account-factory.d.ts +0 -16
- package/dist/services/factories/cash-account-factory.d.ts.map +0 -1
- package/dist/services/factories/cash-account-factory.js +0 -74
- package/dist/services/factories/document-factory.d.ts +0 -16
- package/dist/services/factories/document-factory.d.ts.map +0 -1
- package/dist/services/factories/document-factory.js +0 -85
- package/dist/services/factories/index.d.ts +0 -21
- package/dist/services/factories/index.d.ts.map +0 -1
- package/dist/services/factories/index.js +0 -40
- package/dist/services/factories/instrument-factory.d.ts +0 -16
- package/dist/services/factories/instrument-factory.d.ts.map +0 -1
- package/dist/services/factories/instrument-factory.js +0 -68
- package/dist/services/factories/master-factory.d.ts +0 -74
- package/dist/services/factories/master-factory.d.ts.map +0 -1
- package/dist/services/factories/master-factory.js +0 -183
- package/dist/services/factories/portfolio-factory.d.ts +0 -16
- package/dist/services/factories/portfolio-factory.d.ts.map +0 -1
- package/dist/services/factories/portfolio-factory.js +0 -74
- package/dist/services/factories/portfolio-template-factory.d.ts +0 -16
- package/dist/services/factories/portfolio-template-factory.d.ts.map +0 -1
- package/dist/services/factories/portfolio-template-factory.js +0 -76
- package/dist/services/factories/reference-data-factory.d.ts +0 -16
- package/dist/services/factories/reference-data-factory.d.ts.map +0 -1
- package/dist/services/factories/reference-data-factory.js +0 -86
- package/dist/services/factories/tax-residency-factory.d.ts +0 -16
- package/dist/services/factories/tax-residency-factory.d.ts.map +0 -1
- package/dist/services/factories/tax-residency-factory.js +0 -73
- package/dist/services/factories/trade-factory.d.ts +0 -16
- package/dist/services/factories/trade-factory.d.ts.map +0 -1
- package/dist/services/factories/trade-factory.js +0 -79
- package/dist/services/factories/types.d.ts +0 -250
- package/dist/services/factories/types.d.ts.map +0 -1
- package/dist/services/factories/types.js +0 -32
- package/dist/services/factories/withdrawal-factory.d.ts +0 -16
- package/dist/services/factories/withdrawal-factory.d.ts.map +0 -1
- package/dist/services/factories/withdrawal-factory.js +0 -78
- package/dist/services/instruments.d.ts +0 -138
- package/dist/services/instruments.d.ts.map +0 -1
- package/dist/services/instruments.js +0 -178
- package/dist/services/portfolio-templates.d.ts +0 -142
- package/dist/services/portfolio-templates.d.ts.map +0 -1
- package/dist/services/portfolio-templates.js +0 -201
- package/dist/services/portfolios.d.ts +0 -157
- package/dist/services/portfolios.d.ts.map +0 -1
- package/dist/services/portfolios.js +0 -144
- package/dist/services/reference-data.d.ts +0 -185
- package/dist/services/reference-data.d.ts.map +0 -1
- package/dist/services/reference-data.js +0 -245
- package/dist/services/tax-residencies.d.ts +0 -83
- package/dist/services/tax-residencies.d.ts.map +0 -1
- package/dist/services/tax-residencies.js +0 -179
- package/dist/services/trades.d.ts +0 -190
- package/dist/services/trades.d.ts.map +0 -1
- package/dist/services/trades.js +0 -207
- package/dist/services/withdrawals.d.ts +0 -236
- package/dist/services/withdrawals.d.ts.map +0 -1
- package/dist/services/withdrawals.js +0 -345
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cranberry-money/shared-services",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Functional architecture shared services with pure functions, dependency injection, and comprehensive TypeScript support for the MyPortfolio platform",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
@@ -22,8 +23,8 @@
|
|
|
22
23
|
"clean": "rm -rf dist",
|
|
23
24
|
"typecheck": "tsc --noEmit",
|
|
24
25
|
"dev": "tsc --watch",
|
|
25
|
-
"lint": "eslint src
|
|
26
|
-
"lint:fix": "eslint src --
|
|
26
|
+
"lint": "eslint src",
|
|
27
|
+
"lint:fix": "eslint src --fix"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
30
|
"axios": "^1.7.0"
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Functional API Client - Pure functional approach
|
|
3
|
-
*
|
|
4
|
-
* Replaces the global singleton pattern with explicit dependency injection.
|
|
5
|
-
* All dependencies are passed explicitly, making testing and configuration clear.
|
|
6
|
-
*/
|
|
7
|
-
export interface ApiClient {
|
|
8
|
-
get<T>(url: string, config?: RequestConfig): Promise<T>;
|
|
9
|
-
post<T>(url: string, data?: unknown, config?: RequestConfig): Promise<T>;
|
|
10
|
-
patch<T>(url: string, data?: unknown, config?: RequestConfig): Promise<T>;
|
|
11
|
-
delete<T>(url: string, config?: RequestConfig): Promise<T>;
|
|
12
|
-
}
|
|
13
|
-
export interface RequestConfig {
|
|
14
|
-
params?: Record<string, string>;
|
|
15
|
-
headers?: Record<string, string>;
|
|
16
|
-
timeout?: number;
|
|
17
|
-
}
|
|
18
|
-
export interface ApiClientConfig {
|
|
19
|
-
baseURL: string;
|
|
20
|
-
timeout?: number;
|
|
21
|
-
defaultHeaders?: Record<string, string>;
|
|
22
|
-
withCredentials?: boolean;
|
|
23
|
-
}
|
|
24
|
-
export interface ApiError {
|
|
25
|
-
message: string;
|
|
26
|
-
status?: number;
|
|
27
|
-
code?: string;
|
|
28
|
-
details?: Record<string, unknown>;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Create a functional API client with explicit configuration
|
|
32
|
-
*
|
|
33
|
-
* @param config - API client configuration
|
|
34
|
-
* @returns Pure functional API client interface
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```typescript
|
|
38
|
-
* const apiClient = createApiClient({
|
|
39
|
-
* baseURL: 'https://api.example.com',
|
|
40
|
-
* timeout: 30000,
|
|
41
|
-
* withCredentials: true,
|
|
42
|
-
* });
|
|
43
|
-
*
|
|
44
|
-
* const data = await apiClient.get<User[]>('/users');
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export declare const createApiClient: (config: ApiClientConfig) => ApiClient;
|
|
48
|
-
/**
|
|
49
|
-
* Create a web-optimized API client
|
|
50
|
-
*
|
|
51
|
-
* @param baseURL - API base URL
|
|
52
|
-
* @returns API client configured for web environments
|
|
53
|
-
*/
|
|
54
|
-
export declare const createWebApiClient: (baseURL: string) => ApiClient;
|
|
55
|
-
/**
|
|
56
|
-
* Create a mobile-optimized API client
|
|
57
|
-
*
|
|
58
|
-
* @param baseURL - API base URL
|
|
59
|
-
* @returns API client configured for mobile environments
|
|
60
|
-
*/
|
|
61
|
-
export declare const createMobileApiClient: (baseURL: string) => ApiClient;
|
|
62
|
-
/**
|
|
63
|
-
* Utility function to check if an error is an API error
|
|
64
|
-
*/
|
|
65
|
-
export declare const isApiError: (error: unknown) => error is ApiError;
|
|
66
|
-
//# sourceMappingURL=functional-client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"functional-client.d.ts","sourceRoot":"","sources":["../../src/api/functional-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzE,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,eAAe,KAAG,SA+FzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,SAQpD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,KAAG,SAQvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,QAOpD,CAAC"}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Functional API Client - Pure functional approach
|
|
4
|
-
*
|
|
5
|
-
* Replaces the global singleton pattern with explicit dependency injection.
|
|
6
|
-
* All dependencies are passed explicitly, making testing and configuration clear.
|
|
7
|
-
*/
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.isApiError = exports.createMobileApiClient = exports.createWebApiClient = exports.createApiClient = void 0;
|
|
13
|
-
const axios_1 = __importDefault(require("axios"));
|
|
14
|
-
/**
|
|
15
|
-
* Create a functional API client with explicit configuration
|
|
16
|
-
*
|
|
17
|
-
* @param config - API client configuration
|
|
18
|
-
* @returns Pure functional API client interface
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```typescript
|
|
22
|
-
* const apiClient = createApiClient({
|
|
23
|
-
* baseURL: 'https://api.example.com',
|
|
24
|
-
* timeout: 30000,
|
|
25
|
-
* withCredentials: true,
|
|
26
|
-
* });
|
|
27
|
-
*
|
|
28
|
-
* const data = await apiClient.get<User[]>('/users');
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
const createApiClient = (config) => {
|
|
32
|
-
// Validate configuration
|
|
33
|
-
if (!config.baseURL) {
|
|
34
|
-
throw new Error('API client baseURL is required');
|
|
35
|
-
}
|
|
36
|
-
if (!config.baseURL.startsWith('http://') && !config.baseURL.startsWith('https://')) {
|
|
37
|
-
throw new Error('API client baseURL must be a valid HTTP/HTTPS URL');
|
|
38
|
-
}
|
|
39
|
-
// Create axios instance with configuration
|
|
40
|
-
const axiosInstance = axios_1.default.create({
|
|
41
|
-
baseURL: config.baseURL,
|
|
42
|
-
timeout: config.timeout ?? 30000,
|
|
43
|
-
headers: {
|
|
44
|
-
'Content-Type': 'application/json',
|
|
45
|
-
...config.defaultHeaders,
|
|
46
|
-
},
|
|
47
|
-
withCredentials: config.withCredentials ?? true,
|
|
48
|
-
});
|
|
49
|
-
// Error handling helper
|
|
50
|
-
const handleError = (error) => {
|
|
51
|
-
if (axios_1.default.isAxiosError(error)) {
|
|
52
|
-
const axiosError = error;
|
|
53
|
-
const responseData = axiosError.response?.data;
|
|
54
|
-
const apiError = {
|
|
55
|
-
message: responseData?.message ||
|
|
56
|
-
responseData?.detail ||
|
|
57
|
-
axiosError.message,
|
|
58
|
-
status: axiosError.response?.status,
|
|
59
|
-
code: responseData?.code,
|
|
60
|
-
details: responseData?.details,
|
|
61
|
-
};
|
|
62
|
-
throw apiError;
|
|
63
|
-
}
|
|
64
|
-
// Re-throw non-axios errors
|
|
65
|
-
throw error;
|
|
66
|
-
};
|
|
67
|
-
// Return pure functional interface
|
|
68
|
-
return {
|
|
69
|
-
async get(url, config) {
|
|
70
|
-
try {
|
|
71
|
-
const response = await axiosInstance.get(url, {
|
|
72
|
-
params: config?.params,
|
|
73
|
-
headers: config?.headers,
|
|
74
|
-
timeout: config?.timeout,
|
|
75
|
-
});
|
|
76
|
-
return response.data;
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
return handleError(error);
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
async post(url, data, config) {
|
|
83
|
-
try {
|
|
84
|
-
const response = await axiosInstance.post(url, data, {
|
|
85
|
-
params: config?.params,
|
|
86
|
-
headers: config?.headers,
|
|
87
|
-
timeout: config?.timeout,
|
|
88
|
-
});
|
|
89
|
-
return response.data;
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
return handleError(error);
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
async patch(url, data, config) {
|
|
96
|
-
try {
|
|
97
|
-
const response = await axiosInstance.patch(url, data, {
|
|
98
|
-
params: config?.params,
|
|
99
|
-
headers: config?.headers,
|
|
100
|
-
timeout: config?.timeout,
|
|
101
|
-
});
|
|
102
|
-
return response.data;
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
return handleError(error);
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
async delete(url, config) {
|
|
109
|
-
try {
|
|
110
|
-
const response = await axiosInstance.delete(url, {
|
|
111
|
-
params: config?.params,
|
|
112
|
-
headers: config?.headers,
|
|
113
|
-
timeout: config?.timeout,
|
|
114
|
-
});
|
|
115
|
-
return response.data;
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
return handleError(error);
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
|
-
exports.createApiClient = createApiClient;
|
|
124
|
-
/**
|
|
125
|
-
* Create a web-optimized API client
|
|
126
|
-
*
|
|
127
|
-
* @param baseURL - API base URL
|
|
128
|
-
* @returns API client configured for web environments
|
|
129
|
-
*/
|
|
130
|
-
const createWebApiClient = (baseURL) => {
|
|
131
|
-
return (0, exports.createApiClient)({
|
|
132
|
-
baseURL,
|
|
133
|
-
withCredentials: true,
|
|
134
|
-
defaultHeaders: {
|
|
135
|
-
'X-Requested-With': 'XMLHttpRequest',
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
};
|
|
139
|
-
exports.createWebApiClient = createWebApiClient;
|
|
140
|
-
/**
|
|
141
|
-
* Create a mobile-optimized API client
|
|
142
|
-
*
|
|
143
|
-
* @param baseURL - API base URL
|
|
144
|
-
* @returns API client configured for mobile environments
|
|
145
|
-
*/
|
|
146
|
-
const createMobileApiClient = (baseURL) => {
|
|
147
|
-
return (0, exports.createApiClient)({
|
|
148
|
-
baseURL,
|
|
149
|
-
withCredentials: false, // Mobile doesn't use cookies
|
|
150
|
-
defaultHeaders: {
|
|
151
|
-
'X-Platform': 'mobile',
|
|
152
|
-
},
|
|
153
|
-
});
|
|
154
|
-
};
|
|
155
|
-
exports.createMobileApiClient = createMobileApiClient;
|
|
156
|
-
/**
|
|
157
|
-
* Utility function to check if an error is an API error
|
|
158
|
-
*/
|
|
159
|
-
const isApiError = (error) => {
|
|
160
|
-
return (typeof error === 'object' &&
|
|
161
|
-
error !== null &&
|
|
162
|
-
'message' in error &&
|
|
163
|
-
typeof error.message === 'string');
|
|
164
|
-
};
|
|
165
|
-
exports.isApiError = isApiError;
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure Authentication Operations
|
|
3
|
-
*
|
|
4
|
-
* All authentication operations as pure functions with explicit dependencies.
|
|
5
|
-
* No side effects, no global state - everything is explicit and testable.
|
|
6
|
-
*/
|
|
7
|
-
import type { ApiClient } from '../../api/functional-client';
|
|
8
|
-
import type { UserProfile, TokenPair } from './auth-state';
|
|
9
|
-
export type { TokenPair } from './auth-state';
|
|
10
|
-
export interface TokenStorage {
|
|
11
|
-
storeTokens(tokens: TokenPair): Promise<void>;
|
|
12
|
-
retrieveTokens(): Promise<TokenPair | null>;
|
|
13
|
-
clearTokens(): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
export interface AuthDependencies {
|
|
16
|
-
apiClient: ApiClient;
|
|
17
|
-
tokenStorage: TokenStorage;
|
|
18
|
-
}
|
|
19
|
-
export interface SigninPayload {
|
|
20
|
-
email: string;
|
|
21
|
-
password: string;
|
|
22
|
-
}
|
|
23
|
-
export interface SignupPayload {
|
|
24
|
-
email: string;
|
|
25
|
-
password: string;
|
|
26
|
-
passwordConfirm: string;
|
|
27
|
-
firstName?: string;
|
|
28
|
-
lastName?: string;
|
|
29
|
-
}
|
|
30
|
-
export interface EmailVerificationPayload {
|
|
31
|
-
token: string;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Sign in with credentials
|
|
35
|
-
*
|
|
36
|
-
* @param credentials - User login credentials
|
|
37
|
-
* @param deps - Required dependencies (API client and token storage)
|
|
38
|
-
* @returns Promise resolving to user profile and tokens
|
|
39
|
-
*/
|
|
40
|
-
export declare const signin: (credentials: SigninPayload, deps: AuthDependencies) => Promise<{
|
|
41
|
-
user: UserProfile;
|
|
42
|
-
tokens: TokenPair;
|
|
43
|
-
}>;
|
|
44
|
-
/**
|
|
45
|
-
* Sign out user
|
|
46
|
-
*
|
|
47
|
-
* @param deps - Required dependencies
|
|
48
|
-
* @returns Promise resolving when signout is complete
|
|
49
|
-
*/
|
|
50
|
-
export declare const signout: (deps: AuthDependencies) => Promise<void>;
|
|
51
|
-
/**
|
|
52
|
-
* Sign up new user
|
|
53
|
-
*
|
|
54
|
-
* @param userData - User registration data
|
|
55
|
-
* @param deps - Required dependencies
|
|
56
|
-
* @returns Promise resolving to success status and optional message
|
|
57
|
-
*/
|
|
58
|
-
export declare const signup: (userData: SignupPayload, deps: AuthDependencies) => Promise<{
|
|
59
|
-
success: boolean;
|
|
60
|
-
message?: string;
|
|
61
|
-
}>;
|
|
62
|
-
/**
|
|
63
|
-
* Refresh authentication tokens
|
|
64
|
-
*
|
|
65
|
-
* @param currentTokens - Current token pair
|
|
66
|
-
* @param deps - Required dependencies
|
|
67
|
-
* @returns Promise resolving to new token pair
|
|
68
|
-
*/
|
|
69
|
-
export declare const refreshTokens: (currentTokens: TokenPair, deps: AuthDependencies) => Promise<TokenPair>;
|
|
70
|
-
/**
|
|
71
|
-
* Get user profile from API
|
|
72
|
-
*
|
|
73
|
-
* @param apiClient - API client instance
|
|
74
|
-
* @returns Promise resolving to user profile
|
|
75
|
-
*/
|
|
76
|
-
export declare const getUserProfile: (apiClient: ApiClient) => Promise<UserProfile>;
|
|
77
|
-
/**
|
|
78
|
-
* Verify email address
|
|
79
|
-
*
|
|
80
|
-
* @param verificationData - Email verification data
|
|
81
|
-
* @param deps - Required dependencies
|
|
82
|
-
* @returns Promise resolving to success status
|
|
83
|
-
*/
|
|
84
|
-
export declare const verifyEmail: (verificationData: EmailVerificationPayload, deps: AuthDependencies) => Promise<{
|
|
85
|
-
success: boolean;
|
|
86
|
-
message?: string;
|
|
87
|
-
}>;
|
|
88
|
-
/**
|
|
89
|
-
* Resend verification code
|
|
90
|
-
*
|
|
91
|
-
* @param deps - Required dependencies
|
|
92
|
-
* @returns Promise resolving to success status
|
|
93
|
-
*/
|
|
94
|
-
export declare const resendVerificationCode: (deps: AuthDependencies) => Promise<{
|
|
95
|
-
success: boolean;
|
|
96
|
-
message?: string;
|
|
97
|
-
}>;
|
|
98
|
-
/**
|
|
99
|
-
* Initialize authentication from stored tokens
|
|
100
|
-
*
|
|
101
|
-
* @param deps - Required dependencies
|
|
102
|
-
* @returns Promise resolving to user and tokens if valid, null otherwise
|
|
103
|
-
*/
|
|
104
|
-
export declare const initializeFromStorage: (deps: AuthDependencies) => Promise<{
|
|
105
|
-
user: UserProfile;
|
|
106
|
-
tokens: TokenPair;
|
|
107
|
-
} | null>;
|
|
108
|
-
/**
|
|
109
|
-
* Validate signin credentials
|
|
110
|
-
*/
|
|
111
|
-
export declare const validateSigninCredentials: (credentials: SigninPayload) => string[];
|
|
112
|
-
/**
|
|
113
|
-
* Validate signup data
|
|
114
|
-
*/
|
|
115
|
-
export declare const validateSignupData: (userData: SignupPayload) => string[];
|
|
116
|
-
//# sourceMappingURL=auth-operations.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-operations.d.ts","sourceRoot":"","sources":["../../../src/auth/functional/auth-operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG3D,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC5C,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAGD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;CACf;AAoBD;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GACjB,aAAa,aAAa,EAC1B,MAAM,gBAAgB,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,CAqBlD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAU,MAAM,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAUlE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GACjB,UAAU,aAAa,EACvB,MAAM,gBAAgB,KACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAahD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GACxB,eAAe,SAAS,EACxB,MAAM,gBAAgB,KACrB,OAAO,CAAC,SAAS,CAqBnB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAU,WAAW,SAAS,KAAG,OAAO,CAAC,WAAW,CAM9E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GACtB,kBAAkB,wBAAwB,EAC1C,MAAM,gBAAgB,KACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAOhD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,gBAAgB,KACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAOhD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAM,gBAAgB,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAAG,IAAI,CAiBzD,CAAC;AAkCF;;GAEG;AACH,eAAO,MAAM,yBAAyB,GAAI,aAAa,aAAa,KAAG,MAAM,EAc5E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,aAAa,KAAG,MAAM,EAkBlE,CAAC"}
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pure Authentication Operations
|
|
4
|
-
*
|
|
5
|
-
* All authentication operations as pure functions with explicit dependencies.
|
|
6
|
-
* No side effects, no global state - everything is explicit and testable.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.validateSignupData = exports.validateSigninCredentials = exports.initializeFromStorage = exports.resendVerificationCode = exports.verifyEmail = exports.getUserProfile = exports.refreshTokens = exports.signup = exports.signout = exports.signin = void 0;
|
|
10
|
-
// Pure authentication operations
|
|
11
|
-
/**
|
|
12
|
-
* Sign in with credentials
|
|
13
|
-
*
|
|
14
|
-
* @param credentials - User login credentials
|
|
15
|
-
* @param deps - Required dependencies (API client and token storage)
|
|
16
|
-
* @returns Promise resolving to user profile and tokens
|
|
17
|
-
*/
|
|
18
|
-
const signin = async (credentials, deps) => {
|
|
19
|
-
try {
|
|
20
|
-
// Call signin API
|
|
21
|
-
const response = await deps.apiClient.post('/api/signin/', credentials);
|
|
22
|
-
// Extract tokens from response
|
|
23
|
-
const tokens = {
|
|
24
|
-
access: response.access,
|
|
25
|
-
refresh: response.refresh,
|
|
26
|
-
};
|
|
27
|
-
// Store tokens
|
|
28
|
-
await deps.tokenStorage.storeTokens(tokens);
|
|
29
|
-
// Get user profile (either from signin response or separate call)
|
|
30
|
-
const user = response.user || await (0, exports.getUserProfile)(deps.apiClient);
|
|
31
|
-
return { user, tokens };
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
throw new Error(extractErrorMessage(error));
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
exports.signin = signin;
|
|
38
|
-
/**
|
|
39
|
-
* Sign out user
|
|
40
|
-
*
|
|
41
|
-
* @param deps - Required dependencies
|
|
42
|
-
* @returns Promise resolving when signout is complete
|
|
43
|
-
*/
|
|
44
|
-
const signout = async (deps) => {
|
|
45
|
-
try {
|
|
46
|
-
// Best effort API call - don't fail signout if API call fails
|
|
47
|
-
await deps.apiClient.post('/api/signout/');
|
|
48
|
-
}
|
|
49
|
-
catch (error) {
|
|
50
|
-
console.warn('API signout failed, continuing with local cleanup:', error);
|
|
51
|
-
}
|
|
52
|
-
finally {
|
|
53
|
-
// Always clear local tokens
|
|
54
|
-
await deps.tokenStorage.clearTokens();
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
exports.signout = signout;
|
|
58
|
-
/**
|
|
59
|
-
* Sign up new user
|
|
60
|
-
*
|
|
61
|
-
* @param userData - User registration data
|
|
62
|
-
* @param deps - Required dependencies
|
|
63
|
-
* @returns Promise resolving to success status and optional message
|
|
64
|
-
*/
|
|
65
|
-
const signup = async (userData, deps) => {
|
|
66
|
-
try {
|
|
67
|
-
const response = await deps.apiClient.post('/api/signup/', userData);
|
|
68
|
-
return {
|
|
69
|
-
success: true,
|
|
70
|
-
message: response.message || 'Account created successfully'
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
return {
|
|
75
|
-
success: false,
|
|
76
|
-
message: extractErrorMessage(error)
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
exports.signup = signup;
|
|
81
|
-
/**
|
|
82
|
-
* Refresh authentication tokens
|
|
83
|
-
*
|
|
84
|
-
* @param currentTokens - Current token pair
|
|
85
|
-
* @param deps - Required dependencies
|
|
86
|
-
* @returns Promise resolving to new token pair
|
|
87
|
-
*/
|
|
88
|
-
const refreshTokens = async (currentTokens, deps) => {
|
|
89
|
-
try {
|
|
90
|
-
const response = await deps.apiClient.post('/api/token/refresh/', { refresh: currentTokens.refresh });
|
|
91
|
-
const newTokens = {
|
|
92
|
-
access: response.access,
|
|
93
|
-
refresh: response.refresh,
|
|
94
|
-
};
|
|
95
|
-
// Store new tokens
|
|
96
|
-
await deps.tokenStorage.storeTokens(newTokens);
|
|
97
|
-
return newTokens;
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
// If refresh fails, clear stored tokens
|
|
101
|
-
await deps.tokenStorage.clearTokens();
|
|
102
|
-
throw new Error('Token refresh failed');
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
exports.refreshTokens = refreshTokens;
|
|
106
|
-
/**
|
|
107
|
-
* Get user profile from API
|
|
108
|
-
*
|
|
109
|
-
* @param apiClient - API client instance
|
|
110
|
-
* @returns Promise resolving to user profile
|
|
111
|
-
*/
|
|
112
|
-
const getUserProfile = async (apiClient) => {
|
|
113
|
-
try {
|
|
114
|
-
return await apiClient.get('/api/profile/');
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
throw new Error(`Failed to fetch user profile: ${extractErrorMessage(error)}`);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
exports.getUserProfile = getUserProfile;
|
|
121
|
-
/**
|
|
122
|
-
* Verify email address
|
|
123
|
-
*
|
|
124
|
-
* @param verificationData - Email verification data
|
|
125
|
-
* @param deps - Required dependencies
|
|
126
|
-
* @returns Promise resolving to success status
|
|
127
|
-
*/
|
|
128
|
-
const verifyEmail = async (verificationData, deps) => {
|
|
129
|
-
try {
|
|
130
|
-
await deps.apiClient.post('/api/email-verification/', verificationData);
|
|
131
|
-
return { success: true, message: 'Email verified successfully' };
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
return { success: false, message: extractErrorMessage(error) };
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
exports.verifyEmail = verifyEmail;
|
|
138
|
-
/**
|
|
139
|
-
* Resend verification code
|
|
140
|
-
*
|
|
141
|
-
* @param deps - Required dependencies
|
|
142
|
-
* @returns Promise resolving to success status
|
|
143
|
-
*/
|
|
144
|
-
const resendVerificationCode = async (deps) => {
|
|
145
|
-
try {
|
|
146
|
-
await deps.apiClient.post('/api/resend-verification/');
|
|
147
|
-
return { success: true, message: 'Verification code sent' };
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
return { success: false, message: extractErrorMessage(error) };
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
exports.resendVerificationCode = resendVerificationCode;
|
|
154
|
-
/**
|
|
155
|
-
* Initialize authentication from stored tokens
|
|
156
|
-
*
|
|
157
|
-
* @param deps - Required dependencies
|
|
158
|
-
* @returns Promise resolving to user and tokens if valid, null otherwise
|
|
159
|
-
*/
|
|
160
|
-
const initializeFromStorage = async (deps) => {
|
|
161
|
-
try {
|
|
162
|
-
// Try to retrieve stored tokens
|
|
163
|
-
const tokens = await deps.tokenStorage.retrieveTokens();
|
|
164
|
-
if (!tokens) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
// Verify tokens are still valid by fetching user profile
|
|
168
|
-
const user = await (0, exports.getUserProfile)(deps.apiClient);
|
|
169
|
-
return { user, tokens };
|
|
170
|
-
}
|
|
171
|
-
catch (error) {
|
|
172
|
-
// If verification fails, clear invalid tokens
|
|
173
|
-
await deps.tokenStorage.clearTokens();
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
exports.initializeFromStorage = initializeFromStorage;
|
|
178
|
-
// Utility functions
|
|
179
|
-
/**
|
|
180
|
-
* Extract error message from various error formats
|
|
181
|
-
*/
|
|
182
|
-
const extractErrorMessage = (error) => {
|
|
183
|
-
if (typeof error === 'string') {
|
|
184
|
-
return error;
|
|
185
|
-
}
|
|
186
|
-
if (error && typeof error === 'object') {
|
|
187
|
-
const errorObj = error;
|
|
188
|
-
// API error format
|
|
189
|
-
if (errorObj.message) {
|
|
190
|
-
return errorObj.message;
|
|
191
|
-
}
|
|
192
|
-
// Django REST framework format
|
|
193
|
-
if (errorObj.detail) {
|
|
194
|
-
return errorObj.detail;
|
|
195
|
-
}
|
|
196
|
-
// Standard Error object
|
|
197
|
-
if (errorObj.message) {
|
|
198
|
-
return errorObj.message;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return 'An unexpected error occurred';
|
|
202
|
-
};
|
|
203
|
-
/**
|
|
204
|
-
* Validate signin credentials
|
|
205
|
-
*/
|
|
206
|
-
const validateSigninCredentials = (credentials) => {
|
|
207
|
-
const errors = [];
|
|
208
|
-
if (!credentials.email || !credentials.email.trim()) {
|
|
209
|
-
errors.push('Email is required');
|
|
210
|
-
}
|
|
211
|
-
else if (!isValidEmail(credentials.email)) {
|
|
212
|
-
errors.push('Invalid email format');
|
|
213
|
-
}
|
|
214
|
-
if (!credentials.password || credentials.password.length < 1) {
|
|
215
|
-
errors.push('Password is required');
|
|
216
|
-
}
|
|
217
|
-
return errors;
|
|
218
|
-
};
|
|
219
|
-
exports.validateSigninCredentials = validateSigninCredentials;
|
|
220
|
-
/**
|
|
221
|
-
* Validate signup data
|
|
222
|
-
*/
|
|
223
|
-
const validateSignupData = (userData) => {
|
|
224
|
-
const errors = [];
|
|
225
|
-
if (!userData.email || !userData.email.trim()) {
|
|
226
|
-
errors.push('Email is required');
|
|
227
|
-
}
|
|
228
|
-
else if (!isValidEmail(userData.email)) {
|
|
229
|
-
errors.push('Invalid email format');
|
|
230
|
-
}
|
|
231
|
-
if (!userData.password || userData.password.length < 8) {
|
|
232
|
-
errors.push('Password must be at least 8 characters');
|
|
233
|
-
}
|
|
234
|
-
if (userData.password !== userData.passwordConfirm) {
|
|
235
|
-
errors.push('Passwords do not match');
|
|
236
|
-
}
|
|
237
|
-
return errors;
|
|
238
|
-
};
|
|
239
|
-
exports.validateSignupData = validateSignupData;
|
|
240
|
-
/**
|
|
241
|
-
* Simple email validation
|
|
242
|
-
*/
|
|
243
|
-
const isValidEmail = (email) => {
|
|
244
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
245
|
-
return emailRegex.test(email);
|
|
246
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure Authentication State Management
|
|
3
|
-
*
|
|
4
|
-
* Immutable state structures and pure functions for managing authentication state.
|
|
5
|
-
* All state transitions are explicit and predictable.
|
|
6
|
-
*/
|
|
7
|
-
export interface TokenPair {
|
|
8
|
-
readonly access: string;
|
|
9
|
-
readonly refresh: string;
|
|
10
|
-
}
|
|
11
|
-
export interface UserProfile {
|
|
12
|
-
readonly id: string;
|
|
13
|
-
readonly email: string;
|
|
14
|
-
readonly firstName: string;
|
|
15
|
-
readonly lastName: string;
|
|
16
|
-
readonly isVerified: boolean;
|
|
17
|
-
readonly isSignupCompleted: boolean;
|
|
18
|
-
}
|
|
19
|
-
export interface AuthState {
|
|
20
|
-
readonly isAuthenticated: boolean;
|
|
21
|
-
readonly isLoading: boolean;
|
|
22
|
-
readonly user: UserProfile | null;
|
|
23
|
-
readonly tokens: TokenPair | null;
|
|
24
|
-
readonly error: string | null;
|
|
25
|
-
}
|
|
26
|
-
export declare const createInitialAuthState: () => AuthState;
|
|
27
|
-
export declare const createLoadingAuthState: (currentState: AuthState) => AuthState;
|
|
28
|
-
export declare const createAuthenticatedState: (user: UserProfile, tokens: TokenPair) => AuthState;
|
|
29
|
-
export declare const createUnauthenticatedState: () => AuthState;
|
|
30
|
-
export declare const createErrorState: (currentState: AuthState, error: string) => AuthState;
|
|
31
|
-
export declare const updateTokens: (currentState: AuthState, tokens: TokenPair) => AuthState;
|
|
32
|
-
export declare const clearError: (currentState: AuthState) => AuthState;
|
|
33
|
-
export declare const isValidAuthState: (state: AuthState) => boolean;
|
|
34
|
-
export declare const hasValidTokens: (state: AuthState) => boolean;
|
|
35
|
-
export declare const getDisplayName: (user: UserProfile | null) => string;
|
|
36
|
-
export declare const requiresVerification: (user: UserProfile | null) => boolean;
|
|
37
|
-
export declare const requiresSignupCompletion: (user: UserProfile | null) => boolean;
|
|
38
|
-
//# sourceMappingURL=auth-state.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-state.d.ts","sourceRoot":"","sources":["../../../src/auth/functional/auth-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAGD,eAAO,MAAM,sBAAsB,QAAO,SAMxC,CAAC;AAEH,eAAO,MAAM,sBAAsB,GAAI,cAAc,SAAS,KAAG,SAI/D,CAAC;AAEH,eAAO,MAAM,wBAAwB,GACnC,MAAM,WAAW,EACjB,QAAQ,SAAS,KAChB,SAMD,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAAO,SAM5C,CAAC;AAEH,eAAO,MAAM,gBAAgB,GAC3B,cAAc,SAAS,EACvB,OAAO,MAAM,KACZ,SAID,CAAC;AAEH,eAAO,MAAM,YAAY,GACvB,cAAc,SAAS,EACvB,QAAQ,SAAS,KAChB,SAGD,CAAC;AAEH,eAAO,MAAM,UAAU,GAAI,cAAc,SAAS,KAAG,SAGnD,CAAC;AAGH,eAAO,MAAM,gBAAgB,GAAI,OAAO,SAAS,KAAG,OAQnD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,KAAG,OAIjD,CAAC;AAGF,eAAO,MAAM,cAAc,GAAI,MAAM,WAAW,GAAG,IAAI,KAAG,MAGzD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,GAAG,IAAI,KAAG,OAE/D,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,MAAM,WAAW,GAAG,IAAI,KAAG,OAEnE,CAAC"}
|