@burdenoff/microfe-workspaces 2026.531.2 → 2026.531.4

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 (44) hide show
  1. package/dist/WorkspacesRoutes.js +36 -17
  2. package/dist/WorkspacesRoutes.js.map +1 -1
  3. package/dist/components/InviteMemberDialog.js +204 -117
  4. package/dist/components/InviteMemberDialog.js.map +1 -1
  5. package/dist/components/MemberListItem.js +2 -1
  6. package/dist/components/MemberListItem.js.map +1 -1
  7. package/dist/components/ProjectMemberPickerDialog.js +211 -0
  8. package/dist/components/ProjectMemberPickerDialog.js.map +1 -0
  9. package/dist/hooks/index.js +1 -1
  10. package/dist/hooks/useMemberMutations.js +13 -13
  11. package/dist/hooks/useMemberMutations.js.map +1 -1
  12. package/dist/hooks/useProjectMemberMutations.js +104 -0
  13. package/dist/hooks/useProjectMemberMutations.js.map +1 -0
  14. package/dist/hooks/useProjectMembers.js +42 -0
  15. package/dist/hooks/useProjectMembers.js.map +1 -0
  16. package/dist/hooks/useWorkspaceMembers.js +60 -24
  17. package/dist/hooks/useWorkspaceMembers.js.map +1 -1
  18. package/dist/hooks/useWorkspacePermissions.js +4 -0
  19. package/dist/hooks/useWorkspacePermissions.js.map +1 -1
  20. package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
  21. package/dist/index.js +16 -15
  22. package/dist/pages/ActivityListPage.js +5 -5
  23. package/dist/pages/InviteAcceptancePage.js +211 -207
  24. package/dist/pages/InviteAcceptancePage.js.map +1 -1
  25. package/dist/pages/MembersListPage.js +210 -208
  26. package/dist/pages/MembersListPage.js.map +1 -1
  27. package/dist/pages/PendingInvitesPage.js +124 -120
  28. package/dist/pages/PendingInvitesPage.js.map +1 -1
  29. package/dist/pages/ProjectDetailPage.js +249 -213
  30. package/dist/pages/ProjectDetailPage.js.map +1 -1
  31. package/dist/pages/ProjectMembersPage.js +265 -0
  32. package/dist/pages/ProjectMembersPage.js.map +1 -0
  33. package/dist/pages/ProjectsListPage.js +9 -9
  34. package/dist/pages/WorkspaceDetailPage.js +119 -111
  35. package/dist/pages/WorkspaceDetailPage.js.map +1 -1
  36. package/dist/pages/WorkspaceInvitePage.js +790 -0
  37. package/dist/pages/WorkspaceInvitePage.js.map +1 -0
  38. package/dist/pages/WorkspacesListPage.js +115 -100
  39. package/dist/pages/WorkspacesListPage.js.map +1 -1
  40. package/dist/utils/invitationDisplay.js +25 -0
  41. package/dist/utils/invitationDisplay.js.map +1 -0
  42. package/dist/utils/workspaceBulkInviteCsv.js +42 -0
  43. package/dist/utils/workspaceBulkInviteCsv.js.map +1 -0
  44. package/package.json +1 -1
@@ -0,0 +1,42 @@
1
+ import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
2
+ import { useInfiniteQuery as t } from "@tanstack/react-query";
3
+ import { graphqlFetch as n } from "@burdenoff/fe-libs/shared/graphql";
4
+ //#region src/hooks/useProjectMembers.ts
5
+ var r = "\n query GetProjectMembers($projectId: ID!, $pagination: PaginationInput) {\n projectMembers(filter: { projectId: $projectId }, pagination: $pagination) {\n items {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n total\n hasMore\n }\n }\n", i = (i, a, o = 100, s = !0) => {
6
+ let { authToken: c, workspaceId: l } = e(), u = a || l;
7
+ return t({
8
+ queryKey: [
9
+ "projectMembersInfinite",
10
+ u,
11
+ i,
12
+ o
13
+ ],
14
+ initialPageParam: 0,
15
+ queryFn: async ({ pageParam: e }) => {
16
+ let t = await n({
17
+ gateway: "workspace",
18
+ authToken: c || void 0,
19
+ query: r,
20
+ variables: {
21
+ projectId: i,
22
+ pagination: {
23
+ limit: o,
24
+ offset: e
25
+ }
26
+ },
27
+ workspaceId: u || void 0,
28
+ workspaceToken: !0
29
+ });
30
+ if (t.errors?.length) throw Error(t.errors[0]?.message || "GraphQL error");
31
+ if (!t.data?.projectMembers) throw Error("Project members query returned no data");
32
+ return t.data.projectMembers;
33
+ },
34
+ getNextPageParam: (e, t, n) => e.hasMore ? Number(n) + o : void 0,
35
+ enabled: s && !!i && !!u,
36
+ staleTime: 60 * 1e3
37
+ });
38
+ };
39
+ //#endregion
40
+ export { i as useInfiniteProjectMembers };
41
+
42
+ //# sourceMappingURL=useProjectMembers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProjectMembers.js","names":[],"sources":["../../src/hooks/useProjectMembers.ts"],"sourcesContent":["import { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport type { PaginationInput, ProjectMember, ProjectMemberList } from '../types';\n\nconst GET_PROJECT_MEMBERS_QUERY = `\n query GetProjectMembers($projectId: ID!, $pagination: PaginationInput) {\n projectMembers(filter: { projectId: $projectId }, pagination: $pagination) {\n items {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n total\n hasMore\n }\n }\n`;\n\nconst GET_PROJECT_MEMBER_QUERY = `\n query GetProjectMember($id: ID!) {\n projectMember(id: $id) {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n }\n`;\n\nexport const useProjectMembers = (\n projectId: string,\n workspaceIdOverride?: string,\n pagination?: PaginationInput,\n enabled = true\n) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useQuery({\n queryKey: ['projectMembers', effectiveWorkspaceId, projectId, pagination],\n queryFn: async (): Promise<ProjectMemberList> => {\n const result = await graphqlFetch<{ projectMembers: ProjectMemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: GET_PROJECT_MEMBERS_QUERY,\n variables: { projectId, pagination },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.projectMembers) {\n throw new Error('Project members query returned no data');\n }\n\n return result.data.projectMembers;\n },\n enabled: enabled && !!projectId && !!effectiveWorkspaceId,\n staleTime: 60 * 1000,\n });\n};\n\nexport const useInfiniteProjectMembers = (\n projectId: string,\n workspaceIdOverride?: string,\n pageSize = 100,\n enabled = true\n) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useInfiniteQuery({\n queryKey: ['projectMembersInfinite', effectiveWorkspaceId, projectId, pageSize],\n initialPageParam: 0,\n queryFn: async ({ pageParam }): Promise<ProjectMemberList> => {\n const result = await graphqlFetch<{ projectMembers: ProjectMemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: GET_PROJECT_MEMBERS_QUERY,\n variables: {\n projectId,\n pagination: {\n limit: pageSize,\n offset: pageParam,\n },\n },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.projectMembers) {\n throw new Error('Project members query returned no data');\n }\n\n return result.data.projectMembers;\n },\n getNextPageParam: (lastPage, _pages, lastPageParam) =>\n lastPage.hasMore ? Number(lastPageParam) + pageSize : undefined,\n enabled: enabled && !!projectId && !!effectiveWorkspaceId,\n staleTime: 60 * 1000,\n });\n};\n\nexport const useProjectMember = (id: string, workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useQuery({\n queryKey: ['projectMember', effectiveWorkspaceId, id],\n queryFn: async (): Promise<ProjectMember> => {\n const result = await graphqlFetch<{ projectMember: ProjectMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: GET_PROJECT_MEMBER_QUERY,\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.projectMember) {\n throw new Error('Project member query returned no data');\n }\n\n return result.data.projectMember;\n },\n enabled: !!id && !!effectiveWorkspaceId,\n staleTime: 60 * 1000,\n });\n};\n"],"mappings":";;;;AAKA,IAAM,IAA4B,4UAkErB,KACX,GACA,GACA,IAAW,KACX,IAAU,OACP;CACH,IAAM,EAAE,cAAW,mBAAgB,GAAsB,EACnD,IAAuB,KAAuB;AAEpD,QAAO,EAAiB;EACtB,UAAU;GAAC;GAA0B;GAAsB;GAAW;GAAS;EAC/E,kBAAkB;EAClB,SAAS,OAAO,EAAE,mBAA4C;GAC5D,IAAM,IAAS,MAAM,EAAoD;IACvE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO;IACP,WAAW;KACT;KACA,YAAY;MACV,OAAO;MACP,QAAQ;MACT;KACF;IACD,aAAa,KAAwB,KAAA;IACrC,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,OAAI,CAAC,EAAO,MAAM,eAChB,OAAU,MAAM,yCAAyC;AAG3D,UAAO,EAAO,KAAK;;EAErB,mBAAmB,GAAU,GAAQ,MACnC,EAAS,UAAU,OAAO,EAAc,GAAG,IAAW,KAAA;EACxD,SAAS,KAAW,CAAC,CAAC,KAAa,CAAC,CAAC;EACrC,WAAW,KAAK;EACjB,CAAC"}
@@ -1,22 +1,22 @@
1
1
  import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
2
2
  import { GetInvitationDocument as t, GetUserWorkspacesDocument as n, GetWorkspaceInvitationsDocument as r, GetWorkspaceMemberDocument as i, GetWorkspaceMembersDocument as a } from "../generated/wspace-operations.js";
3
- import { useQuery as o } from "@tanstack/react-query";
4
- import { print as s } from "graphql";
5
- import { graphqlFetch as c } from "@burdenoff/fe-libs/shared/graphql";
3
+ import { useInfiniteQuery as o, useQuery as s } from "@tanstack/react-query";
4
+ import { print as c } from "graphql";
5
+ import { graphqlFetch as l } from "@burdenoff/fe-libs/shared/graphql";
6
6
  //#region src/hooks/useWorkspaceMembers.ts
7
- var l = (t, n) => {
7
+ var u = (t, n) => {
8
8
  let { authToken: r } = e();
9
- return o({
9
+ return s({
10
10
  queryKey: [
11
11
  "workspaceMembers",
12
12
  t,
13
13
  n
14
14
  ],
15
15
  queryFn: async () => {
16
- let e = await c({
16
+ let e = await l({
17
17
  gateway: "workspace",
18
18
  authToken: r || void 0,
19
- query: s(a),
19
+ query: c(a),
20
20
  variables: {
21
21
  workspaceId: t,
22
22
  pagination: n
@@ -25,47 +25,81 @@ var l = (t, n) => {
25
25
  workspaceToken: !0
26
26
  });
27
27
  if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
28
+ if (!e.data?.workspaceMembers) throw Error("Workspace members query returned no data");
28
29
  return e.data.workspaceMembers;
29
30
  },
30
31
  enabled: !!t,
31
32
  staleTime: 300 * 1e3
32
33
  });
33
- }, u = (t) => {
34
- let { authToken: n, workspaceId: r } = e();
34
+ }, d = (t, n = 100, r = !0) => {
35
+ let { authToken: i } = e();
35
36
  return o({
37
+ queryKey: [
38
+ "workspaceMembersInfinite",
39
+ t,
40
+ n
41
+ ],
42
+ initialPageParam: 0,
43
+ queryFn: async ({ pageParam: e }) => {
44
+ let r = await l({
45
+ gateway: "workspace",
46
+ authToken: i || void 0,
47
+ query: c(a),
48
+ variables: {
49
+ workspaceId: t,
50
+ pagination: {
51
+ limit: n,
52
+ offset: e
53
+ }
54
+ },
55
+ workspaceId: t,
56
+ workspaceToken: !0
57
+ });
58
+ if (r.errors?.length) throw Error(r.errors[0]?.message || "GraphQL error");
59
+ if (!r.data?.workspaceMembers) throw Error("Workspace members query returned no data");
60
+ return r.data.workspaceMembers;
61
+ },
62
+ getNextPageParam: (e, t, r) => e.hasMore ? Number(r) + n : void 0,
63
+ enabled: r && !!t,
64
+ staleTime: 300 * 1e3
65
+ });
66
+ }, f = (t) => {
67
+ let { authToken: n, workspaceId: r } = e();
68
+ return s({
36
69
  queryKey: [
37
70
  "workspaceMember",
38
71
  r,
39
72
  t
40
73
  ],
41
74
  queryFn: async () => {
42
- let e = await c({
75
+ let e = await l({
43
76
  gateway: "workspace",
44
77
  authToken: n || void 0,
45
- query: s(i),
78
+ query: c(i),
46
79
  variables: { id: t },
47
80
  workspaceId: r || void 0,
48
81
  workspaceToken: !0
49
82
  });
50
83
  if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
84
+ if (!e.data?.workspaceMember) throw Error("Workspace member query returned no data");
51
85
  return e.data.workspaceMember;
52
86
  },
53
87
  enabled: !!t,
54
88
  staleTime: 300 * 1e3
55
89
  });
56
- }, d = (t, r) => {
90
+ }, p = (t, r) => {
57
91
  let { authToken: i, workspaceId: a } = e();
58
- return o({
92
+ return s({
59
93
  queryKey: [
60
94
  "userWorkspaces",
61
95
  t,
62
96
  r
63
97
  ],
64
98
  queryFn: async () => {
65
- let e = await c({
99
+ let e = await l({
66
100
  gateway: "workspace",
67
101
  authToken: i || void 0,
68
- query: s(n),
102
+ query: c(n),
69
103
  variables: {
70
104
  userId: t,
71
105
  pagination: r
@@ -74,14 +108,15 @@ var l = (t, n) => {
74
108
  workspaceToken: !0
75
109
  });
76
110
  if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
111
+ if (!e.data?.userWorkspaces) throw Error("User workspaces query returned no data");
77
112
  return e.data.userWorkspaces;
78
113
  },
79
114
  enabled: !!t,
80
115
  staleTime: 300 * 1e3
81
116
  });
82
- }, f = (t, n, i) => {
117
+ }, m = (t, n, i) => {
83
118
  let { authToken: a } = e();
84
- return o({
119
+ return s({
85
120
  queryKey: [
86
121
  "workspaceInvitations",
87
122
  t,
@@ -89,10 +124,10 @@ var l = (t, n) => {
89
124
  i
90
125
  ],
91
126
  queryFn: async () => {
92
- let e = await c({
127
+ let e = await l({
93
128
  gateway: "workspace",
94
129
  authToken: a || void 0,
95
- query: s(r),
130
+ query: c(r),
96
131
  variables: {
97
132
  status: n,
98
133
  pagination: i
@@ -101,20 +136,21 @@ var l = (t, n) => {
101
136
  workspaceToken: !0
102
137
  });
103
138
  if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
139
+ if (!e.data?.workspaceInvitations) throw Error("Workspace invitations query returned no data");
104
140
  return e.data.workspaceInvitations;
105
141
  },
106
142
  enabled: !!t,
107
143
  staleTime: 300 * 1e3
108
144
  });
109
- }, p = (n, r = !0) => {
145
+ }, h = (n, r = !0) => {
110
146
  let { authToken: i } = e();
111
- return o({
147
+ return s({
112
148
  queryKey: ["invitation", n],
113
149
  queryFn: async () => {
114
- let e = await c({
150
+ let e = await l({
115
151
  gateway: "workspace",
116
152
  authToken: i || void 0,
117
- query: s(t),
153
+ query: c(t),
118
154
  variables: { id: n }
119
155
  });
120
156
  if (e.errors?.length) throw Error(e.errors[0]?.message || "Failed to fetch invitation");
@@ -127,6 +163,6 @@ var l = (t, n) => {
127
163
  });
128
164
  };
129
165
  //#endregion
130
- export { p as useInvitation, d as useUserWorkspaces, f as useWorkspaceInvitations, u as useWorkspaceMember, l as useWorkspaceMembers };
166
+ export { d as useInfiniteWorkspaceMembers, h as useInvitation, p as useUserWorkspaces, m as useWorkspaceInvitations, f as useWorkspaceMember, u as useWorkspaceMembers };
131
167
 
132
168
  //# sourceMappingURL=useWorkspaceMembers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useWorkspaceMembers.js","names":[],"sources":["../../src/hooks/useWorkspaceMembers.ts"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n GetWorkspaceMembersDocument,\n GetWorkspaceMemberDocument,\n GetUserWorkspacesDocument,\n GetWorkspaceInvitationsDocument,\n GetInvitationDocument,\n} from '../generated/wspace-operations';\nimport type {\n MemberList,\n WorkspaceMember,\n WorkspaceInvitation,\n InvitationList,\n PaginationInput,\n InvitationStatus,\n} from '../types';\n\n/**\n * Hook to fetch all members of the current workspace\n */\nexport const useWorkspaceMembers = (workspaceId: string, pagination?: PaginationInput) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMembers', workspaceId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ workspaceMembers: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMembersDocument),\n variables: { workspaceId, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header (required by gateway RBAC)\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.workspaceMembers;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch a single workspace member by ID\n */\nexport const useWorkspaceMember = (id: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMember', workspaceId, id],\n queryFn: async (): Promise<WorkspaceMember> => {\n const result = await graphqlFetch<{ workspaceMember: WorkspaceMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMemberDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.workspaceMember;\n },\n enabled: !!id,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch all workspaces a user is a member of\n */\nexport const useUserWorkspaces = (userId: string, pagination?: PaginationInput) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['userWorkspaces', userId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ userWorkspaces: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetUserWorkspacesDocument),\n variables: { userId, pagination },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.userWorkspaces;\n },\n enabled: !!userId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch workspace invitations\n * Requires x-workspace-id header for workspace context\n */\nexport const useWorkspaceInvitations = (\n workspaceId: string,\n status?: InvitationStatus,\n pagination?: PaginationInput\n) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceInvitations', workspaceId, status, pagination],\n queryFn: async (): Promise<InvitationList> => {\n const result = await graphqlFetch<{ workspaceInvitations: InvitationList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceInvitationsDocument),\n variables: { status, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.workspaceInvitations;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to get a single invitation by ID (for acceptance page)\n */\nexport const useInvitation = (id: string, enabled = true) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['invitation', id],\n queryFn: async (): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ invitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetInvitationDocument),\n variables: { id },\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'Failed to fetch invitation');\n }\n\n if (!result.data?.invitation) {\n throw new Error('Invitation not found');\n }\n\n return result.data.invitation;\n },\n enabled: !!id && enabled,\n retry: 1,\n staleTime: 5 * 60 * 1000,\n });\n};\n"],"mappings":";;;;;;AAuBA,IAAa,KAAuB,GAAqB,MAAiC;CACxF,IAAM,EAAE,iBAAc,GAAsB;AAE5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAoB;GAAa;GAAW;EACvD,SAAS,YAAiC;GACxC,IAAM,IAAS,MAAM,EAA+C;IAClE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA4B;IACzC,WAAW;KAAE;KAAa;KAAY;IACtC;IACA,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAMS,KAAsB,MAAe;CAChD,IAAM,EAAE,cAAW,mBAAgB,GAAsB;AAEzD,QAAO,EAAS;EACd,UAAU;GAAC;GAAmB;GAAa;GAAG;EAC9C,SAAS,YAAsC;GAC7C,IAAM,IAAS,MAAM,EAAmD;IACtE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA2B;IACxC,WAAW,EAAE,OAAI;IACjB,aAAa,KAAe,KAAA;IAC5B,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAMS,KAAqB,GAAgB,MAAiC;CACjF,IAAM,EAAE,cAAW,mBAAgB,GAAsB;AAEzD,QAAO,EAAS;EACd,UAAU;GAAC;GAAkB;GAAQ;GAAW;EAChD,SAAS,YAAiC;GACxC,IAAM,IAAS,MAAM,EAA6C;IAChE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA0B;IACvC,WAAW;KAAE;KAAQ;KAAY;IACjC,aAAa,KAAe,KAAA;IAC5B,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAOS,KACX,GACA,GACA,MACG;CACH,IAAM,EAAE,iBAAc,GAAsB;AAE5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAwB;GAAa;GAAQ;GAAW;EACnE,SAAS,YAAqC;GAC5C,IAAM,IAAS,MAAM,EAAuD;IAC1E,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAAgC;IAC7C,WAAW;KAAE;KAAQ;KAAY;IACjC;IACA,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAMS,KAAiB,GAAY,IAAU,OAAS;CAC3D,IAAM,EAAE,iBAAc,GAAsB;AAE5C,QAAO,EAAS;EACd,UAAU,CAAC,cAAc,EAAG;EAC5B,SAAS,YAA0C;GACjD,IAAM,IAAS,MAAM,EAAkD;IACrE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAAsB;IACnC,WAAW,EAAE,OAAI;IAClB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,6BAA6B;AAG5E,OAAI,CAAC,EAAO,MAAM,WAChB,OAAU,MAAM,uBAAuB;AAGzC,UAAO,EAAO,KAAK;;EAErB,SAAS,CAAC,CAAC,KAAM;EACjB,OAAO;EACP,WAAW,MAAS;EACrB,CAAC"}
1
+ {"version":3,"file":"useWorkspaceMembers.js","names":[],"sources":["../../src/hooks/useWorkspaceMembers.ts"],"sourcesContent":["import { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n GetWorkspaceMembersDocument,\n GetWorkspaceMemberDocument,\n GetUserWorkspacesDocument,\n GetWorkspaceInvitationsDocument,\n GetInvitationDocument,\n} from '../generated/wspace-operations';\nimport type {\n MemberList,\n WorkspaceMember,\n WorkspaceInvitation,\n InvitationList,\n PaginationInput,\n InvitationStatus,\n} from '../types';\n\n/**\n * Hook to fetch all members of the current workspace\n */\nexport const useWorkspaceMembers = (workspaceId: string, pagination?: PaginationInput) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMembers', workspaceId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ workspaceMembers: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMembersDocument),\n variables: { workspaceId, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header (required by gateway RBAC)\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceMembers) {\n throw new Error('Workspace members query returned no data');\n }\n\n return result.data.workspaceMembers;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\nexport const useInfiniteWorkspaceMembers = (\n workspaceId: string,\n pageSize = 100,\n enabled = true\n) => {\n const { authToken } = useWorkspacesContext();\n\n return useInfiniteQuery({\n queryKey: ['workspaceMembersInfinite', workspaceId, pageSize],\n initialPageParam: 0,\n queryFn: async ({ pageParam }): Promise<MemberList> => {\n const result = await graphqlFetch<{ workspaceMembers: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMembersDocument),\n variables: {\n workspaceId,\n pagination: {\n limit: pageSize,\n offset: pageParam,\n },\n },\n workspaceId,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceMembers) {\n throw new Error('Workspace members query returned no data');\n }\n\n return result.data.workspaceMembers;\n },\n getNextPageParam: (lastPage, _pages, lastPageParam) =>\n lastPage.hasMore ? Number(lastPageParam) + pageSize : undefined,\n enabled: enabled && !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch a single workspace member by ID\n */\nexport const useWorkspaceMember = (id: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMember', workspaceId, id],\n queryFn: async (): Promise<WorkspaceMember> => {\n const result = await graphqlFetch<{ workspaceMember: WorkspaceMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMemberDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceMember) {\n throw new Error('Workspace member query returned no data');\n }\n\n return result.data.workspaceMember;\n },\n enabled: !!id,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch all workspaces a user is a member of\n */\nexport const useUserWorkspaces = (userId: string, pagination?: PaginationInput) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['userWorkspaces', userId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ userWorkspaces: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetUserWorkspacesDocument),\n variables: { userId, pagination },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.userWorkspaces) {\n throw new Error('User workspaces query returned no data');\n }\n\n return result.data.userWorkspaces;\n },\n enabled: !!userId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch workspace invitations\n * Requires x-workspace-id header for workspace context\n */\nexport const useWorkspaceInvitations = (\n workspaceId: string,\n status?: InvitationStatus,\n pagination?: PaginationInput\n) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceInvitations', workspaceId, status, pagination],\n queryFn: async (): Promise<InvitationList> => {\n const result = await graphqlFetch<{ workspaceInvitations: InvitationList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceInvitationsDocument),\n variables: { status, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceInvitations) {\n throw new Error('Workspace invitations query returned no data');\n }\n\n return result.data.workspaceInvitations;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to get a single invitation by ID (for acceptance page)\n */\nexport const useInvitation = (id: string, enabled = true) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['invitation', id],\n queryFn: async (): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ invitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetInvitationDocument),\n variables: { id },\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'Failed to fetch invitation');\n }\n\n if (!result.data?.invitation) {\n throw new Error('Invitation not found');\n }\n\n return result.data.invitation;\n },\n enabled: !!id && enabled,\n retry: 1,\n staleTime: 5 * 60 * 1000,\n });\n};\n"],"mappings":"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"}
@@ -22,6 +22,10 @@ function n() {
22
22
  canUpdateProject: n(e.PROJECT_UPDATE),
23
23
  canDeleteProject: n(e.PROJECT_DELETE),
24
24
  canArchiveProject: n(e.PROJECT_ARCHIVE),
25
+ canListProjectMembers: n(e.PROJECT_MEMBER_LIST),
26
+ canViewProjectMember: n(e.PROJECT_MEMBER_READ),
27
+ canAddProjectMember: n(e.PROJECT_MEMBER_CREATE),
28
+ canRemoveProjectMember: n(e.PROJECT_MEMBER_DELETE),
25
29
  canViewSettings: n(e.SETTINGS_READ),
26
30
  canUpdateSettings: n(e.SETTINGS_WRITE),
27
31
  canViewActivity: n(e.ACTIVITY_READ)
@@ -1 +1 @@
1
- {"version":3,"file":"useWorkspacePermissions.js","names":[],"sources":["../../src/hooks/useWorkspacePermissions.ts"],"sourcesContent":["/**\n * Workspace MFE - Permission Hook\n *\n * Wraps usePermissions() with typed permission flags for all workspace resources.\n */\n\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\n\nexport function useWorkspacePermissions() {\n const { hasPermission, isLoading } = usePermissions();\n\n return {\n isLoading,\n\n // Workspace\n canListWorkspaces: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_LIST),\n canViewWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_READ),\n canCreateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_CREATE),\n canUpdateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_UPDATE),\n canDeleteWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_DELETE),\n canArchiveWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_ARCHIVE),\n\n // Members\n canListMembers: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_LIST),\n canViewMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_READ),\n canInviteMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_CREATE),\n canUpdateMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_UPDATE),\n canRemoveMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_DELETE),\n\n // Projects\n canListProjects: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_LIST),\n canViewProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_READ),\n canCreateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_CREATE),\n canUpdateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_UPDATE),\n canDeleteProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_DELETE),\n canArchiveProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_ARCHIVE),\n\n // Settings\n canViewSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_READ),\n canUpdateSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_WRITE),\n\n // Activity\n canViewActivity: hasPermission(WORKSPACE_PERMISSIONS.ACTIVITY_READ),\n };\n}\n"],"mappings":";;;AASA,SAAgB,IAA0B;CACxC,IAAM,EAAE,kBAAe,iBAAc,GAAgB;AAErD,QAAO;EACL;EAGA,mBAAmB,EAAc,EAAsB,eAAe;EACtE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,qBAAqB,EAAc,EAAsB,kBAAkB;EAG3E,gBAAgB,EAAc,EAAsB,YAAY;EAChE,eAAe,EAAc,EAAsB,YAAY;EAC/D,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EAGnE,iBAAiB,EAAc,EAAsB,aAAa;EAClE,gBAAgB,EAAc,EAAsB,aAAa;EACjE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,mBAAmB,EAAc,EAAsB,gBAAgB;EAGvE,iBAAiB,EAAc,EAAsB,cAAc;EACnE,mBAAmB,EAAc,EAAsB,eAAe;EAGtE,iBAAiB,EAAc,EAAsB,cAAc;EACpE"}
1
+ {"version":3,"file":"useWorkspacePermissions.js","names":[],"sources":["../../src/hooks/useWorkspacePermissions.ts"],"sourcesContent":["/**\n * Workspace MFE - Permission Hook\n *\n * Wraps usePermissions() with typed permission flags for all workspace resources.\n */\n\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\n\nexport function useWorkspacePermissions() {\n const { hasPermission, isLoading } = usePermissions();\n\n return {\n isLoading,\n\n // Workspace\n canListWorkspaces: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_LIST),\n canViewWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_READ),\n canCreateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_CREATE),\n canUpdateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_UPDATE),\n canDeleteWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_DELETE),\n canArchiveWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_ARCHIVE),\n\n // Members\n canListMembers: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_LIST),\n canViewMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_READ),\n canInviteMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_CREATE),\n canUpdateMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_UPDATE),\n canRemoveMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_DELETE),\n\n // Projects\n canListProjects: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_LIST),\n canViewProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_READ),\n canCreateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_CREATE),\n canUpdateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_UPDATE),\n canDeleteProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_DELETE),\n canArchiveProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_ARCHIVE),\n\n // Project members\n canListProjectMembers: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_LIST),\n canViewProjectMember: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_READ),\n canAddProjectMember: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_CREATE),\n canRemoveProjectMember: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_DELETE),\n\n // Settings\n canViewSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_READ),\n canUpdateSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_WRITE),\n\n // Activity\n canViewActivity: hasPermission(WORKSPACE_PERMISSIONS.ACTIVITY_READ),\n };\n}\n"],"mappings":";;;AASA,SAAgB,IAA0B;CACxC,IAAM,EAAE,kBAAe,iBAAc,GAAgB;AAErD,QAAO;EACL;EAGA,mBAAmB,EAAc,EAAsB,eAAe;EACtE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,qBAAqB,EAAc,EAAsB,kBAAkB;EAG3E,gBAAgB,EAAc,EAAsB,YAAY;EAChE,eAAe,EAAc,EAAsB,YAAY;EAC/D,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EAGnE,iBAAiB,EAAc,EAAsB,aAAa;EAClE,gBAAgB,EAAc,EAAsB,aAAa;EACjE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,mBAAmB,EAAc,EAAsB,gBAAgB;EAGvE,uBAAuB,EAAc,EAAsB,oBAAoB;EAC/E,sBAAsB,EAAc,EAAsB,oBAAoB;EAC9E,qBAAqB,EAAc,EAAsB,sBAAsB;EAC/E,wBAAwB,EAAc,EAAsB,sBAAsB;EAGlF,iBAAiB,EAAc,EAAsB,cAAc;EACnE,mBAAmB,EAAc,EAAsB,eAAe;EAGtE,iBAAiB,EAAc,EAAsB,cAAc;EACpE"}
@@ -1 +1 @@
1
- {"version":3,"file":"useWorkspacesEventEmitter.js","names":[],"sources":["../../src/hooks/useWorkspacesEventEmitter.ts"],"sourcesContent":["/**\n * Workspaces-domain event emitter. Emits lifecycle events to the host shell's\n * event bus per `~/products/infra/infra-specs/microfrontends/47-FRONTEND-EVENT-BUS.md`.\n *\n * The MFE never sinks directly to Rybbit/audit — it goes through the bus.\n *\n * The fe-libs `EventBus.emit` is statically typed against `BurdenoffEventName`\n * which doesn't list our workspaces-domain names. The runtime bus is dynamic,\n * so the cast loses autocomplete but is sound.\n */\nimport { useCallback } from 'react';\n\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nexport type WorkspacesDomainEvent =\n // Lifecycle (success)\n | 'workspace.created'\n | 'workspace.updated'\n | 'workspace.deleted'\n | 'workspace.archived'\n | 'workspace.reactivated'\n | 'project.created'\n | 'project.updated'\n | 'project.deleted'\n | 'project.archived'\n | 'project.unarchived'\n | 'workspace-member.added'\n | 'workspace-member.removed'\n | 'workspace-member.role-updated'\n | 'workspace-invitation.created'\n | 'workspace-invitation.updated'\n | 'workspace-invitation.accepted'\n | 'workspace-invitation.rejected'\n | 'workspace-invitation.cancelled'\n | 'workspace-invitation.resent'\n | 'workspace-invitation.deleted'\n | 'workspace-activity.appended'\n // Failure / observability — forwarded to OtelBrowserSink + audit sink\n | 'workspace.create_failed'\n | 'workspace.update_failed'\n | 'workspace.delete_failed'\n | 'workspace.archive_failed'\n | 'workspace.reactivate_failed'\n | 'project.create_failed'\n | 'project.update_failed'\n | 'project.delete_failed'\n | 'project.archive_failed'\n | 'project.unarchive_failed'\n | 'workspace-member.add_failed'\n | 'workspace-member.remove_failed'\n | 'workspace-member.role-update_failed'\n | 'workspace-invitation.create_failed'\n | 'workspace-invitation.update_failed'\n | 'workspace-invitation.accept_failed'\n | 'workspace-invitation.reject_failed'\n | 'workspace-invitation.cancel_failed'\n | 'workspace-invitation.resend_failed'\n | 'workspace-invitation.delete_failed'\n // Module-scoped (plural) — describes a navigation event into the module,\n // not an action on a single resource.\n | 'workspaces.page.viewed';\n\nexport interface WorkspacesEventPayload {\n workspaceId?: string;\n projectId?: string;\n memberId?: string;\n invitationId?: string;\n userId?: string;\n email?: string;\n source?: string;\n // Observability fields (no PII per SRE guide §7)\n page?: string;\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport function useWorkspacesEventEmitter(): {\n emit: (event: WorkspacesDomainEvent, payload?: WorkspacesEventPayload) => void;\n} {\n const bus = useEventBus();\n // Memoize the emit callback so consumers (notably `useWorkspacesPageView`)\n // can put it in effect dep arrays without firing on every render.\n const emit = useCallback(\n (event: WorkspacesDomainEvent, payload: WorkspacesEventPayload = {}) => {\n try {\n type DynamicEmit = (e: string, p: unknown) => void;\n (bus as unknown as { emit: DynamicEmit }).emit(event, payload);\n } catch (err) {\n // Bus failures must not break workspace operations — but in dev we\n // surface the error so a wrong event shape doesn't disappear silently.\n if (import.meta.env?.DEV) {\n console.warn('[useWorkspacesEventEmitter] event bus emit failed', {\n event,\n payload,\n err,\n });\n }\n }\n },\n [bus]\n );\n return { emit };\n}\n"],"mappings":";;;AA6EA,SAAgB,IAEd;CACA,IAAM,IAAM,GAAa;AAsBzB,QAAO,EAAE,MAnBI,GACV,GAA8B,IAAkC,EAAE,KAAK;AACtE,MAAI;AAED,KAAyC,KAAK,GAAO,EAAQ;UAClD;IAYhB,CAAC,EAAI,CACN,EACc"}
1
+ {"version":3,"file":"useWorkspacesEventEmitter.js","names":[],"sources":["../../src/hooks/useWorkspacesEventEmitter.ts"],"sourcesContent":["/**\n * Workspaces-domain event emitter. Emits lifecycle events to the host shell's\n * event bus per `~/products/infra/infra-specs/microfrontends/47-FRONTEND-EVENT-BUS.md`.\n *\n * The MFE never sinks directly to Rybbit/audit — it goes through the bus.\n *\n * The fe-libs `EventBus.emit` is statically typed against `BurdenoffEventName`\n * which doesn't list our workspaces-domain names. The runtime bus is dynamic,\n * so the cast loses autocomplete but is sound.\n */\nimport { useCallback } from 'react';\n\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nexport type WorkspacesDomainEvent =\n // Lifecycle (success)\n | 'workspace.created'\n | 'workspace.updated'\n | 'workspace.deleted'\n | 'workspace.archived'\n | 'workspace.reactivated'\n | 'project.created'\n | 'project.updated'\n | 'project.deleted'\n | 'project.archived'\n | 'project.unarchived'\n | 'project-member.added'\n | 'project-member.removed'\n | 'workspace-member.added'\n | 'workspace-member.removed'\n | 'workspace-member.role-updated'\n | 'workspace-invitation.created'\n | 'workspace-invitation.updated'\n | 'workspace-invitation.accepted'\n | 'workspace-invitation.rejected'\n | 'workspace-invitation.cancelled'\n | 'workspace-invitation.resent'\n | 'workspace-invitation.deleted'\n | 'workspace-activity.appended'\n // Failure / observability — forwarded to OtelBrowserSink + audit sink\n | 'workspace.create_failed'\n | 'workspace.update_failed'\n | 'workspace.delete_failed'\n | 'workspace.archive_failed'\n | 'workspace.reactivate_failed'\n | 'project.create_failed'\n | 'project.update_failed'\n | 'project.delete_failed'\n | 'project.archive_failed'\n | 'project.unarchive_failed'\n | 'project-member.add_failed'\n | 'project-member.remove_failed'\n | 'workspace-member.add_failed'\n | 'workspace-member.remove_failed'\n | 'workspace-member.role-update_failed'\n | 'workspace-invitation.create_failed'\n | 'workspace-invitation.update_failed'\n | 'workspace-invitation.accept_failed'\n | 'workspace-invitation.reject_failed'\n | 'workspace-invitation.cancel_failed'\n | 'workspace-invitation.resend_failed'\n | 'workspace-invitation.delete_failed'\n // Module-scoped (plural) — describes a navigation event into the module,\n // not an action on a single resource.\n | 'workspaces.page.viewed';\n\nexport interface WorkspacesEventPayload {\n workspaceId?: string;\n projectId?: string;\n memberId?: string;\n invitationId?: string;\n userId?: string;\n email?: string;\n source?: string;\n // Observability fields (no PII per SRE guide §7)\n page?: string;\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport function useWorkspacesEventEmitter(): {\n emit: (event: WorkspacesDomainEvent, payload?: WorkspacesEventPayload) => void;\n} {\n const bus = useEventBus();\n // Memoize the emit callback so consumers (notably `useWorkspacesPageView`)\n // can put it in effect dep arrays without firing on every render.\n const emit = useCallback(\n (event: WorkspacesDomainEvent, payload: WorkspacesEventPayload = {}) => {\n try {\n type DynamicEmit = (e: string, p: unknown) => void;\n (bus as unknown as { emit: DynamicEmit }).emit(event, payload);\n } catch (err) {\n // Bus failures must not break workspace operations — but in dev we\n // surface the error so a wrong event shape doesn't disappear silently.\n if (import.meta.env?.DEV) {\n console.warn('[useWorkspacesEventEmitter] event bus emit failed', {\n event,\n payload,\n err,\n });\n }\n }\n },\n [bus]\n );\n return { emit };\n}\n"],"mappings":";;;AAiFA,SAAgB,IAEd;CACA,IAAM,IAAM,GAAa;AAsBzB,QAAO,EAAE,MAnBI,GACV,GAA8B,IAAkC,EAAE,KAAK;AACtE,MAAI;AAED,KAAyC,KAAK,GAAO,EAAQ;UAClD;IAYhB,CAAC,EAAI,CACN,EACc"}
package/dist/index.js CHANGED
@@ -7,20 +7,21 @@ import { getMemberRoleClasses as c, getMemberRoleLabel as l, getProjectStatusCla
7
7
  import { WorkspaceCard as _ } from "./components/WorkspaceCard.js";
8
8
  import { WorkspacesRoot as v } from "./WorkspacesRoot.js";
9
9
  import { DashboardPage as y } from "./pages/dashboard/DashboardPage.js";
10
- import { useInvitation as b, useUserWorkspaces as x, useWorkspaceInvitations as S, useWorkspaceMember as C, useWorkspaceMembers as w } from "./hooks/useWorkspaceMembers.js";
11
- import { useAcceptInvitation as T, useAddWorkspaceMember as E, useBulkCreateInvitations as D, useCancelInvitation as O, useCreateInvitation as k, useDeleteInvitation as A, useRejectInvitation as j, useRemoveUserFromWorkspace as M, useRemoveWorkspaceMember as N, useResendInvitation as P, useUpdateInvitation as F } from "./hooks/useMemberMutations.js";
12
- import { InviteAcceptancePage as I } from "./pages/InviteAcceptancePage.js";
13
- import { PendingInvitesPage as L } from "./pages/PendingInvitesPage.js";
14
- import { useArchiveWorkspace as R, useCreateWorkspace as z, useDeleteWorkspace as B, useReactivateWorkspace as V, useUpdateWorkspace as H } from "./hooks/useWorkspaceMutations.js";
15
- import { useMyProjects as U, useProject as W, useProjectMembersCount as G, useProjects as K } from "./hooks/useProjects.js";
16
- import { useArchiveProject as q, useCreateProject as J, useDeleteProject as Y, useTagProject as X, useUnarchiveProject as Z, useUntagProject as Q, useUpdateProject as $ } from "./hooks/useProjectMutations.js";
17
- import { useMyOrganizations as ee, useMyTenants as te } from "./hooks/useTenants.js";
10
+ import { useInfiniteWorkspaceMembers as b, useInvitation as x, useUserWorkspaces as S, useWorkspaceInvitations as C, useWorkspaceMember as w, useWorkspaceMembers as T } from "./hooks/useWorkspaceMembers.js";
11
+ import { useAcceptInvitation as E, useAddWorkspaceMember as D, useBulkCreateInvitations as O, useCancelInvitation as k, useCreateInvitation as A, useDeleteInvitation as j, useRejectInvitation as M, useRemoveUserFromWorkspace as N, useRemoveWorkspaceMember as P, useResendInvitation as F, useUpdateInvitation as I } from "./hooks/useMemberMutations.js";
12
+ import { InviteAcceptancePage as L } from "./pages/InviteAcceptancePage.js";
13
+ import { PendingInvitesPage as R } from "./pages/PendingInvitesPage.js";
14
+ import { useMyProjects as z, useProject as B, useProjectMembersCount as V, useProjects as H } from "./hooks/useProjects.js";
15
+ import { WorkspaceInvitePage as U } from "./pages/WorkspaceInvitePage.js";
16
+ import { useArchiveWorkspace as W, useCreateWorkspace as G, useDeleteWorkspace as K, useReactivateWorkspace as q, useUpdateWorkspace as J } from "./hooks/useWorkspaceMutations.js";
17
+ import { useArchiveProject as Y, useCreateProject as X, useDeleteProject as Z, useTagProject as Q, useUnarchiveProject as $, useUntagProject as ee, useUpdateProject as te } from "./hooks/useProjectMutations.js";
18
+ import { useMyOrganizations as ne, useMyTenants as re } from "./hooks/useTenants.js";
18
19
  import "./hooks/index.js";
19
- import { CreateWorkspaceDialog as ne } from "./components/CreateWorkspaceDialog.js";
20
- import { formatDate as re, formatDateTime as ie, formatFileSize as ae, formatProjectStatus as oe, formatRelativeTime as se, formatWorkspaceStatus as ce, getInitials as le, toTitleCase as ue, truncate as de } from "./utils/formatters.js";
21
- import { ProjectCard as fe } from "./components/ProjectCard.js";
22
- import { CreateProjectDialog as pe } from "./components/CreateProjectDialog.js";
23
- import { MemberListItem as me } from "./components/MemberListItem.js";
24
- import { InviteMemberDialog as he } from "./components/InviteMemberDialog.js";
20
+ import { CreateWorkspaceDialog as ie } from "./components/CreateWorkspaceDialog.js";
21
+ import { formatDate as ae, formatDateTime as oe, formatFileSize as se, formatProjectStatus as ce, formatRelativeTime as le, formatWorkspaceStatus as ue, getInitials as de, toTitleCase as fe, truncate as pe } from "./utils/formatters.js";
22
+ import { ProjectCard as me } from "./components/ProjectCard.js";
23
+ import { CreateProjectDialog as he } from "./components/CreateProjectDialog.js";
24
+ import { MemberListItem as ge } from "./components/MemberListItem.js";
25
+ import { InviteMemberDialog as _e } from "./components/InviteMemberDialog.js";
25
26
  import "./components/index.js";
26
- export { pe as CreateProjectDialog, ne as CreateWorkspaceDialog, y as DashboardPage, I as InviteAcceptancePage, he as InviteMemberDialog, me as MemberListItem, L as PendingInvitesPage, fe as ProjectCard, _ as WorkspaceCard, n as WorkspacesErrorBoundary, e as WorkspacesProvider, v as WorkspacesRoot, re as formatDate, ie as formatDateTime, ae as formatFileSize, oe as formatProjectStatus, se as formatRelativeTime, ce as formatWorkspaceStatus, le as getInitials, c as getMemberRoleClasses, l as getMemberRoleLabel, u as getProjectStatusClasses, d as getProjectStatusIconClass, f as getProjectStatusLabel, p as getWorkspaceStatusBgClass, m as getWorkspaceStatusClasses, h as getWorkspaceStatusIconClass, g as getWorkspaceStatusLabel, ue as toTitleCase, de as truncate, T as useAcceptInvitation, E as useAddWorkspaceMember, q as useArchiveProject, R as useArchiveWorkspace, D as useBulkCreateInvitations, O as useCancelInvitation, k as useCreateInvitation, J as useCreateProject, z as useCreateWorkspace, A as useDeleteInvitation, Y as useDeleteProject, B as useDeleteWorkspace, b as useInvitation, ee as useMyOrganizations, s as useMyPendingInvitations, U as useMyProjects, te as useMyTenants, i as useMyWorkspaces, W as useProject, G as useProjectMembersCount, K as useProjects, V as useReactivateWorkspace, j as useRejectInvitation, M as useRemoveUserFromWorkspace, N as useRemoveWorkspaceMember, P as useResendInvitation, X as useTagProject, Z as useUnarchiveProject, Q as useUntagProject, F as useUpdateInvitation, $ as useUpdateProject, H as useUpdateWorkspace, x as useUserWorkspaces, a as useWorkspace, S as useWorkspaceInvitations, C as useWorkspaceMember, w as useWorkspaceMembers, o as useWorkspaces, t as useWorkspacesContext, r as useWorkspacesStore };
27
+ export { he as CreateProjectDialog, ie as CreateWorkspaceDialog, y as DashboardPage, L as InviteAcceptancePage, _e as InviteMemberDialog, ge as MemberListItem, R as PendingInvitesPage, me as ProjectCard, _ as WorkspaceCard, U as WorkspaceInvitePage, n as WorkspacesErrorBoundary, e as WorkspacesProvider, v as WorkspacesRoot, ae as formatDate, oe as formatDateTime, se as formatFileSize, ce as formatProjectStatus, le as formatRelativeTime, ue as formatWorkspaceStatus, de as getInitials, c as getMemberRoleClasses, l as getMemberRoleLabel, u as getProjectStatusClasses, d as getProjectStatusIconClass, f as getProjectStatusLabel, p as getWorkspaceStatusBgClass, m as getWorkspaceStatusClasses, h as getWorkspaceStatusIconClass, g as getWorkspaceStatusLabel, fe as toTitleCase, pe as truncate, E as useAcceptInvitation, D as useAddWorkspaceMember, Y as useArchiveProject, W as useArchiveWorkspace, O as useBulkCreateInvitations, k as useCancelInvitation, A as useCreateInvitation, X as useCreateProject, G as useCreateWorkspace, j as useDeleteInvitation, Z as useDeleteProject, K as useDeleteWorkspace, b as useInfiniteWorkspaceMembers, x as useInvitation, ne as useMyOrganizations, s as useMyPendingInvitations, z as useMyProjects, re as useMyTenants, i as useMyWorkspaces, B as useProject, V as useProjectMembersCount, H as useProjects, q as useReactivateWorkspace, M as useRejectInvitation, N as useRemoveUserFromWorkspace, P as useRemoveWorkspaceMember, F as useResendInvitation, Q as useTagProject, $ as useUnarchiveProject, ee as useUntagProject, I as useUpdateInvitation, te as useUpdateProject, J as useUpdateWorkspace, S as useUserWorkspaces, a as useWorkspace, C as useWorkspaceInvitations, w as useWorkspaceMember, T as useWorkspaceMembers, o as useWorkspaces, t as useWorkspacesContext, r as useWorkspacesStore };
@@ -1,8 +1,8 @@
1
1
  import { tWithFallback as e } from "../utils/i18n.js";
2
2
  import { useWorkspacesPageView as t } from "../hooks/useWorkspacesPageView.js";
3
- import { formatDate as n } from "../utils/formatters.js";
4
- import { useWorkspaceActivity as r } from "../hooks/useWorkspaceActivity.js";
5
- import { useWorkspacePermissions as i } from "../hooks/useWorkspacePermissions.js";
3
+ import { useWorkspacePermissions as n } from "../hooks/useWorkspacePermissions.js";
4
+ import { formatDate as r } from "../utils/formatters.js";
5
+ import { useWorkspaceActivity as i } from "../hooks/useWorkspaceActivity.js";
6
6
  import { Activity as a } from "lucide-react";
7
7
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
8
  import { Card as c, CardContent as l, CardHeader as u, CardTitle as d, Skeleton as f } from "@burdenoff/fe-libs/ui";
@@ -15,7 +15,7 @@ function h() {
15
15
  workspaceId: g,
16
16
  requireParams: !0
17
17
  });
18
- let { data: _, isLoading: v, error: y } = r(g), { canViewActivity: b, isLoading: x } = i();
18
+ let { data: _, isLoading: v, error: y } = i(g), { canViewActivity: b, isLoading: x } = n();
19
19
  return x ? /* @__PURE__ */ s("div", {
20
20
  className: "space-y-4 p-6",
21
21
  children: [/* @__PURE__ */ o(f, { className: "h-10 w-1/3" }), /* @__PURE__ */ o(f, { className: "h-64" })]
@@ -87,7 +87,7 @@ function h() {
87
87
  " ",
88
88
  /* @__PURE__ */ o("span", {
89
89
  className: "text-foreground",
90
- children: n(t.timestamp)
90
+ children: r(t.timestamp)
91
91
  })
92
92
  ] }),
93
93
  /* @__PURE__ */ s("p", { children: [