clivly 0.7.2 → 0.7.3
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/README.md +159 -103
- package/drizzle.d.cts +1 -9
- package/drizzle.d.mts +1 -9
- package/index.cjs +708 -106
- package/index.d.cts +6 -0
- package/index.d.mts +6 -0
- package/index.mjs +709 -107
- package/internal-entity-heuristics.cjs +27 -7
- package/internal-entity-heuristics.mjs +27 -7
- package/namespace-probe-B4WE45TH.d.mts +372 -0
- package/namespace-probe-DRzOtaRT.d.cts +372 -0
- package/package.json +1 -1
- package/{sdk-iqOXeWIp.cjs → sdk-BrQYA-GT.cjs} +125 -27
- package/{sdk-C6WANW8M.mjs → sdk-C2VL28du.mjs} +125 -27
- package/sdk.cjs +1 -1
- package/sdk.d.cts +36 -1
- package/sdk.d.mts +36 -1
- package/sdk.mjs +1 -1
- package/vite.d.cts +1 -1
- package/vite.d.mts +1 -1
- package/types-CsL0rFYh.d.cts +0 -155
- package/types-CsL0rFYh.d.mts +0 -155
package/README.md
CHANGED
|
@@ -1,40 +1,34 @@
|
|
|
1
1
|
# clivly
|
|
2
2
|
|
|
3
|
-
Clivly
|
|
3
|
+
Configure and integrate [Clivly](https://clivly.com) — the CRM that lives inside
|
|
4
|
+
your app.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
For the full integration path, including when to use `start()` versus
|
|
7
|
+
`runScheduled()` / `createClivlyHandler()`, see the
|
|
8
|
+
[connecting to Clivly Cloud guide](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/connecting-to-clivly-cloud.md).
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
- the package that exposes the stable runtime subpaths such as `clivly/sdk`
|
|
9
|
-
|
|
10
|
-
## Install
|
|
10
|
+
## Usage
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
npm install clivly
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Stable releases publish on npm's `latest` tag. Use `@next` only when you are
|
|
17
|
-
intentionally testing a prerelease build.
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## CLI commands
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npx clivly init # scaffold config, route files, and .env placeholders
|
|
25
|
-
npx clivly add widget # scaffold the chat-session route for the widget
|
|
26
|
-
npx clivly login # pair this machine and write credentials to .env
|
|
15
|
+
npx clivly init # scaffold config, routes and .env, then pair this machine
|
|
16
|
+
npx clivly login # pair this machine and write your credentials to .env
|
|
27
17
|
npx clivly status # check your setup, step by step
|
|
28
18
|
npx clivly dev # tunnel localhost so remote sync can reach you
|
|
29
19
|
npx clivly push-schema # report your schema to Clivly without deploying
|
|
30
20
|
```
|
|
31
21
|
|
|
32
|
-
`ping` and `doctor` remain
|
|
33
|
-
`status` ladder.
|
|
22
|
+
`ping` and `doctor` remain as aliases that run subsets of the `status` ladder.
|
|
34
23
|
|
|
35
|
-
|
|
24
|
+
Clivly's stable packages publish on npm's `latest` tag. Once installed, the
|
|
25
|
+
`npx clivly …` commands above use your local copy. Use `@next` only when you
|
|
26
|
+
are intentionally testing a prerelease cut.
|
|
36
27
|
|
|
37
|
-
|
|
28
|
+
## Imports
|
|
29
|
+
|
|
30
|
+
`clivly` is the consolidated public package. The CLI remains available as
|
|
31
|
+
`npx clivly`, while application code imports from typed subpaths:
|
|
38
32
|
|
|
39
33
|
```ts
|
|
40
34
|
import { createClivlySDK, defineClivlyConfig } from "clivly/sdk";
|
|
@@ -45,43 +39,71 @@ import { createWorkOSAuthAdapter } from "clivly/auth/workos";
|
|
|
45
39
|
import { createBetterAuthAdapter } from "clivly/auth/better-auth";
|
|
46
40
|
```
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Provider and framework integrations use optional peer dependencies. Install only
|
|
42
|
+
Provider and framework integrations use optional peer dependencies.
|
|
43
|
+
**Supported auth providers: Clerk, WorkOS, and BetterAuth.** Install only
|
|
52
44
|
what your app actually uses, such as `drizzle-orm`, `vite`, `@clerk/backend`,
|
|
53
45
|
`@workos-inc/node`, or `better-auth`.
|
|
54
46
|
|
|
55
|
-
## `clivly init`
|
|
56
|
-
|
|
57
47
|
`clivly init` detects your framework from `package.json`, locates your Drizzle
|
|
58
|
-
schema, and
|
|
48
|
+
schema, and generates a `clivly.config.ts` that maps likely contact and company
|
|
49
|
+
tables. The init command currently generates config for Drizzle only; Prisma and
|
|
50
|
+
Kysely projects should use a hand-written `fetchPage` source for now.
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
- missing `.env` placeholders
|
|
52
|
+
Use `--schema` when your Drizzle schema is not in a common location or in
|
|
53
|
+
`drizzle.config.ts`. Re-run with `--force` to overwrite an existing config.
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
can still integrate, but should provide hand-written `fetchPage` sources rather
|
|
66
|
-
than relying on the generated Drizzle path.
|
|
55
|
+
### Monorepos
|
|
67
56
|
|
|
68
|
-
|
|
57
|
+
In a workspace, `init` reads your `pnpm-workspace.yaml` (or `workspaces` array)
|
|
58
|
+
and imports anything owned by a *sibling* package by **package name** rather than
|
|
59
|
+
by a relative path that climbs out of your app:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import * as schema from "@acme/database"; // not "../../packages/database/src/index"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`--schema` accepts a package specifier as well as a path, so all of these work:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
clivly init --schema @acme/database # the package entry
|
|
69
|
+
clivly init --schema @acme/database/src/schema.ts # a subpath inside it
|
|
70
|
+
clivly init --schema ./src/db/schema.ts # a plain path (unchanged)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
A real file always wins over a same-named package, so existing relative paths
|
|
74
|
+
keep their meaning.
|
|
69
75
|
|
|
70
76
|
| Flag | Purpose |
|
|
71
77
|
| --- | --- |
|
|
72
|
-
| `--schema <path\|package>` | Where your Drizzle
|
|
73
|
-
| `--db-import <specifier>` | Where the Drizzle
|
|
74
|
-
| `--auth-import <specifier>` | Where your auth instance lives |
|
|
75
|
-
| `--contact-table <name>` |
|
|
76
|
-
| `--company-table <name>` |
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
| `--schema <path\|package>` | Where your Drizzle tables live. |
|
|
79
|
+
| `--db-import <specifier>` | Where the Drizzle instance lives, when it isn't beside the schema. Accepts `@acme/database#database` to name the export. |
|
|
80
|
+
| `--auth-import <specifier>` | Where your better-auth instance lives. Same `#exportName` form. Overrides on-disk probing, which cannot see across a package boundary. |
|
|
81
|
+
| `--contact-table <name>` | Use this table as the contact entity, skipping the naming heuristics. |
|
|
82
|
+
| `--company-table <name>` | Same for companies. |
|
|
83
|
+
|
|
84
|
+
`--contact-table` and `--company-table` accept either the SQL table name or the
|
|
85
|
+
name it is exported under in your schema module — whichever you have in front of
|
|
86
|
+
you.
|
|
87
|
+
|
|
88
|
+
### When no contact entity can be found
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
90
|
+
`init` **writes nothing** rather than scaffolding a config that cannot compile.
|
|
91
|
+
Clivly needs one entity before a config will load, and it will not invent one:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
No usable contact entity
|
|
83
95
|
|
|
84
|
-
|
|
96
|
+
Tables in @acme/database:
|
|
97
|
+
widgets
|
|
98
|
+
invoices
|
|
99
|
+
|
|
100
|
+
Pick the one that holds your people and re-run:
|
|
101
|
+
clivly init --schema @acme/database --contact-table widgets
|
|
102
|
+
|
|
103
|
+
Nothing was written — Clivly needs one entity before a config can load.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
First-class route scaffolding currently exists for:
|
|
85
107
|
|
|
86
108
|
- Next.js
|
|
87
109
|
- TanStack Start
|
|
@@ -89,50 +111,81 @@ Supported first-class route scaffolding today:
|
|
|
89
111
|
- Remix
|
|
90
112
|
- Nuxt
|
|
91
113
|
|
|
92
|
-
|
|
114
|
+
Vue.js apps can still integrate Clivly, but they usually need a manual server
|
|
115
|
+
layer for the tick route unless they are using Nuxt.
|
|
116
|
+
|
|
117
|
+
When `init` finishes and `CLIVLY_SECRET_KEY` is still empty, it hands you straight
|
|
118
|
+
into `clivly login` so you don't end up staring at a blank `.env`. That step is
|
|
119
|
+
interactive, so it is skipped automatically when there is no TTY or when `CI` is
|
|
120
|
+
set — and you can always turn it off yourself:
|
|
93
121
|
|
|
94
122
|
```bash
|
|
95
|
-
npx clivly
|
|
123
|
+
npx clivly init --no-login # scaffold only; pair later with `clivly login`
|
|
124
|
+
npx clivly init --no-browser # pair, but print the URL instead of opening it
|
|
96
125
|
```
|
|
97
126
|
|
|
98
|
-
Scaffolds the host-side widget session route that mounts
|
|
99
|
-
`createChatSessionHandler()` from `clivly/sdk`. It is idempotent and supports
|
|
100
|
-
`--dry-run` and `--force`.
|
|
101
|
-
|
|
102
127
|
## `clivly login`
|
|
103
128
|
|
|
104
129
|
```bash
|
|
105
130
|
npx clivly login [--force] [--rotate] [--api-url <url>] [--no-browser]
|
|
106
131
|
```
|
|
107
132
|
|
|
108
|
-
Pairs this machine with a Clivly workspace and writes
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
Pairs this machine with a Clivly workspace and writes `CLIVLY_SECRET_KEY` and
|
|
134
|
+
`CLIVLY_SYNC_TRIGGER_SECRET` into your project's `.env`. It creates a pairing
|
|
135
|
+
session, prints (and by default opens) an approval link, and waits while you
|
|
136
|
+
approve it in a signed-in browser. The approval link is always printed, so an
|
|
137
|
+
SSH or headless session can be approved by opening the link elsewhere.
|
|
138
|
+
|
|
139
|
+
- `--no-browser` — print the approval URL without opening a browser.
|
|
140
|
+
- `--force` — overwrite `.env` values that already have a real value. Without
|
|
141
|
+
it, existing values are kept and reported as skipped; an empty placeholder
|
|
142
|
+
(`CLIVLY_SECRET_KEY=`) is always filled in.
|
|
143
|
+
- `--rotate` — rotate the workspace's remote-sync trigger secret instead of
|
|
144
|
+
revealing the current one. Your already-deployed host app will stop receiving
|
|
145
|
+
sync triggers until you redeploy it with the new secret.
|
|
146
|
+
|
|
147
|
+
Before anything is written, the CLI prints which workspace approved the pairing
|
|
148
|
+
and asks you to confirm. Declining writes nothing and exits non-zero. In a
|
|
149
|
+
non-interactive run (no TTY, or `CI` set) the workspace is still printed but
|
|
150
|
+
you are not prompted, so scripted pairing cannot hang.
|
|
151
|
+
|
|
152
|
+
The pairing endpoints are feature-flagged server-side
|
|
153
|
+
(`CLIVLY_CLI_PAIRING_ENABLED`); if the backend you point at has not enabled
|
|
154
|
+
them, `clivly login` says so and exits non-zero.
|
|
155
|
+
|
|
156
|
+
**Clivly Cloud has pairing enabled**, so `clivly login` is the normal path there.
|
|
157
|
+
The flag defaults to `false`, so a self-hosted backend must opt in.
|
|
158
|
+
|
|
159
|
+
### Manual credential path
|
|
160
|
+
|
|
161
|
+
If pairing is unavailable — a self-hosted backend with the flag off, or a
|
|
162
|
+
restricted environment — every credential can be set by hand. Nothing about the
|
|
163
|
+
CLI requires pairing.
|
|
164
|
+
|
|
165
|
+
| Value | Where to get it | Notes |
|
|
166
|
+
| --- | --- | --- |
|
|
167
|
+
| `CLIVLY_SECRET_KEY` | Dashboard → **Settings → API keys** → Create | **Shown once.** Copy it immediately; you cannot retrieve it later, only regenerate. Regenerating **revokes the previous key**, so redeploy after rotating. The legacy name `CLIVLY_API_KEY` is still accepted as a fallback. |
|
|
168
|
+
| `CLIVLY_SYNC_TRIGGER_SECRET` | Dashboard → **Integrations → Remote sync** | Must match the value in your app's env exactly. A mismatch surfaces as a `401` on the signed trigger. |
|
|
169
|
+
| `CLIVLY_SYNC_TRIGGER_URL` | Your own deployment | The public URL of your mounted tick route, e.g. `https://app.example.com/api/clivly/tick`. Optional until you deploy — push-only setups can leave it unset. |
|
|
170
|
+
|
|
171
|
+
Write them into the `.env` of the package that imports `clivly`, then re-run
|
|
172
|
+
`clivly status` to confirm each rung goes green.
|
|
173
|
+
|
|
174
|
+
> **Running your own Clivly backend?** `CLIVLY_TRIGGER_SECRET_WRAPPING_KEY` (a
|
|
175
|
+
> 32-byte hex key) is a **hard production prerequisite** for pairing. The
|
|
176
|
+
> trigger secret is stored encrypted with it, so without the key set on the
|
|
177
|
+
> server, `clivly login` fails with a 500 at the moment it would hand over
|
|
178
|
+
> credentials. Set it before enabling `CLIVLY_CLI_PAIRING_ENABLED`.
|
|
127
179
|
|
|
128
180
|
## `clivly status`
|
|
129
181
|
|
|
130
182
|
```bash
|
|
131
|
-
npx clivly status [--verbose] [--config <path>]
|
|
183
|
+
npx clivly status [--verbose] [--config <path>]
|
|
132
184
|
```
|
|
133
185
|
|
|
134
|
-
Walks
|
|
135
|
-
connectivity
|
|
186
|
+
Walks your setup one rung at a time — credentials, config, schema, sources,
|
|
187
|
+
connectivity — and stops at the first thing that isn't ready, telling you what
|
|
188
|
+
to do about it. This is the command to reach for when something isn't working.
|
|
136
189
|
|
|
137
190
|
## `clivly dev`
|
|
138
191
|
|
|
@@ -141,49 +194,52 @@ npx clivly dev [--port <n>] [--api-url <url>] [--route-path <path>] [-- <cmd>]
|
|
|
141
194
|
```
|
|
142
195
|
|
|
143
196
|
Opens a `cloudflared` tunnel to your local app and registers it with Clivly for
|
|
144
|
-
the
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
197
|
+
the length of the session, so remote sync can reach `localhost` while you
|
|
198
|
+
develop. Your dev server is detected from `package.json` scripts, or pass it
|
|
199
|
+
explicitly after `--`. Needs `cloudflared` on `PATH` and `CLIVLY_SECRET_KEY` set.
|
|
200
|
+
The override is cleared when the process exits; remote sync is otherwise
|
|
201
|
+
deploy-only.
|
|
148
202
|
|
|
149
|
-
|
|
150
|
-
- `CLIVLY_SECRET_KEY` set
|
|
203
|
+
## `clivly ping` / `clivly doctor`
|
|
151
204
|
|
|
152
|
-
|
|
205
|
+
`clivly ping` reads `CLIVLY_SECRET_KEY` from the environment, sends one heartbeat, and prints a clear ✅/❌ with the resolved org or the failure reason — so you can confirm a connection from the terminal without writing any code. Point it at a non-default backend with `--api-url <url>` (or `CLIVLY_API_URL`).
|
|
153
206
|
|
|
154
207
|
```bash
|
|
155
|
-
npx clivly
|
|
208
|
+
CLIVLY_SECRET_KEY=sk_live_… npx clivly ping
|
|
209
|
+
#
|
|
210
|
+
# Clivly ping
|
|
211
|
+
# ✅ Connected to Clivly
|
|
212
|
+
# Org: Acme (org_1)
|
|
156
213
|
```
|
|
157
214
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
## `clivly ping` / `clivly doctor`
|
|
162
|
-
|
|
163
|
-
`clivly ping` sends one heartbeat and prints a terse pass/fail result.
|
|
215
|
+
`clivly doctor` loads your config and runs the same read-only checks as
|
|
216
|
+
`await clivly.doctor()`: API key, entity config, sources, Drizzle cursor/id
|
|
217
|
+
columns, sample fetch, and heartbeat.
|
|
164
218
|
|
|
165
|
-
|
|
166
|
-
|
|
219
|
+
```bash
|
|
220
|
+
npx clivly doctor
|
|
221
|
+
npx clivly doctor --config ./apps/web/clivly.config.ts
|
|
222
|
+
```
|
|
167
223
|
|
|
168
224
|
## Telemetry
|
|
169
225
|
|
|
170
|
-
Clivly collects no telemetry
|
|
171
|
-
Clivly API you point it at, and only to do
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
See the telemetry section in:
|
|
175
|
-
[SECURITY.md](https://github.com/amani-joseph/clivly.com/blob/master/SECURITY.md#telemetry)
|
|
226
|
+
**Clivly collects no telemetry.** The CLI makes network requests only to the
|
|
227
|
+
Clivly API you point it at, and only to do what you asked: pairing, heartbeats,
|
|
228
|
+
schema pushes, and status checks. No usage analytics, no crash reporting, no
|
|
229
|
+
phone-home. See [SECURITY.md](https://github.com/amani-joseph/clivly.com/blob/master/SECURITY.md#telemetry).
|
|
176
230
|
|
|
177
231
|
## More docs
|
|
178
232
|
|
|
179
|
-
-
|
|
180
|
-
[
|
|
181
|
-
-
|
|
182
|
-
[
|
|
233
|
+
- Onboarding guide:
|
|
234
|
+
[connecting to Clivly Cloud](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/connecting-to-clivly-cloud.md)
|
|
235
|
+
- Adding the chat widget:
|
|
236
|
+
[guide](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/adding-the-chat-widget.md)
|
|
237
|
+
- Security policy:
|
|
238
|
+
[SECURITY.md](https://github.com/amani-joseph/clivly.com/blob/master/SECURITY.md)
|
|
183
239
|
- SDK docs:
|
|
184
|
-
[
|
|
240
|
+
[`@clivly/sdk` README](https://github.com/amani-joseph/clivly.com/blob/master/packages/sdk/README.md)
|
|
185
241
|
- Release notes:
|
|
186
|
-
[CHANGELOG
|
|
242
|
+
[CHANGELOG](https://github.com/amani-joseph/clivly.com/blob/master/CHANGELOG.md)
|
|
187
243
|
|
|
188
244
|
## License
|
|
189
245
|
|
package/drizzle.d.cts
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { t as discoverFromDrizzle } from "./drizzle-DmeKSqeF.cjs";
|
|
2
|
-
import {
|
|
2
|
+
import { m as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-DRzOtaRT.cjs";
|
|
3
3
|
import { Table } from "drizzle-orm";
|
|
4
|
-
//#region ../sdk/src/namespace-probe.d.ts
|
|
5
|
-
interface NamespaceIntrospector {
|
|
6
|
-
/** All base table names in the reachable schema. */
|
|
7
|
-
listTables(): Promise<string[]>;
|
|
8
|
-
/** Prove a table is genuinely selectable (SELECT ... LIMIT 1). Throws if unreachable/denied. */
|
|
9
|
-
sampleSelect(table: string): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
4
|
//#region ../sdk/src/drizzle.d.ts
|
|
13
5
|
interface DrizzleDb {
|
|
14
6
|
select: (...args: any[]) => any;
|
package/drizzle.d.mts
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { t as discoverFromDrizzle } from "./drizzle-CFOr9dU9.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { m as SyncSource, t as NamespaceIntrospector } from "./namespace-probe-B4WE45TH.mjs";
|
|
3
3
|
import { Table } from "drizzle-orm";
|
|
4
|
-
//#region ../sdk/src/namespace-probe.d.ts
|
|
5
|
-
interface NamespaceIntrospector {
|
|
6
|
-
/** All base table names in the reachable schema. */
|
|
7
|
-
listTables(): Promise<string[]>;
|
|
8
|
-
/** Prove a table is genuinely selectable (SELECT ... LIMIT 1). Throws if unreachable/denied. */
|
|
9
|
-
sampleSelect(table: string): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
4
|
//#region ../sdk/src/drizzle.d.ts
|
|
13
5
|
interface DrizzleDb {
|
|
14
6
|
select: (...args: any[]) => any;
|