@stigmer/react 0.0.89 → 0.0.91
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/identity-provider/CreateIdentityProviderForm.d.ts.map +1 -1
- package/identity-provider/CreateIdentityProviderForm.js +60 -2
- package/identity-provider/CreateIdentityProviderForm.js.map +1 -1
- package/identity-provider/IdentityProviderDetailPanel.d.ts.map +1 -1
- package/identity-provider/IdentityProviderDetailPanel.js +87 -4
- package/identity-provider/IdentityProviderDetailPanel.js.map +1 -1
- package/identity-provider/IdentityProviderListPanel.js +5 -3
- package/identity-provider/IdentityProviderListPanel.js.map +1 -1
- package/identity-provider/IdentityProviderWizard.d.ts.map +1 -1
- package/identity-provider/IdentityProviderWizard.js +59 -4
- package/identity-provider/IdentityProviderWizard.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/package.json +7 -7
- package/platform-client/CreatePlatformClientForm.d.ts +42 -0
- package/platform-client/CreatePlatformClientForm.d.ts.map +1 -0
- package/platform-client/CreatePlatformClientForm.js +148 -0
- package/platform-client/CreatePlatformClientForm.js.map +1 -0
- package/platform-client/PlatformClientDetailPanel.d.ts +51 -0
- package/platform-client/PlatformClientDetailPanel.d.ts.map +1 -0
- package/platform-client/PlatformClientDetailPanel.js +247 -0
- package/platform-client/PlatformClientDetailPanel.js.map +1 -0
- package/platform-client/PlatformClientListPanel.d.ts +41 -0
- package/platform-client/PlatformClientListPanel.d.ts.map +1 -0
- package/platform-client/PlatformClientListPanel.js +123 -0
- package/platform-client/PlatformClientListPanel.js.map +1 -0
- package/platform-client/PlatformClientSecretAlert.d.ts +39 -0
- package/platform-client/PlatformClientSecretAlert.d.ts.map +1 -0
- package/platform-client/PlatformClientSecretAlert.js +74 -0
- package/platform-client/PlatformClientSecretAlert.js.map +1 -0
- package/platform-client/index.d.ts +11 -0
- package/platform-client/index.d.ts.map +1 -0
- package/platform-client/index.js +11 -0
- package/platform-client/index.js.map +1 -0
- package/platform-client/useCreatePlatformClient.d.ts +42 -0
- package/platform-client/useCreatePlatformClient.d.ts.map +1 -0
- package/platform-client/useCreatePlatformClient.js +49 -0
- package/platform-client/useCreatePlatformClient.js.map +1 -0
- package/platform-client/useDeletePlatformClient.d.ts +31 -0
- package/platform-client/useDeletePlatformClient.d.ts.map +1 -0
- package/platform-client/useDeletePlatformClient.js +42 -0
- package/platform-client/useDeletePlatformClient.js.map +1 -0
- package/platform-client/usePlatformClient.d.ts +37 -0
- package/platform-client/usePlatformClient.d.ts.map +1 -0
- package/platform-client/usePlatformClient.js +62 -0
- package/platform-client/usePlatformClient.js.map +1 -0
- package/platform-client/usePlatformClientList.d.ts +42 -0
- package/platform-client/usePlatformClientList.d.ts.map +1 -0
- package/platform-client/usePlatformClientList.js +71 -0
- package/platform-client/usePlatformClientList.js.map +1 -0
- package/platform-client/useRotatePlatformClientSecret.d.ts +35 -0
- package/platform-client/useRotatePlatformClientSecret.d.ts.map +1 -0
- package/platform-client/useRotatePlatformClientSecret.js +43 -0
- package/platform-client/useRotatePlatformClientSecret.js.map +1 -0
- package/platform-client/useUpdatePlatformClient.d.ts +39 -0
- package/platform-client/useUpdatePlatformClient.d.ts.map +1 -0
- package/platform-client/useUpdatePlatformClient.js +50 -0
- package/platform-client/useUpdatePlatformClient.js.map +1 -0
- package/src/identity-provider/CreateIdentityProviderForm.tsx +220 -0
- package/src/identity-provider/IdentityProviderDetailPanel.tsx +288 -6
- package/src/identity-provider/IdentityProviderListPanel.tsx +9 -2
- package/src/identity-provider/IdentityProviderWizard.tsx +231 -25
- package/src/index.ts +26 -0
- package/src/platform-client/CreatePlatformClientForm.tsx +519 -0
- package/src/platform-client/PlatformClientDetailPanel.tsx +898 -0
- package/src/platform-client/PlatformClientListPanel.tsx +413 -0
- package/src/platform-client/PlatformClientSecretAlert.tsx +252 -0
- package/src/platform-client/index.ts +49 -0
- package/src/platform-client/useCreatePlatformClient.ts +77 -0
- package/src/platform-client/useDeletePlatformClient.ts +64 -0
- package/src/platform-client/usePlatformClient.ts +86 -0
- package/src/platform-client/usePlatformClientList.ts +96 -0
- package/src/platform-client/useRotatePlatformClientSecret.ts +68 -0
- package/src/platform-client/useUpdatePlatformClient.ts +70 -0
- package/src/test/index.ts +6 -0
- package/src/{demo → test}/samples.ts +1 -1
- package/styles.css +1 -1
- package/test/__tests__/samples.test.d.ts.map +1 -0
- package/{demo → test}/__tests__/samples.test.js.map +1 -1
- package/test/index.d.ts +2 -0
- package/test/index.d.ts.map +1 -0
- package/test/index.js +6 -0
- package/test/index.js.map +1 -0
- package/{demo → test}/samples.d.ts +1 -1
- package/{demo → test}/samples.d.ts.map +1 -1
- package/{demo → test}/samples.js +1 -1
- package/{demo → test}/samples.js.map +1 -1
- package/demo/__tests__/demo-client.test.d.ts +0 -2
- package/demo/__tests__/demo-client.test.d.ts.map +0 -1
- package/demo/__tests__/demo-client.test.js +0 -133
- package/demo/__tests__/demo-client.test.js.map +0 -1
- package/demo/__tests__/fixtures.test.d.ts +0 -2
- package/demo/__tests__/fixtures.test.d.ts.map +0 -1
- package/demo/__tests__/fixtures.test.js +0 -135
- package/demo/__tests__/fixtures.test.js.map +0 -1
- package/demo/__tests__/samples.test.d.ts.map +0 -1
- package/demo/client.d.ts +0 -29
- package/demo/client.d.ts.map +0 -1
- package/demo/client.js +0 -52
- package/demo/client.js.map +0 -1
- package/demo/fixtures.d.ts +0 -194
- package/demo/fixtures.d.ts.map +0 -1
- package/demo/fixtures.js +0 -267
- package/demo/fixtures.js.map +0 -1
- package/demo/index.d.ts +0 -6
- package/demo/index.d.ts.map +0 -1
- package/demo/index.js +0 -6
- package/demo/index.js.map +0 -1
- package/demo/transport.d.ts +0 -59
- package/demo/transport.d.ts.map +0 -1
- package/demo/transport.js +0 -75
- package/demo/transport.js.map +0 -1
- package/demo/types.d.ts +0 -62
- package/demo/types.d.ts.map +0 -1
- package/demo/types.js +0 -16
- package/demo/types.js.map +0 -1
- package/src/demo/__tests__/demo-client.test.tsx +0 -213
- package/src/demo/__tests__/fixtures.test.ts +0 -214
- package/src/demo/client.ts +0 -78
- package/src/demo/fixtures.ts +0 -409
- package/src/demo/index.ts +0 -12
- package/src/demo/transport.ts +0 -116
- package/src/demo/types.ts +0 -69
- /package/src/{demo → test}/__tests__/samples.test.ts +0 -0
- /package/{demo → test}/__tests__/samples.test.d.ts +0 -0
- /package/{demo → test}/__tests__/samples.test.js +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { PlatformClientInput } from "@stigmer/sdk";
|
|
5
|
+
import type { PlatformClientCreateResponse } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/io_pb";
|
|
6
|
+
import { useStigmer } from "../hooks";
|
|
7
|
+
import { toError } from "../internal/toError";
|
|
8
|
+
|
|
9
|
+
/** Return value of {@link useCreatePlatformClient}. */
|
|
10
|
+
export interface UseCreatePlatformClientReturn {
|
|
11
|
+
/**
|
|
12
|
+
* Submit a {@link PlatformClientInput} to create a new platform client.
|
|
13
|
+
* Resolves with a {@link PlatformClientCreateResponse} containing the
|
|
14
|
+
* resource and the **one-time raw client secret**.
|
|
15
|
+
*/
|
|
16
|
+
readonly create: (
|
|
17
|
+
input: PlatformClientInput,
|
|
18
|
+
) => Promise<PlatformClientCreateResponse>;
|
|
19
|
+
/** `true` while the create request is in flight. */
|
|
20
|
+
readonly isCreating: boolean;
|
|
21
|
+
/** Error from the last failed create, or `null` when healthy. */
|
|
22
|
+
readonly error: Error | null;
|
|
23
|
+
/** Reset `error` to `null`. */
|
|
24
|
+
readonly clearError: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Mutation hook that wraps `platformclient.create()` with loading
|
|
29
|
+
* and error state.
|
|
30
|
+
*
|
|
31
|
+
* Creates a platform client resource within an organization. The
|
|
32
|
+
* response includes a **one-time raw client secret** that must be
|
|
33
|
+
* shown to the user immediately — the server never returns it again.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* const { create, isCreating, error } = useCreatePlatformClient();
|
|
38
|
+
*
|
|
39
|
+
* const response = await create({
|
|
40
|
+
* name: "my-saas-backend",
|
|
41
|
+
* org: "acme",
|
|
42
|
+
* autoProvisionAccounts: true,
|
|
43
|
+
* autoGrantOnOrg: true,
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* // response.clientSecret is the one-time raw secret
|
|
47
|
+
* // response.platformClient is the created resource
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export function useCreatePlatformClient(): UseCreatePlatformClientReturn {
|
|
51
|
+
const stigmer = useStigmer();
|
|
52
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
53
|
+
const [error, setError] = useState<Error | null>(null);
|
|
54
|
+
|
|
55
|
+
const clearError = useCallback(() => setError(null), []);
|
|
56
|
+
|
|
57
|
+
const create = useCallback(
|
|
58
|
+
async (
|
|
59
|
+
input: PlatformClientInput,
|
|
60
|
+
): Promise<PlatformClientCreateResponse> => {
|
|
61
|
+
setIsCreating(true);
|
|
62
|
+
setError(null);
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
return await stigmer.platformclient.create(input);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
setError(toError(err));
|
|
68
|
+
throw err;
|
|
69
|
+
} finally {
|
|
70
|
+
setIsCreating(false);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
[stigmer],
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return { create, isCreating, error, clearError };
|
|
77
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { DeleteResourceInput } from "@stigmer/sdk";
|
|
5
|
+
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
6
|
+
import { useStigmer } from "../hooks";
|
|
7
|
+
import { toError } from "../internal/toError";
|
|
8
|
+
|
|
9
|
+
/** Return value of {@link useDeletePlatformClient}. */
|
|
10
|
+
export interface UseDeletePlatformClientReturn {
|
|
11
|
+
/** Delete a platform client. Resolves with the deleted resource for confirmation display. */
|
|
12
|
+
readonly deletePlatformClient: (
|
|
13
|
+
input: DeleteResourceInput,
|
|
14
|
+
) => Promise<PlatformClient>;
|
|
15
|
+
/** `true` while the delete request is in flight. */
|
|
16
|
+
readonly isDeleting: boolean;
|
|
17
|
+
/** Error from the last failed delete, or `null` when healthy. */
|
|
18
|
+
readonly error: Error | null;
|
|
19
|
+
/** Reset `error` to `null`. */
|
|
20
|
+
readonly clearError: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Mutation hook that wraps `platformclient.delete()` with loading
|
|
25
|
+
* and error state.
|
|
26
|
+
*
|
|
27
|
+
* Deletes a platform client by its resource ID. Returns the deleted
|
|
28
|
+
* {@link PlatformClient} on success so callers can confirm which
|
|
29
|
+
* resource was removed.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { deletePlatformClient, isDeleting, error } = useDeletePlatformClient();
|
|
34
|
+
*
|
|
35
|
+
* await deletePlatformClient({ resourceId: "pc-abc123" });
|
|
36
|
+
* refetch(); // refresh the list after deletion
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function useDeletePlatformClient(): UseDeletePlatformClientReturn {
|
|
40
|
+
const stigmer = useStigmer();
|
|
41
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
42
|
+
const [error, setError] = useState<Error | null>(null);
|
|
43
|
+
|
|
44
|
+
const clearError = useCallback(() => setError(null), []);
|
|
45
|
+
|
|
46
|
+
const deletePlatformClient = useCallback(
|
|
47
|
+
async (input: DeleteResourceInput): Promise<PlatformClient> => {
|
|
48
|
+
setIsDeleting(true);
|
|
49
|
+
setError(null);
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
return await stigmer.platformclient.delete(input);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
setError(toError(err));
|
|
55
|
+
throw err;
|
|
56
|
+
} finally {
|
|
57
|
+
setIsDeleting(false);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
[stigmer],
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return { deletePlatformClient, isDeleting, error, clearError };
|
|
64
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
5
|
+
import { useStigmer } from "../hooks";
|
|
6
|
+
import { toError } from "../internal/toError";
|
|
7
|
+
|
|
8
|
+
/** Return value of {@link usePlatformClient}. */
|
|
9
|
+
export interface UsePlatformClientReturn {
|
|
10
|
+
/** The fetched PlatformClient, or `null` while loading or on error. */
|
|
11
|
+
readonly platformClient: PlatformClient | null;
|
|
12
|
+
/** `true` while the initial fetch or a refetch is in flight. */
|
|
13
|
+
readonly isLoading: boolean;
|
|
14
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
15
|
+
readonly error: Error | null;
|
|
16
|
+
/** Discard cached data and re-fetch from the server. */
|
|
17
|
+
readonly refetch: () => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Data hook that fetches a single PlatformClient by ID.
|
|
22
|
+
*
|
|
23
|
+
* Pass `null` to skip fetching (stable no-op). When the `id` changes,
|
|
24
|
+
* the previous in-flight request is discarded and a fresh fetch begins.
|
|
25
|
+
*
|
|
26
|
+
* Returns the full proto {@link PlatformClient} resource so consumers
|
|
27
|
+
* have access to metadata, spec (client ID, expiry, JIT config), and
|
|
28
|
+
* status without additional calls.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* function PlatformClientDetail({ pcId }: { pcId: string }) {
|
|
33
|
+
* const { platformClient, isLoading, error } = usePlatformClient(pcId);
|
|
34
|
+
*
|
|
35
|
+
* if (isLoading) return <Skeleton />;
|
|
36
|
+
* if (error) return <ErrorMessage error={error} />;
|
|
37
|
+
* if (!platformClient) return <NotFound />;
|
|
38
|
+
*
|
|
39
|
+
* return <h1>{platformClient.metadata?.name}</h1>;
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function usePlatformClient(
|
|
44
|
+
id: string | null,
|
|
45
|
+
): UsePlatformClientReturn {
|
|
46
|
+
const stigmer = useStigmer();
|
|
47
|
+
const [platformClient, setPlatformClient] =
|
|
48
|
+
useState<PlatformClient | null>(null);
|
|
49
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
50
|
+
const [error, setError] = useState<Error | null>(null);
|
|
51
|
+
const [fetchKey, setFetchKey] = useState(0);
|
|
52
|
+
|
|
53
|
+
const refetch = useCallback(() => setFetchKey((k) => k + 1), []);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!id) {
|
|
57
|
+
setPlatformClient(null);
|
|
58
|
+
setIsLoading(false);
|
|
59
|
+
setError(null);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const cancelled = { current: false };
|
|
64
|
+
setIsLoading(true);
|
|
65
|
+
setError(null);
|
|
66
|
+
|
|
67
|
+
stigmer.platformclient.get(id).then(
|
|
68
|
+
(result) => {
|
|
69
|
+
if (cancelled.current) return;
|
|
70
|
+
setPlatformClient(result);
|
|
71
|
+
setIsLoading(false);
|
|
72
|
+
},
|
|
73
|
+
(err) => {
|
|
74
|
+
if (cancelled.current) return;
|
|
75
|
+
setError(toError(err));
|
|
76
|
+
setIsLoading(false);
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return () => {
|
|
81
|
+
cancelled.current = true;
|
|
82
|
+
};
|
|
83
|
+
}, [id, stigmer, fetchKey]);
|
|
84
|
+
|
|
85
|
+
return { platformClient, isLoading, error, refetch };
|
|
86
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { create } from "@bufbuild/protobuf";
|
|
5
|
+
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
6
|
+
import { ListPlatformClientsByOrgInputSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/io_pb";
|
|
7
|
+
import { useStigmer } from "../hooks";
|
|
8
|
+
import { toError } from "../internal/toError";
|
|
9
|
+
|
|
10
|
+
/** Return value of {@link usePlatformClientList}. */
|
|
11
|
+
export interface UsePlatformClientListReturn {
|
|
12
|
+
/** All platform clients for the organization. Empty while loading or on error. */
|
|
13
|
+
readonly platformClients: readonly PlatformClient[];
|
|
14
|
+
/** `true` while the initial fetch or a refetch is in flight. */
|
|
15
|
+
readonly isLoading: boolean;
|
|
16
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
17
|
+
readonly error: Error | null;
|
|
18
|
+
/** Discard cached data and re-fetch from the server. */
|
|
19
|
+
readonly refetch: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Data hook that fetches all platform clients for an organization.
|
|
24
|
+
*
|
|
25
|
+
* Platform clients are admin-level resources with small cardinality
|
|
26
|
+
* (typically 1–5 per org), so results are returned as a flat list
|
|
27
|
+
* without pagination.
|
|
28
|
+
*
|
|
29
|
+
* Pass `null` to skip fetching (stable no-op). Call `refetch()` to
|
|
30
|
+
* re-query after mutations (create / update / delete / rotateSecret).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function PlatformClientSettings({ org }: { org: string }) {
|
|
35
|
+
* const { platformClients, isLoading, error } = usePlatformClientList(org);
|
|
36
|
+
*
|
|
37
|
+
* if (isLoading) return <Skeleton />;
|
|
38
|
+
* if (error) return <ErrorMessage error={error} />;
|
|
39
|
+
*
|
|
40
|
+
* return (
|
|
41
|
+
* <ul>
|
|
42
|
+
* {platformClients.map((pc) => (
|
|
43
|
+
* <li key={pc.metadata?.id}>{pc.metadata?.name}</li>
|
|
44
|
+
* ))}
|
|
45
|
+
* </ul>
|
|
46
|
+
* );
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export function usePlatformClientList(
|
|
51
|
+
org: string | null,
|
|
52
|
+
): UsePlatformClientListReturn {
|
|
53
|
+
const stigmer = useStigmer();
|
|
54
|
+
const [platformClients, setPlatformClients] = useState<PlatformClient[]>([]);
|
|
55
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
56
|
+
const [error, setError] = useState<Error | null>(null);
|
|
57
|
+
const [fetchKey, setFetchKey] = useState(0);
|
|
58
|
+
|
|
59
|
+
const refetch = useCallback(() => setFetchKey((k) => k + 1), []);
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (!org) {
|
|
63
|
+
setPlatformClients([]);
|
|
64
|
+
setIsLoading(false);
|
|
65
|
+
setError(null);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const cancelled = { current: false };
|
|
70
|
+
setIsLoading(true);
|
|
71
|
+
setError(null);
|
|
72
|
+
|
|
73
|
+
stigmer.platformclient
|
|
74
|
+
.listByOrg(
|
|
75
|
+
create(ListPlatformClientsByOrgInputSchema, { org }),
|
|
76
|
+
)
|
|
77
|
+
.then(
|
|
78
|
+
(result) => {
|
|
79
|
+
if (cancelled.current) return;
|
|
80
|
+
setPlatformClients([...result.entries]);
|
|
81
|
+
setIsLoading(false);
|
|
82
|
+
},
|
|
83
|
+
(err) => {
|
|
84
|
+
if (cancelled.current) return;
|
|
85
|
+
setError(toError(err));
|
|
86
|
+
setIsLoading(false);
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return () => {
|
|
91
|
+
cancelled.current = true;
|
|
92
|
+
};
|
|
93
|
+
}, [org, stigmer, fetchKey]);
|
|
94
|
+
|
|
95
|
+
return { platformClients, isLoading, error, refetch };
|
|
96
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { PlatformClientCreateResponse } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/io_pb";
|
|
5
|
+
import { useStigmer } from "../hooks";
|
|
6
|
+
import { toError } from "../internal/toError";
|
|
7
|
+
|
|
8
|
+
/** Return value of {@link useRotatePlatformClientSecret}. */
|
|
9
|
+
export interface UseRotatePlatformClientSecretReturn {
|
|
10
|
+
/**
|
|
11
|
+
* Rotate the client secret for a platform client by its resource ID.
|
|
12
|
+
* Resolves with a {@link PlatformClientCreateResponse} containing the
|
|
13
|
+
* updated resource and the **one-time new raw client secret**.
|
|
14
|
+
*/
|
|
15
|
+
readonly rotateSecret: (
|
|
16
|
+
id: string,
|
|
17
|
+
) => Promise<PlatformClientCreateResponse>;
|
|
18
|
+
/** `true` while the rotation request is in flight. */
|
|
19
|
+
readonly isRotating: boolean;
|
|
20
|
+
/** Error from the last failed rotation, or `null` when healthy. */
|
|
21
|
+
readonly error: Error | null;
|
|
22
|
+
/** Reset `error` to `null`. */
|
|
23
|
+
readonly clearError: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Mutation hook that wraps `platformclient.rotateSecret()` with
|
|
28
|
+
* loading and error state.
|
|
29
|
+
*
|
|
30
|
+
* Generates a new client secret, invalidating the previous one.
|
|
31
|
+
* The response includes a **one-time raw client secret** — it must
|
|
32
|
+
* be shown to the user immediately as the server never returns it
|
|
33
|
+
* again.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* const { rotateSecret, isRotating, error } = useRotatePlatformClientSecret();
|
|
38
|
+
*
|
|
39
|
+
* const response = await rotateSecret("pc-abc123");
|
|
40
|
+
* // response.clientSecret is the new one-time raw secret
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function useRotatePlatformClientSecret(): UseRotatePlatformClientSecretReturn {
|
|
44
|
+
const stigmer = useStigmer();
|
|
45
|
+
const [isRotating, setIsRotating] = useState(false);
|
|
46
|
+
const [error, setError] = useState<Error | null>(null);
|
|
47
|
+
|
|
48
|
+
const clearError = useCallback(() => setError(null), []);
|
|
49
|
+
|
|
50
|
+
const rotateSecret = useCallback(
|
|
51
|
+
async (id: string): Promise<PlatformClientCreateResponse> => {
|
|
52
|
+
setIsRotating(true);
|
|
53
|
+
setError(null);
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
return await stigmer.platformclient.rotateSecret(id);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
setError(toError(err));
|
|
59
|
+
throw err;
|
|
60
|
+
} finally {
|
|
61
|
+
setIsRotating(false);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
[stigmer],
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return { rotateSecret, isRotating, error, clearError };
|
|
68
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { PlatformClientInput } from "@stigmer/sdk";
|
|
5
|
+
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
6
|
+
import { useStigmer } from "../hooks";
|
|
7
|
+
import { toError } from "../internal/toError";
|
|
8
|
+
|
|
9
|
+
/** Return value of {@link useUpdatePlatformClient}. */
|
|
10
|
+
export interface UseUpdatePlatformClientReturn {
|
|
11
|
+
/** Submit a {@link PlatformClientInput} to update an existing platform client. Resolves with the updated resource. */
|
|
12
|
+
readonly update: (input: PlatformClientInput) => Promise<PlatformClient>;
|
|
13
|
+
/** `true` while the update request is in flight. */
|
|
14
|
+
readonly isUpdating: boolean;
|
|
15
|
+
/** Error from the last failed update, or `null` when healthy. */
|
|
16
|
+
readonly error: Error | null;
|
|
17
|
+
/** Reset `error` to `null`. */
|
|
18
|
+
readonly clearError: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Mutation hook that wraps `platformclient.update()` with loading
|
|
23
|
+
* and error state.
|
|
24
|
+
*
|
|
25
|
+
* Updates an existing platform client. The input must include the
|
|
26
|
+
* `slug` field to identify the target resource, along with the
|
|
27
|
+
* updated spec fields. Credential fields (`clientId`,
|
|
28
|
+
* `clientSecretHash`, `secretFingerprint`) are computed and
|
|
29
|
+
* preserved by the backend — do not set them in the input.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { update, isUpdating, error } = useUpdatePlatformClient();
|
|
34
|
+
*
|
|
35
|
+
* await update({
|
|
36
|
+
* name: "my-saas-backend",
|
|
37
|
+
* slug: "my-saas-backend",
|
|
38
|
+
* org: "acme",
|
|
39
|
+
* autoProvisionAccounts: true,
|
|
40
|
+
* autoGrantOnOrg: true,
|
|
41
|
+
* });
|
|
42
|
+
* refetch(); // refresh detail view
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function useUpdatePlatformClient(): UseUpdatePlatformClientReturn {
|
|
46
|
+
const stigmer = useStigmer();
|
|
47
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
48
|
+
const [error, setError] = useState<Error | null>(null);
|
|
49
|
+
|
|
50
|
+
const clearError = useCallback(() => setError(null), []);
|
|
51
|
+
|
|
52
|
+
const update = useCallback(
|
|
53
|
+
async (input: PlatformClientInput): Promise<PlatformClient> => {
|
|
54
|
+
setIsUpdating(true);
|
|
55
|
+
setError(null);
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
return await stigmer.platformclient.update(input);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
setError(toError(err));
|
|
61
|
+
throw err;
|
|
62
|
+
} finally {
|
|
63
|
+
setIsUpdating(false);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
[stigmer],
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return { update, isUpdating, error, clearError };
|
|
70
|
+
}
|
|
@@ -171,7 +171,7 @@ export interface SearchResultOverrides {
|
|
|
171
171
|
*
|
|
172
172
|
* @example
|
|
173
173
|
* ```ts
|
|
174
|
-
* import { samples
|
|
174
|
+
* import { samples } from "@stigmer/react/test";
|
|
175
175
|
*
|
|
176
176
|
* const scenario = buildScenario(
|
|
177
177
|
* fixtures.session.get(() => samples.session({ subject: "My topic" })),
|