forked from electric-sql/pglite
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'electric-sql:main' into main
- Loading branch information
Showing
22 changed files
with
1,477 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
module.exports = { | ||
root: true, | ||
env: { browser: true, es2020: true }, | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
'plugin:react-hooks/recommended', | ||
], | ||
ignorePatterns: ['dist', '.eslintrc.cjs'], | ||
parser: '@typescript-eslint/parser', | ||
plugins: ['react-refresh'], | ||
rules: { | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
dist-webcomponent | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# PGlite REPL React Component | ||
|
||
A REPL, or terminal, for use in the browser with PGlite, allowing you to have an interactive session with your WASM Postgres in the page. | ||
|
||
<img width="918" src="https://github.com/electric-sql/pglite/assets/31130/f7c9c2dd-4de8-4033-9905-9637ae998034"> | ||
|
||
## Features: | ||
|
||
- Available as both a React.js component and a Web Components | ||
- [CodeMirror](https://codemirror.net) for input editing | ||
- Auto complete, including table and column names from the database | ||
- Input history (up and down keys) | ||
- `\d` PSQL commands (via [psql-describe](https://www.npmjs.com/package/psql-describe)) | ||
|
||
## How to use with React | ||
|
||
``` | ||
npm install @electric-sql/pglite-repl | ||
``` | ||
|
||
then to include in a page: | ||
|
||
```tsx | ||
import { PGlite } from "@electric-sql/pglite"; | ||
import { Repl } from "@electric-sql/pglite-repl"; | ||
|
||
function MyComponent() { | ||
const pg = new PGlite(); | ||
|
||
return <> | ||
<Repl pg={pg} /> | ||
</> | ||
} | ||
``` | ||
|
||
The props for the `<Repl>` component are described by this interface: | ||
|
||
```ts | ||
// The theme to use, auto is auto switching based on the system | ||
type ReplTheme = "light" | "dark" | "auto"; | ||
|
||
interface ReplProps { | ||
pg: PGlite; // PGlite db instance | ||
border?: boolean; // Outer border on the component, defaults to false | ||
lightTheme?: Extension; | ||
darkTheme?: Extension; | ||
theme?: ReplTheme; // Defaults to "auto" | ||
} | ||
``` | ||
|
||
The `lightTheme` and `darkTheme` should be instances of a [React CodeMirror](https://uiwjs.github.io/react-codemirror/) theme. | ||
|
||
## How to use as a Web Component | ||
|
||
Although the PGlite REPL is built with React, its also available as a web component for easy inclusion in any page or other framework. | ||
|
||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/@electric-sql/pglite/dist-webcomponent/Repl.js" type="module"></script> | ||
|
||
<!-- Include the Repl web component in your page --> | ||
<pglite-repl id="repl"></pglite-repl> | ||
|
||
<script type="module"> | ||
import { PGlite } from "https://cdn.jsdelivr.net/npm/@electric-sql/pglite/dist/index.js"; | ||
// Create a PGlite instance | ||
const pg = new PGlite(); | ||
// Retrieve the Repl element | ||
const repl = document.getElementById('repl'); | ||
// REPL to your PGlite instance | ||
repl.pg = pg; | ||
</script> | ||
``` | ||
|
||
## Development | ||
|
||
Checkout this repo and from package dir: | ||
|
||
```sh | ||
# Install deps | ||
pnpm install | ||
|
||
# Run dev server | ||
pnpm dev | ||
# then open a browser to the url shown | ||
|
||
# Build the lib | ||
pnpm build | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>PGlite REPL</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
{ | ||
"name": "@electric-sql/pglite-repl", | ||
"version": "0.0.0", | ||
"author": "Electric DB Limited", | ||
"license": "Apache-2.0", | ||
"private": false, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"type": "module", | ||
"files": [ | ||
"dist", | ||
"dist-webcomponent" | ||
], | ||
"module": "dist/Repl.js", | ||
"exports": { | ||
".": { | ||
"import": "./dist/Repl.js" | ||
}, | ||
"./webcomponent": { | ||
"import": "./dist-webcomponent/Repl.js" | ||
} | ||
}, | ||
"scripts": { | ||
"dev": "vite", | ||
"build:react": "tsc && vite build", | ||
"build:webcomp": "vite build --config vite.webcomp.config.ts", | ||
"build": "npm run build:react && npm run build:webcomp", | ||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", | ||
"preview": "vite preview", | ||
"format": "prettier --write ./src && prettier --write ./src-webcomponent" | ||
}, | ||
"dependencies": { | ||
"@codemirror/autocomplete": "^6.16.2", | ||
"@codemirror/commands": "^6.6.0", | ||
"@codemirror/lang-sql": "^6.6.4", | ||
"@codemirror/language": "^6.10.2", | ||
"@codemirror/view": "^6.28.1", | ||
"@uiw/codemirror-theme-xcode": "^4.22.2", | ||
"@uiw/react-codemirror": "^4.22.2", | ||
"psql-describe": "^0.1.5", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"peerDependencies": { | ||
"@electric-sql/pglite": "workspace:^" | ||
}, | ||
"peerDependenciesMeta": { | ||
"@electric-sql/pglite": { | ||
"optional": true | ||
} | ||
}, | ||
"devDependencies": { | ||
"@electric-sql/pglite": "workspace:^", | ||
"@types/react": "^18.2.66", | ||
"@types/react-dom": "^18.2.22", | ||
"@typescript-eslint/eslint-plugin": "^7.2.0", | ||
"@typescript-eslint/parser": "^7.2.0", | ||
"@vitejs/plugin-react": "^4.2.1", | ||
"eslint": "^8.57.0", | ||
"eslint-plugin-react-hooks": "^4.6.0", | ||
"eslint-plugin-react-refresh": "^0.4.6", | ||
"terser": "^5.31.1", | ||
"typescript": "^5.2.2", | ||
"vite": "^5.2.0", | ||
"vite-plugin-dts": "^3.9.1", | ||
"vite-plugin-libcss": "^1.1.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { createRoot } from "react-dom/client"; | ||
import { Repl } from "../src/Repl"; | ||
import type { ReplProps, ReplTheme } from "../src/Repl"; | ||
import type { PGlite } from "@electric-sql/pglite"; | ||
import type { Extension } from "@uiw/react-codemirror"; | ||
|
||
// @ts-ignore | ||
import css from "../src/Repl.css?raw"; | ||
|
||
export type { ReplProps, ReplTheme }; | ||
|
||
export class PGliteREPL extends HTMLElement { | ||
#mountPoint: HTMLDivElement; | ||
#root: ReturnType<typeof createRoot>; | ||
#pg?: PGlite; | ||
#lightTheme?: Extension; | ||
#darkTheme?: Extension; | ||
|
||
constructor() { | ||
super(); | ||
this.#mountPoint = document.createElement("div"); | ||
const shadowRoot = this.attachShadow({ mode: "open" }); | ||
const style = document.createElement("style"); | ||
style.textContent = css; | ||
shadowRoot.appendChild(style); | ||
shadowRoot.appendChild(this.#mountPoint); | ||
this.#root = createRoot(this.#mountPoint); | ||
} | ||
|
||
static get observedAttributes() { | ||
return ["border", "theme"]; | ||
} | ||
|
||
connectedCallback() { | ||
this.render(); | ||
} | ||
|
||
attributeChangedCallback(_name: string, oldValue: any, newValue: any) { | ||
if (oldValue !== newValue) { | ||
this.render(); | ||
} | ||
} | ||
|
||
disconnectedCallback() { | ||
this.#root?.unmount(); | ||
} | ||
|
||
get pg() { | ||
return this.#pg; | ||
} | ||
|
||
set pg(pg: PGlite | undefined) { | ||
this.#pg = pg; | ||
this.render(); | ||
} | ||
|
||
get lightTheme() { | ||
return this.#lightTheme; | ||
} | ||
|
||
set lightTheme(lightTheme: Extension | undefined) { | ||
this.#lightTheme = lightTheme; | ||
this.render(); | ||
} | ||
|
||
get darkTheme() { | ||
return this.#darkTheme; | ||
} | ||
|
||
set darkTheme(darkTheme: Extension | undefined) { | ||
this.#darkTheme = darkTheme; | ||
this.render(); | ||
} | ||
|
||
render() { | ||
const border = this.hasAttribute("border") | ||
? this.getAttribute("border") === "true" | ||
: undefined; | ||
const theme = this.getAttribute("theme"); | ||
|
||
const props: ReplProps = { | ||
pg: this.#pg!, | ||
border, | ||
lightTheme: this.#lightTheme, | ||
darkTheme: this.#darkTheme, | ||
theme: (theme as ReplTheme | null) || "auto", | ||
}; | ||
|
||
this.#root.render( | ||
<> | ||
{this.#pg ? ( | ||
<Repl {...props} /> | ||
) : ( | ||
<div>PGlite instance not provided</div> | ||
)} | ||
</>, | ||
); | ||
} | ||
} | ||
|
||
customElements.define("pglite-repl", PGliteREPL); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#root { | ||
padding: 1rem; | ||
height: calc(100vh - 2rem); | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
.App { | ||
display: flex; | ||
flex-direction: column; | ||
height: 100%; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { PGlite } from "@electric-sql/pglite"; | ||
import "./App.css"; | ||
import { Repl } from "./Repl"; | ||
|
||
const pg = new PGlite(); | ||
|
||
function App() { | ||
return ( | ||
<div className="App"> | ||
<Repl pg={pg} border /> | ||
</div> | ||
); | ||
} | ||
|
||
export default App; |
Oops, something went wrong.