(function(global, factory) {
  typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("react"), require("@uiw/react-codemirror"), require("@codemirror/commands"), require("@codemirror/view"), require("@codemirror/lang-sql"), require("@electric-sql/pglite-react"), require("@codemirror/language"), require("psql-describe"), require("@uiw/codemirror-theme-github")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "react", "@uiw/react-codemirror", "@codemirror/commands", "@codemirror/view", "@codemirror/lang-sql", "@electric-sql/pglite-react", "@codemirror/language", "psql-describe", "@uiw/codemirror-theme-github"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.PGliteREPL = {}, global.jsxRuntime, global.react, global.CodeMirror, global.commands, global.view, global.langSql, global.pgliteReact, global.language, global.psqlDescribe, global.codemirrorThemeGithub));
})(this, function(exports2, jsxRuntime, react, CodeMirror, commands, view, langSql, pgliteReact, language, psqlDescribe, codemirrorThemeGithub) {
  "use strict";
  const describeCompletions = [
    {
      label: "\\d",
      type: "function",
      displayLabel: "\\d[S+] [ pattern ]",
      detail: "PSQL Describe"
    },
    {
      label: "\\da",
      type: "function",
      displayLabel: "\\da[S] [ pattern ]",
      detail: "Lists aggregate functions"
    },
    {
      label: "\\dA",
      type: "function",
      displayLabel: "\\dA[+] [ pattern ]",
      detail: "Lists access methods"
    },
    {
      label: "\\dAc",
      type: "function",
      displayLabel: "\\dAc[+] [access-method-pattern [input-type-pattern]]",
      detail: "Lists operator classes"
    },
    {
      label: "\\dAf",
      type: "function",
      displayLabel: "\\dAf[+] [access-method-pattern [input-type-pattern]]",
      detail: "Lists operator families"
    },
    {
      label: "\\dAo",
      type: "function",
      displayLabel: "\\dAo[+] [access-method-pattern [operator-family-pattern]]",
      detail: "Lists operators associated with operator families"
    },
    {
      label: "\\dAp",
      type: "function",
      displayLabel: "\\dAp[+] [access-method-pattern [operator-family-pattern]]",
      detail: "Lists support functions associated with operator families"
    },
    {
      label: "\\db",
      type: "function",
      displayLabel: "\\db[+] [ pattern ]",
      detail: "Lists tablespaces"
    },
    {
      label: "\\dc",
      type: "function",
      displayLabel: "\\dc[S+] [ pattern ]",
      detail: "Lists conversions between character-set encodings"
    },
    {
      label: "\\dconfig",
      type: "function",
      displayLabel: "\\dconfig[+] [ pattern ]",
      detail: "Lists server configuration parameters and their values"
    },
    {
      label: "\\dC",
      type: "function",
      displayLabel: "\\dC[+] [ pattern ]",
      detail: "Lists type casts"
    },
    {
      label: "\\dd",
      type: "function",
      displayLabel: "\\dd[S] [ pattern ]",
      detail: "Shows the descriptions of objects of type constraint, operator class, operator family, rule, and trigger"
    },
    {
      label: "\\dD",
      type: "function",
      displayLabel: "\\dD[S+] [ pattern ]",
      detail: "Lists domains"
    },
    {
      label: "\\ddp",
      type: "function",
      displayLabel: "\\ddp [ pattern ]",
      detail: "Lists default access privilege settings"
    },
    {
      label: "\\dE",
      type: "function",
      displayLabel: "\\dE[S+] [ pattern ]",
      detail: "Lists foreign tables"
    },
    {
      label: "\\di",
      type: "function",
      displayLabel: "\\di[S+] [ pattern ]",
      detail: "Lists indexes"
    },
    {
      label: "\\dm",
      type: "function",
      displayLabel: "\\dm[S+] [ pattern ]",
      detail: "Lists materialized views"
    },
    {
      label: "\\ds",
      type: "function",
      displayLabel: "\\ds[S+] [ pattern ]",
      detail: "Lists sequences"
    },
    {
      label: "\\dt",
      type: "function",
      displayLabel: "\\dt[S+] [ pattern ]",
      detail: "Lists tables"
    },
    {
      label: "\\dv",
      type: "function",
      displayLabel: "\\dv[S+] [ pattern ]",
      detail: "Lists views"
    },
    {
      label: "\\des",
      type: "function",
      displayLabel: "\\des[+] [ pattern ]",
      detail: "Lists foreign servers"
    },
    {
      label: "\\det",
      type: "function",
      displayLabel: "\\det[+] [ pattern ]",
      detail: "Lists foreign tables"
    },
    {
      label: "\\deu",
      type: "function",
      displayLabel: "\\deu[+] [ pattern ]",
      detail: "Lists user mappings"
    },
    {
      label: "\\dew",
      type: "function",
      displayLabel: "\\dew[+] [ pattern ]",
      detail: "Lists foreign-data wrappers"
    },
    {
      label: "\\df",
      type: "function",
      displayLabel: "\\df[anptwS+] [ pattern [ arg_pattern ... ] ]",
      detail: "Lists functions"
    },
    {
      label: "\\dF",
      type: "function",
      displayLabel: "\\dF[+] [ pattern ]",
      detail: "Lists text search configurations"
    },
    {
      label: "\\dFd",
      type: "function",
      displayLabel: "\\dFd[+] [ pattern ]",
      detail: "Lists text search dictionaries"
    },
    {
      label: "\\dFp",
      type: "function",
      displayLabel: "\\dFp[+] [ pattern ]",
      detail: "Lists text search parsers"
    },
    {
      label: "\\dFt",
      type: "function",
      displayLabel: "\\dFt[+] [ pattern ]",
      detail: "Lists text search templates"
    },
    {
      label: "\\dg",
      type: "function",
      displayLabel: "\\dg[S+] [ pattern ]",
      detail: "Lists database roles"
    },
    {
      label: "\\dl",
      type: "function",
      displayLabel: "\\dl[+] ",
      detail: "List large objects"
    },
    {
      label: "\\dL",
      type: "function",
      displayLabel: "\\dL[S+] [ pattern ]",
      detail: "Lists procedural languages"
    },
    {
      label: "\\dn",
      type: "function",
      displayLabel: "\\dn[S+] [ pattern ]",
      detail: "Lists schemas"
    },
    {
      label: "\\do",
      type: "function",
      displayLabel: "\\do[S+] [ pattern [ arg_pattern [ arg_pattern ] ] ]",
      detail: "Lists operators with their operand and result types"
    },
    {
      label: "\\dO",
      type: "function",
      displayLabel: "\\dO[S+] [ pattern ]",
      detail: "Lists collations"
    },
    {
      label: "\\dp",
      type: "function",
      displayLabel: "\\dp[S] [ pattern ]",
      detail: "Lists tables, views and sequences with their associated access privileges"
    },
    {
      label: "\\dP",
      type: "function",
      displayLabel: "\\dP[itn+] [ pattern ]",
      detail: "Lists partitioned relations"
    },
    {
      label: "\\drds",
      type: "function",
      displayLabel: "\\drds [ role-pattern [ database-pattern ] ]",
      detail: "Lists defined configuration settings"
    },
    {
      label: "\\drg",
      type: "function",
      displayLabel: "\\drg[S] [ pattern ]",
      detail: "Lists information about each granted role membership"
    },
    {
      label: "\\dRp",
      type: "function",
      displayLabel: "\\dRp[+] [ pattern ]",
      detail: "Lists replication publications"
    },
    {
      label: "\\dRs",
      type: "function",
      displayLabel: "\\dRs[+] [ pattern ]",
      detail: "Lists replication subscriptions"
    },
    {
      label: "\\dT",
      type: "function",
      displayLabel: "\\dT[S+] [ pattern ]",
      detail: "Lists data types"
    },
    {
      label: "\\du",
      type: "function",
      displayLabel: "\\du[S+] [ pattern ]",
      detail: "Lists database roles"
    },
    {
      label: "\\dx",
      type: "function",
      displayLabel: "\\dx[+] [ pattern ]",
      detail: "Lists installed extensions"
    },
    {
      label: "\\dX",
      type: "function",
      displayLabel: "\\dX [ pattern ]",
      detail: "Lists extended statistics"
    },
    {
      label: "\\dy",
      type: "function",
      displayLabel: "\\dy[+] [ pattern ]",
      detail: "Lists event triggers"
    }
  ];
  function describeCompletionsAutoComplete(context) {
    const word = context.matchBefore(/\\\w*/);
    if (!word || word.from === word.to) return null;
    return {
      from: word.from,
      options: describeCompletions
    };
  }
  function makeSqlExt(config = {}) {
    const lang = config.dialect || langSql.PostgreSQL;
    return new language.LanguageSupport(lang.language, [
      // schemaCompletion(config),
      config.schema ? lang.language.data.of({
        autocomplete: langSql.schemaCompletionSource(config)
      }) : [],
      // keywordCompletion(lang, !!config.upperCaseKeywords)
      lang.language.data.of({
        autocomplete: langSql.keywordCompletionSource(lang, !!config.upperCaseKeywords)
      }),
      lang.language.data.of({
        autocomplete: describeCompletionsAutoComplete
      })
    ]);
  }
  async function runQuery(query, pg) {
    if (query.trim().toLowerCase().startsWith("\\")) {
      return runDescribe(query, pg);
    }
    const start = performance.now();
    try {
      const result = await pg.exec(query, {
        rowMode: "array"
      });
      const elapsed = performance.now() - start;
      return {
        query,
        results: result,
        time: elapsed
      };
    } catch (err) {
      return {
        query,
        error: err.message,
        time: performance.now() - start
      };
    }
  }
  async function runDescribe(query, pg) {
    const start = performance.now();
    let out;
    let ret;
    const { promise, cancel: _cancel } = psqlDescribe.describe(
      query,
      "postgres",
      async (sql) => {
        ret = (await pg.exec(sql, { rowMode: "array" }))[0];
        return {
          rows: ret.rows,
          fields: ret.fields,
          rowCount: ret.rows.length
        };
      },
      (output) => {
        out = output;
      }
    );
    await promise;
    const elapsed = performance.now() - start;
    if (!out) {
      return {
        query,
        error: "No output",
        time: elapsed
      };
    } else if (typeof out === "string") {
      if (out.startsWith("ERROR:")) {
        return {
          query,
          error: out,
          time: elapsed
        };
      } else {
        return {
          query,
          text: out,
          time: elapsed
        };
      }
    } else {
      return {
        query,
        text: out.title,
        results: [ret],
        time: elapsed
      };
    }
  }
  async function getSchema(pg) {
    const ret = await pg.query(`
    SELECT 
      table_schema AS schema,
      table_name AS table,
      array_agg(column_name) AS columns
    FROM 
      information_schema.columns
    GROUP BY 
      table_schema, table_name
    ORDER BY 
      table_schema, table_name;
  `);
    const schema = {};
    for (const row of ret.rows) {
      schema[`${row.schema}.${row.table}`] = Array.isArray(row.columns) ? row.columns : row.columns.slice(1, -1).split(",");
    }
    return schema;
  }
  const tableRowIncrement = 100;
  const maxCellLength = 200;
  function cellClass(value) {
    if (value === null) {
      return "PGliteRepl-null";
    } else if (typeof value === "number") {
      return "PGliteRepl-number";
    } else if (typeof value === "boolean") {
      return "PGliteRepl-boolean";
    } else {
      return "";
    }
  }
  function cellValue(value) {
    let str;
    if (value === null) {
      str = "null";
    } else if (typeof value === "number") {
      str = value.toString();
    } else if (typeof value === "boolean") {
      str = value ? "true" : "false";
    } else if (value instanceof Date) {
      str = value.toISOString();
    } else if (Array.isArray(value)) {
      str = `[${value.map(cellValue).join(", ")}]`;
    } else if (typeof value === "object") {
      str = JSON.stringify(value);
    } else if (ArrayBuffer.isView(value)) {
      str = `${value.byteLength} bytes`;
    } else if (value === void 0) {
      str = "undefined";
    } else {
      str = value.toString();
    }
    return str.length > maxCellLength ? str.slice(0, maxCellLength) + "…" : str;
  }
  function ReplTable({ result }) {
    const [maxRows, setMaxRows] = react.useState(tableRowIncrement);
    const rows = result.rows.slice(0, maxRows);
    react.useEffect(() => {
      setMaxRows(tableRowIncrement);
    }, [result]);
    const showMore = () => {
      setMaxRows((prev) => prev + tableRowIncrement);
    };
    return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
      /* @__PURE__ */ jsxRuntime.jsx("div", { className: "PGliteRepl-table-scroll", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "PGliteRepl-table", children: [
        /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: result.fields.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { children: col.name }, col.name)) }) }),
        /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => (
          // eslint-disable-next-line @eslint-react/no-array-index-key
          /* @__PURE__ */ jsxRuntime.jsx("tr", { children: row.map((col, j) => (
            // eslint-disable-next-line @eslint-react/no-array-index-key
            /* @__PURE__ */ jsxRuntime.jsx("td", { className: cellClass(col), children: cellValue(col) }, j)
          )) }, i)
        )) })
      ] }) }),
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "PGliteRepl-table-row-count", children: [
        result.rows.length > maxRows ? `${maxRows} of ` : "",
        result.rows.length,
        " rows",
        " ",
        result.rows.length > maxRows && /* @__PURE__ */ jsxRuntime.jsx(
          "a",
          {
            href: "",
            onClick: (e) => {
              e.preventDefault();
              showMore();
            },
            children: "Show more"
          }
        )
      ] })
    ] });
  }
  function OutLine({ result }) {
    return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "PGliteRepl-line", children: result.fields.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ReplTable, { result }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "PGliteRepl-null", children: "null" }) });
  }
  function ReplResponse({
    response,
    showTime
  }) {
    var _a;
    let out;
    if (response.error) {
      out = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "PGliteRepl-line PGliteRepl-error", children: response.error });
    } else {
      out = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (_a = response.results) == null ? void 0 : _a.map((result, i) => (
        // eslint-disable-next-line @eslint-react/no-array-index-key
        /* @__PURE__ */ jsxRuntime.jsx(OutLine, { result }, i)
      )) });
    }
    return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
      /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "PGliteRepl-line PGliteRepl-query", children: response.query }),
      response.text && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "PGliteRepl-line PGliteRepl-text", children: response.text }),
      out,
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "PGliteRepl-divider", children: [
        /* @__PURE__ */ jsxRuntime.jsx("hr", {}),
        showTime && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "PGliteRepl-time", children: [
          response.time.toFixed(1),
          "ms"
        ] })
      ] })
    ] });
  }
  const baseKeymap = commands.defaultKeymap.filter((key) => key.key !== "Enter");
  const defaultLightThemeInit = codemirrorThemeGithub.githubLightInit;
  const defaultLightTheme = codemirrorThemeGithub.githubLight;
  const defaultDarkThemeInit = codemirrorThemeGithub.githubDarkInit;
  const defaultDarkTheme = codemirrorThemeGithub.githubDark;
  function Repl({
    pg: pgProp,
    border = false,
    lightTheme = defaultLightTheme,
    darkTheme = defaultDarkTheme,
    theme = "auto",
    showTime = false,
    disableUpdateSchema = false
  }) {
    const [value, setValue] = react.useState("");
    const valueNoHistory = react.useRef("");
    const [loading, setLoading] = react.useState(true);
    const [output, setOutput] = react.useState([]);
    const outputRef = react.useRef(null);
    const [schema, setSchema] = react.useState({});
    const historyPos = react.useRef(-1);
    const rcm = react.useRef(null);
    const [themeToUse, setThemeToUse] = react.useState(
      theme === "dark" ? darkTheme : lightTheme
    );
    const [styles, setStyles] = react.useState({});
    const pg = pgliteReact.usePGlite(pgProp);
    react.useEffect(() => {
      let ignore = false;
      const init = async () => {
        await pg.waitReady;
        if (ignore) return;
        setLoading(false);
      };
      setLoading(true);
      init();
      return () => {
        ignore = true;
      };
    }, [pg]);
    react.useEffect(() => {
      if (theme === "auto") {
        const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
        setThemeToUse(systemTheme === "dark" ? darkTheme : lightTheme);
        const listener = (e) => {
          setThemeToUse(e.matches ? darkTheme : lightTheme);
          setTimeout(() => {
            extractStyles();
          }, 0);
        };
        window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", listener);
        return () => {
          window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change", listener);
        };
      } else {
        setThemeToUse(theme === "dark" ? darkTheme : lightTheme);
        setTimeout(() => {
          extractStyles();
        }, 0);
        return;
      }
    }, [theme, lightTheme, darkTheme]);
    const onChange = react.useCallback((val, _viewUpdate) => {
      extractStyles();
      setValue(val);
      if (historyPos.current === -1) {
        valueNoHistory.current = val;
      }
    }, []);
    const extensions = react.useMemo(
      () => [
        view.keymap.of([
          {
            key: "Enter",
            preventDefault: true,
            run: () => {
              if (value.trim() === "") return false;
              runQuery(value, pg).then((response) => {
                setOutput((prev) => [...prev, response]);
                if (outputRef.current) {
                  setTimeout(() => {
                    outputRef.current.scrollTop = outputRef.current.scrollHeight;
                  }, 0);
                }
                if (!disableUpdateSchema) {
                  getSchema(pg).then(setSchema);
                }
              });
              historyPos.current = -1;
              valueNoHistory.current = "";
              setValue("");
              return true;
            }
          },
          {
            key: "ArrowUp",
            run: (view2) => {
              const state = view2.state;
              const cursorLine = state.doc.lineAt(
                state.selection.main.head
              ).number;
              if (cursorLine === 1) {
                const currentPos = historyPos.current;
                historyPos.current++;
                if (historyPos.current >= output.length) {
                  historyPos.current = output.length - 1;
                }
                if (historyPos.current < -1) {
                  historyPos.current = -1;
                }
                if (historyPos.current === currentPos) return true;
                if (historyPos.current === -1) {
                  setValue(valueNoHistory.current);
                } else {
                  setValue(output[output.length - historyPos.current - 1].query);
                }
                return true;
              }
              return false;
            }
          },
          {
            key: "ArrowDown",
            run: (view2) => {
              const state = view2.state;
              const cursorLine = state.doc.lineAt(
                state.selection.main.head
              ).number;
              const lastLine = state.doc.lines;
              if (cursorLine === lastLine) {
                const currentPos = historyPos.current;
                historyPos.current--;
                if (historyPos.current >= output.length) {
                  historyPos.current = output.length - 1;
                }
                if (historyPos.current < -1) {
                  historyPos.current = -1;
                }
                if (historyPos.current === currentPos) return true;
                if (historyPos.current === -1) {
                  setValue(valueNoHistory.current);
                } else {
                  setValue(output[output.length - historyPos.current - 1].query);
                }
                return true;
              }
              return false;
            }
          },
          ...baseKeymap
        ]),
        makeSqlExt({
          dialect: langSql.PostgreSQL,
          schema,
          tables: [
            {
              label: "d",
              displayLabel: "\\d"
            }
          ],
          defaultSchema: "public"
        })
      ],
      [pg, schema, value, output, disableUpdateSchema]
    );
    const extractStyles = () => {
      var _a, _b;
      const cmEditorEl = (_b = (_a = rcm.current) == null ? void 0 : _a.editor) == null ? void 0 : _b.querySelector(".cm-editor");
      if (!cmEditorEl) {
        throw new Error("No CodeMirror editor found");
      }
      const gutterEl = cmEditorEl.querySelector(".cm-gutters");
      const cmEditorElComputedStyles = window.getComputedStyle(cmEditorEl);
      const foregroundColor = cmEditorElComputedStyles.color;
      const backgroundColor = cmEditorElComputedStyles.backgroundColor;
      const gutterElComputedStyles = window.getComputedStyle(gutterEl);
      const gutterBorder = gutterElComputedStyles.borderRight;
      const borderWidth = parseInt(gutterElComputedStyles.borderRightWidth) || 0;
      const borderColor = borderWidth ? gutterElComputedStyles.borderRightColor : foregroundColor.replace("rgb", "rgba").replace(")", ", 0.15)");
      const border2 = borderWidth ? gutterElComputedStyles.borderRight : `1px solid ${borderColor}`;
      setStyles({
        "--PGliteRepl-foreground-color": foregroundColor,
        "--PGliteRepl-background-color": backgroundColor,
        "--PGliteRepl-border": border2,
        "--PGliteRepl-gutter-border": gutterBorder,
        "--PGliteRepl-border-color": borderColor
      });
    };
    return /* @__PURE__ */ jsxRuntime.jsxs(
      "div",
      {
        className: `
      PGliteRepl-root
      ${border ? "PGliteRepl-root-border" : ""}
    `,
        style: styles,
        children: [
          /* @__PURE__ */ jsxRuntime.jsxs(
            "div",
            {
              className: "PGliteRepl-output",
              ref: (ref) => outputRef.current = ref,
              children: [
                loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "PGliteRepl-loading-msg", children: "Loading..." }),
                output.map((response) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ReplResponse, { response: response || [], showTime }) }, `${response.query}-${response.time}`))
              ]
            }
          ),
          /* @__PURE__ */ jsxRuntime.jsx(
            CodeMirror,
            {
              ref: rcm,
              className: `PGliteRepl-input ${loading ? "PGliteRepl-input-loading" : ""}`,
              width: "100%",
              value,
              basicSetup: {
                defaultKeymap: false
              },
              extensions,
              theme: themeToUse,
              onChange,
              editable: !loading,
              onCreateEditor: () => {
                extractStyles();
                setTimeout(extractStyles, 0);
                getSchema(pg).then(setSchema);
              }
            }
          )
        ]
      }
    );
  }
  exports2.Repl = Repl;
  exports2.defaultDarkTheme = defaultDarkTheme;
  exports2.defaultDarkThemeInit = defaultDarkThemeInit;
  exports2.defaultLightTheme = defaultLightTheme;
  exports2.defaultLightThemeInit = defaultLightThemeInit;
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
});
//# sourceMappingURL=Repl.umd.cjs.map
