@arcote.tech/arc-workspace 0.4.6 → 0.4.8
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-workspace",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.8",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Reusable workspace module for Arc framework — multi-workspace with dual token architecture",
|
|
7
7
|
"main": "./src/index.ts",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"type-check": "tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@arcote.tech/arc": "^0.4.
|
|
14
|
-
"@arcote.tech/arc-auth": "^0.4.
|
|
13
|
+
"@arcote.tech/arc": "^0.4.8",
|
|
14
|
+
"@arcote.tech/arc-auth": "^0.4.8",
|
|
15
15
|
"typescript": "^5.0.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import {
|
|
2
|
+
aggregate,
|
|
3
|
+
date,
|
|
4
|
+
string,
|
|
5
|
+
type ArcId,
|
|
6
|
+
} from "@arcote.tech/arc";
|
|
7
|
+
import type { Token } from "@arcote.tech/arc-auth";
|
|
8
|
+
import type { WorkspaceToken } from "../tokens/workspace-token";
|
|
9
|
+
|
|
10
|
+
export type WorkspaceInvitationAggregateData = {
|
|
11
|
+
name: string;
|
|
12
|
+
workspaceInvitationId: ArcId<any>;
|
|
13
|
+
workspaceId: ArcId<any>;
|
|
14
|
+
accountId: ArcId<any>;
|
|
15
|
+
workspaceToken: WorkspaceToken;
|
|
16
|
+
userToken: Token;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function generateInviteToken(): string {
|
|
20
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
21
|
+
let result = "";
|
|
22
|
+
for (let i = 0; i < 32; i++) {
|
|
23
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const createWorkspaceInvitationAggregate = <
|
|
29
|
+
const Data extends WorkspaceInvitationAggregateData,
|
|
30
|
+
>(
|
|
31
|
+
data: Data,
|
|
32
|
+
) => {
|
|
33
|
+
const {
|
|
34
|
+
workspaceInvitationId,
|
|
35
|
+
workspaceId,
|
|
36
|
+
accountId,
|
|
37
|
+
workspaceToken,
|
|
38
|
+
userToken,
|
|
39
|
+
} = data;
|
|
40
|
+
|
|
41
|
+
return aggregate(
|
|
42
|
+
`${data.name}WorkspaceInvitations`,
|
|
43
|
+
workspaceInvitationId,
|
|
44
|
+
{
|
|
45
|
+
workspaceId,
|
|
46
|
+
invitedBy: accountId,
|
|
47
|
+
role: string(),
|
|
48
|
+
token: string(),
|
|
49
|
+
email: string().optional(),
|
|
50
|
+
workspaceName: string(),
|
|
51
|
+
workspaceType: string(),
|
|
52
|
+
status: string(), // "pending" | "accepted" | "revoked"
|
|
53
|
+
createdAt: date(),
|
|
54
|
+
expiresAt: date(),
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
.publicEvent(
|
|
58
|
+
"invitationCreated",
|
|
59
|
+
{
|
|
60
|
+
workspaceInvitationId,
|
|
61
|
+
workspaceId,
|
|
62
|
+
invitedBy: accountId,
|
|
63
|
+
role: string(),
|
|
64
|
+
token: string(),
|
|
65
|
+
email: string().optional(),
|
|
66
|
+
workspaceName: string(),
|
|
67
|
+
workspaceType: string(),
|
|
68
|
+
expiresAt: date(),
|
|
69
|
+
},
|
|
70
|
+
async (ctx, event) => {
|
|
71
|
+
const p = event.payload;
|
|
72
|
+
await ctx.set(p.workspaceInvitationId, {
|
|
73
|
+
workspaceId: p.workspaceId,
|
|
74
|
+
invitedBy: p.invitedBy,
|
|
75
|
+
role: p.role,
|
|
76
|
+
token: p.token,
|
|
77
|
+
email: p.email,
|
|
78
|
+
workspaceName: p.workspaceName,
|
|
79
|
+
workspaceType: p.workspaceType,
|
|
80
|
+
status: "pending",
|
|
81
|
+
createdAt: event.createdAt,
|
|
82
|
+
expiresAt: p.expiresAt,
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
.publicEvent(
|
|
88
|
+
"invitationAccepted",
|
|
89
|
+
{
|
|
90
|
+
workspaceInvitationId,
|
|
91
|
+
workspaceId,
|
|
92
|
+
acceptedBy: accountId,
|
|
93
|
+
role: string(),
|
|
94
|
+
workspaceName: string(),
|
|
95
|
+
workspaceType: string(),
|
|
96
|
+
},
|
|
97
|
+
async (ctx, event) => {
|
|
98
|
+
await ctx.modify(event.payload.workspaceInvitationId, {
|
|
99
|
+
status: "accepted",
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
.publicEvent(
|
|
105
|
+
"invitationRevoked",
|
|
106
|
+
{ workspaceInvitationId },
|
|
107
|
+
async (ctx, event) => {
|
|
108
|
+
await ctx.modify(event.payload.workspaceInvitationId, {
|
|
109
|
+
status: "revoked",
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
.mutateMethod(
|
|
115
|
+
"createInvitation",
|
|
116
|
+
{
|
|
117
|
+
params: {
|
|
118
|
+
workspaceId,
|
|
119
|
+
role: string(),
|
|
120
|
+
workspaceName: string(),
|
|
121
|
+
workspaceType: string(),
|
|
122
|
+
email: string().optional(),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
ONLY_SERVER &&
|
|
126
|
+
(async (ctx, params) => {
|
|
127
|
+
const invId = workspaceInvitationId.generate();
|
|
128
|
+
const token = generateInviteToken();
|
|
129
|
+
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); // 7 days
|
|
130
|
+
|
|
131
|
+
await ctx.invitationCreated.emit({
|
|
132
|
+
workspaceInvitationId: invId,
|
|
133
|
+
workspaceId: params.workspaceId,
|
|
134
|
+
invitedBy: ctx.$auth.params.accountId,
|
|
135
|
+
role: params.role,
|
|
136
|
+
token,
|
|
137
|
+
email: params.email,
|
|
138
|
+
workspaceName: params.workspaceName,
|
|
139
|
+
workspaceType: params.workspaceType,
|
|
140
|
+
expiresAt,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return { workspaceInvitationId: invId, token };
|
|
144
|
+
}),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
.mutateMethod(
|
|
148
|
+
"acceptInvitation",
|
|
149
|
+
{ params: { token: string() } },
|
|
150
|
+
ONLY_SERVER &&
|
|
151
|
+
(async (ctx, params) => {
|
|
152
|
+
const invitation = await ctx.$query.findOne({
|
|
153
|
+
token: params.token,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (!invitation) {
|
|
157
|
+
return { error: "INVITATION_NOT_FOUND" as const };
|
|
158
|
+
}
|
|
159
|
+
if (invitation.status !== "pending") {
|
|
160
|
+
return { error: "INVITATION_NOT_VALID" as const };
|
|
161
|
+
}
|
|
162
|
+
if (new Date(invitation.expiresAt) < new Date()) {
|
|
163
|
+
return { error: "INVITATION_EXPIRED" as const };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Emit accepted event — WorkspaceMember handles adding the member
|
|
167
|
+
await ctx.invitationAccepted.emit({
|
|
168
|
+
workspaceInvitationId: invitation._id,
|
|
169
|
+
workspaceId: invitation.workspaceId,
|
|
170
|
+
acceptedBy: ctx.$auth.params.accountId,
|
|
171
|
+
role: invitation.role,
|
|
172
|
+
workspaceName: invitation.workspaceName,
|
|
173
|
+
workspaceType: invitation.workspaceType,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Generate workspace token for the new member
|
|
177
|
+
const wsToken = workspaceToken.generateJWT({
|
|
178
|
+
accountId: ctx.$auth.params.accountId,
|
|
179
|
+
workspaceId: invitation.workspaceId,
|
|
180
|
+
role: invitation.role,
|
|
181
|
+
workspaceType: invitation.workspaceType,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
success: true,
|
|
186
|
+
token: wsToken,
|
|
187
|
+
workspaceId: invitation.workspaceId,
|
|
188
|
+
};
|
|
189
|
+
}),
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
.mutateMethod(
|
|
193
|
+
"revokeInvitation",
|
|
194
|
+
{ params: { workspaceInvitationId } },
|
|
195
|
+
ONLY_SERVER &&
|
|
196
|
+
(async (ctx, params) => {
|
|
197
|
+
const invitation = await ctx.$query.findOne({
|
|
198
|
+
_id: params.workspaceInvitationId,
|
|
199
|
+
});
|
|
200
|
+
if (!invitation || invitation.status !== "pending") {
|
|
201
|
+
return { error: "INVITATION_NOT_VALID" as const };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
await ctx.invitationRevoked.emit({
|
|
205
|
+
workspaceInvitationId: params.workspaceInvitationId,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return { success: true };
|
|
209
|
+
}),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
.protectBy(userToken, (p: any) => ({ invitedBy: p.accountId }))
|
|
213
|
+
.clientQuery("getByWorkspace", async (ctx) => ctx.$query.find({}))
|
|
214
|
+
;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export type WorkspaceInvitationAggregate<
|
|
218
|
+
Data extends WorkspaceInvitationAggregateData = WorkspaceInvitationAggregateData,
|
|
219
|
+
> = ReturnType<typeof createWorkspaceInvitationAggregate<Data>>;
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
aggregate,
|
|
3
3
|
date,
|
|
4
4
|
string,
|
|
5
|
-
type
|
|
5
|
+
type ArcAggregateElement,
|
|
6
6
|
type ArcId,
|
|
7
7
|
} from "@arcote.tech/arc";
|
|
8
8
|
import type { Token } from "@arcote.tech/arc-auth";
|
|
@@ -15,7 +15,8 @@ export type WorkspaceMemberAggregateData = {
|
|
|
15
15
|
accountId: ArcId<any>;
|
|
16
16
|
workspaceToken: WorkspaceToken;
|
|
17
17
|
userToken: Token;
|
|
18
|
-
WorkspaceAggregate:
|
|
18
|
+
WorkspaceAggregate: ArcAggregateElement<any, any, any, any, any, any>;
|
|
19
|
+
WorkspaceInvitationAggregate?: ArcAggregateElement<any, any, any, any, any, any>;
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
export const createWorkspaceMemberAggregate = <
|
|
@@ -30,11 +31,12 @@ export const createWorkspaceMemberAggregate = <
|
|
|
30
31
|
workspaceToken,
|
|
31
32
|
userToken,
|
|
32
33
|
WorkspaceAggregate,
|
|
34
|
+
WorkspaceInvitationAggregate,
|
|
33
35
|
} = data;
|
|
34
36
|
|
|
35
37
|
const workspaceCreatedEvent = WorkspaceAggregate.getEvent("workspaceCreated");
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
let Constructor = aggregate(
|
|
38
40
|
`${data.name}WorkspaceMembers`,
|
|
39
41
|
workspaceMemberId,
|
|
40
42
|
{
|
|
@@ -109,7 +111,48 @@ export const createWorkspaceMemberAggregate = <
|
|
|
109
111
|
});
|
|
110
112
|
})
|
|
111
113
|
|
|
112
|
-
|
|
114
|
+
// Remove all members when workspace is archived
|
|
115
|
+
.handleEvent(WorkspaceAggregate.getEvent("workspaceArchived"), async (ctx, event) => {
|
|
116
|
+
const members = await ctx.find({
|
|
117
|
+
where: { workspaceId: event.payload.workspaceId },
|
|
118
|
+
});
|
|
119
|
+
for (const member of members) {
|
|
120
|
+
await ctx.remove(member._id);
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
// Sync workspace name to all members when workspace is renamed
|
|
125
|
+
.handleEvent(WorkspaceAggregate.getEvent("workspaceRenamed"), async (ctx, event) => {
|
|
126
|
+
const members = await ctx.find({
|
|
127
|
+
where: { workspaceId: event.payload.workspaceId },
|
|
128
|
+
});
|
|
129
|
+
for (const member of members) {
|
|
130
|
+
await ctx.modify(member._id, {
|
|
131
|
+
workspaceName: event.payload.name,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
;
|
|
137
|
+
|
|
138
|
+
// Auto-add member when invitation is accepted
|
|
139
|
+
if (WorkspaceInvitationAggregate) {
|
|
140
|
+
const invitationAcceptedEvent = WorkspaceInvitationAggregate.getEvent("invitationAccepted");
|
|
141
|
+
Constructor = Constructor.handleEvent(invitationAcceptedEvent, async (ctx, event) => {
|
|
142
|
+
const p = event.payload;
|
|
143
|
+
const memberId = workspaceMemberId.generate();
|
|
144
|
+
await ctx.set(memberId, {
|
|
145
|
+
workspaceId: p.workspaceId,
|
|
146
|
+
accountId: p.acceptedBy,
|
|
147
|
+
role: p.role,
|
|
148
|
+
workspaceName: p.workspaceName,
|
|
149
|
+
workspaceType: p.workspaceType,
|
|
150
|
+
joinedAt: event.createdAt,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
Constructor = Constructor.mutateMethod(
|
|
113
156
|
"addMember",
|
|
114
157
|
{
|
|
115
158
|
params: {
|
|
@@ -205,12 +248,12 @@ export const createWorkspaceMemberAggregate = <
|
|
|
205
248
|
)
|
|
206
249
|
|
|
207
250
|
.protectBy(userToken, (params: any) => ({ accountId: params.accountId }))
|
|
251
|
+
.protectBy(workspaceToken, (params: any) => ({ workspaceId: params.workspaceId }))
|
|
208
252
|
.clientQuery("getAll", async (ctx) => ctx.$query.find({}))
|
|
209
|
-
.
|
|
210
|
-
|
|
211
|
-
class WorkspaceMember extends Constructor {}
|
|
253
|
+
.clientQuery("getByWorkspace", async (ctx) => ctx.$query.find({}))
|
|
254
|
+
;
|
|
212
255
|
|
|
213
|
-
return
|
|
256
|
+
return Constructor;
|
|
214
257
|
};
|
|
215
258
|
|
|
216
259
|
export type WorkspaceMemberAggregate<
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aggregate, date, string, type ArcId } from "@arcote.tech/arc";
|
|
1
|
+
import { aggregate, boolean, date, string, type ArcId } from "@arcote.tech/arc";
|
|
2
2
|
import type { WorkspaceToken } from "../tokens/workspace-token";
|
|
3
3
|
|
|
4
4
|
export type WorkspaceAggregateData = {
|
|
@@ -20,6 +20,7 @@ export const createWorkspaceAggregate = <
|
|
|
20
20
|
name: string().minLength(1).maxLength(100),
|
|
21
21
|
type: string(),
|
|
22
22
|
ownerId: accountId,
|
|
23
|
+
isArchived: boolean(),
|
|
23
24
|
createdAt: date(),
|
|
24
25
|
})
|
|
25
26
|
.publicEvent(
|
|
@@ -37,6 +38,7 @@ export const createWorkspaceAggregate = <
|
|
|
37
38
|
name,
|
|
38
39
|
type,
|
|
39
40
|
ownerId,
|
|
41
|
+
isArchived: false,
|
|
40
42
|
createdAt: event.createdAt,
|
|
41
43
|
});
|
|
42
44
|
},
|
|
@@ -114,8 +116,38 @@ export const createWorkspaceAggregate = <
|
|
|
114
116
|
}),
|
|
115
117
|
)
|
|
116
118
|
|
|
119
|
+
.publicEvent(
|
|
120
|
+
"workspaceArchived",
|
|
121
|
+
{ workspaceId },
|
|
122
|
+
async (ctx, event) => {
|
|
123
|
+
await ctx.modify(event.payload.workspaceId, {
|
|
124
|
+
isArchived: true,
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
.mutateMethod(
|
|
130
|
+
"archive",
|
|
131
|
+
{ params: { workspaceId } },
|
|
132
|
+
ONLY_SERVER &&
|
|
133
|
+
(async (ctx, params) => {
|
|
134
|
+
const existing = await ctx.$query.findOne({
|
|
135
|
+
_id: params.workspaceId,
|
|
136
|
+
});
|
|
137
|
+
if (!existing) {
|
|
138
|
+
return { error: "WORKSPACE_NOT_FOUND" as const };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
await ctx.workspaceArchived.emit({
|
|
142
|
+
workspaceId: params.workspaceId,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return { success: true };
|
|
146
|
+
}),
|
|
147
|
+
)
|
|
148
|
+
|
|
117
149
|
.clientQuery("getAll", async (ctx) => ctx.$query.find({}))
|
|
118
|
-
|
|
150
|
+
;
|
|
119
151
|
};
|
|
120
152
|
|
|
121
153
|
export type WorkspaceAggregate<
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { id } from "@arcote.tech/arc";
|
|
2
|
+
|
|
3
|
+
export type WorkspaceInvitationIdData = {
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const createWorkspaceInvitationId = <const Data extends WorkspaceInvitationIdData>(
|
|
8
|
+
data: Readonly<Data>,
|
|
9
|
+
) => id(`${data.name}WorkspaceInvitation`);
|
|
10
|
+
|
|
11
|
+
export type WorkspaceInvitationId<Data extends WorkspaceInvitationIdData = WorkspaceInvitationIdData> =
|
|
12
|
+
ReturnType<typeof createWorkspaceInvitationId<Data>>;
|
package/src/index.ts
CHANGED
|
@@ -6,12 +6,16 @@ export { createWorkspaceAggregate } from "./aggregates/workspace";
|
|
|
6
6
|
export type { WorkspaceAggregate } from "./aggregates/workspace";
|
|
7
7
|
export { createWorkspaceMemberAggregate } from "./aggregates/workspace-member";
|
|
8
8
|
export type { WorkspaceMemberAggregate } from "./aggregates/workspace-member";
|
|
9
|
+
export { createWorkspaceInvitationAggregate } from "./aggregates/workspace-invitation";
|
|
10
|
+
export type { WorkspaceInvitationAggregate } from "./aggregates/workspace-invitation";
|
|
9
11
|
|
|
10
12
|
// --- ID factories & types ---
|
|
11
13
|
export { createWorkspaceId } from "./ids/workspace";
|
|
12
14
|
export type { WorkspaceId } from "./ids/workspace";
|
|
13
15
|
export { createWorkspaceMemberId } from "./ids/workspace-member";
|
|
14
16
|
export type { WorkspaceMemberId } from "./ids/workspace-member";
|
|
17
|
+
export { createWorkspaceInvitationId } from "./ids/workspace-invitation";
|
|
18
|
+
export type { WorkspaceInvitationId } from "./ids/workspace-invitation";
|
|
15
19
|
|
|
16
20
|
// --- Token factory & type ---
|
|
17
21
|
export { createWorkspaceToken } from "./tokens/workspace-token";
|
package/src/workspace-builder.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
|
-
aggregateContextElement,
|
|
3
2
|
context,
|
|
4
3
|
type ArcAggregateElement,
|
|
5
4
|
type ArcContextElement,
|
|
6
|
-
type AggregateConstructorAny,
|
|
7
5
|
} from "@arcote.tech/arc";
|
|
8
6
|
import type { AccountId, Token } from "@arcote.tech/arc-auth";
|
|
9
7
|
import { createWorkspaceId } from "./ids/workspace";
|
|
10
8
|
import { createWorkspaceMemberId } from "./ids/workspace-member";
|
|
9
|
+
import { createWorkspaceInvitationId } from "./ids/workspace-invitation";
|
|
11
10
|
import { createWorkspaceToken } from "./tokens/workspace-token";
|
|
12
11
|
import { createWorkspaceAggregate } from "./aggregates/workspace";
|
|
13
12
|
import { createWorkspaceMemberAggregate } from "./aggregates/workspace-member";
|
|
13
|
+
import { createWorkspaceInvitationAggregate } from "./aggregates/workspace-invitation";
|
|
14
14
|
|
|
15
15
|
export class WorkspaceBuilder<
|
|
16
16
|
WsId,
|
|
17
17
|
WsMemberId,
|
|
18
|
+
WsInvId,
|
|
18
19
|
WsToken,
|
|
19
|
-
Workspace extends
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
WorkspaceMemberEl extends ArcAggregateElement<WorkspaceMember>,
|
|
20
|
+
Workspace extends ArcAggregateElement,
|
|
21
|
+
WorkspaceMember extends ArcAggregateElement,
|
|
22
|
+
WorkspaceInvitation extends ArcAggregateElement,
|
|
23
23
|
Types extends readonly string[],
|
|
24
24
|
Elements extends ArcContextElement<any>[],
|
|
25
25
|
> {
|
|
@@ -27,11 +27,11 @@ export class WorkspaceBuilder<
|
|
|
27
27
|
private readonly _name: string,
|
|
28
28
|
readonly workspaceId: WsId,
|
|
29
29
|
readonly workspaceMemberId: WsMemberId,
|
|
30
|
+
readonly workspaceInvitationId: WsInvId,
|
|
30
31
|
readonly workspaceToken: WsToken,
|
|
31
32
|
readonly Workspace: Workspace,
|
|
32
|
-
readonly workspaceElement: WorkspaceEl,
|
|
33
33
|
readonly WorkspaceMember: WorkspaceMember,
|
|
34
|
-
readonly
|
|
34
|
+
readonly WorkspaceInvitation: WorkspaceInvitation,
|
|
35
35
|
readonly types: Types,
|
|
36
36
|
readonly elements: Elements,
|
|
37
37
|
) {}
|
|
@@ -41,16 +41,17 @@ export class WorkspaceBuilder<
|
|
|
41
41
|
context: context(this.elements),
|
|
42
42
|
workspaceId: this.workspaceId,
|
|
43
43
|
workspaceMemberId: this.workspaceMemberId,
|
|
44
|
+
workspaceInvitationId: this.workspaceInvitationId,
|
|
44
45
|
workspaceToken: this.workspaceToken,
|
|
45
46
|
Workspace: this.Workspace,
|
|
46
47
|
WorkspaceMember: this.WorkspaceMember,
|
|
48
|
+
WorkspaceInvitation: this.WorkspaceInvitation,
|
|
47
49
|
types: this.types,
|
|
48
|
-
// Protection helpers
|
|
49
50
|
isOwner: (params: { role: string }) => params.role === "owner",
|
|
50
51
|
isMember: (params: { role: string }) =>
|
|
51
52
|
params.role === "member" || params.role === "owner",
|
|
52
|
-
isType: (
|
|
53
|
-
params
|
|
53
|
+
isType: (...types: string[]) => (token: { params?: { workspaceType?: string } }) =>
|
|
54
|
+
types.includes(token.params?.workspaceType ?? ""),
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
57
|
}
|
|
@@ -68,6 +69,7 @@ export function workspace<
|
|
|
68
69
|
}) {
|
|
69
70
|
const workspaceId = createWorkspaceId({ name: config.name });
|
|
70
71
|
const workspaceMemberId = createWorkspaceMemberId({ name: config.name });
|
|
72
|
+
const workspaceInvitationId = createWorkspaceInvitationId({ name: config.name });
|
|
71
73
|
const workspaceToken = createWorkspaceToken({
|
|
72
74
|
name: config.name,
|
|
73
75
|
secret: config.secret,
|
|
@@ -80,7 +82,15 @@ export function workspace<
|
|
|
80
82
|
accountId: config.accountId,
|
|
81
83
|
workspaceToken,
|
|
82
84
|
});
|
|
83
|
-
|
|
85
|
+
|
|
86
|
+
const WorkspaceInvitation = createWorkspaceInvitationAggregate({
|
|
87
|
+
name: config.name,
|
|
88
|
+
workspaceInvitationId,
|
|
89
|
+
workspaceId,
|
|
90
|
+
accountId: config.accountId,
|
|
91
|
+
workspaceToken,
|
|
92
|
+
userToken: config.userToken,
|
|
93
|
+
});
|
|
84
94
|
|
|
85
95
|
const WorkspaceMember = createWorkspaceMemberAggregate({
|
|
86
96
|
name: config.name,
|
|
@@ -90,21 +100,19 @@ export function workspace<
|
|
|
90
100
|
workspaceToken,
|
|
91
101
|
userToken: config.userToken,
|
|
92
102
|
WorkspaceAggregate: Workspace,
|
|
103
|
+
WorkspaceInvitationAggregate: WorkspaceInvitation,
|
|
93
104
|
});
|
|
94
|
-
const workspaceMemberElement = aggregateContextElement(WorkspaceMember);
|
|
95
|
-
|
|
96
|
-
const elements = [workspaceElement, workspaceMemberElement];
|
|
97
105
|
|
|
98
106
|
return new WorkspaceBuilder(
|
|
99
107
|
config.name,
|
|
100
108
|
workspaceId,
|
|
101
109
|
workspaceMemberId,
|
|
110
|
+
workspaceInvitationId,
|
|
102
111
|
workspaceToken,
|
|
103
112
|
Workspace,
|
|
104
|
-
workspaceElement,
|
|
105
113
|
WorkspaceMember,
|
|
106
|
-
|
|
114
|
+
WorkspaceInvitation,
|
|
107
115
|
config.types,
|
|
108
|
-
|
|
116
|
+
[Workspace, WorkspaceMember, WorkspaceInvitation],
|
|
109
117
|
);
|
|
110
118
|
}
|