@kelpie/server 0.7.0 → 0.8.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/dist/lib/consumerEmailDomains.d.ts +2 -0
- package/dist/lib/consumerEmailDomains.d.ts.map +1 -0
- package/dist/lib/consumerEmailDomains.js +62 -0
- package/dist/lib/consumerEmailDomains.js.map +1 -0
- package/dist/lib/email.d.ts +7 -0
- package/dist/lib/email.d.ts.map +1 -1
- package/dist/lib/email.js.map +1 -1
- package/dist/lib/emailContent.d.ts +33 -0
- package/dist/lib/emailContent.d.ts.map +1 -0
- package/dist/lib/emailContent.js +54 -0
- package/dist/lib/emailContent.js.map +1 -0
- package/dist/lib/emailDomainAutoLink.d.ts +27 -0
- package/dist/lib/emailDomainAutoLink.d.ts.map +1 -0
- package/dist/lib/emailDomainAutoLink.js +119 -0
- package/dist/lib/emailDomainAutoLink.js.map +1 -0
- package/dist/lib/ids.d.ts +2 -0
- package/dist/lib/ids.d.ts.map +1 -1
- package/dist/lib/ids.js +2 -0
- package/dist/lib/ids.js.map +1 -1
- package/dist/modules/attachedRecords.d.ts.map +1 -1
- package/dist/modules/attachedRecords.js +4 -2
- package/dist/modules/attachedRecords.js.map +1 -1
- package/dist/modules/auth/preferences.d.ts +11 -1
- package/dist/modules/auth/preferences.d.ts.map +1 -1
- package/dist/modules/auth/preferences.js +11 -0
- package/dist/modules/auth/preferences.js.map +1 -1
- package/dist/modules/auth/routes.d.ts.map +1 -1
- package/dist/modules/auth/routes.js +18 -0
- package/dist/modules/auth/routes.js.map +1 -1
- package/dist/modules/auth/schema.d.ts +20 -0
- package/dist/modules/auth/schema.d.ts.map +1 -1
- package/dist/modules/auth/schema.js +11 -1
- package/dist/modules/auth/schema.js.map +1 -1
- package/dist/modules/auth/service.d.ts.map +1 -1
- package/dist/modules/auth/service.js +27 -3
- package/dist/modules/auth/service.js.map +1 -1
- package/dist/modules/companies/repository.d.ts +2 -0
- package/dist/modules/companies/repository.d.ts.map +1 -1
- package/dist/modules/companies/repository.js +1 -0
- package/dist/modules/companies/repository.js.map +1 -1
- package/dist/modules/companies/routes.d.ts +2 -0
- package/dist/modules/companies/routes.d.ts.map +1 -1
- package/dist/modules/companies/routes.js +11 -0
- package/dist/modules/companies/routes.js.map +1 -1
- package/dist/modules/companies/schema.d.ts +17 -0
- package/dist/modules/companies/schema.d.ts.map +1 -1
- package/dist/modules/companies/schema.js +5 -1
- package/dist/modules/companies/schema.js.map +1 -1
- package/dist/modules/companies/service.d.ts +1 -0
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +22 -0
- package/dist/modules/companies/service.js.map +1 -1
- package/dist/modules/core.d.ts.map +1 -1
- package/dist/modules/core.js +11 -0
- package/dist/modules/core.js.map +1 -1
- package/dist/modules/email-domain-linker/index.d.ts +12 -0
- package/dist/modules/email-domain-linker/index.d.ts.map +1 -0
- package/dist/modules/email-domain-linker/index.js +34 -0
- package/dist/modules/email-domain-linker/index.js.map +1 -0
- package/dist/modules/email-domain-linker/routes.d.ts +14 -0
- package/dist/modules/email-domain-linker/routes.d.ts.map +1 -0
- package/dist/modules/email-domain-linker/routes.js +15 -0
- package/dist/modules/email-domain-linker/routes.js.map +1 -0
- package/dist/modules/email-domain-linker/service.d.ts +37 -0
- package/dist/modules/email-domain-linker/service.d.ts.map +1 -0
- package/dist/modules/email-domain-linker/service.js +63 -0
- package/dist/modules/email-domain-linker/service.js.map +1 -0
- package/dist/modules/eventCatalogs.d.ts +1 -0
- package/dist/modules/eventCatalogs.d.ts.map +1 -1
- package/dist/modules/eventCatalogs.js +1 -0
- package/dist/modules/eventCatalogs.js.map +1 -1
- package/dist/modules/lists/events.d.ts +42 -0
- package/dist/modules/lists/events.d.ts.map +1 -0
- package/dist/modules/lists/events.js +16 -0
- package/dist/modules/lists/events.js.map +1 -0
- package/dist/modules/lists/index.d.ts +10 -0
- package/dist/modules/lists/index.d.ts.map +1 -0
- package/dist/modules/lists/index.js +35 -0
- package/dist/modules/lists/index.js.map +1 -0
- package/dist/modules/lists/repository.d.ts +69 -0
- package/dist/modules/lists/repository.d.ts.map +1 -0
- package/dist/modules/lists/repository.js +165 -0
- package/dist/modules/lists/repository.js.map +1 -0
- package/dist/modules/lists/routes.d.ts +51 -0
- package/dist/modules/lists/routes.d.ts.map +1 -0
- package/dist/modules/lists/routes.js +160 -0
- package/dist/modules/lists/routes.js.map +1 -0
- package/dist/modules/lists/schema.d.ts +264 -0
- package/dist/modules/lists/schema.d.ts.map +1 -0
- package/dist/modules/lists/schema.js +73 -0
- package/dist/modules/lists/schema.js.map +1 -0
- package/dist/modules/lists/service.d.ts +70 -0
- package/dist/modules/lists/service.d.ts.map +1 -0
- package/dist/modules/lists/service.js +214 -0
- package/dist/modules/lists/service.js.map +1 -0
- package/dist/modules/lists/tools.d.ts +4 -0
- package/dist/modules/lists/tools.d.ts.map +1 -0
- package/dist/modules/lists/tools.js +86 -0
- package/dist/modules/lists/tools.js.map +1 -0
- package/dist/modules/people/repository.d.ts +11 -0
- package/dist/modules/people/repository.d.ts.map +1 -1
- package/dist/modules/people/repository.js +16 -0
- package/dist/modules/people/repository.js.map +1 -1
- package/dist/modules/people/service.d.ts.map +1 -1
- package/dist/modules/people/service.js +18 -0
- package/dist/modules/people/service.js.map +1 -1
- package/dist/modules/positions/routes.d.ts.map +1 -1
- package/dist/modules/positions/routes.js +4 -2
- package/dist/modules/positions/routes.js.map +1 -1
- package/dist/modules/sample-data/fixture.d.ts +139 -0
- package/dist/modules/sample-data/fixture.d.ts.map +1 -0
- package/dist/modules/sample-data/fixture.js +461 -0
- package/dist/modules/sample-data/fixture.js.map +1 -0
- package/dist/modules/sample-data/index.d.ts +11 -0
- package/dist/modules/sample-data/index.d.ts.map +1 -0
- package/dist/modules/sample-data/index.js +43 -0
- package/dist/modules/sample-data/index.js.map +1 -0
- package/dist/modules/sample-data/routes.d.ts +15 -0
- package/dist/modules/sample-data/routes.d.ts.map +1 -0
- package/dist/modules/sample-data/routes.js +24 -0
- package/dist/modules/sample-data/routes.js.map +1 -0
- package/dist/modules/sample-data/service.d.ts +38 -0
- package/dist/modules/sample-data/service.d.ts.map +1 -0
- package/dist/modules/sample-data/service.js +412 -0
- package/dist/modules/sample-data/service.js.map +1 -0
- package/dist/modules/sample-data/tools.d.ts +4 -0
- package/dist/modules/sample-data/tools.d.ts.map +1 -0
- package/dist/modules/sample-data/tools.js +22 -0
- package/dist/modules/sample-data/tools.js.map +1 -0
- package/dist/modules/smtp-email/index.d.ts +1 -0
- package/dist/modules/smtp-email/index.d.ts.map +1 -1
- package/dist/modules/smtp-email/index.js +1 -0
- package/dist/modules/smtp-email/index.js.map +1 -1
- package/dist/modules/workspace/service.d.ts.map +1 -1
- package/dist/modules/workspace/service.js +10 -1
- package/dist/modules/workspace/service.js.map +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -0
- package/dist/schema/index.js.map +1 -1
- package/migrations/0021_certain_maggott.sql +30 -0
- package/migrations/0022_stormy_manta.sql +1 -0
- package/migrations/0023_funny_maddog.sql +1 -0
- package/migrations/meta/0021_snapshot.json +5389 -0
- package/migrations/meta/0022_snapshot.json +5396 -0
- package/migrations/meta/0023_snapshot.json +5403 -0
- package/migrations/meta/_journal.json +21 -0
- package/package.json +3 -2
- package/src/lib/consumerEmailDomains.ts +62 -0
- package/src/lib/email.ts +7 -0
- package/src/lib/emailContent.ts +91 -0
- package/src/lib/emailDomainAutoLink.ts +165 -0
- package/src/lib/ids.ts +2 -0
- package/src/modules/attachedRecords.ts +9 -2
- package/src/modules/auth/preferences.ts +13 -1
- package/src/modules/auth/routes.ts +22 -0
- package/src/modules/auth/schema.ts +12 -2
- package/src/modules/auth/service.ts +37 -3
- package/src/modules/companies/repository.ts +3 -0
- package/src/modules/companies/routes.ts +13 -0
- package/src/modules/companies/schema.ts +5 -1
- package/src/modules/companies/service.ts +25 -0
- package/src/modules/core.ts +11 -0
- package/src/modules/email-domain-linker/index.ts +40 -0
- package/src/modules/email-domain-linker/routes.ts +40 -0
- package/src/modules/email-domain-linker/service.ts +122 -0
- package/src/modules/eventCatalogs.ts +1 -0
- package/src/modules/lists/events.ts +41 -0
- package/src/modules/lists/index.ts +41 -0
- package/src/modules/lists/repository.ts +313 -0
- package/src/modules/lists/routes.ts +247 -0
- package/src/modules/lists/schema.ts +85 -0
- package/src/modules/lists/service.ts +404 -0
- package/src/modules/lists/tools.ts +128 -0
- package/src/modules/people/repository.ts +26 -0
- package/src/modules/people/service.ts +20 -0
- package/src/modules/positions/routes.ts +4 -2
- package/src/modules/sample-data/fixture.ts +627 -0
- package/src/modules/sample-data/index.ts +50 -0
- package/src/modules/sample-data/routes.ts +49 -0
- package/src/modules/sample-data/service.ts +590 -0
- package/src/modules/sample-data/tools.ts +32 -0
- package/src/modules/smtp-email/index.ts +8 -1
- package/src/modules/workspace/service.ts +13 -1
- package/src/schema/index.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/modules/lists/schema.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEvD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBjB,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BvB,CAAA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { RECORD_TARGET_TYPES } from '@kelpie/schemas';
|
|
2
|
+
import { foreignKey, index, pgTable, text, timestamp, unique } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { checkOneOf, createdAt, primaryId, updatedAt } from '../../lib/columns.js';
|
|
4
|
+
import { workspaces } from '../workspace/schema.js';
|
|
5
|
+
/**
|
|
6
|
+
* The target types come from `@kelpie/schemas`, so this check constraint, the
|
|
7
|
+
* route's Zod enum, and the browser's decoder are one list rather than three
|
|
8
|
+
* copies. Re-exported because `routes.ts` reads them from here, and the tables
|
|
9
|
+
* they constrain are the reason they matter.
|
|
10
|
+
*/
|
|
11
|
+
export { RECORD_TARGET_TYPES } from '@kelpie/schemas';
|
|
12
|
+
/**
|
|
13
|
+
* A named collection of records of one type.
|
|
14
|
+
*
|
|
15
|
+
* The `target_type` is chosen at creation and never changes. A `list_members`
|
|
16
|
+
* row's `(list_id, target_type)` foreign-keys back into the composite unique on
|
|
17
|
+
* this table, so adding a person to a company list is refused by the database
|
|
18
|
+
* rather than trusted to the service.
|
|
19
|
+
*
|
|
20
|
+
* `(workspace_id, name)` is unique so the sidebar never shows two lists with the
|
|
21
|
+
* same label. Renaming to an in-use name returns 409.
|
|
22
|
+
*/
|
|
23
|
+
export const lists = pgTable('lists', {
|
|
24
|
+
id: primaryId(),
|
|
25
|
+
workspaceId: text('workspace_id')
|
|
26
|
+
.notNull()
|
|
27
|
+
.references(() => workspaces.id, { onDelete: 'cascade' }),
|
|
28
|
+
name: text('name').notNull(),
|
|
29
|
+
description: text('description'),
|
|
30
|
+
targetType: text('target_type').notNull(),
|
|
31
|
+
createdAt: createdAt(),
|
|
32
|
+
updatedAt: updatedAt(),
|
|
33
|
+
}, (table) => [
|
|
34
|
+
index('lists_workspace_idx').on(table.workspaceId),
|
|
35
|
+
unique('lists_workspace_name_key').on(table.workspaceId, table.name),
|
|
36
|
+
// The referent of the composite FK from `list_members`. Postgres requires a
|
|
37
|
+
// unique key over the referenced columns; this exists solely to satisfy it.
|
|
38
|
+
unique('lists_id_target_type_key').on(table.id, table.targetType),
|
|
39
|
+
checkOneOf('lists_target_type_check', table.targetType, RECORD_TARGET_TYPES),
|
|
40
|
+
]);
|
|
41
|
+
/**
|
|
42
|
+
* A record's membership in a list.
|
|
43
|
+
*
|
|
44
|
+
* `(list_id, target_type)` foreign-keys back to the list's own unique key, so
|
|
45
|
+
* the member's type must equal its parent list's. The target itself is
|
|
46
|
+
* polymorphic and carries no foreign key of its own; the owning service checks
|
|
47
|
+
* existence with `missingTargets` and removes the row when the target goes
|
|
48
|
+
* (`attachedRecords.ts`).
|
|
49
|
+
*/
|
|
50
|
+
export const listMembers = pgTable('list_members', {
|
|
51
|
+
id: primaryId(),
|
|
52
|
+
workspaceId: text('workspace_id')
|
|
53
|
+
.notNull()
|
|
54
|
+
.references(() => workspaces.id, { onDelete: 'cascade' }),
|
|
55
|
+
listId: text('list_id').notNull(),
|
|
56
|
+
targetType: text('target_type').notNull(),
|
|
57
|
+
targetId: text('target_id').notNull(),
|
|
58
|
+
// A membership is not edited, only added or removed, so no `updated_at`.
|
|
59
|
+
addedAt: timestamp('added_at', { withTimezone: true, mode: 'date' })
|
|
60
|
+
.notNull()
|
|
61
|
+
.defaultNow(),
|
|
62
|
+
}, (table) => [
|
|
63
|
+
index('list_members_list_idx').on(table.workspaceId, table.listId),
|
|
64
|
+
index('list_members_target_idx').on(table.workspaceId, table.targetType, table.targetId),
|
|
65
|
+
unique('list_members_list_target_key').on(table.listId, table.targetId),
|
|
66
|
+
foreignKey({
|
|
67
|
+
name: 'list_members_list_target_type_fk',
|
|
68
|
+
columns: [table.listId, table.targetType],
|
|
69
|
+
foreignColumns: [lists.id, lists.targetType],
|
|
70
|
+
}).onDelete('cascade'),
|
|
71
|
+
checkOneOf('list_members_target_type_check', table.targetType, RECORD_TARGET_TYPES),
|
|
72
|
+
]);
|
|
73
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/modules/lists/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Database } from '../../lib/database.ts';
|
|
2
|
+
import type { IdFactory } from '../../lib/ids.ts';
|
|
3
|
+
import type { ListQueryParameters, Page } from '../../lib/pagination.ts';
|
|
4
|
+
import type { TransactionScope } from '../../runtime/transaction.ts';
|
|
5
|
+
import type { Actor } from '../auth/actor.ts';
|
|
6
|
+
import type { RecordTargetType } from '../recordTargets.ts';
|
|
7
|
+
import './events.ts';
|
|
8
|
+
import type { ListFilters, ListMemberFilters, ListWithCount } from './repository.ts';
|
|
9
|
+
/**
|
|
10
|
+
* Lists: named collections of records of one type.
|
|
11
|
+
*
|
|
12
|
+
* The type is fixed at creation. A member's type must match the parent list's,
|
|
13
|
+
* a rule the database enforces through a composite foreign key. The service
|
|
14
|
+
* checks the same before the insert so a mismatch produces a friendly 422
|
|
15
|
+
* rather than a driver error the caller has to decode.
|
|
16
|
+
*/
|
|
17
|
+
export interface ListsDependencies {
|
|
18
|
+
readonly db: Database;
|
|
19
|
+
readonly transaction: TransactionScope;
|
|
20
|
+
readonly createId: IdFactory;
|
|
21
|
+
readonly now: () => Date;
|
|
22
|
+
}
|
|
23
|
+
/** A list as the API returns one: the stored row minus the tenancy column. */
|
|
24
|
+
export type ListView = Omit<ListWithCount, 'workspaceId'>;
|
|
25
|
+
/** A membership plus the list it points at, as `/v1/list-memberships` returns one. */
|
|
26
|
+
export interface ListMembershipView {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly listId: string;
|
|
29
|
+
readonly listName: string;
|
|
30
|
+
readonly listTargetType: RecordTargetType;
|
|
31
|
+
readonly targetType: RecordTargetType;
|
|
32
|
+
readonly targetId: string;
|
|
33
|
+
readonly addedAt: Date;
|
|
34
|
+
}
|
|
35
|
+
/** A member enriched with the resolved name of the record it points at. */
|
|
36
|
+
export interface ListMemberView {
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly listId: string;
|
|
39
|
+
readonly targetType: RecordTargetType;
|
|
40
|
+
readonly targetId: string;
|
|
41
|
+
readonly targetName: string | null;
|
|
42
|
+
readonly addedAt: Date;
|
|
43
|
+
}
|
|
44
|
+
export interface CreateListInput {
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly targetType: RecordTargetType;
|
|
47
|
+
readonly description: string | null;
|
|
48
|
+
}
|
|
49
|
+
/** PATCH semantics: an absent field is left alone. The type never moves. */
|
|
50
|
+
export interface UpdateListInput {
|
|
51
|
+
readonly name?: string | undefined;
|
|
52
|
+
readonly description?: string | null | undefined;
|
|
53
|
+
}
|
|
54
|
+
export interface AddListMemberInput {
|
|
55
|
+
readonly targetType: RecordTargetType;
|
|
56
|
+
readonly targetId: string;
|
|
57
|
+
}
|
|
58
|
+
export interface ListsService {
|
|
59
|
+
list(actor: Actor, filters: ListFilters, query: ListQueryParameters): Promise<Page<ListView>>;
|
|
60
|
+
get(actor: Actor, id: string): Promise<ListView>;
|
|
61
|
+
create(actor: Actor, input: CreateListInput): Promise<ListView>;
|
|
62
|
+
update(actor: Actor, id: string, changes: UpdateListInput): Promise<ListView>;
|
|
63
|
+
remove(actor: Actor, id: string): Promise<void>;
|
|
64
|
+
listMembers(actor: Actor, filters: ListMemberFilters, query: ListQueryParameters): Promise<Page<ListMemberView>>;
|
|
65
|
+
addMember(actor: Actor, listId: string, input: AddListMemberInput): Promise<ListMemberView>;
|
|
66
|
+
removeMember(actor: Actor, listId: string, id: string): Promise<void>;
|
|
67
|
+
membershipsFor(actor: Actor, targetType: RecordTargetType, targetId: string): Promise<readonly ListMembershipView[]>;
|
|
68
|
+
}
|
|
69
|
+
export declare function createListsService(dependencies: ListsDependencies): ListsService;
|
|
70
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/lists/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { changedKeys } from '../../lib/changes.js';
|
|
2
|
+
import { UNIQUE_VIOLATION, postgresErrorCode } from '../../lib/database.js';
|
|
3
|
+
import { AppError } from '../../lib/errors.js';
|
|
4
|
+
import { mapPage, readListWindow, toPage } from '../../lib/pagination.js';
|
|
5
|
+
import { toEventActor } from '../../lib/actor.js';
|
|
6
|
+
import { requireWorkspaceId } from '../auth/actor.js';
|
|
7
|
+
import { missingTargets, resolveTargetNames, targetKey } from '../recordTargets.js';
|
|
8
|
+
import './events.js';
|
|
9
|
+
import * as repository from './repository.js';
|
|
10
|
+
import { DEFAULT_LIST_MEMBER_SORT, DEFAULT_LIST_SORT, LIST_MEMBER_SORTS, LIST_SORTS, } from './repository.js';
|
|
11
|
+
function toView(record) {
|
|
12
|
+
const { workspaceId: _workspaceId, ...view } = record;
|
|
13
|
+
return view;
|
|
14
|
+
}
|
|
15
|
+
function toMembershipView(row) {
|
|
16
|
+
return {
|
|
17
|
+
id: row.id,
|
|
18
|
+
listId: row.listId,
|
|
19
|
+
listName: row.listName,
|
|
20
|
+
listTargetType: row.listTargetType,
|
|
21
|
+
targetType: row.targetType,
|
|
22
|
+
targetId: row.targetId,
|
|
23
|
+
addedAt: row.addedAt,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function toMemberView(record, name) {
|
|
27
|
+
return {
|
|
28
|
+
id: record.id,
|
|
29
|
+
listId: record.listId,
|
|
30
|
+
targetType: record.targetType,
|
|
31
|
+
targetId: record.targetId,
|
|
32
|
+
targetName: name ?? null,
|
|
33
|
+
addedAt: record.addedAt,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function duplicateName() {
|
|
37
|
+
return AppError.conflict('Another list in this workspace already has that name', [
|
|
38
|
+
{ field: 'name', message: 'Already in use' },
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
function typeMismatch(expected, got) {
|
|
42
|
+
return AppError.validationFailed(`That record cannot join a ${expected} list`, [
|
|
43
|
+
{
|
|
44
|
+
field: 'target_type',
|
|
45
|
+
message: `Expected ${expected} to match the list's type, got ${got}`,
|
|
46
|
+
},
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
function alreadyMember() {
|
|
50
|
+
return AppError.conflict('That record is already on the list', [
|
|
51
|
+
{ field: 'target_id', message: 'Already a member' },
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
export function createListsService(dependencies) {
|
|
55
|
+
async function require(workspaceId, id) {
|
|
56
|
+
const list = await repository.findList(dependencies.db, workspaceId, id);
|
|
57
|
+
if (list === undefined) {
|
|
58
|
+
throw AppError.notFound('List not found');
|
|
59
|
+
}
|
|
60
|
+
return list;
|
|
61
|
+
}
|
|
62
|
+
async function requireTarget(workspaceId, targetType, targetId) {
|
|
63
|
+
const missing = await missingTargets(dependencies.db, workspaceId, targetType, [targetId]);
|
|
64
|
+
if (missing.length > 0) {
|
|
65
|
+
throw AppError.notFound('Record not found');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
async list(actor, filters, query) {
|
|
70
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
71
|
+
const window = readListWindow(query, LIST_SORTS, DEFAULT_LIST_SORT);
|
|
72
|
+
const rows = await repository.listLists(dependencies.db, workspaceId, filters, window);
|
|
73
|
+
return mapPage(toPage(rows, window, (row) => row.id), toView);
|
|
74
|
+
},
|
|
75
|
+
async get(actor, id) {
|
|
76
|
+
return toView(await require(requireWorkspaceId(actor), id));
|
|
77
|
+
},
|
|
78
|
+
async create(actor, input) {
|
|
79
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
80
|
+
const id = dependencies.createId('list');
|
|
81
|
+
return dependencies.transaction(async ({ tx, events }) => {
|
|
82
|
+
let created;
|
|
83
|
+
try {
|
|
84
|
+
created = await repository.insertList(tx, {
|
|
85
|
+
id,
|
|
86
|
+
workspaceId,
|
|
87
|
+
name: input.name,
|
|
88
|
+
description: input.description,
|
|
89
|
+
targetType: input.targetType,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
|
|
94
|
+
throw duplicateName();
|
|
95
|
+
}
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
events.emit('lists.list.created', { type: 'list', id: created.id }, {});
|
|
99
|
+
return toView({ ...created, memberCount: 0 });
|
|
100
|
+
}, { workspaceId, actor: toEventActor(actor) });
|
|
101
|
+
},
|
|
102
|
+
async update(actor, id, changes) {
|
|
103
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
104
|
+
const existing = await require(workspaceId, id);
|
|
105
|
+
const columns = {
|
|
106
|
+
...(changes.name === undefined ? {} : { name: changes.name }),
|
|
107
|
+
...(changes.description === undefined ? {} : { description: changes.description }),
|
|
108
|
+
};
|
|
109
|
+
const changed = changedKeys(existing, columns);
|
|
110
|
+
if (changed.length === 0) {
|
|
111
|
+
return toView(existing);
|
|
112
|
+
}
|
|
113
|
+
return dependencies.transaction(async ({ tx, events }) => {
|
|
114
|
+
let updated;
|
|
115
|
+
try {
|
|
116
|
+
updated = await repository.updateList(tx, workspaceId, id, {
|
|
117
|
+
...columns,
|
|
118
|
+
updatedAt: dependencies.now(),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
|
|
123
|
+
throw duplicateName();
|
|
124
|
+
}
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
if (updated === undefined) {
|
|
128
|
+
throw AppError.notFound('List not found');
|
|
129
|
+
}
|
|
130
|
+
events.emit('lists.list.updated', { type: 'list', id }, { changed });
|
|
131
|
+
return toView({ ...updated, memberCount: existing.memberCount });
|
|
132
|
+
}, { workspaceId, actor: toEventActor(actor) });
|
|
133
|
+
},
|
|
134
|
+
async remove(actor, id) {
|
|
135
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
136
|
+
await dependencies.transaction(async ({ tx, events }) => {
|
|
137
|
+
await require(workspaceId, id);
|
|
138
|
+
// Members cascade with the list; nothing else references it.
|
|
139
|
+
await repository.deleteList(tx, workspaceId, id);
|
|
140
|
+
events.emit('lists.list.deleted', { type: 'list', id }, {});
|
|
141
|
+
}, { workspaceId, actor: toEventActor(actor) });
|
|
142
|
+
},
|
|
143
|
+
async listMembers(actor, filters, query) {
|
|
144
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
145
|
+
// The list must exist. A caller reading members of a missing list gets a
|
|
146
|
+
// 404, not a silent empty page.
|
|
147
|
+
await require(workspaceId, filters.listId);
|
|
148
|
+
const window = readListWindow(query, LIST_MEMBER_SORTS, DEFAULT_LIST_MEMBER_SORT);
|
|
149
|
+
const rows = await repository.listListMembers(dependencies.db, workspaceId, filters, window);
|
|
150
|
+
const names = await resolveTargetNames(dependencies.db, workspaceId, rows.map((row) => ({
|
|
151
|
+
targetType: row.targetType,
|
|
152
|
+
targetId: row.targetId,
|
|
153
|
+
})));
|
|
154
|
+
const page = toPage(rows, window, (row) => row.id);
|
|
155
|
+
return mapPage(page, (row) => toMemberView(row, names.get(targetKey({
|
|
156
|
+
targetType: row.targetType,
|
|
157
|
+
targetId: row.targetId,
|
|
158
|
+
}))));
|
|
159
|
+
},
|
|
160
|
+
async addMember(actor, listId, input) {
|
|
161
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
162
|
+
const list = await require(workspaceId, listId);
|
|
163
|
+
if (list.targetType !== input.targetType) {
|
|
164
|
+
throw typeMismatch(list.targetType, input.targetType);
|
|
165
|
+
}
|
|
166
|
+
await requireTarget(workspaceId, input.targetType, input.targetId);
|
|
167
|
+
const id = dependencies.createId('listMember');
|
|
168
|
+
return dependencies.transaction(async ({ tx, events }) => {
|
|
169
|
+
let created;
|
|
170
|
+
try {
|
|
171
|
+
created = await repository.insertListMember(tx, {
|
|
172
|
+
id,
|
|
173
|
+
workspaceId,
|
|
174
|
+
listId,
|
|
175
|
+
targetType: input.targetType,
|
|
176
|
+
targetId: input.targetId,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
|
|
181
|
+
throw alreadyMember();
|
|
182
|
+
}
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
events.emit('lists.member.added', { type: input.targetType, id: input.targetId }, { listId });
|
|
186
|
+
const names = await resolveTargetNames(tx, workspaceId, [
|
|
187
|
+
{ targetType: input.targetType, targetId: input.targetId },
|
|
188
|
+
]);
|
|
189
|
+
return toMemberView(created, names.get(targetKey({ targetType: input.targetType, targetId: input.targetId })));
|
|
190
|
+
}, { workspaceId, actor: toEventActor(actor) });
|
|
191
|
+
},
|
|
192
|
+
async membershipsFor(actor, targetType, targetId) {
|
|
193
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
194
|
+
// The target must exist. A caller listing memberships of a missing record
|
|
195
|
+
// gets 404, not a silent empty list — same rule as notes/decisions.
|
|
196
|
+
await requireTarget(workspaceId, targetType, targetId);
|
|
197
|
+
const rows = await repository.listMembershipsForTarget(dependencies.db, workspaceId, targetType, targetId);
|
|
198
|
+
return rows.map(toMembershipView);
|
|
199
|
+
},
|
|
200
|
+
async removeMember(actor, listId, id) {
|
|
201
|
+
const workspaceId = requireWorkspaceId(actor);
|
|
202
|
+
await require(workspaceId, listId);
|
|
203
|
+
const existing = await repository.findListMember(dependencies.db, workspaceId, listId, id);
|
|
204
|
+
if (existing === undefined) {
|
|
205
|
+
throw AppError.notFound('List member not found');
|
|
206
|
+
}
|
|
207
|
+
await dependencies.transaction(async ({ tx, events }) => {
|
|
208
|
+
await repository.deleteListMember(tx, workspaceId, listId, id);
|
|
209
|
+
events.emit('lists.member.removed', { type: existing.targetType, id: existing.targetId }, { listId });
|
|
210
|
+
}, { workspaceId, actor: toEventActor(actor) });
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/modules/lists/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/modules/lists/tools.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAoB9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AA0ChD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CA8DpF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { RECORD_TARGET_TYPES } from '@kelpie/schemas';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { deleteResult, idArg, listWindowShape, pageResult, registerCrudTools, toListQuery, } from '../crudTools.js';
|
|
4
|
+
import { addMemberBody, createBody, listMemberResponse, listMembershipResponse, listResponse, toAddMemberInput, toCreateInput, toUpdateInput, updateBody, } from './routes.js';
|
|
5
|
+
/**
|
|
6
|
+
* `lists_*`. Same schemas and mappers as `/v1/lists`, so the two cannot drift.
|
|
7
|
+
*
|
|
8
|
+
* The list-level five come from `registerCrudTools`; the three membership tools
|
|
9
|
+
* are declared by hand because they hang off `/v1/lists/:id/members`, which does
|
|
10
|
+
* not fit the by-id CRUD shape.
|
|
11
|
+
*/
|
|
12
|
+
const listArgs = z.strictObject({
|
|
13
|
+
...listWindowShape,
|
|
14
|
+
q: z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Free text. Matches list names.'),
|
|
19
|
+
target_type: z
|
|
20
|
+
.enum(RECORD_TARGET_TYPES)
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Only lists that hold this kind of record.'),
|
|
23
|
+
});
|
|
24
|
+
const membersListArgs = z.strictObject({
|
|
25
|
+
...listWindowShape,
|
|
26
|
+
list_id: idArg.describe('The list whose members you want.'),
|
|
27
|
+
});
|
|
28
|
+
const addMemberArgs = addMemberBody.extend({
|
|
29
|
+
list_id: idArg.describe('The list to add to. Its type must match target_type.'),
|
|
30
|
+
});
|
|
31
|
+
const removeMemberArgs = z.strictObject({
|
|
32
|
+
list_id: idArg.describe('The list to remove from.'),
|
|
33
|
+
id: idArg.describe('The membership id, from list_members_list.'),
|
|
34
|
+
});
|
|
35
|
+
const membershipsForArgs = z.strictObject({
|
|
36
|
+
target_type: z.enum(RECORD_TARGET_TYPES).describe('The kind of record.'),
|
|
37
|
+
target_id: idArg.describe('The record whose list memberships you want.'),
|
|
38
|
+
});
|
|
39
|
+
export function registerListsTools(mcp, service) {
|
|
40
|
+
registerCrudTools(mcp, {
|
|
41
|
+
resource: 'lists',
|
|
42
|
+
subject: 'list',
|
|
43
|
+
about: 'A named collection of records of one type, chosen when the list is created and fixed for its lifetime.',
|
|
44
|
+
service,
|
|
45
|
+
render: listResponse,
|
|
46
|
+
listArgs,
|
|
47
|
+
toFilters: (args) => ({ term: args.q, targetType: args.target_type }),
|
|
48
|
+
createArgs: createBody,
|
|
49
|
+
toCreateInput,
|
|
50
|
+
updateArgs: updateBody.extend({ id: idArg }),
|
|
51
|
+
toUpdateInput,
|
|
52
|
+
});
|
|
53
|
+
mcp.tool({
|
|
54
|
+
name: 'list_members_list',
|
|
55
|
+
description: 'List the records on one list. Cursor paged. Mirrors GET /v1/lists/{id}/members.',
|
|
56
|
+
inputSchema: membersListArgs,
|
|
57
|
+
invoke: async (args, actor) => pageResult(await service.listMembers(actor, { listId: args.list_id }, toListQuery(args)), listMemberResponse),
|
|
58
|
+
});
|
|
59
|
+
mcp.tool({
|
|
60
|
+
name: 'list_members_add',
|
|
61
|
+
description: 'Add a record to a list. The record\'s type must match the list\'s. ' +
|
|
62
|
+
'Mirrors POST /v1/lists/{id}/members.',
|
|
63
|
+
inputSchema: addMemberArgs,
|
|
64
|
+
invoke: async (args, actor) => listMemberResponse(await service.addMember(actor, args.list_id, toAddMemberInput(args))),
|
|
65
|
+
});
|
|
66
|
+
mcp.tool({
|
|
67
|
+
name: 'list_members_remove',
|
|
68
|
+
description: 'Remove a record from a list. Mirrors DELETE /v1/lists/{id}/members/{memberId}.',
|
|
69
|
+
inputSchema: removeMemberArgs,
|
|
70
|
+
invoke: async (args, actor) => {
|
|
71
|
+
await service.removeMember(actor, args.list_id, args.id);
|
|
72
|
+
return deleteResult(args.id);
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
mcp.tool({
|
|
76
|
+
name: 'list_memberships_for',
|
|
77
|
+
description: 'Which lists is this record on? Returns one row per membership, with the ' +
|
|
78
|
+
'list joined in. Mirrors GET /v1/list-memberships.',
|
|
79
|
+
inputSchema: membershipsForArgs,
|
|
80
|
+
invoke: async (args, actor) => {
|
|
81
|
+
const memberships = await service.membershipsFor(actor, args.target_type, args.target_id);
|
|
82
|
+
return { data: memberships.map(listMembershipResponse), next_cursor: null };
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/modules/lists/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EACL,YAAY,EACZ,KAAK,EACL,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,WAAW,GACZ,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,UAAU,GACX,MAAM,aAAa,CAAA;AAGpB;;;;;;GAMG;AAEH,MAAM,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC;IAC9B,GAAG,eAAe;IAClB,CAAC,EAAE,CAAC;SACD,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,gCAAgC,CAAC;IAC7C,WAAW,EAAE,CAAC;SACX,IAAI,CAAC,mBAAmB,CAAC;SACzB,QAAQ,EAAE;SACV,QAAQ,CAAC,2CAA2C,CAAC;CACzD,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,CAAC;IACrC,GAAG,eAAe;IAClB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,kCAAkC,CAAC;CAC5D,CAAC,CAAA;AAEF,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,sDAAsD,CAAC;CAChF,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAAC,CAAC,YAAY,CAAC;IACtC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACnD,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,4CAA4C,CAAC;CACjE,CAAC,CAAA;AAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC,YAAY,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACxE,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,6CAA6C,CAAC;CACzE,CAAC,CAAA;AAEF,MAAM,UAAU,kBAAkB,CAAC,GAAoB,EAAE,OAAqB;IAC5E,iBAAiB,CAAC,GAAG,EAAE;QACrB,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,MAAM;QACf,KAAK,EACH,wGAAwG;QAC1G,OAAO;QACP,MAAM,EAAE,YAAY;QACpB,QAAQ;QACR,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QACrE,UAAU,EAAE,UAAU;QACtB,aAAa;QACb,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAC5C,aAAa;KACd,CAAC,CAAA;IAEF,GAAG,CAAC,IAAI,CAAC;QACP,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACT,iFAAiF;QACnF,WAAW,EAAE,eAAe;QAC5B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAC5B,UAAU,CACR,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,EAC7E,kBAAkB,CACnB;KACJ,CAAC,CAAA;IAEF,GAAG,CAAC,IAAI,CAAC;QACP,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,qEAAqE;YACrE,sCAAsC;QACxC,WAAW,EAAE,aAAa;QAC1B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAC5B,kBAAkB,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;KAC3F,CAAC,CAAA;IAEF,GAAG,CAAC,IAAI,CAAC;QACP,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EACT,gFAAgF;QAClF,WAAW,EAAE,gBAAgB;QAC7B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YAC5B,MAAM,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;YAExD,OAAO,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC9B,CAAC;KACF,CAAC,CAAA;IAEF,GAAG,CAAC,IAAI,CAAC;QACP,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EACT,0EAA0E;YAC1E,mDAAmD;QACrD,WAAW,EAAE,kBAAkB;QAC/B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YAC5B,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;YAEzF,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;QAC7E,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -25,6 +25,17 @@ export declare function findPerson(db: Queryable, workspaceId: string, id: strin
|
|
|
25
25
|
* is the second line of defence described in `lib/normalisation.ts`.
|
|
26
26
|
*/
|
|
27
27
|
export declare function findPersonByEmail(db: Queryable, workspaceId: string, email: string): Promise<PersonRecord | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Every person in this workspace whose email is exactly at `domain`, case-
|
|
30
|
+
* insensitive. Used by the email-domain auto-linker when a Company is created
|
|
31
|
+
* or its domain is set.
|
|
32
|
+
*
|
|
33
|
+
* Not `ilike '%@domain'`: that also matches `alex@sub.domain`, which the
|
|
34
|
+
* person-side matcher (exact `email.slice(at + 1) = companies.domain`) would
|
|
35
|
+
* never link. `split_part` peels off the address at the last `@`, keeping the
|
|
36
|
+
* two directions consistent.
|
|
37
|
+
*/
|
|
38
|
+
export declare function findPeopleByEmailDomain(db: Queryable, workspaceId: string, domain: string): Promise<PersonRecord[]>;
|
|
28
39
|
export declare function insertPerson(db: Queryable, values: PersonColumns): Promise<PersonRecord>;
|
|
29
40
|
export declare function updatePerson(db: Queryable, workspaceId: string, id: string, changes: Partial<PersonColumns>): Promise<PersonRecord | undefined>;
|
|
30
41
|
export declare function deletePerson(db: Queryable, workspaceId: string, id: string): Promise<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../src/modules/people/repository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,MAAM,YAAY,GAAG,OAAO,MAAM,CAAC,YAAY,CAAA;AAErD,mGAAmG;AACnG,MAAM,MAAM,aAAa,GAAG,OAAO,MAAM,CAAC,YAAY,CAAA;AAEtD,kHAAkH;AAClH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,YAAY,CAIrD,CAAA;AAED,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAEhD,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,uFAAuF;IACvF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACpD;AAqDD,mHAAmH;AACnH,wBAAgB,UAAU,CACxB,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC,CAOzB;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAQnC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAQnC;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAQ9F;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAQnC;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlG"}
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../src/modules/people/repository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,MAAM,YAAY,GAAG,OAAO,MAAM,CAAC,YAAY,CAAA;AAErD,mGAAmG;AACnG,MAAM,MAAM,aAAa,GAAG,OAAO,MAAM,CAAC,YAAY,CAAA;AAEtD,kHAAkH;AAClH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,YAAY,CAIrD,CAAA;AAED,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAEhD,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,uFAAuF;IACvF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACpD;AAqDD,mHAAmH;AACnH,wBAAgB,UAAU,CACxB,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC,CAOzB;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAQnC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAQnC;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,EAAE,CAAC,CAUzB;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAQ9F;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAQnC;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlG"}
|
|
@@ -84,6 +84,22 @@ export async function findPersonByEmail(db, workspaceId, email) {
|
|
|
84
84
|
.limit(1);
|
|
85
85
|
return found;
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Every person in this workspace whose email is exactly at `domain`, case-
|
|
89
|
+
* insensitive. Used by the email-domain auto-linker when a Company is created
|
|
90
|
+
* or its domain is set.
|
|
91
|
+
*
|
|
92
|
+
* Not `ilike '%@domain'`: that also matches `alex@sub.domain`, which the
|
|
93
|
+
* person-side matcher (exact `email.slice(at + 1) = companies.domain`) would
|
|
94
|
+
* never link. `split_part` peels off the address at the last `@`, keeping the
|
|
95
|
+
* two directions consistent.
|
|
96
|
+
*/
|
|
97
|
+
export async function findPeopleByEmailDomain(db, workspaceId, domain) {
|
|
98
|
+
return db
|
|
99
|
+
.select()
|
|
100
|
+
.from(people)
|
|
101
|
+
.where(and(eq(people.workspaceId, workspaceId), sql `split_part(${people.email}::text, '@', 2) = lower(${domain})`));
|
|
102
|
+
}
|
|
87
103
|
export async function insertPerson(db, values) {
|
|
88
104
|
const [created] = await db.insert(people).values(values).returning();
|
|
89
105
|
if (created === undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/modules/people/repository.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/modules/people/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/people/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/people/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAGrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAGjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAIjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,aAAa,CAAA;AAQpB,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3F;;;;;;;;GAQG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAA;IACtC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAA;IACxB,QAAQ,CAAC,cAAc,EAAE,gBAAgB,CAAA;CAC1C;AAwBD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAA;AAE1D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAA;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAA;IAC3C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,eAAe,EAAE,IAAI,GAAG,IAAI,CAAA;CACtC;AAED,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE1D,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;IACjG,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAClD,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACnE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACjF,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD;AAoCD,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,kBAAkB,GAAG,aAAa,CAkLnF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { changedKeys } from '../../lib/changes.js';
|
|
2
2
|
import { UNIQUE_VIOLATION, isReferenceViolation, postgresErrorCode } from '../../lib/database.js';
|
|
3
|
+
import { autoLinkPersonByEmailDomain } from '../../lib/emailDomainAutoLink.js';
|
|
3
4
|
import { AppError } from '../../lib/errors.js';
|
|
4
5
|
import { normaliseEmail } from '../../lib/normalisation.js';
|
|
5
6
|
import { mapPage, readListWindow, toPage } from '../../lib/pagination.js';
|
|
@@ -118,6 +119,14 @@ export function createPeopleService(dependencies) {
|
|
|
118
119
|
...describeCreation('Person'),
|
|
119
120
|
});
|
|
120
121
|
events.emit('people.person.created', { type: 'person', id: created.id }, {});
|
|
122
|
+
// Sync auto-link. Inside the same transaction so the response returns
|
|
123
|
+
// with the Position already visible to a follow-up read; without this
|
|
124
|
+
// the UI would not see the new Position until a manual refresh.
|
|
125
|
+
await autoLinkPersonByEmailDomain(tx, events, workspaceId, created, {
|
|
126
|
+
createId: dependencies.createId,
|
|
127
|
+
now: dependencies.now,
|
|
128
|
+
recordActivity: dependencies.recordActivity,
|
|
129
|
+
});
|
|
121
130
|
return toView(created);
|
|
122
131
|
}, { workspaceId, actor: toEventActor(actor) });
|
|
123
132
|
},
|
|
@@ -156,6 +165,15 @@ export function createPeopleService(dependencies) {
|
|
|
156
165
|
...describeUpdate(changed, PERSON_FIELD_LABELS, existing, columns),
|
|
157
166
|
});
|
|
158
167
|
events.emit('people.person.updated', { type: 'person', id }, { changed });
|
|
168
|
+
// Sync auto-link when the email moved. Same-transaction rationale as
|
|
169
|
+
// the create path above.
|
|
170
|
+
if (changed.includes('email')) {
|
|
171
|
+
await autoLinkPersonByEmailDomain(tx, events, workspaceId, updated, {
|
|
172
|
+
createId: dependencies.createId,
|
|
173
|
+
now: dependencies.now,
|
|
174
|
+
recordActivity: dependencies.recordActivity,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
159
177
|
return toView(updated);
|
|
160
178
|
}, { workspaceId, actor: toEventActor(actor) });
|
|
161
179
|
},
|