@fonderie/workspaces 5.0.0 → 5.2.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 +11 -0
- package/dist/index.cjs +80 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -5
- package/dist/index.d.ts +25 -5
- package/dist/index.js +77 -11
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
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
|
@@ -106,6 +106,7 @@ interface IWorkspaceDTO {
|
|
|
106
106
|
isPersonal: boolean;
|
|
107
107
|
isArchived: boolean;
|
|
108
108
|
archivedAt: string;
|
|
109
|
+
archivedBy: string;
|
|
109
110
|
createdAt: string;
|
|
110
111
|
updatedAt: string;
|
|
111
112
|
}
|
|
@@ -126,6 +127,10 @@ interface IMemberDTO {
|
|
|
126
127
|
roleName: string;
|
|
127
128
|
confirmed: boolean;
|
|
128
129
|
createdAt: string;
|
|
130
|
+
email: string;
|
|
131
|
+
firstName: string;
|
|
132
|
+
lastName: string;
|
|
133
|
+
profileImageUrl: string;
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
interface IInvitationDTO {
|
|
@@ -204,4 +209,10 @@ interface IImportMembership {
|
|
|
204
209
|
confirmed?: boolean;
|
|
205
210
|
createdAt?: Date;
|
|
206
211
|
}
|
|
212
|
+
|
|
213
|
+
function deleteUserData(store: IStoreAdapter, userId: string): Promise<number>
|
|
214
|
+
|
|
215
|
+
function exportUserData(store: IStoreAdapter, userId: string): Promise<unknown>
|
|
216
|
+
|
|
217
|
+
function workspaceExportContributor(store: IStoreAdapter): { name: string; collect: (userId: string) => Promise<unknown>; }
|
|
207
218
|
```
|
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
|
|
|
@@ -75,10 +78,10 @@ var addressSchema = import_zod.z.object({
|
|
|
75
78
|
line1: import_zod.z.string().max(200).optional(),
|
|
76
79
|
line2: import_zod.z.string().max(200).optional(),
|
|
77
80
|
city: import_zod.z.string().max(100).optional(),
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
state: import_zod.z.string().max(100).optional(),
|
|
82
|
+
zip: import_zod.z.string().max(20).optional(),
|
|
80
83
|
country: import_zod.z.string().max(60).optional()
|
|
81
|
-
})
|
|
84
|
+
});
|
|
82
85
|
var updateWorkspaceSchema = import_zod.z.object({
|
|
83
86
|
name: import_zod.z.string().trim().min(1).max(200).optional(),
|
|
84
87
|
description: import_zod.z.string().max(2e3).nullable().optional(),
|
|
@@ -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
|
|
@@ -674,9 +693,10 @@ function toWorkspaceDTO(ws) {
|
|
|
674
693
|
ownerId: (0, import_parser.stringOrEmpty)(ws.ownerId),
|
|
675
694
|
isPersonal: (0, import_parser.booleanOrFalse)(ws.isPersonal),
|
|
676
695
|
isArchived: ws.archivedAt !== null,
|
|
677
|
-
archivedAt: (0, import_parser.
|
|
678
|
-
|
|
679
|
-
|
|
696
|
+
archivedAt: (0, import_parser.dateOrEmpty)(ws.archivedAt),
|
|
697
|
+
archivedBy: (0, import_parser.stringOrEmpty)(ws.archivedBy),
|
|
698
|
+
createdAt: (0, import_parser.dateOrEmpty)(ws.createdAt),
|
|
699
|
+
updatedAt: (0, import_parser.dateOrEmpty)(ws.updatedAt)
|
|
680
700
|
};
|
|
681
701
|
}
|
|
682
702
|
function toRoleDTO(role) {
|
|
@@ -696,7 +716,11 @@ function toMemberDTO(m) {
|
|
|
696
716
|
roleId: (0, import_parser.stringOrEmpty)(m.roleId),
|
|
697
717
|
roleName: (0, import_parser.stringOrEmpty)(m.roleName),
|
|
698
718
|
confirmed: (0, import_parser.booleanOrFalse)(m.confirmed),
|
|
699
|
-
createdAt: (0, import_parser.
|
|
719
|
+
createdAt: (0, import_parser.dateOrEmpty)(m.createdAt),
|
|
720
|
+
email: (0, import_parser.stringOrEmpty)(m.email),
|
|
721
|
+
firstName: (0, import_parser.stringOrEmpty)(m.firstName),
|
|
722
|
+
lastName: (0, import_parser.stringOrEmpty)(m.lastName),
|
|
723
|
+
profileImageUrl: (0, import_parser.stringOrEmpty)(m.profileImageUrl)
|
|
700
724
|
};
|
|
701
725
|
}
|
|
702
726
|
function toInvitationDTO(inv) {
|
|
@@ -707,8 +731,8 @@ function toInvitationDTO(inv) {
|
|
|
707
731
|
roleId: (0, import_parser.stringOrEmpty)(inv.roleId),
|
|
708
732
|
token: (0, import_parser.stringOrEmpty)(inv.token),
|
|
709
733
|
status: (0, import_parser.stringOrEmpty)(inv.status),
|
|
710
|
-
expiresAt: (0, import_parser.
|
|
711
|
-
createdAt: (0, import_parser.
|
|
734
|
+
expiresAt: (0, import_parser.dateOrEmpty)(inv.expiresAt),
|
|
735
|
+
createdAt: (0, import_parser.dateOrEmpty)(inv.createdAt)
|
|
712
736
|
};
|
|
713
737
|
}
|
|
714
738
|
function toSettingsDTO(s) {
|
|
@@ -1027,6 +1051,24 @@ function roleController(store) {
|
|
|
1027
1051
|
await roles.delete(roleId, ctx.workspace.id);
|
|
1028
1052
|
return (0, import_core4.setApiResponse)(import_core4.HTTP.OK, "ROLE_DELETED", "Role deleted successfully.");
|
|
1029
1053
|
},
|
|
1054
|
+
async getPermissions(ctx) {
|
|
1055
|
+
if (!ctx.workspace) {
|
|
1056
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.NOT_FOUND, "NOT_FOUND", "Workspace not found");
|
|
1057
|
+
}
|
|
1058
|
+
const params = ctx.meta["params"];
|
|
1059
|
+
const roleId = params?.["roleId"];
|
|
1060
|
+
if (!roleId) {
|
|
1061
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.UNPROCESSABLE, "INVALID_PARAMETER", "roleId is required");
|
|
1062
|
+
}
|
|
1063
|
+
const role = await roles.findById(roleId);
|
|
1064
|
+
if (!role) {
|
|
1065
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.NOT_FOUND, "NOT_FOUND", "Role not found");
|
|
1066
|
+
}
|
|
1067
|
+
const permissions = await roles.getPermissions(roleId, ctx.workspace.id);
|
|
1068
|
+
return (0, import_core4.setApiResponse)(import_core4.HTTP.OK, "PERMISSIONS_FETCHED", "Role permissions retrieved successfully.", {
|
|
1069
|
+
permissions
|
|
1070
|
+
});
|
|
1071
|
+
},
|
|
1030
1072
|
async setPermissions(ctx) {
|
|
1031
1073
|
if (!ctx.workspace) {
|
|
1032
1074
|
return (0, import_core4.setApiResponse)(import_core4.HTTP.NOT_FOUND, "NOT_FOUND", "Workspace not found");
|
|
@@ -1337,6 +1379,7 @@ function buildWorkspaceRoutes(store, config, bus) {
|
|
|
1337
1379
|
R("getRole", "GET", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, role.get),
|
|
1338
1380
|
R("updateRole", "PUT", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateRoleSchema), role.update),
|
|
1339
1381
|
R("removeRole", "DELETE", "/workspaces/roles/:roleId", import_middlewares.requireAuth, wsCtx, role.remove),
|
|
1382
|
+
R("getRolePermissions", "GET", "/workspaces/roles/:roleId/permissions", import_middlewares.requireAuth, wsCtx, role.getPermissions),
|
|
1340
1383
|
R("setRolePermissions", "POST", "/workspaces/roles/:roleId/permissions", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(setRolePermissionsSchema), role.setPermissions),
|
|
1341
1384
|
// ── Workspace lifecycle
|
|
1342
1385
|
R("archive", "POST", "/workspaces/archive", import_middlewares.requireAuth, wsCtx, workspace.archive),
|
|
@@ -1493,11 +1536,36 @@ async function importMembership(store, m) {
|
|
|
1493
1536
|
vals
|
|
1494
1537
|
);
|
|
1495
1538
|
}
|
|
1539
|
+
|
|
1540
|
+
// src/retention.ts
|
|
1541
|
+
async function deleteUserData(store, userId) {
|
|
1542
|
+
const rows = await store.query(
|
|
1543
|
+
`DELETE FROM fonderie_role_user_workspaces WHERE user_id = $1 RETURNING user_id`,
|
|
1544
|
+
[userId]
|
|
1545
|
+
);
|
|
1546
|
+
return rows.length;
|
|
1547
|
+
}
|
|
1548
|
+
async function exportUserData(store, userId) {
|
|
1549
|
+
const rows = await store.query(
|
|
1550
|
+
`SELECT ruw.workspace_id, ruw.role_id, r.name AS role_name
|
|
1551
|
+
FROM fonderie_role_user_workspaces ruw
|
|
1552
|
+
JOIN fonderie_roles r ON r.id = ruw.role_id
|
|
1553
|
+
WHERE ruw.user_id = $1 AND ruw.removed = false
|
|
1554
|
+
ORDER BY ruw.workspace_id`,
|
|
1555
|
+
[userId]
|
|
1556
|
+
);
|
|
1557
|
+
return { memberships: rows };
|
|
1558
|
+
}
|
|
1559
|
+
function workspaceExportContributor(store) {
|
|
1560
|
+
return { name: "workspaces", collect: (userId) => exportUserData(store, userId) };
|
|
1561
|
+
}
|
|
1496
1562
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1497
1563
|
0 && (module.exports = {
|
|
1498
1564
|
EVENT_KEYS,
|
|
1499
1565
|
MESSAGE_KEYS,
|
|
1500
1566
|
WorkspacesModule,
|
|
1567
|
+
deleteUserData,
|
|
1568
|
+
exportUserData,
|
|
1501
1569
|
importMembership,
|
|
1502
1570
|
importRole,
|
|
1503
1571
|
importWorkspace,
|
|
@@ -1508,6 +1576,7 @@ async function importMembership(store, m) {
|
|
|
1508
1576
|
toRoleDTO,
|
|
1509
1577
|
toSettingsDTO,
|
|
1510
1578
|
toWorkspaceDTO,
|
|
1511
|
-
withWorkspace
|
|
1579
|
+
withWorkspace,
|
|
1580
|
+
workspaceExportContributor
|
|
1512
1581
|
});
|
|
1513
1582
|
//# sourceMappingURL=index.cjs.map
|