[{"data":1,"prerenderedAt":1793},["ShallowReactive",2],{"navigation_docs_en":3,"-en-storage-overview":441,"-en-storage-overview-surround":1788},[4,45,60,81,112,129,146,173,197,213,242,279,356,372,384,403,429],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"queue","i-lucide-layers","\u002Fen\u002Fqueue","en\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Overview","\u002Fen\u002Fqueue\u002Foverview","en\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F11.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F12.auth\u002F5.social-standalone","i-lucide-log-in",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fen\u002Fstorage\u002Foverview","en\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"Kit","i-lucide-box","\u002Fen\u002Fkit","en\u002F3.kit",[248,251,256,261,266,270,275],{"title":52,"path":249,"stem":250,"icon":244},"\u002Fen\u002Fkit\u002Foverview","en\u002F3.kit\u002F1.overview",{"title":252,"path":253,"stem":254,"icon":255},"Application lifecycle","\u002Fen\u002Fkit\u002Fapp","en\u002F3.kit\u002F2.app","i-lucide-power",{"title":257,"path":258,"stem":259,"icon":260},"Server","\u002Fen\u002Fkit\u002Fserver","en\u002F3.kit\u002F3.server","i-lucide-server",{"title":262,"path":263,"stem":264,"icon":265},"Worker","\u002Fen\u002Fkit\u002Fworker","en\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":267,"path":268,"stem":269,"icon":70},"Realtime","\u002Fen\u002Fkit\u002Frealtime","en\u002F3.kit\u002F5.realtime",{"title":271,"path":272,"stem":273,"icon":274},"Migrations","\u002Fen\u002Fkit\u002Fmigrations","en\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":276,"path":277,"stem":278,"icon":111},"Social login","\u002Fen\u002Fkit\u002Fsocial-login","en\u002F3.kit\u002F7.social-login",{"title":280,"icon":281,"path":282,"stem":283,"children":284,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F4.cli",[285,288,293,298,303,308,313,318,323,328,333,337,342,347,351],{"title":52,"path":286,"stem":287,"icon":281},"\u002Fen\u002Fcli\u002Foverview","en\u002F4.cli\u002F1.overview",{"title":289,"path":290,"stem":291,"icon":292},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":294,"path":295,"stem":296,"icon":297},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":299,"path":300,"stem":301,"icon":302},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":304,"path":305,"stem":306,"icon":307},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":309,"path":310,"stem":311,"icon":312},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":314,"path":315,"stem":316,"icon":317},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":319,"path":320,"stem":321,"icon":322},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":324,"path":325,"stem":326,"icon":327},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":329,"path":330,"stem":331,"icon":332},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":334,"path":335,"stem":336,"icon":244},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F4.cli\u002F5.add-core",{"title":338,"path":339,"stem":340,"icon":341},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":343,"path":344,"stem":345,"icon":346},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":348,"path":349,"stem":350,"icon":265},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F4.cli\u002F8.worker-generators",{"title":352,"path":353,"stem":354,"icon":355},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":357,"icon":227,"path":358,"stem":359,"children":360,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F5.errs",[361,364,368],{"title":52,"path":362,"stem":363,"icon":227},"\u002Fen\u002Ferrs\u002Foverview","en\u002F5.errs\u002F1.overview",{"title":365,"path":366,"stem":367},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F5.errs\u002F2.api",{"title":369,"path":370,"stem":371,"icon":227},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F5.errs\u002F3.integration",{"title":373,"icon":231,"path":374,"stem":375,"children":376,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F6.envconf",[377,380],{"title":52,"path":378,"stem":379,"icon":231},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F6.envconf\u002F1.overview",{"title":381,"path":382,"stem":383},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F6.envconf\u002F2.recipes",{"title":385,"icon":386,"path":387,"stem":388,"children":389,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F7.httperr",[390,393,398],{"title":52,"path":391,"stem":392,"icon":386},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F7.httperr\u002F1.overview",{"title":394,"path":395,"stem":396,"icon":397},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":399,"path":400,"stem":401,"icon":402},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":404,"icon":405,"path":406,"stem":407,"children":408,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F8.dbx",[409,412,416,420,425],{"title":52,"path":410,"stem":411,"icon":405},"\u002Fen\u002Fdbx\u002Foverview","en\u002F8.dbx\u002F1.overview",{"title":413,"path":414,"stem":415,"icon":106},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F8.dbx\u002F2.pg",{"title":417,"path":418,"stem":419,"icon":47},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F8.dbx\u002F3.bunx",{"title":421,"path":422,"stem":423,"icon":424},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":426,"path":427,"stem":428,"icon":317},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F8.dbx\u002F5.seed",{"title":430,"icon":55,"path":431,"stem":432,"children":433,"page":44},"paginate","\u002Fen\u002Fpaginate","en\u002F9.paginate",[434,437],{"title":52,"path":435,"stem":436,"icon":55},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F9.paginate\u002F1.overview",{"title":438,"path":439,"stem":440,"icon":19},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F9.paginate\u002F2.cursor",{"id":442,"title":52,"body":443,"description":1781,"extension":1782,"links":1783,"meta":1784,"navigation":1785,"path":153,"seo":1786,"stem":154,"__hash__":1787},"docs_en\u002Fen\u002F15.storage\u002F1.overview.md",{"type":444,"value":445,"toc":1770},"minimark",[446,486,491,530,552,556,559,625,630,1069,1098,1147,1162,1190,1194,1219,1244,1248,1297,1318,1322,1555,1584,1588,1597,1679,1722,1733,1737,1766],[447,448,449,452,453,456,457,461,462,465,466,470,471,474,475,474,478,481,482,485],"p",{},[450,451,147],"code",{}," is a standalone Go module (",[450,454,455],{},"github.com\u002Fgp-system\u002Fstorage","): object storage for uploads, avatars, generated reports, exports, anything that isn't a database row. In the ",[458,459,460],"a",{"href":41},"shop sample app",", the ",[450,463,464],{},"admin"," surface uploads product images through it. The root module has ",[467,468,469],"strong",{},"zero gp-system dependencies",", and only three third-party ones (",[450,472,473],{},"go.opentelemetry.io\u002Fotel",", ",[450,476,477],{},"...\u002Fmetric",[450,479,480],{},"...\u002Ftrace","), so pulling it into a project that doesn't otherwise use the kit costs nothing beyond OTel's own API package. It works in any Go program: a CLI tool, a Lambda, a plain ",[450,483,484],{},"net\u002Fhttp"," service, with or without the gpsystem kit installed.",[487,488,490],"h2",{"id":489},"install","Install",[492,493,498],"pre",{"className":494,"code":495,"language":496,"meta":497,"style":497},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com\u002Fgp-system\u002Fstorage@v0.1.0 # the kit itself uses this tag\ngo get github.com\u002Fgp-system\u002Fstorage@latest\n","sh","",[450,499,500,520],{"__ignoreMap":497},[501,502,505,509,513,516],"span",{"class":503,"line":504},"line",1,[501,506,508],{"class":507},"sBMFI","go",[501,510,512],{"class":511},"sfazB"," get",[501,514,515],{"class":511}," github.com\u002Fgp-system\u002Fstorage@v0.1.0",[501,517,519],{"class":518},"sHwdD"," # the kit itself uses this tag\n",[501,521,523,525,527],{"class":503,"line":522},2,[501,524,508],{"class":507},[501,526,512],{"class":511},[501,528,529],{"class":511}," github.com\u002Fgp-system\u002Fstorage@latest\n",[447,531,532,533,536,537,540,541,544,545,548,549,551],{},"Go 1.23+ (the ",[450,534,535],{},"Files"," iterator on ",[450,538,539],{},"Disk"," uses range-over-func). The built-in drivers are separate imports: ",[450,542,543],{},"storage\u002Fmemory"," and ",[450,546,547],{},"storage\u002Flocal"," ship inside the same module, at no extra dependency cost. The S3-compatible driver is different, see ",[458,550,164],{"href":165}," for why it's its own module.",[487,553,555],{"id":554},"the-model-driver-disk-manager","The model: Driver, Disk, Manager",[447,557,558],{},"The package is deliberately layered into three pieces, each with one job:",[560,561,562,578],"table",{},[563,564,565],"thead",{},[566,567,568,572,575],"tr",{},[569,570,571],"th",{},"Layer",[569,573,574],{},"What it is",[569,576,577],{},"What you do with it",[579,580,581,595,609],"tbody",{},[566,582,583,589,592],{},[584,585,586],"td",{},[450,587,588],{},"Driver",[584,590,591],{},"the pluggable backend contract",[584,593,594],{},"implement it once per backend; most code never calls it directly",[566,596,597,601,606],{},[584,598,599],{},[450,600,539],{},[584,602,603,604],{},"an instrumented, ergonomic wrapper around one ",[450,605,588],{},[584,607,608],{},"the day-to-day API your service layer calls",[566,610,611,616,622],{},[584,612,613],{},[450,614,615],{},"Manager",[584,617,618,619,621],{},"a named collection of ",[450,620,539],{},"s",[584,623,624],{},"pick a disk by name when a project needs more than one",[626,627,629],"h3",{"id":628},"driver-the-backend-contract","Driver: the backend contract",[492,631,634],{"className":632,"code":633,"language":508,"meta":497,"style":497},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type Driver interface {\n    Name() string\n    Put(ctx context.Context, path string, r io.Reader, opts PutOptions) error\n    Reader(ctx context.Context, path string) (io.ReadCloser, error)\n    RangeReader(ctx context.Context, path string, offset, length int64) (io.ReadCloser, error)\n    Stat(ctx context.Context, path string) (FileInfo, error)\n    List(ctx context.Context, opts ListOptions) (ListPage, error)\n    Copy(ctx context.Context, src, dst string) error\n    Delete(ctx context.Context, path string) error\n    URL(ctx context.Context, path string) (string, error)\n    TemporaryURL(ctx context.Context, path string, opts TemporaryURLOptions) (string, error)\n    TemporaryUploadURL(ctx context.Context, path string, opts TemporaryUploadURLOptions) (UploadURL, error)\n}\n",[450,635,636,651,664,722,765,816,851,887,919,945,980,1021,1063],{"__ignoreMap":497},[501,637,638,642,645,648],{"class":503,"line":504},[501,639,641],{"class":640},"sMK4o","type",[501,643,644],{"class":507}," Driver",[501,646,647],{"class":640}," interface",[501,649,650],{"class":640}," {\n",[501,652,653,657,660],{"class":503,"line":522},[501,654,656],{"class":655},"s2Zo4","    Name",[501,658,659],{"class":640},"()",[501,661,663],{"class":662},"spNyl"," string\n",[501,665,667,670,673,677,680,683,686,689,692,695,697,700,703,705,708,710,713,716,719],{"class":503,"line":666},3,[501,668,669],{"class":655},"    Put",[501,671,672],{"class":640},"(",[501,674,676],{"class":675},"sHdIc","ctx",[501,678,679],{"class":507}," context",[501,681,682],{"class":640},".",[501,684,685],{"class":507},"Context",[501,687,688],{"class":640},",",[501,690,691],{"class":675}," path",[501,693,694],{"class":662}," string",[501,696,688],{"class":640},[501,698,699],{"class":675}," r",[501,701,702],{"class":507}," io",[501,704,682],{"class":640},[501,706,707],{"class":507},"Reader",[501,709,688],{"class":640},[501,711,712],{"class":675}," opts",[501,714,715],{"class":507}," PutOptions",[501,717,718],{"class":640},")",[501,720,721],{"class":662}," error\n",[501,723,725,728,730,732,734,736,738,740,742,744,746,749,752,754,757,759,762],{"class":503,"line":724},4,[501,726,727],{"class":655},"    Reader",[501,729,672],{"class":640},[501,731,676],{"class":675},[501,733,679],{"class":507},[501,735,682],{"class":640},[501,737,685],{"class":507},[501,739,688],{"class":640},[501,741,691],{"class":675},[501,743,694],{"class":662},[501,745,718],{"class":640},[501,747,748],{"class":640}," (",[501,750,751],{"class":507},"io",[501,753,682],{"class":640},[501,755,756],{"class":507},"ReadCloser",[501,758,688],{"class":640},[501,760,761],{"class":662}," error",[501,763,764],{"class":640},")\n",[501,766,768,771,773,775,777,779,781,783,785,787,789,792,794,797,800,802,804,806,808,810,812,814],{"class":503,"line":767},5,[501,769,770],{"class":655},"    RangeReader",[501,772,672],{"class":640},[501,774,676],{"class":675},[501,776,679],{"class":507},[501,778,682],{"class":640},[501,780,685],{"class":507},[501,782,688],{"class":640},[501,784,691],{"class":675},[501,786,694],{"class":662},[501,788,688],{"class":640},[501,790,791],{"class":675}," offset",[501,793,688],{"class":640},[501,795,796],{"class":675}," length",[501,798,799],{"class":662}," int64",[501,801,718],{"class":640},[501,803,748],{"class":640},[501,805,751],{"class":507},[501,807,682],{"class":640},[501,809,756],{"class":507},[501,811,688],{"class":640},[501,813,761],{"class":662},[501,815,764],{"class":640},[501,817,819,822,824,826,828,830,832,834,836,838,840,842,845,847,849],{"class":503,"line":818},6,[501,820,821],{"class":655},"    Stat",[501,823,672],{"class":640},[501,825,676],{"class":675},[501,827,679],{"class":507},[501,829,682],{"class":640},[501,831,685],{"class":507},[501,833,688],{"class":640},[501,835,691],{"class":675},[501,837,694],{"class":662},[501,839,718],{"class":640},[501,841,748],{"class":640},[501,843,844],{"class":507},"FileInfo",[501,846,688],{"class":640},[501,848,761],{"class":662},[501,850,764],{"class":640},[501,852,854,857,859,861,863,865,867,869,871,874,876,878,881,883,885],{"class":503,"line":853},7,[501,855,856],{"class":655},"    List",[501,858,672],{"class":640},[501,860,676],{"class":675},[501,862,679],{"class":507},[501,864,682],{"class":640},[501,866,685],{"class":507},[501,868,688],{"class":640},[501,870,712],{"class":675},[501,872,873],{"class":507}," ListOptions",[501,875,718],{"class":640},[501,877,748],{"class":640},[501,879,880],{"class":507},"ListPage",[501,882,688],{"class":640},[501,884,761],{"class":662},[501,886,764],{"class":640},[501,888,890,893,895,897,899,901,903,905,908,910,913,915,917],{"class":503,"line":889},8,[501,891,892],{"class":655},"    Copy",[501,894,672],{"class":640},[501,896,676],{"class":675},[501,898,679],{"class":507},[501,900,682],{"class":640},[501,902,685],{"class":507},[501,904,688],{"class":640},[501,906,907],{"class":675}," src",[501,909,688],{"class":640},[501,911,912],{"class":675}," dst",[501,914,694],{"class":662},[501,916,718],{"class":640},[501,918,721],{"class":662},[501,920,922,925,927,929,931,933,935,937,939,941,943],{"class":503,"line":921},9,[501,923,924],{"class":655},"    Delete",[501,926,672],{"class":640},[501,928,676],{"class":675},[501,930,679],{"class":507},[501,932,682],{"class":640},[501,934,685],{"class":507},[501,936,688],{"class":640},[501,938,691],{"class":675},[501,940,694],{"class":662},[501,942,718],{"class":640},[501,944,721],{"class":662},[501,946,948,951,953,955,957,959,961,963,965,967,969,971,974,976,978],{"class":503,"line":947},10,[501,949,950],{"class":655},"    URL",[501,952,672],{"class":640},[501,954,676],{"class":675},[501,956,679],{"class":507},[501,958,682],{"class":640},[501,960,685],{"class":507},[501,962,688],{"class":640},[501,964,691],{"class":675},[501,966,694],{"class":662},[501,968,718],{"class":640},[501,970,748],{"class":640},[501,972,973],{"class":662},"string",[501,975,688],{"class":640},[501,977,761],{"class":662},[501,979,764],{"class":640},[501,981,983,986,988,990,992,994,996,998,1000,1002,1004,1006,1009,1011,1013,1015,1017,1019],{"class":503,"line":982},11,[501,984,985],{"class":655},"    TemporaryURL",[501,987,672],{"class":640},[501,989,676],{"class":675},[501,991,679],{"class":507},[501,993,682],{"class":640},[501,995,685],{"class":507},[501,997,688],{"class":640},[501,999,691],{"class":675},[501,1001,694],{"class":662},[501,1003,688],{"class":640},[501,1005,712],{"class":675},[501,1007,1008],{"class":507}," TemporaryURLOptions",[501,1010,718],{"class":640},[501,1012,748],{"class":640},[501,1014,973],{"class":662},[501,1016,688],{"class":640},[501,1018,761],{"class":662},[501,1020,764],{"class":640},[501,1022,1024,1027,1029,1031,1033,1035,1037,1039,1041,1043,1045,1047,1050,1052,1054,1057,1059,1061],{"class":503,"line":1023},12,[501,1025,1026],{"class":655},"    TemporaryUploadURL",[501,1028,672],{"class":640},[501,1030,676],{"class":675},[501,1032,679],{"class":507},[501,1034,682],{"class":640},[501,1036,685],{"class":507},[501,1038,688],{"class":640},[501,1040,691],{"class":675},[501,1042,694],{"class":662},[501,1044,688],{"class":640},[501,1046,712],{"class":675},[501,1048,1049],{"class":507}," TemporaryUploadURLOptions",[501,1051,718],{"class":640},[501,1053,748],{"class":640},[501,1055,1056],{"class":507},"UploadURL",[501,1058,688],{"class":640},[501,1060,761],{"class":662},[501,1062,764],{"class":640},[501,1064,1066],{"class":503,"line":1065},13,[501,1067,1068],{"class":640},"}\n",[447,1070,1071,1072,1074,1075,1078,1079,1082,1083,1086,1087,1093,1094,1097],{},"A ",[450,1073,588],{}," doesn't have to support everything: a driver that can't produce signed URLs returns ",[450,1076,1077],{},"ErrUnsupported"," from ",[450,1080,1081],{},"TemporaryURL","\u002F",[450,1084,1085],{},"TemporaryUploadURL"," rather than faking one, and callers that care check for it (see ",[458,1088,1090],{"href":1089},"\u002Fen\u002Fstorage\u002Fdisk-api#urls",[450,1091,1092],{},"Disk.ProvidesTemporaryURLs","). A driver may additionally implement the optional ",[450,1095,1096],{},"Mover"," interface:",[492,1099,1101],{"className":632,"code":1100,"language":508,"meta":497,"style":497},"type Mover interface {\n    Move(ctx context.Context, src, dst string) error\n}\n",[450,1102,1103,1114,1143],{"__ignoreMap":497},[501,1104,1105,1107,1110,1112],{"class":503,"line":504},[501,1106,641],{"class":640},[501,1108,1109],{"class":507}," Mover",[501,1111,647],{"class":640},[501,1113,650],{"class":640},[501,1115,1116,1119,1121,1123,1125,1127,1129,1131,1133,1135,1137,1139,1141],{"class":503,"line":522},[501,1117,1118],{"class":655},"    Move",[501,1120,672],{"class":640},[501,1122,676],{"class":675},[501,1124,679],{"class":507},[501,1126,682],{"class":640},[501,1128,685],{"class":507},[501,1130,688],{"class":640},[501,1132,907],{"class":675},[501,1134,688],{"class":640},[501,1136,912],{"class":675},[501,1138,694],{"class":662},[501,1140,718],{"class":640},[501,1142,721],{"class":662},[501,1144,1145],{"class":503,"line":666},[501,1146,1068],{"class":640},[447,1148,1149,1150,1153,1154,1157,1158,1161],{},"if it can move an object natively (a rename, not a byte-for-byte copy); ",[450,1151,1152],{},"Disk.Move"," uses it when available and falls back to ",[450,1155,1156],{},"Copy"," + ",[450,1159,1160],{},"Delete"," otherwise.",[447,1163,1164,1165,1169,1170,1174,1175,1180,1181,1183,1184,1189],{},"Three built-in drivers ship with the ecosystem: ",[458,1166,1167],{"href":161},[450,1168,543],{}," (in-process, for tests), ",[458,1171,1172],{"href":161},[450,1173,547],{}," (filesystem, for single-server deployments), and ",[458,1176,1177],{"href":165},[450,1178,1179],{},"storage\u002Fdriver\u002Fs3"," (S3-compatible, for production). All three satisfy the same ",[450,1182,588],{}," contract, and ",[458,1185,1186],{"href":170},[450,1187,1188],{},"storage\u002Fstoragetest"," runs one conformance suite against all of them, plus any driver you write yourself.",[626,1191,1193],{"id":1192},"validpath","ValidPath",[492,1195,1197],{"className":632,"code":1196,"language":508,"meta":497,"style":497},"func ValidPath(path string) bool\n",[450,1198,1199],{"__ignoreMap":497},[501,1200,1201,1204,1207,1209,1212,1214,1216],{"class":503,"line":504},[501,1202,1203],{"class":640},"func",[501,1205,1206],{"class":655}," ValidPath",[501,1208,672],{"class":640},[501,1210,1211],{"class":675},"path",[501,1213,694],{"class":662},[501,1215,718],{"class":640},[501,1217,1218],{"class":662}," bool\n",[447,1220,1221,1222,1224,1225,1082,1227,1230,1231,474,1234,1236,1237,1240,1241,682],{},"A small guard every ",[450,1223,588],{}," implementation is expected to call before touching the backend: it rejects the empty path, absolute paths, ",[450,1226,682],{},[450,1228,1229],{},".."," segments, and anything else that could escape the storage root. Writing a custom driver means calling it at the top of ",[450,1232,1233],{},"Put",[450,1235,1156],{},", and friends, and returning ",[450,1238,1239],{},"ErrInvalidPath"," when it's ",[450,1242,1243],{},"false",[626,1245,1247],{"id":1246},"disk-the-api-you-actually-call","Disk: the API you actually call",[492,1249,1251],{"className":632,"code":1250,"language":508,"meta":497,"style":497},"disk := storage.NewDisk(driver, storage.WithName(\"uploads\"))\n",[450,1252,1253],{"__ignoreMap":497},[501,1254,1255,1259,1262,1265,1267,1270,1272,1275,1277,1279,1281,1284,1286,1289,1292,1294],{"class":503,"line":504},[501,1256,1258],{"class":1257},"sTEyZ","disk ",[501,1260,1261],{"class":640},":=",[501,1263,1264],{"class":1257}," storage",[501,1266,682],{"class":640},[501,1268,1269],{"class":655},"NewDisk",[501,1271,672],{"class":640},[501,1273,1274],{"class":1257},"driver",[501,1276,688],{"class":640},[501,1278,1264],{"class":1257},[501,1280,682],{"class":640},[501,1282,1283],{"class":655},"WithName",[501,1285,672],{"class":640},[501,1287,1288],{"class":640},"\"",[501,1290,1291],{"class":511},"uploads",[501,1293,1288],{"class":640},[501,1295,1296],{"class":640},"))\n",[447,1298,1299,1301,1302,1304,1305,1307,1308,474,1311,474,1314,1317],{},[450,1300,1269],{}," wraps a ",[450,1303,588],{}," with a name and OTel instrumentation (a span per operation, with the disk name and path as attributes), and is what service code depends on day to day; see ",[458,1306,156],{"href":157}," for the full method set. Options: ",[450,1309,1310],{},"WithName(string)",[450,1312,1313],{},"WithTracerProvider",[450,1315,1316],{},"WithMeterProvider","; with none of the latter two set, instrumentation is a no-op, same as everywhere else in the kit.",[626,1319,1321],{"id":1320},"manager-more-than-one-named-disk","Manager: more than one named disk",[492,1323,1325],{"className":632,"code":1324,"language":508,"meta":497,"style":497},"mgr := storage.New(\"public\", map[string]*storage.Disk{\n    \"public\":  storage.NewDisk(local.New(cfg), storage.WithName(\"public\")),\n    \"backups\": storage.NewDisk(s3.New(s3cfg), storage.WithName(\"backups\")),\n})\n\nmgr.Default().Put(ctx, \"avatars\u002F42.png\", r, storage.PutOptions{})\nbackups, _ := mgr.Disk(\"backups\")\n",[450,1326,1327,1369,1422,1471,1476,1482,1527],{"__ignoreMap":497},[501,1328,1329,1332,1334,1336,1338,1341,1343,1345,1348,1350,1352,1355,1357,1360,1362,1364,1366],{"class":503,"line":504},[501,1330,1331],{"class":1257},"mgr ",[501,1333,1261],{"class":640},[501,1335,1264],{"class":1257},[501,1337,682],{"class":640},[501,1339,1340],{"class":655},"New",[501,1342,672],{"class":640},[501,1344,1288],{"class":640},[501,1346,1347],{"class":511},"public",[501,1349,1288],{"class":640},[501,1351,688],{"class":640},[501,1353,1354],{"class":640}," map[",[501,1356,973],{"class":662},[501,1358,1359],{"class":640},"]*",[501,1361,147],{"class":507},[501,1363,682],{"class":640},[501,1365,539],{"class":507},[501,1367,1368],{"class":640},"{\n",[501,1370,1371,1374,1376,1378,1381,1384,1386,1388,1390,1393,1395,1397,1399,1402,1405,1407,1409,1411,1413,1415,1417,1419],{"class":503,"line":522},[501,1372,1373],{"class":640},"    \"",[501,1375,1347],{"class":511},[501,1377,1288],{"class":640},[501,1379,1380],{"class":640},":",[501,1382,1383],{"class":1257},"  storage",[501,1385,682],{"class":640},[501,1387,1269],{"class":655},[501,1389,672],{"class":640},[501,1391,1392],{"class":1257},"local",[501,1394,682],{"class":640},[501,1396,1340],{"class":655},[501,1398,672],{"class":640},[501,1400,1401],{"class":1257},"cfg",[501,1403,1404],{"class":640},"),",[501,1406,1264],{"class":1257},[501,1408,682],{"class":640},[501,1410,1283],{"class":655},[501,1412,672],{"class":640},[501,1414,1288],{"class":640},[501,1416,1347],{"class":511},[501,1418,1288],{"class":640},[501,1420,1421],{"class":640},")),\n",[501,1423,1424,1426,1429,1431,1433,1435,1437,1439,1441,1444,1446,1448,1450,1453,1455,1457,1459,1461,1463,1465,1467,1469],{"class":503,"line":666},[501,1425,1373],{"class":640},[501,1427,1428],{"class":511},"backups",[501,1430,1288],{"class":640},[501,1432,1380],{"class":640},[501,1434,1264],{"class":1257},[501,1436,682],{"class":640},[501,1438,1269],{"class":655},[501,1440,672],{"class":640},[501,1442,1443],{"class":1257},"s3",[501,1445,682],{"class":640},[501,1447,1340],{"class":655},[501,1449,672],{"class":640},[501,1451,1452],{"class":1257},"s3cfg",[501,1454,1404],{"class":640},[501,1456,1264],{"class":1257},[501,1458,682],{"class":640},[501,1460,1283],{"class":655},[501,1462,672],{"class":640},[501,1464,1288],{"class":640},[501,1466,1428],{"class":511},[501,1468,1288],{"class":640},[501,1470,1421],{"class":640},[501,1472,1473],{"class":503,"line":724},[501,1474,1475],{"class":640},"})\n",[501,1477,1478],{"class":503,"line":767},[501,1479,1481],{"emptyLinePlaceholder":1480},true,"\n",[501,1483,1484,1487,1489,1492,1495,1497,1499,1501,1503,1506,1509,1511,1513,1515,1517,1519,1521,1524],{"class":503,"line":818},[501,1485,1486],{"class":1257},"mgr",[501,1488,682],{"class":640},[501,1490,1491],{"class":655},"Default",[501,1493,1494],{"class":640},"().",[501,1496,1233],{"class":655},[501,1498,672],{"class":640},[501,1500,676],{"class":1257},[501,1502,688],{"class":640},[501,1504,1505],{"class":640}," \"",[501,1507,1508],{"class":511},"avatars\u002F42.png",[501,1510,1288],{"class":640},[501,1512,688],{"class":640},[501,1514,699],{"class":1257},[501,1516,688],{"class":640},[501,1518,1264],{"class":507},[501,1520,682],{"class":640},[501,1522,1523],{"class":507},"PutOptions",[501,1525,1526],{"class":640},"{})\n",[501,1528,1529,1531,1533,1536,1538,1541,1543,1545,1547,1549,1551,1553],{"class":503,"line":853},[501,1530,1428],{"class":1257},[501,1532,688],{"class":640},[501,1534,1535],{"class":1257}," _ ",[501,1537,1261],{"class":640},[501,1539,1540],{"class":1257}," mgr",[501,1542,682],{"class":640},[501,1544,539],{"class":655},[501,1546,672],{"class":640},[501,1548,1288],{"class":640},[501,1550,1428],{"class":511},[501,1552,1288],{"class":640},[501,1554,764],{"class":640},[447,1556,1557,1558,1560,1561,1563,1564,1567,1568,1571,1572,1575,1576,1579,1580,1583],{},"A single ",[450,1559,539],{}," is all most projects need. ",[450,1562,615],{}," exists for the case where one app genuinely uses more than one: public assets on local disk, nightly database dumps on S3, say. ",[450,1565,1566],{},"New(defaultDiskName, disks)"," builds it; ",[450,1569,1570],{},"Default()"," returns the named default, ",[450,1573,1574],{},"Disk(name)"," looks one up by name (with an ",[450,1577,1578],{},"ok bool"," the same shape as a map lookup), and ",[450,1581,1582],{},"Names()"," lists everything registered.",[487,1585,1587],{"id":1586},"decorators-composing-behavior-onto-a-driver","Decorators: composing behavior onto a Driver",[447,1589,1590,1591,1593,1594,1596],{},"Both wrap any ",[450,1592,588],{}," and return another ",[450,1595,588],{},", so they compose:",[492,1598,1600],{"className":632,"code":1599,"language":508,"meta":497,"style":497},"d := storage.ReadOnly(s3.New(cfg))                    \u002F\u002F rejects writes\nscoped, err := storage.Scoped(s3.New(cfg), \"tenant-42\") \u002F\u002F confines to a prefix\n",[450,1601,1602,1634],{"__ignoreMap":497},[501,1603,1604,1607,1609,1611,1613,1616,1618,1620,1622,1624,1626,1628,1631],{"class":503,"line":504},[501,1605,1606],{"class":1257},"d ",[501,1608,1261],{"class":640},[501,1610,1264],{"class":1257},[501,1612,682],{"class":640},[501,1614,1615],{"class":655},"ReadOnly",[501,1617,672],{"class":640},[501,1619,1443],{"class":1257},[501,1621,682],{"class":640},[501,1623,1340],{"class":655},[501,1625,672],{"class":640},[501,1627,1401],{"class":1257},[501,1629,1630],{"class":640},"))",[501,1632,1633],{"class":518},"                    \u002F\u002F rejects writes\n",[501,1635,1636,1639,1641,1644,1646,1648,1650,1653,1655,1657,1659,1661,1663,1665,1667,1669,1672,1674,1676],{"class":503,"line":522},[501,1637,1638],{"class":1257},"scoped",[501,1640,688],{"class":640},[501,1642,1643],{"class":1257}," err ",[501,1645,1261],{"class":640},[501,1647,1264],{"class":1257},[501,1649,682],{"class":640},[501,1651,1652],{"class":655},"Scoped",[501,1654,672],{"class":640},[501,1656,1443],{"class":1257},[501,1658,682],{"class":640},[501,1660,1340],{"class":655},[501,1662,672],{"class":640},[501,1664,1401],{"class":1257},[501,1666,1404],{"class":640},[501,1668,1505],{"class":640},[501,1670,1671],{"class":511},"tenant-42",[501,1673,1288],{"class":640},[501,1675,718],{"class":640},[501,1677,1678],{"class":518}," \u002F\u002F confines to a prefix\n",[1680,1681,1682,1703],"ul",{},[1683,1684,1685,1690,1691,474,1693,1695,1696,1698,1699,1702],"li",{},[467,1686,1687],{},[450,1688,1689],{},"ReadOnly(Driver) Driver",": every ",[450,1692,1233],{},[450,1694,1160],{},", and ",[450,1697,1156],{}," call returns ",[450,1700,1701],{},"ErrReadOnly"," immediately, without reaching the backend. Useful for a disk that serves archived or externally-managed content, where a bug that tries to write should fail loudly and locally, not silently succeed against production storage.",[1683,1704,1705,1710,1711,1714,1715,1717,1718,1721],{},[467,1706,1707],{},[450,1708,1709],{},"Scoped(Driver, prefix string) (Driver, error)",": confines every operation to paths under ",[450,1712,1713],{},"prefix",", transparently. A common use is per-tenant isolation on a shared bucket: give each tenant a ",[450,1716,539],{}," built from ",[450,1719,1720],{},"Scoped(sharedDriver, \"tenants\u002F\"+tenantID)",", and a bug that assembles the wrong path for one tenant can't reach another tenant's files, because the scoped driver never sees paths outside its prefix in the first place.",[447,1723,1724,1725,1727,1728,1730,1731,682],{},"Both compose with each other and with the built-in drivers freely, since a ",[450,1726,588],{}," wrapping a ",[450,1729,588],{}," is still just a ",[450,1732,588],{},[487,1734,1736],{"id":1735},"related-pages","Related pages",[1680,1738,1739,1744,1749,1754,1759],{},[1683,1740,1741,1743],{},[458,1742,156],{"href":157},": the full method set: writes, reads, listing, URLs.",[1683,1745,1746,1748],{},[458,1747,160],{"href":161},": the two drivers that ship in the root module.",[1683,1750,1751,1753],{},[458,1752,164],{"href":165},": the S3-compatible driver, its own Go module.",[1683,1755,1756,1758],{},[458,1757,169],{"href":170},": the conformance suite, and writing a custom driver.",[1683,1760,1761,1765],{},[458,1762,1764],{"href":1763},"\u002Fen\u002Fconcepts\u002Farchitecture#the-three-deliberate-exceptions","Architecture: the three deliberate exceptions",": why storage is one of the few places the kit hides a dependency behind an interface.",[1767,1768,1769],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":497,"searchDepth":522,"depth":522,"links":1771},[1772,1773,1779,1780],{"id":489,"depth":522,"text":490},{"id":554,"depth":522,"text":555,"children":1774},[1775,1776,1777,1778],{"id":628,"depth":666,"text":629},{"id":1192,"depth":666,"text":1193},{"id":1246,"depth":666,"text":1247},{"id":1320,"depth":666,"text":1321},{"id":1586,"depth":522,"text":1587},{"id":1735,"depth":522,"text":1736},"Object storage behind a Driver\u002FDisk\u002FManager model, with in-memory, local-disk and S3-compatible drivers.","md",null,{},{"icon":148},{"title":52,"description":1781},"P5S9P1vQP6eGThSHxzwnvrPQRlL2y7NhVsIJiIVboeg",[1789,1791],{"title":143,"path":144,"stem":145,"description":1790,"icon":131,"children":-1},"The realtime broadcast notification channel.",{"title":156,"path":157,"stem":158,"description":1792,"children":-1},"[object Object]",1785445889946]