@fonderie/workspaces 1.2.2 → 2.1.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/brain/signatures.md +1 -0
- package/dist/index.cjs +42 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +42 -28
- package/dist/index.js.map +1 -1
- package/package.json +93 -94
package/brain/signatures.md
CHANGED
|
@@ -15,6 +15,7 @@ new WorkspacesModule(store: IStoreAdapter, config?: IWorkspacesConfig, bus?: Eve
|
|
|
15
15
|
interface IWorkspacesConfig {
|
|
16
16
|
invitationTtl?: string;
|
|
17
17
|
personalWorkspace?: boolean;
|
|
18
|
+
routes?: Partial<Record<WorkspaceRouteId, WorkspaceRouteOverride>>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
type WorkspacesMessageKey = (typeof MESSAGE_KEYS)[keyof typeof MESSAGE_KEYS];
|
package/dist/index.cjs
CHANGED
|
@@ -1061,7 +1061,6 @@ function roleController(store) {
|
|
|
1061
1061
|
// src/controllers/invitation.controller.ts
|
|
1062
1062
|
var import_core5 = require("@fonderie/core");
|
|
1063
1063
|
var import_events = require("@fonderie/events");
|
|
1064
|
-
var import_billing = require("@fonderie/billing");
|
|
1065
1064
|
|
|
1066
1065
|
// src/services/invitations.ts
|
|
1067
1066
|
var import_node_crypto = require("crypto");
|
|
@@ -1183,6 +1182,12 @@ var InvitationModel = class {
|
|
|
1183
1182
|
};
|
|
1184
1183
|
|
|
1185
1184
|
// src/controllers/invitation.controller.ts
|
|
1185
|
+
function seatLimitFromMeta(ctx) {
|
|
1186
|
+
const billing = ctx.meta["billing"];
|
|
1187
|
+
const status = billing?.statuses?.["seats"];
|
|
1188
|
+
if (!status || status.type === "feature" || typeof status.limit !== "number") return null;
|
|
1189
|
+
return status.limit;
|
|
1190
|
+
}
|
|
1186
1191
|
function invitationController(store, ttl, bus) {
|
|
1187
1192
|
const invitations = new InvitationModel(store);
|
|
1188
1193
|
return {
|
|
@@ -1212,7 +1217,7 @@ function invitationController(store, ttl, bus) {
|
|
|
1212
1217
|
return (0, import_core5.setApiResponse)(import_core5.HTTP.UNPROCESSABLE, "INVALID_PARAMETER", "email is required for every invite");
|
|
1213
1218
|
}
|
|
1214
1219
|
}
|
|
1215
|
-
const seatLimit = (
|
|
1220
|
+
const seatLimit = seatLimitFromMeta(ctx);
|
|
1216
1221
|
if (seatLimit !== null) {
|
|
1217
1222
|
const [countRow] = await store.query(
|
|
1218
1223
|
`SELECT COUNT(*) AS count FROM fonderie_role_user_workspaces
|
|
@@ -1302,38 +1307,45 @@ function buildWorkspaceRoutes(store, config, bus) {
|
|
|
1302
1307
|
const member = memberController(store);
|
|
1303
1308
|
const role = roleController(store);
|
|
1304
1309
|
const invitation = invitationController(store, ttl, bus);
|
|
1310
|
+
const R = (id, method, path, ...handlers) => {
|
|
1311
|
+
const o = config.routes?.[id];
|
|
1312
|
+
if (!o) return [method, path, ...handlers];
|
|
1313
|
+
if (typeof o === "string") return [method, o, ...handlers];
|
|
1314
|
+
return [o.method ?? method, o.path ?? path, ...handlers];
|
|
1315
|
+
};
|
|
1305
1316
|
return [
|
|
1306
1317
|
// ── Workspace creation + listing (no workspace context required)
|
|
1307
|
-
|
|
1308
|
-
|
|
1318
|
+
R("createWorkspace", "POST", "/workspaces", import_middlewares.requireAuth, (0, import_middlewares.validate)(createWorkspaceSchema), workspace.create),
|
|
1319
|
+
R("listWorkspaces", "GET", "/workspaces", import_middlewares.requireAuth, workspace.list),
|
|
1309
1320
|
// ── Members (workspace resolved from X-Workspace-ID header)
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1321
|
+
R("listMembers", "GET", "/workspaces/members", import_middlewares.requireAuth, wsCtx, member.list),
|
|
1322
|
+
R("removeMember", "DELETE", "/workspaces/members/:userId", import_middlewares.requireAuth, wsCtx, member.remove),
|
|
1323
|
+
R("getMemberRoles", "GET", "/workspaces/members/:userId/roles", import_middlewares.requireAuth, wsCtx, member.getUserRoles),
|
|
1324
|
+
R("addMemberRole", "POST", "/workspaces/members/:userId/roles", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(addMemberRoleSchema), member.addRole),
|
|
1325
|
+
R("removeMemberRole", "DELETE", "/workspaces/members/:userId/roles/:roleId", import_middlewares.requireAuth, wsCtx, member.removeRole),
|
|
1315
1326
|
// ── Invitations
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1327
|
+
R("listInvitations", "GET", "/workspaces/invitations", import_middlewares.requireAuth, wsCtx, invitation.list),
|
|
1328
|
+
R("invite", "POST", "/workspaces/invitations", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(createInvitationsSchema), invitation.invite),
|
|
1329
|
+
R("cancelInvitation", "DELETE", "/workspaces/invitations/:inviteId", import_middlewares.requireAuth, wsCtx, invitation.cancel),
|
|
1330
|
+
R("acceptInvitation", "POST", "/workspaces/invitations/accept", import_middlewares.requireAuth, (0, import_middlewares.validate)(acceptInvitationSchema), invitation.accept),
|
|
1320
1331
|
// ── Roles
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1332
|
+
R("createRole", "POST", "/workspaces/roles", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(createRoleSchema), role.create),
|
|
1333
|
+
R("listRoles", "GET", "/workspaces/roles", import_middlewares.requireAuth, wsCtx, role.list),
|
|
1334
|
+
R("getRole", "GET", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, role.get),
|
|
1335
|
+
R("updateRole", "PUT", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateRoleSchema), role.update),
|
|
1336
|
+
R("removeRole", "DELETE", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, role.remove),
|
|
1337
|
+
R("setRolePermissions", "POST", "/workspaces/roles/:roleId/permissions", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(setRolePermissionsSchema), role.setPermissions),
|
|
1327
1338
|
// ── Workspace lifecycle
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1339
|
+
R("archive", "POST", "/workspaces/archive", import_middlewares.requireAuth, wsCtx, workspace.archive),
|
|
1340
|
+
R("restore", "POST", "/workspaces/restore", import_middlewares.requireAuth, wsCtx, workspace.restore),
|
|
1341
|
+
R("getSettings", "GET", "/workspaces/settings", import_middlewares.requireAuth, wsCtx, workspace.getSettings),
|
|
1342
|
+
R("updateSettings", "PUT", "/workspaces/settings", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateSettingsSchema), workspace.updateSettings),
|
|
1332
1343
|
// ── Path-based lookup by ID (admin / cross-workspace use)
|
|
1333
|
-
|
|
1334
|
-
// ── Update current workspace — ID
|
|
1335
|
-
// (or personal
|
|
1336
|
-
|
|
1344
|
+
R("getWorkspace", "GET", "/workspaces/:id", import_middlewares.requireAuth, wsCtx, workspace.get),
|
|
1345
|
+
// ── Update current workspace — ID from :id path param (wsCtx) or the
|
|
1346
|
+
// X-Workspace-ID header (or personal-workspace fallback when absent). Set
|
|
1347
|
+
// routes.updateWorkspace = '/workspaces/:id' to match a path-id frontend.
|
|
1348
|
+
R("updateWorkspace", "PUT", "/workspaces", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateWorkspaceSchema), workspace.update)
|
|
1337
1349
|
];
|
|
1338
1350
|
}
|
|
1339
1351
|
|
|
@@ -1349,7 +1361,9 @@ var WorkspacesModule = class {
|
|
|
1349
1361
|
config;
|
|
1350
1362
|
bus;
|
|
1351
1363
|
name = "@fonderie/workspaces";
|
|
1352
|
-
|
|
1364
|
+
// billing is OPTIONAL — seat limits activate if it's registered (read via
|
|
1365
|
+
// ctx.meta['billing']), otherwise invitations are unlimited. Not a hard dep.
|
|
1366
|
+
deps = ["@fonderie/auth"];
|
|
1353
1367
|
install(app) {
|
|
1354
1368
|
if (this.bus && this.config.personalWorkspace !== false) {
|
|
1355
1369
|
this.bus.on(
|