@hasna/shortlinks 0.2.5 → 0.2.10

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Shortlink management for custom domains — CLI, MCP server, REST API, and a generated SDK.
4
4
 
5
- `shortlinks` creates Bitly-style short URLs, supports multiple domains, records click analytics, can run a tiny redirect server, and includes helper commands for Cloudflare DNS/Workers and `@hasna/domains`. It defaults to local SQLite and can serve from an app-owned PostgreSQL database when `HASNA_SHORTLINKS_STORE=postgres` and `HASNA_SHORTLINKS_DATABASE_URL` are configured.
5
+ `shortlinks` creates Bitly-style short URLs, supports multiple domains, records click analytics, can run a tiny redirect server, and includes helper commands for Cloudflare DNS/Workers and `@hasna/domains`. It defaults to local SQLite and serves from an app-owned PostgreSQL database when `HASNA_SHORTLINKS_DATABASE_URL` is configured.
6
6
 
7
7
  ## Surfaces
8
8
 
@@ -15,19 +15,18 @@ Four surfaces share one core library:
15
15
  | REST API | `shortlinks-serve` | HTTP service: `GET /health`, `/ready`, `/version`, `/openapi.json`, and a versioned `/v1` CRUD API guarded by API-key auth. |
16
16
  | SDK | `@hasna/shortlinks-sdk` (+ `@hasna/shortlinks/sdk`) | Typed fetch client generated from the serve OpenAPI (`bun run sdk:generate`). |
17
17
 
18
- ### Cloud service (PURE REMOTE, Amendment A1)
18
+ ### Hosted service
19
19
 
20
- `shortlinks-serve` reads/writes the shared cloud Postgres directly via the vendored `@hasna/contracts` storage kit — no sync engine or cache in the service. API-key auth comes from `@hasna/contracts/auth`; mint keys with `contracts issue-key --app shortlinks --scopes 'shortlinks:read,shortlinks:write'`.
20
+ `shortlinks-serve` reads/writes PostgreSQL directly via the vendored `@hasna/contracts` storage kit — no sync engine or cache in the service. A configured `HASNA_SHORTLINKS_DATABASE_URL` selects the postgresql server data backend; the pool factory fails closed without it. API-key auth comes from `@hasna/contracts/auth`; mint keys with `contracts issue-key --app shortlinks --scopes 'shortlinks:read,shortlinks:write'`.
21
21
 
22
22
  ```bash
23
- HASNA_SHORTLINKS_STORAGE_MODE=cloud \
24
- HASNA_SHORTLINKS_DATABASE_URL=postgres://user:pass@host:5432/shortlinks?sslmode=require \
23
+ HASNA_SHORTLINKS_DATABASE_URL=$DATABASE_URL \
25
24
  HASNA_SHORTLINKS_API_SIGNING_KEY=... \
26
25
  shortlinks-serve # migrate (idempotent) then serve on :8080
27
26
  shortlinks-serve migrate # one-shot migration task
28
27
  ```
29
28
 
30
- Client self_hosted mode uses `SHORTLINKS_API_URL` + `SHORTLINKS_API_KEY` (never a DSN).
29
+ Clients use `SHORTLINKS_API_URL` + `SHORTLINKS_API_KEY` (never a DSN).
31
30
 
32
31
  [![npm](https://img.shields.io/npm/v/@hasna/shortlinks)](https://www.npmjs.com/package/@hasna/shortlinks)
33
32
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
@@ -71,6 +70,41 @@ Errors are emitted as:
71
70
  { "error": "message" }
72
71
  ```
73
72
 
73
+ ## Compact Defaults and Details
74
+
75
+ Human output is compact by default so agent terminals do not fill with full
76
+ records. List and status commands show essential fields, truncate long URLs or
77
+ text, cap human rows, and print the next command to use for details.
78
+
79
+ Use these gradual disclosure paths when you need more:
80
+
81
+ ```bash
82
+ shortlinks link list --limit 50
83
+ shortlinks link get home --verbose
84
+ shortlinks stats home --verbose
85
+ shortlinks doctor --verbose
86
+ shortlinks domain check has.na --verbose
87
+ shortlinks events list --limit 50
88
+ shortlinks webhooks list --limit 50
89
+ shortlinks --json link get home
90
+ ```
91
+
92
+ `--json` remains the machine-readable path and keeps full objects where commands
93
+ already returned them. Prefer `--json` for automation and `--verbose` for human
94
+ debugging.
95
+
96
+ Example compact output:
97
+
98
+ ```text
99
+ https://has.na/home -> https://example.com/landing-page-with-a-very-long-path... active
100
+ Showing 1 link(s).
101
+ Use `shortlinks link get <slug>` for details.
102
+ ```
103
+
104
+ Before this behavior, detail/status commands such as `shortlinks link get home`,
105
+ `shortlinks stats home`, and `shortlinks doctor` printed full JSON-like objects
106
+ by default.
107
+
74
108
  ## CLI
75
109
 
76
110
  ```bash
@@ -126,8 +160,8 @@ Create a dry-run plan:
126
160
 
127
161
  ```bash
128
162
  shortlinks cloudflare plan has.na \
129
- --target shortlinks.hasna.xyz \
130
- --origin https://shortlinks.hasna.xyz
163
+ --target shortlinks.example.com \
164
+ --origin https://shortlinks.example.com
131
165
  ```
132
166
 
133
167
  Write a Cloudflare Worker that forwards requests to the redirect server while preserving the original host:
@@ -135,13 +169,13 @@ Write a Cloudflare Worker that forwards requests to the redirect server while pr
135
169
  ```bash
136
170
  shortlinks cloudflare worker \
137
171
  --worker shortlinks \
138
- --origin https://shortlinks.hasna.xyz
172
+ --origin https://shortlinks.example.com
139
173
  ```
140
174
 
141
175
  Upsert DNS when `CLOUDFLARE_API_TOKEN` is available. Global API key auth is also supported with `CLOUDFLARE_API_KEY` plus `CLOUDFLARE_EMAIL`.
142
176
 
143
177
  ```bash
144
- shortlinks cloudflare dns has.na --target shortlinks.hasna.xyz
178
+ shortlinks cloudflare dns has.na --target shortlinks.example.com
145
179
  ```
146
180
 
147
181
  ## Buying Domains
@@ -155,28 +189,26 @@ shortlinks domain buy new-short-domain.ai --dry-run
155
189
 
156
190
  This package does not install or call any removed `connect-*` packages.
157
191
 
158
- ## Storage modes
192
+ ## Storage selection
159
193
 
160
194
  The client resolves ONE `Store` from the environment — there is no DSN on any client:
161
195
 
162
- - **local** (default): on-box SQLite. Every command, MCP tool, and SDK call reads
163
- and writes the local database.
164
- - **self_hosted / cloud**: set `HASNA_SHORTLINKS_API_URL` + `HASNA_SHORTLINKS_API_KEY`
165
- (and optionally `HASNA_SHORTLINKS_STORAGE_MODE`) to route every call to the cloud
166
- `/v1` HTTP API with a bearer key. `self_hosted` and `cloud` are identical client
167
- code; only the URL/key differ.
196
+ - **on-box SQLite** (default): every command, MCP tool, and SDK call reads and
197
+ writes the local database.
198
+ - **hosted `/v1` HTTP API**: set `HASNA_SHORTLINKS_API_URL` + `HASNA_SHORTLINKS_API_KEY`
199
+ to route every call to the hosted `/v1` API with a bearer key. Setting only one
200
+ of the two is a configuration error and fails loudly never silent local drift.
168
201
 
169
202
  ```bash
170
- # Route the client to the self-hosted cloud API (bearer key, never a DSN):
171
- export HASNA_SHORTLINKS_API_URL=https://shortlinks.hasna.xyz
203
+ # Route the client to the hosted API (bearer key, never a DSN):
204
+ export HASNA_SHORTLINKS_API_URL=https://shortlinks.example.com
172
205
  export HASNA_SHORTLINKS_API_KEY=hsk_...
173
- export HASNA_SHORTLINKS_STORAGE_MODE=self_hosted
174
206
  shortlinks doctor
175
207
  ```
176
208
 
177
- The cloud server (`shortlinks-serve`, run on ECS Fargate) is the only component
178
- that holds a Postgres connection, and it opens its pool server-side through the
179
- sanctioned storage kit — the raw RDS DSN is never distributed to clients.
209
+ The server (`shortlinks-serve`) is the only component that holds a Postgres
210
+ connection, and it opens its pool server-side through the sanctioned storage
211
+ kit — the raw RDS DSN is never distributed to clients.
180
212
 
181
213
  ## Development
182
214
 
@@ -195,7 +227,7 @@ The OSS repository is expected to be:
195
227
  hasna/shortlinks
196
228
  ```
197
229
 
198
- The local workspace folder may still be named `open-shortlinks`; the published package and GitHub repo do not use the `open-` prefix.
230
+ The local workspace folder is named `shortlinks`; the published package and GitHub repo use bare names without the retired `open-` prefix.
199
231
 
200
232
  ## License
201
233
 
@@ -3,4 +3,4 @@ main = "shortlinks.js"
3
3
  compatibility_date = "2026-05-01"
4
4
 
5
5
  [vars]
6
- SHORTLINKS_ORIGIN = "https://shortlinks.hasna.xyz"
6
+ SHORTLINKS_ORIGIN = "https://shortlinks.example.com"