@gmickel/gno 0.33.4 → 0.34.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.
@@ -33,10 +33,7 @@ import {
33
33
  type CodeMirrorEditorRef,
34
34
  MarkdownPreview,
35
35
  } from "../components/editor";
36
- import {
37
- FrontmatterDisplay,
38
- parseFrontmatter,
39
- } from "../components/FrontmatterDisplay";
36
+ import { parseFrontmatter } from "../components/FrontmatterDisplay";
40
37
  import { Badge } from "../components/ui/badge";
41
38
  import { Button } from "../components/ui/button";
42
39
  import {
@@ -227,7 +224,6 @@ export default function DocumentEditor({ navigate }: PageProps) {
227
224
  const hasUnsavedChanges = content !== originalContent;
228
225
  const hasLocalSnapshot = historyEntries.length > 0;
229
226
  const parsedContent = useMemo(() => parseFrontmatter(content), [content]);
230
- const hasFrontmatter = Object.keys(parsedContent.data).length > 0;
231
227
 
232
228
  const refreshHistoryEntries = useCallback((docId: string) => {
233
229
  const next = loadLocalHistory(docId);
@@ -1090,12 +1086,6 @@ export default function DocumentEditor({ navigate }: PageProps) {
1090
1086
  ref={previewRef}
1091
1087
  >
1092
1088
  <div className="mx-auto max-w-3xl">
1093
- {hasFrontmatter && (
1094
- <FrontmatterDisplay
1095
- className="mb-4 rounded-lg border border-border/40 bg-muted/10 p-4"
1096
- content={content}
1097
- />
1098
- )}
1099
1089
  <MarkdownPreview content={parsedContent.body} />
1100
1090
  </div>
1101
1091
  </div>
@@ -298,8 +298,8 @@ export default function GraphView({ navigate }: PageProps) {
298
298
  if (includeSimilar) {
299
299
  params.set("includeSimilar", "true");
300
300
  }
301
- params.set("limit", "2000");
302
- params.set("edgeLimit", "10000");
301
+ params.set("limit", "600");
302
+ params.set("edgeLimit", "2200");
303
303
 
304
304
  const url = `/api/graph?${params.toString()}`;
305
305
  const { data, error: fetchError } = await apiFetch<GraphResponse>(url);
@@ -632,14 +632,14 @@ export default function GraphView({ navigate }: PageProps) {
632
632
  <Suspense fallback={<GraphLoading />}>
633
633
  <ForceGraph2D
634
634
  backgroundColor={COLORS.canvas}
635
- cooldownTicks={100}
635
+ cooldownTicks={45}
636
636
  graphData={forceGraphData}
637
637
  linkColor={(link: any) => link.color}
638
638
  linkCurvature={0.1}
639
639
  linkDirectionalParticleColor={() => COLORS.nodeDefault}
640
640
  linkDirectionalParticles={
641
641
  // Disable particles on large graphs for performance
642
- forceGraphData.links.length > 500 ? 0 : 1
642
+ forceGraphData.links.length > 250 ? 0 : 1
643
643
  }
644
644
  linkDirectionalParticleWidth={1.5}
645
645
  linkWidth={(link: any) =>
@@ -670,6 +670,7 @@ export default function GraphView({ navigate }: PageProps) {
670
670
  onZoom={(transform: { k: number }) => {
671
671
  pointerScaleRef.current = transform.k;
672
672
  }}
673
+ warmupTicks={20}
673
674
  ref={graphRef}
674
675
  />
675
676
  </Suspense>
@@ -50,6 +50,7 @@ import {
50
50
  import { searchHybrid } from "../../pipeline/hybrid";
51
51
  import { validateQueryModes } from "../../pipeline/query-modes";
52
52
  import { searchBm25 } from "../../pipeline/search";
53
+ import { buildBrowseTree, normalizeBrowsePath } from "../browse-tree";
53
54
  import { applyConfigChange, applyConfigChangeTyped } from "../config-sync";
54
55
  import { getConnectorStatuses, installConnector } from "../connectors";
55
56
  import {
@@ -780,6 +781,12 @@ export async function handleDocs(
780
781
  url: URL
781
782
  ): Promise<Response> {
782
783
  const collection = url.searchParams.get("collection") || undefined;
784
+ const pathPrefix = normalizeBrowsePath(url.searchParams.get("pathPrefix"));
785
+ const directChildrenOnlyParam = (
786
+ url.searchParams.get("directChildrenOnly") ?? ""
787
+ )
788
+ .trim()
789
+ .toLowerCase();
783
790
  const sortFieldRaw = (url.searchParams.get("sortField") ?? "modified")
784
791
  .trim()
785
792
  .toLowerCase();
@@ -818,6 +825,15 @@ export async function handleDocs(
818
825
  return errorResponse("VALIDATION", "sortOrder must be 'asc' or 'desc'");
819
826
  }
820
827
  const sortOrder: "asc" | "desc" = sortOrderRaw === "asc" ? "asc" : "desc";
828
+ const directChildrenOnly =
829
+ directChildrenOnlyParam === "1" || directChildrenOnlyParam === "true";
830
+
831
+ if (pathPrefix && !collection) {
832
+ return errorResponse(
833
+ "VALIDATION",
834
+ "pathPrefix requires a collection filter"
835
+ );
836
+ }
821
837
 
822
838
  // Parse tag filters
823
839
  let tagsAll: string[] | undefined;
@@ -867,6 +883,8 @@ export async function handleDocs(
867
883
  collection,
868
884
  limit,
869
885
  offset,
886
+ pathPrefix: pathPrefix || undefined,
887
+ directChildrenOnly,
870
888
  tagsAll,
871
889
  tagsAny,
872
890
  sortField: sortFieldRaw,
@@ -893,12 +911,41 @@ export async function handleDocs(
893
911
  total,
894
912
  limit,
895
913
  offset,
914
+ pathPrefix,
915
+ directChildrenOnly,
896
916
  availableDateFields,
897
917
  sortField: sortFieldRaw,
898
918
  sortOrder,
899
919
  });
900
920
  }
901
921
 
922
+ export async function handleBrowseTree(
923
+ store: SqliteAdapter
924
+ ): Promise<Response> {
925
+ const [collectionsResult, documentsResult] = await Promise.all([
926
+ store.getCollections(),
927
+ store.listActiveDocumentsForBrowse(),
928
+ ]);
929
+
930
+ if (!collectionsResult.ok) {
931
+ return errorResponse("RUNTIME", collectionsResult.error.message, 500);
932
+ }
933
+ if (!documentsResult.ok) {
934
+ return errorResponse("RUNTIME", documentsResult.error.message, 500);
935
+ }
936
+
937
+ const collections = buildBrowseTree(
938
+ collectionsResult.value,
939
+ documentsResult.value
940
+ );
941
+
942
+ return jsonResponse({
943
+ collections,
944
+ totalCollections: collections.length,
945
+ totalDocuments: documentsResult.value.length,
946
+ });
947
+ }
948
+
902
949
  /**
903
950
  * GET /api/docs/autocomplete
904
951
  * Query params: query, collection, limit
@@ -15,6 +15,7 @@ import homepage from "./public/index.html";
15
15
  import {
16
16
  handleActiveJob,
17
17
  handleAsk,
18
+ handleBrowseTree,
18
19
  handleCapabilities,
19
20
  handleCollections,
20
21
  handleConnectors,
@@ -256,6 +257,10 @@ export async function startServer(
256
257
  );
257
258
  },
258
259
  },
260
+ "/api/browse/tree": {
261
+ GET: async () =>
262
+ withSecurityHeaders(await handleBrowseTree(store), isDev),
263
+ },
259
264
  "/api/docs/:id/deactivate": {
260
265
  POST: async (req: Request) => {
261
266
  if (!isRequestAllowed(req, port)) {