[{"data":1,"prerenderedAt":4270},["ShallowReactive",2],{"navigation_docs":3,"-modules-subscriptions":153,"-modules-subscriptions-surround":4265},[4,35,50,59,144],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting started",false,"\u002Fgetting-started","1.getting-started",[10,15,20,25,30],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Local Development","\u002Fgetting-started\u002Flocal-development","1.getting-started\u002F3.local-development","i-lucide-terminal",{"title":21,"path":22,"stem":23,"icon":24},"Publishing Packages","\u002Fgetting-started\u002Fpublishing","1.getting-started\u002F4.publishing","i-lucide-package-check",{"title":26,"path":27,"stem":28,"icon":29},"Writing a Module","\u002Fgetting-started\u002Fwriting-a-module","1.getting-started\u002F5.writing-a-module","i-lucide-puzzle",{"title":31,"path":32,"stem":33,"icon":34},"UX Patterns","\u002Fgetting-started\u002Fux-patterns","1.getting-started\u002F6.ux-patterns","i-lucide-layout-template",{"title":36,"path":37,"stem":38,"children":39},"Applications","\u002Fapplications","2.applications",[40,45],{"title":41,"path":42,"stem":43,"icon":44},"Website","\u002Fapplications\u002Fwebsite","2.applications\u002F1.website","i-lucide-layout-dashboard",{"title":46,"path":47,"stem":48,"icon":49},"Docs","\u002Fapplications\u002Fdocs","2.applications\u002F2.docs","i-lucide-book-open",{"title":51,"path":52,"stem":53,"children":54},"Layers","\u002Flayers","3.layers",[55],{"title":56,"path":57,"stem":58},"Base Layer","\u002Flayers\u002Fbase","3.layers\u002F1.base",{"title":60,"path":61,"stem":62,"children":63},"Modules","\u002Fmodules","4.modules",[64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140],{"title":65,"path":66,"stem":67},"Account","\u002Fmodules\u002Faccount","4.modules\u002F01.account",{"title":69,"path":70,"stem":71},"Admin","\u002Fmodules\u002Fadmin","4.modules\u002F02.admin",{"title":73,"path":74,"stem":75},"Auth","\u002Fmodules\u002Fauth","4.modules\u002F03.auth",{"title":77,"path":78,"stem":79},"Authorization","\u002Fmodules\u002Fauthorization","4.modules\u002F04.authorization",{"title":81,"path":82,"stem":83},"Cookie Consent","\u002Fmodules\u002Fcookie-consent","4.modules\u002F05.cookie-consent",{"title":85,"path":86,"stem":87},"Events","\u002Fmodules\u002Fevents","4.modules\u002F06.events",{"title":89,"path":90,"stem":91},"Forms","\u002Fmodules\u002Fforms","4.modules\u002F07.forms",{"title":93,"path":94,"stem":95},"MCP","\u002Fmodules\u002Fmcp","4.modules\u002F08.mcp",{"title":97,"path":98,"stem":99},"Menu","\u002Fmodules\u002Fmenu","4.modules\u002F09.menu",{"title":101,"path":102,"stem":103},"Module Kit","\u002Fmodules\u002Fmodule-kit","4.modules\u002F10.module-kit",{"title":105,"path":106,"stem":107},"Notify","\u002Fmodules\u002Fnotify","4.modules\u002F11.notify",{"title":109,"path":110,"stem":111},"OAuth Server","\u002Fmodules\u002Foauth-server","4.modules\u002F12.oauth-server",{"title":113,"path":114,"stem":115},"Payments","\u002Fmodules\u002Fpayments","4.modules\u002F13.payments",{"title":117,"path":118,"stem":119},"Preferences","\u002Fmodules\u002Fpreferences","4.modules\u002F14.preferences",{"title":121,"path":122,"stem":123},"Stripe","\u002Fmodules\u002Fstripe","4.modules\u002F15.stripe",{"title":125,"path":126,"stem":127},"Subscriptions","\u002Fmodules\u002Fsubscriptions","4.modules\u002F16.subscriptions",{"title":129,"path":130,"stem":131},"UI","\u002Fmodules\u002Fui","4.modules\u002F17.ui",{"title":133,"path":134,"stem":135},"Users","\u002Fmodules\u002Fusers","4.modules\u002F18.users",{"title":137,"path":138,"stem":139},"Widget","\u002Fmodules\u002Fwidget","4.modules\u002F19.widget",{"title":141,"path":142,"stem":143},"Email Templates","\u002Fmodules\u002Femail-templates","4.modules\u002F20.email-templates",{"title":145,"path":146,"stem":147,"children":148},"Packages","\u002Fpackages","5.packages",[149],{"title":150,"path":151,"stem":152},"CLI","\u002Fpackages\u002Fcli","5.packages\u002F4.cli",{"id":154,"title":125,"body":155,"description":4259,"extension":4260,"links":4261,"meta":4262,"navigation":1468,"path":126,"seo":4263,"stem":127,"__hash__":4264},"docs\u002F4.modules\u002F16.subscriptions.md",{"type":156,"value":157,"toc":4239},"minimark",[158,174,207,279,284,287,688,730,734,1016,1054,1058,1063,1069,1177,1193,1198,1268,1291,1295,1322,1347,1380,1384,1393,1550,1563,1653,1656,1660,1693,1903,1920,1924,1930,2121,2144,2148,2227,2244,2248,2260,2408,2426,2621,2635,2639,2699,2702,2709,2760,3124,3158,3362,3366,3568,3579,3760,3763,3805,3808,3815,3978,3983,4001,4005,4034,4235],[159,160,161,162,165,166,170,171,173],"p",{},"Recurring subscriptions on top of ",[163,164,121],"a",{"href":122},". It handles ",[167,168,169],"strong",{},"only"," recurring subscriptions; one-off\npayments belong to ",[163,172,113],{"href":114},". \"Membership\" is just a label a host chooses for its plans.",[175,176,177,184,195,201],"ul",{},[178,179,180,183],"li",{},[167,181,182],{},"Stripe owns the catalog; the module mirrors per-user state."," No products or prices tables. Plans are declared in\nconfig and prices are resolved live from Stripe, cached in NuxtHub KV for about five minutes.",[178,185,186,189,190,194],{},[167,187,188],{},"Host policy through hooks."," Seasonal windows, member discounts and similar rules are injected with\n",[163,191,193],{"href":192},"#hooks","hooks",", not built in.",[178,196,197,200],{},[167,198,199],{},"No copy in Stripe."," Labels come from config and optional i18n keys. The UI is headless-first (composables) with\nreplaceable components and slots; pages are opt-in.",[178,202,203,206],{},[167,204,205],{},"Entitlements, not roles."," Other code asks \"does this user hold plan X?\".",[208,209,210,213,214,218,219,222,223,228,229,228,234,239,240,245,246,251,252,213,255,228,260,239,265,270,271,274,275,278],"note",{},[167,211,212],{},"Requires"," ",[215,216,217],"code",{},"@nuxthub\u002Fcore"," (KV on; the build throws without it), ",[215,220,221],{},"@frigear-nu\u002Fmodule-kit",",\n",[163,224,225],{"href":74},[215,226,227],{},"@frigear-nu\u002Fauth",", ",[163,230,231],{"href":94},[215,232,233],{},"@frigear-nu\u002Fmcp",[163,235,236],{"href":134},[215,237,238],{},"@frigear-nu\u002Fusers"," and\n",[163,241,242],{"href":122},[215,243,244],{},"@frigear-nu\u002Fstripe"," (configure it as described there: keys, webhook and KV) and\n",[163,247,248],{"href":130},[215,249,250],{},"@frigear-nu\u002Fui"," (the shared components the pages are built from).\n",[167,253,254],{},"Optional",[163,256,257],{"href":98},[215,258,259],{},"@frigear-nu\u002Fmenu",[163,261,262],{"href":138},[215,263,264],{},"@frigear-nu\u002Fwidget",[163,266,267],{"href":70},[215,268,269],{},"@frigear-nu\u002Fadmin"," (the admin user tab and card need both), ",[215,272,273],{},"@nuxt\u002Fui"," (components and pages) and\n",[215,276,277],{},"@nuxtjs\u002Fi18n"," (translated labels; English otherwise).",[280,281,283],"h2",{"id":282},"quick-setup","Quick setup",[159,285,286],{},"List the module after the ones it builds on:",[288,289,294],"pre",{"className":290,"code":291,"language":292,"meta":293,"style":293},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: [\n    '@nuxthub\u002Fcore',\n    '@nuxt\u002Fui',\n    '@frigear-nu\u002Fusers',\n    '@frigear-nu\u002Fmenu', \u002F\u002F optional\n    '@frigear-nu\u002Fstripe',\n    '@frigear-nu\u002Fsubscriptions',\n  ],\n  hub: { db: { dialect: 'sqlite', driver: 'libsql' }, kv: true },\n  subscriptions: {\n    plans: {\n      member: { label: 'Member', rank: 1, prices: [{ lookupKey: 'member_yearly' }] },\n      patron: { label: 'Patron', rank: 2, prices: [{ lookupKey: 'patron_yearly' }] },\n    },\n    settings: { pages: { membership: true, success: true, cancel: true } },\n  },\n})\n","ts","",[215,295,296,320,333,347,358,369,385,396,408,416,476,487,497,564,621,627,673,679],{"__ignoreMap":293},[297,298,301,305,308,312,316],"span",{"class":299,"line":300},"line",1,[297,302,304],{"class":303},"s7zQu","export",[297,306,307],{"class":303}," default",[297,309,311],{"class":310},"s2Zo4"," defineNuxtConfig",[297,313,315],{"class":314},"sTEyZ","(",[297,317,319],{"class":318},"sMK4o","{\n",[297,321,323,327,330],{"class":299,"line":322},2,[297,324,326],{"class":325},"swJcz","  modules",[297,328,329],{"class":318},":",[297,331,332],{"class":314}," [\n",[297,334,336,339,342,345],{"class":299,"line":335},3,[297,337,338],{"class":318},"    '",[297,340,217],{"class":341},"sfazB",[297,343,344],{"class":318},"'",[297,346,222],{"class":318},[297,348,350,352,354,356],{"class":299,"line":349},4,[297,351,338],{"class":318},[297,353,273],{"class":341},[297,355,344],{"class":318},[297,357,222],{"class":318},[297,359,361,363,365,367],{"class":299,"line":360},5,[297,362,338],{"class":318},[297,364,238],{"class":341},[297,366,344],{"class":318},[297,368,222],{"class":318},[297,370,372,374,376,378,381],{"class":299,"line":371},6,[297,373,338],{"class":318},[297,375,259],{"class":341},[297,377,344],{"class":318},[297,379,380],{"class":318},",",[297,382,384],{"class":383},"sHwdD"," \u002F\u002F optional\n",[297,386,388,390,392,394],{"class":299,"line":387},7,[297,389,338],{"class":318},[297,391,244],{"class":341},[297,393,344],{"class":318},[297,395,222],{"class":318},[297,397,399,401,404,406],{"class":299,"line":398},8,[297,400,338],{"class":318},[297,402,403],{"class":341},"@frigear-nu\u002Fsubscriptions",[297,405,344],{"class":318},[297,407,222],{"class":318},[297,409,411,414],{"class":299,"line":410},9,[297,412,413],{"class":314},"  ]",[297,415,222],{"class":318},[297,417,419,422,424,427,430,432,434,437,439,442,445,447,449,452,454,456,459,461,464,467,469,473],{"class":299,"line":418},10,[297,420,421],{"class":325},"  hub",[297,423,329],{"class":318},[297,425,426],{"class":318}," {",[297,428,429],{"class":325}," db",[297,431,329],{"class":318},[297,433,426],{"class":318},[297,435,436],{"class":325}," dialect",[297,438,329],{"class":318},[297,440,441],{"class":318}," '",[297,443,444],{"class":341},"sqlite",[297,446,344],{"class":318},[297,448,380],{"class":318},[297,450,451],{"class":325}," driver",[297,453,329],{"class":318},[297,455,441],{"class":318},[297,457,458],{"class":341},"libsql",[297,460,344],{"class":318},[297,462,463],{"class":318}," },",[297,465,466],{"class":325}," kv",[297,468,329],{"class":318},[297,470,472],{"class":471},"sfNiH"," true",[297,474,475],{"class":318}," },\n",[297,477,479,482,484],{"class":299,"line":478},11,[297,480,481],{"class":325},"  subscriptions",[297,483,329],{"class":318},[297,485,486],{"class":318}," {\n",[297,488,490,493,495],{"class":299,"line":489},12,[297,491,492],{"class":325},"    plans",[297,494,329],{"class":318},[297,496,486],{"class":318},[297,498,500,503,505,507,510,512,514,517,519,521,524,526,530,532,535,537,540,543,546,548,550,553,555,558,561],{"class":299,"line":499},13,[297,501,502],{"class":325},"      member",[297,504,329],{"class":318},[297,506,426],{"class":318},[297,508,509],{"class":325}," label",[297,511,329],{"class":318},[297,513,441],{"class":318},[297,515,516],{"class":341},"Member",[297,518,344],{"class":318},[297,520,380],{"class":318},[297,522,523],{"class":325}," rank",[297,525,329],{"class":318},[297,527,529],{"class":528},"sbssI"," 1",[297,531,380],{"class":318},[297,533,534],{"class":325}," prices",[297,536,329],{"class":318},[297,538,539],{"class":314}," [",[297,541,542],{"class":318},"{",[297,544,545],{"class":325}," lookupKey",[297,547,329],{"class":318},[297,549,441],{"class":318},[297,551,552],{"class":341},"member_yearly",[297,554,344],{"class":318},[297,556,557],{"class":318}," }",[297,559,560],{"class":314},"] ",[297,562,563],{"class":318},"},\n",[297,565,567,570,572,574,576,578,580,583,585,587,589,591,594,596,598,600,602,604,606,608,610,613,615,617,619],{"class":299,"line":566},14,[297,568,569],{"class":325},"      patron",[297,571,329],{"class":318},[297,573,426],{"class":318},[297,575,509],{"class":325},[297,577,329],{"class":318},[297,579,441],{"class":318},[297,581,582],{"class":341},"Patron",[297,584,344],{"class":318},[297,586,380],{"class":318},[297,588,523],{"class":325},[297,590,329],{"class":318},[297,592,593],{"class":528}," 2",[297,595,380],{"class":318},[297,597,534],{"class":325},[297,599,329],{"class":318},[297,601,539],{"class":314},[297,603,542],{"class":318},[297,605,545],{"class":325},[297,607,329],{"class":318},[297,609,441],{"class":318},[297,611,612],{"class":341},"patron_yearly",[297,614,344],{"class":318},[297,616,557],{"class":318},[297,618,560],{"class":314},[297,620,563],{"class":318},[297,622,624],{"class":299,"line":623},15,[297,625,626],{"class":318},"    },\n",[297,628,630,633,635,637,640,642,644,647,649,651,653,656,658,660,662,665,667,669,671],{"class":299,"line":629},16,[297,631,632],{"class":325},"    settings",[297,634,329],{"class":318},[297,636,426],{"class":318},[297,638,639],{"class":325}," pages",[297,641,329],{"class":318},[297,643,426],{"class":318},[297,645,646],{"class":325}," membership",[297,648,329],{"class":318},[297,650,472],{"class":471},[297,652,380],{"class":318},[297,654,655],{"class":325}," success",[297,657,329],{"class":318},[297,659,472],{"class":471},[297,661,380],{"class":318},[297,663,664],{"class":325}," cancel",[297,666,329],{"class":318},[297,668,472],{"class":471},[297,670,557],{"class":318},[297,672,475],{"class":318},[297,674,676],{"class":299,"line":675},17,[297,677,678],{"class":318},"  },\n",[297,680,682,685],{"class":299,"line":681},18,[297,683,684],{"class":318},"}",[297,686,687],{"class":314},")\n",[689,690,691,699,707,715],"ol",{},[178,692,693,694,698],{},"Set the Stripe ",[163,695,697],{"href":696},"\u002Fmodules\u002Fstripe#environment-variables","environment variables"," (test keys in development).",[178,700,701,702,706],{},"Complete the ",[163,703,705],{"href":704},"#stripe-dashboard-setup","Stripe dashboard setup",".",[178,708,709,710,714],{},"Generate and commit your app's migration (see ",[163,711,713],{"href":712},"#database","Database","); skipping it is the most common cause of failing\nwebhooks and checkouts.",[178,716,717,718,721,722,725,726,729],{},"Verify: sign in, open ",[215,719,720],{},"\u002Faccount\u002Fmembership"," and subscribe with Stripe's test card ",[215,723,724],{},"4242 4242 4242 4242",". After the\nredirect, ",[215,727,728],{},"GET \u002Fapi\u002Fsubscriptions\u002Fme"," returns the subscription once the webhook has landed.",[280,731,733],{"id":732},"options","Options",[735,736,737,756],"table",{},[738,739,740],"thead",{},[741,742,743,747,750,753],"tr",{},[744,745,746],"th",{},"Option",[744,748,749],{},"Type",[744,751,752],{},"Default",[744,754,755],{},"Purpose",[757,758,759,780,798,815,837,857,878,903,927,947,967,991],"tbody",{},[741,760,761,767,772,777],{},[762,763,764],"td",{},[215,765,766],{},"plans",[762,768,769],{},[215,770,771],{},"Record\u003Cstring, PlanConfig>",[762,773,774],{},[215,775,776],{},"{}",[762,778,779],{},"Plans keyed by plan key. Empty means \"any active subscription\" (see below).",[741,781,782,787,792,795],{},[762,783,784],{},[215,785,786],{},"plans.\u003Ckey>.prices",[762,788,789],{},[215,790,791],{},"Array\u003Cstring | { lookupKey }>",[762,793,794],{},"-",[762,796,797],{},"Required. Stripe price ids and\u002For lookup refs; several per plan (monthly, yearly).",[741,799,800,805,810,812],{},[762,801,802],{},[215,803,804],{},"plans.\u003Ckey>.rank",[762,806,807],{},[215,808,809],{},"number",[762,811,794],{},[762,813,814],{},"Required. Higher is a higher tier; decides upgrade vs downgrade. Amounts are never compared.",[741,816,817,822,827,830],{},[762,818,819],{},[215,820,821],{},"plans.\u003Ckey>.label",[762,823,824],{},[215,825,826],{},"string",[762,828,829],{},"the key",[762,831,832,833,836],{},"Display label; i18n ",[215,834,835],{},"subscriptions.catalog.\u003Ckey>.label"," wins when defined.",[741,838,839,844,848,850],{},[762,840,841],{},[215,842,843],{},"plans.\u003Ckey>.description",[762,845,846],{},[215,847,826],{},[762,849,794],{},[762,851,852,853,856],{},"Optional; i18n ",[215,854,855],{},"catalog.\u003Ckey>.description"," wins.",[741,858,859,864,869,871],{},[762,860,861],{},[215,862,863],{},"plans.\u003Ckey>.features",[762,865,866],{},[215,867,868],{},"string[]",[762,870,794],{},[762,872,873,874,877],{},"Bullet points on the plan card; i18n ",[215,875,876],{},"catalog.\u003Ckey>.features"," (array) wins.",[741,879,880,885,890,892],{},[762,881,882],{},[215,883,884],{},"plans.\u003Ckey>.availability.disabledRanges",[762,886,887],{},[215,888,889],{},"{ from, to }[]",[762,891,794],{},[762,893,894,895,898,899,902],{},"Date windows (inclusive; ",[215,896,897],{},"{fullYear}"," becomes the current year, e.g. ",[215,900,901],{},"{fullYear}-06-01",") in which the plan is hidden from visitors without an active subscription. Subscribers still see it; checkout rejects a hidden plan.",[741,904,905,910,915,918],{},[762,906,907],{},[215,908,909],{},"settings.pages.membership",[762,911,912],{},[215,913,914],{},"string | boolean",[762,916,917],{},"off",[762,919,920,923,924,926],{},[215,921,922],{},"true"," = ",[215,925,720],{},", a string = custom path.",[741,928,929,934,938,940],{},[762,930,931],{},[215,932,933],{},"settings.pages.success",[762,935,936],{},[215,937,914],{},[762,939,917],{},[762,941,942,923,944,706],{},[215,943,922],{},[215,945,946],{},"\u002Faccount\u002Fmembership\u002Fsuccess",[741,948,949,954,958,960],{},[762,950,951],{},[215,952,953],{},"settings.pages.cancel",[762,955,956],{},[215,957,914],{},[762,959,917],{},[762,961,962,923,964,706],{},[215,963,922],{},[215,965,966],{},"\u002Faccount\u002Fmembership\u002Fcancel",[741,968,969,974,979,984],{},[762,970,971],{},[215,972,973],{},"settings.allowChangeInPortal",[762,975,976],{},[215,977,978],{},"boolean",[762,980,981],{},[215,982,983],{},"false",[762,985,986,987,990],{},"Hint exposed as ",[215,988,989],{},"public.subscriptions.allowChangeInPortal",". Not enforced; mirror your billing portal.",[741,992,993,998,1002,1006],{},[762,994,995],{},[215,996,997],{},"settings.mcp",[762,999,1000],{},[215,1001,978],{},[762,1003,1004],{},[215,1005,983],{},[762,1007,1008,1009,1012,1013,1015],{},"Expose the ",[215,1010,1011],{},"my-subscriptions"," tool on the ",[163,1014,93],{"href":94}," endpoint.",[159,1017,1018,1019,1022,1023,1026,1027,1030,1031,1034,1035,1038,1039,1042,1043,1046,1047,1049,1050,706],{},"Without plans, checkout requires a ",[215,1020,1021],{},"priceId"," and accepts any active recurring Stripe price; stored rows get\n",[215,1024,1025],{},"planKey = null",". Runtime config exposes ",[215,1028,1029],{},"public.subscriptions"," (",[215,1032,1033],{},"pages",", plans sorted by ",[215,1036,1037],{},"rank"," without prices, and\n",[215,1040,1041],{},"allowChangeInPortal",") and a private ",[215,1044,1045],{},"subscriptions.plans",". Pages need ",[215,1048,273],{}," in the app; leave them out to build\nyour own UI with the ",[163,1051,1053],{"href":1052},"#app","composables",[280,1055,1057],{"id":1056},"server","Server",[1059,1060,1062],"h3",{"id":1061},"entitlements","Entitlements",[159,1064,1065,1066,329],{},"Auto-imported in Nitro, or import from ",[215,1067,1068],{},"@frigear-nu\u002Fsubscriptions\u002Futils",[288,1070,1072],{"className":290,"code":1071,"language":292,"meta":293,"style":293},"getUserSubscription(userId: number, options?: { statuses?: string[] }): Promise\u003CSubscriptionRow | null>\nhasActiveSubscription(userId: number, options?: {\n  plans?: string[]      \u002F\u002F only these plan keys; omit for any plan\n  statuses?: string[]   \u002F\u002F default DEFAULT_ENTITLED_STATUSES = ['active', 'trialing']\n}): Promise\u003Cboolean>\n",[215,1073,1074,1121,1136,1149,1162],{"__ignoreMap":293},[297,1075,1076,1079,1082,1084,1087,1090,1092,1095,1097,1100,1102,1105,1109,1112,1115,1118],{"class":299,"line":300},[297,1077,1078],{"class":310},"getUserSubscription",[297,1080,1081],{"class":314},"(userId: number",[297,1083,380],{"class":318},[297,1085,1086],{"class":314}," options",[297,1088,1089],{"class":318},"?:",[297,1091,426],{"class":318},[297,1093,1094],{"class":314}," statuses?",[297,1096,329],{"class":318},[297,1098,1099],{"class":314}," string[] ",[297,1101,684],{"class":318},[297,1103,1104],{"class":314},"): ",[297,1106,1108],{"class":1107},"sBMFI","Promise",[297,1110,1111],{"class":318},"\u003C",[297,1113,1114],{"class":314},"SubscriptionRow ",[297,1116,1117],{"class":318},"|",[297,1119,1120],{"class":318}," null>\n",[297,1122,1123,1126,1128,1130,1132,1134],{"class":299,"line":322},[297,1124,1125],{"class":310},"hasActiveSubscription",[297,1127,1081],{"class":314},[297,1129,380],{"class":318},[297,1131,1086],{"class":314},[297,1133,1089],{"class":318},[297,1135,486],{"class":318},[297,1137,1138,1141,1143,1146],{"class":299,"line":335},[297,1139,1140],{"class":314},"  plans?",[297,1142,329],{"class":318},[297,1144,1145],{"class":314}," string[]      ",[297,1147,1148],{"class":383},"\u002F\u002F only these plan keys; omit for any plan\n",[297,1150,1151,1154,1156,1159],{"class":299,"line":349},[297,1152,1153],{"class":314},"  statuses",[297,1155,1089],{"class":318},[297,1157,1158],{"class":314}," string[]   ",[297,1160,1161],{"class":383},"\u002F\u002F default DEFAULT_ENTITLED_STATUSES = ['active', 'trialing']\n",[297,1163,1164,1166,1168,1170,1172,1174],{"class":299,"line":360},[297,1165,684],{"class":318},[297,1167,1104],{"class":314},[297,1169,1108],{"class":1107},[297,1171,1111],{"class":318},[297,1173,978],{"class":314},[297,1175,1176],{"class":318},">\n",[159,1178,1179,1181,1182,1185,1186,1189,1190,1192],{},[215,1180,1078],{}," returns the entitled row with the latest ",[215,1183,1184],{},"currentPeriodEnd",". Rows with ",[215,1187,1188],{},"endedAt",", and manual\ngrants past their end date, never count. These are meant for other modules (for example ",[163,1191,85],{"href":86},"),\nserver middleware and gating.",[159,1194,1195,1196,329],{},"Also exported from ",[215,1197,1068],{},[735,1199,1200,1210],{},[738,1201,1202],{},[741,1203,1204,1207],{},[744,1205,1206],{},"Export",[744,1208,1209],{},"Description",[757,1211,1212,1229,1242,1256],{},[741,1213,1214,1219],{},[762,1215,1216],{},[215,1217,1218],{},"decideChangeKind(currentRank, targetRank)",[762,1220,1221,1224,1225,1228],{},[215,1222,1223],{},"'upgrade'"," or ",[215,1226,1227],{},"'downgrade'"," from plan ranks; an unconfigured current plan counts as lowest.",[741,1230,1231,1236],{},[762,1232,1233],{},[215,1234,1235],{},"resolvePlanKey(plans, { id, lookupKey? })",[762,1237,1238,1239,706],{},"Maps a Stripe price to the configured plan key, or ",[215,1240,1241],{},"null",[741,1243,1244,1249],{},[762,1245,1246],{},[215,1247,1248],{},"isWithinDisabledRanges(ranges, now?)",[762,1250,1251,1252,1255],{},"Whether a date falls in any ",[215,1253,1254],{},"disabledRanges"," window.",[741,1257,1258,1263],{},[762,1259,1260],{},[215,1261,1262],{},"DEFAULT_ENTITLED_STATUSES",[762,1264,1265,706],{},[215,1266,1267],{},"['active', 'trialing']",[159,1269,1270,1271,1274,1275,1278,1279,1282,1283,1286,1287,1290],{},"Further server helpers are auto-imported in Nitro: ",[215,1272,1273],{},"listUserSubscriptions(userId)"," (the ",[215,1276,1277],{},"MeResponse","),\n",[215,1280,1281],{},"getResolvedPlans()"," (unfiltered, cached) and ",[215,1284,1285],{},"getAvailablePlans(event?)"," (after availability windows and the\n",[215,1288,1289],{},"subscriptions:plans:filter"," hook).",[1059,1292,1294],{"id":1293},"webhook-handling","Webhook handling",[159,1296,1297,1298,1304,1305,228,1308,228,1311,228,1314,1317,1318,1321],{},"The module registers with ",[163,1299,1301],{"href":1300},"\u002Fmodules\u002Fstripe#in-a-module",[215,1302,1303],{},"registerStripeEventHandler"," for\n",[215,1306,1307],{},"customer.subscription.created",[215,1309,1310],{},"updated",[215,1312,1313],{},"deleted",[215,1315,1316],{},"paused"," and ",[215,1319,1320],{},"resumed",". Each event is an idempotent upsert keyed\nby the Stripe subscription id:",[175,1323,1324,1327,1335],{},[178,1325,1326],{},"The user is resolved from the Stripe customer id. For an unknown customer the event is logged and ignored (the webhook\nstill succeeds); users are never created from webhooks.",[178,1328,1329,1332,1333,706],{},[215,1330,1331],{},"planKey"," comes from the first subscription item's price (price id or lookup key), else ",[215,1334,1241],{},[178,1336,1337,1338,1340,1341,1344,1345,706],{},"Period start and end are derived from the items; ",[215,1339,1313],{}," stores status ",[215,1342,1343],{},"canceled"," and sets ",[215,1346,1188],{},[159,1348,1349,1350,1353,1354,1357,1358,228,1361,228,1364,1317,1367,1370,1371,1374,1375,1379],{},"Retries and idempotency follow ",[163,1351,121],{"href":1352},"\u002Fmodules\u002Fstripe#delivery-and-retries",". When ",[215,1355,1356],{},"@frigear-nu\u002Fpayments"," is\ninstalled, ",[215,1359,1360],{},"invoice.paid",[215,1362,1363],{},"invoice.payment_failed",[215,1365,1366],{},"invoice.voided",[215,1368,1369],{},"invoice.marked_uncollectible"," for\nsubscription invoices are also handled: they are announced through the ",[215,1372,1373],{},"subscriptions:invoice"," hook and stored by\npayments as ",[163,1376,1378],{"href":1377},"\u002Fmodules\u002Fpayments#membership-payments","membership payments",". Without payments no invoice event is handled.",[1059,1381,1383],{"id":1382},"checkout","Checkout",[159,1385,1386,1389,1390,329],{},[215,1387,1388],{},"POST \u002Fapi\u002Fsubscriptions\u002Fcheckout"," takes ",[215,1391,1392],{},"CheckoutBody",[288,1394,1396],{"className":290,"code":1395,"language":292,"meta":293,"style":293},"type CheckoutBody = {\n  planKey?: string      \u002F\u002F planKey or priceId is required (400 otherwise)\n  priceId?: string      \u002F\u002F required when the plan has several prices, and when no plans are configured\n  successUrl?: string   \u002F\u002F relative path or same-origin URL, else 400; defaults to the success page, membership page or '\u002F'\n  cancelUrl?: string\n}\n\ntype CheckoutResponse =\n  | { url: string }                                           \u002F\u002F new Stripe Checkout Session: redirect to it\n  | { updated: true, kind: 'upgrade' | 'downgrade' | 'resume' } \u002F\u002F an existing subscription was changed in place\n",[215,1397,1398,1412,1425,1437,1449,1459,1464,1470,1480,1499],{"__ignoreMap":293},[297,1399,1400,1404,1407,1410],{"class":299,"line":300},[297,1401,1403],{"class":1402},"spNyl","type",[297,1405,1406],{"class":1107}," CheckoutBody",[297,1408,1409],{"class":318}," =",[297,1411,486],{"class":318},[297,1413,1414,1417,1419,1422],{"class":299,"line":322},[297,1415,1416],{"class":325},"  planKey",[297,1418,1089],{"class":318},[297,1420,1421],{"class":1107}," string",[297,1423,1424],{"class":383},"      \u002F\u002F planKey or priceId is required (400 otherwise)\n",[297,1426,1427,1430,1432,1434],{"class":299,"line":335},[297,1428,1429],{"class":325},"  priceId",[297,1431,1089],{"class":318},[297,1433,1421],{"class":1107},[297,1435,1436],{"class":383},"      \u002F\u002F required when the plan has several prices, and when no plans are configured\n",[297,1438,1439,1442,1444,1446],{"class":299,"line":349},[297,1440,1441],{"class":325},"  successUrl",[297,1443,1089],{"class":318},[297,1445,1421],{"class":1107},[297,1447,1448],{"class":383},"   \u002F\u002F relative path or same-origin URL, else 400; defaults to the success page, membership page or '\u002F'\n",[297,1450,1451,1454,1456],{"class":299,"line":360},[297,1452,1453],{"class":325},"  cancelUrl",[297,1455,1089],{"class":318},[297,1457,1458],{"class":1107}," string\n",[297,1460,1461],{"class":299,"line":371},[297,1462,1463],{"class":318},"}\n",[297,1465,1466],{"class":299,"line":387},[297,1467,1469],{"emptyLinePlaceholder":1468},true,"\n",[297,1471,1472,1474,1477],{"class":299,"line":398},[297,1473,1403],{"class":1402},[297,1475,1476],{"class":1107}," CheckoutResponse",[297,1478,1479],{"class":318}," =\n",[297,1481,1482,1485,1487,1490,1492,1494,1496],{"class":299,"line":410},[297,1483,1484],{"class":318},"  |",[297,1486,426],{"class":318},[297,1488,1489],{"class":325}," url",[297,1491,329],{"class":318},[297,1493,1421],{"class":1107},[297,1495,557],{"class":318},[297,1497,1498],{"class":383},"                                           \u002F\u002F new Stripe Checkout Session: redirect to it\n",[297,1500,1501,1503,1505,1508,1510,1512,1514,1517,1519,1521,1524,1526,1529,1531,1534,1536,1538,1540,1543,1545,1547],{"class":299,"line":418},[297,1502,1484],{"class":318},[297,1504,426],{"class":318},[297,1506,1507],{"class":325}," updated",[297,1509,329],{"class":318},[297,1511,472],{"class":1107},[297,1513,380],{"class":318},[297,1515,1516],{"class":325}," kind",[297,1518,329],{"class":318},[297,1520,441],{"class":318},[297,1522,1523],{"class":341},"upgrade",[297,1525,344],{"class":318},[297,1527,1528],{"class":318}," |",[297,1530,441],{"class":318},[297,1532,1533],{"class":341},"downgrade",[297,1535,344],{"class":318},[297,1537,1528],{"class":318},[297,1539,441],{"class":318},[297,1541,1542],{"class":341},"resume",[297,1544,344],{"class":318},[297,1546,557],{"class":318},[297,1548,1549],{"class":383}," \u002F\u002F an existing subscription was changed in place\n",[159,1551,1552,1553,228,1556,1224,1559,1562],{},"The plan must be in the filtered plan list (a hidden plan is 400). A user \"has a subscription\" here when a Stripe-synced\nrow is ",[215,1554,1555],{},"active",[215,1557,1558],{},"trialing",[215,1560,1561],{},"past_due"," and not ended; manual grants are ignored.",[735,1564,1565,1575],{},[738,1566,1567],{},[741,1568,1569,1572],{},[744,1570,1571],{},"Situation",[744,1573,1574],{},"Result",[757,1576,1577,1591,1601,1612,1626,1636,1644],{},[741,1578,1579,1582],{},[762,1580,1581],{},"No existing subscription",[762,1583,1584,1587,1588,706],{},[215,1585,1586],{},"kind: 'checkout'",": returns ",[215,1589,1590],{},"{ url }",[741,1592,1593,1596],{},[762,1594,1595],{},"Same price, set to cancel at period end",[762,1597,1598,1600],{},[215,1599,1542],{},": releases a pending schedule and clears the cancellation. Skips the hook.",[741,1602,1603,1606],{},[762,1604,1605],{},"Same price, not cancelling",[762,1607,1608,1611],{},[215,1609,1610],{},"409"," (\"already subscribed to this price\").",[741,1613,1614,1617],{},[762,1615,1616],{},"Higher plan rank",[762,1618,1619,1621,1622,1625],{},[215,1620,1523],{},": immediate, ",[215,1623,1624],{},"always_invoice"," proration; a pending schedule is released.",[741,1627,1628,1631],{},[762,1629,1630],{},"Lower or equal rank (including a monthly to yearly change)",[762,1632,1633,1635],{},[215,1634,1533],{},": deferred to the period end through a subscription schedule.",[741,1637,1638,1641],{},[762,1639,1640],{},"Existing subscription set to cancel at period end, any change",[762,1642,1643],{},"Switched immediately, which also keeps it from ending.",[741,1645,1646,1649],{},[762,1647,1648],{},"Subscription has no items, or its billing phase cannot be read",[762,1650,1651,706],{},[215,1652,1610],{},[159,1654,1655],{},"A target price outside the configured plans (only possible with no plans configured) counts as an upgrade. The local\nrow is updated by the webhook afterwards; cancellation is done in the billing portal.",[1059,1657,1659],{"id":1658},"staff-membership","Staff membership",[159,1661,1662,1663,1666,1667,1030,1669,1672,1673,1676,1677,1680,1681,1684,1685,1688,1689,1692],{},"Staff manage a user's membership through the admin routes below, authorized by the ",[215,1664,1665],{},"users:admin:authorize"," hook of\n",[163,1668,133],{"href":134},[215,1670,1671],{},"view"," for reads, ",[215,1674,1675],{},"update"," for changes). A free grant is a ",[167,1678,1679],{},"manual"," row (",[215,1682,1683],{},"source: 'manual'",",\nid ",[215,1686,1687],{},"manual_\u003Cuuid>",", no Stripe subscription) that counts as active until revoked or its optional ",[215,1690,1691],{},"endsAt"," passes.",[288,1694,1696],{"className":290,"code":1695,"language":292,"meta":293,"style":293},"\u002F\u002F GET \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription\ntype AdminMembershipResponse = {\n  plans: Array\u003C{ key: string, label: string, rank: number }>\n  current: {\n    id: string\n    planKey: string | null\n    status: string\n    source: 'stripe' | 'manual'\n    currentPeriodEnd: string | null\n    cancelAtPeriodEnd: boolean\n  } | null\n}\n\n\u002F\u002F POST \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription        body { planKey, endsAt? }   400 unknown plan or past date, 409 paid subscription exists\n\u002F\u002F DELETE \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription      404 when there is no free membership\n\u002F\u002F POST ...\u002Fsubscription\u002Fpayment-link            body { planKey?, priceId?, email? }\ntype AdminPaymentLinkResponse = { url: string, emailed: boolean }\n",[215,1697,1698,1703,1714,1754,1763,1772,1786,1795,1818,1831,1841,1850,1854,1858,1863,1868,1873],{"__ignoreMap":293},[297,1699,1700],{"class":299,"line":300},[297,1701,1702],{"class":383},"\u002F\u002F GET \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription\n",[297,1704,1705,1707,1710,1712],{"class":299,"line":322},[297,1706,1403],{"class":1402},[297,1708,1709],{"class":1107}," AdminMembershipResponse",[297,1711,1409],{"class":318},[297,1713,486],{"class":318},[297,1715,1716,1719,1721,1724,1727,1730,1732,1734,1736,1738,1740,1742,1744,1746,1748,1751],{"class":299,"line":335},[297,1717,1718],{"class":325},"  plans",[297,1720,329],{"class":318},[297,1722,1723],{"class":1107}," Array",[297,1725,1726],{"class":318},"\u003C{",[297,1728,1729],{"class":325}," key",[297,1731,329],{"class":318},[297,1733,1421],{"class":1107},[297,1735,380],{"class":318},[297,1737,509],{"class":325},[297,1739,329],{"class":318},[297,1741,1421],{"class":1107},[297,1743,380],{"class":318},[297,1745,523],{"class":325},[297,1747,329],{"class":318},[297,1749,1750],{"class":1107}," number",[297,1752,1753],{"class":318}," }>\n",[297,1755,1756,1759,1761],{"class":299,"line":349},[297,1757,1758],{"class":325},"  current",[297,1760,329],{"class":318},[297,1762,486],{"class":318},[297,1764,1765,1768,1770],{"class":299,"line":360},[297,1766,1767],{"class":325},"    id",[297,1769,329],{"class":318},[297,1771,1458],{"class":1107},[297,1773,1774,1777,1779,1781,1783],{"class":299,"line":371},[297,1775,1776],{"class":325},"    planKey",[297,1778,329],{"class":318},[297,1780,1421],{"class":1107},[297,1782,1528],{"class":318},[297,1784,1785],{"class":1107}," null\n",[297,1787,1788,1791,1793],{"class":299,"line":387},[297,1789,1790],{"class":325},"    status",[297,1792,329],{"class":318},[297,1794,1458],{"class":1107},[297,1796,1797,1800,1802,1804,1807,1809,1811,1813,1815],{"class":299,"line":398},[297,1798,1799],{"class":325},"    source",[297,1801,329],{"class":318},[297,1803,441],{"class":318},[297,1805,1806],{"class":341},"stripe",[297,1808,344],{"class":318},[297,1810,1528],{"class":318},[297,1812,441],{"class":318},[297,1814,1679],{"class":341},[297,1816,1817],{"class":318},"'\n",[297,1819,1820,1823,1825,1827,1829],{"class":299,"line":410},[297,1821,1822],{"class":325},"    currentPeriodEnd",[297,1824,329],{"class":318},[297,1826,1421],{"class":1107},[297,1828,1528],{"class":318},[297,1830,1785],{"class":1107},[297,1832,1833,1836,1838],{"class":299,"line":418},[297,1834,1835],{"class":325},"    cancelAtPeriodEnd",[297,1837,329],{"class":318},[297,1839,1840],{"class":1107}," boolean\n",[297,1842,1843,1846,1848],{"class":299,"line":478},[297,1844,1845],{"class":318},"  }",[297,1847,1528],{"class":318},[297,1849,1785],{"class":1107},[297,1851,1852],{"class":299,"line":489},[297,1853,1463],{"class":318},[297,1855,1856],{"class":299,"line":499},[297,1857,1469],{"emptyLinePlaceholder":1468},[297,1859,1860],{"class":299,"line":566},[297,1861,1862],{"class":383},"\u002F\u002F POST \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription        body { planKey, endsAt? }   400 unknown plan or past date, 409 paid subscription exists\n",[297,1864,1865],{"class":299,"line":623},[297,1866,1867],{"class":383},"\u002F\u002F DELETE \u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription      404 when there is no free membership\n",[297,1869,1870],{"class":299,"line":629},[297,1871,1872],{"class":383},"\u002F\u002F POST ...\u002Fsubscription\u002Fpayment-link            body { planKey?, priceId?, email? }\n",[297,1874,1875,1877,1880,1882,1884,1886,1888,1890,1892,1895,1897,1900],{"class":299,"line":675},[297,1876,1403],{"class":1402},[297,1878,1879],{"class":1107}," AdminPaymentLinkResponse",[297,1881,1409],{"class":318},[297,1883,426],{"class":318},[297,1885,1489],{"class":325},[297,1887,329],{"class":318},[297,1889,1421],{"class":1107},[297,1891,380],{"class":318},[297,1893,1894],{"class":325}," emailed",[297,1896,329],{"class":318},[297,1898,1899],{"class":1107}," boolean",[297,1901,1902],{"class":318}," }\n",[159,1904,1905,1906,1909,1910,1912,1913,1916,1917,1919],{},"A payment link is a Stripe Checkout session valid for 24 hours; ",[215,1907,1908],{},"email: true"," also mails it through\n",[163,1911,105],{"href":106}," (rendered from the ",[215,1914,1915],{},"subscriptions-payment-link"," template when\n",[163,1918,141],{"href":142}," is installed). The plan filter hook is not applied for staff. Granting replaces an existing manual grant.",[280,1921,1923],{"id":1922},"app","App",[159,1925,1926,1927,706],{},"Auto-imported, and also available from ",[215,1928,1929],{},"@frigear-nu\u002Fsubscriptions\u002Fcomposables",[288,1931,1933],{"className":290,"code":1932,"language":292,"meta":293,"style":293},"usePlans(): { plans, status, error, refresh }            \u002F\u002F plans sorted by rank\nuseSubscription(): {\n  subscription, plan, status, isActive, cancelsAt,\n  has(planKey: string): boolean,\n  pending, error, refresh,\n  subscribe(planKeyOrPriceId: string, options?: { successUrl?: string, cancelUrl?: string }): Promise\u003CCheckoutResponse>,\n  openPortal(returnUrl?: string): Promise\u003Cvoid>,\n}\n",[215,1934,1935,1968,1977,2003,2024,2040,2092,2117],{"__ignoreMap":293},[297,1936,1937,1940,1943,1945,1948,1950,1953,1955,1958,1960,1963,1965],{"class":299,"line":300},[297,1938,1939],{"class":310},"usePlans",[297,1941,1942],{"class":314},"(): ",[297,1944,542],{"class":318},[297,1946,1947],{"class":314}," plans",[297,1949,380],{"class":318},[297,1951,1952],{"class":314}," status",[297,1954,380],{"class":318},[297,1956,1957],{"class":314}," error",[297,1959,380],{"class":318},[297,1961,1962],{"class":314}," refresh ",[297,1964,684],{"class":318},[297,1966,1967],{"class":383},"            \u002F\u002F plans sorted by rank\n",[297,1969,1970,1973,1975],{"class":299,"line":322},[297,1971,1972],{"class":310},"useSubscription",[297,1974,1942],{"class":314},[297,1976,319],{"class":318},[297,1978,1979,1982,1984,1987,1989,1991,1993,1996,1998,2001],{"class":299,"line":335},[297,1980,1981],{"class":314},"  subscription",[297,1983,380],{"class":318},[297,1985,1986],{"class":314}," plan",[297,1988,380],{"class":318},[297,1990,1952],{"class":314},[297,1992,380],{"class":318},[297,1994,1995],{"class":314}," isActive",[297,1997,380],{"class":318},[297,1999,2000],{"class":314}," cancelsAt",[297,2002,222],{"class":318},[297,2004,2005,2008,2010,2013,2015,2017,2020,2022],{"class":299,"line":349},[297,2006,2007],{"class":325},"  has",[297,2009,315],{"class":318},[297,2011,1331],{"class":2012},"sHdIc",[297,2014,329],{"class":318},[297,2016,1421],{"class":1107},[297,2018,2019],{"class":318},"):",[297,2021,1899],{"class":1107},[297,2023,222],{"class":318},[297,2025,2026,2029,2031,2033,2035,2038],{"class":299,"line":360},[297,2027,2028],{"class":314},"  pending",[297,2030,380],{"class":318},[297,2032,1957],{"class":314},[297,2034,380],{"class":318},[297,2036,2037],{"class":314}," refresh",[297,2039,222],{"class":318},[297,2041,2042,2045,2047,2050,2052,2054,2056,2058,2060,2062,2065,2067,2069,2071,2074,2076,2078,2081,2084,2086,2089],{"class":299,"line":371},[297,2043,2044],{"class":325},"  subscribe",[297,2046,315],{"class":318},[297,2048,2049],{"class":2012},"planKeyOrPriceId",[297,2051,329],{"class":318},[297,2053,1421],{"class":1107},[297,2055,380],{"class":318},[297,2057,1086],{"class":2012},[297,2059,1089],{"class":318},[297,2061,426],{"class":318},[297,2063,2064],{"class":325}," successUrl",[297,2066,1089],{"class":318},[297,2068,1421],{"class":1107},[297,2070,380],{"class":318},[297,2072,2073],{"class":325}," cancelUrl",[297,2075,1089],{"class":318},[297,2077,1421],{"class":1107},[297,2079,2080],{"class":318}," }):",[297,2082,2083],{"class":1107}," Promise",[297,2085,1111],{"class":318},[297,2087,2088],{"class":1107},"CheckoutResponse",[297,2090,2091],{"class":318},">,\n",[297,2093,2094,2097,2099,2102,2104,2106,2108,2110,2112,2115],{"class":299,"line":387},[297,2095,2096],{"class":325},"  openPortal",[297,2098,315],{"class":318},[297,2100,2101],{"class":2012},"returnUrl",[297,2103,1089],{"class":318},[297,2105,1421],{"class":1107},[297,2107,2019],{"class":318},[297,2109,2083],{"class":1107},[297,2111,1111],{"class":318},[297,2113,2114],{"class":1107},"void",[297,2116,2091],{"class":318},[297,2118,2119],{"class":299,"line":398},[297,2120,1463],{"class":318},[159,2122,2123,2126,2127,2130,2131,2133,2134,2136,2137,2140,2141,2143],{},[215,2124,2125],{},"subscribe"," sends strings starting with ",[215,2128,2129],{},"price_"," as ",[215,2132,1021],{},", anything else as ",[215,2135,1331],{},"; it redirects to Stripe\nCheckout, or refreshes when an existing subscription was changed. ",[215,2138,2139],{},"openPortal"," redirects to the billing portal and\ndefaults ",[215,2142,2101],{}," to the current page.",[1059,2145,2147],{"id":2146},"middleware","Middleware",[288,2149,2151],{"className":290,"code":2150,"language":292,"meta":293,"style":293},"definePageMeta({\n  middleware: 'subscription',\n  subscription: { plans: ['member'], redirectTo: '\u002Fjoin' }, \u002F\u002F both optional\n})\n",[215,2152,2153,2162,2178,2221],{"__ignoreMap":293},[297,2154,2155,2158,2160],{"class":299,"line":300},[297,2156,2157],{"class":310},"definePageMeta",[297,2159,315],{"class":314},[297,2161,319],{"class":318},[297,2163,2164,2167,2169,2171,2174,2176],{"class":299,"line":322},[297,2165,2166],{"class":325},"  middleware",[297,2168,329],{"class":318},[297,2170,441],{"class":318},[297,2172,2173],{"class":341},"subscription",[297,2175,344],{"class":318},[297,2177,222],{"class":318},[297,2179,2180,2182,2184,2186,2188,2190,2192,2194,2197,2199,2202,2204,2207,2209,2211,2214,2216,2218],{"class":299,"line":335},[297,2181,1981],{"class":325},[297,2183,329],{"class":318},[297,2185,426],{"class":318},[297,2187,1947],{"class":325},[297,2189,329],{"class":318},[297,2191,539],{"class":314},[297,2193,344],{"class":318},[297,2195,2196],{"class":341},"member",[297,2198,344],{"class":318},[297,2200,2201],{"class":314},"]",[297,2203,380],{"class":318},[297,2205,2206],{"class":325}," redirectTo",[297,2208,329],{"class":318},[297,2210,441],{"class":318},[297,2212,2213],{"class":341},"\u002Fjoin",[297,2215,344],{"class":318},[297,2217,463],{"class":318},[297,2219,2220],{"class":383}," \u002F\u002F both optional\n",[297,2222,2223,2225],{"class":299,"line":349},[297,2224,684],{"class":318},[297,2226,687],{"class":314},[159,2228,2229,2230,2233,2234,2237,2238,2241,2242,706],{},"Redirects to ",[215,2231,2232],{},"redirectTo",", else to the membership page, with the original route in ",[215,2235,2236],{},"?redirect=","; without either target\nit does nothing. Anonymous users and users without an active plan are redirected, and a subscription on a price outside\nevery configured plan has no ",[215,2239,2240],{},"activePlan"," and is not let through. This guards navigation only; enforce access in API\nroutes with ",[215,2243,1125],{},[1059,2245,2247],{"id":2246},"components","Components",[159,2249,2250,1317,2253,2256,2257,2259],{},[215,2251,2252],{},"SubscriptionPlans",[215,2254,2255],{},"SubscriptionStatus"," are built on ",[215,2258,273],{}," and expose scoped slots.",[735,2261,2262,2277],{},[738,2263,2264],{},[741,2265,2266,2271,2273,2275],{},[744,2267,2268,2270],{},[215,2269,2252],{}," prop",[744,2272,749],{},[744,2274,752],{},[744,2276,755],{},[757,2278,2279,2295,2312,2330,2346,2364,2391],{},[741,2280,2281,2286,2290,2292],{},[762,2282,2283],{},[215,2284,2285],{},"locale",[762,2287,2288],{},[215,2289,826],{},[762,2291,794],{},[762,2293,2294],{},"Formatting locale.",[741,2296,2297,2302,2306,2309],{},[762,2298,2299],{},[215,2300,2301],{},"currency",[762,2303,2304],{},[215,2305,826],{},[762,2307,2308],{},"price's",[762,2310,2311],{},"Currency override for formatting.",[741,2313,2314,2319,2324,2327],{},[762,2315,2316],{},[215,2317,2318],{},"interval",[762,2320,2321],{},[215,2322,2323],{},"'day' | 'week' | 'month' | 'year'",[762,2325,2326],{},"first price",[762,2328,2329],{},"Which price to show per plan.",[741,2331,2332,2336,2340,2343],{},[762,2333,2334],{},[215,2335,766],{},[762,2337,2338],{},[215,2339,868],{},[762,2341,2342],{},"all",[762,2344,2345],{},"Only show these plan keys.",[741,2347,2348,2353,2357,2361],{},[762,2349,2350],{},[215,2351,2352],{},"confirmChange",[762,2354,2355],{},[215,2356,978],{},[762,2358,2359],{},[215,2360,983],{},[762,2362,2363],{},"Ask for confirmation before changing an existing subscription.",[741,2365,2366,2371,2376,2381],{},[762,2367,2368],{},[215,2369,2370],{},"mode",[762,2372,2373],{},[215,2374,2375],{},"'auto' | 'list' | 'tabs'",[762,2377,2378],{},[215,2379,2380],{},"'auto'",[762,2382,2383,2386,2387,2390],{},[215,2384,2385],{},"auto"," = tabs on small screens, side-by-side cards from ",[215,2388,2389],{},"sm"," up.",[741,2392,2393,2398,2402,2405],{},[762,2394,2395],{},[215,2396,2397],{},"highlight",[762,2399,2400],{},[215,2401,826],{},[762,2403,2404],{},"current plan",[762,2406,2407],{},"Plan key to emphasise.",[159,2409,2410,2411,2414,2415,2418,2419,2422,2423,706],{},"Emits ",[215,2412,2413],{},"select(plan, price)",". Each plan has a ",[215,2416,2417],{},"state",": ",[215,2420,2421],{},"'current' | 'upgrade' | 'downgrade' | 'subscribe'",". Visitors who\nare not signed in are sent to the Users register page with ",[215,2424,2425],{},"?redirect=\u003Cmembership page>?plan=\u003Ckey>",[735,2427,2428,2441],{},[738,2429,2430],{},[741,2431,2432,2435,2438],{},[744,2433,2434],{},"Component",[744,2436,2437],{},"Slot",[744,2439,2440],{},"Slot props",[757,2442,2443,2459,2476,2490,2504,2518,2532,2546,2566,2580,2593,2607],{},[741,2444,2445,2449,2457],{},[762,2446,2447],{},[215,2448,2252],{},[762,2450,2451,228,2454],{},[215,2452,2453],{},"loading",[215,2455,2456],{},"empty",[762,2458,794],{},[741,2460,2461,2463,2471],{},[762,2462],{},[762,2464,2465,228,2468],{},[215,2466,2467],{},"header",[215,2469,2470],{},"badge",[762,2472,2473],{},[215,2474,2475],{},"{ plan, state }",[741,2477,2478,2480,2485],{},[762,2479],{},[762,2481,2482],{},[215,2483,2484],{},"price",[762,2486,2487],{},[215,2488,2489],{},"{ plan, price, formatPrice, intervalLabel }",[741,2491,2492,2494,2499],{},[762,2493],{},[762,2495,2496],{},[215,2497,2498],{},"features",[762,2500,2501],{},[215,2502,2503],{},"{ plan }",[741,2505,2506,2508,2513],{},[762,2507],{},[762,2509,2510],{},[215,2511,2512],{},"action",[762,2514,2515],{},[215,2516,2517],{},"{ plan, state, pending, select }",[741,2519,2520,2522,2527],{},[762,2521],{},[762,2523,2524],{},[215,2525,2526],{},"confirm",[762,2528,2529],{},[215,2530,2531],{},"{ plan, price }",[741,2533,2534,2536,2541],{},[762,2535],{},[762,2537,2538],{},[215,2539,2540],{},"confirm-actions",[762,2542,2543],{},[215,2544,2545],{},"{ plan, price, confirm }",[741,2547,2548,2552,2560],{},[762,2549,2550],{},[215,2551,2255],{},[762,2553,2554,228,2556,228,2558],{},[215,2555,2467],{},[215,2557,2453],{},[215,2559,2456],{},[762,2561,2562,2563,2565],{},"- (prop ",[215,2564,2285],{},")",[741,2567,2568,2570,2575],{},[762,2569],{},[762,2571,2572],{},[215,2573,2574],{},"plan",[762,2576,2577],{},[215,2578,2579],{},"{ plan, label, subscription }",[741,2581,2582,2584,2588],{},[762,2583],{},[762,2585,2586],{},[215,2587,2470],{},[762,2589,2590],{},[215,2591,2592],{},"{ subscription, badge }",[741,2594,2595,2597,2602],{},[762,2596],{},[762,2598,2599],{},[215,2600,2601],{},"dates",[762,2603,2604],{},[215,2605,2606],{},"{ subscription, cancelsAt, dateText }",[741,2608,2609,2611,2616],{},[762,2610],{},[762,2612,2613],{},[215,2614,2615],{},"actions",[762,2617,2618],{},[215,2619,2620],{},"{ manage, resubscribe, cancelling, pending }",[159,2622,2623,2626,2627,2630,2631,2634],{},[215,2624,2625],{},"UsersAdminMembership"," (prop ",[215,2628,2629],{},"user",", emits ",[215,2632,2633],{},"refresh",") is the staff grant and revoke panel used by the admin user tab.",[1059,2636,2638],{"id":2637},"pages-and-menu","Pages and menu",[159,2640,2641,2642,2645,2646,2649,2650,2653,2654,2657,2658,2661,2662,2665,2666,2668,2669,2671,2672,2675,2676,2680,2681,228,2683,2686,2687,2690,2691,2694,2695,2698],{},"Each enabled page in ",[215,2643,2644],{},"settings.pages"," is added at its path (skipped if the path already exists): the membership page\n(a ",[215,2647,2648],{},"SectionCard"," with the status when subscribed, then the plans with confirmation), a success page (polls ",[215,2651,2652],{},"me"," up to five\ntimes, two seconds apart, while the webhook lands) and a cancel page. The pages sit under ",[215,2655,2656],{},"\u002Faccount\u002F**",", so they render\nno container or page heading of their own (the ",[215,2659,2660],{},"account"," layout provides both); success and cancel are empty states\nwith one action, ",[167,2663,2664],{},"Back to membership",". With ",[163,2667,97],{"href":98}," and the membership page enabled, a \"Subscription\"\nitem (order 15) is added to the ",[215,2670,2660],{}," menu (the account tile and left navigation). With Widget installed, a\nmembership summary is added to the ",[215,2673,2674],{},"account.overview"," widget area. With Widget and Admin installed, the admin user page\ngains a ",[2677,2678,2679],"em",{},"Subscription"," tab (order 10, built from ",[215,2682,2648],{},[215,2684,2685],{},"DescriptionList"," and a history table) and a ",[2677,2688,2689],{},"Current\nsubscription"," card (",[215,2692,2693],{},"admin.users"," tab area, ",[215,2696,2697],{},"admin.users.overview"," widget area). Revoking a free membership asks for\nconfirmation first.",[280,2700,2701],{"id":193},"Hooks",[159,2703,2704,2705,2708],{},"Register with ",[215,2706,2707],{},"nitro.hooks.hook(...)"," in a Nitro plugin. The module contains no seasonal or pricing rules.",[735,2710,2711,2724],{},[738,2712,2713],{},[741,2714,2715,2718,2721],{},[744,2716,2717],{},"Hook",[744,2719,2720],{},"When",[744,2722,2723],{},"Payload",[757,2725,2726,2743],{},[741,2727,2728,2733,2738],{},[762,2729,2730],{},[215,2731,2732],{},"subscriptions:checkout:before",[762,2734,2735,2736,706],{},"After validation and the kind decision, for new checkouts and plan changes. Throw to deny. Not run for ",[215,2737,1542],{},[762,2739,2740],{},[215,2741,2742],{},"CheckoutBeforeContext",[741,2744,2745,2749,2755],{},[762,2746,2747],{},[215,2748,1289],{},[762,2750,2751,2752,706],{},"Whenever plans are listed or checked (also gates checkout). Mutate or reassign ",[215,2753,2754],{},"ctx.plans",[762,2756,2757],{},[215,2758,2759],{},"PlansFilterContext",[288,2761,2763],{"className":290,"code":2762,"language":292,"meta":293,"style":293},"type CheckoutBeforeContext = {\n  event: H3Event\n  userId: number\n  planKey: string | null\n  priceId: string\n  kind: 'checkout' | 'upgrade' | 'downgrade'\n  params: Stripe.Checkout.SessionCreateParams   \u002F\u002F only used when kind === 'checkout'\n}\n\ntype PlansFilterContext = {\n  event: H3Event | undefined   \u002F\u002F undefined outside a request\n  plans: ResolvedPlan[]        \u002F\u002F a copy of the cached plans\n}\n\ntype ResolvedPlan = { key: string, label: string, description?: string, rank: number, features?: string[], prices: PlanPrice[] }\ntype PlanPrice = {\n  id: string\n  amount: number | null           \u002F\u002F minor units\n  currency: string\n  interval: 'day' | 'week' | 'month' | 'year'\n  intervalCount: number\n  trialPeriodDays: number | null\n  lookupKey: string | null\n}\n",[215,2764,2765,2776,2786,2796,2808,2816,2845,2867,2871,2875,2886,2903,2918,2922,2926,2993,3003,3012,3029,3039,3081,3091,3105,3119],{"__ignoreMap":293},[297,2766,2767,2769,2772,2774],{"class":299,"line":300},[297,2768,1403],{"class":1402},[297,2770,2771],{"class":1107}," CheckoutBeforeContext",[297,2773,1409],{"class":318},[297,2775,486],{"class":318},[297,2777,2778,2781,2783],{"class":299,"line":322},[297,2779,2780],{"class":325},"  event",[297,2782,329],{"class":318},[297,2784,2785],{"class":1107}," H3Event\n",[297,2787,2788,2791,2793],{"class":299,"line":335},[297,2789,2790],{"class":325},"  userId",[297,2792,329],{"class":318},[297,2794,2795],{"class":1107}," number\n",[297,2797,2798,2800,2802,2804,2806],{"class":299,"line":349},[297,2799,1416],{"class":325},[297,2801,329],{"class":318},[297,2803,1421],{"class":1107},[297,2805,1528],{"class":318},[297,2807,1785],{"class":1107},[297,2809,2810,2812,2814],{"class":299,"line":360},[297,2811,1429],{"class":325},[297,2813,329],{"class":318},[297,2815,1458],{"class":1107},[297,2817,2818,2821,2823,2825,2827,2829,2831,2833,2835,2837,2839,2841,2843],{"class":299,"line":371},[297,2819,2820],{"class":325},"  kind",[297,2822,329],{"class":318},[297,2824,441],{"class":318},[297,2826,1382],{"class":341},[297,2828,344],{"class":318},[297,2830,1528],{"class":318},[297,2832,441],{"class":318},[297,2834,1523],{"class":341},[297,2836,344],{"class":318},[297,2838,1528],{"class":318},[297,2840,441],{"class":318},[297,2842,1533],{"class":341},[297,2844,1817],{"class":318},[297,2846,2847,2850,2852,2855,2857,2859,2861,2864],{"class":299,"line":387},[297,2848,2849],{"class":325},"  params",[297,2851,329],{"class":318},[297,2853,2854],{"class":1107}," Stripe",[297,2856,706],{"class":318},[297,2858,1383],{"class":1107},[297,2860,706],{"class":318},[297,2862,2863],{"class":1107},"SessionCreateParams",[297,2865,2866],{"class":383},"   \u002F\u002F only used when kind === 'checkout'\n",[297,2868,2869],{"class":299,"line":398},[297,2870,1463],{"class":318},[297,2872,2873],{"class":299,"line":410},[297,2874,1469],{"emptyLinePlaceholder":1468},[297,2876,2877,2879,2882,2884],{"class":299,"line":418},[297,2878,1403],{"class":1402},[297,2880,2881],{"class":1107}," PlansFilterContext",[297,2883,1409],{"class":318},[297,2885,486],{"class":318},[297,2887,2888,2890,2892,2895,2897,2900],{"class":299,"line":478},[297,2889,2780],{"class":325},[297,2891,329],{"class":318},[297,2893,2894],{"class":1107}," H3Event",[297,2896,1528],{"class":318},[297,2898,2899],{"class":1107}," undefined",[297,2901,2902],{"class":383},"   \u002F\u002F undefined outside a request\n",[297,2904,2905,2907,2909,2912,2915],{"class":299,"line":489},[297,2906,1718],{"class":325},[297,2908,329],{"class":318},[297,2910,2911],{"class":1107}," ResolvedPlan",[297,2913,2914],{"class":314},"[]        ",[297,2916,2917],{"class":383},"\u002F\u002F a copy of the cached plans\n",[297,2919,2920],{"class":299,"line":499},[297,2921,1463],{"class":318},[297,2923,2924],{"class":299,"line":566},[297,2925,1469],{"emptyLinePlaceholder":1468},[297,2927,2928,2930,2932,2934,2936,2938,2940,2942,2944,2946,2948,2950,2952,2955,2957,2959,2961,2963,2965,2967,2969,2972,2974,2976,2979,2981,2983,2985,2988,2991],{"class":299,"line":623},[297,2929,1403],{"class":1402},[297,2931,2911],{"class":1107},[297,2933,1409],{"class":318},[297,2935,426],{"class":318},[297,2937,1729],{"class":325},[297,2939,329],{"class":318},[297,2941,1421],{"class":1107},[297,2943,380],{"class":318},[297,2945,509],{"class":325},[297,2947,329],{"class":318},[297,2949,1421],{"class":1107},[297,2951,380],{"class":318},[297,2953,2954],{"class":325}," description",[297,2956,1089],{"class":318},[297,2958,1421],{"class":1107},[297,2960,380],{"class":318},[297,2962,523],{"class":325},[297,2964,329],{"class":318},[297,2966,1750],{"class":1107},[297,2968,380],{"class":318},[297,2970,2971],{"class":325}," features",[297,2973,1089],{"class":318},[297,2975,1421],{"class":1107},[297,2977,2978],{"class":314},"[]",[297,2980,380],{"class":318},[297,2982,534],{"class":325},[297,2984,329],{"class":318},[297,2986,2987],{"class":1107}," PlanPrice",[297,2989,2990],{"class":314},"[] ",[297,2992,1463],{"class":318},[297,2994,2995,2997,2999,3001],{"class":299,"line":629},[297,2996,1403],{"class":1402},[297,2998,2987],{"class":1107},[297,3000,1409],{"class":318},[297,3002,486],{"class":318},[297,3004,3005,3008,3010],{"class":299,"line":675},[297,3006,3007],{"class":325},"  id",[297,3009,329],{"class":318},[297,3011,1458],{"class":1107},[297,3013,3014,3017,3019,3021,3023,3026],{"class":299,"line":681},[297,3015,3016],{"class":325},"  amount",[297,3018,329],{"class":318},[297,3020,1750],{"class":1107},[297,3022,1528],{"class":318},[297,3024,3025],{"class":1107}," null",[297,3027,3028],{"class":383},"           \u002F\u002F minor units\n",[297,3030,3032,3035,3037],{"class":299,"line":3031},19,[297,3033,3034],{"class":325},"  currency",[297,3036,329],{"class":318},[297,3038,1458],{"class":1107},[297,3040,3042,3045,3047,3049,3052,3054,3056,3058,3061,3063,3065,3067,3070,3072,3074,3076,3079],{"class":299,"line":3041},20,[297,3043,3044],{"class":325},"  interval",[297,3046,329],{"class":318},[297,3048,441],{"class":318},[297,3050,3051],{"class":341},"day",[297,3053,344],{"class":318},[297,3055,1528],{"class":318},[297,3057,441],{"class":318},[297,3059,3060],{"class":341},"week",[297,3062,344],{"class":318},[297,3064,1528],{"class":318},[297,3066,441],{"class":318},[297,3068,3069],{"class":341},"month",[297,3071,344],{"class":318},[297,3073,1528],{"class":318},[297,3075,441],{"class":318},[297,3077,3078],{"class":341},"year",[297,3080,1817],{"class":318},[297,3082,3084,3087,3089],{"class":299,"line":3083},21,[297,3085,3086],{"class":325},"  intervalCount",[297,3088,329],{"class":318},[297,3090,2795],{"class":1107},[297,3092,3094,3097,3099,3101,3103],{"class":299,"line":3093},22,[297,3095,3096],{"class":325},"  trialPeriodDays",[297,3098,329],{"class":318},[297,3100,1750],{"class":1107},[297,3102,1528],{"class":318},[297,3104,1785],{"class":1107},[297,3106,3108,3111,3113,3115,3117],{"class":299,"line":3107},23,[297,3109,3110],{"class":325},"  lookupKey",[297,3112,329],{"class":318},[297,3114,1421],{"class":1107},[297,3116,1528],{"class":318},[297,3118,1785],{"class":1107},[297,3120,3122],{"class":299,"line":3121},24,[297,3123,1463],{"class":318},[159,3125,3126,3127,3130,3131,3134,3135,228,3138,228,3141,3144,3145,1030,3148,228,3151,3153,3154,3157],{},"The default ",[215,3128,3129],{},"params"," are ",[215,3132,3133],{},"mode: 'subscription'",", the line item, ",[215,3136,3137],{},"success_url",[215,3139,3140],{},"cancel_url",[215,3142,3143],{},"client_reference_id"," (the\nuser id) and ",[215,3146,3147],{},"subscription_data.metadata",[215,3149,3150],{},"userId",[215,3152,1331],{},"); the Stripe ",[215,3155,3156],{},"customer"," is added afterwards.",[288,3159,3161],{"className":290,"code":3160,"language":292,"meta":293,"style":293},"export default defineNitroPlugin((nitro) => {\n  nitro.hooks.hook('subscriptions:checkout:before', (ctx) => {\n    if (!isSignupSeason(new Date())) throw createError({ statusCode: 403, statusMessage: 'Sign-up is closed' })\n    if (ctx.kind === 'checkout') ctx.params.metadata = { ...ctx.params.metadata, source: 'website' }\n  })\n})\n",[215,3162,3163,3186,3221,3281,3350,3356],{"__ignoreMap":293},[297,3164,3165,3167,3169,3172,3174,3176,3179,3181,3184],{"class":299,"line":300},[297,3166,304],{"class":303},[297,3168,307],{"class":303},[297,3170,3171],{"class":310}," defineNitroPlugin",[297,3173,315],{"class":314},[297,3175,315],{"class":318},[297,3177,3178],{"class":2012},"nitro",[297,3180,2565],{"class":318},[297,3182,3183],{"class":1402}," =>",[297,3185,486],{"class":318},[297,3187,3188,3191,3193,3195,3197,3200,3202,3204,3206,3208,3210,3212,3215,3217,3219],{"class":299,"line":322},[297,3189,3190],{"class":314},"  nitro",[297,3192,706],{"class":318},[297,3194,193],{"class":314},[297,3196,706],{"class":318},[297,3198,3199],{"class":310},"hook",[297,3201,315],{"class":325},[297,3203,344],{"class":318},[297,3205,2732],{"class":341},[297,3207,344],{"class":318},[297,3209,380],{"class":318},[297,3211,1030],{"class":318},[297,3213,3214],{"class":2012},"ctx",[297,3216,2565],{"class":318},[297,3218,3183],{"class":1402},[297,3220,486],{"class":318},[297,3222,3223,3226,3228,3231,3234,3236,3239,3242,3245,3248,3251,3253,3255,3258,3260,3263,3265,3268,3270,3272,3275,3277,3279],{"class":299,"line":335},[297,3224,3225],{"class":303},"    if",[297,3227,1030],{"class":325},[297,3229,3230],{"class":318},"!",[297,3232,3233],{"class":310},"isSignupSeason",[297,3235,315],{"class":325},[297,3237,3238],{"class":318},"new",[297,3240,3241],{"class":310}," Date",[297,3243,3244],{"class":325},"())) ",[297,3246,3247],{"class":303},"throw",[297,3249,3250],{"class":310}," createError",[297,3252,315],{"class":325},[297,3254,542],{"class":318},[297,3256,3257],{"class":325}," statusCode",[297,3259,329],{"class":318},[297,3261,3262],{"class":528}," 403",[297,3264,380],{"class":318},[297,3266,3267],{"class":325}," statusMessage",[297,3269,329],{"class":318},[297,3271,441],{"class":318},[297,3273,3274],{"class":341},"Sign-up is closed",[297,3276,344],{"class":318},[297,3278,557],{"class":318},[297,3280,687],{"class":325},[297,3282,3283,3285,3287,3289,3291,3294,3297,3299,3301,3303,3306,3308,3310,3312,3314,3317,3319,3321,3324,3326,3328,3330,3332,3334,3336,3339,3341,3343,3346,3348],{"class":299,"line":349},[297,3284,3225],{"class":303},[297,3286,1030],{"class":325},[297,3288,3214],{"class":314},[297,3290,706],{"class":318},[297,3292,3293],{"class":314},"kind",[297,3295,3296],{"class":318}," ===",[297,3298,441],{"class":318},[297,3300,1382],{"class":341},[297,3302,344],{"class":318},[297,3304,3305],{"class":325},") ",[297,3307,3214],{"class":314},[297,3309,706],{"class":318},[297,3311,3129],{"class":314},[297,3313,706],{"class":318},[297,3315,3316],{"class":314},"metadata",[297,3318,1409],{"class":318},[297,3320,426],{"class":318},[297,3322,3323],{"class":318}," ...",[297,3325,3214],{"class":314},[297,3327,706],{"class":318},[297,3329,3129],{"class":314},[297,3331,706],{"class":318},[297,3333,3316],{"class":314},[297,3335,380],{"class":318},[297,3337,3338],{"class":325}," source",[297,3340,329],{"class":318},[297,3342,441],{"class":318},[297,3344,3345],{"class":341},"website",[297,3347,344],{"class":318},[297,3349,1902],{"class":318},[297,3351,3352,3354],{"class":299,"line":360},[297,3353,1845],{"class":318},[297,3355,687],{"class":325},[297,3357,3358,3360],{"class":299,"line":371},[297,3359,684],{"class":318},[297,3361,687],{"class":314},[280,3363,3365],{"id":3364},"routes","Routes",[735,3367,3368,3382],{},[738,3369,3370],{},[741,3371,3372,3375,3378,3380],{},[744,3373,3374],{},"Method",[744,3376,3377],{},"Path",[744,3379,73],{},[744,3381,755],{},[757,3383,3384,3407,3432,3455,3477,3495,3515,3532,3550],{},[741,3385,3386,3389,3394,3397],{},[762,3387,3388],{},"GET",[762,3390,3391],{},[215,3392,3393],{},"\u002Fapi\u002Fsubscriptions\u002Fplans",[762,3395,3396],{},"public",[762,3398,3399,3402,3403,3406],{},[215,3400,3401],{},"{ plans: ResolvedPlan[] }",", after the ",[215,3404,3405],{},"plans:filter"," hook.",[741,3408,3409,3411,3416,3425],{},[762,3410,3388],{},[762,3412,3413],{},[215,3414,3415],{},"\u002Fapi\u002Fsubscriptions\u002Fme",[762,3417,3418,3421,3422],{},[215,3419,3420],{},"requireUser",", scope ",[215,3423,3424],{},"subscriptions:read",[762,3426,3427,3429,3430,706],{},[215,3428,1277],{},": all subscriptions plus ",[215,3431,2240],{},[741,3433,3434,3437,3442,3449],{},[762,3435,3436],{},"POST",[762,3438,3439],{},[215,3440,3441],{},"\u002Fapi\u002Fsubscriptions\u002Fcheckout",[762,3443,3444,3421,3446],{},[215,3445,3420],{},[215,3447,3448],{},"subscriptions:write",[762,3450,3451,3452,706],{},"New checkout or plan change, see ",[163,3453,1383],{"href":3454},"#checkout",[741,3456,3457,3459,3464,3467],{},[762,3458,3436],{},[762,3460,3461],{},[215,3462,3463],{},"\u002Fapi\u002Fsubscriptions\u002Fportal",[762,3465,3466],{},"session only",[762,3468,3469,3470,3473,3474,3476],{},"Body ",[215,3471,3472],{},"{ returnUrl? }"," (same origin, else 400). Returns ",[215,3475,1590],{}," of a billing portal session.",[741,3478,3479,3481,3486,3492],{},[762,3480,3388],{},[762,3482,3483],{},[215,3484,3485],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription",[762,3487,3488,1030,3490,2565],{},[215,3489,1665],{},[215,3491,1671],{},[762,3493,3494],{},"Current membership and plans.",[741,3496,3497,3499,3504,3510],{},[762,3498,3388],{},[762,3500,3501],{},[215,3502,3503],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscriptions",[762,3505,3506,1030,3508,2565],{},[215,3507,1665],{},[215,3509,1671],{},[762,3511,3512,3513,706],{},"Full history including ended rows, as ",[215,3514,1277],{},[741,3516,3517,3519,3523,3529],{},[762,3518,3436],{},[762,3520,3521],{},[215,3522,3485],{},[762,3524,3525,1030,3527,2565],{},[215,3526,1665],{},[215,3528,1675],{},[762,3530,3531],{},"Grant a free membership.",[741,3533,3534,3537,3541,3547],{},[762,3535,3536],{},"DELETE",[762,3538,3539],{},[215,3540,3485],{},[762,3542,3543,1030,3545,2565],{},[215,3544,1665],{},[215,3546,1675],{},[762,3548,3549],{},"Revoke a free membership.",[741,3551,3552,3554,3559,3565],{},[762,3553,3436],{},[762,3555,3556],{},[215,3557,3558],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fsubscription\u002Fpayment-link",[762,3560,3561,1030,3563,2565],{},[215,3562,1665],{},[215,3564,1675],{},[762,3566,3567],{},"Create (and optionally email) a checkout link.",[159,3569,3570,3571,2130,3573,3575,3576,3578],{},"The scoped user routes also accept bearer and OAuth tokens that carry the scope. The scopes are registered with\n",[163,3572,73],{"href":74},[215,3574,3424],{}," (\"Read your subscription and plans\") and ",[215,3577,3448],{}," (\"Start a\nsubscription checkout\").",[288,3580,3582],{"className":290,"code":3581,"language":292,"meta":293,"style":293},"type SubscriptionDto = {\n  id: string\n  planKey: string | null\n  priceId: string\n  status: string                      \u002F\u002F raw Stripe status\n  cancelAtPeriodEnd: boolean\n  currentPeriodStart: string | null   \u002F\u002F ISO\n  currentPeriodEnd: string | null\n  endedAt: string | null\n  source?: 'stripe' | 'manual'        \u002F\u002F 'manual' for free grants made by staff\n}\n\ntype MeResponse = {\n  subscriptions: SubscriptionDto[]\n  activePlan: string | null           \u002F\u002F plan of the entitled subscription with the latest period end\n}\n",[215,3583,3584,3595,3603,3615,3623,3635,3644,3660,3673,3686,3710,3714,3718,3729,3740,3756],{"__ignoreMap":293},[297,3585,3586,3588,3591,3593],{"class":299,"line":300},[297,3587,1403],{"class":1402},[297,3589,3590],{"class":1107}," SubscriptionDto",[297,3592,1409],{"class":318},[297,3594,486],{"class":318},[297,3596,3597,3599,3601],{"class":299,"line":322},[297,3598,3007],{"class":325},[297,3600,329],{"class":318},[297,3602,1458],{"class":1107},[297,3604,3605,3607,3609,3611,3613],{"class":299,"line":335},[297,3606,1416],{"class":325},[297,3608,329],{"class":318},[297,3610,1421],{"class":1107},[297,3612,1528],{"class":318},[297,3614,1785],{"class":1107},[297,3616,3617,3619,3621],{"class":299,"line":349},[297,3618,1429],{"class":325},[297,3620,329],{"class":318},[297,3622,1458],{"class":1107},[297,3624,3625,3628,3630,3632],{"class":299,"line":360},[297,3626,3627],{"class":325},"  status",[297,3629,329],{"class":318},[297,3631,1421],{"class":1107},[297,3633,3634],{"class":383},"                      \u002F\u002F raw Stripe status\n",[297,3636,3637,3640,3642],{"class":299,"line":371},[297,3638,3639],{"class":325},"  cancelAtPeriodEnd",[297,3641,329],{"class":318},[297,3643,1840],{"class":1107},[297,3645,3646,3649,3651,3653,3655,3657],{"class":299,"line":387},[297,3647,3648],{"class":325},"  currentPeriodStart",[297,3650,329],{"class":318},[297,3652,1421],{"class":1107},[297,3654,1528],{"class":318},[297,3656,3025],{"class":1107},[297,3658,3659],{"class":383},"   \u002F\u002F ISO\n",[297,3661,3662,3665,3667,3669,3671],{"class":299,"line":398},[297,3663,3664],{"class":325},"  currentPeriodEnd",[297,3666,329],{"class":318},[297,3668,1421],{"class":1107},[297,3670,1528],{"class":318},[297,3672,1785],{"class":1107},[297,3674,3675,3678,3680,3682,3684],{"class":299,"line":410},[297,3676,3677],{"class":325},"  endedAt",[297,3679,329],{"class":318},[297,3681,1421],{"class":1107},[297,3683,1528],{"class":318},[297,3685,1785],{"class":1107},[297,3687,3688,3691,3693,3695,3697,3699,3701,3703,3705,3707],{"class":299,"line":418},[297,3689,3690],{"class":325},"  source",[297,3692,1089],{"class":318},[297,3694,441],{"class":318},[297,3696,1806],{"class":341},[297,3698,344],{"class":318},[297,3700,1528],{"class":318},[297,3702,441],{"class":318},[297,3704,1679],{"class":341},[297,3706,344],{"class":318},[297,3708,3709],{"class":383},"        \u002F\u002F 'manual' for free grants made by staff\n",[297,3711,3712],{"class":299,"line":478},[297,3713,1463],{"class":318},[297,3715,3716],{"class":299,"line":489},[297,3717,1469],{"emptyLinePlaceholder":1468},[297,3719,3720,3722,3725,3727],{"class":299,"line":499},[297,3721,1403],{"class":1402},[297,3723,3724],{"class":1107}," MeResponse",[297,3726,1409],{"class":318},[297,3728,486],{"class":318},[297,3730,3731,3733,3735,3737],{"class":299,"line":566},[297,3732,481],{"class":325},[297,3734,329],{"class":318},[297,3736,3590],{"class":1107},[297,3738,3739],{"class":314},"[]\n",[297,3741,3742,3745,3747,3749,3751,3753],{"class":299,"line":623},[297,3743,3744],{"class":325},"  activePlan",[297,3746,329],{"class":318},[297,3748,1421],{"class":1107},[297,3750,1528],{"class":318},[297,3752,3025],{"class":1107},[297,3754,3755],{"class":383},"           \u002F\u002F plan of the entitled subscription with the latest period end\n",[297,3757,3758],{"class":299,"line":629},[297,3759,1463],{"class":318},[280,3761,705],{"id":3762},"stripe-dashboard-setup",[689,3764,3765,3789,3795],{},[178,3766,3767,3770,3771,3774,3775,228,3777,228,3780,228,3783,1317,3786,706],{},[167,3768,3769],{},"API keys and webhook",": configure ",[163,3772,121],{"href":3773},"\u002Fmodules\u002Fstripe#stripe-dashboard-setup"," and subscribe the endpoint to\n",[215,3776,1307],{},[215,3778,3779],{},".updated",[215,3781,3782],{},".deleted",[215,3784,3785],{},".paused",[215,3787,3788],{},".resumed",[178,3790,3791,3794],{},[167,3792,3793],{},"Products and prices",": create recurring prices. Use lookup keys to keep config environment-independent (test and\nlive have different price ids). No metadata or copy is needed in Stripe.",[178,3796,3797,3800,3801,3804],{},[167,3798,3799],{},"Billing portal"," (Settings > Billing > Customer portal): enable cancellation and payment method updates. Enable\nsubscription updates only with ",[215,3802,3803],{},"allowChangeInPortal: true",", and list the prices the portal may switch between.",[280,3806,713],{"id":3807},"database",[159,3809,3810,3811,3814],{},"One ",[215,3812,3813],{},"subscriptions"," table.",[735,3816,3817,3829],{},[738,3818,3819],{},[741,3820,3821,3824,3826],{},[744,3822,3823],{},"Column",[744,3825,749],{},[744,3827,3828],{},"Notes",[757,3830,3831,3851,3866,3880,3892,3904,3915,3934,3950,3963],{},[741,3832,3833,3838,3841],{},[762,3834,3835],{},[215,3836,3837],{},"id",[762,3839,3840],{},"text, primary key",[762,3842,3843,3844,3847,3848,3850],{},"Stripe subscription id (",[215,3845,3846],{},"sub_...","), or ",[215,3849,1687],{}," for free grants.",[741,3852,3853,3857,3860],{},[762,3854,3855],{},[215,3856,3150],{},[762,3858,3859],{},"integer",[762,3861,3862,3863,706],{},"Indexed; no foreign key. The webhook resolves it through ",[215,3864,3865],{},"users.stripeCustomerId",[741,3867,3868,3872,3875],{},[762,3869,3870],{},[215,3871,1331],{},[762,3873,3874],{},"text, nullable",[762,3876,3877,3879],{},[215,3878,1241],{}," when the price is in no configured plan, so config changes never lose data.",[741,3881,3882,3886,3889],{},[762,3883,3884],{},[215,3885,1021],{},[762,3887,3888],{},"text",[762,3890,3891],{},"Empty for manual grants.",[741,3893,3894,3899,3901],{},[762,3895,3896],{},[215,3897,3898],{},"status",[762,3900,3888],{},[762,3902,3903],{},"Raw Stripe status.",[741,3905,3906,3911,3913],{},[762,3907,3908],{},[215,3909,3910],{},"cancelAtPeriodEnd",[762,3912,978],{},[762,3914],{},[741,3916,3917,3926,3929],{},[762,3918,3919,228,3922,228,3924],{},[215,3920,3921],{},"currentPeriodStart",[215,3923,1184],{},[215,3925,1188],{},[762,3927,3928],{},"timestamps, nullable",[762,3930,3931,3933],{},[215,3932,1184],{}," on a manual grant is its optional end date.",[741,3935,3936,3941,3943],{},[762,3937,3938],{},[215,3939,3940],{},"source",[762,3942,3888],{},[762,3944,3945,3947,3948,706],{},[215,3946,1806],{}," (default) or ",[215,3949,1679],{},[741,3951,3952,3957,3960],{},[762,3953,3954],{},[215,3955,3956],{},"rawItems",[762,3958,3959],{},"JSON, nullable",[762,3961,3962],{},"Item id, price id, lookup key, quantity.",[741,3964,3965,3973,3976],{},[762,3966,3967,228,3970],{},[215,3968,3969],{},"createdAt",[215,3971,3972],{},"updatedAt",[762,3974,3975],{},"timestamps",[762,3977],{},[159,3979,3980,3981,706],{},"Rows are never deleted; ended subscriptions get ",[215,3982,1188],{},[3984,3985,3986,3987,3990,3991,3994,3995,3998,3999,706],"warning",{},"The module ships no migration: generate and commit one in every host app and fixture, covering this table ",[167,3988,3989],{},"and"," the\n",[215,3992,3993],{},"users.stripe_customer_id"," column from ",[163,3996,121],{"href":3997},"\u002Fmodules\u002Fstripe#database",". See ",[163,4000,101],{"href":102},[280,4002,4004],{"id":4003},"translations","Translations",[159,4006,4007,1317,4010,4013,4014,4017,4018,4021,4022,4025,4026,4030,4031,706],{},[215,4008,4009],{},"da",[215,4011,4012],{},"en"," locale files are registered with ",[163,4015,101],{"href":4016},"\u002Fmodules\u002Fmodule-kit#translations-i18n","; components read them\nthrough ",[215,4019,4020],{},"useModuleT('subscriptions.\u003Cgroup>')",". Override any key in your app's ",[215,4023,4024],{},"i18n\u002Flocales\u002F\u003Ccode>.json"," (see\n",[163,4027,4029],{"href":4028},"\u002Fmodules\u002Fmodule-kit#overriding-module-strings-in-your-app","overriding module strings","). Parameters use ",[215,4032,4033],{},"{name}",[735,4035,4036,4046],{},[738,4037,4038],{},[741,4039,4040,4043],{},[744,4041,4042],{},"Group",[744,4044,4045],{},"Keys",[757,4047,4048,4098,4119,4165,4187,4201,4217],{},[741,4049,4050,4055],{},[762,4051,4052],{},[215,4053,4054],{},"plans.*",[762,4056,4057,228,4059,228,4061,228,4064,228,4066,228,4068,228,4070,1030,4073,4076,4077,228,4080,1030,4083,4076,4086,228,4088,228,4091,228,4094,4097],{},[215,4058,2453],{},[215,4060,2456],{},[215,4062,4063],{},"current",[215,4065,2125],{},[215,4067,1523],{},[215,4069,1533],{},[215,4071,4072],{},"trial",[215,4074,4075],{},"{days}","), ",[215,4078,4079],{},"confirmTitle",[215,4081,4082],{},"confirmBody",[215,4084,4085],{},"{plan}",[215,4087,2526],{},[215,4089,4090],{},"cancel",[215,4092,4093],{},"select",[215,4095,4096],{},"resubscribe"," and the checkout, upgrade and downgrade confirmation texts.",[741,4099,4100,4105],{},[762,4101,4102],{},[215,4103,4104],{},"interval.*",[762,4106,4107,228,4109,228,4111,228,4113,4115,4116,706],{},[215,4108,3051],{},[215,4110,3060],{},[215,4112,3069],{},[215,4114,3078],{},", their plurals, and ",[215,4117,4118],{},"quarter",[741,4120,4121,4126],{},[762,4122,4123],{},[215,4124,4125],{},"status.*",[762,4127,4128,228,4130,228,4133,228,4136,1030,4139,4076,4142,1030,4145,4076,4147,228,4150,228,4152,228,4154,228,4156,228,4159,228,4161,4164],{},[215,4129,2453],{},[215,4131,4132],{},"title",[215,4134,4135],{},"none",[215,4137,4138],{},"renews",[215,4140,4141],{},"{date}",[215,4143,4144],{},"cancels",[215,4146,4141],{},[215,4148,4149],{},"manage",[215,4151,4096],{},[215,4153,1555],{},[215,4155,1558],{},[215,4157,4158],{},"pastDue",[215,4160,1343],{},[215,4162,4163],{},"other",", plus the status card texts.",[741,4166,4167,4175],{},[762,4168,4169,228,4172],{},[215,4170,4171],{},"success.*",[215,4173,4174],{},"cancel.*",[762,4176,4177,4178,228,4180,228,4183,4186],{},"Page texts: ",[215,4179,4132],{},[215,4181,4182],{},"body",[215,4184,4185],{},"back"," (\"Back to membership\").",[741,4188,4189,4194],{},[762,4190,4191],{},[215,4192,4193],{},"errors.*",[762,4195,4196,228,4198,706],{},[215,4197,1382],{},[215,4199,4200],{},"portal",[741,4202,4203,4214],{},[762,4204,4205,228,4208,228,4211],{},[215,4206,4207],{},"menu.*",[215,4209,4210],{},"admin.*",[215,4212,4213],{},"overview.*",[762,4215,4216],{},"Account menu item, the admin tab, card and membership panel, and the account overview summary.",[741,4218,4219,4224],{},[762,4220,4221],{},[215,4222,4223],{},"catalog.\u003CplanKey>.*",[762,4225,4226,228,4229,1317,4232,4234],{},[215,4227,4228],{},"label",[215,4230,4231],{},"description",[215,4233,2498],{}," (array) per plan; host-defined and falling back to the plan config.",[4236,4237,4238],"style",{},"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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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}",{"title":293,"searchDepth":322,"depth":322,"links":4240},[4241,4242,4243,4249,4254,4255,4256,4257,4258],{"id":282,"depth":322,"text":283},{"id":732,"depth":322,"text":733},{"id":1056,"depth":322,"text":1057,"children":4244},[4245,4246,4247,4248],{"id":1061,"depth":335,"text":1062},{"id":1293,"depth":335,"text":1294},{"id":1382,"depth":335,"text":1383},{"id":1658,"depth":335,"text":1659},{"id":1922,"depth":322,"text":1923,"children":4250},[4251,4252,4253],{"id":2146,"depth":335,"text":2147},{"id":2246,"depth":335,"text":2247},{"id":2637,"depth":335,"text":2638},{"id":193,"depth":322,"text":2701},{"id":3364,"depth":322,"text":3365},{"id":3762,"depth":322,"text":705},{"id":3807,"depth":322,"text":713},{"id":4003,"depth":322,"text":4004},"Recurring Stripe subscriptions - host-defined plans, checkout, upgrade\u002Fdowngrade, billing portal, entitlements and account UI.","md",null,{},{"title":125,"description":4259},"TQDxEBhj9cvI1sekqbPbxhjOn9XtnxAoVKJdJ54Bgrg",[4266,4268],{"title":121,"path":122,"stem":123,"description":4267,"children":-1},"Stripe core - the SDK client, user-to-customer linking, one verified webhook endpoint and an event-listener API other modules plug into.",{"title":129,"path":130,"stem":131,"description":4269,"children":-1},"Shared Vue components and composables for Frigear Nuxt applications, built on Nuxt UI.",1792824485285]