[{"data":1,"prerenderedAt":1833},["ShallowReactive",2],{"docs:/docs/high-level-sdks/dash":3},{"id":4,"title":5,"body":6,"description":17,"extension":1827,"meta":1828,"navigation":208,"path":1829,"seo":1830,"stem":1831,"__hash__":1832},"docs/docs/high-level-sdks/dash.md","Dash SDK",{"type":7,"value":8,"toc":1813},"minimark",[9,14,18,23,33,38,57,61,94,132,141,167,340,344,368,391,395,1153,1157,1160,1163,1168,1327,1436,1440,1552,1555,1561,1729,1733,1809],[10,11,13],"h1",{"id":12},"nolagdash","@nolag/dash",[15,16,17],"p",{},"Live dashboards with real-time metrics, time-series aggregation, and widgets.",[19,20,22],"h2",{"id":21},"overview","Overview",[15,24,25,28,29,32],{},[26,27,13],"code",{}," powers live operational dashboards with streaming metrics and interactive widgets. Agents or servers publish metric data points and widget state snapshots to panels; viewers connected to the same panel receive updates instantly and can query rolling aggregations (average, min, max, sum, count, last) over any time window without hitting a separate time-series database. Your app owns one core NoLag client and injects it into ",[26,30,31],{},"NoLagDash","; the wrapper attaches its behaviour to that connection.",[34,35,37],"h3",{"id":36},"key-features","Key Features",[39,40,41,45,48,51,54],"ul",{},[42,43,44],"li",{},"Streaming metric ingestion with per-stream data point buffering",[42,46,47],{},"Client-side rolling aggregation over configurable time windows",[42,49,50],{},"Widget state publishing for gauges, charts, counters, tables, text, and custom types",[42,52,53],{},"Tag-based metadata on metrics for multi-dimensional filtering",[42,55,56],{},"Automatic reconnection with panel subscriptions restored",[19,58,60],{"id":59},"how-it-works","How It Works",[15,62,63,65,66,69,70,73,74,77,78,81,82,85,86,89,90,93],{},[26,64,31],{}," attaches to an injected ",[26,67,68],{},"@nolag/js-sdk"," client. Calling ",[26,71,72],{},"joinPanel()"," creates a ",[26,75,76],{},"DashboardPanel"," that subscribes to two topics: ",[26,79,80],{},"metrics"," for time-series data points and ",[26,83,84],{},"widgets"," for widget state snapshots. A ",[26,87,88],{},"MetricStore"," inside the panel accumulates data points per stream ID and provides rolling-window aggregation, while a ",[26,91,92],{},"WidgetManager"," keeps the latest state for each widget keyed by widget ID. The app owns the socket lifecycle; the wrapper never opens or closes it.",[95,96,97,110],"table",{},[98,99,100],"thead",{},[101,102,103,107],"tr",{},[104,105,106],"th",{},"Topic",[104,108,109],{},"Purpose",[111,112,113,123],"tbody",{},[101,114,115,120],{},[116,117,118],"td",{},[26,119,80],{},[116,121,122],{},"Time-series data points: value, timestamp, unit, tags",[101,124,125,129],{},[116,126,127],{},[26,128,84],{},[116,130,131],{},"Widget state snapshots: type, data payload, label, timestamp",[15,133,134,135,140],{},"A viewer's buffer starts empty and fills from the data points published after it joined. A fresh subscribe or an ordinary reconnect never replays history; see ",[136,137,139],"a",{"href":138},"/docs/concepts/replay","Replay"," for the one case where the broker replays messages. If new viewers need a starting state, have your publisher re-send its current widget snapshots on a timer.",[142,143,145],"callout",{"type":144},"info",[15,146,147,151,152,155,156,158,159,162,163,166],{},[148,149,150],"strong",{},"Before you start."," Create an app from the ",[26,153,154],{},"nolag-dash-sdk"," blueprint. That seeds the panel this SDK expects (",[26,157,21],{},") and the ",[26,160,161],{},"online"," lobby, and returns an app slug with a random suffix. That slug is the ",[26,164,165],{},"appName"," you pass to the wrapper. You can also do this in the portal: Apps, New App, pick the blueprint.",[168,169,170],"code-tabs",{},[171,172,178],"pre",{"className":173,"code":174,"filename":175,"language":176,"meta":177,"style":177},"language-typescript shiki shiki-themes github-light github-dark","import { NoLagApi } from \"@nolag/js-sdk\";\n\nconst api = new NoLagApi(process.env.NOLAG_API_KEY); // nlg_live_...\nconst app = await api.apps.create({ name: \"My App\", blueprintId: \"nolag-dash-sdk\" });\nconsole.log(app.slug); // e.g. \"my-app-a3f9\": this is your appName\n\nconst actor = await api.actors.create({ name: \"web-client\", actorType: \"user\" });\nconsole.log(actor.accessToken); // shown once; keep it\n","Setup (server side, once)","typescript","",[26,179,180,203,210,243,277,292,297,327],{"__ignoreMap":177},[181,182,185,189,193,196,200],"span",{"class":183,"line":184},"line",1,[181,186,188],{"class":187},"szBVR","import",[181,190,192],{"class":191},"sVt8B"," { NoLagApi } ",[181,194,195],{"class":187},"from",[181,197,199],{"class":198},"sZZnC"," \"@nolag/js-sdk\"",[181,201,202],{"class":191},";\n",[181,204,206],{"class":183,"line":205},2,[181,207,209],{"emptyLinePlaceholder":208},true,"\n",[181,211,213,216,220,223,226,230,233,236,239],{"class":183,"line":212},3,[181,214,215],{"class":187},"const",[181,217,219],{"class":218},"sj4cs"," api",[181,221,222],{"class":187}," =",[181,224,225],{"class":187}," new",[181,227,229],{"class":228},"sScJk"," NoLagApi",[181,231,232],{"class":191},"(process.env.",[181,234,235],{"class":218},"NOLAG_API_KEY",[181,237,238],{"class":191},"); ",[181,240,242],{"class":241},"sJ8bj","// nlg_live_...\n",[181,244,246,248,251,253,256,259,262,265,268,271,274],{"class":183,"line":245},4,[181,247,215],{"class":187},[181,249,250],{"class":218}," app",[181,252,222],{"class":187},[181,254,255],{"class":187}," await",[181,257,258],{"class":191}," api.apps.",[181,260,261],{"class":228},"create",[181,263,264],{"class":191},"({ name: ",[181,266,267],{"class":198},"\"My App\"",[181,269,270],{"class":191},", blueprintId: ",[181,272,273],{"class":198},"\"nolag-dash-sdk\"",[181,275,276],{"class":191}," });\n",[181,278,280,283,286,289],{"class":183,"line":279},5,[181,281,282],{"class":191},"console.",[181,284,285],{"class":228},"log",[181,287,288],{"class":191},"(app.slug); ",[181,290,291],{"class":241},"// e.g. \"my-app-a3f9\": this is your appName\n",[181,293,295],{"class":183,"line":294},6,[181,296,209],{"emptyLinePlaceholder":208},[181,298,300,302,305,307,309,312,314,316,319,322,325],{"class":183,"line":299},7,[181,301,215],{"class":187},[181,303,304],{"class":218}," actor",[181,306,222],{"class":187},[181,308,255],{"class":187},[181,310,311],{"class":191}," api.actors.",[181,313,261],{"class":228},[181,315,264],{"class":191},[181,317,318],{"class":198},"\"web-client\"",[181,320,321],{"class":191},", actorType: ",[181,323,324],{"class":198},"\"user\"",[181,326,276],{"class":191},[181,328,330,332,334,337],{"class":183,"line":329},8,[181,331,282],{"class":191},[181,333,285],{"class":228},[181,335,336],{"class":191},"(actor.accessToken); ",[181,338,339],{"class":241},"// shown once; keep it\n",[19,341,343],{"id":342},"installation","Installation",[168,345,346],{},[171,347,352],{"className":348,"code":349,"filename":350,"language":351,"meta":177,"style":177},"language-bash shiki shiki-themes github-light github-dark","npm install @nolag/dash @nolag/js-sdk\n","Terminal","bash",[26,353,354],{"__ignoreMap":177},[181,355,356,359,362,365],{"class":183,"line":184},[181,357,358],{"class":228},"npm",[181,360,361],{"class":198}," install",[181,363,364],{"class":198}," @nolag/dash",[181,366,367],{"class":198}," @nolag/js-sdk\n",[142,369,370],{"type":144},[15,371,372,375,376,378,379,382,383,386,387,390],{},[148,373,374],{},"Shared connection."," One core NoLag client can back several wrapper SDKs at once, for example a dashboard, chat, and notify on a single socket, as long as each wrapper uses a distinct ",[26,377,165],{},". Each wrapper attaches its handlers on construction and releases them with ",[26,380,381],{},"detach()",", and never touches the socket itself. Your app owns ",[26,384,385],{},"connect()"," and ",[26,388,389],{},"disconnect()",".",[19,392,394],{"id":393},"quick-start","Quick Start",[168,396,397],{},[171,398,401],{"className":173,"code":399,"filename":400,"language":176,"meta":177,"style":177},"import { NoLag } from '@nolag/js-sdk'\nimport { NoLagDash } from '@nolag/dash'\n\n// The app owns one core client. In a browser, pass a token provider so the\n// SDK can mint fresh short-lived client tokens from your backend.\nconst client = NoLag(async () => (await (await fetch('/api/nolag-token')).json()).token)\n\n// Inject the client into the dash wrapper\nconst dash = new NoLagDash({\n  client,\n  appName: APP_SLUG, // the slug returned when you created the app\n  username: 'Alice',\n})\n\nawait client.connect()   // the app owns the connection\nawait dash.ready()       // wrapper setup complete\n\n// Join the seeded panel\nconst panel = dash.joinPanel('overview')\n\n// Publish a metric (typically called from a server or agent). The point is\n// stamped with Date.now() and added to the publisher's own buffer.\npanel.publishMetric('cpu.usage', 74.2, {\n  unit: 'percent',\n  tags: { host: 'web-01', region: 'us-east-1' },\n})\n\n// Listen for incoming metrics from other publishers\npanel.on('metric', ({ streamId, value, timestamp }) => {\n  console.log(`[${streamId}] ${value} @ ${new Date(timestamp).toISOString()}`)\n})\n\n// Get all buffered data points for a metric stream\nconst points = panel.getMetrics('cpu.usage')\nconsole.log('Data points:', points.length)\n\n// Get a rolling aggregation over the last 5 minutes\nconst agg = panel.getAggregation('cpu.usage', 5 * 60_000)\nconsole.log('Avg CPU:', agg.avg.toFixed(1) + '%')\nconsole.log('Max CPU:', agg.max.toFixed(1) + '%')\n\n// Publish a widget state (e.g. a status counter)\npanel.publishWidget('active-sessions', 'counter', { value: 1_248, trend: 'up' }, 'Active Sessions')\n\n// Listen for widget updates\npanel.on('widgetUpdate', ({ widgetId, type, data }) => {\n  console.log(`Widget ${widgetId} (${type}):`, data)\n})\n\n// Read current widget state\nconst widget = panel.getWidget('active-sessions')\n\n// Teardown: the wrapper releases its handlers; the app closes the socket.\ndash.detach()\nclient.disconnect()\n","TypeScript",[26,402,403,415,427,431,436,441,492,496,501,519,525,540,552,558,563,580,597,602,608,631,636,642,648,670,681,699,704,709,715,753,800,805,810,816,838,858,863,869,901,935,964,969,975,1013,1018,1024,1057,1082,1087,1092,1098,1119,1124,1130,1142],{"__ignoreMap":177},[181,404,405,407,410,412],{"class":183,"line":184},[181,406,188],{"class":187},[181,408,409],{"class":191}," { NoLag } ",[181,411,195],{"class":187},[181,413,414],{"class":198}," '@nolag/js-sdk'\n",[181,416,417,419,422,424],{"class":183,"line":205},[181,418,188],{"class":187},[181,420,421],{"class":191}," { NoLagDash } ",[181,423,195],{"class":187},[181,425,426],{"class":198}," '@nolag/dash'\n",[181,428,429],{"class":183,"line":212},[181,430,209],{"emptyLinePlaceholder":208},[181,432,433],{"class":183,"line":245},[181,434,435],{"class":241},"// The app owns one core client. In a browser, pass a token provider so the\n",[181,437,438],{"class":183,"line":279},[181,439,440],{"class":241},"// SDK can mint fresh short-lived client tokens from your backend.\n",[181,442,443,445,448,450,453,456,459,462,465,468,471,473,475,478,480,483,486,489],{"class":183,"line":294},[181,444,215],{"class":187},[181,446,447],{"class":218}," client",[181,449,222],{"class":187},[181,451,452],{"class":228}," NoLag",[181,454,455],{"class":191},"(",[181,457,458],{"class":187},"async",[181,460,461],{"class":191}," () ",[181,463,464],{"class":187},"=>",[181,466,467],{"class":191}," (",[181,469,470],{"class":187},"await",[181,472,467],{"class":191},[181,474,470],{"class":187},[181,476,477],{"class":228}," fetch",[181,479,455],{"class":191},[181,481,482],{"class":198},"'/api/nolag-token'",[181,484,485],{"class":191},")).",[181,487,488],{"class":228},"json",[181,490,491],{"class":191},"()).token)\n",[181,493,494],{"class":183,"line":299},[181,495,209],{"emptyLinePlaceholder":208},[181,497,498],{"class":183,"line":329},[181,499,500],{"class":241},"// Inject the client into the dash wrapper\n",[181,502,504,506,509,511,513,516],{"class":183,"line":503},9,[181,505,215],{"class":187},[181,507,508],{"class":218}," dash",[181,510,222],{"class":187},[181,512,225],{"class":187},[181,514,515],{"class":228}," NoLagDash",[181,517,518],{"class":191},"({\n",[181,520,522],{"class":183,"line":521},10,[181,523,524],{"class":191},"  client,\n",[181,526,528,531,534,537],{"class":183,"line":527},11,[181,529,530],{"class":191},"  appName: ",[181,532,533],{"class":218},"APP_SLUG",[181,535,536],{"class":191},", ",[181,538,539],{"class":241},"// the slug returned when you created the app\n",[181,541,543,546,549],{"class":183,"line":542},12,[181,544,545],{"class":191},"  username: ",[181,547,548],{"class":198},"'Alice'",[181,550,551],{"class":191},",\n",[181,553,555],{"class":183,"line":554},13,[181,556,557],{"class":191},"})\n",[181,559,561],{"class":183,"line":560},14,[181,562,209],{"emptyLinePlaceholder":208},[181,564,566,568,571,574,577],{"class":183,"line":565},15,[181,567,470],{"class":187},[181,569,570],{"class":191}," client.",[181,572,573],{"class":228},"connect",[181,575,576],{"class":191},"()   ",[181,578,579],{"class":241},"// the app owns the connection\n",[181,581,583,585,588,591,594],{"class":183,"line":582},16,[181,584,470],{"class":187},[181,586,587],{"class":191}," dash.",[181,589,590],{"class":228},"ready",[181,592,593],{"class":191},"()       ",[181,595,596],{"class":241},"// wrapper setup complete\n",[181,598,600],{"class":183,"line":599},17,[181,601,209],{"emptyLinePlaceholder":208},[181,603,605],{"class":183,"line":604},18,[181,606,607],{"class":241},"// Join the seeded panel\n",[181,609,611,613,616,618,620,623,625,628],{"class":183,"line":610},19,[181,612,215],{"class":187},[181,614,615],{"class":218}," panel",[181,617,222],{"class":187},[181,619,587],{"class":191},[181,621,622],{"class":228},"joinPanel",[181,624,455],{"class":191},[181,626,627],{"class":198},"'overview'",[181,629,630],{"class":191},")\n",[181,632,634],{"class":183,"line":633},20,[181,635,209],{"emptyLinePlaceholder":208},[181,637,639],{"class":183,"line":638},21,[181,640,641],{"class":241},"// Publish a metric (typically called from a server or agent). The point is\n",[181,643,645],{"class":183,"line":644},22,[181,646,647],{"class":241},"// stamped with Date.now() and added to the publisher's own buffer.\n",[181,649,651,654,657,659,662,664,667],{"class":183,"line":650},23,[181,652,653],{"class":191},"panel.",[181,655,656],{"class":228},"publishMetric",[181,658,455],{"class":191},[181,660,661],{"class":198},"'cpu.usage'",[181,663,536],{"class":191},[181,665,666],{"class":218},"74.2",[181,668,669],{"class":191},", {\n",[181,671,673,676,679],{"class":183,"line":672},24,[181,674,675],{"class":191},"  unit: ",[181,677,678],{"class":198},"'percent'",[181,680,551],{"class":191},[181,682,684,687,690,693,696],{"class":183,"line":683},25,[181,685,686],{"class":191},"  tags: { host: ",[181,688,689],{"class":198},"'web-01'",[181,691,692],{"class":191},", region: ",[181,694,695],{"class":198},"'us-east-1'",[181,697,698],{"class":191}," },\n",[181,700,702],{"class":183,"line":701},26,[181,703,557],{"class":191},[181,705,707],{"class":183,"line":706},27,[181,708,209],{"emptyLinePlaceholder":208},[181,710,712],{"class":183,"line":711},28,[181,713,714],{"class":241},"// Listen for incoming metrics from other publishers\n",[181,716,718,720,723,725,728,731,735,737,740,742,745,748,750],{"class":183,"line":717},29,[181,719,653],{"class":191},[181,721,722],{"class":228},"on",[181,724,455],{"class":191},[181,726,727],{"class":198},"'metric'",[181,729,730],{"class":191},", ({ ",[181,732,734],{"class":733},"s4XuR","streamId",[181,736,536],{"class":191},[181,738,739],{"class":733},"value",[181,741,536],{"class":191},[181,743,744],{"class":733},"timestamp",[181,746,747],{"class":191}," }) ",[181,749,464],{"class":187},[181,751,752],{"class":191}," {\n",[181,754,756,759,761,763,766,768,771,773,776,779,782,784,786,789,792,795,798],{"class":183,"line":755},30,[181,757,758],{"class":191},"  console.",[181,760,285],{"class":228},[181,762,455],{"class":191},[181,764,765],{"class":198},"`[${",[181,767,734],{"class":191},[181,769,770],{"class":198},"}] ${",[181,772,739],{"class":191},[181,774,775],{"class":198},"} @ ${",[181,777,778],{"class":187},"new",[181,780,781],{"class":228}," Date",[181,783,455],{"class":198},[181,785,744],{"class":191},[181,787,788],{"class":198},").",[181,790,791],{"class":228},"toISOString",[181,793,794],{"class":198},"()",[181,796,797],{"class":198},"}`",[181,799,630],{"class":191},[181,801,803],{"class":183,"line":802},31,[181,804,557],{"class":191},[181,806,808],{"class":183,"line":807},32,[181,809,209],{"emptyLinePlaceholder":208},[181,811,813],{"class":183,"line":812},33,[181,814,815],{"class":241},"// Get all buffered data points for a metric stream\n",[181,817,819,821,824,826,829,832,834,836],{"class":183,"line":818},34,[181,820,215],{"class":187},[181,822,823],{"class":218}," points",[181,825,222],{"class":187},[181,827,828],{"class":191}," panel.",[181,830,831],{"class":228},"getMetrics",[181,833,455],{"class":191},[181,835,661],{"class":198},[181,837,630],{"class":191},[181,839,841,843,845,847,850,853,856],{"class":183,"line":840},35,[181,842,282],{"class":191},[181,844,285],{"class":228},[181,846,455],{"class":191},[181,848,849],{"class":198},"'Data points:'",[181,851,852],{"class":191},", points.",[181,854,855],{"class":218},"length",[181,857,630],{"class":191},[181,859,861],{"class":183,"line":860},36,[181,862,209],{"emptyLinePlaceholder":208},[181,864,866],{"class":183,"line":865},37,[181,867,868],{"class":241},"// Get a rolling aggregation over the last 5 minutes\n",[181,870,872,874,877,879,881,884,886,888,890,893,896,899],{"class":183,"line":871},38,[181,873,215],{"class":187},[181,875,876],{"class":218}," agg",[181,878,222],{"class":187},[181,880,828],{"class":191},[181,882,883],{"class":228},"getAggregation",[181,885,455],{"class":191},[181,887,661],{"class":198},[181,889,536],{"class":191},[181,891,892],{"class":218},"5",[181,894,895],{"class":187}," *",[181,897,898],{"class":218}," 60_000",[181,900,630],{"class":191},[181,902,904,906,908,910,913,916,919,921,924,927,930,933],{"class":183,"line":903},39,[181,905,282],{"class":191},[181,907,285],{"class":228},[181,909,455],{"class":191},[181,911,912],{"class":198},"'Avg CPU:'",[181,914,915],{"class":191},", agg.avg.",[181,917,918],{"class":228},"toFixed",[181,920,455],{"class":191},[181,922,923],{"class":218},"1",[181,925,926],{"class":191},") ",[181,928,929],{"class":187},"+",[181,931,932],{"class":198}," '%'",[181,934,630],{"class":191},[181,936,938,940,942,944,947,950,952,954,956,958,960,962],{"class":183,"line":937},40,[181,939,282],{"class":191},[181,941,285],{"class":228},[181,943,455],{"class":191},[181,945,946],{"class":198},"'Max CPU:'",[181,948,949],{"class":191},", agg.max.",[181,951,918],{"class":228},[181,953,455],{"class":191},[181,955,923],{"class":218},[181,957,926],{"class":191},[181,959,929],{"class":187},[181,961,932],{"class":198},[181,963,630],{"class":191},[181,965,967],{"class":183,"line":966},41,[181,968,209],{"emptyLinePlaceholder":208},[181,970,972],{"class":183,"line":971},42,[181,973,974],{"class":241},"// Publish a widget state (e.g. a status counter)\n",[181,976,978,980,983,985,988,990,993,996,999,1002,1005,1008,1011],{"class":183,"line":977},43,[181,979,653],{"class":191},[181,981,982],{"class":228},"publishWidget",[181,984,455],{"class":191},[181,986,987],{"class":198},"'active-sessions'",[181,989,536],{"class":191},[181,991,992],{"class":198},"'counter'",[181,994,995],{"class":191},", { value: ",[181,997,998],{"class":218},"1_248",[181,1000,1001],{"class":191},", trend: ",[181,1003,1004],{"class":198},"'up'",[181,1006,1007],{"class":191}," }, ",[181,1009,1010],{"class":198},"'Active Sessions'",[181,1012,630],{"class":191},[181,1014,1016],{"class":183,"line":1015},44,[181,1017,209],{"emptyLinePlaceholder":208},[181,1019,1021],{"class":183,"line":1020},45,[181,1022,1023],{"class":241},"// Listen for widget updates\n",[181,1025,1027,1029,1031,1033,1036,1038,1041,1043,1046,1048,1051,1053,1055],{"class":183,"line":1026},46,[181,1028,653],{"class":191},[181,1030,722],{"class":228},[181,1032,455],{"class":191},[181,1034,1035],{"class":198},"'widgetUpdate'",[181,1037,730],{"class":191},[181,1039,1040],{"class":733},"widgetId",[181,1042,536],{"class":191},[181,1044,1045],{"class":733},"type",[181,1047,536],{"class":191},[181,1049,1050],{"class":733},"data",[181,1052,747],{"class":191},[181,1054,464],{"class":187},[181,1056,752],{"class":191},[181,1058,1060,1062,1064,1066,1069,1071,1074,1076,1079],{"class":183,"line":1059},47,[181,1061,758],{"class":191},[181,1063,285],{"class":228},[181,1065,455],{"class":191},[181,1067,1068],{"class":198},"`Widget ${",[181,1070,1040],{"class":191},[181,1072,1073],{"class":198},"} (${",[181,1075,1045],{"class":191},[181,1077,1078],{"class":198},"}):`",[181,1080,1081],{"class":191},", data)\n",[181,1083,1085],{"class":183,"line":1084},48,[181,1086,557],{"class":191},[181,1088,1090],{"class":183,"line":1089},49,[181,1091,209],{"emptyLinePlaceholder":208},[181,1093,1095],{"class":183,"line":1094},50,[181,1096,1097],{"class":241},"// Read current widget state\n",[181,1099,1101,1103,1106,1108,1110,1113,1115,1117],{"class":183,"line":1100},51,[181,1102,215],{"class":187},[181,1104,1105],{"class":218}," widget",[181,1107,222],{"class":187},[181,1109,828],{"class":191},[181,1111,1112],{"class":228},"getWidget",[181,1114,455],{"class":191},[181,1116,987],{"class":198},[181,1118,630],{"class":191},[181,1120,1122],{"class":183,"line":1121},52,[181,1123,209],{"emptyLinePlaceholder":208},[181,1125,1127],{"class":183,"line":1126},53,[181,1128,1129],{"class":241},"// Teardown: the wrapper releases its handlers; the app closes the socket.\n",[181,1131,1133,1136,1139],{"class":183,"line":1132},54,[181,1134,1135],{"class":191},"dash.",[181,1137,1138],{"class":228},"detach",[181,1140,1141],{"class":191},"()\n",[181,1143,1145,1148,1151],{"class":183,"line":1144},55,[181,1146,1147],{"class":191},"client.",[181,1149,1150],{"class":228},"disconnect",[181,1152,1141],{"class":191},[19,1154,1156],{"id":1155},"api-reference","API Reference",[34,1158,31],{"id":1159},"nolagdash-1",[15,1161,1162],{},"The main class. Attaches to the injected core client and manages the dashboard panel lifecycle.",[1164,1165,1167],"h4",{"id":1166},"constructor-options","Constructor Options",[95,1169,1170,1183],{},[98,1171,1172],{},[101,1173,1174,1177,1180],{},[104,1175,1176],{},"Option",[104,1178,1179],{},"Type",[104,1181,1182],{},"Description",[111,1184,1185,1203,1218,1233,1250,1265,1283,1309],{},[101,1186,1187,1192,1197],{},[116,1188,1189],{},[26,1190,1191],{},"client",[116,1193,1194],{},[26,1195,1196],{},"NoLagSocket",[116,1198,1199,1202],{},[148,1200,1201],{},"Required."," The injected core NoLag client the app owns and connects.",[101,1204,1205,1210,1215],{},[116,1206,1207],{},[26,1208,1209],{},"username",[116,1211,1212],{},[26,1213,1214],{},"string",[116,1216,1217],{},"Optional display name for this viewer.",[101,1219,1220,1225,1230],{},[116,1221,1222],{},[26,1223,1224],{},"metadata",[116,1226,1227],{},[26,1228,1229],{},"Record\u003Cstring, unknown>",[116,1231,1232],{},"Optional custom viewer data attached to presence.",[101,1234,1235,1239,1243],{},[116,1236,1237],{},[26,1238,165],{},[116,1240,1241],{},[26,1242,1214],{},[116,1244,1245,1246,1249],{},"The app slug returned when you created the app (default ",[26,1247,1248],{},"'dash'",", which only works if an app with exactly that slug exists).",[101,1251,1252,1257,1262],{},[116,1253,1254],{},[26,1255,1256],{},"panels",[116,1258,1259],{},[26,1260,1261],{},"string[]",[116,1263,1264],{},"Panels to subscribe to once the wrapper is ready.",[101,1266,1267,1272,1277],{},[116,1268,1269],{},[26,1270,1271],{},"maxMetricPoints",[116,1273,1274],{},[26,1275,1276],{},"number",[116,1278,1279,1280,788],{},"Max metric points kept in memory per stream (default ",[26,1281,1282],{},"1000",[101,1284,1285,1290,1294],{},[116,1286,1287],{},[26,1288,1289],{},"aggregationWindow",[116,1291,1292],{},[26,1293,1276],{},[116,1295,1296,1297,1300,1301,1304,1305,1308],{},"Accepted and stored (default ",[26,1298,1299],{},"60000",") but not read yet: ",[26,1302,1303],{},"getAggregation()"," uses 60000 ms whenever ",[26,1306,1307],{},"windowMs"," is omitted.",[101,1310,1311,1316,1321],{},[116,1312,1313],{},[26,1314,1315],{},"debug",[116,1317,1318],{},[26,1319,1320],{},"boolean",[116,1322,1323,1324,788],{},"Enable wrapper debug logging (default ",[26,1325,1326],{},"false",[95,1328,1329,1341],{},[98,1330,1331],{},[101,1332,1333,1336,1339],{},[104,1334,1335],{},"Method",[104,1337,1338],{},"Returns",[104,1340,1182],{},[111,1342,1343,1358,1372,1392,1406,1421],{},[101,1344,1345,1350,1355],{},[116,1346,1347],{},[26,1348,1349],{},"ready()",[116,1351,1352],{},[26,1353,1354],{},"Promise\u003Cvoid>",[116,1356,1357],{},"Resolves once wrapper setup completed",[101,1359,1360,1364,1369],{},[116,1361,1362],{},[26,1363,381],{},[116,1365,1366],{},[26,1367,1368],{},"void",[116,1370,1371],{},"Release this wrapper's handlers and topics; terminal, never closes the socket",[101,1373,1374,1379,1383],{},[116,1375,1376],{},[26,1377,1378],{},"joinPanel(name, opts?)",[116,1380,1381],{},[26,1382,76],{},[116,1384,1385,1386,1389,1390],{},"Join a dashboard panel; ",[26,1387,1388],{},"opts.filters"," limits metrics and widgets to matching values; throws before ",[26,1391,1349],{},[101,1393,1394,1399,1403],{},[116,1395,1396],{},[26,1397,1398],{},"leavePanel(name)",[116,1400,1401],{},[26,1402,1368],{},[116,1404,1405],{},"Leave a panel and unsubscribe from its topics",[101,1407,1408,1413,1418],{},[116,1409,1410],{},[26,1411,1412],{},"getPanels()",[116,1414,1415],{},[26,1416,1417],{},"DashboardPanel[]",[116,1419,1420],{},"All joined panels",[101,1422,1423,1428,1433],{},[116,1424,1425],{},[26,1426,1427],{},"getOnlineViewers()",[116,1429,1430],{},[26,1431,1432],{},"DashboardViewer[]",[116,1434,1435],{},"All viewers currently online in the lobby",[34,1437,1439],{"id":1438},"events-nolagdash","Events: NoLagDash",[95,1441,1442,1454],{},[98,1443,1444],{},[101,1445,1446,1449,1452],{},[104,1447,1448],{},"Event",[104,1450,1451],{},"Payload",[104,1453,1182],{},[111,1455,1456,1469,1484,1496,1508,1523,1538],{},[101,1457,1458,1463,1466],{},[116,1459,1460],{},[26,1461,1462],{},"connected",[116,1464,1465],{},"none",[116,1467,1468],{},"Wrapper setup completed on a fresh connection",[101,1470,1471,1476,1481],{},[116,1472,1473],{},[26,1474,1475],{},"disconnected",[116,1477,1478],{},[26,1479,1480],{},"reason: string",[116,1482,1483],{},"Connection closed",[101,1485,1486,1491,1493],{},[116,1487,1488],{},[26,1489,1490],{},"reconnecting",[116,1492,1465],{},[116,1494,1495],{},"The client is attempting to reconnect",[101,1497,1498,1503,1505],{},[116,1499,1500],{},[26,1501,1502],{},"reconnected",[116,1504,1465],{},[116,1506,1507],{},"Reconnection successful; panels are restored automatically",[101,1509,1510,1515,1520],{},[116,1511,1512],{},[26,1513,1514],{},"error",[116,1516,1517],{},[26,1518,1519],{},"error: Error",[116,1521,1522],{},"Unrecoverable error occurred",[101,1524,1525,1530,1535],{},[116,1526,1527],{},[26,1528,1529],{},"viewerOnline",[116,1531,1532],{},[26,1533,1534],{},"viewer: DashboardViewer",[116,1536,1537],{},"A viewer appeared in the lobby",[101,1539,1540,1545,1549],{},[116,1541,1542],{},[26,1543,1544],{},"viewerOffline",[116,1546,1547],{},[26,1548,1534],{},[116,1550,1551],{},"A viewer left the lobby",[34,1553,76],{"id":1554},"dashboardpanel",[15,1556,1557,1558,1560],{},"Returned by ",[26,1559,72],{},". Handles metric ingestion, aggregation, widget state, and per-panel viewer presence.",[95,1562,1563,1573],{},[98,1564,1565],{},[101,1566,1567,1569,1571],{},[104,1568,1335],{},[104,1570,1338],{},[104,1572,1182],{},[111,1574,1575,1610,1631,1646,1667,1682,1697,1711],{},[101,1576,1577,1582,1587],{},[116,1578,1579],{},[26,1580,1581],{},"publishMetric(streamId, value, opts?)",[116,1583,1584],{},[26,1585,1586],{},"MetricPoint",[116,1588,1589,1590,1593,1594,536,1597,536,1600,536,1603,1606,1607],{},"Publish a data point; ",[26,1591,1592],{},"opts"," accepts ",[26,1595,1596],{},"unit",[26,1598,1599],{},"tags",[26,1601,1602],{},"filter",[26,1604,1605],{},"filters",". The timestamp is always ",[26,1608,1609],{},"Date.now()",[101,1611,1612,1617,1622],{},[116,1613,1614],{},[26,1615,1616],{},"publishWidget(widgetId, type, data, label?, opts?)",[116,1618,1619],{},[26,1620,1621],{},"WidgetUpdate",[116,1623,1624,1625,1627,1628],{},"Publish a widget snapshot; replaces the previous state for that widget ID. ",[26,1626,1045],{}," is ",[26,1629,1630],{},"'gauge' | 'chart' | 'counter' | 'table' | 'text' | 'custom'",[101,1632,1633,1638,1643],{},[116,1634,1635],{},[26,1636,1637],{},"getMetrics(streamId?)",[116,1639,1640],{},[26,1641,1642],{},"MetricPoint[]",[116,1644,1645],{},"Buffered data points for one stream, or every stream when omitted",[101,1647,1648,1653,1658],{},[116,1649,1650],{},[26,1651,1652],{},"getAggregation(streamId, windowMs?)",[116,1654,1655],{},[26,1656,1657],{},"Aggregation",[116,1659,1660,1663,1664,1666],{},[26,1661,1662],{},"{ streamId, min, max, avg, sum, count, last, windowMs }"," over the last ",[26,1665,1307],{}," ms (60000 when omitted)",[101,1668,1669,1674,1679],{},[116,1670,1671],{},[26,1672,1673],{},"getWidget(widgetId)",[116,1675,1676],{},[26,1677,1678],{},"WidgetUpdate | undefined",[116,1680,1681],{},"Latest state snapshot for a single widget",[101,1683,1684,1689,1694],{},[116,1685,1686],{},[26,1687,1688],{},"getWidgets()",[116,1690,1691],{},[26,1692,1693],{},"WidgetUpdate[]",[116,1695,1696],{},"Latest state snapshots for all widgets in this panel",[101,1698,1699,1704,1708],{},[116,1700,1701],{},[26,1702,1703],{},"getViewers()",[116,1705,1706],{},[26,1707,1432],{},[116,1709,1710],{},"Remote viewers present in this panel",[101,1712,1713,1718,1722],{},[116,1714,1715],{},[26,1716,1717],{},"setFilters(values, opts?)",[116,1719,1720],{},[26,1721,1368],{},[116,1723,1724,1725],{},"Replace the panel's subscription filters; see ",[136,1726,1728],{"href":1727},"/docs/concepts/filters","Filters",[34,1730,1732],{"id":1731},"events-dashboardpanel","Events: DashboardPanel",[95,1734,1735,1745],{},[98,1736,1737],{},[101,1738,1739,1741,1743],{},[104,1740,1448],{},[104,1742,1451],{},[104,1744,1182],{},[111,1746,1747,1764,1781,1795],{},[101,1748,1749,1754,1758],{},[116,1750,1751],{},[26,1752,1753],{},"metric",[116,1755,1756],{},[26,1757,1586],{},[116,1759,1760,1761],{},"A data point arrived: ",[26,1762,1763],{},"{ id, streamId, value, unit?, tags?, timestamp, isReplay }",[101,1765,1766,1771,1775],{},[116,1767,1768],{},[26,1769,1770],{},"widgetUpdate",[116,1772,1773],{},[26,1774,1621],{},[116,1776,1777,1778],{},"A widget snapshot arrived: ",[26,1779,1780],{},"{ id, widgetId, type, data, label?, timestamp, isReplay }",[101,1782,1783,1788,1792],{},[116,1784,1785],{},[26,1786,1787],{},"viewerJoined",[116,1789,1790],{},[26,1791,1534],{},[116,1793,1794],{},"A viewer joined this panel",[101,1796,1797,1802,1806],{},[116,1798,1799],{},[26,1800,1801],{},"viewerLeft",[116,1803,1804],{},[26,1805,1534],{},[116,1807,1808],{},"A viewer left this panel",[1810,1811,1812],"style",{},"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 .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":177,"searchDepth":205,"depth":205,"links":1814},[1815,1818,1819,1820,1821],{"id":21,"depth":205,"text":22,"children":1816},[1817],{"id":36,"depth":212,"text":37},{"id":59,"depth":205,"text":60},{"id":342,"depth":205,"text":343},{"id":393,"depth":205,"text":394},{"id":1155,"depth":205,"text":1156,"children":1822},[1823,1824,1825,1826],{"id":1159,"depth":212,"text":31},{"id":1438,"depth":212,"text":1439},{"id":1554,"depth":212,"text":76},{"id":1731,"depth":212,"text":1732},"md",{},"/docs/high-level-sdks/dash",{"title":5,"description":17},"docs/high-level-sdks/dash","AyqOBleAx1jfg4SkOVGj0nu2BFIGk7hjiJR-_IFRZuQ",1789869420243]