nohead 0.5.0 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +22 -4
- data/lib/nohead/client.rb +4 -2
- data/lib/nohead/images.rb +64 -0
- data/lib/nohead/operations.rb +2 -1
- data/lib/nohead/resources/assets.rb +28 -12
- data/lib/nohead/resources/records.rb +18 -6
- data/lib/nohead/version.rb +1 -1
- data/lib/nohead.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b3361c68d640e8b2774b8e797bbf4108e19be21f0019600788d9f45e04457fe
|
|
4
|
+
data.tar.gz: d3c200b25b6afd1db440dced441f142da3d38b1731e34780356c373c2bc4b67c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 409ee914aaf232ce8f7109b4628f260f47f6b83861dceb48aebeaee661873c03f5ebef3ccbbd6e269504febad9325505a3b97a2f42905bb279e81d76aef70f18
|
|
7
|
+
data.tar.gz: 87b158ed9116745555538a9ef4297c584050251e69d0bab6101b823e239b3586262f161901f519973b1b07c4f2f2b76dfcd78ac86c55eedb905b208867d96d60
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@ Changes to the `nohead` gem 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.7.0
|
|
9
|
+
|
|
10
|
+
- `assets.list(q:, kind:)`: `q` finds assets whose filename or alt text has
|
|
11
|
+
every word, ignoring case; `kind` lists only `image`, `video`, `audio`,
|
|
12
|
+
`document` or `other` assets, or several kinds as an array.
|
|
13
|
+
|
|
14
|
+
## 0.6.0
|
|
15
|
+
|
|
16
|
+
- API keys now start `nohead_sk_`, or `nohead_pk_` for published-only keys;
|
|
17
|
+
keys in the old `sk_live_` format no longer work. The gem sends whatever key
|
|
18
|
+
it's given, so only the docs and examples change.
|
|
19
|
+
|
|
20
|
+
- `assets.update(asset, filename:, alt:)` renames an asset and sets its alt
|
|
21
|
+
text (`PATCH /v1/assets/{asset_id}`). Assets have `alt` (a string or
|
|
22
|
+
`nil`), and webhooks can subscribe to `asset.updated`.
|
|
23
|
+
|
|
24
|
+
- Image URLs are open. Assets have `image_url`, the whole image, and the new
|
|
25
|
+
`Nohead::Images.url` writes any of imgproxy's processing options into it,
|
|
26
|
+
without a request.
|
|
27
|
+
|
|
28
|
+
- **Breaking:** `assets.image_url` is gone, with the API's
|
|
29
|
+
`GET /v1/assets/{asset_id}/image-url`: use `Nohead::Images.url`, which
|
|
30
|
+
needs no request.
|
|
31
|
+
|
|
32
|
+
- **Breaking:** collections have no `search_enabled`, and search indexes no
|
|
33
|
+
`enabled`, and collections' `create` and `update` no longer take
|
|
34
|
+
`search_enabled:`: API keys search every collection they can read.
|
|
35
|
+
|
|
36
|
+
- `revisions.get(revision)` reads a revision by its own `rev_` ID, as
|
|
37
|
+
webhooks and the activity log name it (`GET /v1/revisions/{revision_id}`).
|
|
38
|
+
|
|
39
|
+
- `records.create` takes `upsert_on:`, a unique field's key: the record
|
|
40
|
+
holding that value is updated instead, if one exists, and `if_match:`
|
|
41
|
+
applies to that update.
|
|
42
|
+
|
|
43
|
+
- Collections have `public_search`: whether the project's search tokens find
|
|
44
|
+
their published records. Off by default;
|
|
45
|
+
`collections.create(public_search: ...)` and `collections.update` take it. A
|
|
46
|
+
collection's search index has `index`, the name a token searches it by.
|
|
47
|
+
|
|
8
48
|
## 0.5.0
|
|
9
49
|
|
|
10
50
|
- **Breaking:** field migrations are created under their collection:
|
data/README.md
CHANGED
|
@@ -52,7 +52,7 @@ nohead = Nohead::Client.new(
|
|
|
52
52
|
|
|
53
53
|
| Option | Default | |
|
|
54
54
|
|---|---|---|
|
|
55
|
-
| `api_key:` | `NOHEAD_API_KEY` | A project API key (`
|
|
55
|
+
| `api_key:` | `NOHEAD_API_KEY` | A project API key (`nohead_sk_...`, or `nohead_pk_...` when published-only). Required. |
|
|
56
56
|
| `base_url:` | `NOHEAD_API_URL`, else `https://api.nohead.io` | |
|
|
57
57
|
| `project_id:` | the key's project | Looked up once with `GET /v1/me` when omitted. |
|
|
58
58
|
| `max_retries:` | `2` | See [retries](#retries-and-idempotency). |
|
|
@@ -76,11 +76,14 @@ nohead.records.delete(post.id) # soft delete; records.restore undoes it
|
|
|
76
76
|
|
|
77
77
|
Methods return the API's resources (see [Results](#results)) and raise on failure. Field values are under `data`, keyed by field API key.
|
|
78
78
|
|
|
79
|
+
**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: `nohead.records.create("products", data: { sku: "TEE-01", title: "Tee" }, upsert_on: "sku")`.
|
|
80
|
+
|
|
79
81
|
**More:**
|
|
80
82
|
|
|
81
83
|
- `count`, and `bulk` (up to 100 records at once)
|
|
82
84
|
- `diff(record, from: 1, to: 2)`
|
|
83
85
|
- `revisions.list` (`filter:` `operation`, `actor_id` and a `created_at` range such as `{ gte: Time.utc(2026, 10, 1) }`), `revisions.get` and `revisions.revert` (with `dry_run: true` for a preview)
|
|
86
|
+
- a revision by its own ID, as webhooks and the activity log name it: `nohead.revisions.get("rev_...")`
|
|
84
87
|
|
|
85
88
|
## Drafts
|
|
86
89
|
|
|
@@ -195,9 +198,17 @@ end
|
|
|
195
198
|
asset = nohead.assets.upload("cover.jpg")
|
|
196
199
|
nohead.records.update(id, data: { cover: asset.id })
|
|
197
200
|
|
|
198
|
-
url = nohead.assets.image_url(asset.id, width: 1200, format: "webp").url
|
|
199
201
|
```
|
|
200
202
|
|
|
203
|
+
**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::Images.url` builds them without a request:
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
Nohead::Images.url(asset, width: 1200, height: 630, fit: "cover", gravity: "sm", format: "webp")
|
|
207
|
+
Nohead::Images.url(asset.image_url, width: 400, dpr: 2, options: ["bl:2"])
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Thumbnails: an image's `preview_url` fits in 640×640, as WebP.
|
|
211
|
+
|
|
201
212
|
**What `upload` accepts:** a path (String or Pathname), or an IO opened in binary mode. For bytes in memory, pass `StringIO.new(bytes)`.
|
|
202
213
|
|
|
203
214
|
**What it does:**
|
|
@@ -212,6 +223,12 @@ url = nohead.assets.image_url(asset.id, width: 1200, format: "webp").url
|
|
|
212
223
|
|
|
213
224
|
**Uploading from a browser:** create the upload on your server with `create_upload`, `PUT` the file from the browser, then `complete` it.
|
|
214
225
|
|
|
226
|
+
**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.
|
|
227
|
+
|
|
228
|
+
```ruby
|
|
229
|
+
nohead.assets.update(asset.id, alt: "The spring menu, on a chalkboard")
|
|
230
|
+
```
|
|
231
|
+
|
|
215
232
|
## Search
|
|
216
233
|
|
|
217
234
|
```ruby
|
|
@@ -223,7 +240,7 @@ results = nohead.search("content model", collections: %w[posts pages], filter: {
|
|
|
223
240
|
results.meta.total_estimate
|
|
224
241
|
```
|
|
225
242
|
|
|
226
|
-
Search needs `
|
|
243
|
+
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.
|
|
227
244
|
|
|
228
245
|
## Schema
|
|
229
246
|
|
|
@@ -275,13 +292,14 @@ The API's resources come back as `Nohead::NoheadObject`s.
|
|
|
275
292
|
| `records` | `list`, `get`, `create`, `update`, `delete`, `restore`, `publish`, `unpublish`, `publication`, `get_schedule`, `schedule`, `unschedule`, `scheduled_changes`, `drafts`, `count`, `bulk`, `diff`, `search` |
|
|
276
293
|
| `drafts` | `create`, `list`, `get`, `update`, `discard`, `merge`, `schedule`, `unschedule` |
|
|
277
294
|
| `records.revisions` | `list`, `get`, `revert` |
|
|
295
|
+
| `revisions` | `get` (by its own `rev_` ID) |
|
|
278
296
|
| `search` | across the project |
|
|
279
297
|
| `collections` | `list`, `get`, `create`, `update`, `delete`, `restore`, `schema` |
|
|
280
298
|
| `collections.schema_changes` | `list`, `get` |
|
|
281
299
|
| `collections.search_index` | `get`, `rebuild` |
|
|
282
300
|
| `fields` | `list`, `get`, `create`, `update`, `delete`, `restore`, `order`, `reorder`, `remove_alias` |
|
|
283
301
|
| `migrations` | `create`, `list`, `get`, `cancel` |
|
|
284
|
-
| `assets` | `upload`, `create_upload`, `complete`, `list`, `get`, `delete`, `restore`, `purge`, `usage`, `
|
|
302
|
+
| `assets` | `upload`, `create_upload`, `complete`, `list`, `get`, `update`, `delete`, `restore`, `purge`, `usage`, `download_url` |
|
|
285
303
|
| `webhooks` | `list`, `get`, `create`, `update`, `delete`, `restore`, `rotate_secret`, `test`, `unwrap` |
|
|
286
304
|
| `webhooks.secrets` | `list`, `retire` |
|
|
287
305
|
| `webhooks.deliveries` | `list`, `get`, `retry` |
|
data/lib/nohead/client.rb
CHANGED
|
@@ -15,10 +15,11 @@ module Nohead
|
|
|
15
15
|
RETRYABLE_STATUSES = [429, 500, 502, 503, 504].freeze
|
|
16
16
|
MAX_RETRY_AFTER = 60
|
|
17
17
|
|
|
18
|
-
attr_reader :records, :drafts, :collections, :fields, :migrations, :assets, :webhooks,
|
|
18
|
+
attr_reader :records, :revisions, :drafts, :collections, :fields, :migrations, :assets, :webhooks,
|
|
19
19
|
:audit_events, :feature_flags, :me, :health
|
|
20
20
|
|
|
21
|
-
# api_key:: A project API key ("
|
|
21
|
+
# api_key:: A project API key ("nohead_sk_...", or "nohead_pk_..." when
|
|
22
|
+
# published-only). Defaults to NOHEAD_API_KEY.
|
|
22
23
|
# base_url:: Defaults to NOHEAD_API_URL, else https://api.nohead.io.
|
|
23
24
|
# project_id:: The key's project. Looked up once with GET /v1/me when omitted.
|
|
24
25
|
# max_retries:: Retries of failed requests (see the README, "Retries").
|
|
@@ -40,6 +41,7 @@ module Nohead
|
|
|
40
41
|
@warned = {}
|
|
41
42
|
|
|
42
43
|
@records = Resources::Records.new(self)
|
|
44
|
+
@revisions = Resources::RevisionsById.new(self)
|
|
43
45
|
@drafts = Resources::Drafts.new(self)
|
|
44
46
|
@collections = Resources::Collections.new(self)
|
|
45
47
|
@fields = Resources::Fields.new(self)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Nohead
|
|
4
|
+
# Image renditions without a request. Image URLs are open: an image asset's
|
|
5
|
+
# `image_url` serves the whole image, and any of imgproxy's processing
|
|
6
|
+
# options written into it transform it
|
|
7
|
+
# (https://docs.imgproxy.net/usage/processing).
|
|
8
|
+
#
|
|
9
|
+
# Nohead::Images.url(asset, width: 800, height: 600, fit: "cover", format: "webp")
|
|
10
|
+
module Images
|
|
11
|
+
FITS = { "contain" => "fit", "cover" => "fill", "fill" => "force" }.freeze
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# A rendition of an image (an asset, as an object or a Hash, or its `image_url`). fit: "contain"
|
|
16
|
+
# fits inside the box, "cover" fills it, cropping, "fill" stretches to it.
|
|
17
|
+
# gravity: is what a crop keeps ("sm" for smart, "fp:0.5:0.3" for a focal
|
|
18
|
+
# point); options: any other processing options, as written in a URL
|
|
19
|
+
# (["bl:2"]).
|
|
20
|
+
def url(image, width: nil, height: nil, fit: "contain", format: nil, quality: nil, dpr: nil,
|
|
21
|
+
gravity: nil, options: [])
|
|
22
|
+
base = base_of(image)
|
|
23
|
+
check_options([gravity, *options])
|
|
24
|
+
at = base.index("/plain/")
|
|
25
|
+
parts = [resize(fit, width, height), ("g:#{gravity}" if gravity), ("dpr:#{dpr}" if dpr),
|
|
26
|
+
("q:#{quality}" if quality), *options].compact
|
|
27
|
+
base[0...at] + parts.map { |part| "/#{part}" }.join + source(base[at..], format)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# rs:<fit>:<width>:<height>, or nothing without a size (0 is none).
|
|
31
|
+
def resize(fit, width, height)
|
|
32
|
+
type = FITS.fetch(fit.to_s) { raise ArgumentError, "fit must be one of #{FITS.keys.join(', ')}" }
|
|
33
|
+
width = nil if width&.zero?
|
|
34
|
+
height = nil if height&.zero?
|
|
35
|
+
"rs:#{type}:#{width || 0}:#{height || 0}" if width || height
|
|
36
|
+
end
|
|
37
|
+
private_class_method :resize
|
|
38
|
+
|
|
39
|
+
def base_of(image)
|
|
40
|
+
base = case image
|
|
41
|
+
when String then image
|
|
42
|
+
when Hash then image["image_url"] || image[:image_url]
|
|
43
|
+
else image.image_url
|
|
44
|
+
end
|
|
45
|
+
raise ArgumentError, "Not a ready image: it has no image_url" if base.nil? || base.empty?
|
|
46
|
+
raise ArgumentError, "Not a Nohead image URL: #{base}" unless base.include?("/plain/")
|
|
47
|
+
|
|
48
|
+
base
|
|
49
|
+
end
|
|
50
|
+
private_class_method :base_of
|
|
51
|
+
|
|
52
|
+
def check_options(values)
|
|
53
|
+
bad = values.compact.find { |value| value.to_s.match?(%r{[/@?#]}) }
|
|
54
|
+
raise ArgumentError, "Not an imgproxy option: #{bad}" if bad
|
|
55
|
+
end
|
|
56
|
+
private_class_method :check_options
|
|
57
|
+
|
|
58
|
+
# The source comes last; a format replaces any the URL already names.
|
|
59
|
+
def source(source, format)
|
|
60
|
+
format ? "#{source.sub(/@[a-z]+\z/, '')}@#{format}" : source
|
|
61
|
+
end
|
|
62
|
+
private_class_method :source
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/nohead/operations.rb
CHANGED
|
@@ -8,10 +8,10 @@ module Nohead
|
|
|
8
8
|
"assets_delete" => ["DELETE", "/v1/assets/{asset_id}"],
|
|
9
9
|
"assets_download_url" => ["GET", "/v1/assets/{asset_id}/download-url"],
|
|
10
10
|
"assets_get" => ["GET", "/v1/assets/{asset_id}"],
|
|
11
|
-
"assets_image_url" => ["GET", "/v1/assets/{asset_id}/image-url"],
|
|
12
11
|
"assets_list" => ["GET", "/v1/projects/{project_id}/assets"],
|
|
13
12
|
"assets_purge" => ["POST", "/v1/assets/{asset_id}/purge"],
|
|
14
13
|
"assets_restore" => ["POST", "/v1/assets/{asset_id}/restore"],
|
|
14
|
+
"assets_update" => ["PATCH", "/v1/assets/{asset_id}"],
|
|
15
15
|
"assets_upload" => ["POST", "/v1/projects/{project_id}/assets"],
|
|
16
16
|
"assets_usage" => ["GET", "/v1/assets/{asset_id}/usage"],
|
|
17
17
|
"audit_events_list" => ["GET", "/v1/projects/{project_id}/audit-events"],
|
|
@@ -67,6 +67,7 @@ module Nohead
|
|
|
67
67
|
"records_unpublish" => ["DELETE", "/v1/records/{record_id}/publication"],
|
|
68
68
|
"records_unschedule" => ["DELETE", "/v1/records/{record_id}/schedule"],
|
|
69
69
|
"records_update" => ["PATCH", "/v1/records/{record_id}"],
|
|
70
|
+
"revisions_get" => ["GET", "/v1/revisions/{revision_id}"],
|
|
70
71
|
"scheduled_changes_list" => ["GET", "/v1/collections/{collection_id}/scheduled-changes"],
|
|
71
72
|
"schema_changes_get" => ["GET", "/v1/schema-changes/{schema_change_id}"],
|
|
72
73
|
"schema_changes_list" => ["GET", "/v1/collections/{collection_id}/schema-changes"],
|
|
@@ -54,20 +54,33 @@ module Nohead
|
|
|
54
54
|
@client.request("assets_complete", path: { asset_id: asset }, idempotency_key: idempotency_key)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# `q` finds assets whose filename or alt text has every word, ignoring
|
|
58
|
+
# case ("hero jpg" finds `Hero-banner.jpg`). `kind` lists only assets of
|
|
59
|
+
# a kind ("image", "video", "audio", "document" or "other"), or of
|
|
60
|
+
# several (%w[image video]).
|
|
61
|
+
#
|
|
57
62
|
# `content_type` lists only assets of a MIME type or `type/*` wildcard
|
|
58
63
|
# ("image/*"), or of several (["image/*", "application/pdf"]), for
|
|
59
64
|
# example the ones an asset field accepts (its `accepted_types`; an
|
|
60
65
|
# empty list, like a field's, means any type).
|
|
61
|
-
def list(content_type: nil, deleted: nil, limit: nil, cursor: nil)
|
|
62
|
-
|
|
63
|
-
@client.paginate("assets_list", query: { filter:
|
|
64
|
-
limit: limit, cursor: cursor })
|
|
66
|
+
def list(q: nil, kind: nil, content_type: nil, deleted: nil, limit: nil, cursor: nil)
|
|
67
|
+
filter = { kind: one_or_in(kind), content_type: one_or_in(content_type), deleted: deleted }
|
|
68
|
+
@client.paginate("assets_list", query: { q: q, filter: filter, limit: limit, cursor: cursor })
|
|
65
69
|
end
|
|
66
70
|
|
|
67
71
|
def get(asset)
|
|
68
72
|
@client.request("assets_get", path: { asset_id: asset })
|
|
69
73
|
end
|
|
70
74
|
|
|
75
|
+
# Renames the asset (`filename:`) or sets its `alt:` text (nil or ""
|
|
76
|
+
# clears it). The file itself can't change: upload a new asset for that.
|
|
77
|
+
# `alt` is the default wherever the asset is used. A deleted asset is a
|
|
78
|
+
# ConflictError: restore it first.
|
|
79
|
+
def update(asset, idempotency_key: nil, **params)
|
|
80
|
+
@client.request("assets_update", path: { asset_id: asset }, body: body_of(params),
|
|
81
|
+
idempotency_key: idempotency_key)
|
|
82
|
+
end
|
|
83
|
+
|
|
71
84
|
# Soft-deletes the asset: restore brings it back until its `purge_after`,
|
|
72
85
|
# when the file is purged.
|
|
73
86
|
def delete(asset, idempotency_key: nil)
|
|
@@ -93,17 +106,20 @@ module Nohead
|
|
|
93
106
|
@client.request("assets_usage", path: { asset_id: asset })
|
|
94
107
|
end
|
|
95
108
|
|
|
96
|
-
# A
|
|
97
|
-
def image_url(asset, width: nil, height: nil, fit: nil, format: nil, quality: nil)
|
|
98
|
-
@client.request("assets_image_url", path: { asset_id: asset }, query: {
|
|
99
|
-
width: width, height: height, fit: fit, format: format, quality: quality
|
|
100
|
-
})
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# A 15-minute link to download the original file (`url`).
|
|
109
|
+
# A link to download the original file (`url`), valid for 2 minutes.
|
|
104
110
|
def download_url(asset)
|
|
105
111
|
@client.request("assets_download_url", path: { asset_id: asset })
|
|
106
112
|
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
# One value as it is, several as `[in]`; an empty list (like an asset
|
|
117
|
+
# field's accepted_types) is no filter.
|
|
118
|
+
def one_or_in(value)
|
|
119
|
+
return value unless value.is_a?(Array)
|
|
120
|
+
|
|
121
|
+
value.empty? ? nil : { in: value }
|
|
122
|
+
end
|
|
107
123
|
end
|
|
108
124
|
end
|
|
109
125
|
end
|
|
@@ -52,9 +52,13 @@ module Nohead
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Creates an unpublished record: create("posts", data: { title: "Hello" }).
|
|
55
|
-
|
|
55
|
+
# With upsert_on:, the key of a unique field, it updates the record holding
|
|
56
|
+
# that value instead, if one exists, so a sync can run again without
|
|
57
|
+
# duplicates; if_match: then applies to that update.
|
|
58
|
+
def create(collection, if_match: nil, idempotency_key: nil, change_note: nil, **params)
|
|
56
59
|
@client.request("records_create", path: { collection_id: collection }, body: body_of(params),
|
|
57
|
-
|
|
60
|
+
if_match: if_match, idempotency_key: idempotency_key,
|
|
61
|
+
change_note: change_note)
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
# Sets the given fields (nil clears one); others keep their values.
|
|
@@ -122,9 +126,9 @@ module Nohead
|
|
|
122
126
|
@client.paginate("record_drafts_list", path: { record_id: record }, query: { limit: limit, cursor: cursor })
|
|
123
127
|
end
|
|
124
128
|
|
|
125
|
-
# A collection's pending scheduled
|
|
126
|
-
#
|
|
127
|
-
# appears twice.
|
|
129
|
+
# A collection's pending scheduled changes, soonest first: publishes,
|
|
130
|
+
# unpublishes and draft merges, one per change, so a record due to
|
|
131
|
+
# publish and later unpublish appears twice.
|
|
128
132
|
def scheduled_changes(collection, sort: nil, limit: nil, cursor: nil)
|
|
129
133
|
@client.paginate("scheduled_changes_list", path: { collection_id: collection },
|
|
130
134
|
query: { sort: sort, limit: limit, cursor: cursor })
|
|
@@ -147,7 +151,7 @@ module Nohead
|
|
|
147
151
|
@client.request("records_diff", path: { record_id: record }, query: { from: from, to: to })
|
|
148
152
|
end
|
|
149
153
|
|
|
150
|
-
# Full-text search in one collection
|
|
154
|
+
# Full-text search in one collection, matching its searchable fields, most
|
|
151
155
|
# relevant first, through the first 1,000 hits.
|
|
152
156
|
def search(collection, query, filter: nil, sort: nil, expand: nil, limit: nil, cursor: nil)
|
|
153
157
|
@client.paginate("collections_search", path: { collection_id: collection }, query: {
|
|
@@ -178,5 +182,13 @@ module Nohead
|
|
|
178
182
|
idempotency_key: idempotency_key, change_note: change_note)
|
|
179
183
|
end
|
|
180
184
|
end
|
|
185
|
+
|
|
186
|
+
# A revision by its own ID ("rev_..."), as webhooks and the activity log name
|
|
187
|
+
# it. Readable while its record is deleted.
|
|
188
|
+
class RevisionsById < Resource
|
|
189
|
+
def get(revision)
|
|
190
|
+
@client.request("revisions_get", path: { revision_id: revision })
|
|
191
|
+
end
|
|
192
|
+
end
|
|
181
193
|
end
|
|
182
194
|
end
|
data/lib/nohead/version.rb
CHANGED
data/lib/nohead.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nohead
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nohead
|
|
@@ -24,6 +24,7 @@ files:
|
|
|
24
24
|
- lib/nohead.rb
|
|
25
25
|
- lib/nohead/client.rb
|
|
26
26
|
- lib/nohead/errors.rb
|
|
27
|
+
- lib/nohead/images.rb
|
|
27
28
|
- lib/nohead/nohead_object.rb
|
|
28
29
|
- lib/nohead/operations.rb
|
|
29
30
|
- lib/nohead/page.rb
|