atlas_rb 1.2.2 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29da2e41c70d17572c6c24002ba0ff25beb2ad6cdd940dee157a83133c86efaf
4
- data.tar.gz: 9e16fed8e22867c37647a12de104135d78f57995ba5e6decd4929ac6a402bae7
3
+ metadata.gz: d65fea7329731bd0fa0a397a19f5764a05e88397c522baf28721e4a08282e2d3
4
+ data.tar.gz: 7b2db70c9e1a7d9e8fad5194bcb045baeed562561b1c36a60c174e2c1fc5d0aa
5
5
  SHA512:
6
- metadata.gz: 7ba5a0216a5cc5dacce4f6822078eb07d71aa4e14b31142c83dd823c0ec177efa92e1712eac0b235c125870611dcd4633817066c5ee70a98d6f85adbec614a7f
7
- data.tar.gz: b176fc377d6d802e356c5f0a0fd487c6c899d4b5e323e3017eb773fd11e06dd8ebb415329a4c4e81aef5f55f0086602fc33a6cb82c4699709e0a3209c542a48d
6
+ metadata.gz: 335c7d4bd02d6bdb6f297cf86857c042d515680fb8e36991d98a7a7bf4fdd1e52470f0dda4b40605f79d0618c7260a64f2125af2a3100a693c920b51ebc1c1f5
7
+ data.tar.gz: ce1bc4b16ce482975af0785138574aa6b42fc2cc05ddfee777adbef2834b733bdb93df5390cfc4e9a5012af4b9483cf5676f7213edc8e79afc0fd886d2b84545
data/.version CHANGED
@@ -1 +1 @@
1
- 1.2.2
1
+ 1.3.0
data/CHANGELOG.md CHANGED
@@ -1,6 +1,33 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 1.3.0
4
+
5
+ ### Added — `AtlasRb::Resource.find_many` (batch resolve by NOID)
6
+
7
+ A binding for Atlas's `POST /resources/find_many`. Resolves a set of NOIDs
8
+ to lightweight digests in **one** round-trip, replacing the `find`-per-id
9
+ fan-out that several Cerberus surfaces (breadcrumbs, linked-member lists,
10
+ load-destination pickers) paid on every render.
11
+
12
+ ```ruby
13
+ nodes = AtlasRb::Resource.find_many(["col-456", "col-457", "missing"])
14
+ by_noid = nodes.index_by { |n| n["noid"] }
15
+ by_noid["col-456"].title # => "Some Collection"
16
+ ```
17
+
18
+ - Each digest is `{ "id", "noid", "klass", "title", "thumbnail",
19
+ "tombstoned" }` — not the full typed payload. `title` / `thumbnail` are
20
+ `null` for resources off the Modsable backbone (FileSet/Blob).
21
+ - The ids ride in the request **body**, so the list isn't bounded by URL
22
+ length. Returns one `AtlasRb::Mash` per resolved resource.
23
+ - The result is **unordered** and **may be shorter than the input**:
24
+ unresolvable ids are dropped, tombstoned ones come back flagged
25
+ (`"tombstoned" => true`). Index by `"noid"` — don't assume positional
26
+ correspondence with the input.
27
+ - Resolves NOIDs (alternate ids) only; raw Valkyrie ids are not a supported
28
+ input.
29
+
30
+ ## 1.2.2
4
31
 
5
32
  ### Added — `AtlasRb::AuditEvent.emit` (session-scoped audit events)
6
33
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atlas_rb (1.2.2)
4
+ atlas_rb (1.3.0)
5
5
  faraday (~> 2.7)
6
6
  faraday-follow_redirects (~> 0.3.0)
7
7
  faraday-multipart (~> 1)
data/README.md CHANGED
@@ -312,6 +312,27 @@ The two mutations raise the same way `reparent` does — `LinkedMemberError`
312
312
  on a structural `422` (carrying the envelope's `error` code as `#code`) and
313
313
  `ForbiddenError` on a `403` — instead of swallowing the envelope.
314
314
 
315
+ ### Batch resolve (`Resource.find_many`)
316
+
317
+ When you have a *set* of NOIDs and only need each one's title / klass /
318
+ thumbnail — breadcrumb chains, linked-member lists, load-destination
319
+ pickers — resolve them in one round-trip instead of a `find`-per-id
320
+ fan-out:
321
+
322
+ ```ruby
323
+ nodes = AtlasRb::Resource.find_many(["col-456", "col-457", "missing"])
324
+ by_noid = nodes.index_by { |n| n["noid"] }
325
+ by_noid["col-456"].title # => "Some Collection"
326
+ ```
327
+
328
+ Each entry is a lightweight digest — `{ "id", "noid", "klass", "title",
329
+ "thumbnail", "tombstoned" }` — not the full typed payload. The ids travel
330
+ in the request body (no URL-length ceiling). The result is **unordered**
331
+ and **may be shorter than the input**: unresolvable ids are dropped and
332
+ tombstoned resources come back flagged (`"tombstoned" => true`), so index
333
+ by `"noid"` rather than assuming positional correspondence. NOIDs only —
334
+ raw Valkyrie ids are not a supported input.
335
+
315
336
  ## End-to-end example
316
337
 
317
338
  JSON responses come back as `AtlasRb::Mash` (a `Hashie::Mash` subclass), so
@@ -47,6 +47,44 @@ module AtlasRb
47
47
  "resource" => result.first[1])
48
48
  end
49
49
 
50
+ # Resolve many resources by NOID in a single round-trip.
51
+ #
52
+ # Wraps Atlas's `POST /resources/find_many`, which returns one lightweight
53
+ # digest per resolvable resource — `{ "id", "noid", "klass", "title",
54
+ # "thumbnail", "tombstoned" }` — rather than full typed payloads. Use it
55
+ # anywhere a set of ids would otherwise be resolved with a `find`-per-id
56
+ # fan-out (breadcrumb chains, linked-member lists, load-destination
57
+ # pickers): one HTTP call instead of N.
58
+ #
59
+ # The ids travel in the request **body**, so the list is not bounded by
60
+ # URL length. The result is **unordered** and **may be shorter than the
61
+ # input** — unresolvable ids are dropped silently, and tombstoned
62
+ # resources come back flagged (`"tombstoned" => true`) rather than
63
+ # omitted. Index the result by `"noid"`; do not assume positional
64
+ # correspondence with `ids`.
65
+ #
66
+ # @param ids [Array<String>] resource NOIDs to resolve. (Raw Valkyrie ids
67
+ # are not a supported input — the endpoint resolves alternate ids only.)
68
+ # @param nuid [String, nil] optional acting user's NUID, forwarded as the
69
+ # `User:` header. Required for cerberus-token requests; legacy bearer
70
+ # tokens still resolve without it.
71
+ # @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
72
+ # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
73
+ # omitted.
74
+ # @return [Array<AtlasRb::Mash>] one digest Mash per resolved resource
75
+ # (dot- or string-keyed access); empty when nothing resolved.
76
+ #
77
+ # @example Resolve a set of collection titles in one call
78
+ # nodes = AtlasRb::Resource.find_many(["col-456", "col-457", "missing"])
79
+ # by_noid = nodes.index_by { |n| n["noid"] }
80
+ # by_noid["col-456"].title # => "Some Collection"
81
+ def self.find_many(ids, nuid: nil, on_behalf_of: nil)
82
+ JSON.parse(
83
+ connection({}, nuid, on_behalf_of: on_behalf_of)
84
+ .post('/resources/find_many', JSON.dump(ids: Array(ids)))&.body
85
+ ).map { |node| AtlasRb::Mash.new(node) }
86
+ end
87
+
50
88
  # Validate a MODS XML document against Atlas's schema *without* persisting it.
51
89
  #
52
90
  # Useful for surfacing validation errors in UIs before the user commits.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atlas_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cliff
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-03 00:00:00.000000000 Z
11
+ date: 2026-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday