@adonis-agora/authkit-react 1.0.0-rc.2 → 1.0.0-rc.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @adonis-agora/authkit-react
2
2
 
3
+ ## 1.0.0-rc.3
4
+
5
+ ### Minor Changes
6
+
7
+ - [#470](https://github.com/DavideCarvalho/adonis-agora-authkit/pull/470) [`d8ee87a`](https://github.com/DavideCarvalho/adonis-agora-authkit/commit/d8ee87abd875e8c141cde051023f1035d8274513) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Account console extensions: other packages (and your app) can add pages to `/account/*`.
8
+
9
+ - New subpath `@adonis-agora/authkit-server/account-extension` with the stable contract (`AccountExtension`, blocks, actions) and the `authkit.accountExtensions` registry binding. Contributors register from their provider's `boot()`; AuthKit renders the pages (Edge or your Inertia page) behind the account sign-in, with CSRF, sudo for sensitive actions, a per-account rate limit, and audit of external redirects.
10
+ - Blocks: `notice`, `keyValue`, `list`, `table`, `meter`, `actions`, `link`, `toolPreview` (approve/reject previews) and `component` (a provider's card fields, scripts loaded with the response's CSP nonce, with a link fallback).
11
+ - `accountConsole` in `config/authkit.ts`: one `subject(account, { activeOrg, tenant })` mapping shared by every extension, host overrides to disable, rename or reorder pages, and `loadTimeoutMs`.
12
+ - The account screens share one navigation (`accountNav`) that lists the mounted screens and the extension pages; `AuthHostRouteMap.account.extensions` lists the pages.
13
+ - JSON API: `GET {prefix}/api/extensions`, `GET {prefix}/api/x/:pageId`, `POST {prefix}/api/x/:pageId/actions/:action`.
14
+ - authkit-react: `<AccountExtensionPage>`, `useAccountExtensions()`, the page/action query options and `client.account.extensions.*`.
15
+
3
16
  ## 1.0.0-rc.2
4
17
 
5
18
  ### Minor Changes
package/build/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ export type { AccountExtensionPageProps, AccountExtensionProviderComponentProps, } from './src/account_extensions/account_extension_page.js';
2
+ export { AccountExtensionPage, useAccountExtensionActionMutationOptions, useAccountExtensionPageQueryOptions, useAccountExtensions, useAccountExtensionsQueryOptions, } from './src/account_extensions/account_extension_page.js';
3
+ export type { AccountExtensionActionButton, AccountExtensionActionDefinition, AccountExtensionActionField, AccountExtensionActionInput, AccountExtensionActionResult, AccountExtensionBlock, AccountExtensionPageResult, AccountExtensionPageView, AccountExtensionsResult, AccountExtensionValue, AccountNavEntry, } from './src/account_extensions/types.js';
1
4
  export type { AuthkitProviderProps } from './src/authkit_provider.js';
2
5
  export { AuthkitProvider } from './src/authkit_provider.js';
3
6
  export type { AuthkitClient, AuthkitClientOptions, } from './src/client/client.js';
package/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { AccountExtensionPage, useAccountExtensionActionMutationOptions, useAccountExtensionPageQueryOptions, useAccountExtensions, useAccountExtensionsQueryOptions, } from './src/account_extensions/account_extension_page.js';
1
2
  export { AuthkitProvider } from './src/authkit_provider.js';
2
3
  export { AuthkitClientError, createAuthkitClient, } from './src/client/client.js';
3
4
  export { AuthkitClientProvider, createAuthkitQueryClient, useAuthkitClient, } from './src/client/context.js';
@@ -0,0 +1,42 @@
1
+ import { type ComponentType } from 'react';
2
+ import type { AuthkitClientError } from '../client/client.js';
3
+ import type { AccountExtensionActionButton, AccountExtensionActionInput, AccountExtensionPageView, AccountExtensionsResult } from './types.js';
4
+ export declare function useAccountExtensionsQueryOptions(): {
5
+ queryKey: readonly ["authkit", "account", "extensions"];
6
+ queryFn: () => Promise<AccountExtensionsResult>;
7
+ };
8
+ export declare function useAccountExtensionPageQueryOptions(pageId: string, query?: {
9
+ cursor?: string;
10
+ tab?: string;
11
+ }): {
12
+ queryKey: readonly ["authkit", "account", "extensions", string, {
13
+ cursor?: string;
14
+ tab?: string;
15
+ }];
16
+ queryFn: () => Promise<import("./types.js").AccountExtensionPageResult>;
17
+ };
18
+ export declare function useAccountExtensionActionMutationOptions(pageId: string): {
19
+ mutationKey: readonly ['authkit', 'account', 'extensions', string, 'action'];
20
+ mutationFn: (input: {
21
+ action: string;
22
+ } & AccountExtensionActionInput) => Promise<import("./types.js").AccountExtensionActionResult>;
23
+ };
24
+ export declare function useAccountExtensions(): import("@tanstack/react-query").UseQueryResult<AccountExtensionsResult, AuthkitClientError>;
25
+ export interface AccountExtensionProviderComponentProps {
26
+ provider: string;
27
+ props: Record<string, unknown>;
28
+ submit: AccountExtensionActionButton | null;
29
+ onSubmit?: (input: AccountExtensionActionInput) => void;
30
+ }
31
+ export interface AccountExtensionPageProps {
32
+ view: AccountExtensionPageView;
33
+ onAction?: (button: AccountExtensionActionButton, input?: AccountExtensionActionInput) => void;
34
+ csrfToken?: string;
35
+ loadComponent?: (provider: string) => ComponentType<AccountExtensionProviderComponentProps> | null | Promise<ComponentType<AccountExtensionProviderComponentProps> | null>;
36
+ nextLabel?: string;
37
+ className?: string;
38
+ }
39
+ export declare function AccountExtensionPage(props: AccountExtensionPageProps): import("react").DetailedReactHTMLElement<{
40
+ className: string | undefined;
41
+ 'data-account-extension': string;
42
+ }, HTMLElement>;
@@ -0,0 +1,144 @@
1
+ import { useQuery } from '@tanstack/react-query';
2
+ import { createElement, useEffect, useState } from 'react';
3
+ import { useAuthkitClient } from '../client/context.js';
4
+ import { authkitKeys } from '../queries/keys.js';
5
+ export function useAccountExtensionsQueryOptions() {
6
+ const client = useAuthkitClient();
7
+ return {
8
+ queryKey: authkitKeys.account.extensions(),
9
+ queryFn: () => client.account.extensions.list(),
10
+ };
11
+ }
12
+ export function useAccountExtensionPageQueryOptions(pageId, query) {
13
+ const client = useAuthkitClient();
14
+ return {
15
+ queryKey: authkitKeys.account.extensionPage(pageId, query),
16
+ queryFn: () => client.account.extensions.page(pageId, query),
17
+ };
18
+ }
19
+ export function useAccountExtensionActionMutationOptions(pageId) {
20
+ const client = useAuthkitClient();
21
+ return {
22
+ mutationKey: ['authkit', 'account', 'extensions', pageId, 'action'],
23
+ mutationFn: (input) => client.account.extensions.action(pageId, input.action, {
24
+ target: input.target ?? null,
25
+ fields: input.fields ?? {},
26
+ }),
27
+ };
28
+ }
29
+ export function useAccountExtensions() {
30
+ return useQuery(useAccountExtensionsQueryOptions());
31
+ }
32
+ const e = createElement;
33
+ function Value({ value }) {
34
+ if (value.type === 'date' && value.iso) {
35
+ return e('time', { dateTime: value.iso, 'data-value': 'date' }, value.text);
36
+ }
37
+ return e('span', {
38
+ 'data-value': value.type,
39
+ ...(value.type === 'badge' ? { 'data-tone': value.tone ?? 'neutral' } : {}),
40
+ }, value.text);
41
+ }
42
+ function ActionButtons({ actions, onAction, csrfToken, }) {
43
+ if (actions.length === 0)
44
+ return null;
45
+ return e('span', { 'data-actions': '' }, actions.map((button) => {
46
+ const key = `${button.action}:${button.target ?? ''}`;
47
+ const common = { 'data-action': button.action, 'data-tone': button.tone };
48
+ if (onAction) {
49
+ return e('button', { key, type: 'button', ...common, onClick: () => onAction(button) }, button.label);
50
+ }
51
+ if (button.step)
52
+ return e('a', { key, href: button.href, ...common }, button.label);
53
+ return e('form', { key, method: 'post', action: button.href }, e('input', { type: 'hidden', name: '_csrf', value: csrfToken ?? '' }), button.target !== null
54
+ ? e('input', { type: 'hidden', name: 'target', value: button.target })
55
+ : null, e('button', { type: 'submit', ...common }, button.label));
56
+ }));
57
+ }
58
+ function ProviderComponent({ block, loadComponent, onAction, }) {
59
+ const [Loaded, setLoaded] = useState(null);
60
+ useEffect(() => {
61
+ let alive = true;
62
+ if (!loadComponent)
63
+ return;
64
+ Promise.resolve(loadComponent(block.provider))
65
+ .then((component) => {
66
+ if (alive && component)
67
+ setLoaded(() => component);
68
+ })
69
+ .catch(() => { });
70
+ return () => {
71
+ alive = false;
72
+ };
73
+ }, [block.provider, loadComponent]);
74
+ const fallback = block.fallback
75
+ ? e('a', {
76
+ href: block.fallback.href,
77
+ 'data-component-fallback': '',
78
+ ...(block.fallback.external ? { rel: 'noopener' } : {}),
79
+ }, block.fallback.label)
80
+ : null;
81
+ return e('div', { 'data-block': 'component', 'data-provider': block.provider }, Loaded
82
+ ? e(Loaded, {
83
+ provider: block.provider,
84
+ props: block.props,
85
+ submit: block.submit,
86
+ ...(onAction && block.submit
87
+ ? {
88
+ onSubmit: (input) => onAction(block.submit, input),
89
+ }
90
+ : {}),
91
+ })
92
+ : fallback);
93
+ }
94
+ function Block({ block, props, }) {
95
+ const actions = (list) => e(ActionButtons, { actions: list, onAction: props.onAction, csrfToken: props.csrfToken });
96
+ const next = (href) => href ? e('a', { href, rel: 'next', 'data-next': '' }, props.nextLabel ?? 'Next page') : null;
97
+ switch (block.kind) {
98
+ case 'notice':
99
+ return e('div', { 'data-block': 'notice', 'data-tone': block.tone, role: 'status' }, block.text);
100
+ case 'keyValue':
101
+ return e('section', { 'data-block': 'keyValue' }, block.title ? e('h2', null, block.title) : null, e('dl', null, block.rows.map((row, i) => e('div', { key: i }, e('dt', null, row.label), e('dd', null, e(Value, { value: row.value }))))), actions(block.actions));
102
+ case 'list':
103
+ return e('section', { 'data-block': 'list' }, block.title ? e('h2', null, block.title) : null, block.items.length === 0
104
+ ? e('p', { 'data-empty': '' }, block.empty)
105
+ : e('ul', null, block.items.map((item, i) => e('li', { key: i }, item.href
106
+ ? e('a', {
107
+ href: item.href,
108
+ ...(item.external ? { rel: 'noopener', target: '_blank' } : {}),
109
+ }, item.title)
110
+ : e('span', null, item.title), item.subtitle ? e('small', null, item.subtitle) : null, item.meta.map((value, j) => e(Value, { key: j, value })), item.badge ? e(Value, { value: item.badge }) : null, actions(item.actions)))), next(block.nextHref));
111
+ case 'table':
112
+ return e('section', { 'data-block': 'table' }, block.title ? e('h2', null, block.title) : null, block.rows.length === 0
113
+ ? e('p', { 'data-empty': '' }, block.empty)
114
+ : e('table', null, e('thead', null, e('tr', null, block.columns.map((c) => e('th', { key: c.id, scope: 'col' }, c.label)), block.hasActions ? e('th', { scope: 'col' }) : null)), e('tbody', null, block.rows.map((row, i) => e('tr', { key: i }, row.cells.map((value, j) => e('td', { key: j }, e(Value, { value }))), block.hasActions ? e('td', null, actions(row.actions)) : null)))), next(block.nextHref));
115
+ case 'meter':
116
+ return e('section', { 'data-block': 'meter' }, e('span', null, block.label), e('span', null, block.text), block.percent !== null ? e('progress', { max: 100, value: block.percent }) : null, block.resetsAt ? e(Value, { value: block.resetsAt }) : null);
117
+ case 'actions':
118
+ return e('div', { 'data-block': 'actions' }, actions(block.items));
119
+ case 'link':
120
+ return e('a', {
121
+ 'data-block': 'link',
122
+ href: block.href,
123
+ ...(block.external ? { rel: 'noopener', target: '_blank' } : {}),
124
+ }, block.label);
125
+ case 'toolPreview':
126
+ return e('section', { 'data-block': 'toolPreview' }, e('h2', null, block.title), block.tool ? e('code', null, block.tool) : null, block.subtitle ? e('small', null, block.subtitle) : null, block.args.length > 0
127
+ ? e('dl', null, block.args.map((arg, i) => e('div', { key: i }, e('dt', null, arg.label), e('dd', null, e(Value, { value: arg.value })))))
128
+ : null, block.body ? e('pre', { 'data-format': block.body.format }, block.body.content) : null, actions(block.actions));
129
+ case 'component':
130
+ return e(ProviderComponent, {
131
+ block,
132
+ loadComponent: props.loadComponent,
133
+ onAction: props.onAction,
134
+ });
135
+ default:
136
+ return null;
137
+ }
138
+ }
139
+ export function AccountExtensionPage(props) {
140
+ const { view } = props;
141
+ return e('div', { className: props.className, 'data-account-extension': view.id }, view.tabs.length > 0
142
+ ? e('nav', { role: 'tablist', 'data-block': 'tabs' }, view.tabs.map((tab) => e('a', { key: tab.id, href: tab.href, role: 'tab', 'aria-selected': tab.active }, tab.label)))
143
+ : null, view.blocks.map((block, i) => e(Block, { key: i, block, props })));
144
+ }
@@ -0,0 +1,174 @@
1
+ export interface AccountExtensionValue {
2
+ type: 'text' | 'money' | 'date' | 'badge' | 'number';
3
+ text: string;
4
+ tone?: 'neutral' | 'success' | 'warning' | 'danger';
5
+ iso?: string;
6
+ amount?: number;
7
+ currency?: string;
8
+ value?: number;
9
+ }
10
+ export interface AccountExtensionActionButton {
11
+ action: string;
12
+ target: string | null;
13
+ label: string;
14
+ tone: 'default' | 'danger';
15
+ sudo: boolean;
16
+ step: boolean;
17
+ href: string;
18
+ postHref: string;
19
+ apiHref: string;
20
+ }
21
+ export type AccountExtensionBlock = {
22
+ kind: 'notice';
23
+ tone: 'info' | 'success' | 'warning' | 'danger';
24
+ text: string;
25
+ } | {
26
+ kind: 'keyValue';
27
+ title: string | null;
28
+ rows: Array<{
29
+ label: string;
30
+ value: AccountExtensionValue;
31
+ }>;
32
+ actions: AccountExtensionActionButton[];
33
+ } | {
34
+ kind: 'list';
35
+ title: string | null;
36
+ empty: string;
37
+ items: Array<{
38
+ title: string;
39
+ subtitle: string | null;
40
+ meta: AccountExtensionValue[];
41
+ badge: AccountExtensionValue | null;
42
+ href: string | null;
43
+ external: boolean;
44
+ actions: AccountExtensionActionButton[];
45
+ }>;
46
+ nextHref: string | null;
47
+ nextCursor: string | null;
48
+ } | {
49
+ kind: 'table';
50
+ title: string | null;
51
+ empty: string;
52
+ columns: Array<{
53
+ id: string;
54
+ label: string;
55
+ }>;
56
+ rows: Array<{
57
+ cells: AccountExtensionValue[];
58
+ actions: AccountExtensionActionButton[];
59
+ }>;
60
+ hasActions: boolean;
61
+ nextHref: string | null;
62
+ nextCursor: string | null;
63
+ } | {
64
+ kind: 'meter';
65
+ label: string;
66
+ used: number;
67
+ limit: number | null;
68
+ percent: number | null;
69
+ text: string;
70
+ resetsAt: AccountExtensionValue | null;
71
+ } | {
72
+ kind: 'actions';
73
+ items: AccountExtensionActionButton[];
74
+ } | {
75
+ kind: 'link';
76
+ label: string;
77
+ href: string;
78
+ external: boolean;
79
+ } | {
80
+ kind: 'toolPreview';
81
+ title: string;
82
+ tool: string | null;
83
+ subtitle: string | null;
84
+ args: Array<{
85
+ label: string;
86
+ value: AccountExtensionValue;
87
+ }>;
88
+ body: {
89
+ format: 'json' | 'text';
90
+ content: string;
91
+ } | null;
92
+ actions: AccountExtensionActionButton[];
93
+ } | {
94
+ kind: 'component';
95
+ provider: string;
96
+ mountId: string;
97
+ scripts: Array<{
98
+ src: string;
99
+ integrity: string | null;
100
+ module: boolean;
101
+ }>;
102
+ propsJson: string;
103
+ props: Record<string, unknown>;
104
+ submit: AccountExtensionActionButton | null;
105
+ fallback: {
106
+ label: string;
107
+ href: string;
108
+ external: boolean;
109
+ } | null;
110
+ };
111
+ export interface AccountExtensionPageView {
112
+ id: string;
113
+ extension: string;
114
+ title: string;
115
+ href: string;
116
+ tabs: Array<{
117
+ id: string;
118
+ label: string;
119
+ href: string;
120
+ active: boolean;
121
+ }>;
122
+ blocks: AccountExtensionBlock[];
123
+ }
124
+ export interface AccountExtensionActionField {
125
+ name: string;
126
+ label: string;
127
+ kind: 'text' | 'select' | 'textarea';
128
+ required: boolean;
129
+ maxLength: number | null;
130
+ options: Array<{
131
+ value: string;
132
+ label: string;
133
+ }>;
134
+ value: string;
135
+ }
136
+ export interface AccountExtensionActionDefinition {
137
+ label: string;
138
+ tone: 'default' | 'danger';
139
+ confirm: string | null;
140
+ sudo: boolean;
141
+ fields: AccountExtensionActionField[];
142
+ }
143
+ export interface AccountExtensionPageResult {
144
+ page: AccountExtensionPageView;
145
+ actions: Record<string, AccountExtensionActionDefinition>;
146
+ }
147
+ export interface AccountNavEntry {
148
+ id: string;
149
+ label: string;
150
+ href: string;
151
+ active: boolean;
152
+ group: 'account' | 'billing' | 'ai' | 'content';
153
+ order: number;
154
+ }
155
+ export interface AccountExtensionsResult {
156
+ nav: AccountNavEntry[];
157
+ pages: Array<{
158
+ id: string;
159
+ label: string;
160
+ href: string;
161
+ order: number;
162
+ group: AccountNavEntry['group'];
163
+ }>;
164
+ }
165
+ export interface AccountExtensionActionInput {
166
+ target?: string | null;
167
+ fields?: Record<string, string>;
168
+ }
169
+ export interface AccountExtensionActionResult {
170
+ ok: true;
171
+ flash: string;
172
+ redirectTo: string | null;
173
+ external: boolean;
174
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { AccountExtensionActionInput, AccountExtensionActionResult, AccountExtensionPageResult, AccountExtensionsResult } from '../account_extensions/types.js';
1
2
  import type { AcceptOrgInvitationResult, AccountAgentsResult, AccountAppsResult, AccountLoginMethodsResult, AccountMe, AccountMfaStatus, AccountOrgDetail, AccountOrgInvitationsResult, AccountOrgsResult, AccountPasskeysResult, AccountSecurityOverview, AccountSessionsResult, AccountTokensResult, ActivateOrgResult, AdminClient, AdminClientListResult, AdminOrgDetail, AdminOrgEntry, AdminOrgInvitation, AdminOrgListResult, AdminOverview, AdminUser, AdminUserListResult, AuditListParams, AuditListResult, ChangePasswordInput, CreateAccountOrgInput, CreateClientInput, CreatedAccountOrgResult, CreatedClientResult, CreatedOrgInvitationResult, CreatedPatResult, CreateOrgInput, CreateRoleInput, CreateTokenInput, CreateUserInput, DeactivateOrgResult, DeletedResult, EmailChangeResult, ImpersonationPanel, InviteOrgMemberInput, KeysRotateInput, KeysRotateResult, KeysStatus, LeaveOrgResult, MfaConfirmResult, MfaDisableResult, MfaEnrollResult, MfaRecoveryCodesResult, OkResult, PasskeyRegistrationOptions, PersonalAgentConnectionsParams, PersonalAgentConnectionsResult, PersonalAgentRegistryInput, PersonalAgentRegistryResult, PersonalAgentsOverview, RegenerateSecretResult, RemoveOrgMemberResult, RemovePasskeyResult, RequestEmailChangeInput, ResetPasswordResult, RevokeAllResult, RevokeAppResult, RevokeOrgInvitationResult, RevokeOthersResult, RevokeSessionResult, RevokeSessionsResult, RevokeTokenResult, RoleCatalogEntry, RoleListResult, SettingEntry, SettingListResult, UpdateClientInput, UpdateLoginMethodsResult, UpdateOrgInput, UpdateOrgMemberRoleResult, UpdateProfileInput, UpdateProfileResult, UpdateRoleInput, UpdateUserInput, UserLoginMethodsInput, UserSessionsResult } from './types.js';
2
3
  export declare class AuthkitClientError extends Error {
3
4
  readonly status: number;
@@ -194,6 +195,14 @@ declare class AuthkitClient {
194
195
  readonly removeMember: (orgId: string, accountId: string) => Promise<RemoveOrgMemberResult>;
195
196
  readonly acceptInvitation: (token: string) => Promise<AcceptOrgInvitationResult>;
196
197
  };
198
+ readonly extensions: {
199
+ readonly list: () => Promise<AccountExtensionsResult>;
200
+ readonly page: (pageId: string, query?: {
201
+ cursor?: string;
202
+ tab?: string;
203
+ }) => Promise<AccountExtensionPageResult>;
204
+ readonly action: (pageId: string, action: string, input?: AccountExtensionActionInput) => Promise<AccountExtensionActionResult>;
205
+ };
197
206
  };
198
207
  }
199
208
  export declare function createAuthkitClient(opts?: AuthkitClientOptions): AuthkitClient;
@@ -244,6 +244,11 @@ class AuthkitClient {
244
244
  removeMember: (orgId, accountId) => this.delete(this.a(`/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(accountId)}`)),
245
245
  acceptInvitation: (token) => this.post(this.a(`/orgs/invitations/${encodeURIComponent(token)}/accept`)),
246
246
  },
247
+ extensions: {
248
+ list: () => this.get(this.a('/extensions')),
249
+ page: (pageId, query) => this.get(this.a(`/x/${encodeURIComponent(pageId)}`), query),
250
+ action: (pageId, action, input = {}) => this.post(this.a(`/x/${encodeURIComponent(pageId)}/actions/${encodeURIComponent(action)}`), input),
251
+ },
247
252
  };
248
253
  }
249
254
  export function createAuthkitClient(opts) {
@@ -50,6 +50,14 @@ export declare const authkitKeys: {
50
50
  readonly org: (id: string) => readonly ['authkit', 'account', 'orgs', string];
51
51
  readonly orgInvitations: () => readonly ['authkit', 'account', 'orgs', 'invitations'];
52
52
  readonly loginMethods: () => readonly ['authkit', 'account', 'login-methods'];
53
+ readonly extensions: () => readonly ['authkit', 'account', 'extensions'];
54
+ readonly extensionPage: (pageId: string, query?: {
55
+ cursor?: string;
56
+ tab?: string;
57
+ }) => readonly ['authkit', 'account', 'extensions', string, {
58
+ cursor?: string;
59
+ tab?: string;
60
+ }];
53
61
  readonly mutations: {
54
62
  readonly orgs: () => readonly ['authkit', 'account', 'orgs', 'mutation'];
55
63
  readonly orgCreate: () => readonly ['authkit', 'account', 'orgs', 'mutation', 'create'];
@@ -34,6 +34,8 @@ export const authkitKeys = {
34
34
  org: (id) => ['authkit', 'account', 'orgs', id],
35
35
  orgInvitations: () => ['authkit', 'account', 'orgs', 'invitations'],
36
36
  loginMethods: () => ['authkit', 'account', 'login-methods'],
37
+ extensions: () => ['authkit', 'account', 'extensions'],
38
+ extensionPage: (pageId, query) => ['authkit', 'account', 'extensions', pageId, query ?? {}],
37
39
  mutations: {
38
40
  orgs: () => ['authkit', 'account', 'orgs', 'mutation'],
39
41
  orgCreate: () => ['authkit', 'account', 'orgs', 'mutation', 'create'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonis-agora/authkit-react",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.3",
4
4
  "description": "Frontend ergonomics over AuthKit for AdonisJS + Inertia + React apps: a typed useAuth() hook, role-gating hooks and gating components.",
5
5
  "license": "MIT",
6
6
  "author": "dudousxd",