3 पॉइंट द्वारा GN⁺ 2023-12-19 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • अगर PostgreSQL फ़ंक्शन सीधे text/html लौटाए, तो सिर्फ़ PostgREST और htmx के साथ ऐसा to-do ऐप बनाया जा सकता है जो AJAX अनुरोध के परिणाम लेकर DOM के हिस्सों को बदल दे
  • उदाहरण में authentication के बिना web_anon को api.todos और api.todos_id_seq की permission दी जाती है, और Accept: text/html अनुरोध संभालने के लिए custom media type जोड़ा जाता है
  • HTML assemble करने का काम SQL फ़ंक्शन करते हैं, और api.sanitize_html, api.html_todo, api.html_all_todos input escaping और list rendering संभालते हैं
  • स्क्रीन का व्यवहार hx-post, hx-get, hx-target, hx-trigger, hx-vals, hx-headers से बनता है, और response HTML #todo-list-area या अलग-अलग edit area को replace करता है
  • यह सेटअप proof of concept के क़रीब है, और PostgREST पक्ष में HTML handling बेहतर करने के लिए plmustache पर काम चल रहा है

PostgREST और htmx की भूमिका

  • PostgREST HTML content लौटाता है, और htmx AJAX अनुरोध के परिणाम में मिले HTML का उपयोग DOM के अंदर elements बदलने के लिए करता है
  • htmx HTML response की अपेक्षा करता है, इसलिए यह उस flow के साथ अच्छी तरह मेल खाता है जहाँ server JSON की जगह HTML fragments लौटाता है
  • यह उदाहरण दिखाता है कि दोनों तकनीकों को साथ इस्तेमाल करने पर कैसी संरचना संभव है; यह एक proof of concept है
  • PostgREST HTML processing को और बेहतर बनाने के लिए plmustache पर काम कर रहा है

to-do ऐप की तैयारी

  • यह उदाहरण Tutorial 0 - Get it Running पर आधारित एक to-do ऐप है
  • सरलता के लिए authentication का उपयोग नहीं किया गया है, और web_anon user को ज़रूरी permissions दी जाती हैं
    • api.todos table पर grant all
    • api.todos_id_seq sequence पर grant usage, select
  • browser के Accept: text/html अनुरोध को PostgREST द्वारा HTML के रूप में पहचानने के लिए media type handler जोड़ना होगा
    • "text/html" domain को text के रूप में बनाया जाता है
    • इस सेटिंग से PostgREST raw HTML document लौटा सकता है

बेसिक HTML पेज लौटाना

  • api.index() फ़ंक्शन "text/html" लौटाता है और एक बेसिक HTML document बनाता है
  • पेज में PostgREST + HTMX To-Do List शीर्षक के साथ ये resources शामिल हैं
    • styling के लिए Pico CSS
    • icon दिखाने के लिए Ionicons
  • browser में यह पेज http://localhost:3000/rpc/index पर खोला जा सकता है

सूची render करना और to-do जोड़ना

  • मौजूदा to-do सूची को HTML में बनाने के लिए तीन SQL फ़ंक्शन उपयोग किए जाते हैं
    • api.sanitize_html(text): &, ", >, <, ' अक्षरों को HTML entities में बदलता है
    • api.html_todo(api.todos): एक single to-do item को HTML fragment के रूप में format करता है
    • api.html_all_todos(): सभी items को एक HTML string में जोड़ता है, और item न होने पर There is nothing else to do. संदेश लौटाता है
  • api.html_todo और api.html_all_todos सूची templates बनाने के लिए internal फ़ंक्शन हैं; इन्हें सीधे PostgREST endpoint के रूप में उपयोग नहीं किया जाता
  • api.add_todo(_task text) नया to-do api.todos में insert करने के बाद updated पूरी सूची का HTML लौटाता है
  • updated api.index() में htmx और input form शामिल है
    • hx-headers='{"Accept": "text/html"}' को parent element पर रखा जाता है ताकि child htmx requests HTML response माँगें
    • यह header न हो तो PostgREST अनुरोध को HTML के रूप में पहचान नहीं पाएगा
  • to-do जोड़ने वाला form htmx attributes से काम करता है
    • hx-post="/rpc/add_todo": _task input value को /rpc/add_todo पर POST करता है
    • hx-target="#todo-list-area": response HTML को to-do list area में डालता है
    • hx-trigger="submit": form submit होने पर request भेजता है
    • hx-on="htmx:afterRequest: this.reset()": request पूरी होने के बाद form खाली करता है
  • नए functions और बदलाव लागू करने के लिए schema cache refresh करना होगा
  • इसके बाद http://localhost:3000/rpc/index पर सूची दिखना और नया to-do जोड़ना देखा जा सकता है

संपादन, हटाना, पूरा होने की स्थिति बदलना

  • api.html_todo को बढ़ाकर हर item में completion status बदलने, edit करने और delete करने का UI शामिल किया जाता है
  • completion status बदलना <form> और htmx attributes से संभाला जाता है
    • hx-post="/rpc/change_todo_state": संबंधित endpoint पर AJAX POST request भेजता है
    • hx-vals='{"_id": ..., "_done": ...}': hidden input की जगह request parameters जोड़ता है
    • hx-trigger="click": item पर click होने पर request चलाता है
  • edit button किसी खास task को input field में बदल देता है
    • hx-get="/rpc/html_editable_task": editable HTML input लौटाने वाले endpoint को कॉल करता है
    • hx-target="#todo-edit-area-...": पूरी सूची की जगह सिर्फ़ उस task area को replace करता है
    • hx-vals GET request parameters जोड़ता है, और table column को दर्शाते समय eq. operator की ज़रूरत होती है
  • delete button hx-post="/rpc/delete_todo" से उस to-do को हटाने का request भेजता है
  • api.html_editable_task(_id int) किसी विशेष to-do को edit करने के लिए input field का HTML लौटाता है
    • hx-post="/rpc/change_todo_task" से बदला हुआ task name submit किया जाता है
    • hx-trigger="submit,focusout" submit या focus out होने पर update करता है
    • hx-headers='{"Accept": "text/html"}' शामिल होता है
  • सभी data-changing endpoints बदलाव के बाद पूरी सूची का HTML लौटाते हैं
    • api.change_todo_state(_id int, _done boolean): done column को update करता है
    • api.change_todo_task(_id int, _task text): task column को update करता है
    • api.delete_todo(_id int): _id के अनुरूप to-do को delete करता है
  • schema cache refresh करने के बाद http://localhost:3000/rpc/index पर to-do edit, delete और completion handling संभव है

1 टिप्पणियां

 
GN⁺ 2023-12-19
Hacker News की रायें
  • PostgREST मेरे पसंदीदा open source projects में से एक है। मुझे लगता है कि Supabase के 1 billion dollar की कंपनी बनने में PostgREST और Postgres के बेहतरीन design का बड़ा योगदान है
    मुझे नहीं पता Supabase इस project को कैसे sponsor करता है, लेकिन उम्मीद है कि यह बहुत बड़े स्तर पर होगा। यह project कम से कम सैकड़ों revenue-generating companies के लिए core dependency है, फिर भी सिर्फ 12 paid sponsors हैं—open source funding की वास्तविकता देखकर दुख होता है
    https://www.patreon.com/postgrest/about

    • यह Supabase stack का core हिस्सा है, इसलिए जैसा बताया गया, वे lead maintainer Steve को मुख्य रूप से PostgREST पर काम करने के लिए employ करते हैं
      https://github.com/steve-chavez
    • अब 13 हो गए हैं। फिर भी अभी सिर्फ $1,529/month है
    • मुझे नहीं पता था कि PostgREST Supabase का हिस्सा है। मैंने सोचा था Supabase तो शुरू से बनाया गया एक copycat product है
    • ऐसी स्थिति में हमेशा आने वाली घिसी-पिटी बातें अभी से सुनाई दे रही हैं। “Users पर तुम्हें financially support करने की कोई obligation नहीं है”, “पसंद नहीं था तो permissive license के साथ release नहीं करना चाहिए था” जैसी बातें
      इसलिए अब मैं सिर्फ AGPLv3 या उससे मिलते-जुलते licenses इस्तेमाल करता हूँ। अगर commercial use करना है, तो gross revenue का 1% दो—ऐसा मॉडल
  • Proof of concept के तौर पर यह बढ़िया है और implementation भी तारीफ़ के काबिल है, लेकिन किसी non-trivial webapp में maintain करना nightmare जैसा लगता है

    • निश्चित रूप से यह website या lightweight app के लिए ज्यादा उपयुक्त है। फिर भी उस scope में इसका काफी इस्तेमाल किया जा सकता है
    • अभी मैं experiment कर रहा हूँ कि Sqitch से maintenance आसान बनाया जा सकता है या नहीं। अब भी hack जैसा लगता है और real-world usability पर शक बाकी है, लेकिन यह मजेदार है और मैं कई advanced Postgres features सीख रहा हूँ
      https://sqitch.org/
    • सच कहूँ तो, हमारे main web application में इसे इस्तेमाल करने पर कौन-सा हिस्सा 100x आसान नहीं होगा, यह जानने की उत्सुकता है
    • फिलहाल तो ऐसा ही लगता है। अब बस CI process के हिस्से के रूप में HTMX routes को database server पर compile और deploy करने का तरीका चाहिए
  • जिज्ञासा है कि ऐसी features या coding patterns नई या modern applications में भी इस्तेमाल होती हैं या नहीं
    CouchDB नाम का JSON document database HTTP-based API देता था, और इसमें built-in list/detail methods थे जो JavaScript interpreter के अंदर बनाए जा सकने वाले किसी भी format में response दे सकते थे। यानी client सीधे database को call करके HTML या JSON पा सकता था और server की जरूरत नहीं थी
    लेकिन v1 के बाद उन्होंने उस दिशा में काम बंद कर दिया, क्योंकि maintenance nightmare बन जाती थी। बहुत से लोगों को पुराने PHP या ASP files के अच्छे दिन याद होंगे, जहाँ एक ही file में SQL statements और HTML मिले होते थे; यह उससे बहुत अलग नहीं लगता

    • लगता है नई generation फिर से वे चीजें सीख रही है जिन्हें पहले valid reasons से छोड़ दिया गया था
      करीब 13 साल पहले एक personal project में मुझे CouchDB की web-related features बहुत पसंद थीं, लेकिन team के लिए उन्हें संभालना काफी inconvenient था
    • इसे modern कहना मुश्किल है। Oracle के पास 25 साल से भी पहले ऐसी चीज थी
  • जिस एकमात्र PostgREST app पर मैंने काम किया, वह भयानक था। क्योंकि ऐसे ज्यादातर “simple” frameworks की तरह, वे सिर्फ तब तक simple रहते हैं जब तक requirements complex नहीं हो जातीं
    मूल authors desired result पाने के लिए database में ढेर सारे stored procedures इस्तेमाल करने लगे, और इससे scalability issues पैदा हुए। हमेशा की तरह solution SQL पर वापस लौटना ही है

    • सुनने में लगता है उस team ने काम के लिए गलत tool चुना। अगर अधिकतर endpoints में complex backend logic है, तो PostgREST इस्तेमाल नहीं करना चाहिए
      PostgREST CRUD apps के लिए बनाया गया है, और जिन applications से मेरा सामना होता है उनमें से बहुत-सी इसी category में आती हैं। कभी-कभार जरूरी custom backend logic को अलग server या edge functions के रूप में चलाकर handle किया जा सकता है
    • मैं PostGREST काफी इस्तेमाल करता हूँ, लेकिन मजबूत guardrails रखता हूँ। मेरा मानना है कि असली API layer हमेशा होनी चाहिए, और इसे सिर्फ basic loading आसान करने वाले supplementary tool की तरह इस्तेमाल करना बेहतर है
      ऐसे सभी tools की तरह, real-world requirements आने पर tool के हिसाब से adapt करने की cost, उस चीज से भी खराब हो जाती है जिसे यह replace करना चाहता था—SQL + कोई language और framework। PostGREST भी पहले से complex होता जा रहा है, और ऐसी extra features मेरे लिए इसकी appeal घटाती हैं
    • Stored procedures भी आखिर function form में SQL ही तो हैं, नहीं?
      Rails के आने और सबको यह यकीन दिलाने से पहले कि slow server-side language में business logic डालना अच्छा idea है, लोग इसी तरह apps बनाते थे
  • सचमुच साफ-सुथरा web development stack है। बस HTML और database हैं, backend और frontend की जरूरत नहीं

    • 90s के मध्य में मैं Ohio में Compuserve गया था। Web बस शुरू ही हुआ था, और वहाँ मिले एक engineer ने मुझे एक music store दिखाया जिसे वह SQL stored procedures से HTML return करके बना रहा था :)
    • अगर यह आपको cool लगता है, तो Omnigres भी देखने लायक है
      https://github.com/omnigres/omnigres
    • हम यह रास्ता पहले ही तय कर चुके हैं। शुरुआत में साफ लगता है, लेकिन long-term maintenance, support और training के लिए अच्छा नहीं है
      HTMX की चमक फीकी पड़ने के बाद उस समय का maintainer आखिर मान लेगा कि सब कुछ scratch से फिर लिखना पड़ेगा
    • Backend और frontend अभी भी हैं। बस वे सब database code के अंदर सीधे उलझे हुए हैं
    • आखिरकार हम mainframe पर लौट आए हैं। इस बार बस browser terminal है
  • एक पुराने project में मैंने HTMX के बिना PostgREST इस्तेमाल किया था, और यह देखकर impressed था कि इसे कितनी दूर तक push किया जा सकता है
    HTMX भी fit बैठता दिखता है, लेकिन SQL functions के अंदर HTMX templates को कितना maintain करना चाहूँगा, यह पक्का नहीं है

    • मुझे बिल्कुल interest नहीं। PHP में यह पहले झेल चुका हूँ। इस pattern में static analysis, local testing, refactoring, atomically delivered large changes जैसी important capabilities missing हैं
      खेलने-कूदने के लिए अच्छा है, लेकिन stable चीज बनाने के लिए suitable नहीं
  • Haskell के नजरिए से PostgREST interesting है। क्योंकि यह बहुत obvious project जैसा दिखता है
    लेकिन ठीक इसी वजह से यह genius है। सच में Haskell जैसी idea है, इसलिए अच्छा लगता है

  • इस concept को medium-to-large applications में भी अच्छे user experience वाला maintainable stack बनाने के लिए आपको कौन-से अतिरिक्त tools ज़रूरी लगते हैं?

    • static site serving के लिए Astro(https://astro.build) इस्तेमाल कर रहा हूँ, और सरल data-centric components के लिए PostgREST Htmx इस्तेमाल कर रहा हूँ
    • medium-to-large scale के लिए मुझे लगता है कि एक अलग abstraction layer, यानी API, ज़रूरी है
      मैंने भी SQL के ऊपर कुछ ऐसा ही बनाने की कोशिश की थी, और tech stack Jinja template SQL और YML से implement की गई OpenAPI layer था, फिर भी शायद इसे internal tools के दायरे तक ही सीमित रखूँगा। यह यहाँ है: https://jinj.at
  • संबंधित Show HN: pg_render से SQL में HTML render करना
    https://news.ycombinator.com/item?id=38677852

  • मैं इस app में न भूलने के लिए एक task लिखना चाहता हूँ। मेरा task यह है:
    इस मामले में task column कहीं भी sanitize होता नहीं दिखता

    • पुराने खराब दिनों में, view सीधे database से बात करता था, इसलिए XSS बहुत आम था। फिर template engine और model को बीच में रखने पर लगा कि समस्या हल हो गई है
      लेकिन अब database ही view है, तो क्या XSS फिर से आ गया? यह रोकी जा सकने वाली समस्या है
    • सही। htmx उस script को खुशी-खुशी execute कर देगा। demo में भी यही bug था: https://github.com/bigskysoftware/htmx/pull/1995/files
    • यह example docs पर किए गए straw man attack जैसा लगता है। HTMX तो सिर्फ HTML serve करता है, और input को किसी-न-किसी तरीके से sanitize करना ही होगा
      HTML को ऐसी किसी भी template language से render किया जा सकता है जो यह handling कर देती हो