[{"data":1,"prerenderedAt":2246},["ShallowReactive",2],{"navigation_docs_hu":3,"-hu-paginate-cursor":442,"-hu-paginate-cursor-surround":2243},[4,45,60,81,112,129,146,173,197,213,242,280,357,373,385,404,430],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Kezdő lépések","i-lucide-rocket","\u002Fhu\u002Fgetting-started","hu\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Bevezetés","\u002Fhu\u002Fgetting-started\u002Fintroduction","hu\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Laravelből érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-laravel","hu\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Symfonyból érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-symfony","hu\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Telepítés","\u002Fhu\u002Fgetting-started\u002Finstallation","hu\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Az első modulod","\u002Fhu\u002Fgetting-started\u002Ffirst-module","hu\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Projektstruktúra","\u002Fhu\u002Fgetting-started\u002Fproject-structure","hu\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"A shop mintaalkalmazás","\u002Fhu\u002Fgetting-started\u002Fsample-app","hu\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","\u002Fhu\u002Fqueue","hu\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Áttekintés","\u002Fhu\u002Fqueue\u002Foverview","hu\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Taskok","\u002Fhu\u002Fqueue\u002Ftasks","hu\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fhu\u002Fevents","hu\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Események","\u002Fhu\u002Fevents\u002Foverview","hu\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fhu\u002Fevents\u002Foutbox","hu\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Ütemezés","\u002Fhu\u002Fevents\u002Fscheduler","hu\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","\u002Fhu\u002Fauth","hu\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Autentikáció","\u002Fhu\u002Fauth\u002Foverview","hu\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fhu\u002Fauth\u002Frbac","hu\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policy-k","\u002Fhu\u002Fauth\u002Fpolicy","hu\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Az auth önálló használata","\u002Fhu\u002Fauth\u002Fstandalone","hu\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login goth-tal, önállóan","\u002Fhu\u002Fauth\u002Fsocial-standalone","hu\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","\u002Fhu\u002Fmail","hu\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fhu\u002Fmail\u002Foverview","hu\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fhu\u002Fmail\u002Fsmtp","hu\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fhu\u002Fmail\u002Fmjml","hu\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fhu\u002Fnotify","hu\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fhu\u002Fnotify\u002Foverview","hu\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database csatorna","\u002Fhu\u002Fnotify\u002Fdatabase","hu\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast csatorna","\u002Fhu\u002Fnotify\u002Fbroadcast","hu\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fhu\u002Fstorage","hu\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fhu\u002Fstorage\u002Foverview","hu\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fhu\u002Fstorage\u002Fdisk-api","hu\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memória és helyi lemez","\u002Fhu\u002Fstorage\u002Flocal","hu\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fhu\u002Fstorage\u002Fs3","hu\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Tesztelés","\u002Fhu\u002Fstorage\u002Ftesting","hu\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fhu\u002Ftelemetry","hu\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fhu\u002Ftelemetry\u002Foverview","hu\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logolás","\u002Fhu\u002Ftelemetry\u002Flogging","hu\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fhu\u002Ftelemetry\u002Fopentelemetry","hu\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fhu\u002Ftelemetry\u002Fsentry","hu\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Referencia","i-lucide-book-open","\u002Fhu\u002Freference","hu\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Konfiguráció","\u002Fhu\u002Freference\u002Fconfiguration","hu\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"Külső függőségek","\u002Fhu\u002Freference\u002Fdependencies","hu\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Koncepciók","i-lucide-lightbulb","\u002Fhu\u002Fconcepts","hu\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architektúra","\u002Fhu\u002Fconcepts\u002Farchitecture","hu\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Hibamodell","\u002Fhu\u002Fconcepts\u002Ferror-model","hu\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fhu\u002Fconcepts\u002Fconfiguration","hu\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fhu\u002Fconcepts\u002Fcodegen-pipeline","hu\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patternek","\u002Fhu\u002Fconcepts\u002Fdesign-patterns","hu\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"A kit","i-lucide-box","\u002Fhu\u002Fkit","hu\u002F3.kit",[248,252,257,262,267,271,276],{"title":249,"path":250,"stem":251,"icon":244},"A kit áttekintése","\u002Fhu\u002Fkit\u002Foverview","hu\u002F3.kit\u002F1.overview",{"title":253,"path":254,"stem":255,"icon":256},"Alkalmazás-életciklus","\u002Fhu\u002Fkit\u002Fapp","hu\u002F3.kit\u002F2.app","i-lucide-power",{"title":258,"path":259,"stem":260,"icon":261},"Szerver","\u002Fhu\u002Fkit\u002Fserver","hu\u002F3.kit\u002F3.server","i-lucide-server",{"title":263,"path":264,"stem":265,"icon":266},"Worker","\u002Fhu\u002Fkit\u002Fworker","hu\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":268,"path":269,"stem":270,"icon":70},"Realtime","\u002Fhu\u002Fkit\u002Frealtime","hu\u002F3.kit\u002F5.realtime",{"title":272,"path":273,"stem":274,"icon":275},"Migrációk","\u002Fhu\u002Fkit\u002Fmigrations","hu\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":277,"path":278,"stem":279,"icon":111},"Social login","\u002Fhu\u002Fkit\u002Fsocial-login","hu\u002F3.kit\u002F7.social-login",{"title":281,"icon":282,"path":283,"stem":284,"children":285,"page":44},"CLI referencia","i-lucide-terminal","\u002Fhu\u002Fcli","hu\u002F4.cli",[286,289,294,299,304,309,314,319,324,329,334,338,343,348,352],{"title":52,"path":287,"stem":288,"icon":282},"\u002Fhu\u002Fcli\u002Foverview","hu\u002F4.cli\u002F1.overview",{"title":290,"path":291,"stem":292,"icon":293},"add db","\u002Fhu\u002Fcli\u002Fadd-db","hu\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":295,"path":296,"stem":297,"icon":298},"add compose \u002F add docker","\u002Fhu\u002Fcli\u002Fadd-compose","hu\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":300,"path":301,"stem":302,"icon":303},"add mail","\u002Fhu\u002Fcli\u002Fadd-mail","hu\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":305,"path":306,"stem":307,"icon":308},"add notification","\u002Fhu\u002Fcli\u002Fadd-notification","hu\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":310,"path":311,"stem":312,"icon":313},"add realtime","\u002Fhu\u002Fcli\u002Fadd-realtime","hu\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":315,"path":316,"stem":317,"icon":318},"add seeder","\u002Fhu\u002Fcli\u002Fadd-seeder","hu\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":320,"path":321,"stem":322,"icon":323},"new project","\u002Fhu\u002Fcli\u002Fnew-project","hu\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":325,"path":326,"stem":327,"icon":328},"new module","\u002Fhu\u002Fcli\u002Fnew-module","hu\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":330,"path":331,"stem":332,"icon":333},"add surface","\u002Fhu\u002Fcli\u002Fadd-surface","hu\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":335,"path":336,"stem":337,"icon":244},"add core","\u002Fhu\u002Fcli\u002Fadd-core","hu\u002F4.cli\u002F5.add-core",{"title":339,"path":340,"stem":341,"icon":342},"add handler","\u002Fhu\u002Fcli\u002Fadd-handler","hu\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":344,"path":345,"stem":346,"icon":347},"new migration","\u002Fhu\u002Fcli\u002Fnew-migration","hu\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":349,"path":350,"stem":351,"icon":266},"worker generátorok","\u002Fhu\u002Fcli\u002Fworker-generators","hu\u002F4.cli\u002F8.worker-generators",{"title":353,"path":354,"stem":355,"icon":356},"upgrade templates","\u002Fhu\u002Fcli\u002Fupgrade-templates","hu\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":358,"icon":227,"path":359,"stem":360,"children":361,"page":44},"errs","\u002Fhu\u002Ferrs","hu\u002F5.errs",[362,365,369],{"title":52,"path":363,"stem":364,"icon":227},"\u002Fhu\u002Ferrs\u002Foverview","hu\u002F5.errs\u002F1.overview",{"title":366,"path":367,"stem":368},"API","\u002Fhu\u002Ferrs\u002Fapi","hu\u002F5.errs\u002F2.api",{"title":370,"path":371,"stem":372,"icon":227},"Integráció","\u002Fhu\u002Ferrs\u002Fintegration","hu\u002F5.errs\u002F3.integration",{"title":374,"icon":231,"path":375,"stem":376,"children":377,"page":44},"envconf","\u002Fhu\u002Fenvconf","hu\u002F6.envconf",[378,381],{"title":52,"path":379,"stem":380,"icon":231},"\u002Fhu\u002Fenvconf\u002Foverview","hu\u002F6.envconf\u002F1.overview",{"title":382,"path":383,"stem":384},"Receptek","\u002Fhu\u002Fenvconf\u002Frecipes","hu\u002F6.envconf\u002F2.recipes",{"title":386,"icon":387,"path":388,"stem":389,"children":390,"page":44},"httperr","i-lucide-globe","\u002Fhu\u002Fhttperr","hu\u002F7.httperr",[391,394,399],{"title":52,"path":392,"stem":393,"icon":387},"\u002Fhu\u002Fhttperr\u002Foverview","hu\u002F7.httperr\u002F1.overview",{"title":395,"path":396,"stem":397,"icon":398},"Hibaválaszok","\u002Fhu\u002Fhttperr\u002Ferror-responses","hu\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":400,"path":401,"stem":402,"icon":403},"Validáció","\u002Fhu\u002Fhttperr\u002Fvalidation","hu\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":405,"icon":406,"path":407,"stem":408,"children":409,"page":44},"dbx","i-lucide-database","\u002Fhu\u002Fdbx","hu\u002F8.dbx",[410,413,417,421,426],{"title":52,"path":411,"stem":412,"icon":406},"\u002Fhu\u002Fdbx\u002Foverview","hu\u002F8.dbx\u002F1.overview",{"title":414,"path":415,"stem":416,"icon":106},"pgx","\u002Fhu\u002Fdbx\u002Fpg","hu\u002F8.dbx\u002F2.pg",{"title":418,"path":419,"stem":420,"icon":47},"bun","\u002Fhu\u002Fdbx\u002Fbunx","hu\u002F8.dbx\u002F3.bunx",{"title":422,"path":423,"stem":424,"icon":425},"Tranzakciók","\u002Fhu\u002Fdbx\u002Ftransactions","hu\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":427,"path":428,"stem":429,"icon":318},"Seederek","\u002Fhu\u002Fdbx\u002Fseed","hu\u002F8.dbx\u002F5.seed",{"title":431,"icon":55,"path":432,"stem":433,"children":434,"page":44},"paginate","\u002Fhu\u002Fpaginate","hu\u002F9.paginate",[435,438],{"title":52,"path":436,"stem":437,"icon":55},"\u002Fhu\u002Fpaginate\u002Foverview","hu\u002F9.paginate\u002F1.overview",{"title":439,"path":440,"stem":441,"icon":19},"Cursor-lapozás","\u002Fhu\u002Fpaginate\u002Fcursor","hu\u002F9.paginate\u002F2.cursor",{"id":443,"title":439,"body":444,"description":2236,"extension":2237,"links":2238,"meta":2239,"navigation":2240,"path":440,"seo":2241,"stem":441,"__hash__":2242},"docs_hu\u002Fhu\u002F9.paginate\u002F2.cursor.md",{"type":445,"value":446,"toc":2228},"minimark",[447,478,875,917,922,932,1155,1356,1913,1956,1960,1967,2023,2027,2045,2064,2082,2086,2170,2176,2180,2207,2211,2224],[448,449,450,451,455,456,460,461,465,466,469,470,473,474,477],"p",{},"Az ",[452,453,454],"a",{"href":436},"offset lapozásnak"," két strukturális baja van nagy vagy gyakran módosuló táblákon: az ",[457,458,459],"code",{},"OFFSET n"," minden kérésnél kiszámolja és ",[462,463,464],"strong",{},"eldobja"," az első ",[457,467,468],{},"n"," sort (O(n), a 400. oldal 8000 sor átfésülése), és konkurens beszúrások alatt a lapok ",[462,471,472],{},"elcsúsznak",": ugyanaz a sor két oldalon jelenik meg, vagy egyiken sem. A cursor- (keyset-) lapozás mindkettőt megoldja: a kliens egy opak kurzort kap, ami az utoljára látott sor rendezőkulcsát kódolja, és a következő lap egy indexelt seekkel (",[457,475,476],{},"WHERE (created_at, id) \u003C (...)",") folytatódik onnan, közel konstans költséggel, akármilyen mélyre lapozol.",[479,480,485],"pre",{"className":481,"code":482,"language":483,"meta":484,"style":484},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","func NormalizeCursor(cursor *string, limit *int, sort string, opts ...Option) (CursorParams, error)\n\ntype CursorParams struct{ Limit int \u002F* + dekódolt kulcsok *\u002F }\nfunc (p CursorParams) HasCursor() bool          \u002F\u002F van-e cursor, azaz nem első oldal-e\nfunc (p CursorParams) DecodeKey(dests ...any) error \u002F\u002F kulcsértékek kiolvasása, Scan-szerűen\nfunc (p CursorParams) FetchLimit() int          \u002F\u002F Limit+1, ebből tudjuk, van-e következő oldal\nfunc (p CursorParams) NextCursor(keys ...any) (string, error)\n\nfunc NewCursorPage[T any](rows []T, p CursorParams, key func(last T) []any) (CursorPage[T], error)\n\ntype CursorPage[T any] struct {\n    Items      []T\n    NextCursor string \u002F\u002F \"\" az utolsó oldalon\n    HasMore    bool\n}\n\nvar ErrInvalidCursor \u002F\u002F errs definition: HTTP 400, kód: paginate_invalid_cursor\n","go","",[457,486,487,562,569,594,620,653,677,714,719,792,797,820,832,843,852,858,863],{"__ignoreMap":484},[488,489,492,496,500,503,507,510,514,517,520,522,525,527,530,533,535,538,541,545,548,551,554,556,559],"span",{"class":490,"line":491},"line",1,[488,493,495],{"class":494},"sMK4o","func",[488,497,499],{"class":498},"s2Zo4"," NormalizeCursor",[488,501,502],{"class":494},"(",[488,504,506],{"class":505},"sHdIc","cursor",[488,508,509],{"class":494}," *",[488,511,513],{"class":512},"spNyl","string",[488,515,516],{"class":494},",",[488,518,519],{"class":505}," limit",[488,521,509],{"class":494},[488,523,524],{"class":512},"int",[488,526,516],{"class":494},[488,528,529],{"class":505}," sort",[488,531,532],{"class":512}," string",[488,534,516],{"class":494},[488,536,537],{"class":505}," opts",[488,539,540],{"class":494}," ...",[488,542,544],{"class":543},"sBMFI","Option",[488,546,547],{"class":494},")",[488,549,550],{"class":494}," (",[488,552,553],{"class":543},"CursorParams",[488,555,516],{"class":494},[488,557,558],{"class":512}," error",[488,560,561],{"class":494},")\n",[488,563,565],{"class":490,"line":564},2,[488,566,568],{"emptyLinePlaceholder":567},true,"\n",[488,570,572,575,578,581,585,587,591],{"class":490,"line":571},3,[488,573,574],{"class":494},"type",[488,576,577],{"class":543}," CursorParams",[488,579,580],{"class":494}," struct{",[488,582,584],{"class":583},"sTEyZ"," Limit ",[488,586,524],{"class":512},[488,588,590],{"class":589},"sHwdD"," \u002F* + dekódolt kulcsok *\u002F",[488,592,593],{"class":494}," }\n",[488,595,597,599,601,604,606,608,611,614,617],{"class":490,"line":596},4,[488,598,495],{"class":494},[488,600,550],{"class":494},[488,602,603],{"class":505},"p ",[488,605,553],{"class":543},[488,607,547],{"class":494},[488,609,610],{"class":498}," HasCursor",[488,612,613],{"class":494},"()",[488,615,616],{"class":512}," bool",[488,618,619],{"class":589},"          \u002F\u002F van-e cursor, azaz nem első oldal-e\n",[488,621,623,625,627,629,631,633,636,638,641,643,646,648,650],{"class":490,"line":622},5,[488,624,495],{"class":494},[488,626,550],{"class":494},[488,628,603],{"class":505},[488,630,553],{"class":543},[488,632,547],{"class":494},[488,634,635],{"class":498}," DecodeKey",[488,637,502],{"class":494},[488,639,640],{"class":505},"dests",[488,642,540],{"class":494},[488,644,645],{"class":543},"any",[488,647,547],{"class":494},[488,649,558],{"class":512},[488,651,652],{"class":589}," \u002F\u002F kulcsértékek kiolvasása, Scan-szerűen\n",[488,654,656,658,660,662,664,666,669,671,674],{"class":490,"line":655},6,[488,657,495],{"class":494},[488,659,550],{"class":494},[488,661,603],{"class":505},[488,663,553],{"class":543},[488,665,547],{"class":494},[488,667,668],{"class":498}," FetchLimit",[488,670,613],{"class":494},[488,672,673],{"class":512}," int",[488,675,676],{"class":589},"          \u002F\u002F Limit+1, ebből tudjuk, van-e következő oldal\n",[488,678,680,682,684,686,688,690,693,695,698,700,702,704,706,708,710,712],{"class":490,"line":679},7,[488,681,495],{"class":494},[488,683,550],{"class":494},[488,685,603],{"class":505},[488,687,553],{"class":543},[488,689,547],{"class":494},[488,691,692],{"class":498}," NextCursor",[488,694,502],{"class":494},[488,696,697],{"class":505},"keys",[488,699,540],{"class":494},[488,701,645],{"class":543},[488,703,547],{"class":494},[488,705,550],{"class":494},[488,707,513],{"class":512},[488,709,516],{"class":494},[488,711,558],{"class":512},[488,713,561],{"class":494},[488,715,717],{"class":490,"line":716},8,[488,718,568],{"emptyLinePlaceholder":567},[488,720,722,724,727,730,733,736,739,742,745,747,749,752,754,756,759,762,765,768,770,772,774,776,778,781,783,785,788,790],{"class":490,"line":721},9,[488,723,495],{"class":494},[488,725,726],{"class":498}," NewCursorPage",[488,728,729],{"class":494},"[",[488,731,732],{"class":505},"T",[488,734,735],{"class":543}," any",[488,737,738],{"class":494},"](",[488,740,741],{"class":505},"rows",[488,743,744],{"class":494}," []",[488,746,732],{"class":543},[488,748,516],{"class":494},[488,750,751],{"class":505}," p",[488,753,577],{"class":543},[488,755,516],{"class":494},[488,757,758],{"class":505}," key",[488,760,761],{"class":494}," func(",[488,763,764],{"class":505},"last",[488,766,767],{"class":543}," T",[488,769,547],{"class":494},[488,771,744],{"class":494},[488,773,645],{"class":543},[488,775,547],{"class":494},[488,777,550],{"class":494},[488,779,780],{"class":543},"CursorPage",[488,782,729],{"class":494},[488,784,732],{"class":543},[488,786,787],{"class":494},"],",[488,789,558],{"class":512},[488,791,561],{"class":494},[488,793,795],{"class":490,"line":794},10,[488,796,568],{"emptyLinePlaceholder":567},[488,798,800,802,805,807,809,811,814,817],{"class":490,"line":799},11,[488,801,574],{"class":494},[488,803,804],{"class":543}," CursorPage",[488,806,729],{"class":494},[488,808,732],{"class":505},[488,810,735],{"class":543},[488,812,813],{"class":494},"]",[488,815,816],{"class":494}," struct",[488,818,819],{"class":494}," {\n",[488,821,823,826,829],{"class":490,"line":822},12,[488,824,825],{"class":583},"    Items      ",[488,827,828],{"class":494},"[]",[488,830,831],{"class":543},"T\n",[488,833,835,838,840],{"class":490,"line":834},13,[488,836,837],{"class":583},"    NextCursor ",[488,839,513],{"class":512},[488,841,842],{"class":589}," \u002F\u002F \"\" az utolsó oldalon\n",[488,844,846,849],{"class":490,"line":845},14,[488,847,848],{"class":583},"    HasMore    ",[488,850,851],{"class":512},"bool\n",[488,853,855],{"class":490,"line":854},15,[488,856,857],{"class":494},"}\n",[488,859,861],{"class":490,"line":860},16,[488,862,568],{"emptyLinePlaceholder":567},[488,864,866,869,872],{"class":490,"line":865},17,[488,867,868],{"class":494},"var",[488,870,871],{"class":583}," ErrInvalidCursor ",[488,873,874],{"class":589},"\u002F\u002F errs definition: HTTP 400, kód: paginate_invalid_cursor\n",[448,876,877,878,881,882,885,886,889,890,893,894,900,901,904,905,908,909,912,913,916],{},"A ",[457,879,880],{},"NormalizeCursor"," a ",[457,883,884],{},"limit","-et ugyanazokkal a ",[457,887,888],{},"WithDefaultPerPage","\u002F",[457,891,892],{},"WithMaxPerPage"," opciókkal szorítja határok közé, mint a ",[452,895,897],{"href":896},"\u002Fhu\u002Fpaginate\u002Foverview#offset-lapoz%C3%A1s",[457,898,899],{},"Normalize"," (a ",[457,902,903],{},"WithMaxPage","-et ignorálja, itt nincs page number). A ",[457,906,907],{},"sort"," argumentum ",[462,910,911],{},"pontosan"," az az ",[457,914,915],{},"ORDER BY"," kifejezés legyen, amit a query használ: a kiadott cursorba ennek ujjlenyomata kerül, és egy más rendezéshez kiadott cursor később elutasításra kerül.",[918,919,921],"h2",{"id":920},"a-shop-terméklistája-végig","A shop terméklistája, végig",[448,923,877,924,927,928,931],{},[457,925,926],{},"GET \u002Fapi\u002Fv1\u002Fshop\u002Fproducts?cursor=...&limit=..."," teljes útja a ",[452,929,930],{"href":41},"mintaalkalmazásban",", handler → service → repository → válasz:",[479,933,936],{"className":481,"code":934,"filename":935,"language":483,"meta":484,"style":484},"func (h *Handler) ListProducts(ctx context.Context, req gen.ListProductsRequest) (gen.ListProductsResponse, error) {\n    page, err := h.svc.ListProducts(ctx, req.Params.Cursor, req.Params.Limit)\n    if err != nil {\n        return nil, service.ErrListProducts.Wrap(err, \"api: list products\")\n    }\n    return mapper.ToProductList(page), nil \u002F\u002F paginate.CursorPage[Product] → gen.CursorPageProduct\n}\n","internal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fhttp\u002Fhandler.go",[457,937,938,1005,1064,1080,1120,1125,1151],{"__ignoreMap":484},[488,939,940,942,944,947,950,953,955,958,960,963,966,969,972,974,977,980,982,985,987,989,992,994,997,999,1001,1003],{"class":490,"line":491},[488,941,495],{"class":494},[488,943,550],{"class":494},[488,945,946],{"class":505},"h ",[488,948,949],{"class":494},"*",[488,951,952],{"class":543},"Handler",[488,954,547],{"class":494},[488,956,957],{"class":498}," ListProducts",[488,959,502],{"class":494},[488,961,962],{"class":505},"ctx",[488,964,965],{"class":543}," context",[488,967,968],{"class":494},".",[488,970,971],{"class":543},"Context",[488,973,516],{"class":494},[488,975,976],{"class":505}," req",[488,978,979],{"class":543}," gen",[488,981,968],{"class":494},[488,983,984],{"class":543},"ListProductsRequest",[488,986,547],{"class":494},[488,988,550],{"class":494},[488,990,991],{"class":543},"gen",[488,993,968],{"class":494},[488,995,996],{"class":543},"ListProductsResponse",[488,998,516],{"class":494},[488,1000,558],{"class":512},[488,1002,547],{"class":494},[488,1004,819],{"class":494},[488,1006,1007,1010,1012,1015,1018,1021,1023,1026,1028,1031,1033,1035,1037,1039,1041,1044,1046,1049,1051,1053,1055,1057,1059,1062],{"class":490,"line":564},[488,1008,1009],{"class":583},"    page",[488,1011,516],{"class":494},[488,1013,1014],{"class":583}," err ",[488,1016,1017],{"class":494},":=",[488,1019,1020],{"class":583}," h",[488,1022,968],{"class":494},[488,1024,1025],{"class":583},"svc",[488,1027,968],{"class":494},[488,1029,1030],{"class":498},"ListProducts",[488,1032,502],{"class":494},[488,1034,962],{"class":583},[488,1036,516],{"class":494},[488,1038,976],{"class":583},[488,1040,968],{"class":494},[488,1042,1043],{"class":583},"Params",[488,1045,968],{"class":494},[488,1047,1048],{"class":583},"Cursor",[488,1050,516],{"class":494},[488,1052,976],{"class":583},[488,1054,968],{"class":494},[488,1056,1043],{"class":583},[488,1058,968],{"class":494},[488,1060,1061],{"class":583},"Limit",[488,1063,561],{"class":494},[488,1065,1066,1070,1072,1075,1078],{"class":490,"line":571},[488,1067,1069],{"class":1068},"s7zQu","    if",[488,1071,1014],{"class":583},[488,1073,1074],{"class":494},"!=",[488,1076,1077],{"class":494}," nil",[488,1079,819],{"class":494},[488,1081,1082,1085,1088,1091,1093,1096,1098,1101,1103,1106,1108,1111,1115,1118],{"class":490,"line":596},[488,1083,1084],{"class":1068},"        return",[488,1086,1087],{"class":494}," nil,",[488,1089,1090],{"class":583}," service",[488,1092,968],{"class":494},[488,1094,1095],{"class":583},"ErrListProducts",[488,1097,968],{"class":494},[488,1099,1100],{"class":498},"Wrap",[488,1102,502],{"class":494},[488,1104,1105],{"class":583},"err",[488,1107,516],{"class":494},[488,1109,1110],{"class":494}," \"",[488,1112,1114],{"class":1113},"sfazB","api: list products",[488,1116,1117],{"class":494},"\"",[488,1119,561],{"class":494},[488,1121,1122],{"class":490,"line":622},[488,1123,1124],{"class":494},"    }\n",[488,1126,1127,1130,1133,1135,1138,1140,1143,1146,1148],{"class":490,"line":655},[488,1128,1129],{"class":1068},"    return",[488,1131,1132],{"class":583}," mapper",[488,1134,968],{"class":494},[488,1136,1137],{"class":498},"ToProductList",[488,1139,502],{"class":494},[488,1141,1142],{"class":583},"page",[488,1144,1145],{"class":494},"),",[488,1147,1077],{"class":494},[488,1149,1150],{"class":589}," \u002F\u002F paginate.CursorPage[Product] → gen.CursorPageProduct\n",[488,1152,1153],{"class":490,"line":679},[488,1154,857],{"class":494},[479,1156,1159],{"className":481,"code":1157,"filename":1158,"language":483,"meta":484,"style":484},"const productSort = \"created_at DESC, id DESC\" \u002F\u002F egyezzen a repository ORDER BY-jával\n\nfunc (s *Service) ListProducts(ctx context.Context, cursor *string, limit *int) (paginate.CursorPage[Product], error) {\n    p, err := paginate.NormalizeCursor(cursor, limit, productSort)\n    if err != nil {\n        return paginate.CursorPage[Product]{}, err \u002F\u002F ErrInvalidCursor → HTTP 400\n    }\n    return s.products.List(ctx, p)\n}\n","internal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fservice\u002Fservice.go",[457,1160,1161,1182,1186,1254,1287,1299,1321,1325,1352],{"__ignoreMap":484},[488,1162,1163,1166,1169,1172,1174,1177,1179],{"class":490,"line":491},[488,1164,1165],{"class":494},"const",[488,1167,1168],{"class":583}," productSort ",[488,1170,1171],{"class":494},"=",[488,1173,1110],{"class":494},[488,1175,1176],{"class":1113},"created_at DESC, id DESC",[488,1178,1117],{"class":494},[488,1180,1181],{"class":589}," \u002F\u002F egyezzen a repository ORDER BY-jával\n",[488,1183,1184],{"class":490,"line":564},[488,1185,568],{"emptyLinePlaceholder":567},[488,1187,1188,1190,1192,1195,1197,1200,1202,1204,1206,1208,1210,1212,1214,1216,1219,1221,1223,1225,1227,1229,1231,1233,1235,1237,1239,1241,1243,1246,1248,1250,1252],{"class":490,"line":571},[488,1189,495],{"class":494},[488,1191,550],{"class":494},[488,1193,1194],{"class":505},"s ",[488,1196,949],{"class":494},[488,1198,1199],{"class":543},"Service",[488,1201,547],{"class":494},[488,1203,957],{"class":498},[488,1205,502],{"class":494},[488,1207,962],{"class":505},[488,1209,965],{"class":543},[488,1211,968],{"class":494},[488,1213,971],{"class":543},[488,1215,516],{"class":494},[488,1217,1218],{"class":505}," cursor",[488,1220,509],{"class":494},[488,1222,513],{"class":512},[488,1224,516],{"class":494},[488,1226,519],{"class":505},[488,1228,509],{"class":494},[488,1230,524],{"class":512},[488,1232,547],{"class":494},[488,1234,550],{"class":494},[488,1236,431],{"class":543},[488,1238,968],{"class":494},[488,1240,780],{"class":543},[488,1242,729],{"class":494},[488,1244,1245],{"class":543},"Product",[488,1247,787],{"class":494},[488,1249,558],{"class":512},[488,1251,547],{"class":494},[488,1253,819],{"class":494},[488,1255,1256,1259,1261,1263,1265,1268,1270,1272,1274,1276,1278,1280,1282,1285],{"class":490,"line":596},[488,1257,1258],{"class":583},"    p",[488,1260,516],{"class":494},[488,1262,1014],{"class":583},[488,1264,1017],{"class":494},[488,1266,1267],{"class":583}," paginate",[488,1269,968],{"class":494},[488,1271,880],{"class":498},[488,1273,502],{"class":494},[488,1275,506],{"class":583},[488,1277,516],{"class":494},[488,1279,519],{"class":583},[488,1281,516],{"class":494},[488,1283,1284],{"class":583}," productSort",[488,1286,561],{"class":494},[488,1288,1289,1291,1293,1295,1297],{"class":490,"line":622},[488,1290,1069],{"class":1068},[488,1292,1014],{"class":583},[488,1294,1074],{"class":494},[488,1296,1077],{"class":494},[488,1298,819],{"class":494},[488,1300,1301,1303,1305,1307,1309,1311,1313,1316,1318],{"class":490,"line":655},[488,1302,1084],{"class":1068},[488,1304,1267],{"class":543},[488,1306,968],{"class":494},[488,1308,780],{"class":543},[488,1310,729],{"class":494},[488,1312,1245],{"class":543},[488,1314,1315],{"class":494},"]{},",[488,1317,1014],{"class":583},[488,1319,1320],{"class":589},"\u002F\u002F ErrInvalidCursor → HTTP 400\n",[488,1322,1323],{"class":490,"line":679},[488,1324,1124],{"class":494},[488,1326,1327,1329,1332,1334,1337,1339,1342,1344,1346,1348,1350],{"class":490,"line":716},[488,1328,1129],{"class":1068},[488,1330,1331],{"class":583}," s",[488,1333,968],{"class":494},[488,1335,1336],{"class":583},"products",[488,1338,968],{"class":494},[488,1340,1341],{"class":498},"List",[488,1343,502],{"class":494},[488,1345,962],{"class":583},[488,1347,516],{"class":494},[488,1349,751],{"class":583},[488,1351,561],{"class":494},[488,1353,1354],{"class":490,"line":721},[488,1355,857],{"class":494},[479,1357,1360],{"className":481,"code":1358,"filename":1359,"language":483,"meta":484,"style":484},"func (r *Products) List(ctx context.Context, p paginate.CursorParams) (paginate.CursorPage[Product], error) {\n    query := `SELECT id, name, price_cents, created_at FROM products`\n    args := []any{p.FetchLimit()}\n\n    if p.HasCursor() {\n        var createdAt time.Time\n        var id string\n        if err := p.DecodeKey(&createdAt, &id); err != nil {\n            return paginate.CursorPage[Product]{}, err\n        }\n        query += ` WHERE (created_at, id) \u003C ($2, $3)`\n        args = append(args, createdAt, id)\n    }\n    query += ` ORDER BY created_at DESC, id DESC LIMIT $1`\n\n    rows, err := r.db.Query(ctx, query, args...)\n    if err != nil {\n        return paginate.CursorPage[Product]{}, errs.Wrap(err, \"products: list\")\n    }\n    products, err := pgx.CollectRows(rows, pgx.RowToStructByName[Product])\n    if err != nil {\n        return paginate.CursorPage[Product]{}, errs.Wrap(err, \"products: scan\")\n    }\n\n    return paginate.NewCursorPage(products, p, func(last Product) []any {\n        return []any{last.CreatedAt, last.ID}\n    })\n}\n","internal\u002Fmodules\u002Fshop\u002Frepository\u002Fproducts.go",[457,1361,1362,1423,1439,1463,1467,1482,1498,1508,1549,1569,1574,1589,1616,1620,1633,1637,1678,1690,1729,1734,1774,1787,1825,1830,1835,1872,1902,1908],{"__ignoreMap":484},[488,1363,1364,1366,1368,1371,1373,1376,1378,1381,1383,1385,1387,1389,1391,1393,1395,1397,1399,1401,1403,1405,1407,1409,1411,1413,1415,1417,1419,1421],{"class":490,"line":491},[488,1365,495],{"class":494},[488,1367,550],{"class":494},[488,1369,1370],{"class":505},"r ",[488,1372,949],{"class":494},[488,1374,1375],{"class":543},"Products",[488,1377,547],{"class":494},[488,1379,1380],{"class":498}," List",[488,1382,502],{"class":494},[488,1384,962],{"class":505},[488,1386,965],{"class":543},[488,1388,968],{"class":494},[488,1390,971],{"class":543},[488,1392,516],{"class":494},[488,1394,751],{"class":505},[488,1396,1267],{"class":543},[488,1398,968],{"class":494},[488,1400,553],{"class":543},[488,1402,547],{"class":494},[488,1404,550],{"class":494},[488,1406,431],{"class":543},[488,1408,968],{"class":494},[488,1410,780],{"class":543},[488,1412,729],{"class":494},[488,1414,1245],{"class":543},[488,1416,787],{"class":494},[488,1418,558],{"class":512},[488,1420,547],{"class":494},[488,1422,819],{"class":494},[488,1424,1425,1428,1430,1433,1436],{"class":490,"line":564},[488,1426,1427],{"class":583},"    query ",[488,1429,1017],{"class":494},[488,1431,1432],{"class":494}," `",[488,1434,1435],{"class":1113},"SELECT id, name, price_cents, created_at FROM products",[488,1437,1438],{"class":494},"`\n",[488,1440,1441,1444,1446,1448,1450,1453,1455,1457,1460],{"class":490,"line":571},[488,1442,1443],{"class":583},"    args ",[488,1445,1017],{"class":494},[488,1447,744],{"class":494},[488,1449,645],{"class":543},[488,1451,1452],{"class":494},"{",[488,1454,448],{"class":583},[488,1456,968],{"class":494},[488,1458,1459],{"class":498},"FetchLimit",[488,1461,1462],{"class":494},"()}\n",[488,1464,1465],{"class":490,"line":596},[488,1466,568],{"emptyLinePlaceholder":567},[488,1468,1469,1471,1473,1475,1478,1480],{"class":490,"line":622},[488,1470,1069],{"class":1068},[488,1472,751],{"class":583},[488,1474,968],{"class":494},[488,1476,1477],{"class":498},"HasCursor",[488,1479,613],{"class":494},[488,1481,819],{"class":494},[488,1483,1484,1487,1490,1493,1495],{"class":490,"line":655},[488,1485,1486],{"class":494},"        var",[488,1488,1489],{"class":583}," createdAt ",[488,1491,1492],{"class":543},"time",[488,1494,968],{"class":494},[488,1496,1497],{"class":543},"Time\n",[488,1499,1500,1502,1505],{"class":490,"line":679},[488,1501,1486],{"class":494},[488,1503,1504],{"class":583}," id ",[488,1506,1507],{"class":512},"string\n",[488,1509,1510,1513,1515,1517,1519,1521,1524,1527,1530,1532,1535,1538,1541,1543,1545,1547],{"class":490,"line":716},[488,1511,1512],{"class":1068},"        if",[488,1514,1014],{"class":583},[488,1516,1017],{"class":494},[488,1518,751],{"class":583},[488,1520,968],{"class":494},[488,1522,1523],{"class":498},"DecodeKey",[488,1525,1526],{"class":494},"(&",[488,1528,1529],{"class":583},"createdAt",[488,1531,516],{"class":494},[488,1533,1534],{"class":494}," &",[488,1536,1537],{"class":583},"id",[488,1539,1540],{"class":494},");",[488,1542,1014],{"class":583},[488,1544,1074],{"class":494},[488,1546,1077],{"class":494},[488,1548,819],{"class":494},[488,1550,1551,1554,1556,1558,1560,1562,1564,1566],{"class":490,"line":721},[488,1552,1553],{"class":1068},"            return",[488,1555,1267],{"class":543},[488,1557,968],{"class":494},[488,1559,780],{"class":543},[488,1561,729],{"class":494},[488,1563,1245],{"class":543},[488,1565,1315],{"class":494},[488,1567,1568],{"class":583}," err\n",[488,1570,1571],{"class":490,"line":794},[488,1572,1573],{"class":494},"        }\n",[488,1575,1576,1579,1582,1584,1587],{"class":490,"line":799},[488,1577,1578],{"class":583},"        query ",[488,1580,1581],{"class":494},"+=",[488,1583,1432],{"class":494},[488,1585,1586],{"class":1113}," WHERE (created_at, id) \u003C ($2, $3)",[488,1588,1438],{"class":494},[488,1590,1591,1594,1596,1599,1601,1604,1606,1609,1611,1614],{"class":490,"line":822},[488,1592,1593],{"class":583},"        args ",[488,1595,1171],{"class":494},[488,1597,1598],{"class":498}," append",[488,1600,502],{"class":494},[488,1602,1603],{"class":583},"args",[488,1605,516],{"class":494},[488,1607,1608],{"class":583}," createdAt",[488,1610,516],{"class":494},[488,1612,1613],{"class":583}," id",[488,1615,561],{"class":494},[488,1617,1618],{"class":490,"line":834},[488,1619,1124],{"class":494},[488,1621,1622,1624,1626,1628,1631],{"class":490,"line":845},[488,1623,1427],{"class":583},[488,1625,1581],{"class":494},[488,1627,1432],{"class":494},[488,1629,1630],{"class":1113}," ORDER BY created_at DESC, id DESC LIMIT $1",[488,1632,1438],{"class":494},[488,1634,1635],{"class":490,"line":854},[488,1636,568],{"emptyLinePlaceholder":567},[488,1638,1639,1642,1644,1646,1648,1651,1653,1656,1658,1661,1663,1665,1667,1670,1672,1675],{"class":490,"line":860},[488,1640,1641],{"class":583},"    rows",[488,1643,516],{"class":494},[488,1645,1014],{"class":583},[488,1647,1017],{"class":494},[488,1649,1650],{"class":583}," r",[488,1652,968],{"class":494},[488,1654,1655],{"class":583},"db",[488,1657,968],{"class":494},[488,1659,1660],{"class":498},"Query",[488,1662,502],{"class":494},[488,1664,962],{"class":583},[488,1666,516],{"class":494},[488,1668,1669],{"class":583}," query",[488,1671,516],{"class":494},[488,1673,1674],{"class":583}," args",[488,1676,1677],{"class":494},"...)\n",[488,1679,1680,1682,1684,1686,1688],{"class":490,"line":865},[488,1681,1069],{"class":1068},[488,1683,1014],{"class":583},[488,1685,1074],{"class":494},[488,1687,1077],{"class":494},[488,1689,819],{"class":494},[488,1691,1693,1695,1697,1699,1701,1703,1705,1707,1710,1712,1714,1716,1718,1720,1722,1725,1727],{"class":490,"line":1692},18,[488,1694,1084],{"class":1068},[488,1696,1267],{"class":543},[488,1698,968],{"class":494},[488,1700,780],{"class":543},[488,1702,729],{"class":494},[488,1704,1245],{"class":543},[488,1706,1315],{"class":494},[488,1708,1709],{"class":583}," errs",[488,1711,968],{"class":494},[488,1713,1100],{"class":498},[488,1715,502],{"class":494},[488,1717,1105],{"class":583},[488,1719,516],{"class":494},[488,1721,1110],{"class":494},[488,1723,1724],{"class":1113},"products: list",[488,1726,1117],{"class":494},[488,1728,561],{"class":494},[488,1730,1732],{"class":490,"line":1731},19,[488,1733,1124],{"class":494},[488,1735,1737,1740,1742,1744,1746,1749,1751,1754,1756,1758,1760,1762,1764,1767,1769,1771],{"class":490,"line":1736},20,[488,1738,1739],{"class":583},"    products",[488,1741,516],{"class":494},[488,1743,1014],{"class":583},[488,1745,1017],{"class":494},[488,1747,1748],{"class":583}," pgx",[488,1750,968],{"class":494},[488,1752,1753],{"class":498},"CollectRows",[488,1755,502],{"class":494},[488,1757,741],{"class":583},[488,1759,516],{"class":494},[488,1761,1748],{"class":583},[488,1763,968],{"class":494},[488,1765,1766],{"class":583},"RowToStructByName",[488,1768,729],{"class":494},[488,1770,1245],{"class":583},[488,1772,1773],{"class":494},"])\n",[488,1775,1777,1779,1781,1783,1785],{"class":490,"line":1776},21,[488,1778,1069],{"class":1068},[488,1780,1014],{"class":583},[488,1782,1074],{"class":494},[488,1784,1077],{"class":494},[488,1786,819],{"class":494},[488,1788,1790,1792,1794,1796,1798,1800,1802,1804,1806,1808,1810,1812,1814,1816,1818,1821,1823],{"class":490,"line":1789},22,[488,1791,1084],{"class":1068},[488,1793,1267],{"class":543},[488,1795,968],{"class":494},[488,1797,780],{"class":543},[488,1799,729],{"class":494},[488,1801,1245],{"class":543},[488,1803,1315],{"class":494},[488,1805,1709],{"class":583},[488,1807,968],{"class":494},[488,1809,1100],{"class":498},[488,1811,502],{"class":494},[488,1813,1105],{"class":583},[488,1815,516],{"class":494},[488,1817,1110],{"class":494},[488,1819,1820],{"class":1113},"products: scan",[488,1822,1117],{"class":494},[488,1824,561],{"class":494},[488,1826,1828],{"class":490,"line":1827},23,[488,1829,1124],{"class":494},[488,1831,1833],{"class":490,"line":1832},24,[488,1834,568],{"emptyLinePlaceholder":567},[488,1836,1838,1840,1842,1844,1847,1849,1851,1853,1855,1857,1859,1861,1864,1866,1868,1870],{"class":490,"line":1837},25,[488,1839,1129],{"class":1068},[488,1841,1267],{"class":583},[488,1843,968],{"class":494},[488,1845,1846],{"class":498},"NewCursorPage",[488,1848,502],{"class":494},[488,1850,1336],{"class":583},[488,1852,516],{"class":494},[488,1854,751],{"class":583},[488,1856,516],{"class":494},[488,1858,761],{"class":494},[488,1860,764],{"class":505},[488,1862,1863],{"class":543}," Product",[488,1865,547],{"class":494},[488,1867,744],{"class":494},[488,1869,645],{"class":543},[488,1871,819],{"class":494},[488,1873,1875,1877,1879,1881,1883,1885,1887,1890,1892,1895,1897,1900],{"class":490,"line":1874},26,[488,1876,1084],{"class":1068},[488,1878,744],{"class":494},[488,1880,645],{"class":543},[488,1882,1452],{"class":494},[488,1884,764],{"class":583},[488,1886,968],{"class":494},[488,1888,1889],{"class":583},"CreatedAt",[488,1891,516],{"class":494},[488,1893,1894],{"class":583}," last",[488,1896,968],{"class":494},[488,1898,1899],{"class":583},"ID",[488,1901,857],{"class":494},[488,1903,1905],{"class":490,"line":1904},27,[488,1906,1907],{"class":494},"    })\n",[488,1909,1911],{"class":490,"line":1910},28,[488,1912,857],{"class":494},[448,1914,1915,1916,1919,1920,1923,1924,1927,1928,1930,1931,1933,1934,1937,1938,881,1941,1944,1945,1948,1949,1952,1953,1955],{},"A mechanika kulcsa a ",[462,1917,1918],{},"+1 sor",": a query a ",[457,1921,1922],{},"FetchLimit()","-et (= ",[457,1925,1926],{},"Limit+1",") kéri, a ",[457,1929,1846],{}," pedig levágja a lapot ",[457,1932,1061],{}," elemre. Ha az extra sor megvolt, ",[457,1935,1936],{},"HasMore = true",", és a ",[457,1939,1940],{},"NextCursor",[462,1942,1943],{},"ténylegesen visszaadott utolsó"," elem kulcsából épül: külön ",[457,1946,1947],{},"COUNT"," query nincs. A ",[457,1950,1951],{},"key"," függvény pontosan azokat az értékeket adja vissza, pontosan abban a sorrendben, amiket az ",[457,1954,915],{}," \u002F seek-predikátum használ.",[918,1957,1959],{"id":1958},"a-seek-predikátum-feltételei","A seek-predikátum feltételei",[448,1961,1962,1963,1966],{},"A Postgres sor-érték összehasonlítás (",[457,1964,1965],{},"(created_at, id) \u003C ($2, $3)",") csak akkor helyes és gyors, ha:",[1968,1969,1970,1984,2000,2010],"ul",{},[1971,1972,1973,1976,1977,889,1980,1983],"li",{},[462,1974,1975],{},"egyirányú a rendezés"," minden kulcsoszlopon: vegyes ",[457,1978,1979],{},"ASC",[457,1981,1982],{},"DESC"," tuple-összehasonlítással nem fejezhető ki;",[1971,1985,1986,1992,1993,1996,1997,1999],{},[462,1987,1988,1991],{},[457,1989,1990],{},"NOT NULL"," minden kulcsoszlop",": egy ",[457,1994,1995],{},"NULL"," tuple-elem az egész összehasonlítást ",[457,1998,1995],{},"-lá teszi, ami észrevétlenül kihagyja a sort minden oldalról;",[1971,2001,2002,2005,2006,2009],{},[462,2003,2004],{},"egyedi tiebreaker az utolsó kulcs",": jellemzően a primary key, hogy egy nem egyedi vezető oszlop (pl. ",[457,2007,2008],{},"created_at",") ne okozzon kihagyott vagy duplikált sorokat az oldalhatárokon;",[1971,2011,2012,2018,2019,2022],{},[462,2013,2014,2015,2017],{},"az ",[457,2016,915],{},"-nak megfelelő összetett index"," létezik (a shopban: ",[457,2020,2021],{},"CREATE INDEX ON products (created_at DESC, id DESC)","), hogy a seek index-scan maradjon.",[918,2024,2026],{"id":2025},"az-opak-cursor","Az opak cursor",[448,2028,2029,2030,2032,2033,2036,2037,2040,2041,2044],{},"A kliens felé a cursor átlátszatlan string: base64url-kódolt, verziózott JSON boríték a kulcsértékekkel és a rendezési spec ujjlenyomatával. A ",[457,2031,880],{}," ",[457,2034,2035],{},"ErrInvalidCursor","-ral (HTTP 400, kód: ",[457,2038,2039],{},"paginate_invalid_cursor",") utasítja el azt a cursort, ami nem dekódolható, más verzióhoz készült, vagy ",[462,2042,2043],{},"más rendezéshez lett kiadva",". Sosem esik vissza némán az első oldalra, mert az elrejtené a kliens hibáját. Két következmény:",[1968,2046,2047,2050],{},[1971,2048,2049],{},"egy végpont default rendezésének megváltoztatása dizájn szerint érvényteleníti a kint lévő cursorokat;",[1971,2051,2052,2053,2055,2056,2059,2060,2063],{},"a cursor nem titkosított és nincs aláírva: kulcsértékei (időbélyeg, id) nyíltan dekódolhatók, és semmi nem akadályozza meg a klienst abban, hogy kézzel átírjon egyet. Kezeld hatékony folytatási tokenként, ne manipuláció-biztos jogosultságként: ne tegyél bele olyat, amit a kliens nem láthat, és ne használd jogosultság-határként. A sort-ujjlenyomat csak azt védi, hogy a cursort ne lehessen egy másik ",[457,2054,915],{}," ellen visszajátszani, azt nem, hogy a kliens meghamisítsa a kulcsértékeket; ha egy hamisított érték olyan sorra mutat, amit a hívó nem láthatna, azt a query saját jogosultsági szűrője (egy tenant- vagy tulajdonos-",[457,2057,2058],{},"WHERE",") kapja el, pontosan úgy, ahogy egy kézzel gyártott ",[457,2061,2062],{},"OFFSET"," esetén is kellene.",[2065,2066,2067,2068,2071,2072,881,2075,2032,2078,2081],"note",{},"A cursor-lapozás ebben a verzióban csak előre halad: nincs ",[457,2069,2070],{},"before"," paraméter visszafelé lapozáshoz. A ",[457,2073,2074],{},"CursorPage[T]",[457,2076,2077],{},"shared\u002Fpaginator.tsp",[457,2079,2080],{},"CursorPage\u003CT>"," modelljének tükre.",[918,2083,2085],{"id":2084},"mikor-melyiket","Mikor melyiket",[2087,2088,2089,2108],"table",{},[2090,2091,2092],"thead",{},[2093,2094,2095,2098,2103],"tr",{},[2096,2097],"th",{},[2096,2099,2100,2101,547],{},"Offset (",[457,2102,899],{},[2096,2104,2105,2106,547],{},"Cursor (",[457,2107,880],{},[2109,2110,2111,2127,2138,2149,2160],"tbody",{},[2093,2112,2113,2117,2124],{},[2114,2115,2116],"td",{},"oldalszámos UI („3. oldal a 12-ből\")",[2114,2118,2119,2120,2123],{},"✔ (",[457,2121,2122],{},"Total","-t ad)",[2114,2125,2126],{},"✘ (nincs oldalszám, se összdarabszám)",[2093,2128,2129,2132,2135],{},[2114,2130,2131],{},"végtelen görgetés \u002F „továbbiak\" gomb",[2114,2133,2134],{},"működik, de drift-veszélyes",[2114,2136,2137],{},"✔ (ez a natív esete)",[2093,2139,2140,2143,2146],{},[2114,2141,2142],{},"nagy tábla, mély lapozás",[2114,2144,2145],{},"O(n), degradálódik",[2114,2147,2148],{},"✔ (közel konstans)",[2093,2150,2151,2154,2157],{},[2114,2152,2153],{},"konkurens insertek alatt stabil lapok",[2114,2155,2156],{},"✘ (csúszik)",[2114,2158,2159],{},"✔",[2093,2161,2162,2165,2167],{},[2114,2163,2164],{},"tetszőleges oldalra ugrás",[2114,2166,2159],{},[2114,2168,2169],{},"✘ (csak szekvenciális)",[448,2171,2172,2173,968],{},"Ökölszabály a shopból: a publikus terméklista (nagy, nő, végtelen görgetés) cursorral megy; egy admin-oldali, pár száz soros lista oldalszámokkal kényelmesebb ",[452,2174,2175],{"href":436},"offsettel",[918,2177,2179],{"id":2178},"használt-patternek","Használt patternek",[1968,2181,2182,2192],{},[1971,2183,2184,2187,2188,2191],{},[462,2185,2186],{},"Opaque, manipuláció-védett cursor"," (base64url + sha256 sort-fingerprint): ",[452,2189,238],{"href":2190},"\u002Fhu\u002Fconcepts\u002Fdesign-patterns#opaque-manipul%C3%A1ci%C3%B3-v%C3%A9dett-cursor",". A „manipuláció-védett\" itt kifejezetten a fenti sort-ujjlenyomat-ellenőrzésre vonatkozik, nem a kulcsértékekre, amik nyíltan utaznak; lásd a fenti integritási megjegyzést.",[1971,2193,2194,550,2197,2199,2200,2203,2204,2206],{},[462,2195,2196],{},"Generikus eredmény-wrapper",[457,2198,2074],{},"), az offset ",[457,2201,2202],{},"Page[T]","-jének testvére: lásd az ",[452,2205,52],{"href":896}," oldalt.",[918,2208,2210],{"id":2209},"merre-tovább","Merre tovább",[1968,2212,2213],{},[1971,2214,2215,2217,2218,2220,2221,2223],{},[452,2216,52],{"href":436},": offset lapozás (",[457,2219,899],{},", ",[457,2222,2202],{},"), telepítés és az önálló példa.",[2225,2226,2227],"style",{},"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 .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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":484,"searchDepth":564,"depth":564,"links":2229},[2230,2231,2232,2233,2234,2235],{"id":920,"depth":564,"text":921},{"id":1958,"depth":564,"text":1959},{"id":2025,"depth":564,"text":2026},{"id":2084,"depth":564,"text":2085},{"id":2178,"depth":564,"text":2179},{"id":2209,"depth":564,"text":2210},"Keyset-lapozás opak cursorral és Postgres tuple-összehasonlításos seekkel, nagy vagy gyorsan növő táblákhoz.","md",null,{},{"icon":19},{"title":439,"description":2236},"xDfbyWfYpoaRCPmd76XuFA0cLH80OjG3hLbivakzhsU",[2244,2238],{"title":52,"path":436,"stem":437,"description":2245,"icon":55,"children":-1},"Offset- (page\u002Fper-page) lapozás a paginate modullal, normalizált paraméterek és egy típusos page-wrapper.",1785445899227]