@stapel/workspaces-react 0.14.0 → 0.15.1

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/api/generated/schema.d.ts +165 -3
  3. package/dist/api/generated/schema.d.ts.map +1 -1
  4. package/dist/api/types.d.ts +22 -0
  5. package/dist/api/types.d.ts.map +1 -1
  6. package/dist/api/workspacesApi.d.ts +5 -1
  7. package/dist/api/workspacesApi.d.ts.map +1 -1
  8. package/dist/api/workspacesApi.js +16 -0
  9. package/dist/api/workspacesApi.js.map +1 -1
  10. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -1
  11. package/dist/i18n/generated/errors.es.gen.js +2 -0
  12. package/dist/i18n/generated/errors.es.gen.js.map +1 -1
  13. package/dist/i18n/generated/errors.gen.d.ts +12 -0
  14. package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
  15. package/dist/i18n/generated/errors.gen.js +6 -0
  16. package/dist/i18n/generated/errors.gen.js.map +1 -1
  17. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -1
  18. package/dist/i18n/generated/errors.ru.gen.js +2 -0
  19. package/dist/i18n/generated/errors.ru.gen.js.map +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/model/mutations.d.ts.map +1 -1
  25. package/dist/model/mutations.js +21 -0
  26. package/dist/model/mutations.js.map +1 -1
  27. package/dist/model/queries.d.ts +33 -1
  28. package/dist/model/queries.d.ts.map +1 -1
  29. package/dist/model/queries.js +44 -0
  30. package/dist/model/queries.js.map +1 -1
  31. package/dist/model/queryKeys.d.ts +3 -1
  32. package/dist/model/queryKeys.d.ts.map +1 -1
  33. package/dist/model/queryKeys.js +6 -0
  34. package/dist/model/queryKeys.js.map +1 -1
  35. package/llms.txt +6 -3
  36. package/manifest.json +53 -2
  37. package/package.json +2 -2
  38. package/src/analytics/generated/events.json +1 -1
  39. package/src/api/generated/schema.ts +165 -3
  40. package/src/api/types.ts +23 -0
  41. package/src/api/workspacesApi.ts +22 -0
  42. package/src/i18n/generated/errors.es.gen.ts +2 -0
  43. package/src/i18n/generated/errors.gen.ts +6 -0
  44. package/src/i18n/generated/errors.json +16 -0
  45. package/src/i18n/generated/errors.ru.gen.ts +2 -0
  46. package/src/index.ts +5 -0
  47. package/src/model/mutations.ts +21 -0
  48. package/src/model/queries.ts +51 -0
  49. package/src/model/queryKeys.ts +16 -1
@@ -12,6 +12,8 @@ import type {
12
12
  InstanceShape,
13
13
  InvitationsParams,
14
14
  MemberPage,
15
+ AuditPage,
16
+ AuditParams,
15
17
  MembersParams,
16
18
  RoleInfo,
17
19
  Workspace,
@@ -90,6 +92,55 @@ export function useMembers(
90
92
  });
91
93
  }
92
94
 
95
+ /**
96
+ * One page of a workspace's membership history (GET /{id}/audit,
97
+ * stapel-workspaces 0.24) — who let this person in, who took them out, when.
98
+ *
99
+ * WHY THE PAIR CARRIES THIS AT ALL. Nothing kept a record before: the comm
100
+ * events this module emits are notifications to other services that nobody
101
+ * stores, and half the transitions emit nothing. Every product that grew an
102
+ * admin screen therefore had the same unanswerable question, and the first one
103
+ * to need it wrote a bespoke fetch through the runtime client — the copy this
104
+ * hook exists to make unnecessary.
105
+ *
106
+ * Gated on `members.view` server-side: every role that may see who is in the
107
+ * room may see how they got there. Disabled until a `workspaceId` is given
108
+ * (and the session is ready — see {@link useWorkspace}).
109
+ *
110
+ * ANCHOR pagination like {@link useMembers}. `action` narrows to one
111
+ * transition, `user_id` to one person's history AS THE SUBJECT — a value the
112
+ * server cannot parse matches nothing rather than being ignored.
113
+ */
114
+ export function useAudit(
115
+ workspaceId: string | null,
116
+ params?: AuditParams
117
+ ): UseQueryResult<AuditPage, StapelApiError> {
118
+ const api = useWorkspacesApi();
119
+ const sessionReady = useActiveSessionReady();
120
+ const p = params ?? {};
121
+ return useQuery({
122
+ queryKey: workspacesQueryKeys.auditPage(workspaceId ?? "", p),
123
+ queryFn: () => api.listAudit(workspaceId as string, p),
124
+ enabled: sessionReady && workspaceId !== null && workspaceId !== "",
125
+ });
126
+ }
127
+
128
+ /**
129
+ * MAY THIS CALLER FOUND A WORKSPACE on this instance — the server's answer
130
+ * (`can_create_workspace`, stapel-workspaces 0.24's `WORKSPACE_CREATE_POLICY`),
131
+ * not a rule re-derived from the deploy shape.
132
+ *
133
+ * Ask this before drawing a "+ New space" control. The same helper answers the
134
+ * gate on `POST /workspaces`, so a drawn button always opens — a client that
135
+ * decided for itself would either draw one that 403s or hide one that should
136
+ * be there. FAILS CLOSED while the list is loading or failed: a hidden action
137
+ * for a second beats an action that refuses.
138
+ */
139
+ export function useCanCreateWorkspace(): boolean {
140
+ const { data } = useWorkspaces();
141
+ return data?.can_create_workspace ?? false;
142
+ }
143
+
93
144
  /**
94
145
  * One page of a workspace's invitations (GET /{id}/invitations, #109) — the
95
146
  * admin's "who has not accepted yet" table. Disabled until a `workspaceId` is
@@ -1,4 +1,8 @@
1
- import type { InvitationsParams, MembersParams } from "../api/types.js";
1
+ import type {
2
+ AuditParams,
3
+ InvitationsParams,
4
+ MembersParams,
5
+ } from "../api/types.js";
2
6
 
3
7
  /**
4
8
  * Namespaced TanStack Query keys (frontend-standard §2 — namespaced keys).
@@ -19,6 +23,11 @@ export const workspacesQueryKeys: {
19
23
  workspaceId: string,
20
24
  params: MembersParams
21
25
  ): readonly ["workspaces", "members", string, MembersParams];
26
+ audit(workspaceId: string): readonly ["workspaces", "audit", string];
27
+ auditPage(
28
+ workspaceId: string,
29
+ params: AuditParams
30
+ ): readonly ["workspaces", "audit", string, AuditParams];
22
31
  invitations(workspaceId: string): readonly ["workspaces", "invitations", string];
23
32
  invitationsPage(
24
33
  workspaceId: string,
@@ -46,6 +55,12 @@ export const workspacesQueryKeys: {
46
55
  // The bare 3-tuple is a valid prefix of membersPage's 4-tuple, so
47
56
  // invalidating `members(workspaceId)` (mutations.ts) drops every page.
48
57
  members: (workspaceId) => [ROOT, "members", workspaceId],
58
+ /** The workspace's membership history (stapel-workspaces 0.24). Its own
59
+ * root, not a slice of `members`: history is append-only and a member
60
+ * mutation invalidates the ROSTER — the history it also appended to is
61
+ * invalidated deliberately, by naming this key, not as a side effect. */
62
+ audit: (workspaceId) => [ROOT, "audit", workspaceId],
63
+ auditPage: (workspaceId, params) => [ROOT, "audit", workspaceId, params],
49
64
  // EVERY workspace's roster, not one. Not a read key — nothing fetches it —
50
65
  // but the invalidation scope of a write that moves a name the whole fleet
51
66
  // shares: `MemberResponse.display_name` is a live lookup in