@crimson-education/sdk 0.3.7 → 0.3.9
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/dist/core/account.d.ts +7 -1
- package/dist/core/account.js +10 -0
- package/dist/core/client.d.ts +7 -0
- package/dist/core/client.js +58 -0
- package/dist/core/types.d.ts +14 -0
- package/dist/react/provider.js +13 -3
- package/package.json +1 -1
package/dist/core/account.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CrimsonClient } from "./client";
|
|
2
|
-
import type { CurrentUserRoles, StudentSummary, UserProfile } from "./types";
|
|
2
|
+
import type { CurrentUserRoles, StudentSummary, UserProfile, LinkedTenantsResponse } from "./types";
|
|
3
3
|
export declare class AccountApi {
|
|
4
4
|
private client;
|
|
5
5
|
constructor(client: CrimsonClient);
|
|
@@ -37,4 +37,10 @@ export declare class AccountApi {
|
|
|
37
37
|
* @returns User profile information
|
|
38
38
|
*/
|
|
39
39
|
getMyProfile(): Promise<UserProfile>;
|
|
40
|
+
/**
|
|
41
|
+
* Get the list of tenants linked to the current user
|
|
42
|
+
*
|
|
43
|
+
* @returns List of linked tenants and current tenant info
|
|
44
|
+
*/
|
|
45
|
+
getLinkedTenants(): Promise<LinkedTenantsResponse>;
|
|
40
46
|
}
|
package/dist/core/account.js
CHANGED
|
@@ -62,5 +62,15 @@ class AccountApi {
|
|
|
62
62
|
return this.client.fetch("/api/v1/account/me/profile");
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the list of tenants linked to the current user
|
|
67
|
+
*
|
|
68
|
+
* @returns List of linked tenants and current tenant info
|
|
69
|
+
*/
|
|
70
|
+
getLinkedTenants() {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
return this.client.fetch("/api/v1/account/linked-tenants");
|
|
73
|
+
});
|
|
74
|
+
}
|
|
65
75
|
}
|
|
66
76
|
exports.AccountApi = AccountApi;
|
package/dist/core/client.d.ts
CHANGED
|
@@ -19,12 +19,19 @@ export declare class CrimsonClient {
|
|
|
19
19
|
private appName;
|
|
20
20
|
private appTenant;
|
|
21
21
|
private oauthAdapter?;
|
|
22
|
+
private tenantDomain?;
|
|
23
|
+
private isResolvingDomain;
|
|
24
|
+
private tenantDomainPromise?;
|
|
22
25
|
constructor(config: CrimsonClientConfig);
|
|
23
26
|
/**
|
|
24
27
|
* Initialize the client (required for OAuth mode)
|
|
25
28
|
* Call this after creating the client to load stored tokens
|
|
26
29
|
*/
|
|
27
30
|
initialize(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the x-tenant-domain dynamically
|
|
33
|
+
*/
|
|
34
|
+
resolveTenantDomain(): Promise<void>;
|
|
28
35
|
/**
|
|
29
36
|
* Get the OAuth adapter (only available in OAuth mode)
|
|
30
37
|
*/
|
package/dist/core/client.js
CHANGED
|
@@ -45,6 +45,7 @@ function isOAuthConfig(config) {
|
|
|
45
45
|
class CrimsonClient {
|
|
46
46
|
constructor(config) {
|
|
47
47
|
this.config = config;
|
|
48
|
+
this.isResolvingDomain = false;
|
|
48
49
|
this.missions = new missions_1.MissionsApi(this);
|
|
49
50
|
this.tasks = new tasks_1.TasksApi(this);
|
|
50
51
|
this.roadmap = new roadmap_1.RoadmapApi(this);
|
|
@@ -91,6 +92,55 @@ class CrimsonClient {
|
|
|
91
92
|
}
|
|
92
93
|
});
|
|
93
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolve the x-tenant-domain dynamically
|
|
97
|
+
*/
|
|
98
|
+
resolveTenantDomain() {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
if (this.tenantDomain)
|
|
101
|
+
return;
|
|
102
|
+
if (!this.tenantDomainPromise) {
|
|
103
|
+
this.isResolvingDomain = true;
|
|
104
|
+
this.tenantDomainPromise = (() => __awaiter(this, void 0, void 0, function* () {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
try {
|
|
107
|
+
const token = yield this.getToken();
|
|
108
|
+
if (!token) {
|
|
109
|
+
// Silently return without error if called early;
|
|
110
|
+
// it will be lazily retried in fetch() or when token is received.
|
|
111
|
+
this.tenantDomainPromise = undefined;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// A newer version of profile will return domain
|
|
115
|
+
const profile = yield this.account.getMyProfile();
|
|
116
|
+
if ((_a = profile.tenant) === null || _a === void 0 ? void 0 : _a.domain) {
|
|
117
|
+
this.tenantDomain = profile.tenant.domain;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// Use getLinkedtenants as a safe fallback when getMyProfile does not return a domain.
|
|
121
|
+
// Can be removed later.
|
|
122
|
+
const linkedRes = yield this.account.getLinkedTenants();
|
|
123
|
+
if (linkedRes.linkedTenants && linkedRes.linkedTenants.length > 0) {
|
|
124
|
+
// find domain.tenantId equals to currentTenantId
|
|
125
|
+
const domain = (_b = linkedRes.linkedTenants.find(t => t.tenantId === linkedRes.currentTenantId)) === null || _b === void 0 ? void 0 : _b.tenantDomain;
|
|
126
|
+
if (domain) {
|
|
127
|
+
this.tenantDomain = domain;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
console.warn('[CrimsonSDK] Failed to resolve tenant domain:', err);
|
|
134
|
+
this.tenantDomainPromise = undefined;
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
this.isResolvingDomain = false;
|
|
138
|
+
}
|
|
139
|
+
}))();
|
|
140
|
+
}
|
|
141
|
+
return this.tenantDomainPromise;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
94
144
|
/**
|
|
95
145
|
* Get the OAuth adapter (only available in OAuth mode)
|
|
96
146
|
*/
|
|
@@ -192,6 +242,10 @@ class CrimsonClient {
|
|
|
192
242
|
}
|
|
193
243
|
fetch(path_1) {
|
|
194
244
|
return __awaiter(this, arguments, void 0, function* (path, options = {}) {
|
|
245
|
+
// If it's a roadmap endpoint, wait for tenant domain to be resolved first
|
|
246
|
+
if (path.includes("/roadmap")) {
|
|
247
|
+
yield this.resolveTenantDomain();
|
|
248
|
+
}
|
|
195
249
|
const token = yield this.getToken();
|
|
196
250
|
if (!token) {
|
|
197
251
|
throw new Error("No authentication token available");
|
|
@@ -207,6 +261,10 @@ class CrimsonClient {
|
|
|
207
261
|
if (this.appTenant) {
|
|
208
262
|
headers["X-App-Tenant"] = this.appTenant;
|
|
209
263
|
}
|
|
264
|
+
console.log(`tenantDomain = ${this.tenantDomain}`);
|
|
265
|
+
if (this.tenantDomain) {
|
|
266
|
+
headers["x-tenant-domain"] = this.tenantDomain;
|
|
267
|
+
}
|
|
210
268
|
const url = `${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
|
|
211
269
|
const response = yield fetch(url, Object.assign(Object.assign({}, options), { headers }));
|
|
212
270
|
if (!response.ok) {
|
package/dist/core/types.d.ts
CHANGED
|
@@ -494,8 +494,22 @@ export interface UserProfile {
|
|
|
494
494
|
tenant: {
|
|
495
495
|
id: string;
|
|
496
496
|
name: string;
|
|
497
|
+
domain?: string;
|
|
497
498
|
};
|
|
498
499
|
}
|
|
500
|
+
export interface LinkedTenant {
|
|
501
|
+
tenantId: string;
|
|
502
|
+
tenantName: string;
|
|
503
|
+
tenantDomain: string | null;
|
|
504
|
+
tenantLevel: number;
|
|
505
|
+
isCurrent: boolean;
|
|
506
|
+
userEmail: string;
|
|
507
|
+
}
|
|
508
|
+
export interface LinkedTenantsResponse {
|
|
509
|
+
currentUserId: string;
|
|
510
|
+
currentTenantId: string;
|
|
511
|
+
linkedTenants: LinkedTenant[];
|
|
512
|
+
}
|
|
499
513
|
/**
|
|
500
514
|
* Prefilled field with value and source information
|
|
501
515
|
*/
|
package/dist/react/provider.js
CHANGED
|
@@ -36,8 +36,18 @@ function CrimsonProvider({ children, apiUrl, allowedParentOrigins, queryClient:
|
|
|
36
36
|
}), [apiUrl, clientId, appName, appTenant]);
|
|
37
37
|
(0, react_1.useEffect)(() => {
|
|
38
38
|
const origins = allowedParentOrigins || (0, iframe_1.getDefaultAllowedOrigins)();
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const cleanupIframe = (0, iframe_1.setupIframeListener)(origins);
|
|
40
|
+
// Eagerly resolve tenant domain as soon as token becomes available from iframe
|
|
41
|
+
const cleanupAuth = (0, iframe_1.subscribeToAuthState)(() => {
|
|
42
|
+
const state = (0, iframe_1.getAuthState)();
|
|
43
|
+
if (state.token) {
|
|
44
|
+
client.resolveTenantDomain().catch(() => { });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return () => {
|
|
48
|
+
cleanupIframe();
|
|
49
|
+
cleanupAuth();
|
|
50
|
+
};
|
|
51
|
+
}, [allowedParentOrigins, client]);
|
|
42
52
|
return ((0, jsx_runtime_1.jsx)(CrimsonContext.Provider, { value: { client }, children: (0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: children }) }));
|
|
43
53
|
}
|