@stapel/workspaces-react 0.6.0 → 0.7.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/CHANGELOG.md +14 -0
- package/dist/api/generated/schema.d.ts +384 -4
- package/dist/api/generated/schema.d.ts.map +1 -1
- package/dist/api/types.d.ts +20 -5
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/workspacesApi.d.ts +23 -1
- package/dist/api/workspacesApi.d.ts.map +1 -1
- package/dist/api/workspacesApi.js +4 -0
- package/dist/api/workspacesApi.js.map +1 -1
- package/dist/default/InviteAcceptPage.d.ts +28 -0
- package/dist/default/InviteAcceptPage.d.ts.map +1 -0
- package/dist/default/InviteAcceptPage.js +141 -0
- package/dist/default/InviteAcceptPage.js.map +1 -0
- package/dist/default/MembersManager.d.ts +4 -4
- package/dist/default/MembersManager.d.ts.map +1 -1
- package/dist/default/MembersManager.js +61 -56
- package/dist/default/MembersManager.js.map +1 -1
- package/dist/default/index.d.ts +2 -0
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js +1 -0
- package/dist/default/index.js.map +1 -1
- package/dist/flows/inviteAcceptFlow.d.ts +155 -0
- package/dist/flows/inviteAcceptFlow.d.ts.map +1 -0
- package/dist/flows/inviteAcceptFlow.js +126 -0
- package/dist/flows/inviteAcceptFlow.js.map +1 -0
- package/dist/headless/Can.d.ts +40 -0
- package/dist/headless/Can.d.ts.map +1 -0
- package/dist/headless/Can.js +30 -0
- package/dist/headless/Can.js.map +1 -0
- package/dist/headless/InviteAcceptFlow.d.ts +44 -0
- package/dist/headless/InviteAcceptFlow.d.ts.map +1 -0
- package/dist/headless/InviteAcceptFlow.js +67 -0
- package/dist/headless/InviteAcceptFlow.js.map +1 -0
- package/dist/headless/RoleSelect.d.ts +41 -0
- package/dist/headless/RoleSelect.d.ts.map +1 -0
- package/dist/headless/RoleSelect.js +34 -0
- package/dist/headless/RoleSelect.js.map +1 -0
- package/dist/i18n/generated/errors.gen.d.ts +48 -0
- package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
- package/dist/i18n/generated/errors.gen.js +24 -0
- package/dist/i18n/generated/errors.gen.js.map +1 -1
- package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -1
- package/dist/i18n/generated/errors.ru.gen.js +8 -0
- package/dist/i18n/generated/errors.ru.gen.js.map +1 -1
- package/dist/i18n/keys.d.ts +28 -0
- package/dist/i18n/keys.d.ts.map +1 -1
- package/dist/i18n/keys.js +64 -0
- package/dist/i18n/keys.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +30 -0
- package/dist/i18n/ru.js.map +1 -1
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/model/capabilities.d.ts +21 -0
- package/dist/model/capabilities.d.ts.map +1 -0
- package/dist/model/capabilities.js +32 -0
- package/dist/model/capabilities.js.map +1 -0
- package/dist/model/emailMask.d.ts +22 -0
- package/dist/model/emailMask.d.ts.map +1 -0
- package/dist/model/emailMask.js +36 -0
- package/dist/model/emailMask.js.map +1 -0
- package/dist/model/mutations.d.ts +23 -3
- package/dist/model/mutations.d.ts.map +1 -1
- package/dist/model/mutations.js +39 -1
- package/dist/model/mutations.js.map +1 -1
- package/dist/model/queries.d.ts +37 -1
- package/dist/model/queries.d.ts.map +1 -1
- package/dist/model/queries.js +49 -0
- package/dist/model/queries.js.map +1 -1
- package/dist/model/queryKeys.d.ts +2 -0
- package/dist/model/queryKeys.d.ts.map +1 -1
- package/dist/model/queryKeys.js +6 -0
- package/dist/model/queryKeys.js.map +1 -1
- package/llms.txt +40 -15
- package/manifest.json +225 -3
- package/package.json +4 -4
- package/src/analytics/generated/events.json +1 -1
- package/src/api/generated/schema.ts +384 -4
- package/src/api/types.ts +20 -5
- package/src/api/workspacesApi.ts +50 -0
- package/src/default/InviteAcceptPage.tsx +373 -0
- package/src/default/MembersManager.tsx +155 -145
- package/src/default/index.ts +2 -0
- package/src/flows/inviteAcceptFlow.ts +289 -0
- package/src/headless/Can.tsx +49 -0
- package/src/headless/InviteAcceptFlow.tsx +105 -0
- package/src/headless/RoleSelect.tsx +58 -0
- package/src/i18n/generated/errors.gen.ts +24 -0
- package/src/i18n/generated/errors.json +62 -0
- package/src/i18n/generated/errors.ru.gen.ts +8 -0
- package/src/i18n/keys.ts +68 -0
- package/src/i18n/ru.ts +34 -0
- package/src/index.ts +26 -0
- package/src/model/capabilities.ts +37 -0
- package/src/model/emailMask.ts +37 -0
- package/src/model/mutations.ts +56 -4
- package/src/model/queries.ts +73 -0
- package/src/model/queryKeys.ts +10 -0
package/dist/model/mutations.js
CHANGED
|
@@ -127,10 +127,48 @@ export function useAcceptInvitation() {
|
|
|
127
127
|
const queryClient = useQueryClient();
|
|
128
128
|
const options = {
|
|
129
129
|
mutationFn: (body) => api.acceptInvitation(body),
|
|
130
|
-
onSuccess: () => {
|
|
130
|
+
onSuccess: (_member, body) => {
|
|
131
131
|
void queryClient.invalidateQueries({
|
|
132
132
|
queryKey: workspacesQueryKeys.list(),
|
|
133
133
|
});
|
|
134
|
+
// The preview's `status` moved pending → accepted.
|
|
135
|
+
void queryClient.invalidateQueries({
|
|
136
|
+
queryKey: workspacesQueryKeys.invitationPreview(body.token),
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
return useMutation(options);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Mint a login grant for a NOT-yet-registered invitee (POST
|
|
144
|
+
* /invitations/{token}/claim, AllowAny — org-program §B2/§B3). The variable
|
|
145
|
+
* is the invite token; the result carries the single-use `grant_token` to
|
|
146
|
+
* exchange at AUTH's `POST /grant/exchange/` (the auth-react api — this pair
|
|
147
|
+
* deliberately does not call it; see `InviteAcceptFlow`'s `onLoginGrant`
|
|
148
|
+
* seam). 409 `email_already_registered` → switch to login. The invitation is
|
|
149
|
+
* NOT consumed here. The grant token is a credential: never log it.
|
|
150
|
+
*/
|
|
151
|
+
export function useClaimInvitation() {
|
|
152
|
+
const api = useWorkspacesApi();
|
|
153
|
+
const options = {
|
|
154
|
+
mutationFn: (token) => api.claimInvitation(token),
|
|
155
|
+
};
|
|
156
|
+
return useMutation(options);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Decline an invitation (POST /invitations/{token}/decline, authenticated +
|
|
160
|
+
* email-match — org-program §B2). The variable is the invite token. Decline ≠
|
|
161
|
+
* revoke — the preview's `status` becomes `declined`.
|
|
162
|
+
*/
|
|
163
|
+
export function useDeclineInvitation() {
|
|
164
|
+
const api = useWorkspacesApi();
|
|
165
|
+
const queryClient = useQueryClient();
|
|
166
|
+
const options = {
|
|
167
|
+
mutationFn: (token) => api.declineInvitation(token),
|
|
168
|
+
onSuccess: (_result, token) => {
|
|
169
|
+
void queryClient.invalidateQueries({
|
|
170
|
+
queryKey: workspacesQueryKeys.invitationPreview(token),
|
|
171
|
+
});
|
|
134
172
|
},
|
|
135
173
|
};
|
|
136
174
|
return useMutation(options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutations.js","sourceRoot":"","sources":["../../src/model/mutations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;;;;;;;GAWG;AAEH,wEAAwE;AACxE,MAAM,UAAU,kBAAkB;IAKhC,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,OAAO,GACX;QACE,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;QAC/C,SAAS,EAAE,GAAG,EAAE;YACd,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,mBAAmB,CAAC,IAAI,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IACJ,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,WAAmB;IAEnB,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,OAAO,GACX;QACE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC;QAC9D,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACrB,WAAW,CAAC,YAAY,CACtB,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,EACvC,OAAO,CACR,CAAC;YACF,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,mBAAmB,CAAC,IAAI,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IACJ,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,kBAAkB;IAKhC,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,OAAO,GAAqD;QAChE,UAAU,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC;QAC7D,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE;YAClC,WAAW,CAAC,aAAa,CAAC;gBACxB,QAAQ,EAAE,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC;aAClD,CAAC,CAAC;YACH,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,mBAAmB,CAAC,IAAI,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IACF,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB;IAEnB,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,OAAO,GAIT;QACF,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC;QAC1D,SAAS,EAAE,GAAG,EAAE;YACd,KAAK,WAAW,CAAC,iBAAiB,CAAC;gBACjC,QAAQ,EAAE,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC;aACnD,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IACF,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC;
|
|
1
|
+
{"version":3,"file":"mutations.js","sourceRoot":"","sources":["../../src/model/mutations.ts"],"names":[],"mappings":"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"}
|
package/dist/model/queries.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UseQueryResult } from "@tanstack/react-query";
|
|
2
2
|
import type { StapelApiError } from "@stapel/core";
|
|
3
|
-
import type { MemberPage, MembersParams, Workspace, WorkspaceList } from "../api/types.js";
|
|
3
|
+
import type { InvitationPreview, MemberPage, MembersParams, RoleInfo, Workspace, WorkspaceList } from "../api/types.js";
|
|
4
4
|
/**
|
|
5
5
|
* Read hooks over the workspaces API. Staleness follows core's query defaults;
|
|
6
6
|
* override per call site via a page that needs fresher data. Keys are
|
|
@@ -34,4 +34,40 @@ export declare function useWorkspace(workspaceId: string | null): UseQueryResult
|
|
|
34
34
|
* to a specific page or filter; omit for the newest page (default limit 100).
|
|
35
35
|
*/
|
|
36
36
|
export declare function useMembers(workspaceId: string | null, params?: MembersParams): UseQueryResult<MemberPage, StapelApiError>;
|
|
37
|
+
/**
|
|
38
|
+
* The effective role registry (GET /roles, org-program §A2): builtin four +
|
|
39
|
+
* the deployment's `STAPEL_WORKSPACES["ROLES"]` overlay, capability strings
|
|
40
|
+
* verbatim, rank-descending. Deployment-static data — role UI (RoleSelect)
|
|
41
|
+
* reads this instead of hardcoding the builtin four. Session-ready-gated like
|
|
42
|
+
* {@link useWorkspaces} (IsAuthenticated endpoint, mounts at screen top).
|
|
43
|
+
*/
|
|
44
|
+
export declare function useRoles(): UseQueryResult<readonly RoleInfo[], StapelApiError>;
|
|
45
|
+
/**
|
|
46
|
+
* Public invitation preview (GET /invitations/{token}, AllowAny — org-program
|
|
47
|
+
* §B2): what the `/invite/{token}` page renders BEFORE any auth decision.
|
|
48
|
+
* Deliberately NOT session-gated — the whole point is that the invitee may
|
|
49
|
+
* have no session at all; the token in the URL is the bearer secret.
|
|
50
|
+
*/
|
|
51
|
+
export declare function useInvitationPreview(token: string | null): UseQueryResult<InvitationPreview, StapelApiError>;
|
|
52
|
+
/** What {@link useCapabilities} returns: the caller's granted capability
|
|
53
|
+
* strings in one workspace plus the wildcard-aware `can()` check. */
|
|
54
|
+
export interface CapabilitiesResult {
|
|
55
|
+
/** Verbatim registry strings of the caller's role (wildcards included);
|
|
56
|
+
* empty while loading or when the caller is not a member. */
|
|
57
|
+
readonly capabilities: readonly string[];
|
|
58
|
+
/** Wildcard-aware check (`*` / `prefix.*` — the backend matcher, ported).
|
|
59
|
+
* UI convenience only: the backend re-checks on every operation. */
|
|
60
|
+
can(capability: string): boolean;
|
|
61
|
+
readonly isLoading: boolean;
|
|
62
|
+
readonly isError: boolean;
|
|
63
|
+
readonly error: StapelApiError | null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The caller's capabilities in one workspace (org-program §A2): reads
|
|
67
|
+
* `my_capabilities` off the workspace detail (`WorkspaceResponse`, additive
|
|
68
|
+
* field since stapel-workspaces 0.6.0) and exposes the ported wildcard
|
|
69
|
+
* matcher. Deny-by-default: `can()` is false while loading, on error, or when
|
|
70
|
+
* the backend predates the field.
|
|
71
|
+
*/
|
|
72
|
+
export declare function useCapabilities(workspaceId: string | null): CapabilitiesResult;
|
|
37
73
|
//# sourceMappingURL=queries.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACd,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,QAAQ,EACR,SAAS,EACT,aAAa,EACd,MAAM,iBAAiB,CAAC;AAKzB;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,cAAc,CAAC,aAAa,EAAE,cAAc,CAAC,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,CAQ3C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,CAAC,EAAE,aAAa,GACrB,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAS5C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,cAAc,CACxC,SAAS,QAAQ,EAAE,EACnB,cAAc,CACf,CAQA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAOnD;AAED;qEACqE;AACrE,MAAM,WAAW,kBAAkB;IACjC;iEAC6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;wEACoE;IACpE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,kBAAkB,CAU9E"}
|
package/dist/model/queries.js
CHANGED
|
@@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
2
2
|
import { useActiveSessionReady } from "@stapel/core";
|
|
3
3
|
import { useWorkspacesApi } from "./context.js";
|
|
4
4
|
import { workspacesQueryKeys } from "./queryKeys.js";
|
|
5
|
+
import { hasCapability } from "./capabilities.js";
|
|
5
6
|
/**
|
|
6
7
|
* Read hooks over the workspaces API. Staleness follows core's query defaults;
|
|
7
8
|
* override per call site via a page that needs fresher data. Keys are
|
|
@@ -60,4 +61,52 @@ export function useMembers(workspaceId, params) {
|
|
|
60
61
|
enabled: sessionReady && workspaceId !== null && workspaceId !== "",
|
|
61
62
|
});
|
|
62
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* The effective role registry (GET /roles, org-program §A2): builtin four +
|
|
66
|
+
* the deployment's `STAPEL_WORKSPACES["ROLES"]` overlay, capability strings
|
|
67
|
+
* verbatim, rank-descending. Deployment-static data — role UI (RoleSelect)
|
|
68
|
+
* reads this instead of hardcoding the builtin four. Session-ready-gated like
|
|
69
|
+
* {@link useWorkspaces} (IsAuthenticated endpoint, mounts at screen top).
|
|
70
|
+
*/
|
|
71
|
+
export function useRoles() {
|
|
72
|
+
const api = useWorkspacesApi();
|
|
73
|
+
const sessionReady = useActiveSessionReady();
|
|
74
|
+
return useQuery({
|
|
75
|
+
queryKey: workspacesQueryKeys.roles(),
|
|
76
|
+
queryFn: async () => (await api.listRoles()).roles ?? [],
|
|
77
|
+
enabled: sessionReady,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Public invitation preview (GET /invitations/{token}, AllowAny — org-program
|
|
82
|
+
* §B2): what the `/invite/{token}` page renders BEFORE any auth decision.
|
|
83
|
+
* Deliberately NOT session-gated — the whole point is that the invitee may
|
|
84
|
+
* have no session at all; the token in the URL is the bearer secret.
|
|
85
|
+
*/
|
|
86
|
+
export function useInvitationPreview(token) {
|
|
87
|
+
const api = useWorkspacesApi();
|
|
88
|
+
return useQuery({
|
|
89
|
+
queryKey: workspacesQueryKeys.invitationPreview(token ?? ""),
|
|
90
|
+
queryFn: () => api.getInvitationPreview(token),
|
|
91
|
+
enabled: token !== null && token !== "",
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The caller's capabilities in one workspace (org-program §A2): reads
|
|
96
|
+
* `my_capabilities` off the workspace detail (`WorkspaceResponse`, additive
|
|
97
|
+
* field since stapel-workspaces 0.6.0) and exposes the ported wildcard
|
|
98
|
+
* matcher. Deny-by-default: `can()` is false while loading, on error, or when
|
|
99
|
+
* the backend predates the field.
|
|
100
|
+
*/
|
|
101
|
+
export function useCapabilities(workspaceId) {
|
|
102
|
+
const query = useWorkspace(workspaceId);
|
|
103
|
+
const capabilities = query.data?.my_capabilities ?? [];
|
|
104
|
+
return {
|
|
105
|
+
capabilities,
|
|
106
|
+
can: (capability) => hasCapability(capabilities, capability),
|
|
107
|
+
isLoading: query.isLoading,
|
|
108
|
+
isError: query.isError,
|
|
109
|
+
error: query.error ?? null,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
63
112
|
//# sourceMappingURL=queries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,5 +5,7 @@ export declare const workspacesQueryKeys: {
|
|
|
5
5
|
detail(workspaceId: string): readonly ["workspaces", "detail", string];
|
|
6
6
|
members(workspaceId: string): readonly ["workspaces", "members", string];
|
|
7
7
|
membersPage(workspaceId: string, params: MembersParams): readonly ["workspaces", "members", string, MembersParams];
|
|
8
|
+
roles(): readonly ["workspaces", "roles"];
|
|
9
|
+
invitationPreview(token: string): readonly ["workspaces", "invitation-preview", string];
|
|
8
10
|
};
|
|
9
11
|
//# sourceMappingURL=queryKeys.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryKeys.d.ts","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWrD,eAAO,MAAM,mBAAmB,EAAE;IAChC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,IAAI,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACzE,WAAW,CACT,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,aAAa,GACpB,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"queryKeys.d.ts","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWrD,eAAO,MAAM,mBAAmB,EAAE;IAChC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,IAAI,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACzE,WAAW,CACT,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,aAAa,GACpB,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7D,KAAK,IAAI,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC1C,iBAAiB,CACf,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,YAAY,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;CAe1D,CAAC"}
|
package/dist/model/queryKeys.js
CHANGED
|
@@ -14,5 +14,11 @@ export const workspacesQueryKeys = {
|
|
|
14
14
|
// invalidating `members(workspaceId)` (mutations.ts) drops every page.
|
|
15
15
|
members: (workspaceId) => [ROOT, "members", workspaceId],
|
|
16
16
|
membersPage: (workspaceId, params) => [ROOT, "members", workspaceId, params],
|
|
17
|
+
roles: () => [ROOT, "roles"],
|
|
18
|
+
// NOTE: the key carries the invite TOKEN (a secret). Core's query persist
|
|
19
|
+
// scope is per-user and the preview response is already public-by-design
|
|
20
|
+
// (masked email only) — but hosts logging query keys should treat this one
|
|
21
|
+
// as sensitive.
|
|
22
|
+
invitationPreview: (token) => [ROOT, "invitation-preview", token],
|
|
17
23
|
};
|
|
18
24
|
//# sourceMappingURL=queryKeys.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,IAAI,GAAG,YAAqB,CAAC;AAEnC,MAAM,CAAC,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,IAAI,GAAG,YAAqB,CAAC;AAEnC,MAAM,CAAC,MAAM,mBAAmB,GAa5B;IACF,GAAG,EAAE,CAAC,IAAI,CAAC;IACX,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC;IACtD,kEAAkE;IAClE,uEAAuE;IACvE,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,CAAC;IACxD,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC;IAC5E,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;IAC5B,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,gBAAgB;IAChB,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,CAAC;CAClE,CAAC"}
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# @stapel/workspaces-react 0.
|
|
1
|
+
# @stapel/workspaces-react 0.7.0
|
|
2
2
|
|
|
3
|
-
Headless React flow pair for stapel-workspaces (contract >=0.
|
|
3
|
+
Headless React flow pair for stapel-workspaces (contract >=0.8 <0.9) — business + state, zero visual opinion.
|
|
4
4
|
Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
|
|
5
5
|
verification-403 interception, i18n engine, analytics facade, TanStack Query layer.
|
|
6
6
|
|
|
@@ -16,37 +16,50 @@ verification-403 interception, i18n engine, analytics facade, TanStack Query lay
|
|
|
16
16
|
## Layers
|
|
17
17
|
api (typed client) · model (hooks, session) · flows (machines) · headless · i18n
|
|
18
18
|
|
|
19
|
+
## Machines (createFlowMachine; analytics funnel flow.<id>.<step>)
|
|
20
|
+
- createInviteAcceptFlow
|
|
21
|
+
|
|
19
22
|
## Documented flows (flows.json — canonical id, steps, endpoints)
|
|
20
23
|
|
|
21
24
|
## Operations (typed; use the named op, never a path string)
|
|
22
25
|
Request/response schema names are in manifest.json + the generated types.
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
26
|
+
Paths are relative to `/workspaces/api/v1/`.
|
|
27
|
+
- workspaces_api_v1_create: POST /
|
|
28
|
+
- workspaces_api_v1_destroy: DELETE /{workspace_id}
|
|
29
|
+
- workspaces_api_v1_internal_members_retrieve: GET /internal/{workspace_id}/members/{user_id}
|
|
30
|
+
- workspaces_api_v1_internal_users_personal_create: POST /internal/users/{user_id}/personal
|
|
31
|
+
- workspaces_api_v1_invitations_accept_create: POST /invitations/accept
|
|
32
|
+
- workspaces_api_v1_invitations_claim_create: POST /invitations/{token}/claim
|
|
33
|
+
- workspaces_api_v1_invitations_decline_create: POST /invitations/{token}/decline
|
|
34
|
+
- workspaces_api_v1_invitations_retrieve: GET /invitations/{token}
|
|
35
|
+
- workspaces_api_v1_members_destroy: DELETE /{workspace_id}/members/{user_id}
|
|
36
|
+
- workspaces_api_v1_members_invite_create: POST /{workspace_id}/members/invite
|
|
37
|
+
- workspaces_api_v1_members_list: GET /{workspace_id}/members
|
|
38
|
+
- workspaces_api_v1_members_partial_update: PATCH /{workspace_id}/members/{user_id}
|
|
39
|
+
- workspaces_api_v1_members_provision_create: POST /{workspace_id}/members/provision
|
|
40
|
+
- workspaces_api_v1_partial_update: PATCH /{workspace_id}
|
|
41
|
+
- workspaces_api_v1_retrieve: GET /
|
|
42
|
+
- workspaces_api_v1_retrieve_2: GET /{workspace_id}
|
|
43
|
+
- workspaces_api_v1_roles_retrieve: GET /roles
|
|
35
44
|
|
|
36
45
|
## Query hooks (server state; keys come only from the key factory)
|
|
37
46
|
- useAcceptInvitation (mutation) → acceptInvitation
|
|
47
|
+
- useClaimInvitation (mutation) → claimInvitation
|
|
38
48
|
- useCreateWorkspace (mutation) → createWorkspace
|
|
49
|
+
- useDeclineInvitation (mutation) → declineInvitation
|
|
39
50
|
- useDeleteWorkspace (mutation) → deleteWorkspace
|
|
51
|
+
- useInvitationPreview (query) → getInvitationPreview
|
|
40
52
|
- useInviteMembers (mutation) → inviteMembers
|
|
41
53
|
- useMembers (query) → listMembers
|
|
42
54
|
- useRemoveMember (mutation) → removeMember
|
|
55
|
+
- useRoles (query) → listRoles
|
|
43
56
|
- useUpdateMemberRole (mutation) → updateMemberRole
|
|
44
57
|
- useUpdateWorkspace (mutation) → updateWorkspace
|
|
45
58
|
- useWorkspace (query) → getWorkspace
|
|
46
59
|
- useWorkspaces (query) → listWorkspaces
|
|
47
60
|
|
|
48
61
|
## Errors (render t(code, params); UX from remediation)
|
|
49
|
-
|
|
62
|
+
60 keys (full catalog: manifest.json §errors). By remediation: fix_input 28 · retry 12 · contact_support 7 · wait_and_retry 6 · verify 5 · reauthenticate 2.
|
|
50
63
|
Param-bearing keys (interpolation slots matter):
|
|
51
64
|
- error.400.field.blank [400] → fix_input {field}
|
|
52
65
|
- error.400.field.does_not_exist [400] → fix_input {field}
|
|
@@ -59,6 +72,9 @@ Param-bearing keys (interpolation slots matter):
|
|
|
59
72
|
- error.400.field.null [400] → fix_input {field}
|
|
60
73
|
- error.400.field.required [400] → fix_input {field}
|
|
61
74
|
- error.400.field.unique [400] → fix_input {field}
|
|
75
|
+
- error.402.member_limit_reached [402] → fix_input {limit}
|
|
76
|
+
- error.403.membership_suspended [403] → fix_input {reason}
|
|
77
|
+
- error.403.missing_capability [403] → contact_support {capability}
|
|
62
78
|
- error.429.rate_limit [429] → wait_and_retry {retry_after_minutes}
|
|
63
79
|
|
|
64
80
|
## Analytics events (typed; defineEvent → events.json, drift-gated)
|
|
@@ -82,13 +98,22 @@ const { tracked } = useTracked();
|
|
|
82
98
|
|
|
83
99
|
## Demos (defineDemo → manifest.demos; compiled, linted, rendered examples)
|
|
84
100
|
- workspaces.accept → <AcceptInvitation> [default] demo/AcceptInvitation.demo.tsx
|
|
101
|
+
- workspaces.can → <Can> [default] demo/Can.demo.tsx
|
|
102
|
+
- workspaces.invite-accept → <InviteAcceptFlow> [default] demo/InviteAcceptFlow.demo.tsx
|
|
85
103
|
- workspaces.list → <WorkspaceList> [default] demo/WorkspaceList.demo.tsx
|
|
86
104
|
- workspaces.members → <Members> [default] demo/Members.demo.tsx
|
|
87
105
|
- workspaces.provider → <WorkspacesProvider> [default] demo/Workspaces.demo.tsx
|
|
106
|
+
- workspaces.role-select → <RoleSelect> [default] demo/RoleSelect.demo.tsx
|
|
88
107
|
Each source file is the canonical usage snippet (open the default variant).
|
|
89
108
|
|
|
90
109
|
## Snippets
|
|
91
110
|
```tsx
|
|
111
|
+
// A flow machine drives state; you render each step.
|
|
112
|
+
const flow = createInviteAcceptFlow({ api: useWorkspacesApi() });
|
|
113
|
+
const s = useFlow(flow.machine);
|
|
114
|
+
if (s.step.endsWith('Error')) return <p>{t(s.error.code, s.error.params)}</p>;
|
|
115
|
+
```
|
|
116
|
+
```tsx
|
|
92
117
|
// Error rendering + remediation branch (one pattern for every pair).
|
|
93
118
|
const r = explainWorkspacesError(err.code); // 'wait_and_retry' | 'verify' | ...
|
|
94
119
|
return <Alert action={r}>{t(err.code, err.params)}</Alert>;
|