[{"data":1,"prerenderedAt":70},["ShallowReactive",2],{"case-dev-build-log-ws-mock-dsl-en":3,"blog-list-en":13},{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11,"html":12},"dev-build-log-ws-mock-dsl","Why We Designed a WebSocket Mock DSL Instead of YAML, JSON, or JS","Lightweight WebSocket Mock shouldn't feel heavier than HTTP Mock. YAML, JSON, and JS all work—but they're wordy for connect, login, heartbeat. We built a short DSL to keep lightweight Mock light.","2026-08-13",false,"DevPeek dev log: why WebSocket Mock uses a custom Flow DSL. YAML, JSON, and JS handle heavy cases; sequential lightweight scripts get a shorter text format.","dev-build-log",3,"\u003Ch2>Lightweight Mock shouldn&#39;t get heavy first\u003C\u002Fh2>\n\u003Cp>For HTTP, \u003Ca href=\"\u002Fen\u002Fdocs\u002Fmock\u002F\">Mock\u003C\u002Fa> is already light: capture a request, tick features, edit the response. One round trip and you&#39;re done.\u003C\u002Fp>\n\u003Cp>Lightweight WebSocket Mock is almost as short: connect, login, one reply, a heartbeat every few seconds. You&#39;re mocking a small dialog, not a program.\u003C\u002Fp>\n\u003Cp>Existing tools still drop that dialog into a JSON rule table, YAML config, or a JS file. \u003Cstrong>They&#39;re capable, and they run.\u003C\u002Fstrong> The catch: something you could say in a dozen lines first needs field names, braces, and \u003Ccode>setInterval\u003C\u002Fcode>. The light case gets weighed down by the container.\u003C\u002Fp>\n\u003Cp>We designed a DSL for that—\u003Cstrong>to make lightweight Mock lighter\u003C\u002Fstrong>. The UI calls it \u003Cstrong>WS Flow\u003C\u002Fstrong>; the file is \u003Ccode>.dpws\u003C\u002Fcode>. People write the script. JSON stays a compile artifact.\u003C\u002Fp>\n\u003Ch2>The same dialog\u003C\u002Fh2>\n\u003Cp>“Challenge on connect → login success → tick every 15s” as rule JSON often looks like this:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;url&quot;: &quot;wss:\u002F\u002Fapi.example.com\u002Fws&quot;,\n  &quot;onOpen&quot;: [{ &quot;send&quot;: { &quot;type&quot;: &quot;challenge&quot; } }],\n  &quot;handlers&quot;: [\n    {\n      &quot;match&quot;: { &quot;type&quot;: &quot;login&quot; },\n      &quot;reply&quot;: { &quot;type&quot;: &quot;loginSuccess&quot; },\n      &quot;then&quot;: {\n        &quot;every&quot;: &quot;15s&quot;,\n        &quot;send&quot;: { &quot;type&quot;: &quot;tick&quot; }\n      }\n    }\n  ]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The words go to \u003Ccode>onOpen\u003C\u002Fcode>, \u003Ccode>handlers\u003C\u002Fcode>, \u003Ccode>match\u003C\u002Fcode>, \u003Ccode>reply\u003C\u002Fcode>, and \u003Ccode>then\u003C\u002Fcode>. YAML drops the braces; the shell remains—keys, lists, another nest, indent that means both config and conversation. JS can do anything; a Mock also turns into a small program.\u003C\u002Fp>\n\u003Cp>The same story as Flow:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-text\"># ws wss:\u002F\u002Fapi.example.com\u002Fws\n# profile type\n# ping auto\n\n--@open\n    challenge\n\n--login\n    loginSuccess\n        --@loop 15s\n            tick\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Ccode>--@open\u003C\u002Fcode> is connect. \u003Ccode>--login\u003C\u002Fcode> is the client logging in. Indented lines are the reply and the later push. \u003Ccode>loginSuccess\u003C\u002Fcode> compiles via the header to \u003Ccode>{&quot;type&quot;:&quot;loginSuccess&quot;}\u003C\u002Fcode>—no hand-written JSON per business frame. Delay and periodic push sit on the line (\u003Ccode>+300ms\u003C\u002Fcode>, \u003Ccode>--@loop 15s\u003C\u002Fcode>). No extra control flow.\u003C\u002Fp>\n\u003Cp>That&#39;s the grammar: an indent tree and a handful of tokens (\u003Ccode>--\u003C\u002Fcode>, \u003Ccode>--@\u003C\u002Fcode>, \u003Ccode>~scope\u003C\u002Fcode>, \u003Ccode>|\u003C\u002Fcode>, \u003Ccode>$\u003C\u002Fcode>, \u003Ccode>+delay\u003C\u002Fcode>, \u003Ccode>!close\u003C\u002Fcode>). No \u003Ccode>if\u003C\u002Fcode> \u002F \u003Ccode>for\u003C\u002Fcode> \u002F functions. Use cases: \u003Ca href=\"\u002Fen\u002Fdocs\u002Fwsmock-dsl\u002F\">WebSocket Mock\u003C\u002Fa>. Tokens: \u003Ca href=\"\u002Fen\u002Fdocs\u002Fdpws\u002F\">\u003Ccode>.dpws\u003C\u002Fcode> language reference\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>HTTP Mock still starts from a capture and a GUI. WS Flow only serves this kind of short dialog. Don&#39;t mash them into one form.\u003C\u002Fp>\n\u003Ch2>DSL for the light cases; JS for the rest\u003C\u002Fh2>\n\u003Cp>Flow is \u003Cstrong>only for lightweight Mock\u003C\u002Fstrong>: a short, sequential session. Concurrent or out-of-order frames, deep branches, dynamic or random payloads, reading external data—YAML\u002FJSON ecosystems (Schema, diffs, CI) or plain JS fit better. That isn&#39;t an unfinished DSL. We don&#39;t want a light grammar stretched into a general-purpose language.\u003C\u002Fp>\n\u003Cp>A custom DSL has a bill: parser, diagnostics, highlighting, completion, and a new set of tokens for teammates. Validate is in the editor; highlighting and completion are not. What we get is a file that reads like a dialog, not like config.\u003C\u002Fp>\n\u003Ch2>Same thread as the last two\u003C\u002Fh2>\n\u003Cp>\u003Ca href=\"\u002Fen\u002Fblog\u002Fdev-build-log-sqljs-to-better-sqlite3\u002F\">Why we moved capture history from sql.js to native SQLite\u003C\u002Fa> was about storage that survives all-day sessions.\u003Cbr>\u003Ca href=\"\u002Fen\u002Fblog\u002Fdev-build-log-electron-to-tauri\u002F\">Dropping Electron for Tauri\u003C\u002Fa> was about a shell that was too heavy.\u003Cbr>This one: lightweight WebSocket Mock shouldn&#39;t get heavy in JSON, YAML, or JS first. We used a shorter DSL to keep it light.\u003C\u002Fp>\n\u003Ch2>Related docs\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fwsmock-dsl\u002F\">WebSocket Mock\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fdpws\u002F\">\u003Ccode>.dpws\u003C\u002Fcode> language reference\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fmock\u002F\">Mock rules\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fen\u002Fdocs\u002Fcapture\u002F\">Capture UI &amp; requests\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Chr>\n\u003Cp>\u003Ca href=\"\u002Fen\u002F\">Download DevPeek\u003C\u002Fa> to see HTTP Mock next to capture. WS Flow is in the \u003Ca href=\"\u002Fen\u002Fdocs\u002Fwsmock-dsl\u002F\">WebSocket Mock guide\u003C\u002Fa>. Different take? \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FGYPengDev\u002Fdevpeek\u002Fdiscussions\">GitHub Discussions\u003C\u002Fa>.\u003C\u002Fp>\n",{"items":14},[15,16,23,30,37,43,51,57,64],{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11},{"slug":17,"title":18,"summary":19,"date":20,"featured":8,"seoDescription":21,"series":10,"seriesOrder":22},"dev-build-log-electron-to-tauri","DevPeek Architecture: Dropping Electron for Tauri","A debugging proxy shouldn't ship a whole Chromium just to open a window. We moved business logic into Core and swapped the desktop shell for Tauri—lighter installs, leaner background use, and the tray brings the UI back after you close the window.","2026-08-08","DevPeek dev log: moving the desktop shell from Electron to Tauri—business stays in Core, the shell handles windows and OS features, with smaller footprint and lower resource use.",2,{"slug":24,"title":25,"summary":26,"date":27,"featured":8,"seoDescription":28,"series":10,"seriesOrder":29},"dev-build-log-sqljs-to-better-sqlite3","Why We Moved Capture History from sql.js to Native SQLite","Early DevPeek stored captures in JavaScript-based SQLite (sql.js); busy sessions ate RAM and stuttered the list. Native SQLite keeps memory flat so the proxy can run all day.","2026-08-05","DevPeek dev log: moving capture storage from sql.js to native SQLite—fixing memory growth and list lag on all-day debugging sessions.",1,{"slug":31,"title":32,"summary":33,"date":34,"featured":8,"seoDescription":35,"series":36,"seriesOrder":22},"mock-map-route-split-api","New API Is Live, Frontend Hasn't Shipped? Debug with Forward Rules","After a service split, the frontend still hits the old API while orders already live on the new service. DevPeek Forward Rules forward specific endpoints to the new host without code changes; if the new service isn't ready, Mock gets the page working first.","2026-07-26","Microservice integration and API host migration: use DevPeek Forward Rules for API forwarding—point old-host requests to the new service without changing the frontend. Mock when migration isn't done. Includes a hands-on demo.","api-debug-new-tricks",{"slug":38,"title":39,"summary":40,"date":41,"featured":8,"seoDescription":42,"series":36,"seriesOrder":29},"api-param-encryption-debug","H5 API Encrypted? Decrypt It On the Fly with DevPeek","Stuck with AES-encrypted API params during integration? Set the key and IV once in DevPeek Param Transform, and see plaintext automatically — you can even edit and re-encrypt on resend.","2026-07-18","Use DevPeek Param Transform to auto-decrypt AES-GCM encrypted H5 API requests. Supports two-way transform, plaintext editing, and debug replay.",{"slug":44,"title":45,"summary":46,"date":47,"featured":48,"seoDescription":49,"series":50,"seriesOrder":22},"h5-debug-console-mock","H5 Debug in Practice (2): Android WebView White Screen—From Console Remote Debug to Mock Validation","A campaign H5 white-screened on some Android devices after a button tap—all requests returned 200, but the page showed nothing. Using DevPeek Console to capture WebView runtime logs, remote eval to confirm a polyfill override, then Mock to verify the fallback UI under error conditions.","2026-07-13",true,"DevPeek H5 debug practice part 2: troubleshoot Android WebView white screen via Console remote debug to locate a JavaScript polyfill conflict, then use Mock to verify page fallback behavior under abnormal API responses.","h5-debug",{"slug":52,"title":53,"summary":54,"date":55,"featured":48,"seoDescription":56,"series":50,"seriesOrder":29},"wechat-h5-storage-debug","H5 Debug in Practice (1): WeChat H5 Local Cache—Debug It on Desktop","After switching test accounts in a WeChat official-account H5, the avatar still showed the old user—capture had the new token, stale data stayed in localStorage. This post walks through a real joint-debug case and how to view and edit localStorage, sessionStorage, and IndexedDB in WeChat WebView from your PC.","2026-07-11","DevPeek H5 debug: locate localStorage, sessionStorage, and IndexedDB cache issues in WeChat H5—compared with vConsole and remote debug, with real WebView debugging workflow.",{"slug":58,"title":59,"summary":60,"date":61,"featured":48,"seoDescription":62,"series":63,"seriesOrder":22},"why-we-built-devpeek-h5-debug","Why We Built DevPeek (2): That H5 Page in the App—Debug It on Your PC","Param transform fixed login, but the activity H5 only broke inside the App WebView. Remote debug and capture lived in different windows—so we folded mirroring and our own debug panels into DevPeek.","2026-07-10","DevPeek origin series, part 2: in-app H5 bugs that only show on real devices, the split between remote debug and capture, and how the Debug tab mirrors pages with built-in DOM, Console, and Network panels.","origin",{"slug":65,"title":66,"summary":67,"date":68,"featured":48,"seoDescription":69,"series":63,"seriesOrder":29},"why-we-built-devpeek","Why We Built DevPeek (1): HTTPS Decrypted, Body Still Gibberish","The night before a release, TLS was already open—but changing one request field still meant digging up encrypt\u002Fdecrypt scripts. That pushed us toward a proxy tool with business-layer crypto built in—and DevPeek started there.","2026-07-09","DevPeek origin series, part 1: the manual request-body encrypt\u002Fdecrypt grind—and why we set out to build a proxy tool that owns business-layer crypto.",1786681095267]