@clivly/core 0.7.3 → 0.7.4

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 (2) hide show
  1. package/README.md +96 -15
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,22 +1,63 @@
1
1
  # @clivly/core
2
2
 
3
- ORM- and auth-agnostic contracts and shared domain types for [Clivly](https://clivly.com) — the CRM that lives inside your app.
3
+ ORM- and auth-agnostic contracts and shared domain types for
4
+ [Clivly](https://clivly.com) — the CRM that lives inside your app.
4
5
 
5
- This package defines the interfaces that ORM and auth adapters implement. It has no runtime dependencies.
6
+ This package defines the interfaces that ORM and auth adapters implement, the
7
+ entity-config schema shared by the SDK and the dashboard's mapping table, and
8
+ the view compiler that turns a mapping into SQL. Its only runtime dependency is
9
+ `zod`.
10
+
11
+ > **Most integrators never install this directly.** `defineClivlyConfig` is
12
+ > re-exported from `clivly/sdk`, which is where the
13
+ > [integration guide](../../docs/guides/connecting-to-clivly-cloud.md) tells you
14
+ > to import it from. Reach for `@clivly/core` when you are building an adapter
15
+ > or working with the entity config outside an SDK instance.
16
+
17
+ ## Prerequisites
18
+
19
+ | Requirement | Version / note |
20
+ | --- | --- |
21
+ | Node.js | **≥ 22** |
22
+ | `drizzle-orm` | **Optional peer** — only needed for the `/drizzle` subpath |
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install @clivly/core
28
+ ```
6
29
 
7
30
  ## Exports
8
31
 
32
+ Every subpath below is importable independently, so you pull in only what you
33
+ use. The root (`.`) re-exports the contracts, entity config, mapping form, sync
34
+ engine and view compiler — but **not** `/drizzle` (which needs the optional
35
+ peer), `/entity-heuristics`, `/mapping-score`, `/integration-state` or
36
+ `/env-file`.
37
+
9
38
  | Entry | Contents |
10
- |---|---|
11
- | `.` | Everything below, re-exported |
39
+ | --- | --- |
40
+ | `@clivly/core` | The re-exported surface: contracts, entity config, mapping form, sync engine, view compiler, shared types |
12
41
  | `@clivly/core/adapter` | `CRMAdapter` — the interface every ORM implementation fulfils (org-scoped; contacts, companies, deals, tasks, activities) |
13
- | `@clivly/core/auth-adapter` | `ClivlyAuthAdapter`, `authCustom()`, `MembershipResolver` — pluggable host-app identity + the `crm_members` authorization layer |
42
+ | `@clivly/core/auth-adapter` | `ClivlyAuthAdapter`, `ClivlyUser`, `authCustom()`, `MembershipResolver`, `CrmMembership` — pluggable host-app identity + the `crm_members` authorization layer |
43
+ | `@clivly/core/entity-config` | `defineClivlyConfig`, `validateEntitiesConfig`, `entitiesConfigSchema`, `CANONICAL_FIELDS`, `CRM_CONCEPTS`, `ClivlyConfigError`, and the config types |
14
44
  | `@clivly/core/types` | Shared domain types (`Contact`, `Company`, `Deal`, `Task`, `Note`, `Activity`, inputs, filters, `CrmRole`) |
15
- | `@clivly/core/drizzle` | `discoverFromDrizzle(schema)` — derive the discovery shape from a Drizzle schema object. Requires the optional `drizzle-orm` peer dependency |
45
+ | `@clivly/core/drizzle` | `discoverFromDrizzle(schema)` — derive the discovery shape from a Drizzle schema object. Requires the optional `drizzle-orm` peer |
46
+ | `@clivly/core/view-compiler` | `compileEntityView`, `compileEntityViews`, `explainEntitiesConfig`, `DEFAULT_VIEW_PREFIX` |
47
+ | `@clivly/core/mappings-config` | `mappingsToEntitiesConfig`, `EntityMappingRow` — turn `crm_entity_mappings` rows into an entities config |
48
+ | `@clivly/core/mapping-form` | `buildFilterFromDiscriminator`, `buildRelationships`, `relationshipViaSignature` — mapping-UI helpers |
49
+ | `@clivly/core/mapping-score` | Scoring helpers for ranking candidate mappings |
50
+ | `@clivly/core/entity-heuristics` | Table-name heuristics that guess which table holds contacts/companies |
51
+ | `@clivly/core/sync-engine` | `reconcile`, `runSync`, `SyncStore` and friends — the mirror reconciliation engine |
52
+ | `@clivly/core/integration-state` | `INSTALL_COMMAND` and the shared onboarding state machine |
53
+ | `@clivly/core/env-file` | `envFileFor(framework)` — the conventional env filename per framework |
54
+
55
+ ## Five-minute quick start
16
56
 
17
- ## Schema discovery (Drizzle)
57
+ ### Schema discovery (Drizzle)
18
58
 
19
- `discoverFromDrizzle` turns your Drizzle schema into Clivly's discovery shape, so you don't hand-author table/column arrays:
59
+ `discoverFromDrizzle` turns your Drizzle schema into Clivly's discovery shape,
60
+ so you don't hand-author table/column arrays:
20
61
 
21
62
  ```ts
22
63
  import { discoverFromDrizzle } from "@clivly/core/drizzle";
@@ -26,9 +67,30 @@ const tables = discoverFromDrizzle(schema);
26
67
  // → [{ name: "participants", columns: ["id", "full_name", "email", …] }, …]
27
68
  ```
28
69
 
29
- Column names are the real DB names (`full_name`), not the Drizzle keys (`fullName`). `drizzle-orm` is an **optional peer dependency** — only needed when you import this subpath.
70
+ Column names are the **real DB names** (`full_name`), not the Drizzle property
71
+ keys (`fullName`).
72
+
73
+ ### Defining an entity config
74
+
75
+ ```ts
76
+ import { defineClivlyConfig } from "@clivly/core/entity-config";
77
+
78
+ const entities = defineClivlyConfig({
79
+ entities: {
80
+ participants: {
81
+ concept: "contact",
82
+ source: "participants", // the host table name
83
+ fields: { name: "full_name", email: "email" }, // canonical key → source column
84
+ },
85
+ },
86
+ });
87
+ ```
88
+
89
+ `defineClivlyConfig` validates at load and warns on any non-canonical field key
90
+ that would mirror as empty. `CANONICAL_FIELDS` lists the accepted keys per
91
+ concept; `CRM_CONCEPTS` lists the concepts.
30
92
 
31
- ## Usage
93
+ ### Implementing an adapter
32
94
 
33
95
  ```ts
34
96
  import type { CRMAdapter } from "@clivly/core";
@@ -39,9 +101,11 @@ function useAdapter(crm: CRMAdapter) {
39
101
  }
40
102
  ```
41
103
 
42
- ## The `$raw` escape hatch
104
+ ## Advanced: the `$raw` escape hatch
43
105
 
44
- Entity `filter`s and relationship `via`s accept a `$raw` form — an opaque SQL fragment for predicates the operators can't express (e.g. a cross-table condition):
106
+ Entity `filter`s and relationship `via`s accept a `$raw` form — an opaque SQL
107
+ fragment for predicates the operators can't express (e.g. a cross-table
108
+ condition):
45
109
 
46
110
  ```ts
47
111
  defineClivlyConfig({
@@ -56,14 +120,21 @@ defineClivlyConfig({
56
120
  });
57
121
  ```
58
122
 
59
- **`$raw` is unchecked.** `validateEntitiesConfig` deliberately **skips** `$raw` filters and joins — it can't know your columns are real or your SQL is valid. Two consequences:
123
+ **`$raw` is unchecked.** `validateEntitiesConfig` deliberately **skips** `$raw`
124
+ filters and joins — it can't know your columns are real or your SQL is valid.
125
+ Two consequences:
60
126
 
61
- - **Injection safety is on you.** Never interpolate untrusted input into a `$raw` string; treat it like handwritten SQL. Everything else in the config is escaped for you; `$raw` is not.
127
+ - **Injection safety is on you.** Never interpolate untrusted input into a
128
+ `$raw` string; treat it like handwritten SQL. Everything else in the config is
129
+ escaped for you; `$raw` is not.
62
130
  - **Mistakes surface at sync time, not config time** — unless you dry-run it.
63
131
 
64
132
  ### Dry-run with `explainEntitiesConfig`
65
133
 
66
- `explainEntitiesConfig(config, run, options?)` compiles each entity's view and executes it via a runner you provide, so a broken `$raw` fragment fails **before** the first sync. It never throws — it returns one `ExplainResult` per entity:
134
+ `explainEntitiesConfig(config, run, options?)` compiles each entity's view and
135
+ executes it via a runner you provide, so a broken `$raw` fragment fails
136
+ **before** the first sync. It never throws — it returns one `ExplainResult` per
137
+ entity:
67
138
 
68
139
  ```ts
69
140
  import { explainEntitiesConfig } from "@clivly/core";
@@ -81,6 +152,16 @@ for (const r of results) {
81
152
  }
82
153
  ```
83
154
 
155
+ `clivly status` runs the same mapping dry-run as one of its setup checks, so you
156
+ get this during normal verification without wiring it up yourself.
157
+
158
+ ## Related documentation
159
+
160
+ - **[Connecting to Clivly Cloud](../../docs/guides/connecting-to-clivly-cloud.md)** — the canonical end-to-end guide
161
+ - [`@clivly/sdk` README](../sdk/README.md) — the runtime that consumes this config
162
+ - [`clivly` CLI README](../cli/README.md) — every command and flag
163
+ - [`STABILITY.md`](../../STABILITY.md) — import tiers before 1.0
164
+
84
165
  ## License
85
166
 
86
167
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clivly/core",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "ORM/auth-agnostic CRM adapter contracts and shared domain types for Clivly.",