clivly 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.
- package/README.md +330 -134
- package/drizzle.cjs +7 -3
- package/drizzle.mjs +7 -3
- package/index.cjs +29 -13
- package/index.mjs +29 -13
- package/package.json +1 -1
- package/{sdk-BrQYA-GT.cjs → sdk-Bj-ZDf4u.cjs} +1 -1
- package/{sdk-C2VL28du.mjs → sdk-BvRD2jAp.mjs} +1 -1
- package/sdk.cjs +1 -1
- package/sdk.mjs +1 -1
package/README.md
CHANGED
|
@@ -1,91 +1,158 @@
|
|
|
1
1
|
# clivly
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
your app.
|
|
3
|
+
The consolidated public package for [Clivly](https://clivly.com) — the CRM that
|
|
4
|
+
lives inside your app. It is two things in one install:
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
- **A CLI** (`npx clivly …`) that scaffolds your integration, pairs your machine
|
|
7
|
+
with a workspace, and diagnoses the setup.
|
|
8
|
+
- **A runtime**, imported from typed subpaths (`clivly/sdk`, `clivly/drizzle`,
|
|
9
|
+
`clivly/vite`, `clivly/auth/*`).
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
> **The canonical end-to-end integration guide is
|
|
12
|
+
> [Connecting to Clivly Cloud](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/connecting-to-clivly-cloud.md).**
|
|
13
|
+
> This README is the command-level reference.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
| Requirement | Version / note |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| Node.js | **≥ 22** |
|
|
20
|
+
| An existing app | The CLI scaffolds into a project you already have |
|
|
21
|
+
| Drizzle ORM | Required for `clivly init` to generate a config. Prisma/Kysely/raw-SQL projects hand-write a `fetchPage` source instead |
|
|
22
|
+
| `cloudflared` on `PATH` | Only for `clivly dev` |
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
11
25
|
|
|
12
26
|
```bash
|
|
13
27
|
npm install clivly
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Published on npm's `latest` tag. Once installed, `npx clivly …` uses your local
|
|
31
|
+
copy rather than re-fetching. Use `@next` only when deliberately testing a
|
|
32
|
+
prerelease cut.
|
|
14
33
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
npx clivly
|
|
34
|
+
## Five-minute quick start
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install clivly
|
|
38
|
+
npx clivly init # scaffold config + routes + .env, then pair this machine
|
|
39
|
+
npx clivly status # check every setup step until they all pass
|
|
20
40
|
```
|
|
21
41
|
|
|
22
|
-
`
|
|
42
|
+
`clivly init` writes exactly three files (plus `.env` keys) — a
|
|
43
|
+
`clivly.config.ts` you own, and two route files Clivly owns. It creates no
|
|
44
|
+
database tables and does not modify your ORM schema.
|
|
23
45
|
|
|
24
|
-
|
|
25
|
-
`npx clivly …` commands above use your local copy. Use `@next` only when you
|
|
26
|
-
are intentionally testing a prerelease cut.
|
|
46
|
+
---
|
|
27
47
|
|
|
28
|
-
##
|
|
48
|
+
## Commands
|
|
29
49
|
|
|
30
|
-
|
|
31
|
-
|
|
50
|
+
| Command | What it does |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| [`clivly init`](#clivly-init) | Scaffold config, routes and env placeholders for your app |
|
|
53
|
+
| [`clivly login`](#clivly-login) | Pair this machine and write credentials to your env file |
|
|
54
|
+
| [`clivly status`](#clivly-status) | Check your setup, step by step. Read-only |
|
|
55
|
+
| [`clivly add widget`](#clivly-add-widget) | Scaffold the chat-session route |
|
|
56
|
+
| [`clivly push-schema`](#clivly-push-schema) | Report your schema to Clivly without deploying |
|
|
57
|
+
| [`clivly dev`](#clivly-dev) | Tunnel localhost so remote sync can reach you |
|
|
58
|
+
| `clivly --version` | Print the installed `clivly` version |
|
|
59
|
+
| [`clivly ping` / `connect` / `doctor`](#deprecated-aliases) | Deprecated aliases running parts of `status` |
|
|
32
60
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
61
|
+
Every command accepts `--help` (or `-h`), which **describes without acting**.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### `clivly init`
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx clivly init [--force] [--dry-run] [--diff] [--yes] [--no-login] [--no-browser]
|
|
69
|
+
[--schema <path|package>] [--db-import <specifier>]
|
|
70
|
+
[--auth-import <specifier>] [--contact-table <table>]
|
|
71
|
+
[--company-table <table>]
|
|
40
72
|
```
|
|
41
73
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
74
|
+
Detects your framework, ORM, auth adapter and app layout, then scaffolds:
|
|
75
|
+
|
|
76
|
+
| File | Owned by Clivly |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `clivly.config.ts` | No — yours to edit |
|
|
79
|
+
| The tick route for your framework | Yes — `--force` to overwrite |
|
|
80
|
+
| The auth-verify route for your framework | Yes — `--force` to overwrite |
|
|
81
|
+
|
|
82
|
+
Plus `CLIVLY_SECRET_KEY`, `CLIVLY_SYNC_TRIGGER_URL` and
|
|
83
|
+
`CLIVLY_SYNC_TRIGGER_SECRET` placeholders in your env file.
|
|
84
|
+
|
|
85
|
+
| Flag | Purpose |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| `--dry-run` | Show what would be written; write nothing |
|
|
88
|
+
| `--diff` | Show a diff for files that already exist |
|
|
89
|
+
| `--force` | Overwrite the files Clivly owns |
|
|
90
|
+
| `--yes` | Skip prompts |
|
|
91
|
+
| `--no-login` | Skip browser pairing |
|
|
92
|
+
| `--no-browser` | Pair, but print the URL instead of opening it |
|
|
93
|
+
| `--schema <path\|package>` | Where your Drizzle tables live |
|
|
94
|
+
| `--db-import <specifier>` | Where the Drizzle instance lives, when it is not beside the schema. Accepts `@acme/database#database` to name the export |
|
|
95
|
+
| `--auth-import <specifier>` | Where your better-auth instance lives. Same `#exportName` form. Overrides on-disk probing, which cannot see across a package boundary |
|
|
96
|
+
| `--contact-table <name>` | Use this table as the contact entity, skipping the naming heuristics |
|
|
97
|
+
| `--company-table <name>` | Same for companies |
|
|
98
|
+
|
|
99
|
+
`--contact-table` and `--company-table` accept either the SQL table name or the
|
|
100
|
+
name it is exported under in your schema module — whichever you have in front of
|
|
101
|
+
you.
|
|
102
|
+
|
|
103
|
+
When `init` finishes and `CLIVLY_SECRET_KEY` is still empty, it hands you
|
|
104
|
+
straight into `clivly login` so you don't end up staring at a blank env file.
|
|
105
|
+
That step is interactive, so it is skipped automatically when there is no TTY or
|
|
106
|
+
when `CI` is set.
|
|
107
|
+
|
|
108
|
+
#### Framework support
|
|
109
|
+
|
|
110
|
+
Route scaffolding exists for these five. Anywhere else, mount the handler
|
|
111
|
+
yourself — it is a plain `(Request) => Promise<Response>`.
|
|
112
|
+
|
|
113
|
+
| Framework | Tick route written |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| Next.js | `app/api/clivly/tick/route.ts` (or `src/app/…`) |
|
|
116
|
+
| TanStack Start | `src/routes/api/clivly/tick.ts` |
|
|
117
|
+
| SvelteKit | `src/routes/api/clivly/tick/+server.ts` |
|
|
118
|
+
| Remix | `app/routes/api.clivly.tick.ts` |
|
|
119
|
+
| Nuxt | `server/api/clivly/tick.ts` |
|
|
120
|
+
|
|
121
|
+
Plain Vue apps can still integrate Clivly, but they need a manual server layer
|
|
122
|
+
for the tick route unless they are on Nuxt.
|
|
123
|
+
|
|
124
|
+
#### ORM support
|
|
46
125
|
|
|
47
|
-
`
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
126
|
+
`init` generates a config for **Drizzle only**. Prisma and Kysely projects
|
|
127
|
+
integrate through a hand-written `fetchPage` source — see the
|
|
128
|
+
[Non-Drizzle sources](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/connecting-to-clivly-cloud.md#non-drizzle-sources)
|
|
129
|
+
section of the guide.
|
|
51
130
|
|
|
52
131
|
Use `--schema` when your Drizzle schema is not in a common location or in
|
|
53
|
-
`drizzle.config.ts`.
|
|
132
|
+
`drizzle.config.ts`.
|
|
54
133
|
|
|
55
|
-
|
|
134
|
+
#### Monorepos
|
|
56
135
|
|
|
57
136
|
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
|
|
59
|
-
by a relative path that climbs out of your app:
|
|
137
|
+
and imports anything owned by a *sibling* package by **package name** rather
|
|
138
|
+
than by a relative path that climbs out of your app:
|
|
60
139
|
|
|
61
140
|
```ts
|
|
62
141
|
import * as schema from "@acme/database"; // not "../../packages/database/src/index"
|
|
63
142
|
```
|
|
64
143
|
|
|
65
|
-
`--schema` accepts a package specifier as well as a path
|
|
144
|
+
`--schema` accepts a package specifier as well as a path:
|
|
66
145
|
|
|
67
146
|
```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
|
|
147
|
+
npx clivly init --schema @acme/database # the package entry
|
|
148
|
+
npx clivly init --schema @acme/database/src/schema.ts # a subpath inside it
|
|
149
|
+
npx clivly init --schema ./src/db/schema.ts # a plain path
|
|
71
150
|
```
|
|
72
151
|
|
|
73
152
|
A real file always wins over a same-named package, so existing relative paths
|
|
74
153
|
keep their meaning.
|
|
75
154
|
|
|
76
|
-
|
|
77
|
-
| --- | --- |
|
|
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
|
|
155
|
+
#### When no contact entity can be found
|
|
89
156
|
|
|
90
157
|
`init` **writes nothing** rather than scaffolding a config that cannot compile.
|
|
91
158
|
Clivly needs one entity before a config will load, and it will not invent one:
|
|
@@ -103,73 +170,67 @@ No usable contact entity
|
|
|
103
170
|
Nothing was written — Clivly needs one entity before a config can load.
|
|
104
171
|
```
|
|
105
172
|
|
|
106
|
-
|
|
173
|
+
---
|
|
107
174
|
|
|
108
|
-
|
|
109
|
-
- TanStack Start
|
|
110
|
-
- SvelteKit
|
|
111
|
-
- Remix
|
|
112
|
-
- Nuxt
|
|
113
|
-
|
|
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:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
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
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## `clivly login`
|
|
175
|
+
### `clivly login`
|
|
128
176
|
|
|
129
177
|
```bash
|
|
130
178
|
npx clivly login [--force] [--rotate] [--api-url <url>] [--no-browser]
|
|
131
179
|
```
|
|
132
180
|
|
|
133
181
|
Pairs this machine with a Clivly workspace and writes `CLIVLY_SECRET_KEY` and
|
|
134
|
-
`CLIVLY_SYNC_TRIGGER_SECRET` into your project's
|
|
182
|
+
`CLIVLY_SYNC_TRIGGER_SECRET` into your project's env file. It creates a pairing
|
|
135
183
|
session, prints (and by default opens) an approval link, and waits while you
|
|
136
184
|
approve it in a signed-in browser. The approval link is always printed, so an
|
|
137
185
|
SSH or headless session can be approved by opening the link elsewhere.
|
|
138
186
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
sync triggers until you redeploy it with the new secret.
|
|
187
|
+
| Flag | Effect |
|
|
188
|
+
| --- | --- |
|
|
189
|
+
| `--no-browser` | Print the approval URL without opening a browser |
|
|
190
|
+
| `--force` | Overwrite env values that already have a real value. Without it, existing values are kept and reported as skipped; an empty placeholder (`CLIVLY_SECRET_KEY=`) is always filled in |
|
|
191
|
+
| `--rotate` | Rotate the workspace's remote-sync trigger secret instead of revealing the current one. **Your already-deployed app stops receiving sync triggers until you redeploy it with the new secret** |
|
|
192
|
+
| `--api-url <url>` | Point at a non-default backend |
|
|
146
193
|
|
|
147
194
|
Before anything is written, the CLI prints which workspace approved the pairing
|
|
148
195
|
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
|
-
|
|
196
|
+
non-interactive run (no TTY, or `CI` set) the workspace is still printed but you
|
|
197
|
+
are not prompted, so scripted pairing cannot hang.
|
|
151
198
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
199
|
+
#### Which env file gets written
|
|
200
|
+
|
|
201
|
+
The CLI follows your framework's convention. This is not cosmetic on Workers:
|
|
202
|
+
wrangler reads `.dev.vars` and nothing else, so credentials written to `.env`
|
|
203
|
+
would never load.
|
|
155
204
|
|
|
156
|
-
|
|
157
|
-
|
|
205
|
+
| Framework | Env file |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| Next.js | `.env.local` |
|
|
208
|
+
| TanStack Start, SvelteKit, Remix, Nuxt | `.env` |
|
|
209
|
+
| Hono on Cloudflare Workers | `.dev.vars` |
|
|
210
|
+
| Anything else | `.env` |
|
|
158
211
|
|
|
159
|
-
|
|
212
|
+
#### Pairing availability
|
|
160
213
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
214
|
+
The pairing endpoints are feature-flagged server-side
|
|
215
|
+
(`CLIVLY_CLI_PAIRING_ENABLED`). **Clivly Cloud has pairing enabled**, so
|
|
216
|
+
`clivly login` is the normal path there. The flag defaults to `false`, so a
|
|
217
|
+
self-hosted backend must opt in — otherwise `clivly login` says so and exits
|
|
218
|
+
non-zero.
|
|
219
|
+
|
|
220
|
+
#### Manual credential path
|
|
221
|
+
|
|
222
|
+
If pairing is unavailable, every credential can be set by hand. Nothing about
|
|
223
|
+
the CLI requires pairing.
|
|
164
224
|
|
|
165
225
|
| Value | Where to get it | Notes |
|
|
166
226
|
| --- | --- | --- |
|
|
167
|
-
| `CLIVLY_SECRET_KEY` | Dashboard → **Settings → API keys**
|
|
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
|
|
227
|
+
| `CLIVLY_SECRET_KEY` | Dashboard → **Connect app**, or **Settings → API keys** | **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 |
|
|
228
|
+
| `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 |
|
|
229
|
+
| `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 |
|
|
230
|
+
| `CLIVLY_PUBLISHABLE_KEY` | Same place as the secret key | Only needed for the chat widget. Safe to expose in client code |
|
|
170
231
|
|
|
171
|
-
Write them into the
|
|
172
|
-
`clivly status` to confirm each
|
|
232
|
+
Write them into the env file of the package that imports `clivly`, then re-run
|
|
233
|
+
`clivly status` to confirm each step goes green.
|
|
173
234
|
|
|
174
235
|
> **Running your own Clivly backend?** `CLIVLY_TRIGGER_SECRET_WRAPPING_KEY` (a
|
|
175
236
|
> 32-byte hex key) is a **hard production prerequisite** for pairing. The
|
|
@@ -177,17 +238,71 @@ Write them into the `.env` of the package that imports `clivly`, then re-run
|
|
|
177
238
|
> server, `clivly login` fails with a 500 at the moment it would hand over
|
|
178
239
|
> credentials. Set it before enabling `CLIVLY_CLI_PAIRING_ENABLED`.
|
|
179
240
|
|
|
180
|
-
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### `clivly status`
|
|
181
244
|
|
|
182
245
|
```bash
|
|
183
|
-
npx clivly status [--verbose] [--config <path>]
|
|
246
|
+
npx clivly status [--verbose] [--config <path>] [--env-file <path>]
|
|
184
247
|
```
|
|
185
248
|
|
|
186
|
-
Walks your setup one
|
|
187
|
-
|
|
188
|
-
|
|
249
|
+
Walks your setup one step at a time and stops at the first thing that isn't
|
|
250
|
+
ready, telling you what to do about it. **This is the command to reach for when
|
|
251
|
+
something isn't working.** It is read-only and writes nothing.
|
|
189
252
|
|
|
190
|
-
|
|
253
|
+
The ladder: credential → Clivly reachable → `clivly.config` loads →
|
|
254
|
+
`clivly.config` is edge-safe → setup checks → sync trigger URL.
|
|
255
|
+
|
|
256
|
+
| Flag | Effect |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| `--verbose` | Show every check, including those that passed |
|
|
259
|
+
| `--config <path>` | Path to `clivly.config.ts` (needed in a monorepo) |
|
|
260
|
+
| `--env-file <path>` | Extra env file to load. Repeatable; later files win |
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
npx clivly status --config ./apps/web/clivly.config.ts
|
|
264
|
+
npx clivly status --env-file ../server/.env
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Env precedence, strongest first: **real environment → `--env-file` / the
|
|
268
|
+
`envFiles` array in `clivly.cli.ts` → `.env.local` → `.env`**.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### `clivly add widget`
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
npx clivly add widget [--force] [--dry-run]
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Writes the route that mints chat-widget sessions, for your detected framework
|
|
279
|
+
(e.g. `app/api/clivly/widget/session/route.ts` on Next.js). Idempotent.
|
|
280
|
+
|
|
281
|
+
It creates **no widget record** — that lives in the Clivly dashboard under
|
|
282
|
+
**Settings → Chat widget**. See
|
|
283
|
+
[Adding the chat widget](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/adding-the-chat-widget.md)
|
|
284
|
+
for the full flow.
|
|
285
|
+
|
|
286
|
+
| Flag | Effect |
|
|
287
|
+
| --- | --- |
|
|
288
|
+
| `--dry-run` | Show what would be written; write nothing |
|
|
289
|
+
| `--force` | Overwrite the route if it already exists |
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
### `clivly push-schema`
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
npx clivly push-schema [--config <path>]
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Sends your discovered tables and columns to Clivly so the dashboard can offer
|
|
300
|
+
them for mapping — without deploying your app. Reads your config; writes nothing
|
|
301
|
+
locally. **Table and column names only; never row data.**
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### `clivly dev`
|
|
191
306
|
|
|
192
307
|
```bash
|
|
193
308
|
npx clivly dev [--port <n>] [--api-url <url>] [--route-path <path>] [-- <cmd>]
|
|
@@ -196,50 +311,131 @@ npx clivly dev [--port <n>] [--api-url <url>] [--route-path <path>] [-- <cmd>]
|
|
|
196
311
|
Opens a `cloudflared` tunnel to your local app and registers it with Clivly for
|
|
197
312
|
the length of the session, so remote sync can reach `localhost` while you
|
|
198
313
|
develop. Your dev server is detected from `package.json` scripts, or pass it
|
|
199
|
-
explicitly after `--`. Needs `cloudflared` on `PATH` and `CLIVLY_SECRET_KEY`
|
|
200
|
-
The override is cleared when the process exits; remote sync is otherwise
|
|
314
|
+
explicitly after `--`. Needs `cloudflared` on `PATH` and `CLIVLY_SECRET_KEY`
|
|
315
|
+
set. The override is cleared when the process exits; remote sync is otherwise
|
|
201
316
|
deploy-only.
|
|
202
317
|
|
|
203
|
-
|
|
318
|
+
```bash
|
|
319
|
+
npx clivly dev --port 3000 -- npm run dev
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
It also watches `clivly.config.ts` and tells you when it changes. It cannot
|
|
323
|
+
reload it for you — the config belongs to your app's process, not to the CLI.
|
|
324
|
+
|
|
325
|
+
If registration fails, the warning names the cause: an invalid key, a backend
|
|
326
|
+
without the endpoint enabled, an HTTP status Clivly returned, or a genuine
|
|
327
|
+
network failure. Your app keeps running either way, and outbound sync (your app
|
|
328
|
+
→ Clivly) is unaffected — only dashboard-triggered sync needs the tunnel.
|
|
329
|
+
|
|
330
|
+
| Flag | Effect |
|
|
331
|
+
| --- | --- |
|
|
332
|
+
| `--port <n>` | Local port your app listens on |
|
|
333
|
+
| `--route-path <path>` | Path to your mounted tick route |
|
|
334
|
+
| `--api-url <url>` | Point at a non-default backend |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
### Deprecated aliases
|
|
339
|
+
|
|
340
|
+
`ping`, `connect` and `doctor` each run part of the `status` ladder. They still
|
|
341
|
+
work, and are kept because output and docs have recommended them — but prefer
|
|
342
|
+
`clivly status`, which runs the whole ladder and tells you which step you are on.
|
|
343
|
+
|
|
344
|
+
| Alias | Equivalent scope |
|
|
345
|
+
| --- | --- |
|
|
346
|
+
| `clivly ping` | Credential + reachability |
|
|
347
|
+
| `clivly connect` | The above, plus config and trigger URL |
|
|
348
|
+
| `clivly doctor` | Config, setup checks and edge safety |
|
|
204
349
|
|
|
205
|
-
|
|
350
|
+
Each prints a deprecation notice, then the steps it covers, renumbered to its own
|
|
351
|
+
scope:
|
|
206
352
|
|
|
207
353
|
```bash
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
354
|
+
$ npx clivly ping
|
|
355
|
+
`clivly ping` is a deprecated alias that runs part of `clivly status`. Prefer `clivly status`.
|
|
356
|
+
|
|
357
|
+
Clivly status
|
|
358
|
+
✅ Step 1 of 2 · API key present — Secret key is set.
|
|
359
|
+
✅ Step 2 of 2 · Clivly reachable — Reached org: acme (org_1)
|
|
213
360
|
```
|
|
214
361
|
|
|
215
|
-
`clivly doctor`
|
|
216
|
-
|
|
217
|
-
columns, sample fetch,
|
|
362
|
+
`clivly doctor` runs the same read-only checks as `await clivly.doctor()` in
|
|
363
|
+
code: API key present, entities configured, sources configured, concept
|
|
364
|
+
coverage, Drizzle cursor/id columns, sample fetch, mapping dry-run,
|
|
365
|
+
custom-object slugs, heartbeat, and namespace reachability.
|
|
218
366
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Runtime imports
|
|
370
|
+
|
|
371
|
+
`clivly` is the consolidated public package. Application code imports from typed
|
|
372
|
+
subpaths:
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
import { createClivlySDK, defineClivlyConfig } from "clivly/sdk";
|
|
376
|
+
import { fromDrizzle, discoverFromDrizzle } from "clivly/drizzle";
|
|
377
|
+
import { clivlyVite } from "clivly/vite";
|
|
378
|
+
import { createClerkAuthAdapter } from "clivly/auth/clerk";
|
|
379
|
+
import { createWorkOSAuthAdapter } from "clivly/auth/workos";
|
|
380
|
+
import { createBetterAuthAdapter } from "clivly/auth/better-auth";
|
|
222
381
|
```
|
|
223
382
|
|
|
383
|
+
> **Never `import` from the bare `clivly` specifier.** The package root is the
|
|
384
|
+
> CLI binary — it imports `node:fs` and `node:child_process` at module scope, so
|
|
385
|
+
> importing it from app code drags the whole CLI into your bundle and throws at
|
|
386
|
+
> import time on Workers and other edge runtimes.
|
|
387
|
+
|
|
388
|
+
Provider and framework integrations use **optional peer dependencies**. Install
|
|
389
|
+
only what your app actually uses:
|
|
390
|
+
|
|
391
|
+
| Subpath | Peer dependency |
|
|
392
|
+
| --- | --- |
|
|
393
|
+
| `clivly/drizzle` | `drizzle-orm` |
|
|
394
|
+
| `clivly/vite` | `vite` |
|
|
395
|
+
| `clivly/auth/clerk` | `@clerk/backend` |
|
|
396
|
+
| `clivly/auth/workos` | `@workos-inc/node` |
|
|
397
|
+
| `clivly/auth/better-auth` | none — you pass your own `betterAuth({...})` instance |
|
|
398
|
+
|
|
399
|
+
`clivly/core/*` is deprecated in favour of `clivly/internal/*`. It still
|
|
400
|
+
resolves, and emits a one-time `process.emitWarning` naming the replacement (so
|
|
401
|
+
it stays off stdout and cannot corrupt machine-readable CLI output). See
|
|
402
|
+
[STABILITY.md](https://github.com/amani-joseph/clivly.com/blob/master/STABILITY.md).
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Common errors
|
|
407
|
+
|
|
408
|
+
| Symptom | Fix |
|
|
409
|
+
| --- | --- |
|
|
410
|
+
| Generated code doesn't match these docs | `npx clivly --version` — an older installed version is the usual cause |
|
|
411
|
+
| `init` refuses to write, "No usable contact entity" | Pass `--contact-table <name>` |
|
|
412
|
+
| `init` cannot find your schema | Pass `--schema <path\|package>` |
|
|
413
|
+
| `init` scaffolded a `db` import that doesn't resolve | The probe cannot evaluate a db module that throws without `DATABASE_URL`. Fix the `TODO(clivly)` import path it left, or pass `--db-import` |
|
|
414
|
+
| `clivly login` exits non-zero, pairing unavailable | The backend has `CLIVLY_CLI_PAIRING_ENABLED` off. Use the manual credential path above |
|
|
415
|
+
| `clivly dev` cannot start | Install `cloudflared`, or set `CLIVLY_SYNC_TRIGGER_URL` to a tunnel you run yourself |
|
|
416
|
+
| Credentials written but the app never loads them | Wrong env file for your framework — see the table under `clivly login` |
|
|
417
|
+
|
|
418
|
+
The full troubleshooting table is in the
|
|
419
|
+
[integration guide](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/connecting-to-clivly-cloud.md#8-common-errors-and-troubleshooting).
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
224
423
|
## Telemetry
|
|
225
424
|
|
|
226
425
|
**Clivly collects no telemetry.** The CLI makes network requests only to the
|
|
227
426
|
Clivly API you point it at, and only to do what you asked: pairing, heartbeats,
|
|
228
427
|
schema pushes, and status checks. No usage analytics, no crash reporting, no
|
|
229
|
-
phone-home. See
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- Adding the chat widget
|
|
236
|
-
|
|
237
|
-
-
|
|
238
|
-
|
|
239
|
-
-
|
|
240
|
-
[`@clivly/sdk` README](https://github.com/amani-joseph/clivly.com/blob/master/packages/sdk/README.md)
|
|
241
|
-
- Release notes:
|
|
242
|
-
[CHANGELOG](https://github.com/amani-joseph/clivly.com/blob/master/CHANGELOG.md)
|
|
428
|
+
phone-home. See
|
|
429
|
+
[SECURITY.md](https://github.com/amani-joseph/clivly.com/blob/master/SECURITY.md#telemetry).
|
|
430
|
+
|
|
431
|
+
## Related documentation
|
|
432
|
+
|
|
433
|
+
- **[Connecting to Clivly Cloud](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/connecting-to-clivly-cloud.md)** — the canonical end-to-end guide
|
|
434
|
+
- [Adding the chat widget](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/adding-the-chat-widget.md)
|
|
435
|
+
- [`@clivly/sdk` README](https://github.com/amani-joseph/clivly.com/blob/master/packages/sdk/README.md) — the runtime API surface
|
|
436
|
+
- [STABILITY.md](https://github.com/amani-joseph/clivly.com/blob/master/STABILITY.md) — import tiers
|
|
437
|
+
- [SECURITY.md](https://github.com/amani-joseph/clivly.com/blob/master/SECURITY.md)
|
|
438
|
+
- [CHANGELOG.md](https://github.com/amani-joseph/clivly.com/blob/master/CHANGELOG.md)
|
|
243
439
|
|
|
244
440
|
## License
|
|
245
441
|
|
package/drizzle.cjs
CHANGED
|
@@ -65,11 +65,15 @@ function fromDrizzle(db, table, opts) {
|
|
|
65
65
|
const idColumn = columns[idField];
|
|
66
66
|
if (!cursorColumn) throw new Error(`fromDrizzle: cursorField "${opts.cursorField}" is not a column on "${(0, drizzle_orm.getTableName)(table)}".`);
|
|
67
67
|
if (!idColumn) throw new Error(`fromDrizzle: idField "${idField}" is not a column on "${(0, drizzle_orm.getTableName)(table)}".`);
|
|
68
|
+
const projection = {};
|
|
69
|
+
for (const column of Object.values(columns)) projection[column.name] = column;
|
|
70
|
+
const cursorColumnName = cursorColumn.name;
|
|
71
|
+
const idColumnName = idColumn.name;
|
|
68
72
|
const source = {
|
|
69
73
|
entity: opts.entity,
|
|
70
|
-
cursorField:
|
|
71
|
-
idField,
|
|
72
|
-
fetchPage: ({ since, limit }) => drizzleDb.select().from(table).where(since ? drizzle_orm.sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy((0, drizzle_orm.asc)(cursorColumn), (0, drizzle_orm.asc)(idColumn)).limit(limit)
|
|
74
|
+
cursorField: cursorColumnName,
|
|
75
|
+
idField: idColumnName,
|
|
76
|
+
fetchPage: ({ since, limit }) => drizzleDb.select(projection).from(table).where(since ? drizzle_orm.sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy((0, drizzle_orm.asc)(cursorColumn), (0, drizzle_orm.asc)(idColumn)).limit(limit)
|
|
73
77
|
};
|
|
74
78
|
const meta = {
|
|
75
79
|
columnKeys: Object.keys(columns),
|
package/drizzle.mjs
CHANGED
|
@@ -64,11 +64,15 @@ function fromDrizzle(db, table, opts) {
|
|
|
64
64
|
const idColumn = columns[idField];
|
|
65
65
|
if (!cursorColumn) throw new Error(`fromDrizzle: cursorField "${opts.cursorField}" is not a column on "${getTableName(table)}".`);
|
|
66
66
|
if (!idColumn) throw new Error(`fromDrizzle: idField "${idField}" is not a column on "${getTableName(table)}".`);
|
|
67
|
+
const projection = {};
|
|
68
|
+
for (const column of Object.values(columns)) projection[column.name] = column;
|
|
69
|
+
const cursorColumnName = cursorColumn.name;
|
|
70
|
+
const idColumnName = idColumn.name;
|
|
67
71
|
const source = {
|
|
68
72
|
entity: opts.entity,
|
|
69
|
-
cursorField:
|
|
70
|
-
idField,
|
|
71
|
-
fetchPage: ({ since, limit }) => drizzleDb.select().from(table).where(since ? sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy(asc(cursorColumn), asc(idColumn)).limit(limit)
|
|
73
|
+
cursorField: cursorColumnName,
|
|
74
|
+
idField: idColumnName,
|
|
75
|
+
fetchPage: ({ since, limit }) => drizzleDb.select(projection).from(table).where(since ? sql`(${cursorColumn}, ${idColumn}) > (${since.time}, ${since.id})` : void 0).orderBy(asc(cursorColumn), asc(idColumn)).limit(limit)
|
|
72
76
|
};
|
|
73
77
|
const meta = {
|
|
74
78
|
columnKeys: Object.keys(columns),
|
package/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const require_entity_config = require("./entity-config-D87rV-tE.cjs");
|
|
4
4
|
require("./mapping-score-CaB3F4Uu.cjs");
|
|
5
5
|
const require_internal_entity_heuristics = require("./internal-entity-heuristics.cjs");
|
|
6
|
-
const require_sdk = require("./sdk-
|
|
6
|
+
const require_sdk = require("./sdk-Bj-ZDf4u.cjs");
|
|
7
7
|
let node_child_process = require("node:child_process");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
let node_module = require("node:module");
|
|
@@ -328,8 +328,19 @@ const OVERRIDE_FAILURE_CAUSES = {
|
|
|
328
328
|
not_enabled: "The target backend does not have the feature-flagged trigger-url endpoint enabled (likely the wrong backend, or the flag is off).",
|
|
329
329
|
unreachable: "Could not reach Clivly at the selected API base URL."
|
|
330
330
|
};
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
/**
|
|
332
|
+
* `status` is required in practice for `unexpected_response` and meaningless
|
|
333
|
+
* for the others.
|
|
334
|
+
*
|
|
335
|
+
* Every non-401/404 status used to collapse into `unreachable`, so the CLI told
|
|
336
|
+
* developers it "could not reach Clivly" while Clivly was answering. That is
|
|
337
|
+
* not a wording nit: when neon-http broke these endpoints in production the CLI
|
|
338
|
+
* discarded the one honest signal it had (HTTP 500) and sent people to check
|
|
339
|
+
* their network and API URL, where nothing was wrong. A response is proof of
|
|
340
|
+
* reachability — so say what came back.
|
|
341
|
+
*/
|
|
342
|
+
function overrideFailureMessage(kind, status) {
|
|
343
|
+
return `Warning: could not register the tunnel URL — ${kind === "unexpected_response" ? `Clivly answered HTTP ${status ?? "an error"} — the request reached Clivly but was rejected, so this is a Clivly-side or request problem rather than a network one.` : OVERRIDE_FAILURE_CAUSES[kind]} Dashboard-triggered sync is unavailable this session. Your app is still running.`;
|
|
333
344
|
}
|
|
334
345
|
function cloudflaredMissingMessage() {
|
|
335
346
|
return [
|
|
@@ -384,7 +395,7 @@ async function runDev(options) {
|
|
|
384
395
|
deps.out(`Tunnel: ${triggerUrl}`);
|
|
385
396
|
const result = await deps.register(triggerUrl).catch(() => UNREACHABLE_RESULT);
|
|
386
397
|
if (result.ok) deps.out("Dashboard-triggered sync now points at this local session.");
|
|
387
|
-
else deps.out(overrideFailureMessage(result.kind));
|
|
398
|
+
else deps.out(overrideFailureMessage(result.kind, result.status));
|
|
388
399
|
});
|
|
389
400
|
const stopWatching = deps.watchConfig?.(options.cwd, () => {
|
|
390
401
|
deps.out("clivly.config.ts changed — restart your app for it to take effect.");
|
|
@@ -415,7 +426,18 @@ const HTTP_NOT_FOUND = 404;
|
|
|
415
426
|
function kindForStatus(status) {
|
|
416
427
|
if (status === HTTP_UNAUTHORIZED) return "unauthorized";
|
|
417
428
|
if (status === HTTP_NOT_FOUND) return "not_enabled";
|
|
418
|
-
return "
|
|
429
|
+
return "unexpected_response";
|
|
430
|
+
}
|
|
431
|
+
function failureFor(status) {
|
|
432
|
+
const kind = kindForStatus(status);
|
|
433
|
+
return kind === "unexpected_response" ? {
|
|
434
|
+
ok: false,
|
|
435
|
+
kind,
|
|
436
|
+
status
|
|
437
|
+
} : {
|
|
438
|
+
ok: false,
|
|
439
|
+
kind
|
|
440
|
+
};
|
|
419
441
|
}
|
|
420
442
|
async function registerTunnelOverride(deps) {
|
|
421
443
|
const res = await (deps.fetchImpl ?? globalThis.fetch)(`${deps.apiUrl}${TRIGGER_URL_PATH}`, {
|
|
@@ -427,10 +449,7 @@ async function registerTunnelOverride(deps) {
|
|
|
427
449
|
body: JSON.stringify({ url: deps.triggerUrl })
|
|
428
450
|
});
|
|
429
451
|
if (res.ok) return { ok: true };
|
|
430
|
-
return
|
|
431
|
-
ok: false,
|
|
432
|
-
kind: kindForStatus(res.status)
|
|
433
|
-
};
|
|
452
|
+
return failureFor(res.status);
|
|
434
453
|
}
|
|
435
454
|
async function clearTunnelOverride(deps) {
|
|
436
455
|
const res = await (deps.fetchImpl ?? globalThis.fetch)(`${deps.apiUrl}${TRIGGER_URL_PATH}`, {
|
|
@@ -438,10 +457,7 @@ async function clearTunnelOverride(deps) {
|
|
|
438
457
|
headers: { authorization: `Bearer ${deps.apiKey}` }
|
|
439
458
|
});
|
|
440
459
|
if (res.ok) return { ok: true };
|
|
441
|
-
return
|
|
442
|
-
ok: false,
|
|
443
|
-
kind: kindForStatus(res.status)
|
|
444
|
-
};
|
|
460
|
+
return failureFor(res.status);
|
|
445
461
|
}
|
|
446
462
|
//#endregion
|
|
447
463
|
//#region src/probe-module.ts
|
package/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { t as CANONICAL_FIELDS } from "./entity-config-va2bkH5o.mjs";
|
|
3
3
|
import "./mapping-score-C68uAqGB.mjs";
|
|
4
4
|
import { matchesConcept, requiredFieldsFor, scoreFieldMap, scoreRelationships, suggestCursorField, toFieldMap } from "./internal-entity-heuristics.mjs";
|
|
5
|
-
import { t as createClivlySDK } from "./sdk-
|
|
5
|
+
import { t as createClivlySDK } from "./sdk-BvRD2jAp.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
8
8
|
import { accessSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, watch, writeFileSync } from "node:fs";
|
|
@@ -327,8 +327,19 @@ const OVERRIDE_FAILURE_CAUSES = {
|
|
|
327
327
|
not_enabled: "The target backend does not have the feature-flagged trigger-url endpoint enabled (likely the wrong backend, or the flag is off).",
|
|
328
328
|
unreachable: "Could not reach Clivly at the selected API base URL."
|
|
329
329
|
};
|
|
330
|
-
|
|
331
|
-
|
|
330
|
+
/**
|
|
331
|
+
* `status` is required in practice for `unexpected_response` and meaningless
|
|
332
|
+
* for the others.
|
|
333
|
+
*
|
|
334
|
+
* Every non-401/404 status used to collapse into `unreachable`, so the CLI told
|
|
335
|
+
* developers it "could not reach Clivly" while Clivly was answering. That is
|
|
336
|
+
* not a wording nit: when neon-http broke these endpoints in production the CLI
|
|
337
|
+
* discarded the one honest signal it had (HTTP 500) and sent people to check
|
|
338
|
+
* their network and API URL, where nothing was wrong. A response is proof of
|
|
339
|
+
* reachability — so say what came back.
|
|
340
|
+
*/
|
|
341
|
+
function overrideFailureMessage(kind, status) {
|
|
342
|
+
return `Warning: could not register the tunnel URL — ${kind === "unexpected_response" ? `Clivly answered HTTP ${status ?? "an error"} — the request reached Clivly but was rejected, so this is a Clivly-side or request problem rather than a network one.` : OVERRIDE_FAILURE_CAUSES[kind]} Dashboard-triggered sync is unavailable this session. Your app is still running.`;
|
|
332
343
|
}
|
|
333
344
|
function cloudflaredMissingMessage() {
|
|
334
345
|
return [
|
|
@@ -383,7 +394,7 @@ async function runDev(options) {
|
|
|
383
394
|
deps.out(`Tunnel: ${triggerUrl}`);
|
|
384
395
|
const result = await deps.register(triggerUrl).catch(() => UNREACHABLE_RESULT);
|
|
385
396
|
if (result.ok) deps.out("Dashboard-triggered sync now points at this local session.");
|
|
386
|
-
else deps.out(overrideFailureMessage(result.kind));
|
|
397
|
+
else deps.out(overrideFailureMessage(result.kind, result.status));
|
|
387
398
|
});
|
|
388
399
|
const stopWatching = deps.watchConfig?.(options.cwd, () => {
|
|
389
400
|
deps.out("clivly.config.ts changed — restart your app for it to take effect.");
|
|
@@ -414,7 +425,18 @@ const HTTP_NOT_FOUND = 404;
|
|
|
414
425
|
function kindForStatus(status) {
|
|
415
426
|
if (status === HTTP_UNAUTHORIZED) return "unauthorized";
|
|
416
427
|
if (status === HTTP_NOT_FOUND) return "not_enabled";
|
|
417
|
-
return "
|
|
428
|
+
return "unexpected_response";
|
|
429
|
+
}
|
|
430
|
+
function failureFor(status) {
|
|
431
|
+
const kind = kindForStatus(status);
|
|
432
|
+
return kind === "unexpected_response" ? {
|
|
433
|
+
ok: false,
|
|
434
|
+
kind,
|
|
435
|
+
status
|
|
436
|
+
} : {
|
|
437
|
+
ok: false,
|
|
438
|
+
kind
|
|
439
|
+
};
|
|
418
440
|
}
|
|
419
441
|
async function registerTunnelOverride(deps) {
|
|
420
442
|
const res = await (deps.fetchImpl ?? globalThis.fetch)(`${deps.apiUrl}${TRIGGER_URL_PATH}`, {
|
|
@@ -426,10 +448,7 @@ async function registerTunnelOverride(deps) {
|
|
|
426
448
|
body: JSON.stringify({ url: deps.triggerUrl })
|
|
427
449
|
});
|
|
428
450
|
if (res.ok) return { ok: true };
|
|
429
|
-
return
|
|
430
|
-
ok: false,
|
|
431
|
-
kind: kindForStatus(res.status)
|
|
432
|
-
};
|
|
451
|
+
return failureFor(res.status);
|
|
433
452
|
}
|
|
434
453
|
async function clearTunnelOverride(deps) {
|
|
435
454
|
const res = await (deps.fetchImpl ?? globalThis.fetch)(`${deps.apiUrl}${TRIGGER_URL_PATH}`, {
|
|
@@ -437,10 +456,7 @@ async function clearTunnelOverride(deps) {
|
|
|
437
456
|
headers: { authorization: `Bearer ${deps.apiKey}` }
|
|
438
457
|
});
|
|
439
458
|
if (res.ok) return { ok: true };
|
|
440
|
-
return
|
|
441
|
-
ok: false,
|
|
442
|
-
kind: kindForStatus(res.status)
|
|
443
|
-
};
|
|
459
|
+
return failureFor(res.status);
|
|
444
460
|
}
|
|
445
461
|
//#endregion
|
|
446
462
|
//#region src/probe-module.ts
|
package/package.json
CHANGED
|
@@ -361,7 +361,7 @@ function cursorColumnChecks(sources) {
|
|
|
361
361
|
});
|
|
362
362
|
continue;
|
|
363
363
|
}
|
|
364
|
-
const idField = source.idField ?? "id";
|
|
364
|
+
const idField = meta.idField ?? source.idField ?? "id";
|
|
365
365
|
const missing = [meta.cursorField, idField].filter((field) => !meta.columnKeys.includes(field));
|
|
366
366
|
checks.push({
|
|
367
367
|
name: `Cursor/id columns exist (${source.entity})`,
|
|
@@ -361,7 +361,7 @@ function cursorColumnChecks(sources) {
|
|
|
361
361
|
});
|
|
362
362
|
continue;
|
|
363
363
|
}
|
|
364
|
-
const idField = source.idField ?? "id";
|
|
364
|
+
const idField = meta.idField ?? source.idField ?? "id";
|
|
365
365
|
const missing = [meta.cursorField, idField].filter((field) => !meta.columnKeys.includes(field));
|
|
366
366
|
checks.push({
|
|
367
367
|
name: `Cursor/id columns exist (${source.entity})`,
|
package/sdk.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_entity_config = require("./entity-config-D87rV-tE.cjs");
|
|
3
|
-
const require_sdk = require("./sdk-
|
|
3
|
+
const require_sdk = require("./sdk-Bj-ZDf4u.cjs");
|
|
4
4
|
exports.ClivlyAuthError = require_sdk.ClivlyAuthError;
|
|
5
5
|
exports.ClivlyError = require_sdk.ClivlyError;
|
|
6
6
|
exports.ClivlyNetworkError = require_sdk.ClivlyNetworkError;
|
package/sdk.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { o as defineClivlyConfig } from "./entity-config-va2bkH5o.mjs";
|
|
2
|
-
import { a as ClivlyRateLimitError, i as ClivlyNetworkError, n as ClivlyAuthError, o as createChatSessionHandler, r as ClivlyError, t as createClivlySDK } from "./sdk-
|
|
2
|
+
import { a as ClivlyRateLimitError, i as ClivlyNetworkError, n as ClivlyAuthError, o as createChatSessionHandler, r as ClivlyError, t as createClivlySDK } from "./sdk-BvRD2jAp.mjs";
|
|
3
3
|
export { ClivlyAuthError, ClivlyError, ClivlyNetworkError, ClivlyRateLimitError, createChatSessionHandler, createClivlySDK, defineClivlyConfig };
|