@lunora/studio 1.0.0-alpha.3 → 1.0.0-alpha.30
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/__assets__/package-og.svg +1 -1
- package/dist/index.d.ts +29 -18
- package/dist/index.js +29 -29
- package/dist/mount.d.ts +1 -1
- package/dist/mount.js +1 -1
- package/dist/{packem_shared/ApiTab-W3no0KOj.js → packem_chunks/ApiTab.js} +5 -5
- package/dist/{packem_shared/AuditPanel-Bq4o_IqT.js → packem_chunks/AuditPanel.js} +24 -36
- package/dist/{packem_shared/ExportImportPanel-dxY56TDF.js → packem_chunks/ExportImportPanel.js} +13 -9
- package/dist/{packem_shared/FileBrowser-Dhy4zES8.js → packem_chunks/FileBrowser.js} +15 -15
- package/dist/{packem_shared/FunctionRunner--fQJRPAD.js → packem_chunks/FunctionRunner.js} +10 -10
- package/dist/{packem_shared/FunctionStatsPanel-BjRUA_G3.js → packem_chunks/FunctionStatsPanel.js} +147 -204
- package/dist/{packem_shared/HealthPanel-PxclMWmA.js → packem_chunks/HealthPanel.js} +37 -29
- package/dist/{packem_shared/InsightsPanel-CWS_C-xW.js → packem_chunks/InsightsPanel.js} +107 -69
- package/dist/{packem_shared/LogsPanel-CTW8CFcM.js → packem_chunks/LogsPanel.js} +41 -53
- package/dist/{packem_shared/MailPanel-BwkvfIHF.js → packem_chunks/MailPanel.js} +37 -44
- package/dist/{packem_shared/MetricsPanel-BLuOhZQ4.js → packem_chunks/MetricsPanel.js} +41 -322
- package/dist/{packem_shared/MigrationsPanel-DT3lnwHF.js → packem_chunks/MigrationsPanel.js} +39 -46
- package/dist/{packem_shared/PitrPanel-CdErL7EJ.js → packem_chunks/PitrPanel.js} +9 -9
- package/dist/{packem_shared/SchemaViewer-LJDcmNIO.js → packem_chunks/SchemaViewer.js} +15 -15
- package/dist/{packem_shared/SecurityAdvisorPanel-C_ETsPih.js → packem_chunks/SecurityAdvisorPanel.js} +44 -31
- package/dist/packem_chunks/SettingsPanel.js +390 -0
- package/dist/{packem_shared/sql-editor-panel-BFRpzj6r.js → packem_chunks/SqlEditorPanel.js} +12 -252
- package/dist/{packem_shared/TableEditor-ChfUOZec.js → packem_chunks/TableEditor.js} +10 -68
- package/dist/packem_chunks/analytics-panel.js +261 -0
- package/dist/packem_chunks/auth-config-panel.js +179 -0
- package/dist/packem_chunks/auth-sessions-panel.js +175 -0
- package/dist/packem_chunks/dashboards-panel.js +779 -0
- package/dist/packem_chunks/fanout-panel.js +481 -0
- package/dist/packem_chunks/flags-panel.js +176 -0
- package/dist/packem_chunks/kv-browser.js +1896 -0
- package/dist/packem_chunks/log-drains-panel.js +273 -0
- package/dist/packem_chunks/organizations-panel.js +670 -0
- package/dist/packem_chunks/payments-panel.js +185 -0
- package/dist/packem_chunks/permissions-panel.js +804 -0
- package/dist/packem_chunks/queues-panel.js +147 -0
- package/dist/packem_chunks/rls-panel.js +313 -0
- package/dist/packem_chunks/schedule-panel.js +831 -0
- package/dist/packem_chunks/sparkline.js +79 -0
- package/dist/packem_chunks/storage-rules-panel.js +138 -0
- package/dist/packem_chunks/subscriptions-panel.js +236 -0
- package/dist/packem_chunks/users-panel.js +1265 -0
- package/dist/packem_chunks/vector-browser.js +281 -0
- package/dist/packem_chunks/workflows-panel.js +562 -0
- package/dist/packem_shared/{ADMIN_FUNCTIONS-DmBqMZ-z.js → ADMIN_FUNCTIONS-CdaxLGkE.js} +3 -0
- package/dist/packem_shared/{ApiDocsPanel-C5-yJ1p7.js → ApiDocsPanel-B6u_wnz-.js} +2 -2
- package/dist/packem_shared/{ApiReferencePanel-1vubqG5s.js → ApiReferencePanel-Drz4UO0a.js} +2 -1
- package/dist/packem_shared/{CommandPalette-BtgkBzZI.js → CommandPalette-B5BertvU.js} +1 -1
- package/dist/packem_shared/{DataBrowser-CtBe1So9.js → DataBrowser-ANTHLWWh.js} +198 -247
- package/dist/packem_shared/{GlobalDataBrowser-BTEmGrph.js → GlobalDataBrowser-CjgTG_wa.js} +37 -66
- package/dist/packem_shared/HomePanel-c2FodE9t.js +14 -0
- package/dist/packem_shared/{OpenRpcReferencePanel-vbcYbv3V.js → OpenRpcReferencePanel-CspFdbUT.js} +2 -1
- package/dist/packem_shared/{ScheduledJobs-CabfKbyM.js → ScheduledJobs-BEJXtsBn.js} +163 -60
- package/dist/packem_shared/Studio-CVTtA_sB.js +16 -0
- package/dist/packem_shared/{StudioApp-CHOZA-z-.js → StudioApp-BSYV2fz6.js} +277 -3
- package/dist/packem_shared/{advisor-view-CGcfMiPq.js → advisor-view-DzqyvUU3.js} +1 -1
- package/dist/packem_shared/{app.d-CCmwDEVs.d.ts → app.d-B6MyY_al.d.ts} +1 -1
- package/dist/packem_shared/{bar-chart-CzJAgqkp.js → bar-chart-Bb__F5-u.js} +1 -1
- package/dist/packem_shared/browser-storage-d03UsV7v.js +249 -0
- package/dist/packem_shared/{cf-links-2cktDedA.js → cf-links-BZfRdxSE.js} +1 -1
- package/dist/packem_shared/{data-grid-B5CaV3wS.js → data-grid-Dsg6nRjo.js} +1 -1
- package/dist/packem_shared/data-view-params-Cd6yRVbv.js +96 -0
- package/dist/packem_shared/{grid-features-CzUfqgsM.js → grid-features-D7nNzBYm.js} +4 -99
- package/dist/packem_shared/{HomePanel-Cw16stjq.js → home-panel-aOR_drVv.js} +833 -469
- package/dist/packem_shared/{internal-rXJEAhXS.js → internal-FcNZ3beb.js} +1 -1
- package/dist/packem_shared/modal-shell-hyaJvIJ6.js +100 -0
- package/dist/packem_shared/{reference-view-B4E49Lip.js → reference-view-Doy1XlQq.js} +4 -44
- package/dist/packem_shared/select-UkNYCT3s.js +273 -0
- package/dist/packem_shared/skeleton-CGhL0p20.js +45 -0
- package/dist/packem_shared/{sparkline-10dG-_f0.js → sparkline-KgMPHS4u.js} +1 -1
- package/dist/packem_shared/studio-dMTJ-kRR.js +3987 -0
- package/dist/packem_shared/{table-_RzNvy3R.js → table-DsCa9Qp9.js} +1 -1
- package/dist/packem_shared/{table-list-sidebar-Bg7uzbvC.js → table-list-sidebar-VMo0ftxD.js} +1 -1
- package/dist/packem_shared/use-admin-query-BViPA3US.js +105 -0
- package/dist/packem_shared/use-auth-capabilities-BHkoBnbZ.js +32 -0
- package/dist/standalone/chunk-2DS7JLWL.js +13 -0
- package/dist/standalone/chunk-2K47A3P6.js +1 -0
- package/dist/standalone/chunk-2NGUNNGW.js +1 -0
- package/dist/standalone/chunk-2PDQ4KZ6.js +1 -0
- package/dist/standalone/chunk-3BP4BTLR.js +4 -0
- package/dist/standalone/chunk-3OA7PECS.js +6 -0
- package/dist/standalone/chunk-4QHKBC77.js +1 -0
- package/dist/standalone/chunk-57LYXHXH.js +1 -0
- package/dist/standalone/chunk-5NSZVXCS.js +1 -0
- package/dist/standalone/chunk-5OIBXYZM.js +1 -0
- package/dist/standalone/chunk-63XKJQTQ.js +1 -0
- package/dist/standalone/chunk-6RC6L33K.js +4 -0
- package/dist/standalone/chunk-6VTGE3WJ.js +1 -0
- package/dist/standalone/chunk-7PBZKXYA.js +1 -0
- package/dist/standalone/chunk-7POIIWC5.js +3 -0
- package/dist/standalone/chunk-7RYIQKZA.js +1 -0
- package/dist/standalone/chunk-7TJJXVSE.js +1 -0
- package/dist/standalone/chunk-AB6QGMBF.js +1 -0
- package/dist/standalone/chunk-AHILM3ZP.js +1 -0
- package/dist/standalone/chunk-AQGOX5DK.js +1 -0
- package/dist/standalone/chunk-ASLGNHAX.js +1 -0
- package/dist/standalone/chunk-BHTPZS7L.js +4 -0
- package/dist/standalone/chunk-BJGBHGK3.js +1 -0
- package/dist/standalone/chunk-D7HKX4DI.js +1 -0
- package/dist/standalone/chunk-DGWTR4G7.js +1 -0
- package/dist/standalone/chunk-DSX53PBM.js +1 -0
- package/dist/standalone/chunk-DV2MNASX.js +1 -0
- package/dist/standalone/chunk-DWDILV2E.js +1 -0
- package/dist/standalone/chunk-E7AVZZKO.js +1 -0
- package/dist/standalone/chunk-EGJX34WM.js +1 -0
- package/dist/standalone/chunk-FCR3HKFV.js +1 -0
- package/dist/standalone/chunk-FKO3HO6I.js +4 -0
- package/dist/standalone/chunk-FQKNJSRA.js +76 -0
- package/dist/standalone/chunk-G2TFEWEQ.js +4 -0
- package/dist/standalone/chunk-GABMIICA.js +1 -0
- package/dist/standalone/chunk-GTM65MVX.js +1 -0
- package/dist/standalone/chunk-GZXPPJVK.js +1 -0
- package/dist/standalone/chunk-HFBRE65A.js +1 -0
- package/dist/standalone/chunk-HFMQNUBC.js +1 -0
- package/dist/standalone/chunk-HG7Q5B3H.js +1 -0
- package/dist/standalone/chunk-HTQL7AXU.js +1 -0
- package/dist/standalone/chunk-HV7G6DFP.js +5 -0
- package/dist/standalone/chunk-ITLLHEVG.js +1 -0
- package/dist/standalone/chunk-J6J54MBP.js +1 -0
- package/dist/standalone/chunk-JSEXCW5Q.js +1 -0
- package/dist/standalone/chunk-KEGAWN6Y.js +1 -0
- package/dist/standalone/chunk-KG3QTFWE.js +1 -0
- package/dist/standalone/chunk-KGS7KM4A.js +2 -0
- package/dist/standalone/chunk-KODWGUAB.js +1 -0
- package/dist/standalone/chunk-KZ6INM5M.js +1 -0
- package/dist/standalone/chunk-MGFEVTRI.js +1 -0
- package/dist/standalone/chunk-N2QDG3MW.js +1 -0
- package/dist/standalone/chunk-N4JI6VQD.js +1 -0
- package/dist/standalone/chunk-NNISYDNI.js +1 -0
- package/dist/standalone/chunk-O4PXDNR3.js +1 -0
- package/dist/standalone/chunk-O77VNUFD.js +1 -0
- package/dist/standalone/chunk-OD2POGPJ.js +1 -0
- package/dist/standalone/chunk-OXCK3ZUG.js +1 -0
- package/dist/standalone/chunk-P7DSVO4U.js +1 -0
- package/dist/standalone/chunk-PKAM3N5C.js +1 -0
- package/dist/standalone/chunk-QGXGBHQO.js +1 -0
- package/dist/standalone/chunk-QHA3TAEJ.js +1 -0
- package/dist/standalone/chunk-QQWC62X7.js +1 -0
- package/dist/standalone/chunk-RMYA7NAH.js +1 -0
- package/dist/standalone/chunk-RRCPZMC2.js +22 -0
- package/dist/standalone/chunk-S53RUBW5.js +1 -0
- package/dist/standalone/chunk-SB4GT6PK.js +1 -0
- package/dist/standalone/chunk-SEU5V7I6.js +1 -0
- package/dist/standalone/chunk-SHIOUDOT.js +1 -0
- package/dist/standalone/chunk-SIDRSX7Y.js +1 -0
- package/dist/standalone/chunk-SVR644RF.js +1 -0
- package/dist/standalone/chunk-TAD43CG5.js +1 -0
- package/dist/standalone/chunk-TBMYIZIO.js +1 -0
- package/dist/standalone/chunk-TICVNLPM.js +1 -0
- package/dist/standalone/chunk-TQ36RWOP.js +1 -0
- package/dist/standalone/chunk-UGMRUEBU.js +1 -0
- package/dist/standalone/chunk-UII66UVF.js +1 -0
- package/dist/standalone/chunk-VJPQUBN6.js +8 -0
- package/dist/standalone/chunk-VLXV72QE.js +1 -0
- package/dist/standalone/chunk-VMJKJWG6.js +1 -0
- package/dist/standalone/chunk-VPDPN5RR.js +2 -0
- package/dist/standalone/chunk-VSEGZA3J.js +1 -0
- package/dist/standalone/chunk-VXBZQIGY.js +4 -0
- package/dist/standalone/chunk-W7PCVQTE.js +1 -0
- package/dist/standalone/chunk-XLILSHPE.js +1 -0
- package/dist/standalone/chunk-XURNGQSS.js +1 -0
- package/dist/standalone/chunk-YJGANMU7.js +18 -0
- package/dist/standalone/chunk-YQQJ4N6U.js +1 -0
- package/dist/standalone/chunk-ZH7UES4T.js +2 -0
- package/dist/standalone/chunk-ZPUO7FNI.js +1 -0
- package/dist/standalone/chunk-ZQCVDXDL.js +1 -0
- package/dist/standalone/studio.js +104 -246
- package/dist/styles.css +1 -1
- package/package.json +13 -12
- package/dist/packem_shared/SettingsPanel-C0uLRf5P.js +0 -176
- package/dist/packem_shared/SqlEditorPanel-CguV7otm.js +0 -13
- package/dist/packem_shared/Studio-DFWAlcuf.js +0 -33
- package/dist/packem_shared/studio-Bj8psK1c.js +0 -10303
- package/dist/packem_shared/use-live-admin-Dq6g3daN.js +0 -73
- package/dist/packem_shared/use-live-shard-seed-Cuk3dnH0.js +0 -76
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { c } from 'react/compiler-runtime';
|
|
2
2
|
import { useLunora } from '@lunora/react';
|
|
3
3
|
import { useNavigate } from '@tanstack/react-router';
|
|
4
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
5
|
-
import { ShardInput } from '
|
|
6
|
-
import { B as Button } from '
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
4
|
+
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
5
|
+
import { ShardInput } from '../packem_shared/ShardInput-gx_DZXXn.js';
|
|
6
|
+
import { B as Button } from '../packem_shared/button-BhsN2uZH.js';
|
|
7
|
+
import { u as useAdminQuery } from '../packem_shared/use-admin-query-BViPA3US.js';
|
|
8
|
+
import useDebounced from '../packem_shared/useDebounced-Dxncpg6z.js';
|
|
9
|
+
import { useT } from '../packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js';
|
|
10
|
+
import { ADMIN_FUNCTIONS } from '../packem_shared/ADMIN_FUNCTIONS-CdaxLGkE.js';
|
|
11
|
+
import { f as fireAndForget, c as callOptions, a as adminRef } from '../packem_shared/internal-FcNZ3beb.js';
|
|
12
|
+
import { r as recordShard } from '../packem_shared/shard-history-DyebH1R5.js';
|
|
13
|
+
import { a as advisoryRow, A as AdvisorView } from '../packem_shared/advisor-view-DzqyvUU3.js';
|
|
14
|
+
import { ConfirmButton } from '../packem_shared/ConfirmButton-C2eVi2Qv.js';
|
|
14
15
|
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
15
|
-
import { deriveInsights } from '
|
|
16
|
+
import { deriveInsights } from '../packem_shared/DEFAULT_INSIGHT_THRESHOLDS-DjF0h-gA.js';
|
|
16
17
|
import { runAdvisor, RUNTIME_LINTS } from '@lunora/advisor';
|
|
17
18
|
|
|
18
19
|
const hasIndexMetadata = (metadata) => {
|
|
@@ -185,9 +186,6 @@ const deriveRuntimeAdvisories = (inputs) => {
|
|
|
185
186
|
return visible.map((finding) => advisoryRow(finding));
|
|
186
187
|
};
|
|
187
188
|
|
|
188
|
-
const GET_ADVISORIES = adminRef(ADMIN_FUNCTIONS.getAdvisories);
|
|
189
|
-
const GET_FUNCTION_STATS = adminRef(ADMIN_FUNCTIONS.getFunctionStats);
|
|
190
|
-
const GET_METRICS = adminRef(ADMIN_FUNCTIONS.getMetrics);
|
|
191
189
|
const LIST_TABLES = adminRef(ADMIN_FUNCTIONS.listTables);
|
|
192
190
|
const LIST_TABLE_INDEXES = adminRef(ADMIN_FUNCTIONS.listTableIndexes);
|
|
193
191
|
const percent = (rate) => `${(rate * 100).toFixed(1)}%`;
|
|
@@ -286,46 +284,41 @@ const InsightsPanel = ({
|
|
|
286
284
|
const navigate = useNavigate();
|
|
287
285
|
const t = useT();
|
|
288
286
|
const [shardKey, setShardKey] = useState(initialShardKey ?? "");
|
|
289
|
-
const [metrics, setMetrics] = useState(null);
|
|
290
|
-
const [functions, setFunctions] = useState(null);
|
|
291
|
-
const [advisories, setAdvisories] = useState(null);
|
|
292
|
-
const [indexHits, setIndexHits] = useState(null);
|
|
293
287
|
const [declaredIndexes, setDeclaredIndexes] = useState(null);
|
|
294
288
|
const [shardTraffic, setShardTraffic] = useState(null);
|
|
295
|
-
const
|
|
289
|
+
const debouncedShard = useDebounced(shardKey.trim(), 400);
|
|
290
|
+
const latestEnumeratedShard = useRef("");
|
|
291
|
+
const metricsQuery = useAdminQuery(ADMIN_FUNCTIONS.getMetrics, {}, {
|
|
292
|
+
live: true,
|
|
293
|
+
shardKey: debouncedShard
|
|
294
|
+
});
|
|
295
|
+
const functionsQuery = useAdminQuery(ADMIN_FUNCTIONS.getFunctionStats, {}, {
|
|
296
|
+
live: true,
|
|
297
|
+
shardKey: debouncedShard
|
|
298
|
+
});
|
|
299
|
+
const advisoriesQuery = useAdminQuery(ADMIN_FUNCTIONS.getAdvisories, {}, {
|
|
300
|
+
live: true,
|
|
301
|
+
shardKey: debouncedShard
|
|
302
|
+
});
|
|
303
|
+
const metrics = metricsQuery.data ?? null;
|
|
304
|
+
const functions = functionsQuery.data?.functions ?? null;
|
|
305
|
+
const advisories = advisoriesQuery.data?.advisories ?? null;
|
|
306
|
+
const indexHits = metricsQuery.data?.indexHits ?? null;
|
|
307
|
+
const error = metricsQuery.error !== null && functionsQuery.error !== null ? metricsQuery.error : null;
|
|
296
308
|
const fanShardTraffic = loadShardTraffic ?? ((table) => client.shardTraffic(table));
|
|
297
|
-
const
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
setError(null);
|
|
303
|
-
recordShard(shard);
|
|
304
|
-
}
|
|
305
|
-
setMetrics(snapshot.status === "fulfilled" ? snapshot.value : null);
|
|
306
|
-
setFunctions(stats.status === "fulfilled" ? stats.value.functions : null);
|
|
307
|
-
setAdvisories(advisorySnapshot.status === "fulfilled" ? advisorySnapshot.value.advisories : null);
|
|
308
|
-
setIndexHits(snapshot.status === "fulfilled" ? snapshot.value.indexHits ?? null : null);
|
|
309
|
-
let tableNames = [];
|
|
310
|
-
try {
|
|
311
|
-
const tables = await client.query(LIST_TABLES, {}, callOptions(shard));
|
|
312
|
-
tableNames = tables.map((table_0) => table_0.name);
|
|
313
|
-
const indexResults = await Promise.allSettled(tables.map(async (table_1) => [table_1.name, await client.query(LIST_TABLE_INDEXES, {
|
|
314
|
-
table: table_1.name
|
|
315
|
-
}, callOptions(shard))]));
|
|
316
|
-
const declared = [];
|
|
317
|
-
for (const result of indexResults) {
|
|
318
|
-
if (result.status === "fulfilled") {
|
|
319
|
-
const [name, payload] = result.value;
|
|
320
|
-
declared.push(...declaredIndexesFor(name, payload.indexes));
|
|
321
|
-
}
|
|
309
|
+
const loadShardTrafficFeed = async (tableNames, shard) => {
|
|
310
|
+
const seedTable = tableNames[0];
|
|
311
|
+
if (seedTable === void 0 || seedTable === "") {
|
|
312
|
+
if (latestEnumeratedShard.current === shard) {
|
|
313
|
+
setShardTraffic(null);
|
|
322
314
|
}
|
|
323
|
-
|
|
324
|
-
} catch {
|
|
325
|
-
setDeclaredIndexes(null);
|
|
315
|
+
return;
|
|
326
316
|
}
|
|
327
317
|
try {
|
|
328
|
-
const traffic = await fanShardTraffic(
|
|
318
|
+
const traffic = await fanShardTraffic(seedTable);
|
|
319
|
+
if (latestEnumeratedShard.current !== shard) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
329
322
|
const byShard = /* @__PURE__ */ new Map();
|
|
330
323
|
for (const entry of traffic.shards) {
|
|
331
324
|
if (!byShard.has(entry.shardKey)) {
|
|
@@ -337,31 +330,76 @@ const InsightsPanel = ({
|
|
|
337
330
|
}
|
|
338
331
|
setShardTraffic([...byShard.values()]);
|
|
339
332
|
} catch {
|
|
340
|
-
|
|
333
|
+
if (latestEnumeratedShard.current === shard) {
|
|
334
|
+
setShardTraffic(null);
|
|
335
|
+
}
|
|
341
336
|
}
|
|
342
337
|
};
|
|
343
|
-
|
|
338
|
+
const enumerateShard = useCallback(
|
|
339
|
+
async (shard) => {
|
|
340
|
+
latestEnumeratedShard.current = shard;
|
|
341
|
+
let tableNames = [];
|
|
342
|
+
try {
|
|
343
|
+
const tables = await client.query(LIST_TABLES, {}, callOptions(shard));
|
|
344
|
+
if (latestEnumeratedShard.current !== shard) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
recordShard(shard);
|
|
348
|
+
tableNames = tables.map((table) => table.name);
|
|
349
|
+
const indexResults = await Promise.allSettled(tables.map(async (table) => [table.name, await client.query(LIST_TABLE_INDEXES, {
|
|
350
|
+
table: table.name
|
|
351
|
+
}, callOptions(shard))]));
|
|
352
|
+
if (latestEnumeratedShard.current !== shard) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const declared = [];
|
|
356
|
+
for (const result of indexResults) {
|
|
357
|
+
if (result.status === "fulfilled") {
|
|
358
|
+
const [name, payload] = result.value;
|
|
359
|
+
declared.push(...declaredIndexesFor(name, payload.indexes));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
setDeclaredIndexes(declared);
|
|
363
|
+
} catch {
|
|
364
|
+
if (latestEnumeratedShard.current === shard) {
|
|
365
|
+
setDeclaredIndexes(null);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
await loadShardTrafficFeed(tableNames, shard);
|
|
369
|
+
},
|
|
370
|
+
// `fanShardTraffic`/`loadShardTrafficFeed` are render-fresh closures; the
|
|
371
|
+
// enumeration only needs to re-run on a shard change (or a manual visibility
|
|
372
|
+
// refresh), so they're intentionally excluded from the cache key.
|
|
373
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
374
|
+
[client]
|
|
375
|
+
);
|
|
376
|
+
useEffect(() => {
|
|
377
|
+
fireAndForget(enumerateShard(debouncedShard));
|
|
378
|
+
}, [debouncedShard, enumerateShard]);
|
|
344
379
|
useEffect(() => {
|
|
345
380
|
const onVisible = () => {
|
|
346
381
|
if (document.visibilityState === "visible") {
|
|
347
|
-
|
|
382
|
+
metricsQuery.refetch();
|
|
383
|
+
functionsQuery.refetch();
|
|
384
|
+
advisoriesQuery.refetch();
|
|
385
|
+
fireAndForget(enumerateShard(debouncedShard));
|
|
348
386
|
}
|
|
349
387
|
};
|
|
350
388
|
document.addEventListener("visibilitychange", onVisible);
|
|
351
389
|
return () => {
|
|
352
390
|
document.removeEventListener("visibilitychange", onVisible);
|
|
353
391
|
};
|
|
354
|
-
}, [
|
|
355
|
-
const jumpToSchemaIndex = (
|
|
392
|
+
}, [advisoriesQuery, debouncedShard, enumerateShard, functionsQuery, metricsQuery]);
|
|
393
|
+
const jumpToSchemaIndex = useCallback((table) => {
|
|
356
394
|
fireAndForget(navigate({
|
|
357
395
|
search: {
|
|
358
|
-
table
|
|
396
|
+
table
|
|
359
397
|
},
|
|
360
398
|
to: "/schema"
|
|
361
399
|
}));
|
|
362
|
-
};
|
|
400
|
+
}, [navigate]);
|
|
363
401
|
const insights = deriveInsights(metrics, functions);
|
|
364
|
-
const missingIndexTables = new Set(insights.filter((insight) => insight.kind === "missing-index").flatMap((
|
|
402
|
+
const missingIndexTables = new Set(insights.filter((insight) => insight.kind === "missing-index").flatMap((insight) => insight.tables ?? []));
|
|
365
403
|
const runtimeRows = deriveRuntimeAdvisories({
|
|
366
404
|
declaredIndexes: declaredIndexes ?? [],
|
|
367
405
|
functions,
|
|
@@ -370,18 +408,18 @@ const InsightsPanel = ({
|
|
|
370
408
|
suppressHotScanTables: missingIndexTables
|
|
371
409
|
});
|
|
372
410
|
const rows = useMemo(() => {
|
|
373
|
-
const insightRows = insights.map((
|
|
374
|
-
const
|
|
411
|
+
const insightRows = insights.map((insight) => {
|
|
412
|
+
const tables = insight.kind === "missing-index" ? insight.tables ?? [] : [];
|
|
375
413
|
return {
|
|
376
|
-
action:
|
|
414
|
+
action: tables.length > 0 ? tables.map((table) => /* @__PURE__ */ jsxDEV(AddIndexButton, {
|
|
377
415
|
onJump: jumpToSchemaIndex,
|
|
378
|
-
table
|
|
379
|
-
},
|
|
380
|
-
description:
|
|
381
|
-
entity:
|
|
382
|
-
issueType: insightTitle(t,
|
|
383
|
-
key: `${
|
|
384
|
-
level:
|
|
416
|
+
table
|
|
417
|
+
}, table, false)) : void 0,
|
|
418
|
+
description: insight.message === void 0 ? insightDetail(t, insight) : `${insightDetail(t, insight)} — ${insight.message}`,
|
|
419
|
+
entity: insight.fn,
|
|
420
|
+
issueType: insightTitle(t, insight),
|
|
421
|
+
key: `${insight.kind}:${insight.fn ?? ""}`,
|
|
422
|
+
level: insight.severity
|
|
385
423
|
};
|
|
386
424
|
});
|
|
387
425
|
const indexAdvisoryLints = /* @__PURE__ */ new Set(["unindexed_foreign_key", "unindexed_relation_target"]);
|
|
@@ -389,16 +427,16 @@ const InsightsPanel = ({
|
|
|
389
427
|
const base = advisoryRow(finding);
|
|
390
428
|
if (indexAdvisoryLints.has(finding.name) && hasIndexMetadata(finding.metadata)) {
|
|
391
429
|
const {
|
|
392
|
-
table
|
|
430
|
+
table,
|
|
393
431
|
suggestedIndex
|
|
394
432
|
} = finding.metadata;
|
|
395
|
-
const testId = `in-apply-index-${
|
|
433
|
+
const testId = `in-apply-index-${table}-${suggestedIndex.name}`;
|
|
396
434
|
return {
|
|
397
435
|
...base,
|
|
398
436
|
action: /* @__PURE__ */ jsxDEV(ApplyIndexButton, {
|
|
399
437
|
fields: suggestedIndex.fields,
|
|
400
438
|
indexName: suggestedIndex.name,
|
|
401
|
-
table
|
|
439
|
+
table,
|
|
402
440
|
testId
|
|
403
441
|
}, void 0, false)
|
|
404
442
|
};
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { c } from 'react/compiler-runtime';
|
|
2
|
-
import { useLunora } from '@lunora/react';
|
|
3
2
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
4
|
-
import { useState, useMemo, useRef } from 'react';
|
|
5
|
-
import { L as LiveError } from '
|
|
6
|
-
import { ShardInput } from '
|
|
7
|
-
import { B as Badge } from '
|
|
8
|
-
import { E as EmptyState } from '
|
|
9
|
-
import { I as Input } from '
|
|
10
|
-
import { u as
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { r as recordShard } from '
|
|
16
|
-
import { c as cn } from '
|
|
17
|
-
import { f as flooredRectObserver } from '
|
|
18
|
-
import { u as useLiveShardSeed } from './use-live-shard-seed-Cuk3dnH0.js';
|
|
3
|
+
import { useState, useEffect, useMemo, useRef } from 'react';
|
|
4
|
+
import { L as LiveError } from '../packem_shared/live-status-FZ0psC1z.js';
|
|
5
|
+
import { ShardInput } from '../packem_shared/ShardInput-gx_DZXXn.js';
|
|
6
|
+
import { B as Badge } from '../packem_shared/badge-B2PKA1-5.js';
|
|
7
|
+
import { E as EmptyState } from '../packem_shared/empty-state-DY_oe0k6.js';
|
|
8
|
+
import { I as Input } from '../packem_shared/input-XH4r1Pt1.js';
|
|
9
|
+
import { u as useAdminQuery } from '../packem_shared/use-admin-query-BViPA3US.js';
|
|
10
|
+
import useDebounced from '../packem_shared/useDebounced-Dxncpg6z.js';
|
|
11
|
+
import { useT } from '../packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js';
|
|
12
|
+
import { ADMIN_FUNCTIONS } from '../packem_shared/ADMIN_FUNCTIONS-CdaxLGkE.js';
|
|
13
|
+
import { a as CLOUDFLARE_OBSERVABILITY_URL } from '../packem_shared/cf-links-BZfRdxSE.js';
|
|
14
|
+
import { r as recordShard } from '../packem_shared/shard-history-DyebH1R5.js';
|
|
15
|
+
import { c as cn } from '../packem_shared/utils-B05Dmz_H.js';
|
|
16
|
+
import { f as flooredRectObserver } from '../packem_shared/virtual-rect-CVMUskSm.js';
|
|
19
17
|
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
20
18
|
|
|
21
19
|
const SCROLL_HEIGHT = 400;
|
|
@@ -316,8 +314,6 @@ const RequestRow = (t0) => {
|
|
|
316
314
|
}
|
|
317
315
|
return t17;
|
|
318
316
|
};
|
|
319
|
-
const GET_LOGS = adminRef(ADMIN_FUNCTIONS.getLogs);
|
|
320
|
-
const GET_REQUEST_LOG = adminRef(ADMIN_FUNCTIONS.getRequestLog);
|
|
321
317
|
const entriesOf = (result) => {
|
|
322
318
|
const {
|
|
323
319
|
entries
|
|
@@ -488,13 +484,9 @@ const SummaryBucketRow = (t0) => {
|
|
|
488
484
|
const LogsPanel = ({
|
|
489
485
|
initialShardKey
|
|
490
486
|
}) => {
|
|
491
|
-
const client = useLunora();
|
|
492
487
|
const t = useT();
|
|
493
488
|
const [view, setView] = useState("requests");
|
|
494
489
|
const [shardKey, setShardKey] = useState(initialShardKey ?? "");
|
|
495
|
-
const [entries, setEntries] = useState([]);
|
|
496
|
-
const [requests, setRequests] = useState([]);
|
|
497
|
-
const [error, setError] = useState(null);
|
|
498
490
|
const [search, setSearch] = useState("");
|
|
499
491
|
const [levelFilter, setLevelFilter] = useState(() => /* @__PURE__ */ new Set());
|
|
500
492
|
const [pathFilter, setPathFilter] = useState("");
|
|
@@ -504,43 +496,36 @@ const LogsPanel = ({
|
|
|
504
496
|
const [userIdFilter, setUserIdFilter] = useState("");
|
|
505
497
|
const [tableFilter, setTableFilter] = useState("");
|
|
506
498
|
const [outcomeFilter, setOutcomeFilter] = useState("all");
|
|
507
|
-
const
|
|
499
|
+
const debouncedShard = useDebounced(shardKey.trim(), 400);
|
|
508
500
|
const requestQuery = buildRequestQuery({
|
|
509
501
|
functionPathPrefix: pathPrefix,
|
|
510
502
|
outcome: outcomeFilter,
|
|
511
503
|
tableTouched: tableFilter,
|
|
512
504
|
userId: userIdFilter
|
|
513
505
|
});
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
506
|
+
const requestsQuery = useAdminQuery(ADMIN_FUNCTIONS.getRequestLog, requestQuery, {
|
|
507
|
+
enabled: view === "requests",
|
|
508
|
+
live: true,
|
|
509
|
+
shardKey: debouncedShard
|
|
510
|
+
});
|
|
511
|
+
const errorsQuery = useAdminQuery(ADMIN_FUNCTIONS.getLogs, {}, {
|
|
512
|
+
enabled: view === "errors",
|
|
513
|
+
live: true,
|
|
514
|
+
shardKey: debouncedShard
|
|
515
|
+
});
|
|
516
|
+
const activeQuery = view === "requests" ? requestsQuery : errorsQuery;
|
|
517
|
+
const {
|
|
518
|
+
error,
|
|
519
|
+
isLoading: activeLoading,
|
|
520
|
+
liveError
|
|
521
|
+
} = activeQuery;
|
|
522
|
+
const entries = entriesOf(errorsQuery.data);
|
|
523
|
+
const requests = entriesOf(requestsQuery.data);
|
|
524
|
+
useEffect(() => {
|
|
525
|
+
if (activeQuery.data !== void 0) {
|
|
526
|
+
recordShard(debouncedShard);
|
|
531
527
|
}
|
|
532
|
-
};
|
|
533
|
-
const committedShard = useLiveShardSeed(shardKey, refresh, [view, requestQuery]);
|
|
534
|
-
useLiveAdmin(ADMIN_FUNCTIONS.getRequestLog, requestQuery, committedShard ?? "", (result_1) => {
|
|
535
|
-
setError(null);
|
|
536
|
-
setLiveError(void 0);
|
|
537
|
-
setRequests(entriesOf(result_1));
|
|
538
|
-
}, view === "requests" && committedShard !== void 0, setLiveError);
|
|
539
|
-
useLiveAdmin(ADMIN_FUNCTIONS.getLogs, {}, committedShard ?? "", (result_2) => {
|
|
540
|
-
setError(null);
|
|
541
|
-
setLiveError(void 0);
|
|
542
|
-
setEntries(entriesOf(result_2));
|
|
543
|
-
}, view === "errors" && committedShard !== void 0, setLiveError);
|
|
528
|
+
}, [activeQuery.data, debouncedShard]);
|
|
544
529
|
const filtered = filterLogs(entries, {
|
|
545
530
|
levels: levelFilter,
|
|
546
531
|
now: Date.now(),
|
|
@@ -556,10 +541,13 @@ const LogsPanel = ({
|
|
|
556
541
|
return "error";
|
|
557
542
|
}
|
|
558
543
|
if (activeCount === 0) {
|
|
544
|
+
if (activeLoading) {
|
|
545
|
+
return summaryVisible ? "summary" : "list";
|
|
546
|
+
}
|
|
559
547
|
return "empty";
|
|
560
548
|
}
|
|
561
549
|
return summaryVisible ? "summary" : "list";
|
|
562
|
-
}, [activeCount, error, summaryVisible]);
|
|
550
|
+
}, [activeCount, activeLoading, error, summaryVisible]);
|
|
563
551
|
const scrollRef = useRef(null);
|
|
564
552
|
const virtualizer = useVirtualizer({
|
|
565
553
|
count: activeCount,
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useLunora } from '@lunora/react';
|
|
3
|
-
import { useState,
|
|
4
|
-
import { B as Badge } from '
|
|
5
|
-
import { B as Button } from '
|
|
6
|
-
import { E as EmptyState } from '
|
|
7
|
-
import { I as Input } from '
|
|
3
|
+
import { useState, useMemo } from 'react';
|
|
4
|
+
import { B as Badge } from '../packem_shared/badge-B2PKA1-5.js';
|
|
5
|
+
import { B as Button } from '../packem_shared/button-BhsN2uZH.js';
|
|
6
|
+
import { E as EmptyState } from '../packem_shared/empty-state-DY_oe0k6.js';
|
|
7
|
+
import { I as Input } from '../packem_shared/input-XH4r1Pt1.js';
|
|
8
8
|
import { c } from 'react/compiler-runtime';
|
|
9
9
|
import { ScrollArea as ScrollArea$1 } from '@base-ui/react/scroll-area';
|
|
10
|
-
import { c as cn } from '
|
|
10
|
+
import { c as cn } from '../packem_shared/utils-B05Dmz_H.js';
|
|
11
11
|
import { jsxDEV, Fragment } from 'react/jsx-dev-runtime';
|
|
12
12
|
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
13
|
+
import { u as useAdminQuery } from '../packem_shared/use-admin-query-BViPA3US.js';
|
|
14
|
+
import { useAutoRefresh } from '../packem_shared/DEFAULT_AUTO_REFRESH_MS-Vxwaxx51.js';
|
|
15
|
+
import { useT } from '../packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js';
|
|
16
|
+
import { ADMIN_FUNCTIONS } from '../packem_shared/ADMIN_FUNCTIONS-CdaxLGkE.js';
|
|
17
|
+
import { g as formatTimestamp, f as fireAndForget, b as copyToClipboard, c as callOptions, e as errorMessage, a as adminRef } from '../packem_shared/internal-FcNZ3beb.js';
|
|
17
18
|
|
|
18
19
|
function Separator({
|
|
19
20
|
className,
|
|
@@ -114,7 +115,6 @@ function ScrollBar({
|
|
|
114
115
|
}, void 0, false);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
const GET_CAPTURED_MAIL = adminRef(ADMIN_FUNCTIONS.getCapturedMail);
|
|
118
118
|
const CLEAR_CAPTURED_MAIL = adminRef(ADMIN_FUNCTIONS.clearCapturedMail);
|
|
119
119
|
const SEND_TEST_MAIL = adminRef(ADMIN_FUNCTIONS.sendTestMail);
|
|
120
120
|
const LINK_PATTERN = /https?:\/\/[^\s"'<>)]+/i;
|
|
@@ -144,49 +144,42 @@ const MailPanel = ({
|
|
|
144
144
|
}) => {
|
|
145
145
|
const client = useLunora();
|
|
146
146
|
const t = useT();
|
|
147
|
-
const
|
|
148
|
-
|
|
147
|
+
const {
|
|
148
|
+
data,
|
|
149
|
+
error: readError,
|
|
150
|
+
isLoading,
|
|
151
|
+
refetch
|
|
152
|
+
} = useAdminQuery(ADMIN_FUNCTIONS.getCapturedMail, {
|
|
153
|
+
limit
|
|
154
|
+
});
|
|
155
|
+
const [actionError, setActionError] = useState(null);
|
|
149
156
|
const [selectedId, setSelectedId] = useState(null);
|
|
150
157
|
const [tab, setTab] = useState("html");
|
|
151
158
|
const [filter, setFilter] = useState("");
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
const next = await client.query(GET_CAPTURED_MAIL, {
|
|
156
|
-
limit
|
|
157
|
-
}, callOptions(""));
|
|
158
|
-
setEntries(next.entries);
|
|
159
|
-
} catch (error_) {
|
|
160
|
-
setEntries([]);
|
|
161
|
-
setError(errorMessage(error_));
|
|
162
|
-
}
|
|
163
|
-
};
|
|
159
|
+
const entries = useMemo(() => data?.entries ?? [], [data]);
|
|
160
|
+
const error = readError ?? actionError;
|
|
164
161
|
const clearInbox = async () => {
|
|
165
|
-
|
|
162
|
+
setActionError(null);
|
|
166
163
|
try {
|
|
167
164
|
await client.query(CLEAR_CAPTURED_MAIL, {}, callOptions(""));
|
|
168
165
|
setSelectedId(null);
|
|
169
|
-
|
|
170
|
-
} catch (
|
|
171
|
-
|
|
166
|
+
refetch();
|
|
167
|
+
} catch (error_) {
|
|
168
|
+
setActionError(errorMessage(error_));
|
|
172
169
|
}
|
|
173
170
|
};
|
|
174
171
|
const sendTest = async () => {
|
|
175
|
-
|
|
172
|
+
setActionError(null);
|
|
176
173
|
try {
|
|
177
174
|
await client.query(SEND_TEST_MAIL, {}, callOptions(""));
|
|
178
|
-
|
|
179
|
-
} catch (
|
|
180
|
-
|
|
175
|
+
refetch();
|
|
176
|
+
} catch (error__0) {
|
|
177
|
+
setActionError(errorMessage(error__0));
|
|
181
178
|
}
|
|
182
179
|
};
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
},
|
|
186
|
-
const reload = () => {
|
|
187
|
-
fireAndForget(refresh());
|
|
188
|
-
};
|
|
189
|
-
useAutoRefresh(reload, true);
|
|
180
|
+
useAutoRefresh(() => {
|
|
181
|
+
refetch();
|
|
182
|
+
}, true);
|
|
190
183
|
const onClear = () => {
|
|
191
184
|
fireAndForget(clearInbox());
|
|
192
185
|
};
|
|
@@ -205,9 +198,9 @@ const MailPanel = ({
|
|
|
205
198
|
}
|
|
206
199
|
};
|
|
207
200
|
const onSelectTab = (event_1) => {
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
210
|
-
setTab(
|
|
201
|
+
const next = event_1.currentTarget.dataset["tab"];
|
|
202
|
+
if (next === "headers" || next === "html" || next === "text") {
|
|
203
|
+
setTab(next);
|
|
211
204
|
}
|
|
212
205
|
};
|
|
213
206
|
const tabTitle = (value) => {
|
|
@@ -276,7 +269,7 @@ const MailPanel = ({
|
|
|
276
269
|
"data-testid": "mail-error",
|
|
277
270
|
role: "alert",
|
|
278
271
|
children: error
|
|
279
|
-
}, void 0, false), error === null && entries.length === 0 && /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
272
|
+
}, void 0, false), error === null && !isLoading && entries.length === 0 && /* @__PURE__ */ jsxDEV(EmptyState, {
|
|
280
273
|
description: t("Email your app sends in dev is captured here — nothing is delivered."),
|
|
281
274
|
icon: /* @__PURE__ */ jsxDEV("svg", {
|
|
282
275
|
"aria-hidden": "true",
|