[{"data":1,"prerenderedAt":654},["ShallowReactive",2],{"navigation_docs":3,"-contributing-guidelines":199,"-contributing-guidelines-surround":649},[4,23,65,87,133,159,177],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":22},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,14,18],{"title":11,"path":12,"stem":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction",{"title":15,"path":16,"stem":17},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":19,"path":20,"stem":21},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start",false,{"title":24,"icon":25,"path":26,"stem":27,"children":28,"page":22},"Guides","i-lucide-compass","\u002Fguides","2.guides",[29,33,37,41,45,49,53,57,61],{"title":30,"path":31,"stem":32},"Authenticate","\u002Fguides\u002Fauthentication","2.guides\u002F1.authentication",{"title":34,"path":35,"stem":36},"Work with several forges","\u002Fguides\u002Fmultiple-forges","2.guides\u002F2.multiple-forges",{"title":38,"path":39,"stem":40},"Configure from the environment","\u002Fguides\u002Fenvironment","2.guides\u002F3.environment",{"title":42,"path":43,"stem":44},"Receive webhooks","\u002Fguides\u002Fwebhooks","2.guides\u002F4.webhooks",{"title":46,"path":47,"stem":48},"Check what a forge supports","\u002Fguides\u002Fcapabilities","2.guides\u002F5.capabilities",{"title":50,"path":51,"stem":52},"Handle errors and rate limits","\u002Fguides\u002Ferrors","2.guides\u002F6.errors",{"title":54,"path":55,"stem":56},"Page through results","\u002Fguides\u002Fpagination","2.guides\u002F7.pagination",{"title":58,"path":59,"stem":60},"Browser bundles","\u002Fguides\u002Fbundling","2.guides\u002F8.bundling",{"title":62,"path":63,"stem":64},"Test your code","\u002Fguides\u002Ftesting","2.guides\u002F9.testing",{"title":66,"icon":67,"path":68,"stem":69,"children":70,"page":22},"Concepts","i-lucide-lightbulb","\u002Fconcepts","3.concepts",[71,75,79,83],{"title":72,"path":73,"stem":74},"Data model","\u002Fconcepts\u002Fdata-model","3.concepts\u002F1.data-model",{"title":76,"path":77,"stem":78},"Capabilities","\u002Fconcepts\u002Fcapabilities","3.concepts\u002F2.capabilities",{"title":80,"path":81,"stem":82},"Providers and factories","\u002Fconcepts\u002Fproviders","3.concepts\u002F3.providers",{"title":84,"path":85,"stem":86},"Events","\u002Fconcepts\u002Fevents","3.concepts\u002F4.events",{"title":88,"icon":89,"path":90,"stem":91,"children":92,"page":22},"Providers","i-lucide-server","\u002Fproviders","4.providers",[93,97,101,105,109,113,117,121,125,129],{"title":94,"path":95,"stem":96},"Azure DevOps","\u002Fproviders\u002Fazure-devops","4.providers\u002Fazure-devops",{"title":98,"path":99,"stem":100},"Bitbucket Cloud","\u002Fproviders\u002Fbitbucket","4.providers\u002Fbitbucket",{"title":102,"path":103,"stem":104},"Cursor Origin","\u002Fproviders\u002Fcursor-origin","4.providers\u002Fcursor-origin",{"title":106,"path":107,"stem":108},"Forgejo and Codeberg","\u002Fproviders\u002Fforgejo","4.providers\u002Fforgejo",{"title":110,"path":111,"stem":112},"Gitea","\u002Fproviders\u002Fgitea","4.providers\u002Fgitea",{"title":114,"path":115,"stem":116},"Gitee","\u002Fproviders\u002Fgitee","4.providers\u002Fgitee",{"title":118,"path":119,"stem":120},"GitHub","\u002Fproviders\u002Fgithub","4.providers\u002Fgithub",{"title":122,"path":123,"stem":124},"GitLab","\u002Fproviders\u002Fgitlab","4.providers\u002Fgitlab",{"title":126,"path":127,"stem":128},"pushin.eu","\u002Fproviders\u002Fpushin","4.providers\u002Fpushin",{"title":130,"path":131,"stem":132},"Tangled","\u002Fproviders\u002Ftangled","4.providers\u002Ftangled",{"title":134,"icon":135,"path":136,"stem":137,"children":138,"page":22},"Reference","i-lucide-book-marked","\u002Freference","5.reference",[139,143,147,151,155],{"title":140,"path":141,"stem":142},"Provider API","\u002Freference\u002Fprovider-api","5.reference\u002F1.provider-api",{"title":144,"path":145,"stem":146},"Capability matrix","\u002Freference\u002Fcapability-matrix","5.reference\u002F2.capability-matrix",{"title":148,"path":149,"stem":150},"Errors","\u002Freference\u002Ferrors","5.reference\u002F3.errors",{"title":152,"path":153,"stem":154},"Environment variables","\u002Freference\u002Fenvironment-variables","5.reference\u002F4.environment-variables",{"title":156,"path":157,"stem":158},"JSON Schemas","\u002Freference\u002Fjson-schemas","5.reference\u002F5.json-schemas",{"title":160,"icon":161,"path":162,"stem":163,"children":164,"page":22},"Examples","i-lucide-boxes","\u002Fexamples","6.examples",[165,169,173],{"title":166,"path":167,"stem":168},"Inbox CLI","\u002Fexamples\u002Finbox-cli","6.examples\u002F1.inbox-cli",{"title":170,"path":171,"stem":172},"Label bot","\u002Fexamples\u002Flabel-bot","6.examples\u002F2.label-bot",{"title":174,"path":175,"stem":176},"Release digest","\u002Fexamples\u002Frelease-digest","6.examples\u002F3.release-digest",{"title":178,"icon":179,"path":180,"stem":181,"children":182,"page":22},"Contributing","i-lucide-git-pull-request","\u002Fcontributing","7.contributing",[183,187,191,195],{"title":184,"path":185,"stem":186},"Contribution guide","\u002Fcontributing\u002Fguidelines","7.contributing\u002F1.guidelines",{"title":188,"path":189,"stem":190},"Write a provider","\u002Fcontributing\u002Fwrite-a-provider","7.contributing\u002F2.write-a-provider",{"title":192,"path":193,"stem":194},"Record fixtures","\u002Fcontributing\u002Frecord-fixtures","7.contributing\u002F3.record-fixtures",{"title":196,"path":197,"stem":198},"Contributors","\u002Fcontributing\u002Fcontributors","7.contributing\u002F4.contributors",{"id":200,"title":184,"body":201,"description":641,"extension":642,"links":643,"meta":644,"navigation":646,"path":185,"seo":647,"stem":186,"__hash__":648},"docs\u002F7.contributing\u002F1.guidelines.md",{"type":202,"value":203,"toc":631},"minimark",[204,221,226,238,261,265,407,411,497,501,545,552,556,565,573,576,580,594,598,605,614,618,627],[205,206,207,208,212,213,220],"p",{},"Thanks for helping with ",[209,210,211],"code",{},"forges",". This page covers how to set up the repository, the checks a change has to pass and the rules that keep the providers consistent. By taking part, you agree to the ",[214,215,219],"a",{"href":216,"rel":217},"https:\u002F\u002Fgithub.com\u002Fdanielroe\u002Fforges\u002Fblob\u002Fmain\u002FCODE_OF_CONDUCT.md",[218],"nofollow","Code of Conduct",".",[222,223,225],"h2",{"id":224},"set-up","Set up",[205,227,228,229,234,235,220],{},"You need Node.js 22.18 or later and ",[214,230,233],{"href":231,"rel":232},"https:\u002F\u002Fpnpm.io",[218],"pnpm",". The repository pins the versions it develops with in ",[209,236,237],{},"devEngines",[239,240,245],"pre",{"className":241,"code":242,"language":243,"meta":244,"style":244},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm install\npnpm test:unit\n","sh","",[209,246,247,255],{"__ignoreMap":244},[248,249,252],"span",{"class":250,"line":251},"line",1,[248,253,254],{},"pnpm install\n",[248,256,258],{"class":250,"line":257},2,[248,259,260],{},"pnpm test:unit\n",[222,262,264],{"id":263},"commands","Commands",[266,267,268,281],"table",{},[269,270,271],"thead",{},[272,273,274,278],"tr",{},[275,276,277],"th",{},"Command",[275,279,280],{},"What it does",[282,283,284,295,305,326,340,350,364,377,387,397],"tbody",{},[272,285,286,292],{},[287,288,289],"td",{},[209,290,291],{},"pnpm dev",[287,293,294],{},"Runs the unit tests in watch mode",[272,296,297,302],{},[287,298,299],{},[209,300,301],{},"pnpm test:unit",[287,303,304],{},"Runs the unit tests once",[272,306,307,312],{},[287,308,309],{},[209,310,311],{},"pnpm test:types",[287,313,314,315,318,319,322,323],{},"Type-checks ",[209,316,317],{},"src",", ",[209,320,321],{},"test"," and ",[209,324,325],{},"scripts",[272,327,328,333],{},[287,329,330],{},[209,331,332],{},"pnpm test:capabilities",[287,334,335,336,339],{},"Fails for a capability that a provider declares ",[209,337,338],{},"true"," and no test called",[272,341,342,347],{},[287,343,344],{},[209,345,346],{},"pnpm test:knip",[287,348,349],{},"Finds unused files, exports and dependencies",[272,351,352,357],{},[287,353,354],{},[209,355,356],{},"pnpm test:size",[287,358,359,360,363],{},"Checks the browser bundle budgets. Run ",[209,361,362],{},"pnpm build"," first",[272,365,366,374],{},[287,367,368,318,371],{},[209,369,370],{},"pnpm lint",[209,372,373],{},"pnpm lint:fix",[287,375,376],{},"Lints, and fixes what it can",[272,378,379,384],{},[287,380,381],{},[209,382,383],{},"pnpm capability-matrix",[287,385,386],{},"Regenerates the capability tables in the docs",[272,388,389,394],{},[287,390,391],{},[209,392,393],{},"pnpm record-fixtures \u003Cforge>",[287,395,396],{},"Records responses from a live forge",[272,398,399,404],{},[287,400,401],{},[209,402,403],{},"pnpm check:all",[287,405,406],{},"Runs lint, tests, the engines check, a build and the size check",[222,408,410],{"id":409},"project-layout","Project layout",[266,412,413,423],{},[269,414,415],{},[272,416,417,420],{},[275,418,419],{},"Path",[275,421,422],{},"Content",[282,424,425,435,454,467,477,487],{},[272,426,427,432],{},[287,428,429],{},[209,430,431],{},"src\u002F\u003Cforge>\u002F",[287,433,434],{},"One provider each: its factory, normalisation and webhook handling",[272,436,437,448],{},[287,438,439,318,442,318,445],{},[209,440,441],{},"src\u002Fmodel.ts",[209,443,444],{},"src\u002Fprovider.ts",[209,446,447],{},"src\u002Fdefine.ts",[287,449,450,451],{},"The shared model, the provider interface and ",[209,452,453],{},"defineForgeProvider()",[272,455,456,464],{},[287,457,458,318,461],{},[209,459,460],{},"src\u002Ffake\u002F",[209,462,463],{},"src\u002Ftesting\u002F",[287,465,466],{},"The in-memory forge and the test helpers",[272,468,469,474],{},[287,470,471],{},[209,472,473],{},"test\u002F",[287,475,476],{},"Unit tests, recorded fixtures and the shared recording steps",[272,478,479,484],{},[287,480,481],{},[209,482,483],{},"examples\u002F",[287,485,486],{},"Small, tested projects that use the library",[272,488,489,494],{},[287,490,491],{},[209,492,493],{},"docs\u002F",[287,495,496],{},"The documentation site",[222,498,500],{"id":499},"rules","Rules",[502,503,504,515,521,532,535,542],"ul",{},[505,506,507,508,510,511,514],"li",{},"Declare a capability ",[209,509,338],{}," only when a test calls it. Use ",[209,512,513],{},"'experimental'"," for anything that isn't verified against a recording of the live forge.",[505,516,517,518,520],{},"After you change a provider's capabilities, run ",[209,519,383],{},". A test fails if the docs are out of date.",[505,522,523,524,527,528,531],{},"Import source files with the ",[209,525,526],{},".ts"," extension, so that ",[209,529,530],{},"node scripts\u002F\u003Cname>.ts"," runs without a build.",[505,533,534],{},"Don't add runtime dependencies. Don't import Node.js built-in modules from a provider.",[505,536,537,538,541],{},"Keep errors, warnings and ",[209,539,540],{},"skipped"," reasons free of credentials.",[505,543,544],{},"Add a test for each change. For a new read, record a fixture instead of writing one by hand.",[205,546,547,548,322,550,220],{},"To add a forge or an operation, read ",[214,549,188],{"href":189},[214,551,192],{"href":193},[222,553,555],{"id":554},"commit-messages","Commit messages",[205,557,558,559,564],{},"Commits follow ",[214,560,563],{"href":561,"rel":562},"https:\u002F\u002Fwww.conventionalcommits.org",[218],"Conventional Commits",". Releases are cut from the commit messages, so the type decides the version bump. Use the provider as the scope when a change concerns one forge:",[239,566,571],{"className":567,"code":569,"language":570,"meta":244},[568],"language-text","feat(github): adopt asynchronous direct merges\nfix(gitlab): read nested group paths\ndocs: explain webhook verification\n","text",[209,572,569],{"__ignoreMap":244},[205,574,575],{},"Use the same format for the title of a pull request.",[222,577,579],{"id":578},"pull-requests","Pull requests",[502,581,582,585,591],{},[505,583,584],{},"Keep a pull request to one change.",[505,586,587,588,590],{},"Run ",[209,589,403],{}," before you push. CI runs the same checks.",[505,592,593],{},"Describe what changed and why. Link the issue it closes.",[222,595,597],{"id":596},"writing-documentation","Writing documentation",[205,599,600,601,604],{},"The documentation lives in ",[209,602,603],{},"docs\u002Fcontent",". Write short sentences in the second person, and prefer a code example to a long explanation. Avoid em-dashes and filler words. Run the site locally with:",[239,606,608],{"className":241,"code":607,"language":243,"meta":244,"style":244},"pnpm --filter forges-docs dev\n",[209,609,610],{"__ignoreMap":244},[248,611,612],{"class":250,"line":251},[248,613,607],{},[222,615,617],{"id":616},"reporting-a-problem","Reporting a problem",[205,619,620,621,626],{},"Open an ",[214,622,625],{"href":623,"rel":624},"https:\u002F\u002Fgithub.com\u002Fdanielroe\u002Fforges\u002Fissues",[218],"issue"," with steps to reproduce. For a forge-specific bug, name the forge and, for a self-hosted forge, its version.",[628,629,630],"style",{},"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);}",{"title":244,"searchDepth":257,"depth":257,"links":632},[633,634,635,636,637,638,639,640],{"id":224,"depth":257,"text":225},{"id":263,"depth":257,"text":264},{"id":409,"depth":257,"text":410},{"id":499,"depth":257,"text":500},{"id":554,"depth":257,"text":555},{"id":578,"depth":257,"text":579},{"id":596,"depth":257,"text":597},{"id":616,"depth":257,"text":617},"Set up the repository, run the checks and follow the rules that keep providers consistent.","md",null,{"icon":645},"i-lucide-book-heart",true,{"title":184,"description":641},"jqyOiJQYsh1LuUjFtWZZHXMlj0qH78nHG4CBP8_pa_U",[650,652],{"title":174,"path":175,"stem":176,"description":651,"children":-1},"Print the latest release and the failing pull requests of repositories on any forge.",{"title":188,"path":189,"stem":190,"description":653,"children":-1},"Add a forge by declaring each operation once.",1791296695321]