@fonderie/workspaces 1.1.1 → 1.2.1
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/outcomes.md +107 -0
- package/brain/signatures.md +164 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<!-- GENERATED — do not edit. Regenerate with: npm run docs:signatures -->
|
|
2
|
+
|
|
3
|
+
# @fonderie/workspaces — outcomes
|
|
4
|
+
|
|
5
|
+
What this package does to a running app: tables its migrations create,
|
|
6
|
+
rows it seeds, routes it registers. Generated from the migration SQL and
|
|
7
|
+
route tables in source — trust this file instead of reading `dist/` or
|
|
8
|
+
downloading tarballs.
|
|
9
|
+
|
|
10
|
+
## Database tables (after all migrations)
|
|
11
|
+
|
|
12
|
+
### `fonderie_role_user_workspaces`
|
|
13
|
+
|
|
14
|
+
```sql
|
|
15
|
+
user_id UUID NOT NULL
|
|
16
|
+
workspace_id UUID NOT NULL
|
|
17
|
+
role_id UUID NOT NULL
|
|
18
|
+
confirmed BOOLEAN NOT NULL DEFAULT false
|
|
19
|
+
removed BOOLEAN NOT NULL DEFAULT false
|
|
20
|
+
suspended BOOLEAN NOT NULL DEFAULT false
|
|
21
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
22
|
+
-- PRIMARY KEY (user_id, workspace_id, role_id)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### `fonderie_roles`
|
|
26
|
+
|
|
27
|
+
```sql
|
|
28
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
29
|
+
name TEXT NOT NULL
|
|
30
|
+
workspace_id UUID
|
|
31
|
+
is_system BOOLEAN NOT NULL DEFAULT false
|
|
32
|
+
active BOOLEAN NOT NULL DEFAULT true
|
|
33
|
+
description TEXT
|
|
34
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### `fonderie_workspace_invitations`
|
|
38
|
+
|
|
39
|
+
```sql
|
|
40
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
41
|
+
workspace_id UUID NOT NULL
|
|
42
|
+
email TEXT NOT NULL
|
|
43
|
+
role_id UUID NOT NULL
|
|
44
|
+
token TEXT UNIQUE
|
|
45
|
+
pin TEXT
|
|
46
|
+
status TEXT NOT NULL DEFAULT 'PENDING'
|
|
47
|
+
expires_at TIMESTAMPTZ NOT NULL
|
|
48
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `fonderie_workspaces`
|
|
52
|
+
|
|
53
|
+
```sql
|
|
54
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
55
|
+
name TEXT NOT NULL
|
|
56
|
+
slug TEXT NOT NULL
|
|
57
|
+
type TEXT NOT NULL DEFAULT 'ORGANIZATION'
|
|
58
|
+
description TEXT
|
|
59
|
+
plan TEXT NOT NULL DEFAULT 'free'
|
|
60
|
+
owner_id UUID NOT NULL
|
|
61
|
+
settings JSONB NOT NULL DEFAULT '{}'
|
|
62
|
+
archived_at TIMESTAMPTZ
|
|
63
|
+
archived_by UUID
|
|
64
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
65
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
66
|
+
is_personal BOOLEAN NOT NULL DEFAULT false
|
|
67
|
+
motto TEXT
|
|
68
|
+
phone TEXT
|
|
69
|
+
business_type TEXT
|
|
70
|
+
address JSONB NOT NULL DEFAULT '{}'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Raw SQL ships in `node_modules/@fonderie/workspaces/dist/migrations/sql/` — read it there if you must; never download tarballs.
|
|
74
|
+
|
|
75
|
+
## Seeded rows (behavioral contract)
|
|
76
|
+
|
|
77
|
+
```sql
|
|
78
|
+
INSERT INTO fonderie_roles (name, workspace_id, is_system, description) VALUES ('ADMIN', NULL, true, 'System administrator with full access'), ('GUEST', NULL, true, 'Guest user with read-only access') ON CONFLICT DO NOTHING;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## HTTP routes registered
|
|
82
|
+
|
|
83
|
+
| Method | Path | Middleware chain (auth / validation / handler) |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| GET | `/workspaces` | `requireAuth → workspace.list` |
|
|
86
|
+
| POST | `/workspaces` | `requireAuth → validate(createWorkspaceSchema) → workspace.create` |
|
|
87
|
+
| PUT | `/workspaces` | `requireAuth → wsCtx → validate(updateWorkspaceSchema) → workspace.update` |
|
|
88
|
+
| GET | `/workspaces/:id` | `requireAuth → wsCtx → workspace.get` |
|
|
89
|
+
| POST | `/workspaces/archive` | `requireAuth → wsCtx → workspace.archive` |
|
|
90
|
+
| GET | `/workspaces/invitations` | `requireAuth → wsCtx → invitation.list` |
|
|
91
|
+
| POST | `/workspaces/invitations` | `requireAuth → wsCtx → validate(createInvitationsSchema) → invitation.invite` |
|
|
92
|
+
| DELETE | `/workspaces/invitations/:inviteId` | `requireAuth → wsCtx → invitation.cancel` |
|
|
93
|
+
| POST | `/workspaces/invitations/accept` | `requireAuth → validate(acceptInvitationSchema) → invitation.accept` |
|
|
94
|
+
| GET | `/workspaces/members` | `requireAuth → wsCtx → member.list` |
|
|
95
|
+
| DELETE | `/workspaces/members/:userId` | `requireAuth → wsCtx → member.remove` |
|
|
96
|
+
| GET | `/workspaces/members/:userId/roles` | `requireAuth → wsCtx → member.getUserRoles` |
|
|
97
|
+
| POST | `/workspaces/members/:userId/roles` | `requireAuth → wsCtx → validate(addMemberRoleSchema) → member.addRole` |
|
|
98
|
+
| DELETE | `/workspaces/members/:userId/roles/:roleId` | `requireAuth → wsCtx → member.removeRole` |
|
|
99
|
+
| POST | `/workspaces/restore` | `requireAuth → wsCtx → workspace.restore` |
|
|
100
|
+
| GET | `/workspaces/roles` | `requireAuth → wsCtx → role.list` |
|
|
101
|
+
| POST | `/workspaces/roles` | `requireAuth → wsCtx → validate(createRoleSchema) → role.create` |
|
|
102
|
+
| DELETE | `/workspaces/roles/:roleId` | `requireAuth → wsCtx → role.remove` |
|
|
103
|
+
| GET | `/workspaces/roles/:roleId` | `requireAuth → wsCtx → role.get` |
|
|
104
|
+
| PUT | `/workspaces/roles/:roleId` | `requireAuth → wsCtx → validate(updateRoleSchema) → role.update` |
|
|
105
|
+
| POST | `/workspaces/roles/:roleId/permissions` | `requireAuth → wsCtx → validate(setRolePermissionsSchema) → role.setPermissions` |
|
|
106
|
+
| GET | `/workspaces/settings` | `requireAuth → wsCtx → workspace.getSettings` |
|
|
107
|
+
| PUT | `/workspaces/settings` | `requireAuth → wsCtx → validate(updateSettingsSchema) → workspace.updateSettings` |
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<!-- GENERATED — do not edit. Regenerate with: npm run docs:signatures -->
|
|
2
|
+
|
|
3
|
+
# @fonderie/workspaces — signatures
|
|
4
|
+
|
|
5
|
+
## @fonderie/workspaces
|
|
6
|
+
|
|
7
|
+
Subpath exports: `@fonderie/workspaces/types`, `@fonderie/workspaces/middleware`, `@fonderie/workspaces/migrations`
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
new WorkspacesModule(store: IStoreAdapter, config?: IWorkspacesConfig, bus?: EventBus | undefined): WorkspacesModule
|
|
11
|
+
.name: "@fonderie/workspaces"
|
|
12
|
+
.deps: string[]
|
|
13
|
+
.install(app: IFonderieApp): void
|
|
14
|
+
|
|
15
|
+
interface IWorkspacesConfig {
|
|
16
|
+
invitationTtl?: string;
|
|
17
|
+
personalWorkspace?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type WorkspacesMessageKey = (typeof MESSAGE_KEYS)[keyof typeof MESSAGE_KEYS];
|
|
21
|
+
|
|
22
|
+
type WorkspacesEventKey = (typeof EVENT_KEYS)[keyof typeof EVENT_KEYS];
|
|
23
|
+
|
|
24
|
+
const MESSAGE_KEYS: { readonly workspaceInvitation: "workspace-invitation"; }
|
|
25
|
+
|
|
26
|
+
const EVENT_KEYS: { readonly personalWorkspaceCreated: "fonderie.workspace.personal.created"; }
|
|
27
|
+
|
|
28
|
+
type WorkspaceType = 'ORGANIZATION' | 'PERSONAL' | 'TEAM' | 'COMMUNITY' | 'VENDOR';
|
|
29
|
+
|
|
30
|
+
type InvitationStatus = 'PENDING' | 'ACCEPTED' | 'REJECTED' | 'CANCELLED';
|
|
31
|
+
|
|
32
|
+
interface IWorkspace {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
slug: string;
|
|
36
|
+
type: WorkspaceType;
|
|
37
|
+
description: string | null;
|
|
38
|
+
motto: string | null;
|
|
39
|
+
phone: string | null;
|
|
40
|
+
businessType: string | null;
|
|
41
|
+
address: IWorkspaceAddress | null;
|
|
42
|
+
plan: string;
|
|
43
|
+
ownerId: string;
|
|
44
|
+
isPersonal: boolean;
|
|
45
|
+
archivedAt: string | null;
|
|
46
|
+
archivedBy: string | null;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
updatedAt: string | null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface IRole {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
isSystem: boolean;
|
|
55
|
+
active: boolean;
|
|
56
|
+
description: string | null;
|
|
57
|
+
workspaceId: string | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface IMember {
|
|
61
|
+
userId: string;
|
|
62
|
+
workspaceId: string;
|
|
63
|
+
roleId: string;
|
|
64
|
+
roleName: string;
|
|
65
|
+
confirmed: boolean;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
firstName: string | null;
|
|
68
|
+
lastName: string | null;
|
|
69
|
+
email: string | null;
|
|
70
|
+
profileImageUrl: string | null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface IInvitation {
|
|
74
|
+
id: string;
|
|
75
|
+
workspaceId: string;
|
|
76
|
+
email: string;
|
|
77
|
+
roleId: string;
|
|
78
|
+
token: string;
|
|
79
|
+
pin: string | null;
|
|
80
|
+
status: InvitationStatus;
|
|
81
|
+
expiresAt: string;
|
|
82
|
+
createdAt: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface IWorkspaceSettings {
|
|
86
|
+
locale: string;
|
|
87
|
+
timezone: string;
|
|
88
|
+
currency: string;
|
|
89
|
+
dateFormat: string;
|
|
90
|
+
timeFormat: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface IWorkspaceDTO {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
slug: string;
|
|
97
|
+
type: string;
|
|
98
|
+
description: string;
|
|
99
|
+
motto: string;
|
|
100
|
+
phone: string;
|
|
101
|
+
businessType: string;
|
|
102
|
+
address: IWorkspaceAddressDTO;
|
|
103
|
+
plan: string;
|
|
104
|
+
ownerId: string;
|
|
105
|
+
isPersonal: boolean;
|
|
106
|
+
isArchived: boolean;
|
|
107
|
+
archivedAt: string;
|
|
108
|
+
createdAt: string;
|
|
109
|
+
updatedAt: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface IRoleDTO {
|
|
113
|
+
id: string;
|
|
114
|
+
name: string;
|
|
115
|
+
isSystem: boolean;
|
|
116
|
+
active: boolean;
|
|
117
|
+
description: string;
|
|
118
|
+
workspaceId: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface IMemberDTO {
|
|
122
|
+
userId: string;
|
|
123
|
+
workspaceId: string;
|
|
124
|
+
roleId: string;
|
|
125
|
+
roleName: string;
|
|
126
|
+
confirmed: boolean;
|
|
127
|
+
createdAt: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface IInvitationDTO {
|
|
131
|
+
id: string;
|
|
132
|
+
workspaceId: string;
|
|
133
|
+
email: string;
|
|
134
|
+
roleId: string;
|
|
135
|
+
token: string;
|
|
136
|
+
status: string;
|
|
137
|
+
expiresAt: string;
|
|
138
|
+
createdAt: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface IWorkspaceSettingsDTO {
|
|
142
|
+
locale: string;
|
|
143
|
+
timezone: string;
|
|
144
|
+
currency: string;
|
|
145
|
+
dateFormat: string;
|
|
146
|
+
timeFormat: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function toWorkspaceDTO(ws: IWorkspace): IWorkspaceDTO
|
|
150
|
+
|
|
151
|
+
function toRoleDTO(role: IRole): IRoleDTO
|
|
152
|
+
|
|
153
|
+
function toMemberDTO(m: IMember): IMemberDTO
|
|
154
|
+
|
|
155
|
+
function toInvitationDTO(inv: IInvitation): IInvitationDTO
|
|
156
|
+
|
|
157
|
+
function toSettingsDTO(s: IWorkspaceSettings): IWorkspaceSettingsDTO
|
|
158
|
+
|
|
159
|
+
function withWorkspace(store: IStoreAdapter): Middleware
|
|
160
|
+
|
|
161
|
+
function requireWorkspace(ctx: IFonderieContext, next: () => Promise<Response>): Promise<Response>
|
|
162
|
+
|
|
163
|
+
namespace schemas — exports: acceptInvitationSchema, addMemberRoleSchema, createInvitationsSchema, createRoleSchema, createWorkspaceSchema, setRolePermissionsSchema, updateRoleSchema, updateSettingsSchema, updateWorkspaceSchema
|
|
164
|
+
```
|