@shipfox/api-workspaces 7.0.1 → 9.0.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +59 -0
- package/README.md +1 -5
- package/dist/core/entities/workspace.d.ts +1 -0
- package/dist/core/entities/workspace.d.ts.map +1 -1
- package/dist/core/entities/workspace.js.map +1 -1
- package/dist/core/workspaces.d.ts +3 -0
- package/dist/core/workspaces.d.ts.map +1 -1
- package/dist/core/workspaces.js +6 -1
- package/dist/core/workspaces.js.map +1 -1
- package/dist/db/db.d.ts +34 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/schema/common.d.ts.map +1 -1
- package/dist/db/schema/common.js +1 -1
- package/dist/db/schema/common.js.map +1 -1
- package/dist/db/schema/workspaces.d.ts +17 -0
- package/dist/db/schema/workspaces.d.ts.map +1 -1
- package/dist/db/schema/workspaces.js +3 -1
- package/dist/db/schema/workspaces.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/presentation/inter-module.d.ts.map +1 -1
- package/dist/presentation/inter-module.js +15 -1
- package/dist/presentation/inter-module.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0000_initial.sql +50 -1
- package/drizzle/meta/0000_snapshot.json +377 -3
- package/drizzle/meta/_journal.json +0 -28
- package/package.json +17 -31
- package/src/core/entities/workspace.ts +1 -0
- package/src/core/workspaces.ts +9 -1
- package/src/db/schema/common.ts +1 -3
- package/src/db/schema/workspaces.ts +3 -1
- package/src/index.ts +1 -1
- package/src/presentation/inter-module.test.ts +71 -0
- package/src/presentation/inter-module.ts +15 -1
- package/test/factories/workspace.ts +1 -0
- package/test/globalSetup.ts +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/drizzle/0001_memberships_invitations.sql +0 -30
- package/drizzle/0002_membership_user_snapshots.sql +0 -40
- package/drizzle/0003_outgoing_enchantress.sql +0 -16
- package/drizzle/0004_tired_talon.sql +0 -1
- package/drizzle/meta/0001_snapshot.json +0 -705
- package/drizzle/meta/0003_snapshot.json +0 -442
- package/drizzle/meta/0004_snapshot.json +0 -448
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {workspacesInterModuleContract} from '@shipfox/api-workspaces-dto/inter-module';
|
|
2
|
+
import {isInterModuleKnownError} from '@shipfox/inter-module';
|
|
3
|
+
import {createInMemoryInterModuleTransport} from '@shipfox/node-module/inter-module';
|
|
4
|
+
import {createWorkspaceForUser} from '#core/workspaces.js';
|
|
5
|
+
import {createMembership, removeMembership} from '#db/memberships.js';
|
|
6
|
+
import {createWorkspace} from '#db/workspaces.js';
|
|
7
|
+
import {createWorkspacesInterModulePresentation} from './inter-module.js';
|
|
8
|
+
|
|
9
|
+
function createClient() {
|
|
10
|
+
const transport = createInMemoryInterModuleTransport();
|
|
11
|
+
const client = transport.createClient(workspacesInterModuleContract);
|
|
12
|
+
transport.register(createWorkspacesInterModulePresentation());
|
|
13
|
+
transport.seal();
|
|
14
|
+
return client;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('Workspaces inter-module presentation', () => {
|
|
18
|
+
test('resolves the workspace creator through the transport', async () => {
|
|
19
|
+
const client = createClient();
|
|
20
|
+
const creatorUserId = crypto.randomUUID();
|
|
21
|
+
const workspace = await createWorkspaceForUser({
|
|
22
|
+
name: 'Creator Workspace',
|
|
23
|
+
userId: creatorUserId,
|
|
24
|
+
});
|
|
25
|
+
await createMembership({workspaceId: workspace.id, userId: crypto.randomUUID()});
|
|
26
|
+
|
|
27
|
+
const result = await client.getWorkspaceCreator({workspaceId: workspace.id});
|
|
28
|
+
|
|
29
|
+
expect(result).toEqual({creatorUserId});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('keeps attributing the workspace to its creator after the creator leaves', async () => {
|
|
33
|
+
const client = createClient();
|
|
34
|
+
const creatorUserId = crypto.randomUUID();
|
|
35
|
+
const workspace = await createWorkspaceForUser({
|
|
36
|
+
name: 'Outlasted Creator Workspace',
|
|
37
|
+
userId: creatorUserId,
|
|
38
|
+
});
|
|
39
|
+
const remainingUserId = crypto.randomUUID();
|
|
40
|
+
await createMembership({workspaceId: workspace.id, userId: remainingUserId});
|
|
41
|
+
|
|
42
|
+
await removeMembership({userId: creatorUserId, workspaceId: workspace.id});
|
|
43
|
+
const result = await client.getWorkspaceCreator({workspaceId: workspace.id});
|
|
44
|
+
|
|
45
|
+
expect(result).toEqual({creatorUserId});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('returns null when a workspace has no known creator', async () => {
|
|
49
|
+
const client = createClient();
|
|
50
|
+
const workspace = await createWorkspace({name: 'Unattributed Workspace'});
|
|
51
|
+
|
|
52
|
+
const result = await client.getWorkspaceCreator({workspaceId: workspace.id});
|
|
53
|
+
|
|
54
|
+
expect(result).toEqual({creatorUserId: null});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('maps a missing workspace to the published known error', async () => {
|
|
58
|
+
const client = createClient();
|
|
59
|
+
const workspaceId = crypto.randomUUID();
|
|
60
|
+
|
|
61
|
+
const error = await client.getWorkspaceCreator({workspaceId}).catch((caught) => caught);
|
|
62
|
+
|
|
63
|
+
expect(
|
|
64
|
+
isInterModuleKnownError(workspacesInterModuleContract.methods.getWorkspaceCreator, error),
|
|
65
|
+
).toBe(true);
|
|
66
|
+
if (isInterModuleKnownError(workspacesInterModuleContract.methods.getWorkspaceCreator, error)) {
|
|
67
|
+
expect(error.code).toBe('workspace-not-found');
|
|
68
|
+
expect(error.details).toEqual({workspaceId});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
WorkspaceNotFoundError,
|
|
15
15
|
} from '#core/errors.js';
|
|
16
16
|
import {acceptWorkspaceInvitation, peekInvitationByRawToken} from '#core/invitations.js';
|
|
17
|
-
import {requireWorkspaceMembership} from '#core/workspaces.js';
|
|
17
|
+
import {getWorkspaceCreator, requireWorkspaceMembership} from '#core/workspaces.js';
|
|
18
18
|
import {listMembershipsByUser} from '#db/memberships.js';
|
|
19
19
|
|
|
20
20
|
export function createWorkspacesInterModulePresentation(): InterModulePresentation<
|
|
@@ -27,6 +27,20 @@ export function createWorkspacesInterModulePresentation(): InterModulePresentati
|
|
|
27
27
|
role: 'admin' as const,
|
|
28
28
|
})),
|
|
29
29
|
}),
|
|
30
|
+
getWorkspaceCreator: async (input) => {
|
|
31
|
+
try {
|
|
32
|
+
return {creatorUserId: await getWorkspaceCreator(input)};
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (error instanceof WorkspaceNotFoundError) {
|
|
35
|
+
throw createInterModuleKnownError(
|
|
36
|
+
workspacesInterModuleContract.methods.getWorkspaceCreator,
|
|
37
|
+
'workspace-not-found',
|
|
38
|
+
{workspaceId: input.workspaceId},
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
30
44
|
preflightInvitationAcceptance: async (input) => {
|
|
31
45
|
try {
|
|
32
46
|
const invitation = await peekInvitationByRawToken({token: input.token});
|
package/test/globalSetup.ts
CHANGED
|
@@ -8,7 +8,7 @@ export async function setup() {
|
|
|
8
8
|
createPostgresClient();
|
|
9
9
|
|
|
10
10
|
await runMigrations(db(), migrationsPath, '__drizzle_migrations_workspaces');
|
|
11
|
-
await db().execute(sql`TRUNCATE workspaces_outbox,
|
|
11
|
+
await db().execute(sql`TRUNCATE workspaces_outbox, workspaces_workspaces CASCADE`);
|
|
12
12
|
|
|
13
13
|
closeDb();
|
|
14
14
|
await closePostgresClient();
|