[{"data":1,"prerenderedAt":436},["ShallowReactive",2],{"docs-nav-pkg":3,"docs-page-pkg-\u002Fpkg\u002Fblob":133},[4,8,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,90,93,96,99,102,105,108,111,114,117,121,124,127,130],{"path":5,"title":6,"section":7},"\u002Fpkg","Overview","Start",{"path":9,"title":10,"section":11},"\u002Fpkg\u002Faccordion","Accordion","Components",{"path":13,"title":14,"section":11},"\u002Fpkg\u002Falert-dialog","Alert Dialog",{"path":16,"title":17,"section":11},"\u002Fpkg\u002Fautocomplete","Autocomplete",{"path":19,"title":20,"section":11},"\u002Fpkg\u002Favatar","Avatar",{"path":22,"title":23,"section":11},"\u002Fpkg\u002Fbutton","Button",{"path":25,"title":26,"section":11},"\u002Fpkg\u002Fcheckbox","Checkbox",{"path":28,"title":29,"section":11},"\u002Fpkg\u002Fcheckbox-group","Checkbox Group",{"path":31,"title":32,"section":11},"\u002Fpkg\u002Fcollapsible","Collapsible",{"path":34,"title":35,"section":11},"\u002Fpkg\u002Fcombobox","Combobox",{"path":37,"title":38,"section":11},"\u002Fpkg\u002Fcontext-menu","Context Menu",{"path":40,"title":41,"section":11},"\u002Fpkg\u002Fdialog","Dialog",{"path":43,"title":44,"section":11},"\u002Fpkg\u002Fdrawer","Drawer",{"path":46,"title":47,"section":11},"\u002Fpkg\u002Ffield","Field",{"path":49,"title":50,"section":11},"\u002Fpkg\u002Ffieldset","Fieldset",{"path":52,"title":53,"section":11},"\u002Fpkg\u002Fform","Form",{"path":55,"title":56,"section":11},"\u002Fpkg\u002Ficon-picker","Icon picker",{"path":58,"title":59,"section":11},"\u002Fpkg\u002Finput","Input",{"path":61,"title":62,"section":11},"\u002Fpkg\u002Fmenu","Menu",{"path":64,"title":65,"section":11},"\u002Fpkg\u002Fmenubar","Menubar",{"path":67,"title":68,"section":11},"\u002Fpkg\u002Fmeter","Meter",{"path":70,"title":71,"section":11},"\u002Fpkg\u002Fnavigation-menu","Navigation Menu",{"path":73,"title":74,"section":11},"\u002Fpkg\u002Fnumber-field","Number Field",{"path":76,"title":77,"section":11},"\u002Fpkg\u002Fotp-field","OTP Field",{"path":79,"title":80,"section":11},"\u002Fpkg\u002Fplot","Plot",{"path":82,"title":83,"section":11},"\u002Fpkg\u002Fpopover","Popover",{"path":85,"title":86,"section":11},"\u002Fpkg\u002Fpreview-card","Preview Card",{"path":88,"title":89,"section":11},"\u002Fpkg\u002Fprogress","Progress",{"path":91,"title":92,"section":11},"\u002Fpkg\u002Fradio-group","Radio Group",{"path":94,"title":95,"section":11},"\u002Fpkg\u002Fscroll-area","Scroll Area",{"path":97,"title":98,"section":11},"\u002Fpkg\u002Fselect","Select",{"path":100,"title":101,"section":11},"\u002Fpkg\u002Fseparator","Separator",{"path":103,"title":104,"section":11},"\u002Fpkg\u002Fsidebar","Sidebar",{"path":106,"title":107,"section":11},"\u002Fpkg\u002Fslider","Slider",{"path":109,"title":110,"section":11},"\u002Fpkg\u002Fswitch","Switch",{"path":112,"title":113,"section":11},"\u002Fpkg\u002Ftabs","Tabs",{"path":115,"title":116,"section":11},"\u002Fpkg\u002Ftoast","Toast",{"path":118,"title":119,"section":120},"\u002Fpkg\u002Fapi","Api","Runtime",{"path":122,"title":123,"section":120},"\u002Fpkg\u002Fauth","Auth",{"path":125,"title":126,"section":120},"\u002Fpkg\u002Fblob","Blob",{"path":128,"title":129,"section":120},"\u002Fpkg\u002Fchannels","Channels",{"path":131,"title":132,"section":120},"\u002Fpkg\u002Fdb","Db",{"id":134,"title":126,"body":135,"description":429,"extension":430,"meta":431,"navigation":432,"path":125,"section":120,"seo":433,"stem":434,"__hash__":435},"pkg\u002Fpkg\u002Fblob.md",{"type":136,"value":137,"toc":427},"minimark",[138,158,210,226,261,267,345,375,389,401,423],[139,140,141,145,146,149,150,157],"p",{},[142,143,144],"code",{},"lib\u002Fblob"," (",[142,147,148],{},"kalt-blob",") stores objects in ",[151,152,156],"a",{"href":153,"rel":154},"https:\u002F\u002Fgaragehq.deuxfleurs.fr\u002F",[155],"nofollow","Garage",". Garage speaks the S3 API. The library signs each request. Object bytes are not rows.",[139,159,160,163,164,167,168,171,172,175,176,171,179,182,183,167,186,189,190,193,194,197,198,201,202,205,206,209],{},[142,161,162],{},"pnpm dev"," starts two local nodes from ",[142,165,166],{},"platform\u002Fblob",". ",[142,169,170],{},"garage-workforce"," listens on ",[142,173,174],{},"http:\u002F\u002F127.0.0.1:3900",". People, agents, and their books use it. ",[142,177,178],{},"garage-workspace",[142,180,181],{},"http:\u002F\u002F127.0.0.1:3910",". Workspace logos use it. The bucket on each node is ",[142,184,185],{},"kalt",[142,187,188],{},"scripts\u002Fdev.sh"," points the workspace process at ",[142,191,192],{},"3910"," and leaves ",[142,195,196],{},"BLOB_ENDPOINT"," for workforce. Keys come from ",[142,199,200],{},"object_key",", ",[142,203,204],{},"logo_key",", and ",[142,207,208],{},"book_key",".",[139,211,212,213,216,217,201,220,205,223,209],{},"Call ",[142,214,215],{},"kalt_blob::install()"," once at process start, then ",[142,218,219],{},"put",[142,221,222],{},"get",[142,224,225],{},"delete",[227,228,233],"pre",{"className":229,"code":230,"language":231,"meta":232,"style":232},"language-rust shiki shiki-themes github-light github-dark","kalt_blob::install()?;\nkalt_blob::put(\"workspace\u002Fperson\u002Fid\", &bytes, \"image\u002Fpng\").await?;\nlet object = kalt_blob::get(\"workspace\u002Fperson\u002Fid\").await?;\nkalt_blob::delete(\"workspace\u002Fperson\u002Fid\").await?;\n","rust","",[142,234,235,243,249,255],{"__ignoreMap":232},[236,237,240],"span",{"class":238,"line":239},"line",1,[236,241,242],{},"kalt_blob::install()?;\n",[236,244,246],{"class":238,"line":245},2,[236,247,248],{},"kalt_blob::put(\"workspace\u002Fperson\u002Fid\", &bytes, \"image\u002Fpng\").await?;\n",[236,250,252],{"class":238,"line":251},3,[236,253,254],{},"let object = kalt_blob::get(\"workspace\u002Fperson\u002Fid\").await?;\n",[236,256,258],{"class":238,"line":257},4,[236,259,260],{},"kalt_blob::delete(\"workspace\u002Fperson\u002Fid\").await?;\n",[139,262,263,266],{},[142,264,265],{},"Store::from_env"," reads:",[268,269,270,283],"table",{},[271,272,273],"thead",{},[274,275,276,280],"tr",{},[277,278,279],"th",{},"Variable",[277,281,282],{},"Local default",[284,285,286,297,308,320,332],"tbody",{},[274,287,288,293],{},[289,290,291],"td",{},[142,292,196],{},[289,294,295],{},[142,296,174],{},[274,298,299,304],{},[289,300,301],{},[142,302,303],{},"BLOB_BUCKET",[289,305,306],{},[142,307,185],{},[274,309,310,315],{},[289,311,312],{},[142,313,314],{},"BLOB_REGION",[289,316,317],{},[142,318,319],{},"garage",[274,321,322,327],{},[289,323,324],{},[142,325,326],{},"BLOB_ACCESS_KEY",[289,328,329],{},[142,330,331],{},"GKkaltlocal0123456789abcdef",[274,333,334,339],{},[289,335,336],{},[142,337,338],{},"BLOB_SECRET_KEY",[289,340,341,342],{},"the dev secret in ",[142,343,344],{},".env.example",[139,346,347,348,350,351,354,355,357,358,361,362,364,365,367,368,371,372,374],{},"A missing scheme on ",[142,349,196],{}," is treated as ",[142,352,353],{},"http:\u002F\u002F",". Keys are object paths. Empty keys, NUL bytes, and ",[142,356,209],{}," or ",[142,359,360],{},".."," segments are rejected. ",[142,363,219],{}," overwrites the same key. ",[142,366,222],{}," returns ",[142,369,370],{},"None"," when Garage replies that the object is missing. ",[142,373,225],{}," is idempotent.",[139,376,377,378,381,382,167,385,388],{},"Workforce avatars use the workforce node. ",[142,379,380],{},"POST \u002Fapi\u002Fworkforce\u002Favatars\u002F{kind}\u002F{id}"," writes ",[142,383,384],{},"{workspace}\u002F{kind}\u002F{id}",[142,386,387],{},"GET \u002Fapi\u002Fworkforce\u002Fmedia?key="," reads it back for a signed-in member of that workspace.",[139,390,391,392,381,395,167,398,388],{},"Workspace logos use the workspace node. ",[142,393,394],{},"POST \u002Fapi\u002Fworkspace\u002F{id}\u002Flogo",[142,396,397],{},"{workspace_id}\u002Flogo",[142,399,400],{},"GET \u002Fapi\u002Fworkspace\u002Fmedia?key=",[139,402,403,404,406,407,409,410,412,413,415,416,419,420,209],{},"On Render, the ",[142,405,148],{}," env group holds ",[142,408,326],{}," and ",[142,411,338],{},". Set both before the first Garage boot. Garage keeps the secret it imported and refuses a later change for the same key id. The workforce service receives ",[142,414,196],{}," from ",[142,417,418],{},"kalt-workforce-garage",". The workspace service receives it from ",[142,421,422],{},"kalt-workspace-garage",[424,425,426],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":232,"searchDepth":245,"depth":245,"links":428},[],"Garage object store for bytes that do not belong in Postgres","md",{},true,{"title":126,"description":429},"pkg\u002Fblob","IzZDNqljBiiIfBeW2ny67h3r1WPATwbdvHvEN6-JgxU",1791043754624]