[{"data":1,"prerenderedAt":1543},["ShallowReactive",2],{"navigation_docs":3,"-core-validation":172,"-core-validation-surround":1538},[4,26,67,98,124,140,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Core","i-lucide-box","\u002Fcore","2.core",[32,37,42,47,52,57,62],{"title":33,"path":34,"stem":35,"icon":36},"Routing","\u002Fcore\u002Frouting","2.core\u002F1.routing","i-lucide-route",{"title":38,"path":39,"stem":40,"icon":41},"Handlers","\u002Fcore\u002Fhandlers","2.core\u002F2.handlers","i-lucide-braces",{"title":43,"path":44,"stem":45,"icon":46},"Request Binding","\u002Fcore\u002Frequest-binding","2.core\u002F3.request-binding","i-lucide-tags",{"title":48,"path":49,"stem":50,"icon":51},"Validation","\u002Fcore\u002Fvalidation","2.core\u002F4.validation","i-lucide-check-check",{"title":53,"path":54,"stem":55,"icon":56},"Context","\u002Fcore\u002Fcontext","2.core\u002F5.context","i-lucide-file-input",{"title":58,"path":59,"stem":60,"icon":61},"Errors","\u002Fcore\u002Ferrors","2.core\u002F6.errors","i-lucide-triangle-alert",{"title":63,"path":64,"stem":65,"icon":66},"Middleware","\u002Fcore\u002Fmiddleware","2.core\u002F7.middleware","i-lucide-layers",{"title":68,"icon":69,"path":70,"stem":71,"children":72,"page":25},"Auth","i-lucide-shield-check","\u002Fauth","3.auth",[73,78,83,88,93],{"title":74,"path":75,"stem":76,"icon":77},"Overview","\u002Fauth\u002Foverview","3.auth\u002F1.overview","i-lucide-shield",{"title":79,"path":80,"stem":81,"icon":82},"Auth Rules","\u002Fauth\u002Fauth-rules","3.auth\u002F2.auth-rules","i-lucide-lock",{"title":84,"path":85,"stem":86,"icon":87},"JWT Providers","\u002Fauth\u002Fjwt-providers","3.auth\u002F3.jwt-providers","i-lucide-key",{"title":89,"path":90,"stem":91,"icon":92},"Roles & Permissions","\u002Fauth\u002Froles-and-permissions","3.auth\u002F4.roles-and-permissions","i-lucide-users",{"title":94,"path":95,"stem":96,"icon":97},"Audit Logging","\u002Fauth\u002Faudit-logging","3.auth\u002F5.audit-logging","i-lucide-scroll-text",{"title":99,"icon":100,"path":101,"stem":102,"children":103,"page":25},"GoTrue","i-lucide-key-round","\u002Fgotrue","4.gotrue",[104,109,114,119],{"title":105,"path":106,"stem":107,"icon":108},"Proxy","\u002Fgotrue\u002Fproxy","4.gotrue\u002F1.proxy","i-lucide-shuffle",{"title":110,"path":111,"stem":112,"icon":113},"Endpoints","\u002Fgotrue\u002Fendpoints","4.gotrue\u002F2.endpoints","i-lucide-list",{"title":115,"path":116,"stem":117,"icon":118},"Client IP & Rate Limits","\u002Fgotrue\u002Fclient-ip-and-rate-limits","4.gotrue\u002F3.client-ip-and-rate-limits","i-lucide-network",{"title":120,"path":121,"stem":122,"icon":123},"Deployment","\u002Fgotrue\u002Fdeployment","4.gotrue\u002F4.deployment","i-lucide-server",{"title":125,"icon":126,"path":127,"stem":128,"children":129,"page":25},"API Docs","i-lucide-file-text","\u002Fapi-docs","5.api-docs",[130,135],{"title":131,"path":132,"stem":133,"icon":134},"OpenAPI","\u002Fapi-docs\u002Fopenapi","5.api-docs\u002F1.openapi","i-lucide-file-json",{"title":136,"path":137,"stem":138,"icon":139},"Scalar UI","\u002Fapi-docs\u002Fscalar","5.api-docs\u002F2.scalar","i-lucide-book-open-text",{"title":141,"icon":142,"path":143,"stem":144,"children":145,"page":25},"Guides","i-lucide-compass","\u002Fguides","6.guides",[146,151,156],{"title":147,"path":148,"stem":149,"icon":150},"Testing","\u002Fguides\u002Ftesting","6.guides\u002F1.testing","i-lucide-flask-conical",{"title":152,"path":153,"stem":154,"icon":155},"Performance","\u002Fguides\u002Fperformance","6.guides\u002F2.performance","i-lucide-gauge",{"title":157,"path":158,"stem":159,"icon":160},"Releasing","\u002Fguides\u002Freleasing","6.guides\u002F3.releasing","i-lucide-tag",{"title":162,"icon":163,"path":164,"stem":165,"children":166,"page":25},"Reference","i-lucide-code","\u002Freference","7.reference",[167],{"title":168,"path":169,"stem":170,"icon":171},"API Reference","\u002Freference\u002Fapi-reference","7.reference\u002F1.api-reference","i-lucide-list-tree",{"id":173,"title":48,"body":174,"description":1531,"extension":1532,"links":1533,"meta":1534,"navigation":1535,"path":49,"seo":1536,"stem":50,"__hash__":1537},"docs\u002F2.core\u002F4.validation.md",{"type":175,"value":176,"toc":1522},"minimark",[177,190,307,312,462,465,476,480,491,556,561,565,571,673,687,691,701,770,773,780,1172,1192,1196,1199,1395,1399,1402,1499,1503,1518],[178,179,180,181,185,186,189],"p",{},"After binding, ezz runs the ",[182,183,184],"code",{},"validate"," tags on your request struct. If anything fails, the request stops with a ",[182,187,188],{},"400"," and your handler is never called.",[191,192,197],"pre",{"className":193,"code":194,"language":195,"meta":196,"style":196},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type CreateUserRequest struct {\n    Name    string `json:\"name\" validate:\"required,min=2,max=100\"`\n    Email   string `json:\"email\" validate:\"required,email\"`\n    Website string `json:\"website\" validate:\"omitempty,url\"`\n    Age     int    `json:\"age\" validate:\"min=13,max=130\"`\n    Code    string `json:\"code\" validate:\"len=6\"`\n}\n","go","",[182,198,199,218,239,254,269,286,301],{"__ignoreMap":196},[200,201,204,208,212,215],"span",{"class":202,"line":203},"line",1,[200,205,207],{"class":206},"sMK4o","type",[200,209,211],{"class":210},"sBMFI"," CreateUserRequest",[200,213,214],{"class":206}," struct",[200,216,217],{"class":206}," {\n",[200,219,221,225,229,232,236],{"class":202,"line":220},2,[200,222,224],{"class":223},"sTEyZ","    Name    ",[200,226,228],{"class":227},"spNyl","string",[200,230,231],{"class":206}," `",[200,233,235],{"class":234},"sfazB","json:\"name\" validate:\"required,min=2,max=100\"",[200,237,238],{"class":206},"`\n",[200,240,242,245,247,249,252],{"class":202,"line":241},3,[200,243,244],{"class":223},"    Email   ",[200,246,228],{"class":227},[200,248,231],{"class":206},[200,250,251],{"class":234},"json:\"email\" validate:\"required,email\"",[200,253,238],{"class":206},[200,255,257,260,262,264,267],{"class":202,"line":256},4,[200,258,259],{"class":223},"    Website ",[200,261,228],{"class":227},[200,263,231],{"class":206},[200,265,266],{"class":234},"json:\"website\" validate:\"omitempty,url\"",[200,268,238],{"class":206},[200,270,272,275,278,281,284],{"class":202,"line":271},5,[200,273,274],{"class":223},"    Age     ",[200,276,277],{"class":227},"int",[200,279,280],{"class":206},"    `",[200,282,283],{"class":234},"json:\"age\" validate:\"min=13,max=130\"",[200,285,238],{"class":206},[200,287,289,292,294,296,299],{"class":202,"line":288},6,[200,290,291],{"class":223},"    Code    ",[200,293,228],{"class":227},[200,295,231],{"class":206},[200,297,298],{"class":234},"json:\"code\" validate:\"len=6\"",[200,300,238],{"class":206},[200,302,304],{"class":202,"line":303},7,[200,305,306],{"class":206},"}\n",[308,309,311],"h2",{"id":310},"available-rules","Available rules",[313,314,315,331],"table",{},[316,317,318],"thead",{},[319,320,321,325,328],"tr",{},[322,323,324],"th",{},"Rule",[322,326,327],{},"Applies to",[322,329,330],{},"Meaning",[332,333,334,348,364,378,392,405,419,431,450],"tbody",{},[319,335,336,342,345],{},[337,338,339],"td",{},[182,340,341],{},"required",[337,343,344],{},"any",[337,346,347],{},"Value must not be the zero value",[319,349,350,355,358],{},[337,351,352],{},[182,353,354],{},"min=n",[337,356,357],{},"string, slice, map",[337,359,360,361],{},"Length is at least ",[182,362,363],{},"n",[319,365,366,370,373],{},[337,367,368],{},[182,369,354],{},[337,371,372],{},"numbers",[337,374,375,376],{},"Value is at least ",[182,377,363],{},[319,379,380,385,387],{},[337,381,382],{},[182,383,384],{},"max=n",[337,386,357],{},[337,388,389,390],{},"Length is at most ",[182,391,363],{},[319,393,394,398,400],{},[337,395,396],{},[182,397,384],{},[337,399,372],{},[337,401,402,403],{},"Value is at most ",[182,404,363],{},[319,406,407,412,414],{},[337,408,409],{},[182,410,411],{},"len=n",[337,413,357],{},[337,415,416,417],{},"Length is exactly ",[182,418,363],{},[319,420,421,426,428],{},[337,422,423],{},[182,424,425],{},"email",[337,427,228],{},[337,429,430],{},"Matches an email pattern",[319,432,433,438,440],{},[337,434,435],{},[182,436,437],{},"url",[337,439,228],{},[337,441,442,443,446,447],{},"Starts with ",[182,444,445],{},"http:\u002F\u002F"," or ",[182,448,449],{},"https:\u002F\u002F",[319,451,452,457,459],{},[337,453,454],{},[182,455,456],{},"omitempty",[337,458,344],{},[337,460,461],{},"Skip every other rule on this field when the value is the zero value",[178,463,464],{},"Rules are comma-separated and evaluated in order. Every failing rule on every field is collected, so one response can report several problems at once.",[466,467,468,469,446,472,475],"warning",{},"Rule names outside this table are ignored silently. A tag like ",[182,470,471],{},"validate:\"uuid\"",[182,473,474],{},"validate:\"gte=5\""," will not fail the request, and it will not warn you. Stick to the supported set and do anything else in the handler.",[308,477,479],{"id":478},"make-a-field-optional","Make a field optional",[178,481,482,484,485,487,488,490],{},[182,483,341],{}," and the other rules treat the zero value differently, which trips people up. An ",[182,486,425],{}," rule on an empty string fails, because the empty string is not a valid email. When a field is genuinely optional, add ",[182,489,456],{}," first:",[191,492,494],{"className":193,"code":493,"language":195,"meta":196,"style":196},"type UpdateProfileRequest struct {\n    \u002F\u002F optional, but must be a valid email when supplied\n    Email string `json:\"email\" validate:\"omitempty,email\"`\n\n    \u002F\u002F optional, but between 2 and 50 characters when supplied\n    Nickname string `json:\"nickname\" validate:\"omitempty,min=2,max=50\"`\n}\n",[182,495,496,507,513,527,533,538,552],{"__ignoreMap":196},[200,497,498,500,503,505],{"class":202,"line":203},[200,499,207],{"class":206},[200,501,502],{"class":210}," UpdateProfileRequest",[200,504,214],{"class":206},[200,506,217],{"class":206},[200,508,509],{"class":202,"line":220},[200,510,512],{"class":511},"sHwdD","    \u002F\u002F optional, but must be a valid email when supplied\n",[200,514,515,518,520,522,525],{"class":202,"line":241},[200,516,517],{"class":223},"    Email ",[200,519,228],{"class":227},[200,521,231],{"class":206},[200,523,524],{"class":234},"json:\"email\" validate:\"omitempty,email\"",[200,526,238],{"class":206},[200,528,529],{"class":202,"line":256},[200,530,532],{"emptyLinePlaceholder":531},true,"\n",[200,534,535],{"class":202,"line":271},[200,536,537],{"class":511},"    \u002F\u002F optional, but between 2 and 50 characters when supplied\n",[200,539,540,543,545,547,550],{"class":202,"line":288},[200,541,542],{"class":223},"    Nickname ",[200,544,228],{"class":227},[200,546,231],{"class":206},[200,548,549],{"class":234},"json:\"nickname\" validate:\"omitempty,min=2,max=50\"",[200,551,238],{"class":206},[200,553,554],{"class":202,"line":303},[200,555,306],{"class":206},[178,557,558,560],{},[182,559,456],{}," is a marker rather than a check. When the field holds its zero value, the remaining rules on that field are skipped entirely.",[308,562,564],{"id":563},"validate-nested-structs","Validate nested structs",[178,566,567,568,570],{},"Nested structs and non-nil pointers to structs are walked recursively, whether or not the parent field carries a ",[182,569,184],{}," tag. Error field names are prefixed with the path:",[191,572,574],{"className":193,"code":573,"language":195,"meta":196,"style":196},"type Address struct {\n    City string `json:\"city\" validate:\"required\"`\n    Zip  string `json:\"zip\" validate:\"len=5\"`\n}\n\ntype CreateOrderRequest struct {\n    Ship Address  `json:\"ship\"`\n    Bill *Address `json:\"bill\"`\n}\n",[182,575,576,587,601,615,619,623,634,650,668],{"__ignoreMap":196},[200,577,578,580,583,585],{"class":202,"line":203},[200,579,207],{"class":206},[200,581,582],{"class":210}," Address",[200,584,214],{"class":206},[200,586,217],{"class":206},[200,588,589,592,594,596,599],{"class":202,"line":220},[200,590,591],{"class":223},"    City ",[200,593,228],{"class":227},[200,595,231],{"class":206},[200,597,598],{"class":234},"json:\"city\" validate:\"required\"",[200,600,238],{"class":206},[200,602,603,606,608,610,613],{"class":202,"line":241},[200,604,605],{"class":223},"    Zip  ",[200,607,228],{"class":227},[200,609,231],{"class":206},[200,611,612],{"class":234},"json:\"zip\" validate:\"len=5\"",[200,614,238],{"class":206},[200,616,617],{"class":202,"line":256},[200,618,306],{"class":206},[200,620,621],{"class":202,"line":271},[200,622,532],{"emptyLinePlaceholder":531},[200,624,625,627,630,632],{"class":202,"line":288},[200,626,207],{"class":206},[200,628,629],{"class":210}," CreateOrderRequest",[200,631,214],{"class":206},[200,633,217],{"class":206},[200,635,636,639,642,645,648],{"class":202,"line":303},[200,637,638],{"class":223},"    Ship ",[200,640,641],{"class":210},"Address",[200,643,644],{"class":206},"  `",[200,646,647],{"class":234},"json:\"ship\"",[200,649,238],{"class":206},[200,651,653,656,659,661,663,666],{"class":202,"line":652},8,[200,654,655],{"class":223},"    Bill ",[200,657,658],{"class":206},"*",[200,660,641],{"class":210},[200,662,231],{"class":206},[200,664,665],{"class":234},"json:\"bill\"",[200,667,238],{"class":206},[200,669,671],{"class":202,"line":670},9,[200,672,306],{"class":206},[178,674,675,676,679,680,683,684,686],{},"A missing city on the shipping address reports as ",[182,677,678],{},"field 'Ship.City' is required",". A nil ",[182,681,682],{},"Bill"," pointer is skipped, so mark it ",[182,685,341],{}," if the caller must supply it.",[308,688,690],{"id":689},"read-the-error-response","Read the error response",[178,692,693,694,696,697,700],{},"Failures are returned as a single ",[182,695,188],{}," with the messages joined by ",[182,698,699],{},"; ",":",[191,702,706],{"className":703,"code":704,"language":705,"meta":196,"style":196},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"error\": true,\n  \"message\": \"field 'Name' is required; field 'Email' must be a valid email\",\n  \"status\": 400\n}\n","json",[182,707,708,713,729,751,766],{"__ignoreMap":196},[200,709,710],{"class":202,"line":203},[200,711,712],{"class":206},"{\n",[200,714,715,718,721,724,726],{"class":202,"line":220},[200,716,717],{"class":206},"  \"",[200,719,720],{"class":227},"error",[200,722,723],{"class":206},"\"",[200,725,700],{"class":206},[200,727,728],{"class":206}," true,\n",[200,730,731,733,736,738,740,743,746,748],{"class":202,"line":241},[200,732,717],{"class":206},[200,734,735],{"class":227},"message",[200,737,723],{"class":206},[200,739,700],{"class":206},[200,741,742],{"class":206}," \"",[200,744,745],{"class":234},"field 'Name' is required; field 'Email' must be a valid email",[200,747,723],{"class":206},[200,749,750],{"class":206},",\n",[200,752,753,755,758,760,762],{"class":202,"line":256},[200,754,717],{"class":206},[200,756,757],{"class":227},"status",[200,759,723],{"class":206},[200,761,700],{"class":206},[200,763,765],{"class":764},"sbssI"," 400\n",[200,767,768],{"class":202,"line":271},[200,769,306],{"class":206},[178,771,772],{},"Field names in messages are the Go field names, not the JSON names.",[178,774,775,776,779],{},"If you need a different error shape, validate manually in the handler and return your own error. ",[182,777,778],{},"binding.Validate"," gives you the structured form:",[191,781,783],{"className":193,"code":782,"language":195,"meta":196,"style":196},"import \"github.com\u002Fsulv-io\u002Fezz\u002Fbinding\"\n\napp.POST(\"\u002Fusers\", ezz.H(func(ctx *ezz.Context, req CreateUserRequest) (any, error) {\n    if err := binding.Validate(req); err != nil {\n        var verrs binding.ValidationErrors\n        if errors.As(err, &verrs) {\n            fields := make(map[string]string, len(verrs))\n            for _, e := range verrs {\n                fields[e.Field] = e.Message\n            }\n            return nil, ctx.JSON(http.StatusUnprocessableEntity, map[string]any{\n                \"error\":  true,\n                \"fields\": fields,\n            })\n        }\n    }\n    return store.Create(req), nil\n}))\n",[182,784,785,799,803,877,914,930,960,992,1014,1043,1049,1089,1107,1124,1130,1136,1142,1166],{"__ignoreMap":196},[200,786,787,791,793,796],{"class":202,"line":203},[200,788,790],{"class":789},"s7zQu","import",[200,792,742],{"class":206},[200,794,795],{"class":210},"github.com\u002Fsulv-io\u002Fezz\u002Fbinding",[200,797,798],{"class":206},"\"\n",[200,800,801],{"class":202,"line":220},[200,802,532],{"emptyLinePlaceholder":531},[200,804,805,808,811,815,818,820,823,825,828,831,833,836,839,843,846,849,851,853,855,858,860,863,866,868,870,873,875],{"class":202,"line":241},[200,806,807],{"class":223},"app",[200,809,810],{"class":206},".",[200,812,814],{"class":813},"s2Zo4","POST",[200,816,817],{"class":206},"(",[200,819,723],{"class":206},[200,821,822],{"class":234},"\u002Fusers",[200,824,723],{"class":206},[200,826,827],{"class":206},",",[200,829,830],{"class":223}," ezz",[200,832,810],{"class":206},[200,834,835],{"class":813},"H",[200,837,838],{"class":206},"(func(",[200,840,842],{"class":841},"sHdIc","ctx",[200,844,845],{"class":206}," *",[200,847,848],{"class":210},"ezz",[200,850,810],{"class":206},[200,852,53],{"class":210},[200,854,827],{"class":206},[200,856,857],{"class":841}," req",[200,859,211],{"class":210},[200,861,862],{"class":206},")",[200,864,865],{"class":206}," (",[200,867,344],{"class":210},[200,869,827],{"class":206},[200,871,872],{"class":227}," error",[200,874,862],{"class":206},[200,876,217],{"class":206},[200,878,879,882,885,888,891,893,896,898,901,904,906,909,912],{"class":202,"line":256},[200,880,881],{"class":789},"    if",[200,883,884],{"class":223}," err ",[200,886,887],{"class":206},":=",[200,889,890],{"class":223}," binding",[200,892,810],{"class":206},[200,894,895],{"class":813},"Validate",[200,897,817],{"class":206},[200,899,900],{"class":223},"req",[200,902,903],{"class":206},");",[200,905,884],{"class":223},[200,907,908],{"class":206},"!=",[200,910,911],{"class":206}," nil",[200,913,217],{"class":206},[200,915,916,919,922,925,927],{"class":202,"line":271},[200,917,918],{"class":206},"        var",[200,920,921],{"class":223}," verrs ",[200,923,924],{"class":210},"binding",[200,926,810],{"class":206},[200,928,929],{"class":210},"ValidationErrors\n",[200,931,932,935,938,940,943,945,948,950,953,956,958],{"class":202,"line":288},[200,933,934],{"class":789},"        if",[200,936,937],{"class":223}," errors",[200,939,810],{"class":206},[200,941,942],{"class":813},"As",[200,944,817],{"class":206},[200,946,947],{"class":223},"err",[200,949,827],{"class":206},[200,951,952],{"class":206}," &",[200,954,955],{"class":223},"verrs",[200,957,862],{"class":206},[200,959,217],{"class":206},[200,961,962,965,967,970,973,975,978,980,982,985,987,989],{"class":202,"line":303},[200,963,964],{"class":223},"            fields ",[200,966,887],{"class":206},[200,968,969],{"class":813}," make",[200,971,972],{"class":206},"(map[",[200,974,228],{"class":227},[200,976,977],{"class":206},"]",[200,979,228],{"class":227},[200,981,827],{"class":206},[200,983,984],{"class":813}," len",[200,986,817],{"class":206},[200,988,955],{"class":223},[200,990,991],{"class":206},"))\n",[200,993,994,997,1000,1002,1005,1007,1010,1012],{"class":202,"line":652},[200,995,996],{"class":789},"            for",[200,998,999],{"class":223}," _",[200,1001,827],{"class":206},[200,1003,1004],{"class":223}," e ",[200,1006,887],{"class":206},[200,1008,1009],{"class":789}," range",[200,1011,921],{"class":223},[200,1013,712],{"class":206},[200,1015,1016,1019,1022,1025,1027,1030,1032,1035,1038,1040],{"class":202,"line":670},[200,1017,1018],{"class":223},"                fields",[200,1020,1021],{"class":206},"[",[200,1023,1024],{"class":223},"e",[200,1026,810],{"class":206},[200,1028,1029],{"class":223},"Field",[200,1031,977],{"class":206},[200,1033,1034],{"class":206}," =",[200,1036,1037],{"class":223}," e",[200,1039,810],{"class":206},[200,1041,1042],{"class":223},"Message\n",[200,1044,1046],{"class":202,"line":1045},10,[200,1047,1048],{"class":206},"            }\n",[200,1050,1052,1055,1058,1061,1063,1066,1068,1071,1073,1076,1078,1081,1083,1085,1087],{"class":202,"line":1051},11,[200,1053,1054],{"class":789},"            return",[200,1056,1057],{"class":206}," nil,",[200,1059,1060],{"class":223}," ctx",[200,1062,810],{"class":206},[200,1064,1065],{"class":813},"JSON",[200,1067,817],{"class":206},[200,1069,1070],{"class":223},"http",[200,1072,810],{"class":206},[200,1074,1075],{"class":223},"StatusUnprocessableEntity",[200,1077,827],{"class":206},[200,1079,1080],{"class":206}," map[",[200,1082,228],{"class":227},[200,1084,977],{"class":206},[200,1086,344],{"class":210},[200,1088,712],{"class":206},[200,1090,1092,1095,1097,1099,1101,1105],{"class":202,"line":1091},12,[200,1093,1094],{"class":206},"                \"",[200,1096,720],{"class":234},[200,1098,723],{"class":206},[200,1100,700],{"class":206},[200,1102,1104],{"class":1103},"sfNiH","  true",[200,1106,750],{"class":206},[200,1108,1110,1112,1115,1117,1119,1122],{"class":202,"line":1109},13,[200,1111,1094],{"class":206},[200,1113,1114],{"class":234},"fields",[200,1116,723],{"class":206},[200,1118,700],{"class":206},[200,1120,1121],{"class":223}," fields",[200,1123,750],{"class":206},[200,1125,1127],{"class":202,"line":1126},14,[200,1128,1129],{"class":206},"            })\n",[200,1131,1133],{"class":202,"line":1132},15,[200,1134,1135],{"class":206},"        }\n",[200,1137,1139],{"class":202,"line":1138},16,[200,1140,1141],{"class":206},"    }\n",[200,1143,1145,1148,1151,1153,1156,1158,1160,1163],{"class":202,"line":1144},17,[200,1146,1147],{"class":789},"    return",[200,1149,1150],{"class":223}," store",[200,1152,810],{"class":206},[200,1154,1155],{"class":813},"Create",[200,1157,817],{"class":206},[200,1159,900],{"class":223},[200,1161,1162],{"class":206},"),",[200,1164,1165],{"class":206}," nil\n",[200,1167,1169],{"class":202,"line":1168},18,[200,1170,1171],{"class":206},"}))\n",[178,1173,1174,1175,1178,1179,1181,1182,1181,1185,1188,1189,810],{},"Each ",[182,1176,1177],{},"binding.ValidationError"," carries ",[182,1180,1029],{},", ",[182,1183,1184],{},"Tag",[182,1186,1187],{},"Value",", and ",[182,1190,1191],{},"Message",[308,1193,1195],{"id":1194},"add-rules-the-tags-cannot-express","Add rules the tags cannot express",[178,1197,1198],{},"Business rules belong in the handler, where you have your dependencies:",[191,1200,1202],{"className":193,"code":1201,"language":195,"meta":196,"style":196},"app.POST(\"\u002Fusers\", ezz.H(func(ctx *ezz.Context, req CreateUserRequest) (*User, error) {\n    if store.EmailTaken(ctx, req.Email) {\n        return nil, ezz.Conflict(\"email already registered\")\n    }\n    if !passwordStrongEnough(req.Password) {\n        return nil, ezz.UnprocessableEntity(\"password is too weak\")\n    }\n    return store.Create(ctx, req)\n}))\n",[182,1203,1204,1262,1290,1316,1320,1343,1367,1371,1391],{"__ignoreMap":196},[200,1205,1206,1208,1210,1212,1214,1216,1218,1220,1222,1224,1226,1228,1230,1232,1234,1236,1238,1240,1242,1244,1246,1248,1251,1254,1256,1258,1260],{"class":202,"line":203},[200,1207,807],{"class":223},[200,1209,810],{"class":206},[200,1211,814],{"class":813},[200,1213,817],{"class":206},[200,1215,723],{"class":206},[200,1217,822],{"class":234},[200,1219,723],{"class":206},[200,1221,827],{"class":206},[200,1223,830],{"class":223},[200,1225,810],{"class":206},[200,1227,835],{"class":813},[200,1229,838],{"class":206},[200,1231,842],{"class":841},[200,1233,845],{"class":206},[200,1235,848],{"class":210},[200,1237,810],{"class":206},[200,1239,53],{"class":210},[200,1241,827],{"class":206},[200,1243,857],{"class":841},[200,1245,211],{"class":210},[200,1247,862],{"class":206},[200,1249,1250],{"class":206}," (*",[200,1252,1253],{"class":210},"User",[200,1255,827],{"class":206},[200,1257,872],{"class":227},[200,1259,862],{"class":206},[200,1261,217],{"class":206},[200,1263,1264,1266,1268,1270,1273,1275,1277,1279,1281,1283,1286,1288],{"class":202,"line":220},[200,1265,881],{"class":789},[200,1267,1150],{"class":223},[200,1269,810],{"class":206},[200,1271,1272],{"class":813},"EmailTaken",[200,1274,817],{"class":206},[200,1276,842],{"class":223},[200,1278,827],{"class":206},[200,1280,857],{"class":223},[200,1282,810],{"class":206},[200,1284,1285],{"class":223},"Email",[200,1287,862],{"class":206},[200,1289,217],{"class":206},[200,1291,1292,1295,1297,1299,1301,1304,1306,1308,1311,1313],{"class":202,"line":241},[200,1293,1294],{"class":789},"        return",[200,1296,1057],{"class":206},[200,1298,830],{"class":223},[200,1300,810],{"class":206},[200,1302,1303],{"class":813},"Conflict",[200,1305,817],{"class":206},[200,1307,723],{"class":206},[200,1309,1310],{"class":234},"email already registered",[200,1312,723],{"class":206},[200,1314,1315],{"class":206},")\n",[200,1317,1318],{"class":202,"line":256},[200,1319,1141],{"class":206},[200,1321,1322,1324,1327,1330,1332,1334,1336,1339,1341],{"class":202,"line":271},[200,1323,881],{"class":789},[200,1325,1326],{"class":206}," !",[200,1328,1329],{"class":813},"passwordStrongEnough",[200,1331,817],{"class":206},[200,1333,900],{"class":223},[200,1335,810],{"class":206},[200,1337,1338],{"class":223},"Password",[200,1340,862],{"class":206},[200,1342,217],{"class":206},[200,1344,1345,1347,1349,1351,1353,1356,1358,1360,1363,1365],{"class":202,"line":288},[200,1346,1294],{"class":789},[200,1348,1057],{"class":206},[200,1350,830],{"class":223},[200,1352,810],{"class":206},[200,1354,1355],{"class":813},"UnprocessableEntity",[200,1357,817],{"class":206},[200,1359,723],{"class":206},[200,1361,1362],{"class":234},"password is too weak",[200,1364,723],{"class":206},[200,1366,1315],{"class":206},[200,1368,1369],{"class":202,"line":303},[200,1370,1141],{"class":206},[200,1372,1373,1375,1377,1379,1381,1383,1385,1387,1389],{"class":202,"line":652},[200,1374,1147],{"class":789},[200,1376,1150],{"class":223},[200,1378,810],{"class":206},[200,1380,1155],{"class":813},[200,1382,817],{"class":206},[200,1384,842],{"class":223},[200,1386,827],{"class":206},[200,1388,857],{"class":223},[200,1390,1315],{"class":206},[200,1392,1393],{"class":202,"line":670},[200,1394,1171],{"class":206},[308,1396,1398],{"id":1397},"see-the-rules-in-your-documentation","See the rules in your documentation",[178,1400,1401],{},"The OpenAPI generator reads the same tags, so constraints appear in the spec without repeating yourself:",[313,1403,1404,1413],{},[316,1405,1406],{},[319,1407,1408,1410],{},[322,1409,1184],{},[322,1411,1412],{},"Schema output",[332,1414,1415,1435,1452,1467,1478,1489],{},[319,1416,1417,1427],{},[337,1418,1419,1422,1423,1426],{},[182,1420,1421],{},"min"," \u002F ",[182,1424,1425],{},"max"," on a string or array",[337,1428,1429,1422,1432],{},[182,1430,1431],{},"minLength",[182,1433,1434],{},"maxLength",[319,1436,1437,1444],{},[337,1438,1439,1422,1441,1443],{},[182,1440,1421],{},[182,1442,1425],{}," on a number",[337,1445,1446,1422,1449],{},[182,1447,1448],{},"minimum",[182,1450,1451],{},"maximum",[319,1453,1454,1459],{},[337,1455,1456],{},[182,1457,1458],{},"len",[337,1460,1461,1463,1464,1466],{},[182,1462,1431],{}," and ",[182,1465,1434],{}," set to the same value",[319,1468,1469,1473],{},[337,1470,1471],{},[182,1472,425],{},[337,1474,1475],{},[182,1476,1477],{},"format: email",[319,1479,1480,1484],{},[337,1481,1482],{},[182,1483,437],{},[337,1485,1486],{},[182,1487,1488],{},"format: uri",[319,1490,1491,1496],{},[337,1492,1493,1495],{},[182,1494,341],{}," on a query or header field",[337,1497,1498],{},"Marks the parameter required",[308,1500,1502],{"id":1501},"next-steps","Next steps",[1504,1505,1506,1513],"ul",{},[1507,1508,1509,1512],"li",{},[1510,1511,58],"a",{"href":59}," for the status codes and error bodies ezz produces.",[1507,1514,1515,1517],{},[1510,1516,131],{"href":132}," for the rest of the generated schema.",[1519,1520,1521],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":196,"searchDepth":220,"depth":220,"links":1523},[1524,1525,1526,1527,1528,1529,1530],{"id":310,"depth":220,"text":311},{"id":478,"depth":220,"text":479},{"id":563,"depth":220,"text":564},{"id":689,"depth":220,"text":690},{"id":1194,"depth":220,"text":1195},{"id":1397,"depth":220,"text":1398},{"id":1501,"depth":220,"text":1502},"Reject bad input with validate tags before your handler runs.","md",null,{},{"icon":51},{"title":48,"description":1531},"R1gjqloC5WxfzLM2nynS8MGM81_F4o116k3HeeLIL5k",[1539,1541],{"title":43,"path":44,"stem":45,"description":1540,"icon":46,"children":-1},"Fill your request struct from the path, query string, headers, form fields, and JSON body.",{"title":53,"path":54,"stem":55,"description":1542,"icon":56,"children":-1},"Read request data, write responses, stream events, and reach the authenticated user.",1784970047281]