@hanzo/iam 0.1.0 → 0.2.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/dist/billing.d.ts +104 -35
- package/dist/billing.d.ts.map +1 -1
- package/dist/billing.js +89 -115
- package/dist/billing.js.map +1 -1
- package/dist/client.d.ts +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +19 -0
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -9
- package/dist/index.js.map +1 -1
- package/dist/nextauth.d.ts +56 -0
- package/dist/nextauth.d.ts.map +1 -0
- package/dist/nextauth.js +67 -0
- package/dist/nextauth.js.map +1 -0
- package/dist/react.d.ts +5 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +47 -0
- package/dist/react.js.map +1 -1
- package/dist/types.d.ts +52 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/billing.ts +164 -197
- package/src/client.ts +36 -0
- package/src/index.ts +22 -10
- package/src/nextauth.ts +93 -0
- package/src/react.ts +61 -1
- package/src/types.ts +62 -10
package/src/react.ts
CHANGED
|
@@ -46,7 +46,7 @@ import type { ReactNode } from "react";
|
|
|
46
46
|
import { BrowserIamSdk } from "./browser.js";
|
|
47
47
|
import type { BrowserIamConfig } from "./browser.js";
|
|
48
48
|
import { IamClient } from "./client.js";
|
|
49
|
-
import type { IamUser, IamOrganization, TokenResponse } from "./types.js";
|
|
49
|
+
import type { IamUser, IamOrganization, IamProject, TokenResponse } from "./types.js";
|
|
50
50
|
|
|
51
51
|
// ---------------------------------------------------------------------------
|
|
52
52
|
// Types
|
|
@@ -96,6 +96,10 @@ export interface OrgState {
|
|
|
96
96
|
currentOrgId: string | null;
|
|
97
97
|
/** Switch to a different organization. */
|
|
98
98
|
switchOrg: (orgId: string) => void;
|
|
99
|
+
/** All projects for the current organization. */
|
|
100
|
+
projects: IamProject[];
|
|
101
|
+
/** Currently selected project. */
|
|
102
|
+
currentProject: IamProject | null;
|
|
99
103
|
/** Currently selected project ID within the org. */
|
|
100
104
|
currentProjectId: string | null;
|
|
101
105
|
/** Switch to a different project (null to clear). */
|
|
@@ -367,6 +371,7 @@ export function useIam(): IamContextValue {
|
|
|
367
371
|
export function useOrganizations(): OrgState {
|
|
368
372
|
const { config, isAuthenticated, accessToken } = useIam();
|
|
369
373
|
const [organizations, setOrganizations] = useState<IamOrganization[]>([]);
|
|
374
|
+
const [projects, setProjects] = useState<IamProject[]>([]);
|
|
370
375
|
const [isLoading, setIsLoading] = useState(false);
|
|
371
376
|
|
|
372
377
|
const [currentOrgId, setCurrentOrgId] = useState<string | null>(() => {
|
|
@@ -391,6 +396,7 @@ export function useOrganizations(): OrgState {
|
|
|
391
396
|
useEffect(() => {
|
|
392
397
|
if (!isAuthenticated || !accessToken) {
|
|
393
398
|
setOrganizations([]);
|
|
399
|
+
setProjects([]);
|
|
394
400
|
return;
|
|
395
401
|
}
|
|
396
402
|
|
|
@@ -459,14 +465,66 @@ export function useOrganizations(): OrgState {
|
|
|
459
465
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
460
466
|
}, [isAuthenticated, accessToken, config.serverUrl, config.clientId]);
|
|
461
467
|
|
|
468
|
+
// Fetch projects when currentOrgId changes
|
|
469
|
+
useEffect(() => {
|
|
470
|
+
if (!isAuthenticated || !accessToken || !currentOrgId) {
|
|
471
|
+
setProjects([]);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
let cancelled = false;
|
|
476
|
+
|
|
477
|
+
const fetchProjects = async () => {
|
|
478
|
+
try {
|
|
479
|
+
const client = new IamClient({
|
|
480
|
+
serverUrl: config.serverUrl,
|
|
481
|
+
clientId: config.clientId,
|
|
482
|
+
});
|
|
483
|
+
const orgProjects = await client.getOrganizationProjects(
|
|
484
|
+
currentOrgId,
|
|
485
|
+
accessToken,
|
|
486
|
+
);
|
|
487
|
+
if (!cancelled) {
|
|
488
|
+
setProjects(orgProjects);
|
|
489
|
+
// Auto-select default project if none selected
|
|
490
|
+
if (!currentProjectId && orgProjects.length > 0) {
|
|
491
|
+
const defaultProject =
|
|
492
|
+
orgProjects.find((p) => p.isDefault) ?? orgProjects[0];
|
|
493
|
+
setCurrentProjectId(defaultProject.name);
|
|
494
|
+
try {
|
|
495
|
+
localStorage.setItem(STORAGE_PROJECT_KEY, defaultProject.name);
|
|
496
|
+
} catch {
|
|
497
|
+
/* ok */
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
} catch {
|
|
502
|
+
// Projects API may not be available yet — that's ok
|
|
503
|
+
if (!cancelled) setProjects([]);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
fetchProjects();
|
|
508
|
+
return () => {
|
|
509
|
+
cancelled = true;
|
|
510
|
+
};
|
|
511
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
512
|
+
}, [isAuthenticated, accessToken, currentOrgId, config.serverUrl, config.clientId]);
|
|
513
|
+
|
|
462
514
|
const currentOrg = useMemo(
|
|
463
515
|
() => organizations.find((o) => o.name === currentOrgId) ?? null,
|
|
464
516
|
[organizations, currentOrgId],
|
|
465
517
|
);
|
|
466
518
|
|
|
519
|
+
const currentProject = useMemo(
|
|
520
|
+
() => projects.find((p) => p.name === currentProjectId) ?? null,
|
|
521
|
+
[projects, currentProjectId],
|
|
522
|
+
);
|
|
523
|
+
|
|
467
524
|
const switchOrg = useCallback((orgId: string) => {
|
|
468
525
|
setCurrentOrgId(orgId);
|
|
469
526
|
setCurrentProjectId(null);
|
|
527
|
+
setProjects([]);
|
|
470
528
|
try {
|
|
471
529
|
localStorage.setItem(STORAGE_ORG_KEY, orgId);
|
|
472
530
|
localStorage.removeItem(STORAGE_PROJECT_KEY);
|
|
@@ -493,6 +551,8 @@ export function useOrganizations(): OrgState {
|
|
|
493
551
|
currentOrg,
|
|
494
552
|
currentOrgId,
|
|
495
553
|
switchOrg,
|
|
554
|
+
projects,
|
|
555
|
+
currentProject,
|
|
496
556
|
currentProjectId,
|
|
497
557
|
switchProject,
|
|
498
558
|
isLoading,
|
package/src/types.ts
CHANGED
|
@@ -115,10 +115,10 @@ export type IamOrganization = {
|
|
|
115
115
|
};
|
|
116
116
|
|
|
117
117
|
// ---------------------------------------------------------------------------
|
|
118
|
-
//
|
|
118
|
+
// Billing (canonical types — backed by Commerce service)
|
|
119
119
|
// ---------------------------------------------------------------------------
|
|
120
120
|
|
|
121
|
-
export type
|
|
121
|
+
export type Subscription = {
|
|
122
122
|
owner: string;
|
|
123
123
|
name: string;
|
|
124
124
|
displayName?: string;
|
|
@@ -133,7 +133,7 @@ export type IamSubscription = {
|
|
|
133
133
|
description?: string;
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
-
export type
|
|
136
|
+
export type Plan = {
|
|
137
137
|
owner: string;
|
|
138
138
|
name: string;
|
|
139
139
|
displayName?: string;
|
|
@@ -147,7 +147,7 @@ export type IamPlan = {
|
|
|
147
147
|
role?: string;
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
export type
|
|
150
|
+
export type Pricing = {
|
|
151
151
|
owner: string;
|
|
152
152
|
name: string;
|
|
153
153
|
displayName?: string;
|
|
@@ -159,11 +159,7 @@ export type IamPricing = {
|
|
|
159
159
|
trialDuration?: number;
|
|
160
160
|
};
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
// Payment / Order
|
|
164
|
-
// ---------------------------------------------------------------------------
|
|
165
|
-
|
|
166
|
-
export type IamPayment = {
|
|
162
|
+
export type Payment = {
|
|
167
163
|
owner: string;
|
|
168
164
|
name: string;
|
|
169
165
|
displayName?: string;
|
|
@@ -177,7 +173,7 @@ export type IamPayment = {
|
|
|
177
173
|
message?: string;
|
|
178
174
|
};
|
|
179
175
|
|
|
180
|
-
export type
|
|
176
|
+
export type Order = {
|
|
181
177
|
owner: string;
|
|
182
178
|
name: string;
|
|
183
179
|
displayName?: string;
|
|
@@ -190,6 +186,62 @@ export type IamOrder = {
|
|
|
190
186
|
message?: string;
|
|
191
187
|
};
|
|
192
188
|
|
|
189
|
+
export type UsageRecord = {
|
|
190
|
+
owner: string;
|
|
191
|
+
name: string;
|
|
192
|
+
user?: string;
|
|
193
|
+
application?: string;
|
|
194
|
+
organization?: string;
|
|
195
|
+
project?: string;
|
|
196
|
+
model?: string;
|
|
197
|
+
provider?: string;
|
|
198
|
+
promptTokens?: number;
|
|
199
|
+
completionTokens?: number;
|
|
200
|
+
totalTokens?: number;
|
|
201
|
+
cost?: number;
|
|
202
|
+
currency?: string;
|
|
203
|
+
premium?: boolean;
|
|
204
|
+
stream?: boolean;
|
|
205
|
+
status?: string;
|
|
206
|
+
errorMsg?: string;
|
|
207
|
+
clientIp?: string;
|
|
208
|
+
requestId?: string;
|
|
209
|
+
createdTime?: string;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export type UsageSummary = {
|
|
213
|
+
totalRequests: number;
|
|
214
|
+
totalTokens: number;
|
|
215
|
+
totalCost: number;
|
|
216
|
+
promptTokens: number;
|
|
217
|
+
completionTokens: number;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// Backwards-compatible aliases
|
|
221
|
+
export type IamSubscription = Subscription;
|
|
222
|
+
export type IamPlan = Plan;
|
|
223
|
+
export type IamPricing = Pricing;
|
|
224
|
+
export type IamPayment = Payment;
|
|
225
|
+
export type IamOrder = Order;
|
|
226
|
+
export type IamUsageRecord = UsageRecord;
|
|
227
|
+
export type IamUsageSummary = UsageSummary;
|
|
228
|
+
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
// Project
|
|
231
|
+
// ---------------------------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
export type IamProject = {
|
|
234
|
+
owner: string;
|
|
235
|
+
name: string;
|
|
236
|
+
displayName?: string;
|
|
237
|
+
description?: string;
|
|
238
|
+
organization: string;
|
|
239
|
+
tags?: string[];
|
|
240
|
+
metadata?: Record<string, unknown>;
|
|
241
|
+
isDefault?: boolean;
|
|
242
|
+
createdTime?: string;
|
|
243
|
+
};
|
|
244
|
+
|
|
193
245
|
// ---------------------------------------------------------------------------
|
|
194
246
|
// Auth result
|
|
195
247
|
// ---------------------------------------------------------------------------
|