class

DataDungeon::API

Inherits HTTP::Handler < Reference < Object

A JSON API over a DB, for tools that browse and curate a store from elsewhere, such as an asset browser. Mount it in an application's HTTP server (it's an HTTP::Handler, under prefix), or run it alone next to the database with dd-serve.

Tokens go in Authorization: Bearer <token>. Reads need read_token, or nothing when it's nil (for a server only this machine can reach). Writes need write_token; with none, there are no writes. The write token reads too. A read-only DB refuses writes whatever the token.

GET    /types                      types, counts (current and retired), registrations
                                     and every consumer's indexes
GET    /types/:type/tags           tag names and how many assets carry each
GET    /types/:type/tags/:key      a tag's values, most frequent first (?limit=)
GET    /types/:type/views          how many pictures are seen from each named direction
GET    /assets                     a page of assets with their tags, newest first:
                                     ?type= &q= (whole words, catt* for a start)
                                     &tag.<key>= &link.<rel>=<name> (or <name>.*
                                     for it and the names under it, <start>*)
                                     &unlinked=<rel> &file_hash=<sha-256>
                                     &description_hash=<sha-256> (every asset sharing
                                     a description) &text.<kind>=<owner:name> (a
                                     wording a recipe used; @<version> for one wording)
                                     &limit= &page=<n> or &before=<id>
                                     &count=1 (a total), &meta=1 (each picture's fields,
                                     and its view readably)
                                     picture fields: &field.<name>=<low>..<high> (either
                                     end open), &view=<named direction>, &view.side=
                                     &view.yaw= &view.pitch= &view.within=<degrees>,
                                     and the same for light
                                   Listings and counts take current assets, or with
                                     ?retired=only retired ones, =include both
GET    /assets/:id                 an asset, its tags, custom tags, metadata (with a
                                     picture's view and light readably) and links
GET    /assets/:id/object          its bytes, streamed from the storage
GET    /assets/:id/recipe          how it was made (DB#recipe): what was sent, the
                                     wordings it used (owner:name@version),
                                     steps included; 404 when it has none
GET    /assets/:id/links           its links, and the links to it
GET    /assets/:id/tracks          what tools measured of a sound or video over time
                                     (DB#tracks): each track's name, tool, made_at and
                                     cues [{start_ms, end_ms, value}]
GET    /assets/:id/tracks/:name    one track; 404 when it has none of that name
POST   /maintenance/check          check_consistency's report
GET    /objects                    every object key the store's rows use (object_keys),
                                     for clearing a shared bucket
GET    /vocabulary                 the shared tags and their values, with their titles
                                     (DB#vocabulary), each rating with DataDungeon's
                                     words for it; DataDungeon's asset types
                                     (DB::STANDARD_TYPES); and the shared tracks
                                     (DB::STANDARD_TRACKS)
GET    /types/:type/matches        best matches, given a matcher (MatchIndex):
                                     ?trait.<k>=<v> &field.<f>=<v> (view=back-left,
                                     dominant-color=#aa3311) &require=a,b &weight.<k>=<n> &limit=
GET    /assets/:id/similar         the assets closest to this one: ?require= &weight.<k>= &limit=
GET    /search                     assets by meaning, given a searcher (SemanticIndex), best
                                     first with their scores: ?q= &type= &media= &tag.<k>=
                                     &key= &key_prefix= &facet= (one facet of type) &limit=
                                     &min_score=; or one query per facet, &facet.<name>=<q>
                                     with type: each asset scores its weakest
GET    /search/status              the store's embedding model, and how many texts wait
                                     to be embedded or failed

POST   /assets                     a file added by hand, as multipart/form-data: file
                                     (its Content-Type the asset's) and asset, JSON
                                     {type, tags, custom, description, permanent,
                                     made_at, supersedes, image}; stored as not generated,
                                     with no recipe; image as PATCH takes it, plus how
                                     to store the file ({compression: "normalize",
                                     target_format: "tiff"} for 8-bit 64x64 tiles); 409
                                     with asset_id when its type already holds the bytes;
                                     413 for a file over max_upload (256 MiB)
POST   /assets/:id/webp            {tags, quality}: a picture's WebP as an asset of its
                                     own, its tags with these over them, linked
                                     derived-from it (DB#store_webp); 409 as above
PATCH  /assets/:id                 {tags, description, everywhere, flagged, rating,
                                     permanent, image}: update_asset;
                                     image holds the fields an application sets, view
                                     and light as {side, yaw, pitch, roll}
DELETE /assets/:id
POST   /assets/:id/links           {rel, to (an asset id) or name, data}: link
                                     (rel supersedes: supersede)
DELETE /assets/:id/links           ?rel= &to= or &name=: unlink
POST   /assets/:id/retire          retire: hidden, kept, reversible
POST   /assets/:id/reinstate       reinstate
POST   /maintenance/prune          {type, keep_last, retired_before}: delete retired assets
POST   /maintenance/measure        {type, all}: measure_images
PUT    /assets/:id/keyframes       [{at_ms, held, view, light, anchor_x, anchor_y}]:
                                     set_keyframes (view and light readably)
PUT    /assets/:id/tracks/:name    {tool, cues}: set_track, replacing the track
POST   /types/:type/promote        {trait, value}: promote
POST   /maintenance/vacuum         {delete_missing_rows, delete_orphan_objects}

Constants

MAX_ASSET_PART = (1_i64 * 1024) * 1024
MAX_PAGE = 500
MAX_UPLOAD = (256_i64 * 1024) * 1024

The most an upload's file may hold unless max_upload: says otherwise, and its asset part (JSON): read no further than that, so a body of any size can't fill the server's memory.

PAGE = 50

Constructors

new(db : DB, *, read_token : String | Nil = nil, write_token : String | Nil = nil, prefix : String = "", matcher : Matcher | Nil = nil, searcher : Searcher | Nil = nil, max_upload : Int64 = MAX_UPLOAD)
Source

Instance methods

call(context : HTTP::Server::Context) : Nil
Source

Nested types