nohead 0.3.0 → 0.5.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 +33 -0
- data/README.md +7 -7
- data/lib/nohead/client.rb +4 -0
- data/lib/nohead/operations.rb +2 -2
- data/lib/nohead/resources/assets.rb +5 -3
- data/lib/nohead/resources/drafts.rb +4 -9
- data/lib/nohead/resources/other.rb +2 -0
- data/lib/nohead/resources/schema.rb +15 -13
- data/lib/nohead/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e94f698ee3cb6906c1b21535666bdefc57f6d864dbad5eb3436c9e0a7a4bff2f
|
|
4
|
+
data.tar.gz: a47d275d02c1b5111b0eadc5f14dedf2a201c5fdcf01ae0eaba306c3bdb87ad2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bbac1644f34a8ea9ff5b41b342facdfea9df8de606cca48e00fcbde9adcb0d3564c65973f43f087d8d6acc4f9443057107c7eb244ab47f557d96bb6b1f1d14cb
|
|
7
|
+
data.tar.gz: e650ba515324f59b5cd141534be18d49ae4530e5fe89d7d19bf3aac1e2a6c97fc502b6094b06e43e580b771391d110ad72e32c166235eab6492b8592aaba4a0c
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,39 @@ 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.5.0
|
|
9
|
+
|
|
10
|
+
- **Breaking:** field migrations are created under their collection:
|
|
11
|
+
`migrations.create(collection, field_id:, ..., dry_run: true)`
|
|
12
|
+
(`POST /v1/collections/{collection_id}/migrations`) replaces
|
|
13
|
+
`fields.migrate(field, ...)`. It returns a preview for a dry run, and the
|
|
14
|
+
FieldMigration otherwise.
|
|
15
|
+
- **Breaking:** `drafts.list` no longer takes `record_id:`; a record's draft
|
|
16
|
+
is `records.drafts(record)`.
|
|
17
|
+
- **Breaking:** `assets.list(content_type:)` takes one MIME type or `type/*`
|
|
18
|
+
wildcard (`"image/*"`), or an Array of them, sent as
|
|
19
|
+
`filter[content_type][in]` (an empty Array is any type). A
|
|
20
|
+
comma-separated string is no longer several types.
|
|
21
|
+
- **Breaking:** `audit_events.list` sorts by `created_at` or `-created_at`
|
|
22
|
+
(the default; was `id` and `-id`), and `records.list` no longer sorts by
|
|
23
|
+
`id`.
|
|
24
|
+
- Webhook events always carry `actor` and `via`, and `via` is no longer
|
|
25
|
+
`import` or `migration`.
|
|
26
|
+
|
|
27
|
+
## 0.4.0
|
|
28
|
+
|
|
29
|
+
- **Breaking:** a field's `api_key` is its `key` (in fields, their aliases,
|
|
30
|
+
`fields.create(..., key:)` and `fields.update(..., key:)`), as the
|
|
31
|
+
editor's "Field key" says. API keys keep their name.
|
|
32
|
+
- **Breaking:** `collections.schema_changes.get(schema_change)` takes the
|
|
33
|
+
schema change's ID alone (`GET /v1/schema-changes/{id}`).
|
|
34
|
+
- **Breaking:** `fields.update` no longer takes `type` or `multiple`; they
|
|
35
|
+
rewrite record values, so they are `fields.migrate`. The API refuses a
|
|
36
|
+
body key an operation doesn't take with `400` (`unknown_parameter`,
|
|
37
|
+
naming it), so a misspelt keyword no longer passes unnoticed.
|
|
38
|
+
- The contract types each field's `configuration` by field type; the API
|
|
39
|
+
reference lists each type's options.
|
|
40
|
+
|
|
8
41
|
## 0.3.0
|
|
9
42
|
|
|
10
43
|
- **Upgrade required:** 0.1 and 0.2 no longer work with the current API,
|
data/README.md
CHANGED
|
@@ -95,7 +95,7 @@ nohead.drafts.merge(draft.id) # or drafts.schedule(draft.id, merge_at: ...)
|
|
|
95
95
|
|
|
96
96
|
- A record has at most one draft; starting a second raises `Nohead::ConflictError` (detail code `draft_exists`, with its `draft_id`).
|
|
97
97
|
- A merge changes content only: a live record stays live, an unpublished one unpublished. Publishing a live record with a pending draft raises `ConflictError` (`draft_pending`).
|
|
98
|
-
- `records.drafts(id)` lists a record's draft, and `drafts.list(collection
|
|
98
|
+
- `records.drafts(id)` lists a record's draft, and `drafts.list(collection)` a collection's.
|
|
99
99
|
- `drafts.discard` deletes one for good.
|
|
100
100
|
|
|
101
101
|
## Pagination
|
|
@@ -229,12 +229,12 @@ Search needs `search_enabled` collections and the `search:read` scope. It pages
|
|
|
229
229
|
|
|
230
230
|
```ruby
|
|
231
231
|
nohead.collections.create(name: "Posts", slug: "posts",
|
|
232
|
-
fields: [{ name: "Title",
|
|
233
|
-
nohead.fields.create("posts", name: "Summary",
|
|
232
|
+
fields: [{ name: "Title", key: "title", type: "text", required: true }])
|
|
233
|
+
nohead.fields.create("posts", name: "Summary", key: "summary", type: "long_text")
|
|
234
234
|
|
|
235
235
|
# Changes that rewrite records go through a migration; preview first
|
|
236
|
-
preview = nohead.
|
|
237
|
-
migration = nohead.
|
|
236
|
+
preview = nohead.migrations.create("posts", field_id: "fld_...", type: "long_text", dry_run: true)
|
|
237
|
+
migration = nohead.migrations.create("posts", field_id: "fld_...", type: "long_text")
|
|
238
238
|
nohead.migrations.get(migration.id)
|
|
239
239
|
```
|
|
240
240
|
|
|
@@ -279,8 +279,8 @@ The API's resources come back as `Nohead::NoheadObject`s.
|
|
|
279
279
|
| `collections` | `list`, `get`, `create`, `update`, `delete`, `restore`, `schema` |
|
|
280
280
|
| `collections.schema_changes` | `list`, `get` |
|
|
281
281
|
| `collections.search_index` | `get`, `rebuild` |
|
|
282
|
-
| `fields` | `list`, `get`, `create`, `update`, `delete`, `restore`, `order`, `reorder`, `remove_alias
|
|
283
|
-
| `migrations` | `list`, `get`, `cancel` |
|
|
282
|
+
| `fields` | `list`, `get`, `create`, `update`, `delete`, `restore`, `order`, `reorder`, `remove_alias` |
|
|
283
|
+
| `migrations` | `create`, `list`, `get`, `cancel` |
|
|
284
284
|
| `assets` | `upload`, `create_upload`, `complete`, `list`, `get`, `delete`, `restore`, `purge`, `usage`, `image_url`, `download_url` |
|
|
285
285
|
| `webhooks` | `list`, `get`, `create`, `update`, `delete`, `restore`, `rotate_secret`, `test`, `unwrap` |
|
|
286
286
|
| `webhooks.secrets` | `list`, `retire` |
|
data/lib/nohead/client.rb
CHANGED
|
@@ -148,6 +148,10 @@ module Nohead
|
|
|
148
148
|
|
|
149
149
|
def build_url(template, values)
|
|
150
150
|
values = values.transform_keys(&:to_s)
|
|
151
|
+
# A value the template doesn't take is a method out of step with its operation.
|
|
152
|
+
unknown = values.keys - template.scan(/\{(\w+)\}/).flatten
|
|
153
|
+
raise ArgumentError, "#{unknown.join(', ')} is not a path parameter of #{template}" if unknown.any?
|
|
154
|
+
|
|
151
155
|
values["project_id"] ||= project_id if template.include?("{project_id}")
|
|
152
156
|
path = template.gsub(/\{(\w+)\}/) do
|
|
153
157
|
value = values[Regexp.last_match(1)]
|
data/lib/nohead/operations.rb
CHANGED
|
@@ -37,7 +37,6 @@ module Nohead
|
|
|
37
37
|
"fields_get" => ["GET", "/v1/fields/{field_id}"],
|
|
38
38
|
"fields_get_order" => ["GET", "/v1/collections/{collection_id}/field-order"],
|
|
39
39
|
"fields_list" => ["GET", "/v1/collections/{collection_id}/fields"],
|
|
40
|
-
"fields_migrate" => ["POST", "/v1/fields/{field_id}/migrations"],
|
|
41
40
|
"fields_remove_alias" => ["DELETE", "/v1/fields/{field_id}/aliases/{alias}"],
|
|
42
41
|
"fields_reorder" => ["PUT", "/v1/collections/{collection_id}/field-order"],
|
|
43
42
|
"fields_restore" => ["POST", "/v1/fields/{field_id}/restore"],
|
|
@@ -45,6 +44,7 @@ module Nohead
|
|
|
45
44
|
"health_check" => ["GET", "/v1/health"],
|
|
46
45
|
"me_get" => ["GET", "/v1/me"],
|
|
47
46
|
"migrations_cancel" => ["POST", "/v1/migrations/{migration_id}/cancel"],
|
|
47
|
+
"migrations_create" => ["POST", "/v1/collections/{collection_id}/migrations"],
|
|
48
48
|
"migrations_get" => ["GET", "/v1/migrations/{migration_id}"],
|
|
49
49
|
"migrations_list" => ["GET", "/v1/collections/{collection_id}/migrations"],
|
|
50
50
|
"projects_search" => ["GET", "/v1/projects/{project_id}/search"],
|
|
@@ -68,7 +68,7 @@ module Nohead
|
|
|
68
68
|
"records_unschedule" => ["DELETE", "/v1/records/{record_id}/schedule"],
|
|
69
69
|
"records_update" => ["PATCH", "/v1/records/{record_id}"],
|
|
70
70
|
"scheduled_changes_list" => ["GET", "/v1/collections/{collection_id}/scheduled-changes"],
|
|
71
|
-
"schema_changes_get" => ["GET", "/v1/
|
|
71
|
+
"schema_changes_get" => ["GET", "/v1/schema-changes/{schema_change_id}"],
|
|
72
72
|
"schema_changes_list" => ["GET", "/v1/collections/{collection_id}/schema-changes"],
|
|
73
73
|
"search_index_get" => ["GET", "/v1/collections/{collection_id}/search-index"],
|
|
74
74
|
"search_index_rebuild" => ["POST", "/v1/collections/{collection_id}/search-index/rebuild"],
|
|
@@ -54,10 +54,12 @@ module Nohead
|
|
|
54
54
|
@client.request("assets_complete", path: { asset_id: asset }, idempotency_key: idempotency_key)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
# `content_type` lists only assets of
|
|
58
|
-
#
|
|
59
|
-
# asset field accepts (its `accepted_types
|
|
57
|
+
# `content_type` lists only assets of a MIME type or `type/*` wildcard
|
|
58
|
+
# ("image/*"), or of several (["image/*", "application/pdf"]), for
|
|
59
|
+
# example the ones an asset field accepts (its `accepted_types`; an
|
|
60
|
+
# empty list, like a field's, means any type).
|
|
60
61
|
def list(content_type: nil, deleted: nil, limit: nil, cursor: nil)
|
|
62
|
+
content_type = (content_type.empty? ? nil : { in: content_type }) if content_type.is_a?(Array)
|
|
61
63
|
@client.paginate("assets_list", query: { filter: { content_type: content_type, deleted: deleted },
|
|
62
64
|
limit: limit, cursor: cursor })
|
|
63
65
|
end
|
|
@@ -16,16 +16,11 @@ module Nohead
|
|
|
16
16
|
idempotency_key: idempotency_key)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# A collection's drafts, most recently changed first.
|
|
20
|
-
#
|
|
21
|
-
|
|
22
|
-
def list(collection, record_id: nil, sort: nil, limit: nil, cursor: nil)
|
|
23
|
-
raise ArgumentError, "record_id needs at least one record ID" if record_id == []
|
|
24
|
-
|
|
25
|
-
record_filter = record_id.is_a?(Array) ? { in: record_id } : record_id
|
|
19
|
+
# A collection's drafts, most recently changed first. One record's
|
|
20
|
+
# draft is `records.drafts(record)`.
|
|
21
|
+
def list(collection, sort: nil, limit: nil, cursor: nil)
|
|
26
22
|
@client.paginate("drafts_list", path: { collection_id: collection },
|
|
27
|
-
query: {
|
|
28
|
-
limit: limit, cursor: cursor })
|
|
23
|
+
query: { sort: sort, limit: limit, cursor: cursor })
|
|
29
24
|
end
|
|
30
25
|
|
|
31
26
|
# With `data` as the record reads after the merge, for previews.
|
|
@@ -10,6 +10,8 @@ module Nohead
|
|
|
10
10
|
#
|
|
11
11
|
# audit_events.list(filter: { type: "record.*", resource_type: %w[record draft],
|
|
12
12
|
# created_at: { gte: Time.utc(2026, 10, 1) } })
|
|
13
|
+
#
|
|
14
|
+
# `sort` is "-created_at" (the default) or "created_at".
|
|
13
15
|
def list(filter: nil, sort: nil, limit: nil, cursor: nil)
|
|
14
16
|
filter = filter&.transform_keys(&:to_sym)
|
|
15
17
|
types = filter&.[](:resource_type)
|
|
@@ -60,9 +60,8 @@ module Nohead
|
|
|
60
60
|
query: { limit: limit, cursor: cursor })
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def get(
|
|
64
|
-
@client.request("schema_changes_get",
|
|
65
|
-
path: { collection_id: collection, schema_change_id: schema_change })
|
|
63
|
+
def get(schema_change)
|
|
64
|
+
@client.request("schema_changes_get", path: { schema_change_id: schema_change })
|
|
66
65
|
end
|
|
67
66
|
end
|
|
68
67
|
|
|
@@ -96,7 +95,7 @@ module Nohead
|
|
|
96
95
|
end
|
|
97
96
|
|
|
98
97
|
# Renames, describes or loosens a field. Changes that rewrite record
|
|
99
|
-
# values (type, multiple, tighter rules) are `
|
|
98
|
+
# values (type, multiple, tighter rules) are `migrations.create`.
|
|
100
99
|
def update(field, idempotency_key: nil, change_note: nil, **params)
|
|
101
100
|
@client.request("fields_update", path: { field_id: field }, body: body_of(params),
|
|
102
101
|
idempotency_key: idempotency_key, change_note: change_note)
|
|
@@ -126,23 +125,26 @@ module Nohead
|
|
|
126
125
|
idempotency_key: idempotency_key, change_note: change_note)
|
|
127
126
|
end
|
|
128
127
|
|
|
129
|
-
# Stops accepting a renamed field's old
|
|
128
|
+
# Stops accepting a renamed field's old key before its 6 months end.
|
|
130
129
|
def remove_alias(field, alias_key, idempotency_key: nil)
|
|
131
130
|
@client.request("fields_remove_alias", path: { field_id: field, alias: alias_key },
|
|
132
131
|
idempotency_key: idempotency_key)
|
|
133
132
|
end
|
|
134
|
-
|
|
135
|
-
# Starts a field migration (type, multiple, tighter configuration or a
|
|
136
|
-
# backfill) that rewrites every record. With dry_run: true, previews it.
|
|
137
|
-
def migrate(field, dry_run: false, idempotency_key: nil, change_note: nil, **params)
|
|
138
|
-
@client.request("fields_migrate", path: { field_id: field }, query: { dry_run: dry_run || nil },
|
|
139
|
-
body: body_of(params), idempotency_key: idempotency_key,
|
|
140
|
-
change_note: change_note)
|
|
141
|
-
end
|
|
142
133
|
end
|
|
143
134
|
|
|
144
135
|
# Field migrations. While one runs, its collection is read-only.
|
|
145
136
|
class Migrations < Resource
|
|
137
|
+
# Starts a migration of one of the collection's fields (`field_id`):
|
|
138
|
+
# its type, multiple, a tighter configuration or a backfill, which
|
|
139
|
+
# rewrites every record. Returns the FieldMigration, or with
|
|
140
|
+
# dry_run: true a preview (counts and sample records, nothing written).
|
|
141
|
+
def create(collection, field_id:, dry_run: false, idempotency_key: nil, change_note: nil, **params)
|
|
142
|
+
@client.request("migrations_create", path: { collection_id: collection },
|
|
143
|
+
query: { dry_run: dry_run || nil },
|
|
144
|
+
body: { field_id: field_id, **body_of(params) },
|
|
145
|
+
idempotency_key: idempotency_key, change_note: change_note)
|
|
146
|
+
end
|
|
147
|
+
|
|
146
148
|
def list(collection, limit: nil, cursor: nil)
|
|
147
149
|
@client.paginate("migrations_list", path: { collection_id: collection },
|
|
148
150
|
query: { limit: limit, cursor: cursor })
|
data/lib/nohead/version.rb
CHANGED