@clivly/core 0.11.0-next.0 → 0.11.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.
Files changed (43) hide show
  1. package/dist/adapter.d.cts +44 -7
  2. package/dist/adapter.d.mts +44 -7
  3. package/dist/auth-adapter.d.cts +6 -7
  4. package/dist/auth-adapter.d.mts +6 -7
  5. package/dist/builder.d.cts +12 -12
  6. package/dist/builder.d.mts +12 -12
  7. package/dist/drizzle.d.cts +5 -6
  8. package/dist/drizzle.d.mts +5 -6
  9. package/dist/{entity-config-BTAJe1Zj.mjs → entity-config-C0rtu-K_.mjs} +19 -2
  10. package/dist/{entity-config-CqJknGOn.cjs → entity-config-C2sKAti2.cjs} +19 -2
  11. package/dist/{entity-config-Ddgukq_E.d.cts → entity-config-OhC4Otkz.d.cts} +3 -1
  12. package/dist/{entity-config-Ddgukq_E.d.mts → entity-config-OhC4Otkz.d.mts} +3 -1
  13. package/dist/entity-config.cjs +1 -1
  14. package/dist/entity-config.d.cts +1 -1
  15. package/dist/entity-config.d.mts +1 -1
  16. package/dist/entity-config.mjs +1 -1
  17. package/dist/entity-heuristics.cjs +9 -7
  18. package/dist/entity-heuristics.d.cts +21 -21
  19. package/dist/entity-heuristics.d.mts +21 -21
  20. package/dist/entity-heuristics.mjs +9 -7
  21. package/dist/env-file.d.cts +6 -7
  22. package/dist/env-file.d.mts +6 -7
  23. package/dist/index.cjs +83 -1
  24. package/dist/index.d.cts +89 -22
  25. package/dist/index.d.mts +89 -22
  26. package/dist/index.mjs +80 -2
  27. package/dist/integration-state.d.cts +30 -31
  28. package/dist/integration-state.d.mts +30 -31
  29. package/dist/mapping-form.d.cts +6 -7
  30. package/dist/mapping-form.d.mts +6 -7
  31. package/dist/mapping-score.d.cts +14 -15
  32. package/dist/mapping-score.d.mts +14 -15
  33. package/dist/mappings-config.cjs +2 -1
  34. package/dist/mappings-config.d.cts +8 -7
  35. package/dist/mappings-config.d.mts +8 -7
  36. package/dist/mappings-config.mjs +2 -1
  37. package/dist/sync-engine.d.cts +15 -16
  38. package/dist/sync-engine.d.mts +15 -16
  39. package/dist/types.d.cts +96 -33
  40. package/dist/types.d.mts +96 -33
  41. package/dist/view-compiler.d.cts +10 -11
  42. package/dist/view-compiler.d.mts +10 -11
  43. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { Activity, Company, Contact, ContactFilters, CreateActivityInput, CreateCompanyInput, CreateContactInput, CreateDealInput, CreateTaskInput, Deal, RecordSource, Task, TaskFilters, UpdateContactInput, UpdateDealInput, UpdateTaskInput } from "./types.cjs";
1
+ import { Activity, Company, CompanyFilters, Contact, ContactFilters, CreateActivityInput, CreateCompanyInput, CreateContactInput, CreateDealInput, CreateTaskInput, Deal, RecordSource, Task, TaskFilters, UpdateCompanyInput, UpdateContactInput, UpdateDealInput, UpdateTaskInput } from "./types.cjs";
2
2
  //#region src/adapter.d.ts
3
3
  /**
4
4
  * The contract every ORM implementation fulfils. `packages/drizzle` is the first
@@ -8,7 +8,15 @@ import { Activity, Company, Contact, ContactFilters, CreateActivityInput, Create
8
8
  * one place tenant isolation is enforced for CRM data. Implementations only ever
9
9
  * read/write Clivly-owned `crm_*` tables; they never mutate host business tables.
10
10
  */
11
- interface CRMAdapter {
11
+ export interface CRMAdapter {
12
+ /**
13
+ * Soft-delete: sets `archivedAt` so the row drops out of lists while the
14
+ * deals, activities and tasks that reference it keep resolving. Mirrors the
15
+ * sync engine's archive-on-leave doctrine — a contact that disappears from
16
+ * the host view is archived, never deleted, for exactly this reason.
17
+ */
18
+ archiveCompany(orgId: string, id: string): Promise<Company>;
19
+ archiveContact(orgId: string, id: string): Promise<Contact>;
12
20
  archiveTask(orgId: string, id: string): Promise<Task>;
13
21
  completeTask(orgId: string, id: string): Promise<Task>;
14
22
  createActivity(orgId: string, data: CreateActivityInput): Promise<Activity>;
@@ -18,11 +26,33 @@ interface CRMAdapter {
18
26
  createTask(orgId: string, data: CreateTaskInput): Promise<Task>;
19
27
  deleteDeal(orgId: string, id: string): Promise<Deal | null>;
20
28
  getActivities(orgId: string, contactId: string): Promise<Activity[]>;
21
- getCompanies(orgId: string, filters?: {
22
- source?: RecordSource;
23
- }): Promise<Company[]>;
29
+ getCompanies(orgId: string, filters?: CompanyFilters): Promise<Company[]>;
30
+ /**
31
+ * The companies named by `ids`, for resolving a page of contacts to company
32
+ * names.
33
+ *
34
+ * `contacts.list` used to build that map from `getCompanies(orgId)` — every
35
+ * company in the org, to label at most one per listed contact. Scoping the
36
+ * fetch to the ids actually referenced keeps a bounded page of contacts from
37
+ * dragging an unbounded sibling query behind it.
38
+ *
39
+ * Returns only the rows that exist; a missing id is not an error, because a
40
+ * contact can reference a company archived since the page was built.
41
+ */
42
+ getCompaniesByIds(orgId: string, ids: string[]): Promise<Company[]>;
43
+ getCompany(orgId: string, id: string): Promise<Company | null>;
24
44
  getContact(orgId: string, id: string): Promise<Contact | null>;
25
45
  getContacts(orgId: string, filters?: ContactFilters): Promise<Contact[]>;
46
+ /**
47
+ * The contacts named by `ids`, for resolving a page of deals to contact
48
+ * names. See {@link CRMAdapter.getCompaniesByIds} — `deals.list` had the
49
+ * same unbounded-sibling problem.
50
+ *
51
+ * Deliberately unfiltered by archive state: a live deal pointing at an
52
+ * archived contact must still render that contact's name, which is the same
53
+ * reason `deals.list` never passed `excludeArchived` to `getContacts`.
54
+ */
55
+ getContactsByIds(orgId: string, ids: string[]): Promise<Contact[]>;
26
56
  getDeal(orgId: string, id: string): Promise<Deal | null>;
27
57
  getDeals(orgId: string, filters?: {
28
58
  source?: RecordSource;
@@ -35,11 +65,18 @@ interface CRMAdapter {
35
65
  */
36
66
  moveDeal(orgId: string, id: string, stage: Deal["stage"], afterId: string | null): Promise<Deal>;
37
67
  reopenTask(orgId: string, id: string): Promise<Task>;
68
+ /**
69
+ * Clear `archivedAt`, putting the row back in the lists. The inverse of
70
+ * `archiveCompany` / `archiveContact`, and what an "Undo" on an archive
71
+ * toast calls — archiving is reversible, so the UI should be able to say so.
72
+ */
73
+ unarchiveCompany(orgId: string, id: string): Promise<Company>;
74
+ unarchiveContact(orgId: string, id: string): Promise<Contact>;
75
+ updateCompany(orgId: string, id: string, data: UpdateCompanyInput): Promise<Company>;
38
76
  updateContact(orgId: string, id: string, data: UpdateContactInput): Promise<Contact>;
39
77
  updateDeal(orgId: string, id: string, data: UpdateDealInput): Promise<Deal>;
40
78
  updateDealStage(orgId: string, id: string, stage: Deal["stage"]): Promise<Deal>;
41
79
  updateTask(orgId: string, id: string, data: UpdateTaskInput): Promise<Task>;
42
80
  updateTaskStatus(orgId: string, id: string, status: Task["status"]): Promise<Task>;
43
81
  }
44
- //#endregion
45
- export { CRMAdapter };
82
+ //#endregion
@@ -1,4 +1,4 @@
1
- import { Activity, Company, Contact, ContactFilters, CreateActivityInput, CreateCompanyInput, CreateContactInput, CreateDealInput, CreateTaskInput, Deal, RecordSource, Task, TaskFilters, UpdateContactInput, UpdateDealInput, UpdateTaskInput } from "./types.mjs";
1
+ import { Activity, Company, CompanyFilters, Contact, ContactFilters, CreateActivityInput, CreateCompanyInput, CreateContactInput, CreateDealInput, CreateTaskInput, Deal, RecordSource, Task, TaskFilters, UpdateCompanyInput, UpdateContactInput, UpdateDealInput, UpdateTaskInput } from "./types.mjs";
2
2
  //#region src/adapter.d.ts
3
3
  /**
4
4
  * The contract every ORM implementation fulfils. `packages/drizzle` is the first
@@ -8,7 +8,15 @@ import { Activity, Company, Contact, ContactFilters, CreateActivityInput, Create
8
8
  * one place tenant isolation is enforced for CRM data. Implementations only ever
9
9
  * read/write Clivly-owned `crm_*` tables; they never mutate host business tables.
10
10
  */
11
- interface CRMAdapter {
11
+ export interface CRMAdapter {
12
+ /**
13
+ * Soft-delete: sets `archivedAt` so the row drops out of lists while the
14
+ * deals, activities and tasks that reference it keep resolving. Mirrors the
15
+ * sync engine's archive-on-leave doctrine — a contact that disappears from
16
+ * the host view is archived, never deleted, for exactly this reason.
17
+ */
18
+ archiveCompany(orgId: string, id: string): Promise<Company>;
19
+ archiveContact(orgId: string, id: string): Promise<Contact>;
12
20
  archiveTask(orgId: string, id: string): Promise<Task>;
13
21
  completeTask(orgId: string, id: string): Promise<Task>;
14
22
  createActivity(orgId: string, data: CreateActivityInput): Promise<Activity>;
@@ -18,11 +26,33 @@ interface CRMAdapter {
18
26
  createTask(orgId: string, data: CreateTaskInput): Promise<Task>;
19
27
  deleteDeal(orgId: string, id: string): Promise<Deal | null>;
20
28
  getActivities(orgId: string, contactId: string): Promise<Activity[]>;
21
- getCompanies(orgId: string, filters?: {
22
- source?: RecordSource;
23
- }): Promise<Company[]>;
29
+ getCompanies(orgId: string, filters?: CompanyFilters): Promise<Company[]>;
30
+ /**
31
+ * The companies named by `ids`, for resolving a page of contacts to company
32
+ * names.
33
+ *
34
+ * `contacts.list` used to build that map from `getCompanies(orgId)` — every
35
+ * company in the org, to label at most one per listed contact. Scoping the
36
+ * fetch to the ids actually referenced keeps a bounded page of contacts from
37
+ * dragging an unbounded sibling query behind it.
38
+ *
39
+ * Returns only the rows that exist; a missing id is not an error, because a
40
+ * contact can reference a company archived since the page was built.
41
+ */
42
+ getCompaniesByIds(orgId: string, ids: string[]): Promise<Company[]>;
43
+ getCompany(orgId: string, id: string): Promise<Company | null>;
24
44
  getContact(orgId: string, id: string): Promise<Contact | null>;
25
45
  getContacts(orgId: string, filters?: ContactFilters): Promise<Contact[]>;
46
+ /**
47
+ * The contacts named by `ids`, for resolving a page of deals to contact
48
+ * names. See {@link CRMAdapter.getCompaniesByIds} — `deals.list` had the
49
+ * same unbounded-sibling problem.
50
+ *
51
+ * Deliberately unfiltered by archive state: a live deal pointing at an
52
+ * archived contact must still render that contact's name, which is the same
53
+ * reason `deals.list` never passed `excludeArchived` to `getContacts`.
54
+ */
55
+ getContactsByIds(orgId: string, ids: string[]): Promise<Contact[]>;
26
56
  getDeal(orgId: string, id: string): Promise<Deal | null>;
27
57
  getDeals(orgId: string, filters?: {
28
58
  source?: RecordSource;
@@ -35,11 +65,18 @@ interface CRMAdapter {
35
65
  */
36
66
  moveDeal(orgId: string, id: string, stage: Deal["stage"], afterId: string | null): Promise<Deal>;
37
67
  reopenTask(orgId: string, id: string): Promise<Task>;
68
+ /**
69
+ * Clear `archivedAt`, putting the row back in the lists. The inverse of
70
+ * `archiveCompany` / `archiveContact`, and what an "Undo" on an archive
71
+ * toast calls — archiving is reversible, so the UI should be able to say so.
72
+ */
73
+ unarchiveCompany(orgId: string, id: string): Promise<Company>;
74
+ unarchiveContact(orgId: string, id: string): Promise<Contact>;
75
+ updateCompany(orgId: string, id: string, data: UpdateCompanyInput): Promise<Company>;
38
76
  updateContact(orgId: string, id: string, data: UpdateContactInput): Promise<Contact>;
39
77
  updateDeal(orgId: string, id: string, data: UpdateDealInput): Promise<Deal>;
40
78
  updateDealStage(orgId: string, id: string, stage: Deal["stage"]): Promise<Deal>;
41
79
  updateTask(orgId: string, id: string, data: UpdateTaskInput): Promise<Task>;
42
80
  updateTaskStatus(orgId: string, id: string, status: Task["status"]): Promise<Task>;
43
81
  }
44
- //#endregion
45
- export { CRMAdapter };
82
+ //#endregion
@@ -1,6 +1,6 @@
1
1
  import { CrmRole } from "./types.cjs";
2
2
  //#region src/auth-adapter.d.ts
3
- interface ClivlyUser {
3
+ export interface ClivlyUser {
4
4
  email: string;
5
5
  id: string;
6
6
  name?: string;
@@ -13,17 +13,16 @@ interface ClivlyUser {
13
13
  * This answers "who is this person?" only. Authorization ("what can they do in
14
14
  * this org?") is the separate `crm_members` layer — see `MembershipResolver`.
15
15
  */
16
- interface ClivlyAuthAdapter {
16
+ export interface ClivlyAuthAdapter {
17
17
  getUser(req: Request): Promise<ClivlyUser | null>;
18
18
  }
19
- declare function authCustom(resolver: (req: Request) => Promise<ClivlyUser | null> | ClivlyUser | null): ClivlyAuthAdapter;
20
- interface CrmMembership {
19
+ export declare function authCustom(resolver: (req: Request) => Promise<ClivlyUser | null> | ClivlyUser | null): ClivlyAuthAdapter;
20
+ export interface CrmMembership {
21
21
  orgId: string;
22
22
  role: CrmRole;
23
23
  userId: string;
24
24
  }
25
- interface MembershipResolver {
25
+ export interface MembershipResolver {
26
26
  getMembership(userId: string, orgId: string): Promise<CrmMembership | null>;
27
27
  }
28
- //#endregion
29
- export { ClivlyAuthAdapter, ClivlyUser, CrmMembership, MembershipResolver, authCustom };
28
+ //#endregion
@@ -1,6 +1,6 @@
1
1
  import { CrmRole } from "./types.mjs";
2
2
  //#region src/auth-adapter.d.ts
3
- interface ClivlyUser {
3
+ export interface ClivlyUser {
4
4
  email: string;
5
5
  id: string;
6
6
  name?: string;
@@ -13,17 +13,16 @@ interface ClivlyUser {
13
13
  * This answers "who is this person?" only. Authorization ("what can they do in
14
14
  * this org?") is the separate `crm_members` layer — see `MembershipResolver`.
15
15
  */
16
- interface ClivlyAuthAdapter {
16
+ export interface ClivlyAuthAdapter {
17
17
  getUser(req: Request): Promise<ClivlyUser | null>;
18
18
  }
19
- declare function authCustom(resolver: (req: Request) => Promise<ClivlyUser | null> | ClivlyUser | null): ClivlyAuthAdapter;
20
- interface CrmMembership {
19
+ export declare function authCustom(resolver: (req: Request) => Promise<ClivlyUser | null> | ClivlyUser | null): ClivlyAuthAdapter;
20
+ export interface CrmMembership {
21
21
  orgId: string;
22
22
  role: CrmRole;
23
23
  userId: string;
24
24
  }
25
- interface MembershipResolver {
25
+ export interface MembershipResolver {
26
26
  getMembership(userId: string, orgId: string): Promise<CrmMembership | null>;
27
27
  }
28
- //#endregion
29
- export { ClivlyAuthAdapter, ClivlyUser, CrmMembership, MembershipResolver, authCustom };
28
+ //#endregion
@@ -1,4 +1,4 @@
1
- import { R as ProjectionMapping, m as DiscoveredSchemaTable } from "./entity-config-Ddgukq_E.cjs";
1
+ import { R as ProjectionMapping, m as DiscoveredSchemaTable } from "./entity-config-OhC4Otkz.cjs";
2
2
  //#region src/relationship-graph.d.ts
3
3
  /**
4
4
  * A bidirectional relationship graph derived from discovery metadata.
@@ -82,14 +82,14 @@ interface RelationshipGraph {
82
82
  nodes: RelationshipNode[];
83
83
  }
84
84
  /** Every edge whose `fromTable` is `table`, in either direction. */
85
- declare function edgesFrom(graph: RelationshipGraph, table: string): RelationshipEdge[];
85
+ export declare function edgesFrom(graph: RelationshipGraph, table: string): RelationshipEdge[];
86
86
  /**
87
87
  * Build the bidirectional relationship graph for a discovered schema.
88
88
  *
89
89
  * No table, column, or relationship is ever named in this function — the
90
90
  * only input is the schema itself.
91
91
  */
92
- declare function buildRelationshipGraph(schema: DiscoveredSchemaTable[]): RelationshipGraph;
92
+ export declare function buildRelationshipGraph(schema: DiscoveredSchemaTable[]): RelationshipGraph;
93
93
  //#endregion
94
94
  //#region src/path-enumeration.d.ts
95
95
  /**
@@ -120,11 +120,11 @@ declare function buildRelationshipGraph(schema: DiscoveredSchemaTable[]): Relati
120
120
  * the graph and the starting table.
121
121
  */
122
122
  /** Spec-mandated: how many edges deep a path may go. */
123
- declare const MAX_HOPS = 3;
123
+ export declare const MAX_HOPS = 3;
124
124
  /** Spec-mandated: how many candidate paths may be considered before stopping. */
125
- declare const MAX_CANDIDATES = 200;
125
+ export declare const MAX_CANDIDATES = 200;
126
126
  /** Spec-mandated: how many ranked results may be displayed. */
127
- declare const MAX_RESULTS = 50;
127
+ export declare const MAX_RESULTS = 50;
128
128
  /** Which budget stopped the walk. Absent when nothing was cut. */
129
129
  type PathTruncationCause = "candidate-budget" | "result-limit";
130
130
  interface EnumeratedPath {
@@ -185,7 +185,7 @@ interface EnumeratePathsOptions {
185
185
  * defect — and it is precisely why truncation is reported, so the UI can
186
186
  * offer a narrower search instead of implying the list is complete.
187
187
  */
188
- declare function enumeratePaths(graph: RelationshipGraph, startTable: string, options?: EnumeratePathsOptions): PathEnumeration;
188
+ export declare function enumeratePaths(graph: RelationshipGraph, startTable: string, options?: EnumeratePathsOptions): PathEnumeration;
189
189
  //#endregion
190
190
  //#region src/path-compiler.d.ts
191
191
  /** A field the user picked, optionally reached through a path. */
@@ -214,7 +214,7 @@ interface CompilePathsOptions {
214
214
  * the point: the alternative — emitting a plausible-looking mapping — is the
215
215
  * defect class this whole body of work exists to close.
216
216
  */
217
- declare class PathCompileError extends Error {
217
+ export declare class PathCompileError extends Error {
218
218
  constructor(message: string);
219
219
  }
220
220
  /**
@@ -225,7 +225,7 @@ declare class PathCompileError extends Error {
225
225
  * mapping it returns satisfies `projectionSchema` and, given a schema whose
226
226
  * tables carry rich metadata, `validateProjection`.
227
227
  */
228
- declare function compilePaths(options: CompilePathsOptions): ProjectionMapping;
228
+ export declare function compilePaths(options: CompilePathsOptions): ProjectionMapping;
229
229
  //#endregion
230
230
  //#region src/starting-record-change.d.ts
231
231
  /**
@@ -297,7 +297,7 @@ interface ClassifyStartingRecordChangeOptions {
297
297
  * throws, because its caller is a confirmation dialog that must be able to
298
298
  * render an answer for any proposed change, including a nonsensical one.
299
299
  */
300
- declare function classifyStartingRecordChange(options: ClassifyStartingRecordChangeOptions): StartingRecordChangeImpact;
300
+ export declare function classifyStartingRecordChange(options: ClassifyStartingRecordChangeOptions): StartingRecordChangeImpact;
301
301
  //#endregion
302
302
  //#region src/starting-record-eligibility.d.ts
303
303
  /**
@@ -331,6 +331,6 @@ interface StartingRecordOption {
331
331
  * No table, column, or relationship is ever named in this function — the
332
332
  * only input is the schema itself.
333
333
  */
334
- declare function listStartingRecordOptions(schema: DiscoveredSchemaTable[]): StartingRecordOption[];
334
+ export declare function listStartingRecordOptions(schema: DiscoveredSchemaTable[]): StartingRecordOption[];
335
335
  //#endregion
336
- export { type ClassifyStartingRecordChangeOptions, type CompilePathsOptions, type CompositePrimaryKeyReason, type EnumeratePathsOptions, type EnumeratedPath, type IneligibilityReason, MAX_CANDIDATES, MAX_HOPS, MAX_RESULTS, type NoPrimaryKeyReason, type NoRichMetaReason, PathCompileError, type PathEnumeration, type PathTruncationCause, type PickedField, type RelationshipCardinality, type RelationshipDirection, type RelationshipEdge, type RelationshipGraph, type RelationshipNode, type StartingRecordChangeImpact, type StartingRecordOption, buildRelationshipGraph, classifyStartingRecordChange, compilePaths, edgesFrom, enumeratePaths, listStartingRecordOptions };
336
+ export type { ClassifyStartingRecordChangeOptions, CompilePathsOptions, CompositePrimaryKeyReason, EnumeratePathsOptions, EnumeratedPath, IneligibilityReason, NoPrimaryKeyReason, NoRichMetaReason, PathEnumeration, PathTruncationCause, PickedField, RelationshipCardinality, RelationshipDirection, RelationshipEdge, RelationshipGraph, RelationshipNode, StartingRecordChangeImpact, StartingRecordOption };
@@ -1,4 +1,4 @@
1
- import { R as ProjectionMapping, m as DiscoveredSchemaTable } from "./entity-config-Ddgukq_E.mjs";
1
+ import { R as ProjectionMapping, m as DiscoveredSchemaTable } from "./entity-config-OhC4Otkz.mjs";
2
2
  //#region src/relationship-graph.d.ts
3
3
  /**
4
4
  * A bidirectional relationship graph derived from discovery metadata.
@@ -82,14 +82,14 @@ interface RelationshipGraph {
82
82
  nodes: RelationshipNode[];
83
83
  }
84
84
  /** Every edge whose `fromTable` is `table`, in either direction. */
85
- declare function edgesFrom(graph: RelationshipGraph, table: string): RelationshipEdge[];
85
+ export declare function edgesFrom(graph: RelationshipGraph, table: string): RelationshipEdge[];
86
86
  /**
87
87
  * Build the bidirectional relationship graph for a discovered schema.
88
88
  *
89
89
  * No table, column, or relationship is ever named in this function — the
90
90
  * only input is the schema itself.
91
91
  */
92
- declare function buildRelationshipGraph(schema: DiscoveredSchemaTable[]): RelationshipGraph;
92
+ export declare function buildRelationshipGraph(schema: DiscoveredSchemaTable[]): RelationshipGraph;
93
93
  //#endregion
94
94
  //#region src/path-enumeration.d.ts
95
95
  /**
@@ -120,11 +120,11 @@ declare function buildRelationshipGraph(schema: DiscoveredSchemaTable[]): Relati
120
120
  * the graph and the starting table.
121
121
  */
122
122
  /** Spec-mandated: how many edges deep a path may go. */
123
- declare const MAX_HOPS = 3;
123
+ export declare const MAX_HOPS = 3;
124
124
  /** Spec-mandated: how many candidate paths may be considered before stopping. */
125
- declare const MAX_CANDIDATES = 200;
125
+ export declare const MAX_CANDIDATES = 200;
126
126
  /** Spec-mandated: how many ranked results may be displayed. */
127
- declare const MAX_RESULTS = 50;
127
+ export declare const MAX_RESULTS = 50;
128
128
  /** Which budget stopped the walk. Absent when nothing was cut. */
129
129
  type PathTruncationCause = "candidate-budget" | "result-limit";
130
130
  interface EnumeratedPath {
@@ -185,7 +185,7 @@ interface EnumeratePathsOptions {
185
185
  * defect — and it is precisely why truncation is reported, so the UI can
186
186
  * offer a narrower search instead of implying the list is complete.
187
187
  */
188
- declare function enumeratePaths(graph: RelationshipGraph, startTable: string, options?: EnumeratePathsOptions): PathEnumeration;
188
+ export declare function enumeratePaths(graph: RelationshipGraph, startTable: string, options?: EnumeratePathsOptions): PathEnumeration;
189
189
  //#endregion
190
190
  //#region src/path-compiler.d.ts
191
191
  /** A field the user picked, optionally reached through a path. */
@@ -214,7 +214,7 @@ interface CompilePathsOptions {
214
214
  * the point: the alternative — emitting a plausible-looking mapping — is the
215
215
  * defect class this whole body of work exists to close.
216
216
  */
217
- declare class PathCompileError extends Error {
217
+ export declare class PathCompileError extends Error {
218
218
  constructor(message: string);
219
219
  }
220
220
  /**
@@ -225,7 +225,7 @@ declare class PathCompileError extends Error {
225
225
  * mapping it returns satisfies `projectionSchema` and, given a schema whose
226
226
  * tables carry rich metadata, `validateProjection`.
227
227
  */
228
- declare function compilePaths(options: CompilePathsOptions): ProjectionMapping;
228
+ export declare function compilePaths(options: CompilePathsOptions): ProjectionMapping;
229
229
  //#endregion
230
230
  //#region src/starting-record-change.d.ts
231
231
  /**
@@ -297,7 +297,7 @@ interface ClassifyStartingRecordChangeOptions {
297
297
  * throws, because its caller is a confirmation dialog that must be able to
298
298
  * render an answer for any proposed change, including a nonsensical one.
299
299
  */
300
- declare function classifyStartingRecordChange(options: ClassifyStartingRecordChangeOptions): StartingRecordChangeImpact;
300
+ export declare function classifyStartingRecordChange(options: ClassifyStartingRecordChangeOptions): StartingRecordChangeImpact;
301
301
  //#endregion
302
302
  //#region src/starting-record-eligibility.d.ts
303
303
  /**
@@ -331,6 +331,6 @@ interface StartingRecordOption {
331
331
  * No table, column, or relationship is ever named in this function — the
332
332
  * only input is the schema itself.
333
333
  */
334
- declare function listStartingRecordOptions(schema: DiscoveredSchemaTable[]): StartingRecordOption[];
334
+ export declare function listStartingRecordOptions(schema: DiscoveredSchemaTable[]): StartingRecordOption[];
335
335
  //#endregion
336
- export { type ClassifyStartingRecordChangeOptions, type CompilePathsOptions, type CompositePrimaryKeyReason, type EnumeratePathsOptions, type EnumeratedPath, type IneligibilityReason, MAX_CANDIDATES, MAX_HOPS, MAX_RESULTS, type NoPrimaryKeyReason, type NoRichMetaReason, PathCompileError, type PathEnumeration, type PathTruncationCause, type PickedField, type RelationshipCardinality, type RelationshipDirection, type RelationshipEdge, type RelationshipGraph, type RelationshipNode, type StartingRecordChangeImpact, type StartingRecordOption, buildRelationshipGraph, classifyStartingRecordChange, compilePaths, edgesFrom, enumeratePaths, listStartingRecordOptions };
336
+ export type { ClassifyStartingRecordChangeOptions, CompilePathsOptions, CompositePrimaryKeyReason, EnumeratePathsOptions, EnumeratedPath, IneligibilityReason, NoPrimaryKeyReason, NoRichMetaReason, PathEnumeration, PathTruncationCause, PickedField, RelationshipCardinality, RelationshipDirection, RelationshipEdge, RelationshipGraph, RelationshipNode, StartingRecordChangeImpact, StartingRecordOption };
@@ -1,4 +1,4 @@
1
- import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-Ddgukq_E.cjs";
1
+ import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-OhC4Otkz.cjs";
2
2
  import { Table } from "drizzle-orm";
3
3
  //#region src/drizzle.d.ts
4
4
  /**
@@ -13,14 +13,14 @@ import { Table } from "drizzle-orm";
13
13
  * "confirmed no constraints", and projection validation fails closed on the
14
14
  * former.
15
15
  */
16
- declare function buildUniqueConstraints(table: unknown): string[][] | undefined;
16
+ export declare function buildUniqueConstraints(table: unknown): string[][] | undefined;
17
17
  /**
18
18
  * Per-column metadata (type, PK, nullability, FK edges) for a Drizzle table.
19
19
  * Structural only — no DB round-trip, so it is safe to recompute on every
20
20
  * heartbeat. FK reflection is best-effort; a non-Postgres table still gets
21
21
  * name/type/PK/nullable.
22
22
  */
23
- declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
23
+ export declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
24
24
  /**
25
25
  * Derive Clivly's discovery shape (table + column names) from a Drizzle schema
26
26
  * object — the `* as schema` you pass to `drizzle(client, { schema })`. This
@@ -36,8 +36,7 @@ declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
36
36
  * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
37
37
  * stays dependency-free.
38
38
  */
39
- declare function discoverFromDrizzle(schema: Record<string, unknown>, options?: {
39
+ export declare function discoverFromDrizzle(schema: Record<string, unknown>, options?: {
40
40
  allowEmpty?: boolean;
41
41
  }): DiscoveredSchemaTable[];
42
- //#endregion
43
- export { buildColumnsMeta, buildUniqueConstraints, discoverFromDrizzle };
42
+ //#endregion
@@ -1,4 +1,4 @@
1
- import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-Ddgukq_E.mjs";
1
+ import { m as DiscoveredSchemaTable, p as DiscoveredColumnMeta } from "./entity-config-OhC4Otkz.mjs";
2
2
  import { Table } from "drizzle-orm";
3
3
  //#region src/drizzle.d.ts
4
4
  /**
@@ -13,14 +13,14 @@ import { Table } from "drizzle-orm";
13
13
  * "confirmed no constraints", and projection validation fails closed on the
14
14
  * former.
15
15
  */
16
- declare function buildUniqueConstraints(table: unknown): string[][] | undefined;
16
+ export declare function buildUniqueConstraints(table: unknown): string[][] | undefined;
17
17
  /**
18
18
  * Per-column metadata (type, PK, nullability, FK edges) for a Drizzle table.
19
19
  * Structural only — no DB round-trip, so it is safe to recompute on every
20
20
  * heartbeat. FK reflection is best-effort; a non-Postgres table still gets
21
21
  * name/type/PK/nullable.
22
22
  */
23
- declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
23
+ export declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
24
24
  /**
25
25
  * Derive Clivly's discovery shape (table + column names) from a Drizzle schema
26
26
  * object — the `* as schema` you pass to `drizzle(client, { schema })`. This
@@ -36,8 +36,7 @@ declare function buildColumnsMeta(table: Table): DiscoveredColumnMeta[];
36
36
  * when you import this entry (`@clivly/core/drizzle`); the rest of `@clivly/core`
37
37
  * stays dependency-free.
38
38
  */
39
- declare function discoverFromDrizzle(schema: Record<string, unknown>, options?: {
39
+ export declare function discoverFromDrizzle(schema: Record<string, unknown>, options?: {
40
40
  allowEmpty?: boolean;
41
41
  }): DiscoveredSchemaTable[];
42
- //#endregion
43
- export { buildColumnsMeta, buildUniqueConstraints, discoverFromDrizzle };
42
+ //#endregion
@@ -234,7 +234,8 @@ function checkFanOut(errors, projection, resolver, base, basePk) {
234
234
  });
235
235
  return;
236
236
  }
237
- if (!coversUniqueKey(joinTable, identityRefs(projection.identity, basePk).filter((ref) => ref.table === join.key).map((ref) => ref.column))) errors.push({
237
+ const identityColumns = identityRefs(projection.identity, basePk).filter((ref) => ref.table === join.key).map((ref) => ref.column);
238
+ if (!coversUniqueKey(joinTable, identityColumns)) errors.push({
238
239
  path: identityPath,
239
240
  message: `identity does not uniquely identify a row of "${joinTable.name}", which fans out — include a unique key of that table`
240
241
  });
@@ -364,7 +365,9 @@ const CANONICAL_FIELDS = {
364
365
  "name",
365
366
  "domain",
366
367
  "industry",
367
- "size"
368
+ "size",
369
+ "email",
370
+ "phone"
368
371
  ],
369
372
  deal: [
370
373
  "name",
@@ -522,6 +525,20 @@ const entitySchema = z.strictObject({
522
525
  /** Named relationships to other entities in this config. */
523
526
  relationships: z.record(z.string(), relationshipSchema).optional(),
524
527
  /**
528
+ * Treat rows from this entity as their company's point of contact.
529
+ *
530
+ * Opt-in, and only meaningful on a `contact` entity that resolves a company.
531
+ * Hosts whose schema knows who owns an account (an `owner` role on a
532
+ * membership table, say) can declare a narrow entity for those rows and have
533
+ * the CRM keep each company's point of contact current automatically.
534
+ *
535
+ * Sync only manages companies nobody has intervened on: the moment a person
536
+ * picks a point of contact in the CRM, that company is stamped and left
537
+ * alone. Without that the user's choice would be silently reverted on the
538
+ * next run — see `syncPrimaryContacts` and `host-owned-fields.ts`.
539
+ */
540
+ isPrimaryContact: z.boolean().optional(),
541
+ /**
525
542
  * For a "custom" entity, the crm_object_types row this materializes into.
526
543
  * Server-generated, so pasting one into config couples the file to a
527
544
  * specific workspace. Prefer declaring `objectType` and letting
@@ -234,7 +234,8 @@ function checkFanOut(errors, projection, resolver, base, basePk) {
234
234
  });
235
235
  return;
236
236
  }
237
- if (!require_schema_meta.coversUniqueKey(joinTable, require_projection.identityRefs(projection.identity, basePk).filter((ref) => ref.table === join.key).map((ref) => ref.column))) errors.push({
237
+ const identityColumns = require_projection.identityRefs(projection.identity, basePk).filter((ref) => ref.table === join.key).map((ref) => ref.column);
238
+ if (!require_schema_meta.coversUniqueKey(joinTable, identityColumns)) errors.push({
238
239
  path: identityPath,
239
240
  message: `identity does not uniquely identify a row of "${joinTable.name}", which fans out — include a unique key of that table`
240
241
  });
@@ -364,7 +365,9 @@ const CANONICAL_FIELDS = {
364
365
  "name",
365
366
  "domain",
366
367
  "industry",
367
- "size"
368
+ "size",
369
+ "email",
370
+ "phone"
368
371
  ],
369
372
  deal: [
370
373
  "name",
@@ -522,6 +525,20 @@ const entitySchema = zod.z.strictObject({
522
525
  /** Named relationships to other entities in this config. */
523
526
  relationships: zod.z.record(zod.z.string(), relationshipSchema).optional(),
524
527
  /**
528
+ * Treat rows from this entity as their company's point of contact.
529
+ *
530
+ * Opt-in, and only meaningful on a `contact` entity that resolves a company.
531
+ * Hosts whose schema knows who owns an account (an `owner` role on a
532
+ * membership table, say) can declare a narrow entity for those rows and have
533
+ * the CRM keep each company's point of contact current automatically.
534
+ *
535
+ * Sync only manages companies nobody has intervened on: the moment a person
536
+ * picks a point of contact in the CRM, that company is stamped and left
537
+ * alone. Without that the user's choice would be silently reverted on the
538
+ * next run — see `syncPrimaryContacts` and `host-owned-fields.ts`.
539
+ */
540
+ isPrimaryContact: zod.z.boolean().optional(),
541
+ /**
525
542
  * For a "custom" entity, the crm_object_types row this materializes into.
526
543
  * Server-generated, so pasting one into config couples the file to a
527
544
  * specific workspace. Prefer declaring `objectType` and letting
@@ -169,7 +169,7 @@ type CrmConcept = (typeof CRM_CONCEPTS)[number];
169
169
  */
170
170
  declare const CANONICAL_FIELDS: {
171
171
  readonly contact: readonly ["name", "email", "phone", "title", "status"];
172
- readonly company: readonly ["name", "domain", "industry", "size"];
172
+ readonly company: readonly ["name", "domain", "industry", "size", "email", "phone"];
173
173
  readonly deal: readonly ["name", "value", "stage"];
174
174
  };
175
175
  /**
@@ -354,6 +354,7 @@ declare const entitySchema: z.ZodObject<{
354
354
  $raw: z.ZodString;
355
355
  }, z.core.$strict>]>;
356
356
  }, z.core.$strict>>>;
357
+ isPrimaryContact: z.ZodOptional<z.ZodBoolean>;
357
358
  targetObjectTypeId: z.ZodOptional<z.ZodString>;
358
359
  objectType: z.ZodOptional<z.ZodObject<{
359
360
  name: z.ZodString;
@@ -454,6 +455,7 @@ declare const entitiesConfigSchema: z.ZodObject<{
454
455
  $raw: z.ZodString;
455
456
  }, z.core.$strict>]>;
456
457
  }, z.core.$strict>>>;
458
+ isPrimaryContact: z.ZodOptional<z.ZodBoolean>;
457
459
  targetObjectTypeId: z.ZodOptional<z.ZodString>;
458
460
  objectType: z.ZodOptional<z.ZodObject<{
459
461
  name: z.ZodString;
@@ -169,7 +169,7 @@ type CrmConcept = (typeof CRM_CONCEPTS)[number];
169
169
  */
170
170
  declare const CANONICAL_FIELDS: {
171
171
  readonly contact: readonly ["name", "email", "phone", "title", "status"];
172
- readonly company: readonly ["name", "domain", "industry", "size"];
172
+ readonly company: readonly ["name", "domain", "industry", "size", "email", "phone"];
173
173
  readonly deal: readonly ["name", "value", "stage"];
174
174
  };
175
175
  /**
@@ -354,6 +354,7 @@ declare const entitySchema: z.ZodObject<{
354
354
  $raw: z.ZodString;
355
355
  }, z.core.$strict>]>;
356
356
  }, z.core.$strict>>>;
357
+ isPrimaryContact: z.ZodOptional<z.ZodBoolean>;
357
358
  targetObjectTypeId: z.ZodOptional<z.ZodString>;
358
359
  objectType: z.ZodOptional<z.ZodObject<{
359
360
  name: z.ZodString;
@@ -454,6 +455,7 @@ declare const entitiesConfigSchema: z.ZodObject<{
454
455
  $raw: z.ZodString;
455
456
  }, z.core.$strict>]>;
456
457
  }, z.core.$strict>>>;
458
+ isPrimaryContact: z.ZodOptional<z.ZodBoolean>;
457
459
  targetObjectTypeId: z.ZodOptional<z.ZodString>;
458
460
  objectType: z.ZodOptional<z.ZodObject<{
459
461
  name: z.ZodString;
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_entity_config = require("./entity-config-CqJknGOn.cjs");
2
+ const require_entity_config = require("./entity-config-C2sKAti2.cjs");
3
3
  exports.CANONICAL_FIELDS = require_entity_config.CANONICAL_FIELDS;
4
4
  exports.CRM_CONCEPTS = require_entity_config.CRM_CONCEPTS;
5
5
  exports.CUSTOM_CONCEPT = require_entity_config.CUSTOM_CONCEPT;
@@ -1,2 +1,2 @@
1
- import { A as relationshipsSchema, C as customObjectDeclarations, D as missingRequiredFields, E as filterSchema, M as validateEntitiesConfig, O as projectionFields, S as RelationshipsMap, T as entitiesConfigSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipSpec, c as ClivlyEntityConfigInput, d as CrmConcept, f as CustomObjectDeclaration, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as requiredFieldsFor, k as relationshipSchema, l as ConfigValidationError, m as DiscoveredSchemaTable, n as CRM_CONCEPTS, o as ClivlyEntitiesConfigInput, p as DiscoveredColumnMeta, r as CUSTOM_CONCEPT, s as ClivlyEntityConfig, t as CANONICAL_FIELDS, u as ConfigValidationResult, v as MaterializingConcept, w as defineClivlyConfig, x as RelationshipVia, y as REQUIRED_FIELDS } from "./entity-config-Ddgukq_E.cjs";
1
+ import { A as relationshipsSchema, C as customObjectDeclarations, D as missingRequiredFields, E as filterSchema, M as validateEntitiesConfig, O as projectionFields, S as RelationshipsMap, T as entitiesConfigSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipSpec, c as ClivlyEntityConfigInput, d as CrmConcept, f as CustomObjectDeclaration, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as requiredFieldsFor, k as relationshipSchema, l as ConfigValidationError, m as DiscoveredSchemaTable, n as CRM_CONCEPTS, o as ClivlyEntitiesConfigInput, p as DiscoveredColumnMeta, r as CUSTOM_CONCEPT, s as ClivlyEntityConfig, t as CANONICAL_FIELDS, u as ConfigValidationResult, v as MaterializingConcept, w as defineClivlyConfig, x as RelationshipVia, y as REQUIRED_FIELDS } from "./entity-config-OhC4Otkz.cjs";
2
2
  export { CANONICAL_FIELDS, CRM_CONCEPTS, CUSTOM_CONCEPT, ClivlyConfigError, ClivlyEntitiesConfig, ClivlyEntitiesConfigInput, ClivlyEntityConfig, ClivlyEntityConfigInput, ConfigValidationError, ConfigValidationResult, CrmConcept, CustomObjectDeclaration, DiscoveredColumnMeta, DiscoveredSchemaTable, FilterExpr, FilterValue, MATERIALIZING_CONCEPTS, MaterializingConcept, REQUIRED_FIELDS, RelationshipSpec, RelationshipVia, RelationshipsMap, customObjectDeclarations, defineClivlyConfig, entitiesConfigSchema, filterSchema, missingRequiredFields, projectionFields, relationshipSchema, relationshipsSchema, requiredFieldsFor, validateEntitiesConfig };
@@ -1,2 +1,2 @@
1
- import { A as relationshipsSchema, C as customObjectDeclarations, D as missingRequiredFields, E as filterSchema, M as validateEntitiesConfig, O as projectionFields, S as RelationshipsMap, T as entitiesConfigSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipSpec, c as ClivlyEntityConfigInput, d as CrmConcept, f as CustomObjectDeclaration, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as requiredFieldsFor, k as relationshipSchema, l as ConfigValidationError, m as DiscoveredSchemaTable, n as CRM_CONCEPTS, o as ClivlyEntitiesConfigInput, p as DiscoveredColumnMeta, r as CUSTOM_CONCEPT, s as ClivlyEntityConfig, t as CANONICAL_FIELDS, u as ConfigValidationResult, v as MaterializingConcept, w as defineClivlyConfig, x as RelationshipVia, y as REQUIRED_FIELDS } from "./entity-config-Ddgukq_E.mjs";
1
+ import { A as relationshipsSchema, C as customObjectDeclarations, D as missingRequiredFields, E as filterSchema, M as validateEntitiesConfig, O as projectionFields, S as RelationshipsMap, T as entitiesConfigSchema, _ as MATERIALIZING_CONCEPTS, a as ClivlyEntitiesConfig, b as RelationshipSpec, c as ClivlyEntityConfigInput, d as CrmConcept, f as CustomObjectDeclaration, g as FilterValue, h as FilterExpr, i as ClivlyConfigError, j as requiredFieldsFor, k as relationshipSchema, l as ConfigValidationError, m as DiscoveredSchemaTable, n as CRM_CONCEPTS, o as ClivlyEntitiesConfigInput, p as DiscoveredColumnMeta, r as CUSTOM_CONCEPT, s as ClivlyEntityConfig, t as CANONICAL_FIELDS, u as ConfigValidationResult, v as MaterializingConcept, w as defineClivlyConfig, x as RelationshipVia, y as REQUIRED_FIELDS } from "./entity-config-OhC4Otkz.mjs";
2
2
  export { CANONICAL_FIELDS, CRM_CONCEPTS, CUSTOM_CONCEPT, ClivlyConfigError, ClivlyEntitiesConfig, ClivlyEntitiesConfigInput, ClivlyEntityConfig, ClivlyEntityConfigInput, ConfigValidationError, ConfigValidationResult, CrmConcept, CustomObjectDeclaration, DiscoveredColumnMeta, DiscoveredSchemaTable, FilterExpr, FilterValue, MATERIALIZING_CONCEPTS, MaterializingConcept, REQUIRED_FIELDS, RelationshipSpec, RelationshipVia, RelationshipsMap, customObjectDeclarations, defineClivlyConfig, entitiesConfigSchema, filterSchema, missingRequiredFields, projectionFields, relationshipSchema, relationshipsSchema, requiredFieldsFor, validateEntitiesConfig };
@@ -1,2 +1,2 @@
1
- import { a as MATERIALIZING_CONCEPTS, c as defineClivlyConfig, d as missingRequiredFields, f as projectionFields, g as validateEntitiesConfig, h as requiredFieldsFor, i as ClivlyConfigError, l as entitiesConfigSchema, m as relationshipsSchema, n as CRM_CONCEPTS, o as REQUIRED_FIELDS, p as relationshipSchema, r as CUSTOM_CONCEPT, s as customObjectDeclarations, t as CANONICAL_FIELDS, u as filterSchema } from "./entity-config-BTAJe1Zj.mjs";
1
+ import { a as MATERIALIZING_CONCEPTS, c as defineClivlyConfig, d as missingRequiredFields, f as projectionFields, g as validateEntitiesConfig, h as requiredFieldsFor, i as ClivlyConfigError, l as entitiesConfigSchema, m as relationshipsSchema, n as CRM_CONCEPTS, o as REQUIRED_FIELDS, p as relationshipSchema, r as CUSTOM_CONCEPT, s as customObjectDeclarations, t as CANONICAL_FIELDS, u as filterSchema } from "./entity-config-C0rtu-K_.mjs";
2
2
  export { CANONICAL_FIELDS, CRM_CONCEPTS, CUSTOM_CONCEPT, ClivlyConfigError, MATERIALIZING_CONCEPTS, REQUIRED_FIELDS, customObjectDeclarations, defineClivlyConfig, entitiesConfigSchema, filterSchema, missingRequiredFields, projectionFields, relationshipSchema, relationshipsSchema, requiredFieldsFor, validateEntitiesConfig };