@nohead/sdk 0.5.0 → 0.6.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.
- package/CHANGELOG.md +36 -0
- package/README.md +54 -16
- package/dist/client.d.ts +2 -1
- package/dist/client.js +3 -1
- package/dist/core.d.ts +4 -1
- package/dist/generated/operations.gen.d.ts +16 -8
- package/dist/generated/operations.gen.js +2 -1
- package/dist/generated/schemas.gen.d.ts +1 -1
- package/dist/generated/types.gen.d.ts +142 -46
- package/dist/images.d.ts +75 -0
- package/dist/images.js +113 -0
- package/dist/resources/assets.d.ts +10 -5
- package/dist/resources/assets.js +10 -5
- package/dist/resources/records.d.ts +14 -3
- package/dist/resources/records.js +15 -2
- package/dist/types.d.ts +5 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,42 @@ Changes to `@nohead/sdk` that you can notice. Versions follow
|
|
|
5
5
|
releases; a change that could break your code is a major one. Each release's
|
|
6
6
|
section is its GitHub release's notes.
|
|
7
7
|
|
|
8
|
+
## 0.6.0
|
|
9
|
+
|
|
10
|
+
- API keys now start `nohead_sk_`, or `nohead_pk_` for published-only keys;
|
|
11
|
+
keys in the old `sk_live_` format no longer work. The SDK sends whatever key
|
|
12
|
+
it's given, so only the docs and examples change.
|
|
13
|
+
|
|
14
|
+
- `assets.update(asset, { filename?, alt? })` renames an asset and sets its
|
|
15
|
+
alt text (`PATCH /v1/assets/{asset_id}`). `Asset` has `alt` (a string or
|
|
16
|
+
`null`), and webhooks can subscribe to `asset.updated`.
|
|
17
|
+
|
|
18
|
+
- Image URLs are open. `Asset` has `image_url`, the whole image, and
|
|
19
|
+
`imageUrl` from the new `@nohead/sdk/images` (no dependencies) writes any of
|
|
20
|
+
imgproxy's processing options into it, without a request. It also has
|
|
21
|
+
loaders for Next.js (`nextImageLoader`), Astro (`astroImageService`) and
|
|
22
|
+
Nuxt Image (`nuxtImageProvider`, or `getImage` on Nuxt Image 1), which leave
|
|
23
|
+
other images as they are.
|
|
24
|
+
|
|
25
|
+
- **Breaking:** `assets.imageUrl` is gone, with the API's
|
|
26
|
+
`GET /v1/assets/{asset_id}/image-url`: use `imageUrl` from
|
|
27
|
+
`@nohead/sdk/images`, which needs no request.
|
|
28
|
+
|
|
29
|
+
- **Breaking:** `Collection` has no `search_enabled`, and `SearchIndex` no
|
|
30
|
+
`enabled`: API keys search every collection they can read.
|
|
31
|
+
|
|
32
|
+
- `revisions.get(revision)` reads a revision by its own `rev_` ID, as
|
|
33
|
+
webhooks and the activity log name it (`GET /v1/revisions/{revision_id}`).
|
|
34
|
+
|
|
35
|
+
- `records.create` takes `upsert_on`, a unique field's key: the record
|
|
36
|
+
holding that value is updated instead, if one exists, and `ifMatch`
|
|
37
|
+
applies to that update.
|
|
38
|
+
|
|
39
|
+
- Collections have `public_search`: whether the project's search tokens find
|
|
40
|
+
their published records. Off by default; `collections.create` and
|
|
41
|
+
`collections.update` take it. A collection's search index has `index`, the
|
|
42
|
+
name a token searches it by.
|
|
43
|
+
|
|
8
44
|
## 0.5.0
|
|
9
45
|
|
|
10
46
|
- **Breaking:** field migrations are created under their collection:
|
package/README.md
CHANGED
|
@@ -51,17 +51,17 @@ const nohead = new Nohead({
|
|
|
51
51
|
})
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
| Option | Default |
|
|
55
|
-
| ------------ | ---------------------------------------------- |
|
|
56
|
-
| `apiKey` | `NOHEAD_API_KEY` | A project API key (`
|
|
57
|
-
| `baseUrl` | `NOHEAD_API_URL`, else `https://api.nohead.io` |
|
|
58
|
-
| `projectId` | the key's project | Looked up once with `GET /v1/me` when omitted.
|
|
59
|
-
| `maxRetries` | `2` | See [retries](#retries-and-idempotency).
|
|
60
|
-
| `timeout` | `60000` | Milliseconds per attempt.
|
|
61
|
-
| `fetch` | `globalThis.fetch` | For proxies, instrumentation and tests.
|
|
62
|
-
| `headers` | `{}` | Added to every request.
|
|
63
|
-
| `warnings` | `true` | Logs deprecation and plan usage warnings, once each.
|
|
64
|
-
| `onRetry` | | Called before each retry. See [retries](#retries-and-idempotency).
|
|
54
|
+
| Option | Default | |
|
|
55
|
+
| ------------ | ---------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
56
|
+
| `apiKey` | `NOHEAD_API_KEY` | A project API key (`nohead_sk_…`, or `nohead_pk_…` when published-only). Required. |
|
|
57
|
+
| `baseUrl` | `NOHEAD_API_URL`, else `https://api.nohead.io` | |
|
|
58
|
+
| `projectId` | the key's project | Looked up once with `GET /v1/me` when omitted. |
|
|
59
|
+
| `maxRetries` | `2` | See [retries](#retries-and-idempotency). |
|
|
60
|
+
| `timeout` | `60000` | Milliseconds per attempt. |
|
|
61
|
+
| `fetch` | `globalThis.fetch` | For proxies, instrumentation and tests. |
|
|
62
|
+
| `headers` | `{}` | Added to every request. |
|
|
63
|
+
| `warnings` | `true` | Logs deprecation and plan usage warnings, once each. |
|
|
64
|
+
| `onRetry` | | Called before each retry. See [retries](#retries-and-idempotency). |
|
|
65
65
|
|
|
66
66
|
API keys belong to a project, so methods like `collections.list()` need no project ID. Collections can be named by ID or slug everywhere.
|
|
67
67
|
|
|
@@ -81,6 +81,15 @@ await nohead.records.delete(post.id) // soft delete; records.restore() undoes it
|
|
|
81
81
|
|
|
82
82
|
`schedule` sets the whole schedule: a time left out is cleared, so `{ unpublish_at }` alone drops a pending publish.
|
|
83
83
|
|
|
84
|
+
**Upserts.** With `upsert_on`, the key of a `unique` field, `create` updates the record holding that value instead, if one exists, so a content sync can run again without duplicates:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
await nohead.records.create("products", {
|
|
88
|
+
data: { sku: "TEE-01", title: "Tee" },
|
|
89
|
+
upsert_on: "sku",
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
84
93
|
Methods return the resource and throw on failure. Field names stay as the API sends them (`published_at`, `data`), so the API reference applies as-is.
|
|
85
94
|
|
|
86
95
|
**Typed data.** Describe a collection's fields and pass the type:
|
|
@@ -97,7 +106,7 @@ await nohead.records.update<Post>(id, { data: { title: null } }) // null clears
|
|
|
97
106
|
|
|
98
107
|
The type is a promise you make; nothing is checked at runtime. The record type itself is `Nohead.Record<Post>` (also exported as `NoheadRecord`).
|
|
99
108
|
|
|
100
|
-
**More:** `count`, `bulk` (up to 100 records at once), `diff`, `revisions.list`, `revisions.get` and `revisions.revert` (with `{ dry_run: true }` for a preview).
|
|
109
|
+
**More:** `count`, `bulk` (up to 100 records at once), `diff`, `revisions.list`, `revisions.get` and `revisions.revert` (with `{ dry_run: true }` for a preview). A revision by its own ID, as webhooks and the activity log name it: `nohead.revisions.get("rev_…")`.
|
|
101
110
|
|
|
102
111
|
## Drafts
|
|
103
112
|
|
|
@@ -258,13 +267,33 @@ const asset = await nohead.assets.upload(await openAsBlob("cover.jpg"), {
|
|
|
258
267
|
filename: "cover.jpg",
|
|
259
268
|
})
|
|
260
269
|
await nohead.records.update(id, { data: { cover: asset.id } })
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Images.** Image URLs are open: an image's `image_url` serves the whole image, and any of [imgproxy's processing options](https://docs.imgproxy.net/usage/processing) written into it transform it. `@nohead/sdk/images` builds them without a request, and has no dependencies, so it suits browser bundles:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import { imageUrl } from "@nohead/sdk/images"
|
|
261
276
|
|
|
262
|
-
|
|
277
|
+
imageUrl(asset, {
|
|
263
278
|
width: 1200,
|
|
279
|
+
height: 630,
|
|
280
|
+
fit: "cover",
|
|
281
|
+
gravity: "sm",
|
|
264
282
|
format: "webp",
|
|
265
283
|
})
|
|
284
|
+
imageUrl(asset.image_url!, { width: 400, dpr: 2, options: ["bl:2"] })
|
|
266
285
|
```
|
|
267
286
|
|
|
287
|
+
Frameworks' image components, with `srcset` and all, take a loader from it:
|
|
288
|
+
|
|
289
|
+
- **Next.js:** a file named by `images.loaderFile` in next.config: `export { nextImageLoader as default } from "@nohead/sdk/images"`, then `<Image src={asset.image_url} … />`.
|
|
290
|
+
- **Astro:** a module named by `image.service.entrypoint` in astro.config: `export { astroImageService as default } from "@nohead/sdk/images"`.
|
|
291
|
+
- **Nuxt Image:** a custom provider file in nuxt.config's `image.providers`: `export { nuxtImageProvider as default } from "@nohead/sdk/images"` (Nuxt Image 1: `export { getImage } from "@nohead/sdk/images"`).
|
|
292
|
+
|
|
293
|
+
The loaders leave other images, the site's own, as they are.
|
|
294
|
+
|
|
295
|
+
Thumbnails: an image's `preview_url` fits in 640×640, as WebP.
|
|
296
|
+
|
|
268
297
|
**What `upload` accepts:** a `Blob`, `File`, `ArrayBuffer`, `Uint8Array`, or a `ReadableStream` with `byte_size`.
|
|
269
298
|
|
|
270
299
|
**What it does:**
|
|
@@ -279,6 +308,14 @@ const { url } = await nohead.assets.imageUrl(asset.id, {
|
|
|
279
308
|
|
|
280
309
|
**Uploading from a browser:** create the upload on your server with `createUpload`, `PUT` the file from the browser, then `complete` it.
|
|
281
310
|
|
|
311
|
+
**Renaming and alt text:** `update` changes an asset's `filename` and `alt` text, the default wherever the asset is used (`expand` returns it with the asset). The file itself never changes.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
await nohead.assets.update(asset.id, {
|
|
315
|
+
alt: "The spring menu, on a chalkboard",
|
|
316
|
+
})
|
|
317
|
+
```
|
|
318
|
+
|
|
282
319
|
**Deleting:** `delete` keeps a deleted asset until its `purge_after` (30 days), and `restore` brings it back. To remove it for good now, `purge` it after the delete. Records that use it keep an ID that no longer resolves, so check `usage` first:
|
|
283
320
|
|
|
284
321
|
```ts
|
|
@@ -298,7 +335,7 @@ const results = await nohead.search("content model", { collections: ["posts", "p
|
|
|
298
335
|
results.meta.total_estimate
|
|
299
336
|
```
|
|
300
337
|
|
|
301
|
-
Search needs `
|
|
338
|
+
Search needs the `search:read` scope and covers every collection the key can read, matching their `searchable` fields. It pages through the first 1,000 hits. For search straight from a site's browser, without the API, use a search token from the web app with Meilisearch's own clients or InstantSearch.
|
|
302
339
|
|
|
303
340
|
## Schema
|
|
304
341
|
|
|
@@ -370,13 +407,14 @@ response.headers.get("RateLimit-Remaining")
|
|
|
370
407
|
| `records` | `list`, `get`, `create`, `update`, `delete`, `restore`, `publish`, `unpublish`, `publication`, `getSchedule`, `schedule`, `unschedule`, `scheduledChanges`, `drafts`, `count`, `bulk`, `diff`, `search` |
|
|
371
408
|
| `drafts` | `create`, `list`, `get`, `update`, `discard`, `merge`, `schedule`, `unschedule` |
|
|
372
409
|
| `records.revisions` | `list`, `get`, `revert` |
|
|
410
|
+
| `revisions` | `get` (by its own `rev_` ID, as webhooks and the activity log name it) |
|
|
373
411
|
| `search` | across the project |
|
|
374
412
|
| `collections` | `list`, `get`, `create`, `update`, `delete`, `restore`, `schema` |
|
|
375
413
|
| `collections.schemaChanges` | `list`, `get` |
|
|
376
414
|
| `collections.searchIndex` | `get`, `rebuild` |
|
|
377
415
|
| `fields` | `list`, `get`, `create`, `update`, `delete`, `restore`, `order`, `reorder`, `removeAlias` |
|
|
378
416
|
| `migrations` | `create`, `list`, `get`, `cancel` |
|
|
379
|
-
| `assets` | `upload`, `createUpload`, `complete`, `list`, `get`, `delete`, `restore`, `purge`, `usage`, `
|
|
417
|
+
| `assets` | `upload`, `createUpload`, `complete`, `list`, `get`, `update`, `delete`, `restore`, `purge`, `usage`, `downloadUrl` |
|
|
380
418
|
| `webhooks` | `list`, `get`, `create`, `update`, `delete`, `restore`, `rotateSecret`, `test`, `unwrap` |
|
|
381
419
|
| `webhooks.secrets` | `list`, `retire` |
|
|
382
420
|
| `webhooks.deliveries` | `list`, `get`, `retry` |
|
|
@@ -395,7 +433,7 @@ npm test # unit and contract tests
|
|
|
395
433
|
npm run lint && npm run typecheck && npm run format:check
|
|
396
434
|
npm run generate # after updating openapi.json
|
|
397
435
|
npm run samples # after changing test/calls.ts (the docs' code samples)
|
|
398
|
-
NOHEAD_API_URL=http://localhost:3000 NOHEAD_API_KEY=
|
|
436
|
+
NOHEAD_API_URL=http://localhost:3000 NOHEAD_API_KEY=nohead_sk_… npm run smoke
|
|
399
437
|
```
|
|
400
438
|
|
|
401
439
|
**How the code is organized:**
|
package/dist/client.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type * as G from "./generated/types.gen.ts";
|
|
|
4
4
|
import { Assets } from "./resources/assets.ts";
|
|
5
5
|
import { Drafts } from "./resources/drafts.ts";
|
|
6
6
|
import { AuditEvents, FeatureFlags, Health, Me } from "./resources/other.ts";
|
|
7
|
-
import { Records } from "./resources/records.ts";
|
|
7
|
+
import { Records, RevisionsById } from "./resources/records.ts";
|
|
8
8
|
import { Collections, Fields, Migrations } from "./resources/schema.ts";
|
|
9
9
|
import { Webhooks } from "./resources/webhooks.ts";
|
|
10
10
|
import type { NoheadDraft, NoheadRecord, ProjectSearchParams, RecordData, SearchMeta } from "./types.ts";
|
|
@@ -19,6 +19,7 @@ import type { NoheadDraft, NoheadRecord, ProjectSearchParams, RecordData, Search
|
|
|
19
19
|
export declare class Nohead {
|
|
20
20
|
#private;
|
|
21
21
|
readonly records: Records;
|
|
22
|
+
readonly revisions: RevisionsById;
|
|
22
23
|
readonly drafts: Drafts;
|
|
23
24
|
readonly collections: Collections;
|
|
24
25
|
readonly fields: Fields;
|
package/dist/client.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Core } from "./core.js";
|
|
|
2
2
|
import { Assets } from "./resources/assets.js";
|
|
3
3
|
import { Drafts } from "./resources/drafts.js";
|
|
4
4
|
import { AuditEvents, FeatureFlags, Health, Me } from "./resources/other.js";
|
|
5
|
-
import { Records } from "./resources/records.js";
|
|
5
|
+
import { Records, RevisionsById } from "./resources/records.js";
|
|
6
6
|
import { Collections, Fields, Migrations } from "./resources/schema.js";
|
|
7
7
|
import { Webhooks } from "./resources/webhooks.js";
|
|
8
8
|
/**
|
|
@@ -15,6 +15,7 @@ import { Webhooks } from "./resources/webhooks.js";
|
|
|
15
15
|
*/
|
|
16
16
|
export class Nohead {
|
|
17
17
|
records;
|
|
18
|
+
revisions;
|
|
18
19
|
drafts;
|
|
19
20
|
collections;
|
|
20
21
|
fields;
|
|
@@ -30,6 +31,7 @@ export class Nohead {
|
|
|
30
31
|
const core = new Core(options);
|
|
31
32
|
this.#core = core;
|
|
32
33
|
this.records = new Records(core);
|
|
34
|
+
this.revisions = new RevisionsById(core);
|
|
33
35
|
this.drafts = new Drafts(core);
|
|
34
36
|
this.collections = new Collections(core);
|
|
35
37
|
this.fields = new Fields(core);
|
package/dist/core.d.ts
CHANGED
|
@@ -4,7 +4,10 @@ import { type OperationId, type Operations } from "./generated/operations.gen.ts
|
|
|
4
4
|
import type { ListMeta } from "./generated/types.gen.ts";
|
|
5
5
|
export declare const DEFAULT_BASE_URL = "https://api.nohead.io";
|
|
6
6
|
export interface ClientOptions {
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* A project API key (`nohead_sk_…`, or `nohead_pk_…` when published-only).
|
|
9
|
+
* Defaults to `NOHEAD_API_KEY`.
|
|
10
|
+
*/
|
|
8
11
|
apiKey?: string;
|
|
9
12
|
/** Defaults to `NOHEAD_API_URL`, else `https://api.nohead.io`. */
|
|
10
13
|
baseUrl?: string;
|
|
@@ -16,10 +16,6 @@ export declare const OPERATIONS: {
|
|
|
16
16
|
readonly method: "GET";
|
|
17
17
|
readonly path: "/v1/assets/{asset_id}";
|
|
18
18
|
};
|
|
19
|
-
readonly assets_image_url: {
|
|
20
|
-
readonly method: "GET";
|
|
21
|
-
readonly path: "/v1/assets/{asset_id}/image-url";
|
|
22
|
-
};
|
|
23
19
|
readonly assets_list: {
|
|
24
20
|
readonly method: "GET";
|
|
25
21
|
readonly path: "/v1/projects/{project_id}/assets";
|
|
@@ -32,6 +28,10 @@ export declare const OPERATIONS: {
|
|
|
32
28
|
readonly method: "POST";
|
|
33
29
|
readonly path: "/v1/assets/{asset_id}/restore";
|
|
34
30
|
};
|
|
31
|
+
readonly assets_update: {
|
|
32
|
+
readonly method: "PATCH";
|
|
33
|
+
readonly path: "/v1/assets/{asset_id}";
|
|
34
|
+
};
|
|
35
35
|
readonly assets_upload: {
|
|
36
36
|
readonly method: "POST";
|
|
37
37
|
readonly path: "/v1/projects/{project_id}/assets";
|
|
@@ -252,6 +252,10 @@ export declare const OPERATIONS: {
|
|
|
252
252
|
readonly method: "PATCH";
|
|
253
253
|
readonly path: "/v1/records/{record_id}";
|
|
254
254
|
};
|
|
255
|
+
readonly revisions_get: {
|
|
256
|
+
readonly method: "GET";
|
|
257
|
+
readonly path: "/v1/revisions/{revision_id}";
|
|
258
|
+
};
|
|
255
259
|
readonly scheduled_changes_list: {
|
|
256
260
|
readonly method: "GET";
|
|
257
261
|
readonly path: "/v1/collections/{collection_id}/scheduled-changes";
|
|
@@ -343,10 +347,6 @@ export interface Operations {
|
|
|
343
347
|
data: T.AssetsGetData;
|
|
344
348
|
response: T.AssetsGetResponse;
|
|
345
349
|
};
|
|
346
|
-
assets_image_url: {
|
|
347
|
-
data: T.AssetsImageUrlData;
|
|
348
|
-
response: T.AssetsImageUrlResponse;
|
|
349
|
-
};
|
|
350
350
|
assets_list: {
|
|
351
351
|
data: T.AssetsListData;
|
|
352
352
|
response: T.AssetsListResponse;
|
|
@@ -359,6 +359,10 @@ export interface Operations {
|
|
|
359
359
|
data: T.AssetsRestoreData;
|
|
360
360
|
response: T.AssetsRestoreResponse;
|
|
361
361
|
};
|
|
362
|
+
assets_update: {
|
|
363
|
+
data: T.AssetsUpdateData;
|
|
364
|
+
response: T.AssetsUpdateResponse;
|
|
365
|
+
};
|
|
362
366
|
assets_upload: {
|
|
363
367
|
data: T.AssetsUploadData;
|
|
364
368
|
response: T.AssetsUploadResponse;
|
|
@@ -579,6 +583,10 @@ export interface Operations {
|
|
|
579
583
|
data: T.RecordsUpdateData;
|
|
580
584
|
response: T.RecordsUpdateResponse;
|
|
581
585
|
};
|
|
586
|
+
revisions_get: {
|
|
587
|
+
data: T.RevisionsGetData;
|
|
588
|
+
response: T.RevisionsGetResponse;
|
|
589
|
+
};
|
|
582
590
|
scheduled_changes_list: {
|
|
583
591
|
data: T.ScheduledChangesListData;
|
|
584
592
|
response: T.ScheduledChangesListResponse;
|
|
@@ -3,10 +3,10 @@ export const OPERATIONS = {
|
|
|
3
3
|
assets_delete: { method: "DELETE", path: "/v1/assets/{asset_id}" },
|
|
4
4
|
assets_download_url: { method: "GET", path: "/v1/assets/{asset_id}/download-url" },
|
|
5
5
|
assets_get: { method: "GET", path: "/v1/assets/{asset_id}" },
|
|
6
|
-
assets_image_url: { method: "GET", path: "/v1/assets/{asset_id}/image-url" },
|
|
7
6
|
assets_list: { method: "GET", path: "/v1/projects/{project_id}/assets" },
|
|
8
7
|
assets_purge: { method: "POST", path: "/v1/assets/{asset_id}/purge" },
|
|
9
8
|
assets_restore: { method: "POST", path: "/v1/assets/{asset_id}/restore" },
|
|
9
|
+
assets_update: { method: "PATCH", path: "/v1/assets/{asset_id}" },
|
|
10
10
|
assets_upload: { method: "POST", path: "/v1/projects/{project_id}/assets" },
|
|
11
11
|
assets_usage: { method: "GET", path: "/v1/assets/{asset_id}/usage" },
|
|
12
12
|
audit_events_list: { method: "GET", path: "/v1/projects/{project_id}/audit-events" },
|
|
@@ -62,6 +62,7 @@ export const OPERATIONS = {
|
|
|
62
62
|
records_unpublish: { method: "DELETE", path: "/v1/records/{record_id}/publication" },
|
|
63
63
|
records_unschedule: { method: "DELETE", path: "/v1/records/{record_id}/schedule" },
|
|
64
64
|
records_update: { method: "PATCH", path: "/v1/records/{record_id}" },
|
|
65
|
+
revisions_get: { method: "GET", path: "/v1/revisions/{revision_id}" },
|
|
65
66
|
scheduled_changes_list: { method: "GET", path: "/v1/collections/{collection_id}/scheduled-changes" },
|
|
66
67
|
schema_changes_get: { method: "GET", path: "/v1/schema-changes/{schema_change_id}" },
|
|
67
68
|
schema_changes_list: { method: "GET", path: "/v1/collections/{collection_id}/schema-changes" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { Actor, ApiKeyScope, Asset, AssetEventData, AssetField, AssetFieldConfiguration, AssetFieldCreate, AssetList, AssetProperties, AssetUploadCreate, AssetUploadTarget, AssetUsage, AssetWithUpload, AuditEvent, AuditEventList, BooleanField, BooleanFieldConfiguration, BooleanFieldCreate, Change, Collection, CollectionCreate, CollectionList, CollectionUpdate, DateField, DateFieldConfiguration, DateFieldCreate, DecimalField, DecimalFieldConfiguration, DecimalFieldCreate, DownloadUrl, Draft, DraftCreate, DraftEventData, DraftList, DraftSchedule, DraftScheduleUpdate, EnumField, EnumFieldConfiguration, EnumFieldCreate, Error, ErrorDetail, ErrorType, FeatureFlags, Field, FieldAliasEventData, FieldConfiguration, FieldCreate, FieldCreateProperties, FieldDefinition, FieldList, FieldMigration, FieldMigrationCounts, FieldMigrationList, FieldMigrationPreview, FieldMigrationRequest, FieldOrder, FieldProperties, FieldType, FieldUpdate, Health,
|
|
1
|
+
export type { Actor, ApiKeyScope, Asset, AssetEventData, AssetField, AssetFieldConfiguration, AssetFieldCreate, AssetList, AssetProperties, AssetUpdate, AssetUploadCreate, AssetUploadTarget, AssetUsage, AssetWithUpload, AuditEvent, AuditEventList, BooleanField, BooleanFieldConfiguration, BooleanFieldCreate, Change, Collection, CollectionCreate, CollectionList, CollectionUpdate, DateField, DateFieldConfiguration, DateFieldCreate, DecimalField, DecimalFieldConfiguration, DecimalFieldCreate, DownloadUrl, Draft, DraftCreate, DraftEventData, DraftList, DraftSchedule, DraftScheduleUpdate, EnumField, EnumFieldConfiguration, EnumFieldCreate, Error, ErrorDetail, ErrorType, FeatureFlags, Field, FieldAliasEventData, FieldConfiguration, FieldCreate, FieldCreateProperties, FieldDefinition, FieldList, FieldMigration, FieldMigrationCounts, FieldMigrationList, FieldMigrationPreview, FieldMigrationRequest, FieldOrder, FieldProperties, FieldType, FieldUpdate, Health, IntegerField, IntegerFieldConfiguration, IntegerFieldCreate, JsonField, JsonFieldConfiguration, JsonFieldCreate, ListMeta, LongTextField, LongTextFieldConfiguration, LongTextFieldCreate, MergedDraft, NullableTimestamp, Principal, PublishedOnly, RecordBatch, RecordBatchRequest, RecordCount, RecordCreate, RecordData, RecordDiff, RecordEventData, RecordFilterValue, RecordList, RecordPublication, RecordRevision, RecordRevisionDetail, RecordRevisionList, RecordRevisionOperation, RecordRevisionProperties, RecordSchedule, RecordScheduleUpdate, RecordWrite, RelationField, RelationFieldConfiguration, RelationFieldCreate, RequestId, RevertPreview, RichTextField, RichTextFieldConfiguration, RichTextFieldCreate, ScheduledChange, ScheduledChangeList, Schema, SchemaChange, SchemaChangeDetail, SchemaChangeList, SchemaChangeProperties, SchemaDefinition, SchemaEventData, SearchIndex, SearchResults, TextField, TextFieldConfiguration, TextFieldCreate, TimeFilter, Timestamp, Via, Webhook, WebhookCreate, WebhookDelivery, WebhookDeliveryDetail, WebhookDeliveryList, WebhookDeliveryProperties, WebhookEventPayload, WebhookEventType, WebhookList, WebhookProperties, WebhookSecret, WebhookSecretList, WebhookSecretProperties, WebhookSecretWithValue, WebhookSubscription, WebhookTestEventData, WebhookUpdate, WebhookWithSecret, } from "./types.gen.ts";
|
|
@@ -574,11 +574,15 @@ export type Collection = {
|
|
|
574
574
|
*/
|
|
575
575
|
purge_after: NullableTimestamp;
|
|
576
576
|
/**
|
|
577
|
-
* Whether
|
|
578
|
-
*
|
|
577
|
+
* Whether the project's search tokens (made in the web app) find
|
|
578
|
+
* its published records, from a browser or a backend. Off by
|
|
579
|
+
* default: every field of those records becomes readable by anyone
|
|
580
|
+
* with a token, so turn it on only for collections whose published
|
|
581
|
+
* records are public. A change reaches search tokens within
|
|
582
|
+
* seconds.
|
|
579
583
|
*
|
|
580
584
|
*/
|
|
581
|
-
|
|
585
|
+
public_search: boolean;
|
|
582
586
|
/**
|
|
583
587
|
* Active fields in position order.
|
|
584
588
|
*/
|
|
@@ -587,17 +591,17 @@ export type Collection = {
|
|
|
587
591
|
updated_at: Timestamp;
|
|
588
592
|
};
|
|
589
593
|
export type CollectionCreate = {
|
|
590
|
-
search_enabled?: boolean;
|
|
591
594
|
name: string;
|
|
592
595
|
slug: string;
|
|
593
596
|
description?: string | null;
|
|
597
|
+
public_search?: boolean;
|
|
594
598
|
fields?: Array<FieldCreate>;
|
|
595
599
|
};
|
|
596
600
|
export type CollectionUpdate = {
|
|
597
|
-
search_enabled?: boolean;
|
|
598
601
|
name?: string;
|
|
599
602
|
slug?: string;
|
|
600
603
|
description?: string | null;
|
|
604
|
+
public_search?: boolean;
|
|
601
605
|
};
|
|
602
606
|
export type CollectionList = {
|
|
603
607
|
data: Array<Collection>;
|
|
@@ -612,7 +616,10 @@ export type SchemaDefinition = {
|
|
|
612
616
|
slug: string;
|
|
613
617
|
description: string | null;
|
|
614
618
|
deleted_at: NullableTimestamp;
|
|
615
|
-
|
|
619
|
+
/**
|
|
620
|
+
* Absent from schemas before the setting existed (off).
|
|
621
|
+
*/
|
|
622
|
+
public_search?: boolean;
|
|
616
623
|
fields: Array<{
|
|
617
624
|
id: string;
|
|
618
625
|
name: string;
|
|
@@ -876,7 +883,7 @@ export type TimeFilter = {
|
|
|
876
883
|
/**
|
|
877
884
|
* The client a change came through; `scheduler` for scheduled changes.
|
|
878
885
|
*/
|
|
879
|
-
export type Via = 'ui' | 'api' | 'cli' | 'sdk' | 'system' | 'scheduler';
|
|
886
|
+
export type Via = 'ui' | 'api' | 'cli' | 'sdk' | 'mcp' | 'system' | 'scheduler';
|
|
880
887
|
/**
|
|
881
888
|
* Changes to a record's content that wait until they are merged into
|
|
882
889
|
* it, now or at `schedule.merge_at`. Content only: whether the record
|
|
@@ -1022,6 +1029,16 @@ export type Record = {
|
|
|
1022
1029
|
export type RecordWrite = {
|
|
1023
1030
|
data: RecordData;
|
|
1024
1031
|
};
|
|
1032
|
+
export type RecordCreate = {
|
|
1033
|
+
data: RecordData;
|
|
1034
|
+
/**
|
|
1035
|
+
* The key of a `unique` field (a slug, or a field with `unique` on)
|
|
1036
|
+
* whose value `data` includes: update the record that has it, or
|
|
1037
|
+
* create one.
|
|
1038
|
+
*
|
|
1039
|
+
*/
|
|
1040
|
+
upsert_on?: string;
|
|
1041
|
+
};
|
|
1025
1042
|
export type RecordList = {
|
|
1026
1043
|
data: Array<Record>;
|
|
1027
1044
|
meta: ListMeta;
|
|
@@ -1140,9 +1157,11 @@ export type SearchIndex = {
|
|
|
1140
1157
|
object: 'search_index';
|
|
1141
1158
|
collection_id: string;
|
|
1142
1159
|
/**
|
|
1143
|
-
* The
|
|
1160
|
+
* The index's name in the search engine, which search tokens search
|
|
1161
|
+
* (`indexUid` in Meilisearch's search API). Opaque; it never changes.
|
|
1162
|
+
*
|
|
1144
1163
|
*/
|
|
1145
|
-
|
|
1164
|
+
index: string;
|
|
1146
1165
|
/**
|
|
1147
1166
|
* `building` until first built; `stale` from the change that queues a rebuild until it has run; `failed` if the last rebuild failed (it is retried).
|
|
1148
1167
|
*/
|
|
@@ -1157,7 +1176,7 @@ export type SearchIndex = {
|
|
|
1157
1176
|
* (`record.*`, `draft.*`, `collection.*`, `field.*`, `asset.*`) or `*` for all.
|
|
1158
1177
|
*
|
|
1159
1178
|
*/
|
|
1160
|
-
export type WebhookEventType = 'record.created' | 'record.updated' | 'record.published' | 'record.unpublished' | 'record.deleted' | 'record.restored' | 'record.reverted' | 'record.redacted' | 'record.scheduled' | 'record.unscheduled' | 'record.schedule_failed' | 'draft.created' | 'draft.updated' | 'draft.discarded' | 'draft.scheduled' | 'draft.unscheduled' | 'draft.schedule_failed' | 'collection.created' | 'collection.updated' | 'collection.deleted' | 'collection.restored' | 'collection.fields_reordered' | 'field.created' | 'field.updated' | 'field.deleted' | 'field.restored' | 'field.migrated' | 'field.alias_removed' | 'asset.created' | 'asset.deleted' | 'asset.restored' | 'asset.purged';
|
|
1179
|
+
export type WebhookEventType = 'record.created' | 'record.updated' | 'record.published' | 'record.unpublished' | 'record.deleted' | 'record.restored' | 'record.reverted' | 'record.redacted' | 'record.scheduled' | 'record.unscheduled' | 'record.schedule_failed' | 'draft.created' | 'draft.updated' | 'draft.discarded' | 'draft.scheduled' | 'draft.unscheduled' | 'draft.schedule_failed' | 'collection.created' | 'collection.updated' | 'collection.deleted' | 'collection.restored' | 'collection.fields_reordered' | 'field.created' | 'field.updated' | 'field.deleted' | 'field.restored' | 'field.migrated' | 'field.alias_removed' | 'asset.created' | 'asset.updated' | 'asset.deleted' | 'asset.restored' | 'asset.purged';
|
|
1161
1180
|
export type WebhookSubscription = WebhookEventType | 'record.*' | 'draft.*' | 'collection.*' | 'field.*' | 'asset.*' | '*';
|
|
1162
1181
|
export type Webhook = WebhookProperties;
|
|
1163
1182
|
export type WebhookProperties = {
|
|
@@ -1461,14 +1480,28 @@ export type WebhookTestEventData = {
|
|
|
1461
1480
|
webhook: null | Webhook;
|
|
1462
1481
|
};
|
|
1463
1482
|
export type Asset = AssetProperties;
|
|
1483
|
+
export type AssetUpdate = {
|
|
1484
|
+
/**
|
|
1485
|
+
* Control characters are removed and path separators become `_`, as on upload.
|
|
1486
|
+
*/
|
|
1487
|
+
filename?: string;
|
|
1488
|
+
/**
|
|
1489
|
+
* Surrounding whitespace is removed; empty or null clears it.
|
|
1490
|
+
*/
|
|
1491
|
+
alt?: string | null;
|
|
1492
|
+
};
|
|
1464
1493
|
export type AssetProperties = {
|
|
1465
1494
|
id: string;
|
|
1466
1495
|
object: 'asset';
|
|
1467
1496
|
project_id: string;
|
|
1468
1497
|
/**
|
|
1469
|
-
* The
|
|
1498
|
+
* The filename, any Unicode, as uploaded unless renamed since. Downloads use it.
|
|
1470
1499
|
*/
|
|
1471
1500
|
filename: string;
|
|
1501
|
+
/**
|
|
1502
|
+
* Alternative text, saying what an image shows; null until set. The default wherever the asset is used.
|
|
1503
|
+
*/
|
|
1504
|
+
alt: string | null;
|
|
1472
1505
|
content_type: string;
|
|
1473
1506
|
byte_size: number;
|
|
1474
1507
|
/**
|
|
@@ -1489,7 +1522,20 @@ export type AssetProperties = {
|
|
|
1489
1522
|
*/
|
|
1490
1523
|
purge_after: NullableTimestamp;
|
|
1491
1524
|
/**
|
|
1492
|
-
*
|
|
1525
|
+
* The URL of the whole image, for ready images (JPEG, PNG, GIF, WebP
|
|
1526
|
+
* or AVIF), deleted ones included until they are purged; null
|
|
1527
|
+
* otherwise. Image URLs are open and never expire. For a rendition,
|
|
1528
|
+
* write [imgproxy processing options](https://docs.imgproxy.net/usage/processing)
|
|
1529
|
+
* before `/plain/`, and a format after `@`: for example
|
|
1530
|
+
* `https://images.nohead.io/rs:fill:800:600/g:sm/plain/…@webp`. Renditions
|
|
1531
|
+
* are at most 4096 pixels a side, from originals of at most 50
|
|
1532
|
+
* megapixels. Options that would return the file as stored (`raw`,
|
|
1533
|
+
* `skip_processing`, `strip_metadata`) are refused.
|
|
1534
|
+
*
|
|
1535
|
+
*/
|
|
1536
|
+
image_url: string | null;
|
|
1537
|
+
/**
|
|
1538
|
+
* The URL of a small rendition (fits in 640×640, WebP), for ready images, deleted ones included until they are purged; null otherwise.
|
|
1493
1539
|
*/
|
|
1494
1540
|
preview_url: string | null;
|
|
1495
1541
|
uploaded_at: NullableTimestamp;
|
|
@@ -1500,16 +1546,6 @@ export type AssetList = {
|
|
|
1500
1546
|
data: Array<Asset>;
|
|
1501
1547
|
meta: ListMeta;
|
|
1502
1548
|
};
|
|
1503
|
-
export type ImageUrl = {
|
|
1504
|
-
object: 'image_url';
|
|
1505
|
-
asset_id: string;
|
|
1506
|
-
url: string;
|
|
1507
|
-
width: number | null;
|
|
1508
|
-
height: number | null;
|
|
1509
|
-
fit: 'contain' | 'cover' | 'fill';
|
|
1510
|
-
format: 'original' | 'webp' | 'avif' | 'jpeg' | 'png';
|
|
1511
|
-
quality: number | null;
|
|
1512
|
-
};
|
|
1513
1549
|
export type AssetUsage = {
|
|
1514
1550
|
object: 'asset_usage';
|
|
1515
1551
|
asset_id: string;
|
|
@@ -1632,6 +1668,7 @@ export type WebhookId = string;
|
|
|
1632
1668
|
export type DeliveryId = string;
|
|
1633
1669
|
export type RecordId = string;
|
|
1634
1670
|
export type DraftId = string;
|
|
1671
|
+
export type RevisionId = string;
|
|
1635
1672
|
/**
|
|
1636
1673
|
* Per-record revision number.
|
|
1637
1674
|
*/
|
|
@@ -1861,7 +1898,7 @@ export type RecordsListResponses = {
|
|
|
1861
1898
|
};
|
|
1862
1899
|
export type RecordsListResponse = RecordsListResponses[keyof RecordsListResponses];
|
|
1863
1900
|
export type RecordsCreateData = {
|
|
1864
|
-
body:
|
|
1901
|
+
body: RecordCreate;
|
|
1865
1902
|
headers?: {
|
|
1866
1903
|
/**
|
|
1867
1904
|
* A unique value (1-255 printable ASCII characters) that makes retrying
|
|
@@ -1873,6 +1910,10 @@ export type RecordsCreateData = {
|
|
|
1873
1910
|
*
|
|
1874
1911
|
*/
|
|
1875
1912
|
'Idempotency-Key'?: string;
|
|
1913
|
+
/**
|
|
1914
|
+
* The revision you last read (the record's, or the draft's for a draft), e.g. `"7"`. Stale writes fail with 412.
|
|
1915
|
+
*/
|
|
1916
|
+
'If-Match'?: string;
|
|
1876
1917
|
/**
|
|
1877
1918
|
* First-party client identifier recorded in history (e.g. `cli/0.3.1`). Informational only.
|
|
1878
1919
|
*/
|
|
@@ -1924,6 +1965,12 @@ export type RecordsCreateErrors = {
|
|
|
1924
1965
|
* The request conflicts with current state.
|
|
1925
1966
|
*/
|
|
1926
1967
|
409: Error;
|
|
1968
|
+
/**
|
|
1969
|
+
* The resource changed since the revision given in `If-Match`. Nothing was
|
|
1970
|
+
* written; `details` includes the current revision.
|
|
1971
|
+
*
|
|
1972
|
+
*/
|
|
1973
|
+
412: Error;
|
|
1927
1974
|
/**
|
|
1928
1975
|
* The request failed validation.
|
|
1929
1976
|
*/
|
|
@@ -1939,6 +1986,10 @@ export type RecordsCreateErrors = {
|
|
|
1939
1986
|
};
|
|
1940
1987
|
export type RecordsCreateError = RecordsCreateErrors[keyof RecordsCreateErrors];
|
|
1941
1988
|
export type RecordsCreateResponses = {
|
|
1989
|
+
/**
|
|
1990
|
+
* The record.
|
|
1991
|
+
*/
|
|
1992
|
+
200: Record;
|
|
1942
1993
|
/**
|
|
1943
1994
|
* The created record.
|
|
1944
1995
|
*/
|
|
@@ -2942,6 +2993,48 @@ export type RecordRevisionsGetResponses = {
|
|
|
2942
2993
|
200: RecordRevisionDetail;
|
|
2943
2994
|
};
|
|
2944
2995
|
export type RecordRevisionsGetResponse = RecordRevisionsGetResponses[keyof RecordRevisionsGetResponses];
|
|
2996
|
+
export type RevisionsGetData = {
|
|
2997
|
+
body?: never;
|
|
2998
|
+
path: {
|
|
2999
|
+
revision_id: string;
|
|
3000
|
+
};
|
|
3001
|
+
query?: never;
|
|
3002
|
+
url: '/v1/revisions/{revision_id}';
|
|
3003
|
+
};
|
|
3004
|
+
export type RevisionsGetErrors = {
|
|
3005
|
+
/**
|
|
3006
|
+
* The request was malformed: unparseable JSON, an invalid query parameter, or a body key the operation doesn't take (detail code `unknown_parameter`, naming the key).
|
|
3007
|
+
*/
|
|
3008
|
+
400: Error;
|
|
3009
|
+
/**
|
|
3010
|
+
* Authentication is missing or invalid.
|
|
3011
|
+
*/
|
|
3012
|
+
401: Error;
|
|
3013
|
+
/**
|
|
3014
|
+
* The caller is not allowed to perform this action.
|
|
3015
|
+
*/
|
|
3016
|
+
403: Error;
|
|
3017
|
+
/**
|
|
3018
|
+
* The resource does not exist or is not visible to the caller.
|
|
3019
|
+
*/
|
|
3020
|
+
404: Error;
|
|
3021
|
+
/**
|
|
3022
|
+
* Too many requests for this API key or user (or, with failing
|
|
3023
|
+
* credentials, this IP address). A published-only key is counted per
|
|
3024
|
+
* client IP. Wait `Retry-After` seconds; retries with the same `Idempotency-Key`
|
|
3025
|
+
* are safe.
|
|
3026
|
+
*
|
|
3027
|
+
*/
|
|
3028
|
+
429: Error;
|
|
3029
|
+
};
|
|
3030
|
+
export type RevisionsGetError = RevisionsGetErrors[keyof RevisionsGetErrors];
|
|
3031
|
+
export type RevisionsGetResponses = {
|
|
3032
|
+
/**
|
|
3033
|
+
* The revision with its snapshot and changes.
|
|
3034
|
+
*/
|
|
3035
|
+
200: RecordRevisionDetail;
|
|
3036
|
+
};
|
|
3037
|
+
export type RevisionsGetResponse = RevisionsGetResponses[keyof RevisionsGetResponses];
|
|
2945
3038
|
export type RecordRevisionsRevertData = {
|
|
2946
3039
|
body?: never;
|
|
2947
3040
|
headers?: {
|
|
@@ -5379,24 +5472,31 @@ export type AssetsGetResponses = {
|
|
|
5379
5472
|
200: Asset;
|
|
5380
5473
|
};
|
|
5381
5474
|
export type AssetsGetResponse = AssetsGetResponses[keyof AssetsGetResponses];
|
|
5382
|
-
export type
|
|
5383
|
-
body
|
|
5384
|
-
|
|
5385
|
-
asset_id: string;
|
|
5386
|
-
};
|
|
5387
|
-
query?: {
|
|
5388
|
-
width?: number;
|
|
5389
|
-
height?: number;
|
|
5475
|
+
export type AssetsUpdateData = {
|
|
5476
|
+
body: AssetUpdate;
|
|
5477
|
+
headers?: {
|
|
5390
5478
|
/**
|
|
5391
|
-
*
|
|
5479
|
+
* A unique value (1-255 printable ASCII characters) that makes retrying
|
|
5480
|
+
* this request safe. The first response (below 500) is stored for 24
|
|
5481
|
+
* hours per user or API key; retries with the same key and the same
|
|
5482
|
+
* request get it again with an `Idempotent-Replayed: true` header. The
|
|
5483
|
+
* same key with a different request is refused with `400`; a retry while
|
|
5484
|
+
* the first request is still running gets `409`.
|
|
5485
|
+
*
|
|
5486
|
+
*/
|
|
5487
|
+
'Idempotency-Key'?: string;
|
|
5488
|
+
/**
|
|
5489
|
+
* First-party client identifier recorded in history (e.g. `cli/0.3.1`). Informational only.
|
|
5392
5490
|
*/
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5491
|
+
'Nohead-Client'?: string;
|
|
5492
|
+
};
|
|
5493
|
+
path: {
|
|
5494
|
+
asset_id: string;
|
|
5396
5495
|
};
|
|
5397
|
-
|
|
5496
|
+
query?: never;
|
|
5497
|
+
url: '/v1/assets/{asset_id}';
|
|
5398
5498
|
};
|
|
5399
|
-
export type
|
|
5499
|
+
export type AssetsUpdateErrors = {
|
|
5400
5500
|
/**
|
|
5401
5501
|
* The request was malformed: unparseable JSON, an invalid query parameter, or a body key the operation doesn't take (detail code `unknown_parameter`, naming the key).
|
|
5402
5502
|
*/
|
|
@@ -5429,19 +5529,15 @@ export type AssetsImageUrlErrors = {
|
|
|
5429
5529
|
*
|
|
5430
5530
|
*/
|
|
5431
5531
|
429: Error;
|
|
5432
|
-
/**
|
|
5433
|
-
* The service is temporarily unavailable.
|
|
5434
|
-
*/
|
|
5435
|
-
503: Error;
|
|
5436
5532
|
};
|
|
5437
|
-
export type
|
|
5438
|
-
export type
|
|
5533
|
+
export type AssetsUpdateError = AssetsUpdateErrors[keyof AssetsUpdateErrors];
|
|
5534
|
+
export type AssetsUpdateResponses = {
|
|
5439
5535
|
/**
|
|
5440
|
-
* The
|
|
5536
|
+
* The asset.
|
|
5441
5537
|
*/
|
|
5442
|
-
200:
|
|
5538
|
+
200: Asset;
|
|
5443
5539
|
};
|
|
5444
|
-
export type
|
|
5540
|
+
export type AssetsUpdateResponse = AssetsUpdateResponses[keyof AssetsUpdateResponses];
|
|
5445
5541
|
export type AssetsDownloadUrlData = {
|
|
5446
5542
|
body?: never;
|
|
5447
5543
|
path: {
|
package/dist/images.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image renditions without a request (`@nohead/sdk/images`). Image URLs are
|
|
3
|
+
* open: an image asset's `image_url` serves the whole image, and any of
|
|
4
|
+
* imgproxy's processing options written into it transform it
|
|
5
|
+
* (https://docs.imgproxy.net/usage/processing). No dependencies, so it suits
|
|
6
|
+
* browser bundles and frameworks' image components.
|
|
7
|
+
*
|
|
8
|
+
* imageUrl(asset, { width: 800, height: 600, fit: "cover", format: "webp" })
|
|
9
|
+
*/
|
|
10
|
+
export interface ImageOptions {
|
|
11
|
+
width?: number;
|
|
12
|
+
height?: number;
|
|
13
|
+
/** `contain` fits inside the box (the default), `cover` fills it, cropping, `fill` stretches to it. */
|
|
14
|
+
fit?: "contain" | "cover" | "fill";
|
|
15
|
+
format?: "webp" | "avif" | "jpeg" | "png";
|
|
16
|
+
/** 1 to 100. */
|
|
17
|
+
quality?: number;
|
|
18
|
+
/** Pixel density: 2 for a 2x screen. */
|
|
19
|
+
dpr?: number;
|
|
20
|
+
/** What a crop keeps, as imgproxy's gravity: `sm` (smart), `ce`, `no`, or `fp:0.5:0.3` (a focal point). */
|
|
21
|
+
gravity?: string;
|
|
22
|
+
/** Any other processing options, as written in a URL: `["bl:2", "sh:0.5"]`. */
|
|
23
|
+
options?: string[];
|
|
24
|
+
}
|
|
25
|
+
/** An image asset, or its `image_url`. */
|
|
26
|
+
export type ImageSource = string | {
|
|
27
|
+
image_url: string | null;
|
|
28
|
+
};
|
|
29
|
+
/** A rendition of an image: its `image_url` with these options. */
|
|
30
|
+
export declare function imageUrl(image: ImageSource, options?: ImageOptions): string;
|
|
31
|
+
/** Whether a URL is a Nohead image's: the loaders leave any other alone. */
|
|
32
|
+
export declare function isImageUrl(src: unknown): src is string;
|
|
33
|
+
/**
|
|
34
|
+
* A Next.js image loader. In a file named by `images.loaderFile` in
|
|
35
|
+
* next.config: `export { nextImageLoader as default } from "@nohead/sdk/images"`,
|
|
36
|
+
* then `<Image src={asset.image_url} width={…} height={…} alt={asset.alt} />`.
|
|
37
|
+
* Other images (the site's own) are left as they are.
|
|
38
|
+
*/
|
|
39
|
+
export declare function nextImageLoader({ src, width, quality, }: {
|
|
40
|
+
src: string;
|
|
41
|
+
width: number;
|
|
42
|
+
quality?: number;
|
|
43
|
+
}): string;
|
|
44
|
+
/**
|
|
45
|
+
* An Astro image service (an external one: Astro never fetches the image).
|
|
46
|
+
* In a module named by `image.service.entrypoint` in astro.config:
|
|
47
|
+
* `export { astroImageService as default } from "@nohead/sdk/images"`.
|
|
48
|
+
* Other images (the site's own, imported or remote) are served as they are.
|
|
49
|
+
*/
|
|
50
|
+
export declare const astroImageService: {
|
|
51
|
+
getURL(options: {
|
|
52
|
+
src: unknown;
|
|
53
|
+
width?: number;
|
|
54
|
+
height?: number;
|
|
55
|
+
format?: string;
|
|
56
|
+
quality?: number | string;
|
|
57
|
+
fit?: string;
|
|
58
|
+
}): string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Nuxt Image's custom provider (`getImage`). In a file named as a provider
|
|
62
|
+
* in nuxt.config's `image.providers`: on Nuxt Image 2,
|
|
63
|
+
* `export { nuxtImageProvider as default } from "@nohead/sdk/images"`; on
|
|
64
|
+
* Nuxt Image 1, `export { getImage } from "@nohead/sdk/images"`. Other
|
|
65
|
+
* images are left as they are.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getImage(src: string, { modifiers }?: {
|
|
68
|
+
modifiers?: Record<string, unknown>;
|
|
69
|
+
}): {
|
|
70
|
+
url: string;
|
|
71
|
+
};
|
|
72
|
+
/** Nuxt Image 2's provider: what its `defineProvider({ getImage })` returns. */
|
|
73
|
+
export declare const nuxtImageProvider: () => {
|
|
74
|
+
getImage: typeof getImage;
|
|
75
|
+
};
|
package/dist/images.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image renditions without a request (`@nohead/sdk/images`). Image URLs are
|
|
3
|
+
* open: an image asset's `image_url` serves the whole image, and any of
|
|
4
|
+
* imgproxy's processing options written into it transform it
|
|
5
|
+
* (https://docs.imgproxy.net/usage/processing). No dependencies, so it suits
|
|
6
|
+
* browser bundles and frameworks' image components.
|
|
7
|
+
*
|
|
8
|
+
* imageUrl(asset, { width: 800, height: 600, fit: "cover", format: "webp" })
|
|
9
|
+
*/
|
|
10
|
+
const FITS = { contain: "fit", cover: "fill", fill: "force" };
|
|
11
|
+
/** A rendition of an image: its `image_url` with these options. */
|
|
12
|
+
export function imageUrl(image, options = {}) {
|
|
13
|
+
const base = typeof image === "string" ? image : image.image_url;
|
|
14
|
+
if (!base)
|
|
15
|
+
throw new TypeError("Not a ready image: it has no image_url");
|
|
16
|
+
const at = base.indexOf("/plain/");
|
|
17
|
+
if (at < 0)
|
|
18
|
+
throw new TypeError(`Not a Nohead image URL: ${base}`);
|
|
19
|
+
const { width, height, fit = "contain", format, quality, dpr, gravity, } = options;
|
|
20
|
+
for (const option of [gravity, ...(options.options ?? [])])
|
|
21
|
+
if (option && /[/@?#]/.test(option))
|
|
22
|
+
throw new TypeError(`Not an imgproxy option: ${option}`);
|
|
23
|
+
const segments = [];
|
|
24
|
+
if (width || height)
|
|
25
|
+
segments.push(`rs:${FITS[fit]}:${width ?? 0}:${height ?? 0}`);
|
|
26
|
+
if (gravity)
|
|
27
|
+
segments.push(`g:${gravity}`);
|
|
28
|
+
if (dpr)
|
|
29
|
+
segments.push(`dpr:${dpr}`);
|
|
30
|
+
if (quality)
|
|
31
|
+
segments.push(`q:${quality}`);
|
|
32
|
+
segments.push(...(options.options ?? []));
|
|
33
|
+
// The source comes last; a format replaces any the URL already names.
|
|
34
|
+
let source = base.slice(at);
|
|
35
|
+
if (format)
|
|
36
|
+
source = `${source.replace(/@[a-z]+$/, "")}@${format}`;
|
|
37
|
+
return `${base.slice(0, at)}${segments.map((s) => `/${s}`).join("")}${source}`;
|
|
38
|
+
}
|
|
39
|
+
/** Whether a URL is a Nohead image's: the loaders leave any other alone. */
|
|
40
|
+
export function isImageUrl(src) {
|
|
41
|
+
return (typeof src === "string" && /^https?:\/\/[^/]+\/(.*\/)?plain\//.test(src));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A Next.js image loader. In a file named by `images.loaderFile` in
|
|
45
|
+
* next.config: `export { nextImageLoader as default } from "@nohead/sdk/images"`,
|
|
46
|
+
* then `<Image src={asset.image_url} width={…} height={…} alt={asset.alt} />`.
|
|
47
|
+
* Other images (the site's own) are left as they are.
|
|
48
|
+
*/
|
|
49
|
+
export function nextImageLoader({ src, width, quality, }) {
|
|
50
|
+
return isImageUrl(src) ? imageUrl(src, { width, quality }) : src;
|
|
51
|
+
}
|
|
52
|
+
const FORMATS = new Set(["webp", "avif", "jpeg", "png"]);
|
|
53
|
+
// Astro's and Nuxt Image's fits, as imgproxy has them.
|
|
54
|
+
const FRAMEWORK_FITS = {
|
|
55
|
+
cover: "cover",
|
|
56
|
+
contain: "contain",
|
|
57
|
+
fill: "fill",
|
|
58
|
+
inside: "contain",
|
|
59
|
+
outside: "cover",
|
|
60
|
+
};
|
|
61
|
+
const fitOf = (fit) => typeof fit === "string" ? FRAMEWORK_FITS[fit] : undefined;
|
|
62
|
+
const formatOf = (format) => typeof format === "string" && FORMATS.has(format)
|
|
63
|
+
? format
|
|
64
|
+
: undefined;
|
|
65
|
+
/**
|
|
66
|
+
* An Astro image service (an external one: Astro never fetches the image).
|
|
67
|
+
* In a module named by `image.service.entrypoint` in astro.config:
|
|
68
|
+
* `export { astroImageService as default } from "@nohead/sdk/images"`.
|
|
69
|
+
* Other images (the site's own, imported or remote) are served as they are.
|
|
70
|
+
*/
|
|
71
|
+
export const astroImageService = {
|
|
72
|
+
getURL(options) {
|
|
73
|
+
const { src } = options;
|
|
74
|
+
if (!isImageUrl(src)) {
|
|
75
|
+
const own = typeof src === "string" ? src : src?.src;
|
|
76
|
+
return typeof own === "string" ? own : "";
|
|
77
|
+
}
|
|
78
|
+
return imageUrl(src, {
|
|
79
|
+
width: options.width,
|
|
80
|
+
height: options.height,
|
|
81
|
+
fit: fitOf(options.fit),
|
|
82
|
+
format: formatOf(options.format),
|
|
83
|
+
quality: typeof options.quality === "number" ? options.quality : undefined,
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Nuxt Image's custom provider (`getImage`). In a file named as a provider
|
|
89
|
+
* in nuxt.config's `image.providers`: on Nuxt Image 2,
|
|
90
|
+
* `export { nuxtImageProvider as default } from "@nohead/sdk/images"`; on
|
|
91
|
+
* Nuxt Image 1, `export { getImage } from "@nohead/sdk/images"`. Other
|
|
92
|
+
* images are left as they are.
|
|
93
|
+
*/
|
|
94
|
+
export function getImage(src, { modifiers = {} } = {}) {
|
|
95
|
+
const number = (value) => typeof value === "number"
|
|
96
|
+
? value
|
|
97
|
+
: typeof value === "string" && value
|
|
98
|
+
? Number(value)
|
|
99
|
+
: undefined;
|
|
100
|
+
if (!isImageUrl(src))
|
|
101
|
+
return { url: src };
|
|
102
|
+
return {
|
|
103
|
+
url: imageUrl(src, {
|
|
104
|
+
width: number(modifiers.width),
|
|
105
|
+
height: number(modifiers.height),
|
|
106
|
+
fit: fitOf(modifiers.fit),
|
|
107
|
+
format: formatOf(modifiers.format),
|
|
108
|
+
quality: number(modifiers.quality),
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/** Nuxt Image 2's provider: what its `defineProvider({ getImage })` returns. */
|
|
113
|
+
export const nuxtImageProvider = () => ({ getImage });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { APIPromise, PagePromise } from "../api-promise.ts";
|
|
2
2
|
import type { RequestOptions } from "../core.ts";
|
|
3
|
-
import type { Asset, AssetUploadCreate, AssetWithUpload, AssetUsage, DownloadUrl
|
|
4
|
-
import type { AssetListParams
|
|
3
|
+
import type { Asset, AssetUpdate, AssetUploadCreate, AssetWithUpload, AssetUsage, DownloadUrl } from "../generated/types.gen.ts";
|
|
4
|
+
import type { AssetListParams } from "../types.ts";
|
|
5
5
|
import { Resource } from "./resource.ts";
|
|
6
6
|
/** What `assets.upload` accepts. A stream needs `byte_size`. */
|
|
7
7
|
export type Uploadable = Blob | ArrayBuffer | Uint8Array | ReadableStream;
|
|
@@ -40,6 +40,13 @@ export declare class Assets extends Resource {
|
|
|
40
40
|
complete(asset: string, options?: RequestOptions): APIPromise<Asset>;
|
|
41
41
|
list({ content_type, ...params }?: AssetListParams, options?: RequestOptions): PagePromise<Asset>;
|
|
42
42
|
get(asset: string, options?: RequestOptions): APIPromise<Asset>;
|
|
43
|
+
/**
|
|
44
|
+
* Renames the asset (`filename`) or sets its `alt` text (`null` or `""`
|
|
45
|
+
* clears it). The file itself can't change: upload a new asset for that.
|
|
46
|
+
* `alt` is the default wherever the asset is used. A deleted asset is a
|
|
47
|
+
* `ConflictError`: restore it first.
|
|
48
|
+
*/
|
|
49
|
+
update(asset: string, params: AssetUpdate, options?: RequestOptions): APIPromise<Asset>;
|
|
43
50
|
/**
|
|
44
51
|
* Soft-deletes the asset: `restore` brings it back until its
|
|
45
52
|
* `purge_after`, when the file is purged (or now, with `purge`).
|
|
@@ -60,8 +67,6 @@ export declare class Assets extends Resource {
|
|
|
60
67
|
* updated with the fields that use it (`uses`). Needs `records:read` too.
|
|
61
68
|
*/
|
|
62
69
|
usage(asset: string, options?: RequestOptions): APIPromise<AssetUsage>;
|
|
63
|
-
/** A
|
|
64
|
-
imageUrl(asset: string, params?: ImageUrlParams, options?: RequestOptions): APIPromise<ImageUrl>;
|
|
65
|
-
/** A 15-minute link to download the original file (`url`). */
|
|
70
|
+
/** A link to download the original file (`url`), valid for 2 minutes. */
|
|
66
71
|
downloadUrl(asset: string, options?: RequestOptions): APIPromise<DownloadUrl>;
|
|
67
72
|
}
|
package/dist/resources/assets.js
CHANGED
|
@@ -87,6 +87,15 @@ export class Assets extends Resource {
|
|
|
87
87
|
get(asset, options) {
|
|
88
88
|
return this.core.request("assets_get", { path: { asset_id: asset } }, options);
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Renames the asset (`filename`) or sets its `alt` text (`null` or `""`
|
|
92
|
+
* clears it). The file itself can't change: upload a new asset for that.
|
|
93
|
+
* `alt` is the default wherever the asset is used. A deleted asset is a
|
|
94
|
+
* `ConflictError`: restore it first.
|
|
95
|
+
*/
|
|
96
|
+
update(asset, params, options) {
|
|
97
|
+
return this.core.request("assets_update", { path: { asset_id: asset }, body: params }, options);
|
|
98
|
+
}
|
|
90
99
|
/**
|
|
91
100
|
* Soft-deletes the asset: `restore` brings it back until its
|
|
92
101
|
* `purge_after`, when the file is purged (or now, with `purge`).
|
|
@@ -115,11 +124,7 @@ export class Assets extends Resource {
|
|
|
115
124
|
usage(asset, options) {
|
|
116
125
|
return this.core.request("assets_usage", { path: { asset_id: asset } }, options);
|
|
117
126
|
}
|
|
118
|
-
/** A
|
|
119
|
-
imageUrl(asset, params = {}, options) {
|
|
120
|
-
return this.core.request("assets_image_url", { path: { asset_id: asset }, query: params }, options);
|
|
121
|
-
}
|
|
122
|
-
/** A 15-minute link to download the original file (`url`). */
|
|
127
|
+
/** A link to download the original file (`url`), valid for 2 minutes. */
|
|
123
128
|
downloadUrl(asset, options) {
|
|
124
129
|
return this.core.request("assets_download_url", { path: { asset_id: asset } }, options);
|
|
125
130
|
}
|
|
@@ -12,8 +12,12 @@ export declare class Records extends Resource {
|
|
|
12
12
|
/** A collection's records, newest first by default. */
|
|
13
13
|
list<D = RecordData>(collection: string, params?: RecordListParams, options?: RequestOptions): PagePromise<NoheadRecord<D>>;
|
|
14
14
|
get<D = RecordData>(record: string, params?: RecordGetParams, options?: RequestOptions): APIPromise<NoheadRecord<D>>;
|
|
15
|
-
/**
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Creates an unpublished record. With `upsert_on`, updates the record
|
|
17
|
+
* holding that unique value instead, if one exists, so a sync can run
|
|
18
|
+
* again without duplicates; `ifMatch` then applies to that update.
|
|
19
|
+
*/
|
|
20
|
+
create<D = RecordData>(collection: string, params: RecordCreateParams<D>, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
|
|
17
21
|
/** Sets the given fields (`null` clears one); others keep their values. */
|
|
18
22
|
update<D = RecordData>(record: string, params: RecordUpdateParams<D>, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
|
|
19
23
|
/**
|
|
@@ -63,7 +67,7 @@ export declare class Records extends Resource {
|
|
|
63
67
|
/** The changes between two revisions. */
|
|
64
68
|
diff(record: string, params: RecordDiffParams, options?: RequestOptions): APIPromise<RecordDiff>;
|
|
65
69
|
/**
|
|
66
|
-
* Full-text search in one collection
|
|
70
|
+
* Full-text search in one collection, matching its `searchable` fields.
|
|
67
71
|
* Pages through the first 1,000 hits, most relevant first.
|
|
68
72
|
*/
|
|
69
73
|
search<D = RecordData>(collection: string, query: string, params?: RecordSearchParams, options?: RequestOptions): PagePromise<NoheadRecord<D>, SearchMeta>;
|
|
@@ -79,3 +83,10 @@ export declare class Revisions extends Resource {
|
|
|
79
83
|
}, options?: ConditionalWriteOptions): APIPromise<RevertPreview>;
|
|
80
84
|
revert<D = RecordData>(record: string, revision: number, params?: DryRunParams, options?: ConditionalWriteOptions): APIPromise<NoheadRecord<D>>;
|
|
81
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* A revision by its own ID (`rev_…`), as webhooks and the activity log name
|
|
88
|
+
* it. Readable while its record is deleted.
|
|
89
|
+
*/
|
|
90
|
+
export declare class RevisionsById extends Resource {
|
|
91
|
+
get(revision: string, options?: RequestOptions): APIPromise<RecordRevisionDetail>;
|
|
92
|
+
}
|
|
@@ -12,7 +12,11 @@ export class Records extends Resource {
|
|
|
12
12
|
get(record, params = {}, options) {
|
|
13
13
|
return this.core.request("records_get", { path: { record_id: record }, query: params }, options);
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Creates an unpublished record. With `upsert_on`, updates the record
|
|
17
|
+
* holding that unique value instead, if one exists, so a sync can run
|
|
18
|
+
* again without duplicates; `ifMatch` then applies to that update.
|
|
19
|
+
*/
|
|
16
20
|
create(collection, params, options) {
|
|
17
21
|
return this.core.request("records_create", { path: { collection_id: collection }, body: params }, options);
|
|
18
22
|
}
|
|
@@ -93,7 +97,7 @@ export class Records extends Resource {
|
|
|
93
97
|
return this.core.request("records_diff", { path: { record_id: record }, query: params }, options);
|
|
94
98
|
}
|
|
95
99
|
/**
|
|
96
|
-
* Full-text search in one collection
|
|
100
|
+
* Full-text search in one collection, matching its `searchable` fields.
|
|
97
101
|
* Pages through the first 1,000 hits, most relevant first.
|
|
98
102
|
*/
|
|
99
103
|
search(collection, query, params = {}, options) {
|
|
@@ -113,3 +117,12 @@ export class Revisions extends Resource {
|
|
|
113
117
|
return this.core.request("record_revisions_revert", { path: { record_id: record, revision }, query: params }, options);
|
|
114
118
|
}
|
|
115
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* A revision by its own ID (`rev_…`), as webhooks and the activity log name
|
|
122
|
+
* it. Readable while its record is deleted.
|
|
123
|
+
*/
|
|
124
|
+
export class RevisionsById extends Resource {
|
|
125
|
+
get(revision, options) {
|
|
126
|
+
return this.core.request("revisions_get", { path: { revision_id: revision } }, options);
|
|
127
|
+
}
|
|
128
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -71,6 +71,11 @@ export interface RecordGetParams {
|
|
|
71
71
|
}
|
|
72
72
|
export interface RecordCreateParams<D = G.RecordData> {
|
|
73
73
|
data: D;
|
|
74
|
+
/**
|
|
75
|
+
* The key of a `unique` field whose value `data` includes: the active
|
|
76
|
+
* record holding that value is updated instead, if there is one.
|
|
77
|
+
*/
|
|
78
|
+
upsert_on?: string;
|
|
74
79
|
}
|
|
75
80
|
export interface RecordUpdateParams<D = G.RecordData> {
|
|
76
81
|
data: RecordDataUpdate<D>;
|
|
@@ -169,7 +174,6 @@ export interface FieldReorderParams {
|
|
|
169
174
|
/** Every active field of the collection, once each, in the new order. */
|
|
170
175
|
field_ids: string[];
|
|
171
176
|
}
|
|
172
|
-
export type ImageUrlParams = NonNullable<G.AssetsImageUrlData["query"]>;
|
|
173
177
|
export interface DeliveryListParams extends ListParams {
|
|
174
178
|
status?: "pending" | "succeeded" | "failed";
|
|
175
179
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.6.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.
|
|
1
|
+
export const VERSION = "0.6.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nohead/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Official TypeScript SDK for the Nohead API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://nohead.io",
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
"types": "./dist/webhooks.d.ts",
|
|
28
28
|
"default": "./dist/webhooks.js"
|
|
29
29
|
},
|
|
30
|
+
"./images": {
|
|
31
|
+
"types": "./dist/images.d.ts",
|
|
32
|
+
"default": "./dist/images.js"
|
|
33
|
+
},
|
|
30
34
|
"./package.json": "./package.json"
|
|
31
35
|
},
|
|
32
36
|
"files": [
|