@fonderie/workspaces 4.0.0 → 5.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/README.md +2 -2
- package/brain/outcomes.md +1 -0
- package/brain/signatures.md +6 -0
- package/dist/index.cjs +66 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +62 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ typed `EVENT_KEYS` are exported for your handlers and event consumers.
|
|
|
34
34
|
You've shipped this plumbing before — auth, teams, billing, messaging —
|
|
35
35
|
and the next project will ask for it again. Fonderie packages it once:
|
|
36
36
|
plain TypeScript modules for
|
|
37
|
-
[`@fonderie/core`](https://github.com/
|
|
37
|
+
[`@fonderie/core`](https://github.com/fonderiejs/sdk/tree/main/packages/core),
|
|
38
38
|
PostgreSQL-backed, self-hosted, MIT. No external control plane, no
|
|
39
39
|
per-seat anything. Register the modules you need; skip the ones you don't.
|
|
40
40
|
|
|
@@ -43,7 +43,7 @@ and role containers — the bricks scope their data by the workspace context
|
|
|
43
43
|
this one provides.
|
|
44
44
|
|
|
45
45
|
Browse the whole set at
|
|
46
|
-
[
|
|
46
|
+
[fonderiejs/sdk](https://github.com/fonderiejs/sdk) · follow
|
|
47
47
|
[@fonderiejs](https://x.com/fonderiejs)
|
|
48
48
|
|
|
49
49
|
## License
|
package/brain/outcomes.md
CHANGED
|
@@ -102,6 +102,7 @@ INSERT INTO fonderie_roles (name, workspace_id, is_system, description) VALUES (
|
|
|
102
102
|
| DELETE | `/workspaces/roles/:roleId` | `requireAuth → wsCtx → role.remove` |
|
|
103
103
|
| GET | `/workspaces/roles/:roleId` | `requireAuth → wsCtx → role.get` |
|
|
104
104
|
| PUT | `/workspaces/roles/:roleId` | `requireAuth → wsCtx → validate(updateRoleSchema) → role.update` |
|
|
105
|
+
| GET | `/workspaces/roles/:roleId/permissions` | `requireAuth → wsCtx → role.getPermissions` |
|
|
105
106
|
| POST | `/workspaces/roles/:roleId/permissions` | `requireAuth → wsCtx → validate(setRolePermissionsSchema) → role.setPermissions` |
|
|
106
107
|
| GET | `/workspaces/settings` | `requireAuth → wsCtx → workspace.getSettings` |
|
|
107
108
|
| PUT | `/workspaces/settings` | `requireAuth → wsCtx → validate(updateSettingsSchema) → workspace.updateSettings` |
|
package/brain/signatures.md
CHANGED
|
@@ -204,4 +204,10 @@ interface IImportMembership {
|
|
|
204
204
|
confirmed?: boolean;
|
|
205
205
|
createdAt?: Date;
|
|
206
206
|
}
|
|
207
|
+
|
|
208
|
+
function deleteUserData(store: IStoreAdapter, userId: string): Promise<number>
|
|
209
|
+
|
|
210
|
+
function exportUserData(store: IStoreAdapter, userId: string): Promise<unknown>
|
|
211
|
+
|
|
212
|
+
function workspaceExportContributor(store: IStoreAdapter): { name: string; collect: (userId: string) => Promise<unknown>; }
|
|
207
213
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,8 @@ __export(index_exports, {
|
|
|
23
23
|
EVENT_KEYS: () => EVENT_KEYS,
|
|
24
24
|
MESSAGE_KEYS: () => MESSAGE_KEYS,
|
|
25
25
|
WorkspacesModule: () => WorkspacesModule,
|
|
26
|
+
deleteUserData: () => deleteUserData,
|
|
27
|
+
exportUserData: () => exportUserData,
|
|
26
28
|
importMembership: () => importMembership,
|
|
27
29
|
importRole: () => importRole,
|
|
28
30
|
importWorkspace: () => importWorkspace,
|
|
@@ -33,7 +35,8 @@ __export(index_exports, {
|
|
|
33
35
|
toRoleDTO: () => toRoleDTO,
|
|
34
36
|
toSettingsDTO: () => toSettingsDTO,
|
|
35
37
|
toWorkspaceDTO: () => toWorkspaceDTO,
|
|
36
|
-
withWorkspace: () => withWorkspace
|
|
38
|
+
withWorkspace: () => withWorkspace,
|
|
39
|
+
workspaceExportContributor: () => workspaceExportContributor
|
|
37
40
|
});
|
|
38
41
|
module.exports = __toCommonJS(index_exports);
|
|
39
42
|
|
|
@@ -619,6 +622,19 @@ async function setRolePermissions(roleId, workspaceId, permissions, store) {
|
|
|
619
622
|
}
|
|
620
623
|
});
|
|
621
624
|
}
|
|
625
|
+
async function getRolePermissions(roleId, workspaceId, store) {
|
|
626
|
+
return store.query(
|
|
627
|
+
`SELECT permission_key AS "permissionKey",
|
|
628
|
+
can_create AS "canCreate",
|
|
629
|
+
can_read AS "canRead",
|
|
630
|
+
can_update AS "canUpdate",
|
|
631
|
+
can_delete AS "canDelete"
|
|
632
|
+
FROM fonderie_role_permissions
|
|
633
|
+
WHERE role_id = $1 AND workspace_id = $2
|
|
634
|
+
ORDER BY permission_key`,
|
|
635
|
+
[roleId, workspaceId]
|
|
636
|
+
);
|
|
637
|
+
}
|
|
622
638
|
|
|
623
639
|
// src/models/role.model.ts
|
|
624
640
|
var RoleModel = class {
|
|
@@ -647,6 +663,9 @@ var RoleModel = class {
|
|
|
647
663
|
setPermissions(roleId, workspaceId, permissions) {
|
|
648
664
|
return setRolePermissions(roleId, workspaceId, permissions, this.store);
|
|
649
665
|
}
|
|
666
|
+
getPermissions(roleId, workspaceId) {
|
|
667
|
+
return getRolePermissions(roleId, workspaceId, this.store);
|
|
668
|
+
}
|
|
650
669
|
};
|
|
651
670
|
|
|
652
671
|
// src/dtos/workspace.ts
|
|
@@ -1027,6 +1046,24 @@ function roleController(store) {
|
|
|
1027
1046
|
await roles.delete(roleId, ctx.workspace.id);
|
|
1028
1047
|
return (0, import_core4.setApiResponse)(import_core4.HTTP.OK, "ROLE_DELETED", "Role deleted successfully.");
|
|
1029
1048
|
},
|
|
1049
|
+
async getPermissions(ctx) {
|
|
1050
|
+
if (!ctx.workspace) {
|
|
1051
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.NOT_FOUND, "NOT_FOUND", "Workspace not found");
|
|
1052
|
+
}
|
|
1053
|
+
const params = ctx.meta["params"];
|
|
1054
|
+
const roleId = params?.["roleId"];
|
|
1055
|
+
if (!roleId) {
|
|
1056
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.UNPROCESSABLE, "INVALID_PARAMETER", "roleId is required");
|
|
1057
|
+
}
|
|
1058
|
+
const role = await roles.findById(roleId);
|
|
1059
|
+
if (!role) {
|
|
1060
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.NOT_FOUND, "NOT_FOUND", "Role not found");
|
|
1061
|
+
}
|
|
1062
|
+
const permissions = await roles.getPermissions(roleId, ctx.workspace.id);
|
|
1063
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.OK, "PERMISSIONS_FETCHED", "Role permissions retrieved successfully.", {
|
|
1064
|
+
permissions
|
|
1065
|
+
});
|
|
1066
|
+
},
|
|
1030
1067
|
async setPermissions(ctx) {
|
|
1031
1068
|
if (!ctx.workspace) {
|
|
1032
1069
|
return (0, import_core4.setApiResponse)(import_core4.HTTP.NOT_FOUND, "NOT_FOUND", "Workspace not found");
|
|
@@ -1337,6 +1374,7 @@ function buildWorkspaceRoutes(store, config, bus) {
|
|
|
1337
1374
|
R("getRole", "GET", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, role.get),
|
|
1338
1375
|
R("updateRole", "PUT", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateRoleSchema), role.update),
|
|
1339
1376
|
R("removeRole", "DELETE", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, role.remove),
|
|
1377
|
+
R("getRolePermissions", "GET", "/workspaces/roles/:roleId/permissions", import_middlewares.requireAuth, wsCtx, role.getPermissions),
|
|
1340
1378
|
R("setRolePermissions", "POST", "/workspaces/roles/:roleId/permissions", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(setRolePermissionsSchema), role.setPermissions),
|
|
1341
1379
|
// ── Workspace lifecycle
|
|
1342
1380
|
R("archive", "POST", "/workspaces/archive", import_middlewares.requireAuth, wsCtx, workspace.archive),
|
|
@@ -1493,11 +1531,36 @@ async function importMembership(store, m) {
|
|
|
1493
1531
|
vals
|
|
1494
1532
|
);
|
|
1495
1533
|
}
|
|
1534
|
+
|
|
1535
|
+
// src/retention.ts
|
|
1536
|
+
async function deleteUserData(store, userId) {
|
|
1537
|
+
const rows = await store.query(
|
|
1538
|
+
`DELETE FROM fonderie_role_user_workspaces WHERE user_id = $1 RETURNING user_id`,
|
|
1539
|
+
[userId]
|
|
1540
|
+
);
|
|
1541
|
+
return rows.length;
|
|
1542
|
+
}
|
|
1543
|
+
async function exportUserData(store, userId) {
|
|
1544
|
+
const rows = await store.query(
|
|
1545
|
+
`SELECT ruw.workspace_id, ruw.role_id, r.name AS role_name
|
|
1546
|
+
FROM fonderie_role_user_workspaces ruw
|
|
1547
|
+
JOIN fonderie_roles r ON r.id = ruw.role_id
|
|
1548
|
+
WHERE ruw.user_id = $1 AND ruw.removed = false
|
|
1549
|
+
ORDER BY ruw.workspace_id`,
|
|
1550
|
+
[userId]
|
|
1551
|
+
);
|
|
1552
|
+
return { memberships: rows };
|
|
1553
|
+
}
|
|
1554
|
+
function workspaceExportContributor(store) {
|
|
1555
|
+
return { name: "workspaces", collect: (userId) => exportUserData(store, userId) };
|
|
1556
|
+
}
|
|
1496
1557
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1497
1558
|
0 && (module.exports = {
|
|
1498
1559
|
EVENT_KEYS,
|
|
1499
1560
|
MESSAGE_KEYS,
|
|
1500
1561
|
WorkspacesModule,
|
|
1562
|
+
deleteUserData,
|
|
1563
|
+
exportUserData,
|
|
1501
1564
|
importMembership,
|
|
1502
1565
|
importRole,
|
|
1503
1566
|
importWorkspace,
|
|
@@ -1508,6 +1571,7 @@ async function importMembership(store, m) {
|
|
|
1508
1571
|
toRoleDTO,
|
|
1509
1572
|
toSettingsDTO,
|
|
1510
1573
|
toWorkspaceDTO,
|
|
1511
|
-
withWorkspace
|
|
1574
|
+
withWorkspace,
|
|
1575
|
+
workspaceExportContributor
|
|
1512
1576
|
});
|
|
1513
1577
|
//# sourceMappingURL=index.cjs.map
|