lopata 0.1.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Lopata
1
+ # Lopata 🪏
2
2
 
3
3
  > **This is a local development tool only.** Lopata is not intended for production use and never will be. Always deploy to Cloudflare Workers for production workloads.
4
4
 
@@ -25,7 +25,6 @@
25
25
  --color-emerald-700: oklch(50.8% .118 165.612);
26
26
  --color-cyan-400: oklch(78.9% .154 211.53);
27
27
  --color-cyan-500: oklch(71.5% .143 215.221);
28
- --color-blue-200: oklch(88.2% .059 254.128);
29
28
  --color-blue-300: oklch(80.9% .105 251.813);
30
29
  --color-blue-400: oklch(70.7% .165 254.624);
31
30
  --color-blue-500: oklch(62.3% .214 259.815);
@@ -720,6 +719,10 @@
720
719
  max-height: 160px;
721
720
  }
722
721
 
722
+ .min-h-0 {
723
+ min-height: calc(var(--spacing) * 0);
724
+ }
725
+
723
726
  .min-h-\[2rem\] {
724
727
  min-height: 2rem;
725
728
  }
@@ -812,6 +815,11 @@
812
815
  width: 960px;
813
816
  }
814
817
 
818
+ .w-fit {
819
+ width: -moz-fit-content;
820
+ width: fit-content;
821
+ }
822
+
815
823
  .w-full {
816
824
  width: 100%;
817
825
  }
@@ -1162,6 +1170,16 @@
1162
1170
  border-left-width: 3px;
1163
1171
  }
1164
1172
 
1173
+ .border-amber-500\/20 {
1174
+ border-color: #f99c0033;
1175
+ }
1176
+
1177
+ @supports (color: color-mix(in lab, red, red)) {
1178
+ .border-amber-500\/20 {
1179
+ border-color: color-mix(in oklab, var(--color-amber-500) 20%, transparent);
1180
+ }
1181
+ }
1182
+
1165
1183
  .border-amber-500\/30 {
1166
1184
  border-color: #f99c004d;
1167
1185
  }
@@ -1172,10 +1190,6 @@
1172
1190
  }
1173
1191
  }
1174
1192
 
1175
- .border-blue-200 {
1176
- border-color: var(--color-blue-200);
1177
- }
1178
-
1179
1193
  .border-blue-500\/30 {
1180
1194
  border-color: #3080ff4d;
1181
1195
  }
@@ -1562,10 +1576,6 @@
1562
1576
  }
1563
1577
  }
1564
1578
 
1565
- .bg-white {
1566
- background-color: var(--color-white);
1567
- }
1568
-
1569
1579
  .bg-yellow-400 {
1570
1580
  background-color: var(--color-yellow-400);
1571
1581
  }
@@ -1751,6 +1761,10 @@
1751
1761
  padding-bottom: calc(var(--spacing) * 5);
1752
1762
  }
1753
1763
 
1764
+ .pl-1 {
1765
+ padding-left: calc(var(--spacing) * 1);
1766
+ }
1767
+
1754
1768
  .text-center {
1755
1769
  text-align: center;
1756
1770
  }
@@ -1892,6 +1906,16 @@
1892
1906
  color: var(--color-amber-400);
1893
1907
  }
1894
1908
 
1909
+ .text-amber-400\/80 {
1910
+ color: #fcbb00cc;
1911
+ }
1912
+
1913
+ @supports (color: color-mix(in lab, red, red)) {
1914
+ .text-amber-400\/80 {
1915
+ color: color-mix(in oklab, var(--color-amber-400) 80%, transparent);
1916
+ }
1917
+ }
1918
+
1895
1919
  .text-amber-500 {
1896
1920
  color: var(--color-amber-500);
1897
1921
  }
@@ -2502,10 +2526,6 @@
2502
2526
  }
2503
2527
  }
2504
2528
 
2505
- .focus\:border-blue-400:focus {
2506
- border-color: var(--color-blue-400);
2507
- }
2508
-
2509
2529
  .focus\:border-border:focus {
2510
2530
  border-color: var(--color-border);
2511
2531
  }
@@ -2523,10 +2543,6 @@
2523
2543
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2524
2544
  }
2525
2545
 
2526
- .focus\:ring-blue-300:focus {
2527
- --tw-ring-color: var(--color-blue-300);
2528
- }
2529
-
2530
2546
  .focus\:ring-border:focus {
2531
2547
  --tw-ring-color: var(--color-border);
2532
2548
  }
@@ -1005,6 +1005,12 @@ function parseHashRoute(hash) {
1005
1005
  const segments = pathname.split("/").filter(Boolean);
1006
1006
  return { segments, query: new URLSearchParams(queryStr) };
1007
1007
  }
1008
+ function parseBrowserRoute(segments, baseLen) {
1009
+ const rawTab = segments[baseLen];
1010
+ const tab = rawTab === "schema" || rawTab === "sql" ? rawTab : "data";
1011
+ const table = segments[baseLen + 1] ? decodeURIComponent(segments[baseLen + 1]) : null;
1012
+ return { tab, table };
1013
+ }
1008
1014
  function formatBytes(bytes) {
1009
1015
  if (bytes === 0)
1010
1016
  return "0 B";
@@ -2600,7 +2606,7 @@ function TableSidebar({ tables, selected, onSelect }) {
2600
2606
  function DataBrowserTab({ tables, execQuery, onOpenInConsole, history: history2, browserHistory, historyScope, basePath, routeTable, routeQuery }) {
2601
2607
  const [localTable, setLocalTable] = d2(null);
2602
2608
  const [localRestoredState, setLocalRestoredState] = d2(null);
2603
- const selectedTable = basePath ? routeTable ?? null : localTable;
2609
+ const selectedTable = basePath ? routeTable ?? tables?.[0]?.name ?? null : localTable;
2604
2610
  y2(() => {
2605
2611
  if (!selectedTable && tables?.length) {
2606
2612
  if (basePath) {
@@ -2824,12 +2830,15 @@ function SchemaBrowserTab({ tables }) {
2824
2830
  }
2825
2831
 
2826
2832
  // src/dashboard/sql-browser/sql-console-tab.tsx
2827
- function SqlConsoleTab({ execQuery, initialSql, history: history2 }) {
2833
+ function SqlConsoleTab({ execQuery, generateSql, initialSql, history: history2 }) {
2828
2834
  const [sql, setSql] = d2(initialSql ?? "");
2829
2835
  const [result, setResult] = d2(null);
2830
2836
  const [error, setError] = d2(null);
2831
2837
  const [loading, setLoading] = d2(false);
2832
2838
  const [showHistory, setShowHistory] = d2(false);
2839
+ const [aiPrompt, setAiPrompt] = d2("");
2840
+ const [aiLoading, setAiLoading] = d2(false);
2841
+ const [aiError, setAiError] = d2(null);
2833
2842
  y2(() => {
2834
2843
  if (initialSql)
2835
2844
  setSql(initialSql);
@@ -2853,11 +2862,56 @@ function SqlConsoleTab({ execQuery, initialSql, history: history2 }) {
2853
2862
  setLoading(false);
2854
2863
  }
2855
2864
  };
2865
+ const generate = async () => {
2866
+ if (!generateSql || !aiPrompt.trim() || aiLoading)
2867
+ return;
2868
+ setAiLoading(true);
2869
+ setAiError(null);
2870
+ try {
2871
+ const result2 = await generateSql(aiPrompt);
2872
+ setSql(result2);
2873
+ } catch (e3) {
2874
+ setAiError(e3.message ?? String(e3));
2875
+ } finally {
2876
+ setAiLoading(false);
2877
+ }
2878
+ };
2856
2879
  return /* @__PURE__ */ u3(k, {
2857
2880
  children: [
2858
2881
  /* @__PURE__ */ u3("div", {
2859
2882
  class: "bg-panel rounded-lg border border-border p-5 mb-6",
2860
2883
  children: [
2884
+ generateSql && /* @__PURE__ */ u3("div", {
2885
+ class: "mb-4",
2886
+ children: [
2887
+ /* @__PURE__ */ u3("div", {
2888
+ class: "flex gap-2",
2889
+ children: [
2890
+ /* @__PURE__ */ u3("input", {
2891
+ type: "text",
2892
+ value: aiPrompt,
2893
+ onInput: (e3) => setAiPrompt(e3.target.value),
2894
+ onKeyDown: (e3) => {
2895
+ if (e3.key === "Enter")
2896
+ generate();
2897
+ },
2898
+ placeholder: "Describe query in natural language...",
2899
+ class: "flex-1 bg-panel-secondary border border-border rounded-lg px-4 py-2 text-sm outline-none focus:border-border focus:ring-1 focus:ring-border transition-all"
2900
+ }, undefined, false, undefined, this),
2901
+ /* @__PURE__ */ u3("button", {
2902
+ onClick: generate,
2903
+ disabled: aiLoading || !aiPrompt.trim(),
2904
+ class: "rounded-md px-4 py-2 text-sm font-medium bg-panel border border-border text-text-secondary hover:bg-panel-hover disabled:opacity-40 disabled:cursor-not-allowed transition-all",
2905
+ children: aiLoading ? "Generating..." : "Generate SQL"
2906
+ }, undefined, false, undefined, this)
2907
+ ]
2908
+ }, undefined, true, undefined, this),
2909
+ aiError && /* @__PURE__ */ u3("div", {
2910
+ class: "text-red-500 text-xs mt-1",
2911
+ children: aiError
2912
+ }, undefined, false, undefined, this)
2913
+ ]
2914
+ }, undefined, true, undefined, this),
2861
2915
  /* @__PURE__ */ u3("textarea", {
2862
2916
  value: sql,
2863
2917
  onInput: (e3) => setSql(e3.target.value),
@@ -2960,7 +3014,7 @@ function ResultTable({ columns, rows }) {
2960
3014
  }
2961
3015
 
2962
3016
  // src/dashboard/sql-browser/sql-browser.tsx
2963
- function SqlBrowser({ tables, execQuery, historyScope, basePath, routeTab, routeTable, routeQuery }) {
3017
+ function SqlBrowser({ tables, execQuery, generateSql, historyScope, basePath, routeTab, routeTable, routeQuery }) {
2964
3018
  const [localTab, setLocalTab] = d2("data");
2965
3019
  const tab = basePath ? routeTab ?? "data" : localTab;
2966
3020
  const [consoleSql, setConsoleSql] = d2("");
@@ -3005,6 +3059,7 @@ function SqlBrowser({ tables, execQuery, historyScope, basePath, routeTab, route
3005
3059
  }, undefined, false, undefined, this),
3006
3060
  tab === "sql" && /* @__PURE__ */ u3(SqlConsoleTab, {
3007
3061
  execQuery,
3062
+ generateSql,
3008
3063
  initialSql: consoleSql,
3009
3064
  history: history2
3010
3065
  }, undefined, false, undefined, this)
@@ -4274,15 +4329,13 @@ function D1View({ route }) {
4274
4329
  if (segments.length <= 1)
4275
4330
  return /* @__PURE__ */ u3(D1DatabaseList, {}, undefined, false, undefined, this);
4276
4331
  const dbName = decodeURIComponent(segments[1]);
4277
- const rawTab = segments[2];
4278
- const tab = rawTab === "schema" || rawTab === "sql" ? rawTab : "data";
4279
- const tableName = segments[3] ? decodeURIComponent(segments[3]) : null;
4332
+ const { tab, table } = parseBrowserRoute(segments, 2);
4280
4333
  const basePath = `/d1/${encodeURIComponent(dbName)}`;
4281
4334
  return /* @__PURE__ */ u3(D1DatabaseDetail, {
4282
4335
  dbName,
4283
4336
  basePath,
4284
4337
  routeTab: tab,
4285
- routeTable: tableName,
4338
+ routeTable: table,
4286
4339
  routeQuery: query
4287
4340
  }, undefined, false, undefined, this);
4288
4341
  }
@@ -4349,6 +4402,10 @@ function D1DatabaseDetail({ dbName, basePath, routeTab, routeTable, routeQuery }
4349
4402
  /* @__PURE__ */ u3(SqlBrowser, {
4350
4403
  tables,
4351
4404
  execQuery: (sql) => rpc("d1.query", { dbName, sql }),
4405
+ generateSql: async (prompt2) => {
4406
+ const res = await rpc("d1.generateSql", { dbName, prompt: prompt2 });
4407
+ return res.sql;
4408
+ },
4352
4409
  historyScope: `d1:${dbName}`,
4353
4410
  basePath,
4354
4411
  routeTab,
@@ -4371,16 +4428,14 @@ function DoView({ route }) {
4371
4428
  if (segments.length >= 3) {
4372
4429
  const ns = decodeURIComponent(segments[1]);
4373
4430
  const id = decodeURIComponent(segments[2]);
4374
- const rawTab = segments[3];
4375
- const tab = rawTab === "schema" || rawTab === "sql" ? rawTab : "data";
4376
- const tableName = segments[4] ? decodeURIComponent(segments[4]) : null;
4431
+ const { tab, table } = parseBrowserRoute(segments, 3);
4377
4432
  const basePath = `/do/${encodeURIComponent(ns)}/${encodeURIComponent(id)}`;
4378
4433
  return /* @__PURE__ */ u3(DoInstanceDetail, {
4379
4434
  ns,
4380
4435
  id,
4381
4436
  basePath,
4382
4437
  routeTab: tab,
4383
- routeTable: tableName,
4438
+ routeTable: table,
4384
4439
  routeQuery: query
4385
4440
  }, undefined, false, undefined, this);
4386
4441
  }
@@ -4552,6 +4607,10 @@ function DoInstanceDetail({ ns, id, basePath, routeTab, routeTable, routeQuery }
4552
4607
  children: /* @__PURE__ */ u3(SqlBrowser, {
4553
4608
  tables: sqlTables,
4554
4609
  execQuery: (sql) => rpc("do.sqlQuery", { ns, id, sql }),
4610
+ generateSql: async (prompt2) => {
4611
+ const res = await rpc("do.generateSql", { ns, id, prompt: prompt2 });
4612
+ return res.sql;
4613
+ },
4555
4614
  historyScope: `do:${ns}:${id}`,
4556
4615
  basePath,
4557
4616
  routeTab,
@@ -4954,7 +5013,10 @@ function TraceWaterfall({ spans, events, highlightSpanId, onAddAttributeFilter }
4954
5013
  childMap.set(key, []);
4955
5014
  childMap.get(key).push(s3);
4956
5015
  }
4957
- const getAutoExpanded = () => {
5016
+ const spanIdKey = spans.map((s3) => s3.spanId).join(",");
5017
+ y2(() => {
5018
+ if (spans.length === 0)
5019
+ return;
4958
5020
  const autoCollapsed = new Set;
4959
5021
  function walk(parentId, depth) {
4960
5022
  const children = childMap.get(parentId) ?? [];
@@ -4971,14 +5033,9 @@ function TraceWaterfall({ spans, events, highlightSpanId, onAddAttributeFilter }
4971
5033
  }
4972
5034
  }
4973
5035
  walk(null, 0);
4974
- return autoCollapsed;
4975
- };
4976
- y2(() => {
4977
- if (spans.length > 0) {
4978
- setCollapsedSpans(getAutoExpanded());
4979
- setExpandedSpan(null);
4980
- }
4981
- }, [spans, getAutoExpanded]);
5036
+ setCollapsedSpans(autoCollapsed);
5037
+ setExpandedSpan(null);
5038
+ }, [spanIdKey]);
4982
5039
  const toggleCollapse = (spanId) => {
4983
5040
  setCollapsedSpans((prev) => {
4984
5041
  const next = new Set(prev);
@@ -5064,37 +5121,34 @@ function TraceWaterfall({ spans, events, highlightSpanId, onAddAttributeFilter }
5064
5121
  ]
5065
5122
  }, undefined, true, undefined, this),
5066
5123
  /* @__PURE__ */ u3("div", {
5067
- class: "flex-1 h-6 relative bg-panel-secondary rounded",
5068
- children: [
5069
- /* @__PURE__ */ u3("div", {
5070
- class: `absolute top-0.5 bottom-0.5 rounded flex items-center overflow-hidden ${span.status !== "error" && span.status !== "ok" ? "animate-pulse" : ""}`,
5071
- style: {
5072
- left: `${offset}%`,
5073
- width: `${Math.max(width, 0.5)}%`,
5074
- background: span.status === "error" ? "var(--color-span-error)" : span.status === "ok" ? "var(--color-span-ok)" : "#d1d5db"
5075
- },
5076
- children: [
5077
- keyAttrs.length > 0 && /* @__PURE__ */ u3("span", {
5078
- class: "text-[9px] text-white px-1 truncate whitespace-nowrap",
5079
- children: keyAttrs.map(([k3, v3]) => `${k3}=${String(v3)}`).join(" ")
5080
- }, undefined, false, undefined, this),
5081
- spanEvents.map((ev) => {
5082
- const evOffset = (ev.timestamp - span.startTime) / ((span.endTime ?? Date.now()) - span.startTime || 1) * 100;
5083
- return /* @__PURE__ */ u3("div", {
5084
- class: `absolute top-0 w-1.5 h-full rounded-full ${ev.name === "exception" ? "bg-red-600" : "bg-panel-secondary0"}`,
5085
- style: { left: `${Math.min(evOffset, 100)}%` },
5086
- title: ev.message ?? ev.name
5087
- }, ev.id, false, undefined, this);
5088
- })
5089
- ]
5090
- }, undefined, true, undefined, this),
5091
- /* @__PURE__ */ u3("span", {
5092
- class: "absolute top-0.5 text-[10px] text-text-secondary whitespace-nowrap",
5093
- style: { left: `${offset + width + 1}%` },
5094
- children: span.durationMs !== null ? formatDuration(span.durationMs) : "..."
5095
- }, undefined, false, undefined, this)
5096
- ]
5097
- }, undefined, true, undefined, this)
5124
+ class: "flex-1 h-6 relative bg-panel-secondary rounded overflow-hidden",
5125
+ children: /* @__PURE__ */ u3("div", {
5126
+ class: `absolute top-0.5 bottom-0.5 rounded flex items-center overflow-hidden ${span.status !== "error" && span.status !== "ok" ? "animate-pulse" : ""}`,
5127
+ style: {
5128
+ left: `${offset}%`,
5129
+ width: `${Math.max(width, 0.5)}%`,
5130
+ background: span.status === "error" ? "var(--color-span-error)" : span.status === "ok" ? "var(--color-span-ok)" : "#d1d5db"
5131
+ },
5132
+ children: [
5133
+ keyAttrs.length > 0 && /* @__PURE__ */ u3("span", {
5134
+ class: "text-[9px] text-white px-1 truncate whitespace-nowrap",
5135
+ children: keyAttrs.map(([k3, v3]) => `${k3}=${String(v3)}`).join(" ")
5136
+ }, undefined, false, undefined, this),
5137
+ spanEvents.map((ev) => {
5138
+ const evOffset = (ev.timestamp - span.startTime) / ((span.endTime ?? Date.now()) - span.startTime || 1) * 100;
5139
+ return /* @__PURE__ */ u3("div", {
5140
+ class: `absolute top-0 w-1.5 h-full rounded-full ${ev.name === "exception" ? "bg-red-600" : "bg-panel-secondary0"}`,
5141
+ style: { left: `${Math.min(evOffset, 100)}%` },
5142
+ title: ev.message ?? ev.name
5143
+ }, ev.id, false, undefined, this);
5144
+ })
5145
+ ]
5146
+ }, undefined, true, undefined, this)
5147
+ }, undefined, false, undefined, this),
5148
+ /* @__PURE__ */ u3("span", {
5149
+ class: "text-[10px] text-text-secondary whitespace-nowrap w-14 text-right flex-shrink-0 pl-1",
5150
+ children: span.durationMs !== null ? formatDuration(span.durationMs) : "..."
5151
+ }, undefined, false, undefined, this)
5098
5152
  ]
5099
5153
  }, undefined, true, undefined, this),
5100
5154
  isExpanded && /* @__PURE__ */ u3("div", {
@@ -6219,6 +6273,50 @@ function Section2({ title, children }) {
6219
6273
  ]
6220
6274
  }, undefined, true, undefined, this);
6221
6275
  }
6276
+ function OptionalDepsCard() {
6277
+ const { data: deps } = useQuery("warnings.optionalDeps");
6278
+ if (!deps)
6279
+ return null;
6280
+ const missing = deps.filter((d3) => !d3.installed);
6281
+ if (!missing.length)
6282
+ return null;
6283
+ return /* @__PURE__ */ u3("div", {
6284
+ class: "bg-panel rounded-lg border border-amber-500/20 p-5",
6285
+ children: [
6286
+ /* @__PURE__ */ u3("div", {
6287
+ class: "text-xs font-semibold uppercase tracking-wider text-amber-400 mb-3",
6288
+ children: "Optional packages"
6289
+ }, undefined, false, undefined, this),
6290
+ /* @__PURE__ */ u3("div", {
6291
+ class: "flex flex-col gap-2",
6292
+ children: deps.map((dep) => /* @__PURE__ */ u3("div", {
6293
+ children: [
6294
+ /* @__PURE__ */ u3("div", {
6295
+ class: "flex items-center gap-2",
6296
+ children: [
6297
+ /* @__PURE__ */ u3("span", {
6298
+ class: `text-xs ${dep.installed ? "text-emerald-400" : "text-amber-400"}`,
6299
+ children: dep.installed ? "✓" : "✗"
6300
+ }, undefined, false, undefined, this),
6301
+ /* @__PURE__ */ u3("span", {
6302
+ class: `text-xs ${dep.installed ? "text-text-muted" : "text-text-secondary"}`,
6303
+ children: dep.description
6304
+ }, undefined, false, undefined, this)
6305
+ ]
6306
+ }, undefined, true, undefined, this),
6307
+ !dep.installed && /* @__PURE__ */ u3("code", {
6308
+ class: "block ml-5 mt-0.5 text-[10px] text-amber-400/80 bg-amber-500/10 px-1.5 py-0.5 rounded w-fit",
6309
+ children: [
6310
+ dep.install,
6311
+ " --dev"
6312
+ ]
6313
+ }, undefined, true, undefined, this)
6314
+ ]
6315
+ }, dep.id, true, undefined, this))
6316
+ }, undefined, false, undefined, this)
6317
+ ]
6318
+ }, undefined, true, undefined, this);
6319
+ }
6222
6320
  function HomeView() {
6223
6321
  const { data } = useQuery("overview.get");
6224
6322
  const { data: workers } = useQuery("workers.list");
@@ -6402,6 +6500,7 @@ function HomeView() {
6402
6500
  /* @__PURE__ */ u3("div", {
6403
6501
  class: "flex flex-col gap-5",
6404
6502
  children: [
6503
+ /* @__PURE__ */ u3(OptionalDepsCard, {}, undefined, false, undefined, this),
6405
6504
  /* @__PURE__ */ u3("div", {
6406
6505
  class: "bg-panel rounded-lg border border-border p-5",
6407
6506
  children: [
@@ -7724,7 +7823,7 @@ function TracesView() {
7724
7823
  }, i3, true, undefined, this))
7725
7824
  }, undefined, false, undefined, this),
7726
7825
  /* @__PURE__ */ u3("div", {
7727
- class: "flex-1 overflow-y-auto scrollbar-thin",
7826
+ class: "flex-1 overflow-y-auto scrollbar-thin min-h-0",
7728
7827
  children: isSearching ? /* @__PURE__ */ u3("div", {
7729
7828
  class: "text-text-muted font-medium text-center py-12",
7730
7829
  children: "Searching..."
@@ -8463,52 +8562,45 @@ function CreateWorkflowForm({ name, onCreated }) {
8463
8562
  setError(create.error.message);
8464
8563
  }
8465
8564
  };
8466
- if (!open) {
8467
- return /* @__PURE__ */ u3("button", {
8468
- onClick: () => setOpen(true),
8469
- class: "rounded-md px-3 py-1.5 text-sm font-medium bg-ink text-surface hover:opacity-80 transition-all",
8470
- children: "Create instance"
8471
- }, undefined, false, undefined, this);
8472
- }
8473
- return /* @__PURE__ */ u3("div", {
8474
- class: "bg-panel border border-border rounded-lg p-4 mb-6",
8565
+ const handleClose = () => {
8566
+ setOpen(false);
8567
+ setError("");
8568
+ };
8569
+ return /* @__PURE__ */ u3(k, {
8475
8570
  children: [
8476
- /* @__PURE__ */ u3("div", {
8477
- class: "flex items-center justify-between mb-3",
8478
- children: [
8479
- /* @__PURE__ */ u3("div", {
8480
- class: "text-sm font-semibold text-ink",
8481
- children: "Create workflow instance"
8482
- }, undefined, false, undefined, this),
8483
- /* @__PURE__ */ u3("button", {
8484
- onClick: () => {
8485
- setOpen(false);
8486
- setError("");
8487
- },
8488
- class: "text-text-muted hover:text-text-data text-xs font-medium",
8489
- children: "Cancel"
8490
- }, undefined, false, undefined, this)
8491
- ]
8492
- }, undefined, true, undefined, this),
8493
- /* @__PURE__ */ u3("textarea", {
8494
- value: params,
8495
- onInput: (e3) => setParams(e3.target.value),
8496
- placeholder: '{"key": "value"}',
8497
- class: "w-full bg-panel-secondary border border-border rounded-lg px-3 py-2 text-sm font-mono outline-none focus:border-border focus:ring-1 focus:ring-border transition-all resize-y min-h-[80px]",
8498
- rows: 3
8499
- }, undefined, false, undefined, this),
8500
- error && /* @__PURE__ */ u3("div", {
8501
- class: "text-red-500 text-xs mt-1",
8502
- children: error
8571
+ /* @__PURE__ */ u3("button", {
8572
+ onClick: () => setOpen(true),
8573
+ class: "rounded-md px-3 py-1.5 text-sm font-medium bg-ink text-surface hover:opacity-80 transition-all",
8574
+ children: "Create instance"
8503
8575
  }, undefined, false, undefined, this),
8504
- /* @__PURE__ */ u3("div", {
8505
- class: "flex justify-end mt-3",
8506
- children: /* @__PURE__ */ u3("button", {
8507
- onClick: handleSubmit,
8508
- disabled: create.isLoading || !params.trim(),
8509
- class: "rounded-md px-4 py-1.5 text-sm font-medium bg-ink text-surface hover:opacity-80 transition-all disabled:opacity-50 disabled:cursor-not-allowed",
8510
- children: create.isLoading ? "Creating..." : "Create"
8511
- }, undefined, false, undefined, this)
8576
+ open && /* @__PURE__ */ u3(Modal, {
8577
+ title: "Create workflow instance",
8578
+ onClose: handleClose,
8579
+ children: /* @__PURE__ */ u3("div", {
8580
+ class: "p-5",
8581
+ children: [
8582
+ /* @__PURE__ */ u3("textarea", {
8583
+ value: params,
8584
+ onInput: (e3) => setParams(e3.target.value),
8585
+ placeholder: '{"key": "value"}',
8586
+ class: "w-full bg-panel-secondary border border-border rounded-lg px-3 py-2 text-sm font-mono outline-none focus:border-border focus:ring-1 focus:ring-border transition-all resize-y min-h-[80px]",
8587
+ rows: 3
8588
+ }, undefined, false, undefined, this),
8589
+ error && /* @__PURE__ */ u3("div", {
8590
+ class: "text-red-500 text-xs mt-1",
8591
+ children: error
8592
+ }, undefined, false, undefined, this),
8593
+ /* @__PURE__ */ u3("div", {
8594
+ class: "flex justify-end mt-3",
8595
+ children: /* @__PURE__ */ u3("button", {
8596
+ onClick: handleSubmit,
8597
+ disabled: create.isLoading || !params.trim(),
8598
+ class: "rounded-md px-4 py-1.5 text-sm font-medium bg-ink text-surface hover:opacity-80 transition-all disabled:opacity-50 disabled:cursor-not-allowed",
8599
+ children: create.isLoading ? "Creating..." : "Create"
8600
+ }, undefined, false, undefined, this)
8601
+ }, undefined, false, undefined, this)
8602
+ ]
8603
+ }, undefined, true, undefined, this)
8512
8604
  }, undefined, false, undefined, this)
8513
8605
  ]
8514
8606
  }, undefined, true, undefined, this);
@@ -8815,13 +8907,13 @@ function SendEventForm({ name, id, waitingForEvents, refetch }) {
8815
8907
  value: eventType,
8816
8908
  onInput: (e3) => setEventType(e3.target.value),
8817
8909
  placeholder: "Event type",
8818
- class: "w-full bg-white border border-blue-200 rounded-lg px-3 py-2 text-sm font-mono outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-300 transition-all mb-2"
8910
+ class: "w-full bg-panel-secondary border border-border rounded-lg px-3 py-2 text-sm font-mono outline-none focus:border-border focus:ring-1 focus:ring-border transition-all mb-2"
8819
8911
  }, undefined, false, undefined, this),
8820
8912
  /* @__PURE__ */ u3("textarea", {
8821
8913
  value: payload,
8822
8914
  onInput: (e3) => setPayload(e3.target.value),
8823
8915
  placeholder: '{"key": "value"}',
8824
- class: "w-full bg-white border border-blue-200 rounded-lg px-3 py-2 text-sm font-mono outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-300 transition-all resize-y min-h-[60px]",
8916
+ class: "w-full bg-panel-secondary border border-border rounded-lg px-3 py-2 text-sm font-mono outline-none focus:border-border focus:ring-1 focus:ring-border transition-all resize-y min-h-[60px]",
8825
8917
  rows: 2
8826
8918
  }, undefined, false, undefined, this),
8827
8919
  error && /* @__PURE__ */ u3("div", {
@@ -8,7 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
9
  <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
10
10
 
11
- <link rel="stylesheet" crossorigin href="/__dashboard/assets/chunk-jrv1mhg9.css"><script type="module" crossorigin src="/__dashboard/assets/chunk-5j5em7qa.js"></script></head>
11
+ <link rel="stylesheet" crossorigin href="/__dashboard/assets/chunk-paesqsyf.css"><script type="module" crossorigin src="/__dashboard/assets/chunk-ymq225fp.js"></script></head>
12
12
  <body class="h-full bg-surface text-ink" style="font-family: system-ui, -apple-system, sans-serif;">
13
13
  <script>
14
14
  // Apply saved theme before first paint to prevent flash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lopata",
3
- "version": "0.1.4",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,25 +32,21 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@biomejs/biome": "^2.3.13",
35
+ "@cloudflare/sandbox": "^0.7.4",
35
36
  "@types/bun": "latest",
36
- "dprint": "^0.51.1",
37
37
  "bun-plugin-tailwind": "^0.1.2",
38
- "vite": "^7.3.1",
39
- "wrangler": "^4.65.0"
40
- },
41
- "peerDependencies": {
42
- "typescript": "^5"
43
- },
44
- "optionalDependencies": {
45
- "puppeteer": "*",
46
- "puppeteer-core": "*"
47
- },
48
- "dependencies": {
49
- "@cloudflare/sandbox": "^0.7.4",
38
+ "dprint": "^0.51.1",
50
39
  "html-rewriter-wasm": "^0.4.1",
51
40
  "preact": "^10.28.3",
41
+ "puppeteer": "*",
42
+ "puppeteer-core": "*",
52
43
  "sharp": "^0.34.5",
53
- "smol-toml": "^1.6.0",
54
- "tailwindcss": "^4.1.18"
44
+ "tailwindcss": "^4.1.18",
45
+ "typescript": "^5",
46
+ "vite": "^7.3.1",
47
+ "wrangler": "^4.67.0"
48
+ },
49
+ "dependencies": {
50
+ "smol-toml": "^1.6.0"
55
51
  }
56
52
  }
@@ -15,6 +15,7 @@ import { handlers as queue } from './handlers/queue'
15
15
  import { handlers as r2 } from './handlers/r2'
16
16
  import { handlers as scheduled } from './handlers/scheduled'
17
17
  import { handlers as traces } from './handlers/traces'
18
+ import { handlers as warnings } from './handlers/warnings'
18
19
  import { handlers as workers } from './handlers/workers'
19
20
  import { handlers as workflows } from './handlers/workflows'
20
21
  import type { HandlerContext } from './types'
@@ -38,6 +39,7 @@ const allHandlers = {
38
39
  ...email,
39
40
  ...ai,
40
41
  ...analyticsEngine,
42
+ ...warnings,
41
43
  }
42
44
 
43
45
  export type Procedures = {