@viyv/account-client 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-UX6UAFIF.js → chunk-V3SLFECG.js} +6 -3
- package/dist/{entitlement-B3pXM2vO.d.cts → entitlement-CfKncUyH.d.cts} +9 -0
- package/dist/{entitlement-B3pXM2vO.d.ts → entitlement-CfKncUyH.d.ts} +9 -0
- package/dist/index.cjs +19 -1
- package/dist/index.d.cts +47 -2
- package/dist/index.d.ts +47 -2
- package/dist/index.js +16 -1
- package/dist/introspect.cjs +64 -1
- package/dist/introspect.d.cts +44 -2
- package/dist/introspect.d.ts +44 -2
- package/dist/introspect.js +64 -2
- package/dist/react.cjs +54 -13
- package/dist/react.d.cts +48 -3
- package/dist/react.d.ts +48 -3
- package/dist/react.js +53 -14
- package/dist/server.cjs +23 -1
- package/dist/server.d.cts +32 -4
- package/dist/server.d.ts +32 -4
- package/dist/server.js +22 -3
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ function parseEntitlement(wire) {
|
|
|
5
5
|
plan: wire.plan,
|
|
6
6
|
addons: wire.addons ?? [],
|
|
7
7
|
products: wire.products ?? [],
|
|
8
|
+
productPlans: wire.product_plans ?? {},
|
|
8
9
|
features: wire.features
|
|
9
10
|
};
|
|
10
11
|
}
|
|
@@ -12,12 +13,14 @@ function entitlementForProduct(entitlement, product) {
|
|
|
12
13
|
if (!entitlement) return null;
|
|
13
14
|
return {
|
|
14
15
|
enabled: entitlement.products.includes(product),
|
|
15
|
-
|
|
16
|
+
// Per-product billing: report THIS product's own tier (free-start default),
|
|
17
|
+
// not the org-wide effective `plan`.
|
|
18
|
+
plan: entitlement.productPlans[product] ?? "free",
|
|
16
19
|
addons: entitlement.addons,
|
|
17
20
|
features: entitlement.features
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
export { entitlementForProduct, parseEntitlement };
|
|
22
|
-
//# sourceMappingURL=chunk-
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
25
|
+
//# sourceMappingURL=chunk-V3SLFECG.js.map
|
|
26
|
+
//# sourceMappingURL=chunk-V3SLFECG.js.map
|
|
@@ -16,16 +16,24 @@ interface AccountOrg {
|
|
|
16
16
|
/** Shape of GET /v1/license/entitlement (docs/09 A-4). */
|
|
17
17
|
interface Entitlement {
|
|
18
18
|
organizationId: string;
|
|
19
|
+
/**
|
|
20
|
+
* The org's effective (highest) tier across its products — a back-compat
|
|
21
|
+
* summary. Per-product billing (2026-06-13): the authoritative per-product
|
|
22
|
+
* tier is in {@link Entitlement.productPlans}.
|
|
23
|
+
*/
|
|
19
24
|
plan: PlanTier;
|
|
20
25
|
addons: string[];
|
|
21
26
|
/** Product slugs this org may use (free-start lists the agent family). */
|
|
22
27
|
products: ProductSlug[];
|
|
28
|
+
/** Per-product tier (each enabled product → its plan; free-start = "free"). */
|
|
29
|
+
productPlans: Partial<Record<ProductSlug, PlanTier>>;
|
|
23
30
|
features: EntitlementFeatures;
|
|
24
31
|
}
|
|
25
32
|
/** Per-product entitlement view returned by useEntitlement(slug). */
|
|
26
33
|
interface ProductEntitlement {
|
|
27
34
|
/** Whether the product is enabled for this org. */
|
|
28
35
|
enabled: boolean;
|
|
36
|
+
/** THIS product's tier (per-product billing) — not the org-wide summary. */
|
|
29
37
|
plan: PlanTier;
|
|
30
38
|
addons: string[];
|
|
31
39
|
/** The full feature map (callers branch on the flags they care about). */
|
|
@@ -37,6 +45,7 @@ interface EntitlementWire {
|
|
|
37
45
|
plan: PlanTier;
|
|
38
46
|
addons: string[];
|
|
39
47
|
products: ProductSlug[];
|
|
48
|
+
product_plans?: Partial<Record<ProductSlug, PlanTier>>;
|
|
40
49
|
features: EntitlementFeatures;
|
|
41
50
|
}
|
|
42
51
|
/** Normalize the wire payload into the camelCase {@link Entitlement}. */
|
|
@@ -16,16 +16,24 @@ interface AccountOrg {
|
|
|
16
16
|
/** Shape of GET /v1/license/entitlement (docs/09 A-4). */
|
|
17
17
|
interface Entitlement {
|
|
18
18
|
organizationId: string;
|
|
19
|
+
/**
|
|
20
|
+
* The org's effective (highest) tier across its products — a back-compat
|
|
21
|
+
* summary. Per-product billing (2026-06-13): the authoritative per-product
|
|
22
|
+
* tier is in {@link Entitlement.productPlans}.
|
|
23
|
+
*/
|
|
19
24
|
plan: PlanTier;
|
|
20
25
|
addons: string[];
|
|
21
26
|
/** Product slugs this org may use (free-start lists the agent family). */
|
|
22
27
|
products: ProductSlug[];
|
|
28
|
+
/** Per-product tier (each enabled product → its plan; free-start = "free"). */
|
|
29
|
+
productPlans: Partial<Record<ProductSlug, PlanTier>>;
|
|
23
30
|
features: EntitlementFeatures;
|
|
24
31
|
}
|
|
25
32
|
/** Per-product entitlement view returned by useEntitlement(slug). */
|
|
26
33
|
interface ProductEntitlement {
|
|
27
34
|
/** Whether the product is enabled for this org. */
|
|
28
35
|
enabled: boolean;
|
|
36
|
+
/** THIS product's tier (per-product billing) — not the org-wide summary. */
|
|
29
37
|
plan: PlanTier;
|
|
30
38
|
addons: string[];
|
|
31
39
|
/** The full feature map (callers branch on the flags they care about). */
|
|
@@ -37,6 +45,7 @@ interface EntitlementWire {
|
|
|
37
45
|
plan: PlanTier;
|
|
38
46
|
addons: string[];
|
|
39
47
|
products: ProductSlug[];
|
|
48
|
+
product_plans?: Partial<Record<ProductSlug, PlanTier>>;
|
|
40
49
|
features: EntitlementFeatures;
|
|
41
50
|
}
|
|
42
51
|
/** Normalize the wire payload into the camelCase {@link Entitlement}. */
|
package/dist/index.cjs
CHANGED
|
@@ -69,6 +69,7 @@ function parseEntitlement(wire) {
|
|
|
69
69
|
plan: wire.plan,
|
|
70
70
|
addons: wire.addons ?? [],
|
|
71
71
|
products: wire.products ?? [],
|
|
72
|
+
productPlans: wire.product_plans ?? {},
|
|
72
73
|
features: wire.features
|
|
73
74
|
};
|
|
74
75
|
}
|
|
@@ -76,7 +77,9 @@ function entitlementForProduct(entitlement, product) {
|
|
|
76
77
|
if (!entitlement) return null;
|
|
77
78
|
return {
|
|
78
79
|
enabled: entitlement.products.includes(product),
|
|
79
|
-
|
|
80
|
+
// Per-product billing: report THIS product's own tier (free-start default),
|
|
81
|
+
// not the org-wide effective `plan`.
|
|
82
|
+
plan: entitlement.productPlans[product] ?? "free",
|
|
80
83
|
addons: entitlement.addons,
|
|
81
84
|
features: entitlement.features
|
|
82
85
|
};
|
|
@@ -101,6 +104,21 @@ function createAccountClient(config) {
|
|
|
101
104
|
email: params.email,
|
|
102
105
|
password: params.password
|
|
103
106
|
}),
|
|
107
|
+
signInWithProvider: (provider, options) => client$1.signIn.social({
|
|
108
|
+
provider,
|
|
109
|
+
callbackURL: options.callbackURL,
|
|
110
|
+
errorCallbackURL: options.errorCallbackURL
|
|
111
|
+
}),
|
|
112
|
+
listAccounts: () => client$1.listAccounts(),
|
|
113
|
+
linkSocial: (provider, options) => client$1.linkSocial({
|
|
114
|
+
provider,
|
|
115
|
+
callbackURL: options.callbackURL,
|
|
116
|
+
errorCallbackURL: options.errorCallbackURL
|
|
117
|
+
}),
|
|
118
|
+
unlinkAccount: (params) => client$1.unlinkAccount({
|
|
119
|
+
providerId: params.providerId,
|
|
120
|
+
accountId: params.accountId
|
|
121
|
+
}),
|
|
104
122
|
signOut: () => client$1.signOut(),
|
|
105
123
|
getSession: () => client$1.getSession()
|
|
106
124
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createAuthClient } from 'better-auth/client';
|
|
2
2
|
import { DeviceUserinfoResponse } from '@viyv/shared';
|
|
3
3
|
export { DeviceUserinfoResponse, EntitlementFeatures, PlanTier, ProductSlug } from '@viyv/shared';
|
|
4
|
-
export { A as AccountOrg, a as AccountUser, E as Entitlement, P as ProductEntitlement, e as entitlementForProduct, p as parseEntitlement } from './entitlement-
|
|
4
|
+
export { A as AccountOrg, a as AccountUser, E as Entitlement, P as ProductEntitlement, e as entitlementForProduct, p as parseEntitlement } from './entitlement-CfKncUyH.cjs';
|
|
5
5
|
|
|
6
6
|
declare const DEFAULT_DEVICE_CLIENT_ID: "viyv-browser-macapp";
|
|
7
7
|
/** RFC 8628 §3.4 device_code grant type (token endpoint `grant_type`). */
|
|
@@ -85,6 +85,29 @@ interface AuthResult<T = unknown> {
|
|
|
85
85
|
statusText?: string;
|
|
86
86
|
} | null;
|
|
87
87
|
}
|
|
88
|
+
/** OAuth providers exposed on the hosted signin surface (app.viyv.io). */
|
|
89
|
+
type SocialProvider = "google" | "github";
|
|
90
|
+
interface SocialRedirectOptions {
|
|
91
|
+
/**
|
|
92
|
+
* Where the provider returns the user AFTER auth completes (success). Social
|
|
93
|
+
* login is a FULL-PAGE redirect, so this is the ONLY carrier that survives the
|
|
94
|
+
* provider round-trip — unlike the email/password path, you cannot set
|
|
95
|
+
* window.location after the call. Pass an open-redirect-validated target (the
|
|
96
|
+
* hosted signin runs `safeReturnTo()` before handing the value here).
|
|
97
|
+
*/
|
|
98
|
+
callbackURL: string;
|
|
99
|
+
/** Where to send the user if the OAuth flow errors (e.g. "/signin?error=oauth"). */
|
|
100
|
+
errorCallbackURL?: string;
|
|
101
|
+
}
|
|
102
|
+
/** One linked credential/OAuth account, as returned by GET /list-accounts. */
|
|
103
|
+
interface LinkedAccount {
|
|
104
|
+
id: string;
|
|
105
|
+
providerId: string;
|
|
106
|
+
accountId: string;
|
|
107
|
+
scopes?: string[];
|
|
108
|
+
createdAt?: string;
|
|
109
|
+
updatedAt?: string;
|
|
110
|
+
}
|
|
88
111
|
/**
|
|
89
112
|
* Public surface of the account client. Methods are typed explicitly (rather
|
|
90
113
|
* than inferred) so the published `.d.ts` does not reference better-auth's
|
|
@@ -102,6 +125,28 @@ interface AccountClient {
|
|
|
102
125
|
email: string;
|
|
103
126
|
password: string;
|
|
104
127
|
}): Promise<AuthResult>;
|
|
128
|
+
/**
|
|
129
|
+
* Begin an OAuth login. NAVIGATES the browser to the provider (full-page
|
|
130
|
+
* redirect), so on success it does not resolve to a useful value — control
|
|
131
|
+
* leaves the page. `options.callbackURL` chooses where the user lands after
|
|
132
|
+
* the round-trip; the AuthResult is meaningful only for a synchronous error.
|
|
133
|
+
*/
|
|
134
|
+
signInWithProvider(provider: SocialProvider, options: SocialRedirectOptions): Promise<AuthResult>;
|
|
135
|
+
/** List the signed-in user's linked accounts (credential + OAuth). */
|
|
136
|
+
listAccounts(): Promise<AuthResult<LinkedAccount[]>>;
|
|
137
|
+
/**
|
|
138
|
+
* Link an OAuth provider to the SIGNED-IN user (explicit link, not implicit).
|
|
139
|
+
* Also a full-page redirect to the provider.
|
|
140
|
+
*/
|
|
141
|
+
linkSocial(provider: SocialProvider, options: SocialRedirectOptions): Promise<AuthResult>;
|
|
142
|
+
/**
|
|
143
|
+
* Unlink an OAuth/credential account from the signed-in user. Fails server-side
|
|
144
|
+
* if it would remove the user's last remaining credential.
|
|
145
|
+
*/
|
|
146
|
+
unlinkAccount(params: {
|
|
147
|
+
providerId: string;
|
|
148
|
+
accountId?: string;
|
|
149
|
+
}): Promise<AuthResult>;
|
|
105
150
|
signOut(): Promise<AuthResult>;
|
|
106
151
|
getSession(): Promise<AuthResult>;
|
|
107
152
|
}
|
|
@@ -112,4 +157,4 @@ interface AccountClient {
|
|
|
112
157
|
*/
|
|
113
158
|
declare function createAccountClient(config: AccountClientConfig): AccountClient;
|
|
114
159
|
|
|
115
|
-
export { ACCOUNT_CLIENT_PACKAGE, type AccountClient, type AccountClientConfig, type AuthResult, DEFAULT_DEVICE_CLIENT_ID, DEVICE_CODE_GRANT_TYPE, type DeviceFlowClient, type DeviceFlowClientConfig, type DevicePollError, type DeviceStartResponse, type DeviceTokenResponse, type LicenseCurrentResponse, createAccountClient, createDeviceFlowClient };
|
|
160
|
+
export { ACCOUNT_CLIENT_PACKAGE, type AccountClient, type AccountClientConfig, type AuthResult, DEFAULT_DEVICE_CLIENT_ID, DEVICE_CODE_GRANT_TYPE, type DeviceFlowClient, type DeviceFlowClientConfig, type DevicePollError, type DeviceStartResponse, type DeviceTokenResponse, type LicenseCurrentResponse, type LinkedAccount, type SocialProvider, type SocialRedirectOptions, createAccountClient, createDeviceFlowClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createAuthClient } from 'better-auth/client';
|
|
2
2
|
import { DeviceUserinfoResponse } from '@viyv/shared';
|
|
3
3
|
export { DeviceUserinfoResponse, EntitlementFeatures, PlanTier, ProductSlug } from '@viyv/shared';
|
|
4
|
-
export { A as AccountOrg, a as AccountUser, E as Entitlement, P as ProductEntitlement, e as entitlementForProduct, p as parseEntitlement } from './entitlement-
|
|
4
|
+
export { A as AccountOrg, a as AccountUser, E as Entitlement, P as ProductEntitlement, e as entitlementForProduct, p as parseEntitlement } from './entitlement-CfKncUyH.js';
|
|
5
5
|
|
|
6
6
|
declare const DEFAULT_DEVICE_CLIENT_ID: "viyv-browser-macapp";
|
|
7
7
|
/** RFC 8628 §3.4 device_code grant type (token endpoint `grant_type`). */
|
|
@@ -85,6 +85,29 @@ interface AuthResult<T = unknown> {
|
|
|
85
85
|
statusText?: string;
|
|
86
86
|
} | null;
|
|
87
87
|
}
|
|
88
|
+
/** OAuth providers exposed on the hosted signin surface (app.viyv.io). */
|
|
89
|
+
type SocialProvider = "google" | "github";
|
|
90
|
+
interface SocialRedirectOptions {
|
|
91
|
+
/**
|
|
92
|
+
* Where the provider returns the user AFTER auth completes (success). Social
|
|
93
|
+
* login is a FULL-PAGE redirect, so this is the ONLY carrier that survives the
|
|
94
|
+
* provider round-trip — unlike the email/password path, you cannot set
|
|
95
|
+
* window.location after the call. Pass an open-redirect-validated target (the
|
|
96
|
+
* hosted signin runs `safeReturnTo()` before handing the value here).
|
|
97
|
+
*/
|
|
98
|
+
callbackURL: string;
|
|
99
|
+
/** Where to send the user if the OAuth flow errors (e.g. "/signin?error=oauth"). */
|
|
100
|
+
errorCallbackURL?: string;
|
|
101
|
+
}
|
|
102
|
+
/** One linked credential/OAuth account, as returned by GET /list-accounts. */
|
|
103
|
+
interface LinkedAccount {
|
|
104
|
+
id: string;
|
|
105
|
+
providerId: string;
|
|
106
|
+
accountId: string;
|
|
107
|
+
scopes?: string[];
|
|
108
|
+
createdAt?: string;
|
|
109
|
+
updatedAt?: string;
|
|
110
|
+
}
|
|
88
111
|
/**
|
|
89
112
|
* Public surface of the account client. Methods are typed explicitly (rather
|
|
90
113
|
* than inferred) so the published `.d.ts` does not reference better-auth's
|
|
@@ -102,6 +125,28 @@ interface AccountClient {
|
|
|
102
125
|
email: string;
|
|
103
126
|
password: string;
|
|
104
127
|
}): Promise<AuthResult>;
|
|
128
|
+
/**
|
|
129
|
+
* Begin an OAuth login. NAVIGATES the browser to the provider (full-page
|
|
130
|
+
* redirect), so on success it does not resolve to a useful value — control
|
|
131
|
+
* leaves the page. `options.callbackURL` chooses where the user lands after
|
|
132
|
+
* the round-trip; the AuthResult is meaningful only for a synchronous error.
|
|
133
|
+
*/
|
|
134
|
+
signInWithProvider(provider: SocialProvider, options: SocialRedirectOptions): Promise<AuthResult>;
|
|
135
|
+
/** List the signed-in user's linked accounts (credential + OAuth). */
|
|
136
|
+
listAccounts(): Promise<AuthResult<LinkedAccount[]>>;
|
|
137
|
+
/**
|
|
138
|
+
* Link an OAuth provider to the SIGNED-IN user (explicit link, not implicit).
|
|
139
|
+
* Also a full-page redirect to the provider.
|
|
140
|
+
*/
|
|
141
|
+
linkSocial(provider: SocialProvider, options: SocialRedirectOptions): Promise<AuthResult>;
|
|
142
|
+
/**
|
|
143
|
+
* Unlink an OAuth/credential account from the signed-in user. Fails server-side
|
|
144
|
+
* if it would remove the user's last remaining credential.
|
|
145
|
+
*/
|
|
146
|
+
unlinkAccount(params: {
|
|
147
|
+
providerId: string;
|
|
148
|
+
accountId?: string;
|
|
149
|
+
}): Promise<AuthResult>;
|
|
105
150
|
signOut(): Promise<AuthResult>;
|
|
106
151
|
getSession(): Promise<AuthResult>;
|
|
107
152
|
}
|
|
@@ -112,4 +157,4 @@ interface AccountClient {
|
|
|
112
157
|
*/
|
|
113
158
|
declare function createAccountClient(config: AccountClientConfig): AccountClient;
|
|
114
159
|
|
|
115
|
-
export { ACCOUNT_CLIENT_PACKAGE, type AccountClient, type AccountClientConfig, type AuthResult, DEFAULT_DEVICE_CLIENT_ID, DEVICE_CODE_GRANT_TYPE, type DeviceFlowClient, type DeviceFlowClientConfig, type DevicePollError, type DeviceStartResponse, type DeviceTokenResponse, type LicenseCurrentResponse, createAccountClient, createDeviceFlowClient };
|
|
160
|
+
export { ACCOUNT_CLIENT_PACKAGE, type AccountClient, type AccountClientConfig, type AuthResult, DEFAULT_DEVICE_CLIENT_ID, DEVICE_CODE_GRANT_TYPE, type DeviceFlowClient, type DeviceFlowClientConfig, type DevicePollError, type DeviceStartResponse, type DeviceTokenResponse, type LicenseCurrentResponse, type LinkedAccount, type SocialProvider, type SocialRedirectOptions, createAccountClient, createDeviceFlowClient };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { entitlementForProduct, parseEntitlement } from './chunk-
|
|
1
|
+
export { entitlementForProduct, parseEntitlement } from './chunk-V3SLFECG.js';
|
|
2
2
|
import { createAuthClient } from 'better-auth/client';
|
|
3
3
|
|
|
4
4
|
// src/device.ts
|
|
@@ -78,6 +78,21 @@ function createAccountClient(config) {
|
|
|
78
78
|
email: params.email,
|
|
79
79
|
password: params.password
|
|
80
80
|
}),
|
|
81
|
+
signInWithProvider: (provider, options) => client.signIn.social({
|
|
82
|
+
provider,
|
|
83
|
+
callbackURL: options.callbackURL,
|
|
84
|
+
errorCallbackURL: options.errorCallbackURL
|
|
85
|
+
}),
|
|
86
|
+
listAccounts: () => client.listAccounts(),
|
|
87
|
+
linkSocial: (provider, options) => client.linkSocial({
|
|
88
|
+
provider,
|
|
89
|
+
callbackURL: options.callbackURL,
|
|
90
|
+
errorCallbackURL: options.errorCallbackURL
|
|
91
|
+
}),
|
|
92
|
+
unlinkAccount: (params) => client.unlinkAccount({
|
|
93
|
+
providerId: params.providerId,
|
|
94
|
+
accountId: params.accountId
|
|
95
|
+
}),
|
|
81
96
|
signOut: () => client.signOut(),
|
|
82
97
|
getSession: () => client.getSession()
|
|
83
98
|
};
|
package/dist/introspect.cjs
CHANGED
|
@@ -7,6 +7,7 @@ function parseEntitlement(wire) {
|
|
|
7
7
|
plan: wire.plan,
|
|
8
8
|
addons: wire.addons ?? [],
|
|
9
9
|
products: wire.products ?? [],
|
|
10
|
+
productPlans: wire.product_plans ?? {},
|
|
10
11
|
features: wire.features
|
|
11
12
|
};
|
|
12
13
|
}
|
|
@@ -59,7 +60,10 @@ function createIntrospectionClient(config) {
|
|
|
59
60
|
try {
|
|
60
61
|
raw = await res.json();
|
|
61
62
|
} catch (err) {
|
|
62
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
status: "integrity_error",
|
|
65
|
+
reason: `introspect unparseable body: ${errMessage(err)}`
|
|
66
|
+
};
|
|
63
67
|
}
|
|
64
68
|
if (!raw || typeof raw !== "object") {
|
|
65
69
|
return { status: "integrity_error", reason: "introspect non-object body" };
|
|
@@ -105,6 +109,65 @@ function createIntrospectionClient(config) {
|
|
|
105
109
|
} catch (err) {
|
|
106
110
|
return { status: "unavailable", reason: `entitlement unparseable body: ${errMessage(err)}` };
|
|
107
111
|
}
|
|
112
|
+
},
|
|
113
|
+
async listOrgMembers(orgId) {
|
|
114
|
+
let res;
|
|
115
|
+
try {
|
|
116
|
+
res = await call(`/v1/orgs/${encodeURIComponent(orgId)}/members`, {
|
|
117
|
+
method: "GET",
|
|
118
|
+
headers: secretHeaders
|
|
119
|
+
});
|
|
120
|
+
} catch (err) {
|
|
121
|
+
return { status: "unavailable", reason: `roster transport error: ${errMessage(err)}` };
|
|
122
|
+
}
|
|
123
|
+
if (!res.ok) return { status: "unavailable", reason: `roster http ${res.status}` };
|
|
124
|
+
try {
|
|
125
|
+
const body = await res.json();
|
|
126
|
+
return {
|
|
127
|
+
status: "ok",
|
|
128
|
+
members: (body.members ?? []).map((m) => ({
|
|
129
|
+
userId: m.user_id,
|
|
130
|
+
email: m.email ?? null,
|
|
131
|
+
name: m.name ?? null,
|
|
132
|
+
role: m.role,
|
|
133
|
+
seatNo: m.seat_no ?? null
|
|
134
|
+
}))
|
|
135
|
+
};
|
|
136
|
+
} catch (err) {
|
|
137
|
+
return { status: "unavailable", reason: `roster unparseable body: ${errMessage(err)}` };
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
async listOrgTeams(orgId) {
|
|
141
|
+
let res;
|
|
142
|
+
try {
|
|
143
|
+
res = await call(`/v1/orgs/${encodeURIComponent(orgId)}/teams`, {
|
|
144
|
+
method: "GET",
|
|
145
|
+
headers: secretHeaders
|
|
146
|
+
});
|
|
147
|
+
} catch (err) {
|
|
148
|
+
return { status: "unavailable", reason: `teams transport error: ${errMessage(err)}` };
|
|
149
|
+
}
|
|
150
|
+
if (!res.ok) return { status: "unavailable", reason: `teams http ${res.status}` };
|
|
151
|
+
try {
|
|
152
|
+
const body = await res.json();
|
|
153
|
+
return {
|
|
154
|
+
status: "ok",
|
|
155
|
+
teams: (body.teams ?? []).map((t) => ({
|
|
156
|
+
id: t.id,
|
|
157
|
+
slug: t.slug,
|
|
158
|
+
name: t.name,
|
|
159
|
+
members: (t.members ?? []).map((m) => ({
|
|
160
|
+
userId: m.user_id,
|
|
161
|
+
orgMemberId: m.org_member_id,
|
|
162
|
+
teamRole: m.team_role,
|
|
163
|
+
email: m.email ?? null,
|
|
164
|
+
name: m.name ?? null
|
|
165
|
+
}))
|
|
166
|
+
}))
|
|
167
|
+
};
|
|
168
|
+
} catch (err) {
|
|
169
|
+
return { status: "unavailable", reason: `teams unparseable body: ${errMessage(err)}` };
|
|
170
|
+
}
|
|
108
171
|
}
|
|
109
172
|
};
|
|
110
173
|
}
|
package/dist/introspect.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as Entitlement } from './entitlement-
|
|
1
|
+
import { E as Entitlement } from './entitlement-CfKncUyH.cjs';
|
|
2
2
|
import '@viyv/shared';
|
|
3
3
|
|
|
4
4
|
interface IntrospectionClientConfig {
|
|
@@ -56,12 +56,54 @@ type OrgEntitlementOutcome = {
|
|
|
56
56
|
status: "unavailable";
|
|
57
57
|
reason: string;
|
|
58
58
|
};
|
|
59
|
+
/** An org member resolved from the m2m roster read (camelCase). */
|
|
60
|
+
interface OrgMemberInfo {
|
|
61
|
+
userId: string;
|
|
62
|
+
email: string | null;
|
|
63
|
+
name: string | null;
|
|
64
|
+
role: string;
|
|
65
|
+
seatNo: number | null;
|
|
66
|
+
}
|
|
67
|
+
/** A sub-team member resolved from the m2m teams read. */
|
|
68
|
+
interface OrgTeamMemberInfo {
|
|
69
|
+
userId: string;
|
|
70
|
+
orgMemberId: string;
|
|
71
|
+
/** lead | member (free-text at the source; the caller maps it). */
|
|
72
|
+
teamRole: string;
|
|
73
|
+
email: string | null;
|
|
74
|
+
name: string | null;
|
|
75
|
+
}
|
|
76
|
+
/** A sub-team resolved from the m2m teams read. */
|
|
77
|
+
interface OrgTeamInfo {
|
|
78
|
+
id: string;
|
|
79
|
+
slug: string;
|
|
80
|
+
name: string;
|
|
81
|
+
members: OrgTeamMemberInfo[];
|
|
82
|
+
}
|
|
83
|
+
type OrgRosterOutcome = {
|
|
84
|
+
status: "ok";
|
|
85
|
+
members: OrgMemberInfo[];
|
|
86
|
+
} | {
|
|
87
|
+
status: "unavailable";
|
|
88
|
+
reason: string;
|
|
89
|
+
};
|
|
90
|
+
type OrgTeamsOutcome = {
|
|
91
|
+
status: "ok";
|
|
92
|
+
teams: OrgTeamInfo[];
|
|
93
|
+
} | {
|
|
94
|
+
status: "unavailable";
|
|
95
|
+
reason: string;
|
|
96
|
+
};
|
|
59
97
|
interface IntrospectionClient {
|
|
60
98
|
/** Resolve a device access token to a subject (fail-closed, see taxonomy). */
|
|
61
99
|
introspectDevice(accessToken: string): Promise<IntrospectionOutcome>;
|
|
62
100
|
/** Read an org's entitlement by id (m2m). */
|
|
63
101
|
getOrgEntitlement(orgId: string): Promise<OrgEntitlementOutcome>;
|
|
102
|
+
/** Read an org's member roster (m2m, service secret). Names are render-time only. */
|
|
103
|
+
listOrgMembers(orgId: string): Promise<OrgRosterOutcome>;
|
|
104
|
+
/** Read an org's sub-teams + their members (m2m, service secret). */
|
|
105
|
+
listOrgTeams(orgId: string): Promise<OrgTeamsOutcome>;
|
|
64
106
|
}
|
|
65
107
|
declare function createIntrospectionClient(config: IntrospectionClientConfig): IntrospectionClient;
|
|
66
108
|
|
|
67
|
-
export { type IntrospectionClient, type IntrospectionClientConfig, type IntrospectionOutcome, type OrgEntitlementOutcome, type ResolvedDeviceSubject, createIntrospectionClient };
|
|
109
|
+
export { type IntrospectionClient, type IntrospectionClientConfig, type IntrospectionOutcome, type OrgEntitlementOutcome, type OrgMemberInfo, type OrgRosterOutcome, type OrgTeamInfo, type OrgTeamMemberInfo, type OrgTeamsOutcome, type ResolvedDeviceSubject, createIntrospectionClient };
|
package/dist/introspect.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as Entitlement } from './entitlement-
|
|
1
|
+
import { E as Entitlement } from './entitlement-CfKncUyH.js';
|
|
2
2
|
import '@viyv/shared';
|
|
3
3
|
|
|
4
4
|
interface IntrospectionClientConfig {
|
|
@@ -56,12 +56,54 @@ type OrgEntitlementOutcome = {
|
|
|
56
56
|
status: "unavailable";
|
|
57
57
|
reason: string;
|
|
58
58
|
};
|
|
59
|
+
/** An org member resolved from the m2m roster read (camelCase). */
|
|
60
|
+
interface OrgMemberInfo {
|
|
61
|
+
userId: string;
|
|
62
|
+
email: string | null;
|
|
63
|
+
name: string | null;
|
|
64
|
+
role: string;
|
|
65
|
+
seatNo: number | null;
|
|
66
|
+
}
|
|
67
|
+
/** A sub-team member resolved from the m2m teams read. */
|
|
68
|
+
interface OrgTeamMemberInfo {
|
|
69
|
+
userId: string;
|
|
70
|
+
orgMemberId: string;
|
|
71
|
+
/** lead | member (free-text at the source; the caller maps it). */
|
|
72
|
+
teamRole: string;
|
|
73
|
+
email: string | null;
|
|
74
|
+
name: string | null;
|
|
75
|
+
}
|
|
76
|
+
/** A sub-team resolved from the m2m teams read. */
|
|
77
|
+
interface OrgTeamInfo {
|
|
78
|
+
id: string;
|
|
79
|
+
slug: string;
|
|
80
|
+
name: string;
|
|
81
|
+
members: OrgTeamMemberInfo[];
|
|
82
|
+
}
|
|
83
|
+
type OrgRosterOutcome = {
|
|
84
|
+
status: "ok";
|
|
85
|
+
members: OrgMemberInfo[];
|
|
86
|
+
} | {
|
|
87
|
+
status: "unavailable";
|
|
88
|
+
reason: string;
|
|
89
|
+
};
|
|
90
|
+
type OrgTeamsOutcome = {
|
|
91
|
+
status: "ok";
|
|
92
|
+
teams: OrgTeamInfo[];
|
|
93
|
+
} | {
|
|
94
|
+
status: "unavailable";
|
|
95
|
+
reason: string;
|
|
96
|
+
};
|
|
59
97
|
interface IntrospectionClient {
|
|
60
98
|
/** Resolve a device access token to a subject (fail-closed, see taxonomy). */
|
|
61
99
|
introspectDevice(accessToken: string): Promise<IntrospectionOutcome>;
|
|
62
100
|
/** Read an org's entitlement by id (m2m). */
|
|
63
101
|
getOrgEntitlement(orgId: string): Promise<OrgEntitlementOutcome>;
|
|
102
|
+
/** Read an org's member roster (m2m, service secret). Names are render-time only. */
|
|
103
|
+
listOrgMembers(orgId: string): Promise<OrgRosterOutcome>;
|
|
104
|
+
/** Read an org's sub-teams + their members (m2m, service secret). */
|
|
105
|
+
listOrgTeams(orgId: string): Promise<OrgTeamsOutcome>;
|
|
64
106
|
}
|
|
65
107
|
declare function createIntrospectionClient(config: IntrospectionClientConfig): IntrospectionClient;
|
|
66
108
|
|
|
67
|
-
export { type IntrospectionClient, type IntrospectionClientConfig, type IntrospectionOutcome, type OrgEntitlementOutcome, type ResolvedDeviceSubject, createIntrospectionClient };
|
|
109
|
+
export { type IntrospectionClient, type IntrospectionClientConfig, type IntrospectionOutcome, type OrgEntitlementOutcome, type OrgMemberInfo, type OrgRosterOutcome, type OrgTeamInfo, type OrgTeamMemberInfo, type OrgTeamsOutcome, type ResolvedDeviceSubject, createIntrospectionClient };
|
package/dist/introspect.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseEntitlement } from './chunk-
|
|
1
|
+
import { parseEntitlement } from './chunk-V3SLFECG.js';
|
|
2
2
|
|
|
3
3
|
// src/introspect.ts
|
|
4
4
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
@@ -48,7 +48,10 @@ function createIntrospectionClient(config) {
|
|
|
48
48
|
try {
|
|
49
49
|
raw = await res.json();
|
|
50
50
|
} catch (err) {
|
|
51
|
-
return {
|
|
51
|
+
return {
|
|
52
|
+
status: "integrity_error",
|
|
53
|
+
reason: `introspect unparseable body: ${errMessage(err)}`
|
|
54
|
+
};
|
|
52
55
|
}
|
|
53
56
|
if (!raw || typeof raw !== "object") {
|
|
54
57
|
return { status: "integrity_error", reason: "introspect non-object body" };
|
|
@@ -94,6 +97,65 @@ function createIntrospectionClient(config) {
|
|
|
94
97
|
} catch (err) {
|
|
95
98
|
return { status: "unavailable", reason: `entitlement unparseable body: ${errMessage(err)}` };
|
|
96
99
|
}
|
|
100
|
+
},
|
|
101
|
+
async listOrgMembers(orgId) {
|
|
102
|
+
let res;
|
|
103
|
+
try {
|
|
104
|
+
res = await call(`/v1/orgs/${encodeURIComponent(orgId)}/members`, {
|
|
105
|
+
method: "GET",
|
|
106
|
+
headers: secretHeaders
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
return { status: "unavailable", reason: `roster transport error: ${errMessage(err)}` };
|
|
110
|
+
}
|
|
111
|
+
if (!res.ok) return { status: "unavailable", reason: `roster http ${res.status}` };
|
|
112
|
+
try {
|
|
113
|
+
const body = await res.json();
|
|
114
|
+
return {
|
|
115
|
+
status: "ok",
|
|
116
|
+
members: (body.members ?? []).map((m) => ({
|
|
117
|
+
userId: m.user_id,
|
|
118
|
+
email: m.email ?? null,
|
|
119
|
+
name: m.name ?? null,
|
|
120
|
+
role: m.role,
|
|
121
|
+
seatNo: m.seat_no ?? null
|
|
122
|
+
}))
|
|
123
|
+
};
|
|
124
|
+
} catch (err) {
|
|
125
|
+
return { status: "unavailable", reason: `roster unparseable body: ${errMessage(err)}` };
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async listOrgTeams(orgId) {
|
|
129
|
+
let res;
|
|
130
|
+
try {
|
|
131
|
+
res = await call(`/v1/orgs/${encodeURIComponent(orgId)}/teams`, {
|
|
132
|
+
method: "GET",
|
|
133
|
+
headers: secretHeaders
|
|
134
|
+
});
|
|
135
|
+
} catch (err) {
|
|
136
|
+
return { status: "unavailable", reason: `teams transport error: ${errMessage(err)}` };
|
|
137
|
+
}
|
|
138
|
+
if (!res.ok) return { status: "unavailable", reason: `teams http ${res.status}` };
|
|
139
|
+
try {
|
|
140
|
+
const body = await res.json();
|
|
141
|
+
return {
|
|
142
|
+
status: "ok",
|
|
143
|
+
teams: (body.teams ?? []).map((t) => ({
|
|
144
|
+
id: t.id,
|
|
145
|
+
slug: t.slug,
|
|
146
|
+
name: t.name,
|
|
147
|
+
members: (t.members ?? []).map((m) => ({
|
|
148
|
+
userId: m.user_id,
|
|
149
|
+
orgMemberId: m.org_member_id,
|
|
150
|
+
teamRole: m.team_role,
|
|
151
|
+
email: m.email ?? null,
|
|
152
|
+
name: m.name ?? null
|
|
153
|
+
}))
|
|
154
|
+
}))
|
|
155
|
+
};
|
|
156
|
+
} catch (err) {
|
|
157
|
+
return { status: "unavailable", reason: `teams unparseable body: ${errMessage(err)}` };
|
|
158
|
+
}
|
|
97
159
|
}
|
|
98
160
|
};
|
|
99
161
|
}
|