ui: Make stdlib docs available in the UI

This approach (possibly naively) just generates json docs for all files
in 'src/trace_processor/perfetto_sql/stdlib/**.sql', and makes it
available to be fetched.

Change-Id: I8071cc2cddb7f4c2ea895299b5e706e2694b2f8e
diff --git a/tools/gen_stdlib_docs_json.py b/tools/gen_stdlib_docs_json.py
index 8ae6044..56293f9 100755
--- a/tools/gen_stdlib_docs_json.py
+++ b/tools/gen_stdlib_docs_json.py
@@ -30,6 +30,7 @@
   parser = argparse.ArgumentParser()
   parser.add_argument('--json-out', required=True)
   parser.add_argument('--input-list-file')
+  parser.add_argument('--minify')
   parser.add_argument('sql_files', nargs='*')
   args = parser.parse_args()
 
@@ -142,8 +143,10 @@
     }
     modules[module_name].append(file_dict)
 
+  indent = None if args.minify else 4
+
   with open(args.json_out, 'w+') as f:
-    json.dump(modules, f, indent=4)
+    json.dump(modules, f, indent=indent)
 
   return 0
 
diff --git a/ui/build.js b/ui/build.js
index 96ac8a6..1079dff 100644
--- a/ui/build.js
+++ b/ui/build.js
@@ -256,6 +256,7 @@
     generateImports('ui/src/plugins', 'all_plugins.ts');
     compileProtos();
     genVersion();
+    generateStdlibDocs();
 
     const tsProjects = [
       'ui',
@@ -453,6 +454,25 @@
   addTask(exec, [cmd, args]);
 }
 
+function generateStdlibDocs() {
+  const cmd = pjoin(ROOT_DIR, 'tools/gen_stdlib_docs_json.py');
+  const stdlibDir = pjoin(ROOT_DIR, 'src/trace_processor/perfetto_sql/stdlib');
+
+  const stdlibFiles =
+    listFilesRecursive(stdlibDir)
+    .filter((filePath) => path.extname(filePath) === '.sql');
+
+  addTask(exec, [
+    cmd,
+    [
+      '--json-out',
+      pjoin(cfg.outDistDir, 'stdlib_docs.json'),
+      '--minify',
+      ...stdlibFiles,
+    ],
+  ]);
+}
+
 function updateSymlinks() {
   // /ui/out -> /out/ui.
   mklink(cfg.outUiDir, pjoin(ROOT_DIR, 'ui/out'));
@@ -823,6 +843,18 @@
   }
 }
 
+// Recursively build a list of files in a given directory and return a list of
+// file paths, similar to `find -type f`.
+function listFilesRecursive(dir) {
+  const fileList = [];
+
+  walk(dir, (filePath) => {
+    fileList.push(filePath);
+  });
+
+  return fileList;
+}
+
 function ensureDir(dirPath, clean) {
   const exists = fs.existsSync(dirPath);
   if (exists && clean) {
diff --git a/ui/src/frontend/stdlib_docs.ts b/ui/src/frontend/stdlib_docs.ts
new file mode 100644
index 0000000..c417519
--- /dev/null
+++ b/ui/src/frontend/stdlib_docs.ts
@@ -0,0 +1,22 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {AppImpl} from '../core/app_impl';
+
+// Fetch the std lib docs
+export async function getStdlibDocs(app: AppImpl): Promise<string> {
+  const resp = await fetch(`${app.rootUrl}/stdlib_docs.json`);
+  const json = await resp.json();
+  return JSON.parse(json);
+}