@shipfox/api-workspaces 2.0.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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +97 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -0
- package/dist/core/entities/index.d.ts +4 -0
- package/dist/core/entities/index.d.ts.map +1 -0
- package/dist/core/entities/index.js +3 -0
- package/dist/core/entities/index.js.map +1 -0
- package/dist/core/entities/invitation.d.ts +14 -0
- package/dist/core/entities/invitation.d.ts.map +1 -0
- package/dist/core/entities/invitation.js +3 -0
- package/dist/core/entities/invitation.js.map +1 -0
- package/dist/core/entities/membership.d.ts +10 -0
- package/dist/core/entities/membership.d.ts.map +1 -0
- package/dist/core/entities/membership.js +3 -0
- package/dist/core/entities/membership.js.map +1 -0
- package/dist/core/entities/workspace.d.ts +10 -0
- package/dist/core/entities/workspace.d.ts.map +1 -0
- package/dist/core/entities/workspace.js +3 -0
- package/dist/core/entities/workspace.js.map +1 -0
- package/dist/core/errors.d.ts +52 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +104 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/invitations.d.ts +51 -0
- package/dist/core/invitations.d.ts.map +1 -0
- package/dist/core/invitations.js +136 -0
- package/dist/core/invitations.js.map +1 -0
- package/dist/core/memberships.d.ts +9 -0
- package/dist/core/memberships.d.ts.map +1 -0
- package/dist/core/memberships.js +13 -0
- package/dist/core/memberships.js.map +1 -0
- package/dist/core/workspaces.d.ts +40 -0
- package/dist/core/workspaces.d.ts.map +1 -0
- package/dist/core/workspaces.js +85 -0
- package/dist/core/workspaces.js.map +1 -0
- package/dist/db/db.d.ts +1253 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +24 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +10 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/invitations.d.ts +47 -0
- package/dist/db/invitations.d.ts.map +1 -0
- package/dist/db/invitations.js +107 -0
- package/dist/db/invitations.js.map +1 -0
- package/dist/db/memberships.d.ts +44 -0
- package/dist/db/memberships.d.ts.map +1 -0
- package/dist/db/memberships.js +75 -0
- package/dist/db/memberships.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/invitations.d.ts +199 -0
- package/dist/db/schema/invitations.d.ts.map +1 -0
- package/dist/db/schema/invitations.js +47 -0
- package/dist/db/schema/invitations.js.map +1 -0
- package/dist/db/schema/memberships.d.ts +131 -0
- package/dist/db/schema/memberships.d.ts.map +1 -0
- package/dist/db/schema/memberships.js +35 -0
- package/dist/db/schema/memberships.js.map +1 -0
- package/dist/db/schema/outbox.d.ts +195 -0
- package/dist/db/schema/outbox.d.ts.map +1 -0
- package/dist/db/schema/outbox.js +5 -0
- package/dist/db/schema/outbox.js.map +1 -0
- package/dist/db/schema/workspaces.d.ts +115 -0
- package/dist/db/schema/workspaces.d.ts.map +1 -0
- package/dist/db/schema/workspaces.js +32 -0
- package/dist/db/schema/workspaces.js.map +1 -0
- package/dist/db/workspaces.d.ts +20 -0
- package/dist/db/workspaces.d.ts.map +1 -0
- package/dist/db/workspaces.js +53 -0
- package/dist/db/workspaces.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +3 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instance.d.ts +8 -0
- package/dist/metrics/instance.d.ts.map +1 -0
- package/dist/metrics/instance.js +41 -0
- package/dist/metrics/instance.js.map +1 -0
- package/dist/metrics/service.d.ts +2 -0
- package/dist/metrics/service.d.ts.map +1 -0
- package/dist/metrics/service.js +26 -0
- package/dist/metrics/service.js.map +1 -0
- package/dist/presentation/dto/index.d.ts +4 -0
- package/dist/presentation/dto/index.d.ts.map +1 -0
- package/dist/presentation/dto/index.js +5 -0
- package/dist/presentation/dto/index.js.map +1 -0
- package/dist/presentation/dto/invitation.d.ts +4 -0
- package/dist/presentation/dto/invitation.d.ts.map +1 -0
- package/dist/presentation/dto/invitation.js +15 -0
- package/dist/presentation/dto/invitation.js.map +1 -0
- package/dist/presentation/dto/membership.d.ts +5 -0
- package/dist/presentation/dto/membership.d.ts.map +1 -0
- package/dist/presentation/dto/membership.js +23 -0
- package/dist/presentation/dto/membership.js.map +1 -0
- package/dist/presentation/dto/workspace.d.ts +4 -0
- package/dist/presentation/dto/workspace.d.ts.map +1 -0
- package/dist/presentation/dto/workspace.js +12 -0
- package/dist/presentation/dto/workspace.js.map +1 -0
- package/dist/presentation/e2eRoutes/create-invitation.d.ts +2 -0
- package/dist/presentation/e2eRoutes/create-invitation.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/create-invitation.js +39 -0
- package/dist/presentation/e2eRoutes/create-invitation.js.map +1 -0
- package/dist/presentation/e2eRoutes/create-workspace.d.ts +2 -0
- package/dist/presentation/e2eRoutes/create-workspace.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/create-workspace.js +27 -0
- package/dist/presentation/e2eRoutes/create-workspace.js.map +1 -0
- package/dist/presentation/e2eRoutes/index.d.ts +3 -0
- package/dist/presentation/e2eRoutes/index.d.ts.map +1 -0
- package/dist/presentation/e2eRoutes/index.js +11 -0
- package/dist/presentation/e2eRoutes/index.js.map +1 -0
- package/dist/presentation/index.d.ts +2 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +3 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/routes/index.d.ts +3 -0
- package/dist/presentation/routes/index.d.ts.map +1 -0
- package/dist/presentation/routes/index.js +23 -0
- package/dist/presentation/routes/index.js.map +1 -0
- package/dist/presentation/routes/invitations/accept.d.ts +2 -0
- package/dist/presentation/routes/invitations/accept.d.ts.map +1 -0
- package/dist/presentation/routes/invitations/accept.js +67 -0
- package/dist/presentation/routes/invitations/accept.js.map +1 -0
- package/dist/presentation/routes/invitations/create.d.ts +2 -0
- package/dist/presentation/routes/invitations/create.d.ts.map +1 -0
- package/dist/presentation/routes/invitations/create.js +66 -0
- package/dist/presentation/routes/invitations/create.js.map +1 -0
- package/dist/presentation/routes/invitations/index.d.ts +4 -0
- package/dist/presentation/routes/invitations/index.d.ts.map +1 -0
- package/dist/presentation/routes/invitations/index.js +19 -0
- package/dist/presentation/routes/invitations/index.js.map +1 -0
- package/dist/presentation/routes/invitations/list.d.ts +2 -0
- package/dist/presentation/routes/invitations/list.d.ts.map +1 -0
- package/dist/presentation/routes/invitations/list.js +58 -0
- package/dist/presentation/routes/invitations/list.js.map +1 -0
- package/dist/presentation/routes/invitations/preview.d.ts +2 -0
- package/dist/presentation/routes/invitations/preview.d.ts.map +1 -0
- package/dist/presentation/routes/invitations/preview.js +47 -0
- package/dist/presentation/routes/invitations/preview.js.map +1 -0
- package/dist/presentation/routes/invitations/revoke.d.ts +2 -0
- package/dist/presentation/routes/invitations/revoke.d.ts.map +1 -0
- package/dist/presentation/routes/invitations/revoke.js +66 -0
- package/dist/presentation/routes/invitations/revoke.js.map +1 -0
- package/dist/presentation/routes/members/index.d.ts +3 -0
- package/dist/presentation/routes/members/index.d.ts.map +1 -0
- package/dist/presentation/routes/members/index.js +8 -0
- package/dist/presentation/routes/members/index.js.map +1 -0
- package/dist/presentation/routes/members/list.d.ts +2 -0
- package/dist/presentation/routes/members/list.d.ts.map +1 -0
- package/dist/presentation/routes/members/list.js +58 -0
- package/dist/presentation/routes/members/list.js.map +1 -0
- package/dist/presentation/routes/members/remove.d.ts +2 -0
- package/dist/presentation/routes/members/remove.d.ts.map +1 -0
- package/dist/presentation/routes/members/remove.js +71 -0
- package/dist/presentation/routes/members/remove.js.map +1 -0
- package/dist/presentation/routes/workspaces/create.d.ts +2 -0
- package/dist/presentation/routes/workspaces/create.d.ts.map +1 -0
- package/dist/presentation/routes/workspaces/create.js +36 -0
- package/dist/presentation/routes/workspaces/create.js.map +1 -0
- package/dist/presentation/routes/workspaces/index.d.ts +3 -0
- package/dist/presentation/routes/workspaces/index.d.ts.map +1 -0
- package/dist/presentation/routes/workspaces/index.js +4 -0
- package/dist/presentation/routes/workspaces/index.js.map +1 -0
- package/dist/presentation/routes/workspaces/list.d.ts +2 -0
- package/dist/presentation/routes/workspaces/list.d.ts.map +1 -0
- package/dist/presentation/routes/workspaces/list.js +32 -0
- package/dist/presentation/routes/workspaces/list.js.map +1 -0
- package/dist/presentation/subscribers/index.d.ts +2 -0
- package/dist/presentation/subscribers/index.d.ts.map +1 -0
- package/dist/presentation/subscribers/index.js +3 -0
- package/dist/presentation/subscribers/index.js.map +1 -0
- package/dist/presentation/subscribers/on-invitation-send-requested.d.ts +3 -0
- package/dist/presentation/subscribers/on-invitation-send-requested.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-invitation-send-requested.js +16 -0
- package/dist/presentation/subscribers/on-invitation-send-requested.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_initial.sql +9 -0
- package/drizzle/0001_memberships_invitations.sql +30 -0
- package/drizzle/0002_membership_user_snapshots.sql +40 -0
- package/drizzle/0003_outgoing_enchantress.sql +16 -0
- package/drizzle/meta/0000_snapshot.json +80 -0
- package/drizzle/meta/0001_snapshot.json +705 -0
- package/drizzle/meta/0003_snapshot.json +442 -0
- package/drizzle/meta/_journal.json +34 -0
- package/drizzle.config.ts +7 -0
- package/package.json +71 -0
- package/src/config.ts +51 -0
- package/src/core/entities/index.ts +3 -0
- package/src/core/entities/invitation.ts +13 -0
- package/src/core/entities/membership.ts +9 -0
- package/src/core/entities/workspace.ts +10 -0
- package/src/core/errors.ts +118 -0
- package/src/core/index.ts +35 -0
- package/src/core/invitations.test.ts +251 -0
- package/src/core/invitations.ts +191 -0
- package/src/core/memberships.test.ts +77 -0
- package/src/core/memberships.ts +17 -0
- package/src/core/workspaces.test.ts +72 -0
- package/src/core/workspaces.ts +126 -0
- package/src/db/db.ts +24 -0
- package/src/db/index.ts +43 -0
- package/src/db/invitations.test.ts +204 -0
- package/src/db/invitations.ts +235 -0
- package/src/db/memberships.test.ts +107 -0
- package/src/db/memberships.ts +139 -0
- package/src/db/schema/common.ts +5 -0
- package/src/db/schema/invitations.ts +47 -0
- package/src/db/schema/memberships.ts +39 -0
- package/src/db/schema/outbox.ts +4 -0
- package/src/db/schema/workspaces.ts +33 -0
- package/src/db/workspaces.test.ts +114 -0
- package/src/db/workspaces.ts +81 -0
- package/src/index.test.ts +25 -0
- package/src/index.ts +43 -0
- package/src/metrics/index.ts +1 -0
- package/src/metrics/instance.test.ts +74 -0
- package/src/metrics/instance.ts +57 -0
- package/src/metrics/service.ts +26 -0
- package/src/presentation/dto/index.ts +3 -0
- package/src/presentation/dto/invitation.ts +16 -0
- package/src/presentation/dto/membership.ts +27 -0
- package/src/presentation/dto/workspace.ts +13 -0
- package/src/presentation/e2eRoutes/create-invitation.ts +44 -0
- package/src/presentation/e2eRoutes/create-workspace.ts +30 -0
- package/src/presentation/e2eRoutes/index.ts +8 -0
- package/src/presentation/index.ts +1 -0
- package/src/presentation/routes/index.ts +23 -0
- package/src/presentation/routes/invitations/accept.test.ts +154 -0
- package/src/presentation/routes/invitations/accept.ts +70 -0
- package/src/presentation/routes/invitations/create.test.ts +99 -0
- package/src/presentation/routes/invitations/create.ts +60 -0
- package/src/presentation/routes/invitations/index.ts +17 -0
- package/src/presentation/routes/invitations/list.test.ts +94 -0
- package/src/presentation/routes/invitations/list.ts +53 -0
- package/src/presentation/routes/invitations/preview.test.ts +140 -0
- package/src/presentation/routes/invitations/preview.ts +46 -0
- package/src/presentation/routes/invitations/revoke.test.ts +99 -0
- package/src/presentation/routes/invitations/revoke.ts +64 -0
- package/src/presentation/routes/members/index.ts +5 -0
- package/src/presentation/routes/members/list.test.ts +95 -0
- package/src/presentation/routes/members/list.ts +53 -0
- package/src/presentation/routes/members/remove.test.ts +110 -0
- package/src/presentation/routes/members/remove.ts +66 -0
- package/src/presentation/routes/workspaces/create.test.ts +87 -0
- package/src/presentation/routes/workspaces/create.ts +36 -0
- package/src/presentation/routes/workspaces/index.ts +2 -0
- package/src/presentation/routes/workspaces/list.test.ts +56 -0
- package/src/presentation/routes/workspaces/list.ts +29 -0
- package/src/presentation/subscribers/index.ts +1 -0
- package/src/presentation/subscribers/invitation-send-requested.test.ts +64 -0
- package/src/presentation/subscribers/on-invitation-send-requested.ts +15 -0
- package/test/env.ts +8 -0
- package/test/factories/index.ts +3 -0
- package/test/factories/membership.ts +24 -0
- package/test/factories/user.ts +15 -0
- package/test/factories/workspace.ts +18 -0
- package/test/globalSetup.ts +15 -0
- package/test/index.ts +3 -0
- package/test/routes.ts +255 -0
- package/test/setup.ts +17 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAOnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKlB,CAAC;AAIF,wBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjB;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B"}
|
package/dist/db/db.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { drizzle } from '@shipfox/node-drizzle';
|
|
2
|
+
import { pgClient } from '@shipfox/node-postgres';
|
|
3
|
+
import { invitations } from './schema/invitations.js';
|
|
4
|
+
import { memberships } from './schema/memberships.js';
|
|
5
|
+
import { workspacesOutbox } from './schema/outbox.js';
|
|
6
|
+
import { workspaces } from './schema/workspaces.js';
|
|
7
|
+
export const schema = {
|
|
8
|
+
workspaces,
|
|
9
|
+
memberships,
|
|
10
|
+
invitations,
|
|
11
|
+
workspacesOutbox
|
|
12
|
+
};
|
|
13
|
+
let _db;
|
|
14
|
+
export function db() {
|
|
15
|
+
if (!_db) _db = drizzle(pgClient(), {
|
|
16
|
+
schema
|
|
17
|
+
});
|
|
18
|
+
return _db;
|
|
19
|
+
}
|
|
20
|
+
export function closeDb() {
|
|
21
|
+
_db = undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/db.ts"],"sourcesContent":["import {drizzle, type NodePgDatabase} from '@shipfox/node-drizzle';\nimport {pgClient} from '@shipfox/node-postgres';\nimport {invitations} from './schema/invitations.js';\nimport {memberships} from './schema/memberships.js';\nimport {workspacesOutbox} from './schema/outbox.js';\nimport {workspaces} from './schema/workspaces.js';\n\nexport const schema = {\n workspaces,\n memberships,\n invitations,\n workspacesOutbox,\n};\n\nlet _db: NodePgDatabase<typeof schema> | undefined;\n\nexport function db() {\n if (!_db) _db = drizzle(pgClient(), {schema});\n return _db;\n}\n\nexport function closeDb(): void {\n _db = undefined;\n}\n"],"names":["drizzle","pgClient","invitations","memberships","workspacesOutbox","workspaces","schema","_db","db","closeDb","undefined"],"mappings":"AAAA,SAAQA,OAAO,QAA4B,wBAAwB;AACnE,SAAQC,QAAQ,QAAO,yBAAyB;AAChD,SAAQC,WAAW,QAAO,0BAA0B;AACpD,SAAQC,WAAW,QAAO,0BAA0B;AACpD,SAAQC,gBAAgB,QAAO,qBAAqB;AACpD,SAAQC,UAAU,QAAO,yBAAyB;AAElD,OAAO,MAAMC,SAAS;IACpBD;IACAF;IACAD;IACAE;AACF,EAAE;AAEF,IAAIG;AAEJ,OAAO,SAASC;IACd,IAAI,CAACD,KAAKA,MAAMP,QAAQC,YAAY;QAACK;IAAM;IAC3C,OAAOC;AACT;AAEA,OAAO,SAASE;IACdF,MAAMG;AACR"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { closeDb, db, schema } from './db.js';
|
|
2
|
+
export type { AcceptInvitationParams, AcceptInvitationResult, CreateInvitationParams, } from './invitations.js';
|
|
3
|
+
export { acceptInvitation, createInvitation, findInvitationByToken, listOpenInvitationsByWorkspace, revokeInvitation, } from './invitations.js';
|
|
4
|
+
export type { CreateMembershipParams, MembershipWithUser, MembershipWithWorkspace, RemoveMembershipParams, } from './memberships.js';
|
|
5
|
+
export { createMembership, findMembership, listMembershipsByUser, listMembershipsByWorkspace, removeMembership, } from './memberships.js';
|
|
6
|
+
export { workspacesOutbox } from './schema/outbox.js';
|
|
7
|
+
export type { CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceServiceMetrics, } from './workspaces.js';
|
|
8
|
+
export { createWorkspace, getWorkspaceById, getWorkspaceServiceMetrics, updateWorkspace, } from './workspaces.js';
|
|
9
|
+
export declare const migrationsPath: string;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,OAAO,EAAE,EAAE,EAAE,MAAM,EAAC,MAAM,SAAS,CAAC;AAC5C,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,8BAA8B,EAC9B,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAEzB,eAAO,MAAM,cAAc,QAAoE,CAAC"}
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
export { closeDb, db, schema } from './db.js';
|
|
4
|
+
export { acceptInvitation, createInvitation, findInvitationByToken, listOpenInvitationsByWorkspace, revokeInvitation } from './invitations.js';
|
|
5
|
+
export { createMembership, findMembership, listMembershipsByUser, listMembershipsByWorkspace, removeMembership } from './memberships.js';
|
|
6
|
+
export { workspacesOutbox } from './schema/outbox.js';
|
|
7
|
+
export { createWorkspace, getWorkspaceById, getWorkspaceServiceMetrics, updateWorkspace } from './workspaces.js';
|
|
8
|
+
export const migrationsPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../drizzle');
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\n\nexport {closeDb, db, schema} from './db.js';\nexport type {\n AcceptInvitationParams,\n AcceptInvitationResult,\n CreateInvitationParams,\n} from './invitations.js';\nexport {\n acceptInvitation,\n createInvitation,\n findInvitationByToken,\n listOpenInvitationsByWorkspace,\n revokeInvitation,\n} from './invitations.js';\nexport type {\n CreateMembershipParams,\n MembershipWithUser,\n MembershipWithWorkspace,\n RemoveMembershipParams,\n} from './memberships.js';\nexport {\n createMembership,\n findMembership,\n listMembershipsByUser,\n listMembershipsByWorkspace,\n removeMembership,\n} from './memberships.js';\nexport {workspacesOutbox} from './schema/outbox.js';\nexport type {\n CreateWorkspaceParams,\n UpdateWorkspaceParams,\n WorkspaceServiceMetrics,\n} from './workspaces.js';\nexport {\n createWorkspace,\n getWorkspaceById,\n getWorkspaceServiceMetrics,\n updateWorkspace,\n} from './workspaces.js';\n\nexport const migrationsPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../drizzle');\n"],"names":["dirname","resolve","fileURLToPath","closeDb","db","schema","acceptInvitation","createInvitation","findInvitationByToken","listOpenInvitationsByWorkspace","revokeInvitation","createMembership","findMembership","listMembershipsByUser","listMembershipsByWorkspace","removeMembership","workspacesOutbox","createWorkspace","getWorkspaceById","getWorkspaceServiceMetrics","updateWorkspace","migrationsPath","url"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AAEvC,SAAQC,OAAO,EAAEC,EAAE,EAAEC,MAAM,QAAO,UAAU;AAM5C,SACEC,gBAAgB,EAChBC,gBAAgB,EAChBC,qBAAqB,EACrBC,8BAA8B,EAC9BC,gBAAgB,QACX,mBAAmB;AAO1B,SACEC,gBAAgB,EAChBC,cAAc,EACdC,qBAAqB,EACrBC,0BAA0B,EAC1BC,gBAAgB,QACX,mBAAmB;AAC1B,SAAQC,gBAAgB,QAAO,qBAAqB;AAMpD,SACEC,eAAe,EACfC,gBAAgB,EAChBC,0BAA0B,EAC1BC,eAAe,QACV,kBAAkB;AAEzB,OAAO,MAAMC,iBAAiBpB,QAAQD,QAAQE,cAAc,YAAYoB,GAAG,IAAI,iBAAiB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Invitation } from '#core/entities/invitation.js';
|
|
2
|
+
import type { Membership } from '#core/entities/membership.js';
|
|
3
|
+
interface CreateInvitationBaseParams {
|
|
4
|
+
workspaceId: string;
|
|
5
|
+
email: string;
|
|
6
|
+
hashedToken: string;
|
|
7
|
+
expiresAt: Date;
|
|
8
|
+
invitedByUserId: string;
|
|
9
|
+
invitedByDisplay?: string | null;
|
|
10
|
+
}
|
|
11
|
+
export type CreateInvitationParams = CreateInvitationBaseParams & ({
|
|
12
|
+
sendEmail: {
|
|
13
|
+
workspaceName: string;
|
|
14
|
+
inviterName: string;
|
|
15
|
+
inviteLink: string;
|
|
16
|
+
};
|
|
17
|
+
skipEmail?: never;
|
|
18
|
+
} | {
|
|
19
|
+
sendEmail?: never;
|
|
20
|
+
skipEmail: true;
|
|
21
|
+
});
|
|
22
|
+
export declare function createInvitation(params: CreateInvitationParams): Promise<Invitation>;
|
|
23
|
+
export declare function findInvitationByToken(params: {
|
|
24
|
+
hashedToken: string;
|
|
25
|
+
}): Promise<Invitation | undefined>;
|
|
26
|
+
export declare function findInvitationById(params: {
|
|
27
|
+
id: string;
|
|
28
|
+
}): Promise<Invitation | undefined>;
|
|
29
|
+
export declare function listOpenInvitationsByWorkspace(params: {
|
|
30
|
+
workspaceId: string;
|
|
31
|
+
}): Promise<Invitation[]>;
|
|
32
|
+
export declare function revokeInvitation(params: {
|
|
33
|
+
invitationId: string;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
export interface AcceptInvitationParams {
|
|
36
|
+
invitationId: string;
|
|
37
|
+
acceptedByUserId: string;
|
|
38
|
+
acceptedByUserName?: string | null | undefined;
|
|
39
|
+
}
|
|
40
|
+
export interface AcceptInvitationResult {
|
|
41
|
+
invitation: Invitation;
|
|
42
|
+
membership: Membership;
|
|
43
|
+
alreadyMember: boolean;
|
|
44
|
+
}
|
|
45
|
+
export declare function acceptInvitation(params: AcceptInvitationParams): Promise<AcceptInvitationResult | undefined>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=invitations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitations.d.ts","sourceRoot":"","sources":["../../src/db/invitations.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAa7D,UAAU,0BAA0B;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,MAAM,sBAAsB,GAAG,0BAA0B,GAC7D,CACI;IACE,SAAS,EAAE;QACT,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,SAAS,CAAC,EAAE,KAAK,CAAC;CACnB,GACD;IAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAC,CACvC,CAAC;AAEJ,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CA4D1F;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAUlC;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAM9F;AAED,wBAAsB,8BAA8B,CAAC,MAAM,EAAE;IAC3D,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAaxB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAAC,YAAY,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpF;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAyE7C"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { WORKSPACES_INVITATION_SEND_REQUESTED } from '@shipfox/api-workspaces-dto';
|
|
2
|
+
import { writeOutboxEvent } from '@shipfox/node-outbox';
|
|
3
|
+
import { and, eq, gt, isNull, lt, sql } from 'drizzle-orm';
|
|
4
|
+
import { OpenInvitationExistsError } from '#core/errors.js';
|
|
5
|
+
import { recordWorkspaceInvitationAccepted, recordWorkspaceInvitationCreated, recordWorkspaceMembershipChanged } from '#metrics/instance.js';
|
|
6
|
+
import { db } from './db.js';
|
|
7
|
+
import { membershipValues } from './memberships.js';
|
|
8
|
+
import { invitations, toInvitation } from './schema/invitations.js';
|
|
9
|
+
import { memberships, toMembership } from './schema/memberships.js';
|
|
10
|
+
import { workspacesOutbox } from './schema/outbox.js';
|
|
11
|
+
export async function createInvitation(params) {
|
|
12
|
+
const result = await db().transaction(async (tx)=>{
|
|
13
|
+
await tx.delete(invitations).where(and(eq(invitations.workspaceId, params.workspaceId), eq(invitations.email, params.email), isNull(invitations.acceptedAt), lt(invitations.expiresAt, sql`now()`)));
|
|
14
|
+
const open = await tx.select().from(invitations).where(and(eq(invitations.workspaceId, params.workspaceId), eq(invitations.email, params.email), isNull(invitations.acceptedAt))).limit(1);
|
|
15
|
+
if (open.length > 0) {
|
|
16
|
+
throw new OpenInvitationExistsError(params.email);
|
|
17
|
+
}
|
|
18
|
+
const rows = await tx.insert(invitations).values({
|
|
19
|
+
workspaceId: params.workspaceId,
|
|
20
|
+
email: params.email,
|
|
21
|
+
hashedToken: params.hashedToken,
|
|
22
|
+
expiresAt: params.expiresAt,
|
|
23
|
+
invitedByUserId: params.invitedByUserId,
|
|
24
|
+
invitedByDisplay: params.invitedByDisplay ?? null
|
|
25
|
+
}).returning();
|
|
26
|
+
const row = rows[0];
|
|
27
|
+
if (!row) throw new Error('Insert returned no rows');
|
|
28
|
+
if (params.sendEmail) {
|
|
29
|
+
await writeOutboxEvent(tx, workspacesOutbox, {
|
|
30
|
+
type: WORKSPACES_INVITATION_SEND_REQUESTED,
|
|
31
|
+
payload: {
|
|
32
|
+
email: params.email,
|
|
33
|
+
...params.sendEmail
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
invitation: toInvitation(row),
|
|
39
|
+
emailRequested: params.sendEmail ? 'requested' : 'skipped'
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
recordWorkspaceInvitationCreated(result.emailRequested);
|
|
43
|
+
return result.invitation;
|
|
44
|
+
}
|
|
45
|
+
export async function findInvitationByToken(params) {
|
|
46
|
+
const rows = await db().select().from(invitations).where(eq(invitations.hashedToken, params.hashedToken)).limit(1);
|
|
47
|
+
const row = rows[0];
|
|
48
|
+
if (!row) return undefined;
|
|
49
|
+
return toInvitation(row);
|
|
50
|
+
}
|
|
51
|
+
export async function findInvitationById(params) {
|
|
52
|
+
const rows = await db().select().from(invitations).where(eq(invitations.id, params.id)).limit(1);
|
|
53
|
+
const row = rows[0];
|
|
54
|
+
if (!row) return undefined;
|
|
55
|
+
return toInvitation(row);
|
|
56
|
+
}
|
|
57
|
+
export async function listOpenInvitationsByWorkspace(params) {
|
|
58
|
+
const rows = await db().select().from(invitations).where(and(eq(invitations.workspaceId, params.workspaceId), isNull(invitations.acceptedAt), gt(invitations.expiresAt, sql`now()`)));
|
|
59
|
+
return rows.map(toInvitation);
|
|
60
|
+
}
|
|
61
|
+
export async function revokeInvitation(params) {
|
|
62
|
+
await db().delete(invitations).where(eq(invitations.id, params.invitationId));
|
|
63
|
+
}
|
|
64
|
+
export async function acceptInvitation(params) {
|
|
65
|
+
const result = await db().transaction(async (tx)=>{
|
|
66
|
+
const inv = await tx.select().from(invitations).where(and(eq(invitations.id, params.invitationId), isNull(invitations.acceptedAt), gt(invitations.expiresAt, sql`now()`))).limit(1);
|
|
67
|
+
const invRow = inv[0];
|
|
68
|
+
if (!invRow) return undefined;
|
|
69
|
+
const existing = await tx.select().from(memberships).where(and(eq(memberships.userId, params.acceptedByUserId), eq(memberships.workspaceId, invRow.workspaceId))).limit(1);
|
|
70
|
+
let membership;
|
|
71
|
+
let alreadyMember = false;
|
|
72
|
+
const existingRow = existing[0];
|
|
73
|
+
if (existingRow) {
|
|
74
|
+
alreadyMember = true;
|
|
75
|
+
membership = toMembership(existingRow);
|
|
76
|
+
} else {
|
|
77
|
+
const created = await tx.insert(memberships).values(membershipValues({
|
|
78
|
+
userId: params.acceptedByUserId,
|
|
79
|
+
userEmail: invRow.email,
|
|
80
|
+
userName: params.acceptedByUserName ?? null,
|
|
81
|
+
workspaceId: invRow.workspaceId
|
|
82
|
+
})).returning();
|
|
83
|
+
const createdRow = created[0];
|
|
84
|
+
if (!createdRow) throw new Error('Insert returned no rows');
|
|
85
|
+
membership = toMembership(createdRow);
|
|
86
|
+
}
|
|
87
|
+
const updated = await tx.update(invitations).set({
|
|
88
|
+
acceptedAt: sql`now()`,
|
|
89
|
+
acceptedByUserId: params.acceptedByUserId,
|
|
90
|
+
updatedAt: sql`now()`
|
|
91
|
+
}).where(eq(invitations.id, params.invitationId)).returning();
|
|
92
|
+
const updatedRow = updated[0];
|
|
93
|
+
if (!updatedRow) throw new Error('Update returned no rows');
|
|
94
|
+
return {
|
|
95
|
+
invitation: toInvitation(updatedRow),
|
|
96
|
+
membership,
|
|
97
|
+
alreadyMember
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
if (result && !result.alreadyMember) recordWorkspaceMembershipChanged('added');
|
|
101
|
+
if (result) {
|
|
102
|
+
recordWorkspaceInvitationAccepted(result.alreadyMember ? 'already_member' : 'added');
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//# sourceMappingURL=invitations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/invitations.ts"],"sourcesContent":["import {\n WORKSPACES_INVITATION_SEND_REQUESTED,\n type WorkspacesEventMap,\n} from '@shipfox/api-workspaces-dto';\nimport {writeOutboxEvent} from '@shipfox/node-outbox';\nimport {and, eq, gt, isNull, lt, sql} from 'drizzle-orm';\nimport type {Invitation} from '#core/entities/invitation.js';\nimport type {Membership} from '#core/entities/membership.js';\nimport {OpenInvitationExistsError} from '#core/errors.js';\nimport {\n recordWorkspaceInvitationAccepted,\n recordWorkspaceInvitationCreated,\n recordWorkspaceMembershipChanged,\n} from '#metrics/instance.js';\nimport {db} from './db.js';\nimport {membershipValues} from './memberships.js';\nimport {invitations, toInvitation} from './schema/invitations.js';\nimport {memberships, toMembership} from './schema/memberships.js';\nimport {workspacesOutbox} from './schema/outbox.js';\n\ninterface CreateInvitationBaseParams {\n workspaceId: string;\n email: string;\n hashedToken: string;\n expiresAt: Date;\n invitedByUserId: string;\n invitedByDisplay?: string | null;\n}\n\nexport type CreateInvitationParams = CreateInvitationBaseParams &\n (\n | {\n sendEmail: {\n workspaceName: string;\n inviterName: string;\n inviteLink: string;\n };\n skipEmail?: never;\n }\n | {sendEmail?: never; skipEmail: true}\n );\n\nexport async function createInvitation(params: CreateInvitationParams): Promise<Invitation> {\n const result = await db().transaction(async (tx) => {\n await tx\n .delete(invitations)\n .where(\n and(\n eq(invitations.workspaceId, params.workspaceId),\n eq(invitations.email, params.email),\n isNull(invitations.acceptedAt),\n lt(invitations.expiresAt, sql`now()`),\n ),\n );\n\n const open = await tx\n .select()\n .from(invitations)\n .where(\n and(\n eq(invitations.workspaceId, params.workspaceId),\n eq(invitations.email, params.email),\n isNull(invitations.acceptedAt),\n ),\n )\n .limit(1);\n\n if (open.length > 0) {\n throw new OpenInvitationExistsError(params.email);\n }\n\n const rows = await tx\n .insert(invitations)\n .values({\n workspaceId: params.workspaceId,\n email: params.email,\n hashedToken: params.hashedToken,\n expiresAt: params.expiresAt,\n invitedByUserId: params.invitedByUserId,\n invitedByDisplay: params.invitedByDisplay ?? null,\n })\n .returning();\n\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n if (params.sendEmail) {\n await writeOutboxEvent<WorkspacesEventMap>(tx, workspacesOutbox, {\n type: WORKSPACES_INVITATION_SEND_REQUESTED,\n payload: {\n email: params.email,\n ...params.sendEmail,\n },\n });\n }\n return {\n invitation: toInvitation(row),\n emailRequested: params.sendEmail ? ('requested' as const) : ('skipped' as const),\n };\n });\n\n recordWorkspaceInvitationCreated(result.emailRequested);\n return result.invitation;\n}\n\nexport async function findInvitationByToken(params: {\n hashedToken: string;\n}): Promise<Invitation | undefined> {\n const rows = await db()\n .select()\n .from(invitations)\n .where(eq(invitations.hashedToken, params.hashedToken))\n .limit(1);\n\n const row = rows[0];\n if (!row) return undefined;\n return toInvitation(row);\n}\n\nexport async function findInvitationById(params: {id: string}): Promise<Invitation | undefined> {\n const rows = await db().select().from(invitations).where(eq(invitations.id, params.id)).limit(1);\n\n const row = rows[0];\n if (!row) return undefined;\n return toInvitation(row);\n}\n\nexport async function listOpenInvitationsByWorkspace(params: {\n workspaceId: string;\n}): Promise<Invitation[]> {\n const rows = await db()\n .select()\n .from(invitations)\n .where(\n and(\n eq(invitations.workspaceId, params.workspaceId),\n isNull(invitations.acceptedAt),\n gt(invitations.expiresAt, sql`now()`),\n ),\n );\n\n return rows.map(toInvitation);\n}\n\nexport async function revokeInvitation(params: {invitationId: string}): Promise<void> {\n await db().delete(invitations).where(eq(invitations.id, params.invitationId));\n}\n\nexport interface AcceptInvitationParams {\n invitationId: string;\n acceptedByUserId: string;\n acceptedByUserName?: string | null | undefined;\n}\n\nexport interface AcceptInvitationResult {\n invitation: Invitation;\n membership: Membership;\n alreadyMember: boolean;\n}\n\nexport async function acceptInvitation(\n params: AcceptInvitationParams,\n): Promise<AcceptInvitationResult | undefined> {\n const result = await db().transaction(async (tx) => {\n const inv = await tx\n .select()\n .from(invitations)\n .where(\n and(\n eq(invitations.id, params.invitationId),\n isNull(invitations.acceptedAt),\n gt(invitations.expiresAt, sql`now()`),\n ),\n )\n .limit(1);\n\n const invRow = inv[0];\n if (!invRow) return undefined;\n\n const existing = await tx\n .select()\n .from(memberships)\n .where(\n and(\n eq(memberships.userId, params.acceptedByUserId),\n eq(memberships.workspaceId, invRow.workspaceId),\n ),\n )\n .limit(1);\n\n let membership: Membership;\n let alreadyMember = false;\n const existingRow = existing[0];\n\n if (existingRow) {\n alreadyMember = true;\n membership = toMembership(existingRow);\n } else {\n const created = await tx\n .insert(memberships)\n .values(\n membershipValues({\n userId: params.acceptedByUserId,\n userEmail: invRow.email,\n userName: params.acceptedByUserName ?? null,\n workspaceId: invRow.workspaceId,\n }),\n )\n .returning();\n const createdRow = created[0];\n if (!createdRow) throw new Error('Insert returned no rows');\n membership = toMembership(createdRow);\n }\n\n const updated = await tx\n .update(invitations)\n .set({\n acceptedAt: sql`now()`,\n acceptedByUserId: params.acceptedByUserId,\n updatedAt: sql`now()`,\n })\n .where(eq(invitations.id, params.invitationId))\n .returning();\n\n const updatedRow = updated[0];\n if (!updatedRow) throw new Error('Update returned no rows');\n\n return {invitation: toInvitation(updatedRow), membership, alreadyMember};\n });\n\n if (result && !result.alreadyMember) recordWorkspaceMembershipChanged('added');\n if (result) {\n recordWorkspaceInvitationAccepted(result.alreadyMember ? 'already_member' : 'added');\n }\n return result;\n}\n"],"names":["WORKSPACES_INVITATION_SEND_REQUESTED","writeOutboxEvent","and","eq","gt","isNull","lt","sql","OpenInvitationExistsError","recordWorkspaceInvitationAccepted","recordWorkspaceInvitationCreated","recordWorkspaceMembershipChanged","db","membershipValues","invitations","toInvitation","memberships","toMembership","workspacesOutbox","createInvitation","params","result","transaction","tx","delete","where","workspaceId","email","acceptedAt","expiresAt","open","select","from","limit","length","rows","insert","values","hashedToken","invitedByUserId","invitedByDisplay","returning","row","Error","sendEmail","type","payload","invitation","emailRequested","findInvitationByToken","undefined","findInvitationById","id","listOpenInvitationsByWorkspace","map","revokeInvitation","invitationId","acceptInvitation","inv","invRow","existing","userId","acceptedByUserId","membership","alreadyMember","existingRow","created","userEmail","userName","acceptedByUserName","createdRow","updated","update","set","updatedAt","updatedRow"],"mappings":"AAAA,SACEA,oCAAoC,QAE/B,8BAA8B;AACrC,SAAQC,gBAAgB,QAAO,uBAAuB;AACtD,SAAQC,GAAG,EAAEC,EAAE,EAAEC,EAAE,EAAEC,MAAM,EAAEC,EAAE,EAAEC,GAAG,QAAO,cAAc;AAGzD,SAAQC,yBAAyB,QAAO,kBAAkB;AAC1D,SACEC,iCAAiC,EACjCC,gCAAgC,EAChCC,gCAAgC,QAC3B,uBAAuB;AAC9B,SAAQC,EAAE,QAAO,UAAU;AAC3B,SAAQC,gBAAgB,QAAO,mBAAmB;AAClD,SAAQC,WAAW,EAAEC,YAAY,QAAO,0BAA0B;AAClE,SAAQC,WAAW,EAAEC,YAAY,QAAO,0BAA0B;AAClE,SAAQC,gBAAgB,QAAO,qBAAqB;AAwBpD,OAAO,eAAeC,iBAAiBC,MAA8B;IACnE,MAAMC,SAAS,MAAMT,KAAKU,WAAW,CAAC,OAAOC;QAC3C,MAAMA,GACHC,MAAM,CAACV,aACPW,KAAK,CACJvB,IACEC,GAAGW,YAAYY,WAAW,EAAEN,OAAOM,WAAW,GAC9CvB,GAAGW,YAAYa,KAAK,EAAEP,OAAOO,KAAK,GAClCtB,OAAOS,YAAYc,UAAU,GAC7BtB,GAAGQ,YAAYe,SAAS,EAAEtB,GAAG,CAAC,KAAK,CAAC;QAI1C,MAAMuB,OAAO,MAAMP,GAChBQ,MAAM,GACNC,IAAI,CAAClB,aACLW,KAAK,CACJvB,IACEC,GAAGW,YAAYY,WAAW,EAAEN,OAAOM,WAAW,GAC9CvB,GAAGW,YAAYa,KAAK,EAAEP,OAAOO,KAAK,GAClCtB,OAAOS,YAAYc,UAAU,IAGhCK,KAAK,CAAC;QAET,IAAIH,KAAKI,MAAM,GAAG,GAAG;YACnB,MAAM,IAAI1B,0BAA0BY,OAAOO,KAAK;QAClD;QAEA,MAAMQ,OAAO,MAAMZ,GAChBa,MAAM,CAACtB,aACPuB,MAAM,CAAC;YACNX,aAAaN,OAAOM,WAAW;YAC/BC,OAAOP,OAAOO,KAAK;YACnBW,aAAalB,OAAOkB,WAAW;YAC/BT,WAAWT,OAAOS,SAAS;YAC3BU,iBAAiBnB,OAAOmB,eAAe;YACvCC,kBAAkBpB,OAAOoB,gBAAgB,IAAI;QAC/C,GACCC,SAAS;QAEZ,MAAMC,MAAMP,IAAI,CAAC,EAAE;QACnB,IAAI,CAACO,KAAK,MAAM,IAAIC,MAAM;QAC1B,IAAIvB,OAAOwB,SAAS,EAAE;YACpB,MAAM3C,iBAAqCsB,IAAIL,kBAAkB;gBAC/D2B,MAAM7C;gBACN8C,SAAS;oBACPnB,OAAOP,OAAOO,KAAK;oBACnB,GAAGP,OAAOwB,SAAS;gBACrB;YACF;QACF;QACA,OAAO;YACLG,YAAYhC,aAAa2B;YACzBM,gBAAgB5B,OAAOwB,SAAS,GAAI,cAAyB;QAC/D;IACF;IAEAlC,iCAAiCW,OAAO2B,cAAc;IACtD,OAAO3B,OAAO0B,UAAU;AAC1B;AAEA,OAAO,eAAeE,sBAAsB7B,MAE3C;IACC,MAAMe,OAAO,MAAMvB,KAChBmB,MAAM,GACNC,IAAI,CAAClB,aACLW,KAAK,CAACtB,GAAGW,YAAYwB,WAAW,EAAElB,OAAOkB,WAAW,GACpDL,KAAK,CAAC;IAET,MAAMS,MAAMP,IAAI,CAAC,EAAE;IACnB,IAAI,CAACO,KAAK,OAAOQ;IACjB,OAAOnC,aAAa2B;AACtB;AAEA,OAAO,eAAeS,mBAAmB/B,MAAoB;IAC3D,MAAMe,OAAO,MAAMvB,KAAKmB,MAAM,GAAGC,IAAI,CAAClB,aAAaW,KAAK,CAACtB,GAAGW,YAAYsC,EAAE,EAAEhC,OAAOgC,EAAE,GAAGnB,KAAK,CAAC;IAE9F,MAAMS,MAAMP,IAAI,CAAC,EAAE;IACnB,IAAI,CAACO,KAAK,OAAOQ;IACjB,OAAOnC,aAAa2B;AACtB;AAEA,OAAO,eAAeW,+BAA+BjC,MAEpD;IACC,MAAMe,OAAO,MAAMvB,KAChBmB,MAAM,GACNC,IAAI,CAAClB,aACLW,KAAK,CACJvB,IACEC,GAAGW,YAAYY,WAAW,EAAEN,OAAOM,WAAW,GAC9CrB,OAAOS,YAAYc,UAAU,GAC7BxB,GAAGU,YAAYe,SAAS,EAAEtB,GAAG,CAAC,KAAK,CAAC;IAI1C,OAAO4B,KAAKmB,GAAG,CAACvC;AAClB;AAEA,OAAO,eAAewC,iBAAiBnC,MAA8B;IACnE,MAAMR,KAAKY,MAAM,CAACV,aAAaW,KAAK,CAACtB,GAAGW,YAAYsC,EAAE,EAAEhC,OAAOoC,YAAY;AAC7E;AAcA,OAAO,eAAeC,iBACpBrC,MAA8B;IAE9B,MAAMC,SAAS,MAAMT,KAAKU,WAAW,CAAC,OAAOC;QAC3C,MAAMmC,MAAM,MAAMnC,GACfQ,MAAM,GACNC,IAAI,CAAClB,aACLW,KAAK,CACJvB,IACEC,GAAGW,YAAYsC,EAAE,EAAEhC,OAAOoC,YAAY,GACtCnD,OAAOS,YAAYc,UAAU,GAC7BxB,GAAGU,YAAYe,SAAS,EAAEtB,GAAG,CAAC,KAAK,CAAC,IAGvC0B,KAAK,CAAC;QAET,MAAM0B,SAASD,GAAG,CAAC,EAAE;QACrB,IAAI,CAACC,QAAQ,OAAOT;QAEpB,MAAMU,WAAW,MAAMrC,GACpBQ,MAAM,GACNC,IAAI,CAAChB,aACLS,KAAK,CACJvB,IACEC,GAAGa,YAAY6C,MAAM,EAAEzC,OAAO0C,gBAAgB,GAC9C3D,GAAGa,YAAYU,WAAW,EAAEiC,OAAOjC,WAAW,IAGjDO,KAAK,CAAC;QAET,IAAI8B;QACJ,IAAIC,gBAAgB;QACpB,MAAMC,cAAcL,QAAQ,CAAC,EAAE;QAE/B,IAAIK,aAAa;YACfD,gBAAgB;YAChBD,aAAa9C,aAAagD;QAC5B,OAAO;YACL,MAAMC,UAAU,MAAM3C,GACnBa,MAAM,CAACpB,aACPqB,MAAM,CACLxB,iBAAiB;gBACfgD,QAAQzC,OAAO0C,gBAAgB;gBAC/BK,WAAWR,OAAOhC,KAAK;gBACvByC,UAAUhD,OAAOiD,kBAAkB,IAAI;gBACvC3C,aAAaiC,OAAOjC,WAAW;YACjC,IAEDe,SAAS;YACZ,MAAM6B,aAAaJ,OAAO,CAAC,EAAE;YAC7B,IAAI,CAACI,YAAY,MAAM,IAAI3B,MAAM;YACjCoB,aAAa9C,aAAaqD;QAC5B;QAEA,MAAMC,UAAU,MAAMhD,GACnBiD,MAAM,CAAC1D,aACP2D,GAAG,CAAC;YACH7C,YAAYrB,GAAG,CAAC,KAAK,CAAC;YACtBuD,kBAAkB1C,OAAO0C,gBAAgB;YACzCY,WAAWnE,GAAG,CAAC,KAAK,CAAC;QACvB,GACCkB,KAAK,CAACtB,GAAGW,YAAYsC,EAAE,EAAEhC,OAAOoC,YAAY,GAC5Cf,SAAS;QAEZ,MAAMkC,aAAaJ,OAAO,CAAC,EAAE;QAC7B,IAAI,CAACI,YAAY,MAAM,IAAIhC,MAAM;QAEjC,OAAO;YAACI,YAAYhC,aAAa4D;YAAaZ;YAAYC;QAAa;IACzE;IAEA,IAAI3C,UAAU,CAACA,OAAO2C,aAAa,EAAErD,iCAAiC;IACtE,IAAIU,QAAQ;QACVZ,kCAAkCY,OAAO2C,aAAa,GAAG,mBAAmB;IAC9E;IACA,OAAO3C;AACT"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Membership } from '#core/entities/membership.js';
|
|
2
|
+
export interface CreateMembershipParams {
|
|
3
|
+
userId: string;
|
|
4
|
+
userEmail?: string | undefined;
|
|
5
|
+
userName?: string | null | undefined;
|
|
6
|
+
workspaceId: string;
|
|
7
|
+
}
|
|
8
|
+
export interface EnsureMembershipParams {
|
|
9
|
+
userId: string;
|
|
10
|
+
userEmail: string;
|
|
11
|
+
userName: string | null;
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function membershipValues(params: CreateMembershipParams): {
|
|
15
|
+
userId: string;
|
|
16
|
+
userEmail: string;
|
|
17
|
+
userName: string | null;
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function createMembership(params: CreateMembershipParams): Promise<Membership>;
|
|
21
|
+
export declare function ensureMembership(params: EnsureMembershipParams): Promise<Membership>;
|
|
22
|
+
export interface MembershipWithWorkspace extends Membership {
|
|
23
|
+
workspaceName: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function listMembershipsByUser(params: {
|
|
26
|
+
userId: string;
|
|
27
|
+
}): Promise<MembershipWithWorkspace[]>;
|
|
28
|
+
export interface MembershipWithUser extends Membership {
|
|
29
|
+
userEmail: string;
|
|
30
|
+
userName: string | null;
|
|
31
|
+
}
|
|
32
|
+
export declare function listMembershipsByWorkspace(params: {
|
|
33
|
+
workspaceId: string;
|
|
34
|
+
}): Promise<MembershipWithUser[]>;
|
|
35
|
+
export declare function findMembership(params: {
|
|
36
|
+
userId: string;
|
|
37
|
+
workspaceId: string;
|
|
38
|
+
}): Promise<Membership | undefined>;
|
|
39
|
+
export interface RemoveMembershipParams {
|
|
40
|
+
userId: string;
|
|
41
|
+
workspaceId: string;
|
|
42
|
+
}
|
|
43
|
+
export declare function removeMembership(params: RemoveMembershipParams): Promise<void>;
|
|
44
|
+
//# sourceMappingURL=memberships.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memberships.d.ts","sourceRoot":"","sources":["../../src/db/memberships.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAO7D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB;;;;;EAO9D;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAO1F;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB1F;AAED,MAAM,WAAW,uBAAwB,SAAQ,UAAU;IACzD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAYrC;AAED,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAOhC;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAYlC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBpF"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { and, eq, sql } from 'drizzle-orm';
|
|
2
|
+
import { LastMemberError } from '#core/errors.js';
|
|
3
|
+
import { recordWorkspaceMembershipChanged } from '#metrics/instance.js';
|
|
4
|
+
import { db } from './db.js';
|
|
5
|
+
import { memberships, toMembership } from './schema/memberships.js';
|
|
6
|
+
import { workspaces } from './schema/workspaces.js';
|
|
7
|
+
export function membershipValues(params) {
|
|
8
|
+
return {
|
|
9
|
+
userId: params.userId,
|
|
10
|
+
userEmail: params.userEmail ?? `user-${params.userId}@example.local`,
|
|
11
|
+
userName: params.userName ?? null,
|
|
12
|
+
workspaceId: params.workspaceId
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export async function createMembership(params) {
|
|
16
|
+
const rows = await db().insert(memberships).values(membershipValues(params)).returning();
|
|
17
|
+
const row = rows[0];
|
|
18
|
+
if (!row) throw new Error('Insert returned no rows');
|
|
19
|
+
recordWorkspaceMembershipChanged('added');
|
|
20
|
+
return toMembership(row);
|
|
21
|
+
}
|
|
22
|
+
export async function ensureMembership(params) {
|
|
23
|
+
const rows = await db().insert(memberships).values(membershipValues(params)).onConflictDoNothing({
|
|
24
|
+
target: [
|
|
25
|
+
memberships.userId,
|
|
26
|
+
memberships.workspaceId
|
|
27
|
+
]
|
|
28
|
+
}).returning();
|
|
29
|
+
const row = rows[0];
|
|
30
|
+
if (row) {
|
|
31
|
+
recordWorkspaceMembershipChanged('added');
|
|
32
|
+
return toMembership(row);
|
|
33
|
+
}
|
|
34
|
+
const existing = await findMembership(params);
|
|
35
|
+
if (existing) return existing;
|
|
36
|
+
throw new Error('Membership conflict returned no membership');
|
|
37
|
+
}
|
|
38
|
+
export async function listMembershipsByUser(params) {
|
|
39
|
+
const rows = await db().select({
|
|
40
|
+
membership: memberships,
|
|
41
|
+
workspaceName: workspaces.name
|
|
42
|
+
}).from(memberships).innerJoin(workspaces, eq(workspaces.id, memberships.workspaceId)).where(eq(memberships.userId, params.userId)).orderBy(workspaces.name);
|
|
43
|
+
return rows.map((row)=>({
|
|
44
|
+
...toMembership(row.membership),
|
|
45
|
+
workspaceName: row.workspaceName
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
export async function listMembershipsByWorkspace(params) {
|
|
49
|
+
const rows = await db().select().from(memberships).where(eq(memberships.workspaceId, params.workspaceId));
|
|
50
|
+
return rows.map(toMembership);
|
|
51
|
+
}
|
|
52
|
+
export async function findMembership(params) {
|
|
53
|
+
const rows = await db().select().from(memberships).where(and(eq(memberships.userId, params.userId), eq(memberships.workspaceId, params.workspaceId))).limit(1);
|
|
54
|
+
const row = rows[0];
|
|
55
|
+
if (!row) return undefined;
|
|
56
|
+
return toMembership(row);
|
|
57
|
+
}
|
|
58
|
+
export async function removeMembership(params) {
|
|
59
|
+
const removed = await db().transaction(async (tx)=>{
|
|
60
|
+
const countResult = await tx.select({
|
|
61
|
+
count: sql`count(*)::int`
|
|
62
|
+
}).from(memberships).where(eq(memberships.workspaceId, params.workspaceId));
|
|
63
|
+
const total = countResult[0]?.count ?? 0;
|
|
64
|
+
if (total <= 1) {
|
|
65
|
+
throw new LastMemberError(params.workspaceId);
|
|
66
|
+
}
|
|
67
|
+
const deleted = await tx.delete(memberships).where(and(eq(memberships.userId, params.userId), eq(memberships.workspaceId, params.workspaceId))).returning({
|
|
68
|
+
id: memberships.id
|
|
69
|
+
});
|
|
70
|
+
return deleted.length > 0;
|
|
71
|
+
});
|
|
72
|
+
if (removed) recordWorkspaceMembershipChanged('removed');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=memberships.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/memberships.ts"],"sourcesContent":["import {and, eq, sql} from 'drizzle-orm';\nimport type {Membership} from '#core/entities/membership.js';\nimport {LastMemberError} from '#core/errors.js';\nimport {recordWorkspaceMembershipChanged} from '#metrics/instance.js';\nimport {db} from './db.js';\nimport {memberships, toMembership} from './schema/memberships.js';\nimport {workspaces} from './schema/workspaces.js';\n\nexport interface CreateMembershipParams {\n userId: string;\n userEmail?: string | undefined;\n userName?: string | null | undefined;\n workspaceId: string;\n}\n\nexport interface EnsureMembershipParams {\n userId: string;\n userEmail: string;\n userName: string | null;\n workspaceId: string;\n}\n\nexport function membershipValues(params: CreateMembershipParams) {\n return {\n userId: params.userId,\n userEmail: params.userEmail ?? `user-${params.userId}@example.local`,\n userName: params.userName ?? null,\n workspaceId: params.workspaceId,\n };\n}\n\nexport async function createMembership(params: CreateMembershipParams): Promise<Membership> {\n const rows = await db().insert(memberships).values(membershipValues(params)).returning();\n\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n recordWorkspaceMembershipChanged('added');\n return toMembership(row);\n}\n\nexport async function ensureMembership(params: EnsureMembershipParams): Promise<Membership> {\n const rows = await db()\n .insert(memberships)\n .values(membershipValues(params))\n .onConflictDoNothing({target: [memberships.userId, memberships.workspaceId]})\n .returning();\n\n const row = rows[0];\n if (row) {\n recordWorkspaceMembershipChanged('added');\n return toMembership(row);\n }\n\n const existing = await findMembership(params);\n if (existing) return existing;\n throw new Error('Membership conflict returned no membership');\n}\n\nexport interface MembershipWithWorkspace extends Membership {\n workspaceName: string;\n}\n\nexport async function listMembershipsByUser(params: {\n userId: string;\n}): Promise<MembershipWithWorkspace[]> {\n const rows = await db()\n .select({\n membership: memberships,\n workspaceName: workspaces.name,\n })\n .from(memberships)\n .innerJoin(workspaces, eq(workspaces.id, memberships.workspaceId))\n .where(eq(memberships.userId, params.userId))\n .orderBy(workspaces.name);\n\n return rows.map((row) => ({...toMembership(row.membership), workspaceName: row.workspaceName}));\n}\n\nexport interface MembershipWithUser extends Membership {\n userEmail: string;\n userName: string | null;\n}\n\nexport async function listMembershipsByWorkspace(params: {\n workspaceId: string;\n}): Promise<MembershipWithUser[]> {\n const rows = await db()\n .select()\n .from(memberships)\n .where(eq(memberships.workspaceId, params.workspaceId));\n\n return rows.map(toMembership);\n}\n\nexport async function findMembership(params: {\n userId: string;\n workspaceId: string;\n}): Promise<Membership | undefined> {\n const rows = await db()\n .select()\n .from(memberships)\n .where(\n and(eq(memberships.userId, params.userId), eq(memberships.workspaceId, params.workspaceId)),\n )\n .limit(1);\n\n const row = rows[0];\n if (!row) return undefined;\n return toMembership(row);\n}\n\nexport interface RemoveMembershipParams {\n userId: string;\n workspaceId: string;\n}\n\nexport async function removeMembership(params: RemoveMembershipParams): Promise<void> {\n const removed = await db().transaction(async (tx) => {\n const countResult = await tx\n .select({count: sql<number>`count(*)::int`})\n .from(memberships)\n .where(eq(memberships.workspaceId, params.workspaceId));\n const total = countResult[0]?.count ?? 0;\n if (total <= 1) {\n throw new LastMemberError(params.workspaceId);\n }\n\n const deleted = await tx\n .delete(memberships)\n .where(\n and(eq(memberships.userId, params.userId), eq(memberships.workspaceId, params.workspaceId)),\n )\n .returning({id: memberships.id});\n\n return deleted.length > 0;\n });\n\n if (removed) recordWorkspaceMembershipChanged('removed');\n}\n"],"names":["and","eq","sql","LastMemberError","recordWorkspaceMembershipChanged","db","memberships","toMembership","workspaces","membershipValues","params","userId","userEmail","userName","workspaceId","createMembership","rows","insert","values","returning","row","Error","ensureMembership","onConflictDoNothing","target","existing","findMembership","listMembershipsByUser","select","membership","workspaceName","name","from","innerJoin","id","where","orderBy","map","listMembershipsByWorkspace","limit","undefined","removeMembership","removed","transaction","tx","countResult","count","total","deleted","delete","length"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/db/schema/common.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,oDAEnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/db/schema/common.ts"],"sourcesContent":["import {pgTableCreator} from 'drizzle-orm/pg-core';\n\nexport const pgTable = pgTableCreator((name) =>\n name === 'workspaces' ? name : `workspaces_${name}`,\n);\n"],"names":["pgTableCreator","pgTable","name"],"mappings":"AAAA,SAAQA,cAAc,QAAO,sBAAsB;AAEnD,OAAO,MAAMC,UAAUD,eAAe,CAACE,OACrCA,SAAS,eAAeA,OAAO,CAAC,WAAW,EAAEA,MAAM,EACnD"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { Invitation } from '#core/entities/invitation.js';
|
|
2
|
+
export declare const invitations: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
3
|
+
name: "invitations";
|
|
4
|
+
schema: undefined;
|
|
5
|
+
columns: {
|
|
6
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
7
|
+
name: "id";
|
|
8
|
+
tableName: "invitations";
|
|
9
|
+
dataType: "string";
|
|
10
|
+
columnType: "PgUUID";
|
|
11
|
+
data: string;
|
|
12
|
+
driverParam: string;
|
|
13
|
+
notNull: true;
|
|
14
|
+
hasDefault: true;
|
|
15
|
+
isPrimaryKey: true;
|
|
16
|
+
isAutoincrement: false;
|
|
17
|
+
hasRuntimeDefault: false;
|
|
18
|
+
enumValues: undefined;
|
|
19
|
+
baseColumn: never;
|
|
20
|
+
identity: undefined;
|
|
21
|
+
generated: undefined;
|
|
22
|
+
}, {}, {}>;
|
|
23
|
+
workspaceId: import("drizzle-orm/pg-core").PgColumn<{
|
|
24
|
+
name: "workspace_id";
|
|
25
|
+
tableName: "invitations";
|
|
26
|
+
dataType: "string";
|
|
27
|
+
columnType: "PgUUID";
|
|
28
|
+
data: string;
|
|
29
|
+
driverParam: string;
|
|
30
|
+
notNull: true;
|
|
31
|
+
hasDefault: false;
|
|
32
|
+
isPrimaryKey: false;
|
|
33
|
+
isAutoincrement: false;
|
|
34
|
+
hasRuntimeDefault: false;
|
|
35
|
+
enumValues: undefined;
|
|
36
|
+
baseColumn: never;
|
|
37
|
+
identity: undefined;
|
|
38
|
+
generated: undefined;
|
|
39
|
+
}, {}, {}>;
|
|
40
|
+
email: import("drizzle-orm/pg-core").PgColumn<{
|
|
41
|
+
name: "email";
|
|
42
|
+
tableName: "invitations";
|
|
43
|
+
dataType: "string";
|
|
44
|
+
columnType: "PgText";
|
|
45
|
+
data: string;
|
|
46
|
+
driverParam: string;
|
|
47
|
+
notNull: true;
|
|
48
|
+
hasDefault: false;
|
|
49
|
+
isPrimaryKey: false;
|
|
50
|
+
isAutoincrement: false;
|
|
51
|
+
hasRuntimeDefault: false;
|
|
52
|
+
enumValues: [string, ...string[]];
|
|
53
|
+
baseColumn: never;
|
|
54
|
+
identity: undefined;
|
|
55
|
+
generated: undefined;
|
|
56
|
+
}, {}, {}>;
|
|
57
|
+
hashedToken: import("drizzle-orm/pg-core").PgColumn<{
|
|
58
|
+
name: "hashed_token";
|
|
59
|
+
tableName: "invitations";
|
|
60
|
+
dataType: "string";
|
|
61
|
+
columnType: "PgText";
|
|
62
|
+
data: string;
|
|
63
|
+
driverParam: string;
|
|
64
|
+
notNull: true;
|
|
65
|
+
hasDefault: false;
|
|
66
|
+
isPrimaryKey: false;
|
|
67
|
+
isAutoincrement: false;
|
|
68
|
+
hasRuntimeDefault: false;
|
|
69
|
+
enumValues: [string, ...string[]];
|
|
70
|
+
baseColumn: never;
|
|
71
|
+
identity: undefined;
|
|
72
|
+
generated: undefined;
|
|
73
|
+
}, {}, {}>;
|
|
74
|
+
expiresAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
75
|
+
name: "expires_at";
|
|
76
|
+
tableName: "invitations";
|
|
77
|
+
dataType: "date";
|
|
78
|
+
columnType: "PgTimestamp";
|
|
79
|
+
data: Date;
|
|
80
|
+
driverParam: string;
|
|
81
|
+
notNull: true;
|
|
82
|
+
hasDefault: false;
|
|
83
|
+
isPrimaryKey: false;
|
|
84
|
+
isAutoincrement: false;
|
|
85
|
+
hasRuntimeDefault: false;
|
|
86
|
+
enumValues: undefined;
|
|
87
|
+
baseColumn: never;
|
|
88
|
+
identity: undefined;
|
|
89
|
+
generated: undefined;
|
|
90
|
+
}, {}, {}>;
|
|
91
|
+
acceptedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
92
|
+
name: "accepted_at";
|
|
93
|
+
tableName: "invitations";
|
|
94
|
+
dataType: "date";
|
|
95
|
+
columnType: "PgTimestamp";
|
|
96
|
+
data: Date;
|
|
97
|
+
driverParam: string;
|
|
98
|
+
notNull: false;
|
|
99
|
+
hasDefault: false;
|
|
100
|
+
isPrimaryKey: false;
|
|
101
|
+
isAutoincrement: false;
|
|
102
|
+
hasRuntimeDefault: false;
|
|
103
|
+
enumValues: undefined;
|
|
104
|
+
baseColumn: never;
|
|
105
|
+
identity: undefined;
|
|
106
|
+
generated: undefined;
|
|
107
|
+
}, {}, {}>;
|
|
108
|
+
acceptedByUserId: import("drizzle-orm/pg-core").PgColumn<{
|
|
109
|
+
name: "accepted_by_user_id";
|
|
110
|
+
tableName: "invitations";
|
|
111
|
+
dataType: "string";
|
|
112
|
+
columnType: "PgUUID";
|
|
113
|
+
data: string;
|
|
114
|
+
driverParam: string;
|
|
115
|
+
notNull: false;
|
|
116
|
+
hasDefault: false;
|
|
117
|
+
isPrimaryKey: false;
|
|
118
|
+
isAutoincrement: false;
|
|
119
|
+
hasRuntimeDefault: false;
|
|
120
|
+
enumValues: undefined;
|
|
121
|
+
baseColumn: never;
|
|
122
|
+
identity: undefined;
|
|
123
|
+
generated: undefined;
|
|
124
|
+
}, {}, {}>;
|
|
125
|
+
invitedByUserId: import("drizzle-orm/pg-core").PgColumn<{
|
|
126
|
+
name: "invited_by_user_id";
|
|
127
|
+
tableName: "invitations";
|
|
128
|
+
dataType: "string";
|
|
129
|
+
columnType: "PgUUID";
|
|
130
|
+
data: string;
|
|
131
|
+
driverParam: string;
|
|
132
|
+
notNull: true;
|
|
133
|
+
hasDefault: false;
|
|
134
|
+
isPrimaryKey: false;
|
|
135
|
+
isAutoincrement: false;
|
|
136
|
+
hasRuntimeDefault: false;
|
|
137
|
+
enumValues: undefined;
|
|
138
|
+
baseColumn: never;
|
|
139
|
+
identity: undefined;
|
|
140
|
+
generated: undefined;
|
|
141
|
+
}, {}, {}>;
|
|
142
|
+
invitedByDisplay: import("drizzle-orm/pg-core").PgColumn<{
|
|
143
|
+
name: "invited_by_display";
|
|
144
|
+
tableName: "invitations";
|
|
145
|
+
dataType: "string";
|
|
146
|
+
columnType: "PgText";
|
|
147
|
+
data: string;
|
|
148
|
+
driverParam: string;
|
|
149
|
+
notNull: false;
|
|
150
|
+
hasDefault: false;
|
|
151
|
+
isPrimaryKey: false;
|
|
152
|
+
isAutoincrement: false;
|
|
153
|
+
hasRuntimeDefault: false;
|
|
154
|
+
enumValues: [string, ...string[]];
|
|
155
|
+
baseColumn: never;
|
|
156
|
+
identity: undefined;
|
|
157
|
+
generated: undefined;
|
|
158
|
+
}, {}, {}>;
|
|
159
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
160
|
+
name: "created_at";
|
|
161
|
+
tableName: "invitations";
|
|
162
|
+
dataType: "date";
|
|
163
|
+
columnType: "PgTimestamp";
|
|
164
|
+
data: Date;
|
|
165
|
+
driverParam: string;
|
|
166
|
+
notNull: true;
|
|
167
|
+
hasDefault: true;
|
|
168
|
+
isPrimaryKey: false;
|
|
169
|
+
isAutoincrement: false;
|
|
170
|
+
hasRuntimeDefault: false;
|
|
171
|
+
enumValues: undefined;
|
|
172
|
+
baseColumn: never;
|
|
173
|
+
identity: undefined;
|
|
174
|
+
generated: undefined;
|
|
175
|
+
}, {}, {}>;
|
|
176
|
+
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
177
|
+
name: "updated_at";
|
|
178
|
+
tableName: "invitations";
|
|
179
|
+
dataType: "date";
|
|
180
|
+
columnType: "PgTimestamp";
|
|
181
|
+
data: Date;
|
|
182
|
+
driverParam: string;
|
|
183
|
+
notNull: true;
|
|
184
|
+
hasDefault: true;
|
|
185
|
+
isPrimaryKey: false;
|
|
186
|
+
isAutoincrement: false;
|
|
187
|
+
hasRuntimeDefault: false;
|
|
188
|
+
enumValues: undefined;
|
|
189
|
+
baseColumn: never;
|
|
190
|
+
identity: undefined;
|
|
191
|
+
generated: undefined;
|
|
192
|
+
}, {}, {}>;
|
|
193
|
+
};
|
|
194
|
+
dialect: "pg";
|
|
195
|
+
}>;
|
|
196
|
+
export type InvitationDb = typeof invitations.$inferSelect;
|
|
197
|
+
export type InvitationCreateDb = typeof invitations.$inferInsert;
|
|
198
|
+
export declare function toInvitation(row: InvitationDb): Invitation;
|
|
199
|
+
//# sourceMappingURL=invitations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitations.d.ts","sourceRoot":"","sources":["../../../src/db/schema/invitations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAI7D,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,WAAW,CAAC,YAAY,CAAC;AAC3D,MAAM,MAAM,kBAAkB,GAAG,OAAO,WAAW,CAAC,YAAY,CAAC;AAEjE,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,UAAU,CAc1D"}
|